Skip to content

Commit

Permalink
feat(compiler): log(struct) (#7018)
Browse files Browse the repository at this point in the history
fixes: #6950
we can now log structs that all of their fields are stringable

## Checklist

- [ ] Title matches [Winglang's style guide](https://www.winglang.io/contributing/start-here/pull_requests#how-are-pull-request-titles-formatted)
- [ ] Description explains motivation and solution
- [ ] Tests added (always)
- [ ] Docs updated (only required for features)
- [ ] Added `pr/e2e-full` label if this feature requires end-to-end testing

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*.
  • Loading branch information
tsuf239 authored Aug 14, 2024
1 parent 46c65c1 commit ef4a141
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 18 deletions.
16 changes: 13 additions & 3 deletions examples/tests/invalid/stringify.test.w
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
class B {}
let b = new B();
struct Foo {
bar: B;
baz: str;
}

let foo: Foo = {bar: b, baz: "hello"};

log("hello {b}");
// ^ Error: expected type to be stringable
// ^ Expected type to be "stringable", but got "B" instead

let x: str? = nil;
log("{x}");
// ^ Error: expected type to be stringable
// ^ Expected type to be "stringable", but got "str?" instead

log(b);
// ^ Error: expected type to be stringable
// ^ Expected type to be "stringable", but got "B" instead

log(foo);
// ^ Expected type to be "stringable", but got "Foo" instead
6 changes: 6 additions & 0 deletions examples/tests/valid/stringify.test.w
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
enum MyEnum { A, B, C }

struct Foo {
bar: str;
}
let foo = Foo { bar: "hello" };

// If a value's type is stringable, it can be passed directly to the "log" function
log("my string");
log(42);
log(true);
log(Json { "cool": "beans" });
log(MyEnum.A);
log(foo);
11 changes: 10 additions & 1 deletion libs/wingc/src/type_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,7 @@ impl Subtype for Type {
(Self::Json(_), Self::Json(_)) => true,
(Self::MutJson, Self::Stringable) => true,
(Self::Enum(_), Self::Stringable) => true,
(Self::Struct(s), Self::Stringable) => s.fields(true).map(|(_, v)| v.type_).all(|t| t.is_stringable()),
_ => false,
}
}
Expand Down Expand Up @@ -1127,6 +1128,14 @@ impl TypeRef {
matches!(**self, Type::Struct(_))
}

pub fn is_stringable_struct(&self) -> bool {
if let Type::Struct(ref s) = **self {
s.fields(true).map(|(_, v)| v.type_).all(|t| t.is_stringable())
} else {
false
}
}

pub fn is_map(&self) -> bool {
matches!(**self, Type::Map(_) | Type::MutMap(_))
}
Expand Down Expand Up @@ -1169,7 +1178,7 @@ impl TypeRef {
matches!(
**self,
Type::String | Type::Number | Type::Boolean | Type::Json(_) | Type::MutJson | Type::Enum(_) | Type::Anything
)
) || self.is_stringable_struct()
}

/// If this is a function and its last argument is a struct, return that struct.
Expand Down
37 changes: 23 additions & 14 deletions tools/hangar/__snapshots__/invalid.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4595,31 +4595,40 @@ Duration <DURATION>"

exports[`stringify.test.w 1`] = `
"error: Expected type to be "stringable", but got "B" instead
--> ../../../examples/tests/invalid/stringify.test.w:3:13
|
3 | log("hello {b}");
| ^
|
= hint: str, num, bool, json, and enums are stringable
--> ../../../examples/tests/invalid/stringify.test.w:10:13
|
10 | log("hello {b}");
| ^
|
= hint: str, num, bool, json, and enums are stringable


error: Expected type to be "stringable", but got "str?" instead
--> ../../../examples/tests/invalid/stringify.test.w:7:7
|
7 | log("{x}");
| ^
|
= hint: str? is an optional, try unwrapping it with 'x ?? "nil"' or 'x!'
--> ../../../examples/tests/invalid/stringify.test.w:14:7
|
14 | log("{x}");
| ^
|
= hint: str? is an optional, try unwrapping it with 'x ?? "nil"' or 'x!'


error: Expected type to be "stringable", but got "B" instead
--> ../../../examples/tests/invalid/stringify.test.w:10:5
--> ../../../examples/tests/invalid/stringify.test.w:17:5
|
10 | log(b);
17 | log(b);
| ^
|
= hint: str, num, bool, json, and enums are stringable


error: Expected type to be "stringable", but got "Foo" instead
--> ../../../examples/tests/invalid/stringify.test.w:20:5
|
20 | log(foo);
| ^^^
|
= hint: str, num, bool, json, and enums are stringable

Tests 1 failed (1)
Snapshots 1 skipped
Test Files 1 failed (1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ class $Root extends $stdlib.std.Resource {
return tmp;
})({})
;
const foo = ({"bar": "hello"});
console.log("my string");
console.log(42);
console.log(true);
console.log(({"cool": "beans"}));
console.log(MyEnum.A);
console.log(foo);
}
}
const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "stringify.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ my string
true
{ cool: 'beans' }
A
{ bar: 'hello' }
pass ─ stringify.test.wsim (no tests)
Tests 1 passed (1)
Expand Down

0 comments on commit ef4a141

Please sign in to comment.