Skip to content

Commit

Permalink
chore: grammar support for phase independent specifier (#6879)
Browse files Browse the repository at this point in the history
First step towards implementing the `unphased` functions RFC (#1711)

## 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
Chriscbr authored and David Boyne committed Jul 15, 2024
1 parent 461081a commit 98ca4f4
Show file tree
Hide file tree
Showing 11 changed files with 387 additions and 290 deletions.
33 changes: 33 additions & 0 deletions examples/tests/invalid/unphased.test.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
unphased class UnphasedClass {}
// ^ Error: Unphased classes are not yet supported

unphased interface UnphasedInterface {}
// ^ Error: Unphased interfaces are not yet supported

let unphasedFn = unphased () => {
// ^ Error: Unphased functions are not yet supported
log("Hello, world!");
};

let fnWithUnphasedParamType = (f: unphased (str): num) => {
// ^ Error: Unphased functions are not yet supported
};

let fnWithUnphasedReturnType = (): (unphased (str): num)? => {
// ^ Error: Unphased functions are not yet supported
return nil;
};

class Foo {
unphased myField: str;
// ^ Error: Class fields cannot be unphased
unphased new() {}
// ^ Error: Class constructors cannot be unphased
unphased myMethod() {}
// ^ Error: Unphased functions are not yet supported
}

interface IFoo {
unphased bar(): void;
// ^ Error: Unphased methods on interfaces are not yet supported
}
101 changes: 35 additions & 66 deletions libs/tree-sitter-wing/grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ module.exports = grammar({
// These modifier conflicts should be solved through GLR parsing
[$.field_modifiers, $.method_modifiers],
[$.class_modifiers, $.closure_modifiers, $.interface_modifiers],
[$.inflight_method_signature, $.field_modifiers],
],

supertypes: ($) => [$.expression, $._literal],
Expand Down Expand Up @@ -108,7 +107,7 @@ module.exports = grammar({

accessor: ($) => choice(".", "?."),

inflight_specifier: ($) => "inflight",
phase_specifier: ($) => choice("unphased", "inflight"),

_statement: ($) =>
choice(
Expand Down Expand Up @@ -220,7 +219,7 @@ module.exports = grammar({
// Classes

class_modifiers: ($) =>
repeat1(choice($.access_modifier, $.inflight_specifier)),
repeat1(choice($.access_modifier, $.phase_specifier)),

class_definition: ($) =>
seq(
Expand All @@ -240,7 +239,7 @@ module.exports = grammar({
choice(
$.access_modifier,
$.static,
$.inflight_specifier,
$.phase_specifier,
$.reassignable
)
),
Expand All @@ -257,7 +256,7 @@ module.exports = grammar({
/// Interfaces

interface_modifiers: ($) =>
repeat1(choice($.access_modifier, $.inflight_specifier)),
repeat1(choice($.access_modifier, $.phase_specifier)),

interface_definition: ($) =>
seq(
Expand All @@ -269,11 +268,7 @@ module.exports = grammar({
),

interface_implementation: ($) =>
braced(
repeat(
choice($.method_signature, $.inflight_method_signature, $.class_field)
)
),
braced(repeat(choice($.method_definition, $.class_field))),

inclusive_range: ($) => "=",

Expand Down Expand Up @@ -369,7 +364,6 @@ module.exports = grammar({

expression: ($) =>
choice(
$.unwrap_or,
$.binary_expression,
$.unary_expression,
$.new_expression,
Expand Down Expand Up @@ -532,7 +526,7 @@ module.exports = grammar({
function_type: ($) =>
prec.right(
seq(
optional(field("inflight", $.inflight_specifier)),
optional(field("phase_specifier", $.phase_specifier)),
field("parameter_types", $.parameter_type_list),
seq(":", field("return_type", $._type))
)
Expand All @@ -545,7 +539,7 @@ module.exports = grammar({

initializer: ($) =>
seq(
optional(field("inflight", $.inflight_specifier)),
optional(field("phase_specifier", $.phase_specifier)),
field("ctor_name", "new"),
field("parameter_list", $.parameter_list),
field("block", $.block)
Expand All @@ -555,21 +549,13 @@ module.exports = grammar({

_return_type: ($) => $._type_annotation,

method_signature: ($) =>
seq(
field("name", $.identifier),
field("parameter_list", $.parameter_list),
optional($._return_type),
$._semicolon
),

method_modifiers: ($) =>
repeat1(
choice(
$.extern_modifier,
$.access_modifier,
$.static,
$.inflight_specifier
$.phase_specifier
)
),

Expand All @@ -582,15 +568,6 @@ module.exports = grammar({
choice(field("block", $.block), $._semicolon)
),

inflight_method_signature: ($) =>
seq(
field("phase_modifier", $.inflight_specifier),
field("name", $.identifier),
field("parameter_list", $.parameter_list),
optional($._return_type),
$._semicolon
),

access_modifier: ($) => choice("pub", "protected", "internal"),

variadic: ($) => "...",
Expand Down Expand Up @@ -625,16 +602,6 @@ module.exports = grammar({
_container_value_type: ($) =>
seq("<", field("type_parameter", $._type), ">"),

unwrap_or: ($) =>
prec.right(
PREC.UNWRAP_OR,
seq(
field("left", $.expression),
field("op", "??"),
field("right", $.expression)
)
),

optional_unwrap: ($) =>
prec.right(PREC.OPTIONAL_UNWRAP, seq($.expression, "!")),

Expand All @@ -658,34 +625,36 @@ module.exports = grammar({
},

binary_expression: ($) => {
/** @type {Array<[RuleOrLiteral, number]>} */
/** @type {Array<[RuleOrLiteral, number, "left" | "right"]>} */
const table = [
["+", PREC.ADD],
["-", PREC.ADD],
["*", PREC.MULTIPLY],
["/", PREC.MULTIPLY],
["\\", PREC.MULTIPLY],
["%", PREC.MULTIPLY],
["**", PREC.POWER],
["||", PREC.LOGICAL_OR],
["&&", PREC.LOGICAL_AND],
//['|', PREC.INCLUSIVE_OR],
//['^', PREC.EXCLUSIVE_OR],
//['&', PREC.BITWISE_AND],
["==", PREC.EQUAL],
["!=", PREC.EQUAL],
[">", PREC.RELATIONAL],
[">=", PREC.RELATIONAL],
["<=", PREC.RELATIONAL],
["<", PREC.RELATIONAL],
//['<<', PREC.SHIFT],
//['>>', PREC.SHIFT],
//['>>>', PREC.SHIFT],
["+", PREC.ADD, "left"],
["-", PREC.ADD, "left"],
["*", PREC.MULTIPLY, "left"],
["/", PREC.MULTIPLY, "left"],
["\\", PREC.MULTIPLY, "left"],
["%", PREC.MULTIPLY, "left"],
["**", PREC.POWER, "left"],
["||", PREC.LOGICAL_OR, "left"],
["&&", PREC.LOGICAL_AND, "left"],
//['|', PREC.INCLUSIVE_OR, "left"],
//['^', PREC.EXCLUSIVE_OR, "left"],
//['&', PREC.BITWISE_AND, "left"],
["==", PREC.EQUAL, "left"],
["!=", PREC.EQUAL, "left"],
[">", PREC.RELATIONAL, "left"],
[">=", PREC.RELATIONAL, "left"],
["<=", PREC.RELATIONAL, "left"],
["<", PREC.RELATIONAL, "left"],
//['<<', PREC.SHIFT, "left"],
//['>>', PREC.SHIFT, "left"],
//['>>>', PREC.SHIFT, "left"],
["??", PREC.UNWRAP_OR, "right"],
];

return choice(
...table.map(([operator, precedence]) => {
return prec.left(
...table.map(([operator, precedence, associativity]) => {
const precFn = associativity === "left" ? prec.left : prec.right;
return precFn(
precedence,
seq(
field("left", $.expression),
Expand All @@ -697,7 +666,7 @@ module.exports = grammar({
);
},

closure_modifiers: ($) => repeat1(choice($.inflight_specifier)),
closure_modifiers: ($) => repeat1(choice($.phase_specifier)),

closure: ($) =>
seq(
Expand Down
2 changes: 1 addition & 1 deletion libs/tree-sitter-wing/queries/highlights.scm
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"class"
"let"
"new"
(inflight_specifier)
(phase_specifier)
] @keyword

[
Expand Down
Loading

0 comments on commit 98ca4f4

Please sign in to comment.