From 02796fd830a09156de6a4b4e3b42cbbf94185d94 Mon Sep 17 00:00:00 2001 From: James Westman Date: Mon, 10 Apr 2023 09:38:56 -0500 Subject: [PATCH] Use <> instead of () for casts & typeof This makes it clearer that they aren't functions, and it eliminates syntactic ambiguity with closure expressions. --- blueprintcompiler/language/expression.py | 25 +++++++++++++++++++- blueprintcompiler/language/types.py | 9 ++++++++ blueprintcompiler/language/values.py | 28 ++++++++++++++++++++--- tests/sample_errors/warn_old_extern.err | 1 + tests/samples/expr_closure.blp | 2 +- tests/samples/expr_closure_args.blp | 2 +- tests/samples/expr_lookup.blp | 2 +- tests/samples/template_binding.blp | 2 +- tests/samples/template_binding_extern.blp | 2 +- tests/samples/typeof.blp | 4 ++-- 10 files changed, 66 insertions(+), 11 deletions(-) diff --git a/blueprintcompiler/language/expression.py b/blueprintcompiler/language/expression.py index 69323f4..16ee33c 100644 --- a/blueprintcompiler/language/expression.py +++ b/blueprintcompiler/language/expression.py @@ -159,7 +159,17 @@ class LookupOp(InfixExpr): class CastExpr(InfixExpr): - grammar = ["as", "(", TypeName, ")"] + grammar = [ + "as", + AnyOf( + ["<", TypeName, Match(">").expected()], + [ + UseExact("lparen", "("), + TypeName, + UseExact("rparen", ")").expected("')'"), + ], + ), + ] @context(ValueTypeCtx) def value_type(self): @@ -183,6 +193,19 @@ class CastExpr(InfixExpr): f"Invalid cast. No instance of {self.lhs.type.full_name} can be an instance of {self.type.full_name}." ) + @validate("lparen", "rparen") + def upgrade_to_angle_brackets(self): + if self.tokens["lparen"]: + raise UpgradeWarning( + "Use angle bracket syntax introduced in blueprint 0.8.0", + actions=[ + CodeAction( + "Use <> instead of ()", + f"<{self.children[TypeName][0].as_string}>", + ) + ], + ) + class ClosureArg(AstNode): grammar = ExprChain diff --git a/blueprintcompiler/language/types.py b/blueprintcompiler/language/types.py index 510dbc7..34e9558 100644 --- a/blueprintcompiler/language/types.py +++ b/blueprintcompiler/language/types.py @@ -89,6 +89,15 @@ class TypeName(AstNode): if self.gir_type: return self.gir_type.doc + @property + def as_string(self) -> str: + if self.tokens["extern"]: + return "$" + self.tokens["class_name"] + elif self.tokens["namespace"]: + return f"{self.tokens['namespace']}.{self.tokens['class_name']}" + else: + return self.tokens["class_name"] + class ClassName(TypeName): @validate("namespace", "class_name") diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index e446b29..0141a2f 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -74,9 +74,18 @@ class Translated(AstNode): class TypeLiteral(AstNode): grammar = [ "typeof", - "(", - to_parse_node(TypeName).expected("type name"), - Match(")").expected(), + AnyOf( + [ + "<", + to_parse_node(TypeName).expected("type name"), + Match(">").expected(), + ], + [ + UseExact("lparen", "("), + to_parse_node(TypeName).expected("type name"), + UseExact("rparen", ")").expected("')'"), + ], + ), ] @property @@ -93,6 +102,19 @@ class TypeLiteral(AstNode): if expected_type is not None and not isinstance(expected_type, gir.TypeType): raise CompileError(f"Cannot convert GType to {expected_type.full_name}") + @validate("lparen", "rparen") + def upgrade_to_angle_brackets(self): + if self.tokens["lparen"]: + raise UpgradeWarning( + "Use angle bracket syntax introduced in blueprint 0.8.0", + actions=[ + CodeAction( + "Use <> instead of ()", + f"<{self.children[TypeName][0].as_string}>", + ) + ], + ) + class QuotedLiteral(AstNode): grammar = UseQuoted("value") diff --git a/tests/sample_errors/warn_old_extern.err b/tests/sample_errors/warn_old_extern.err index c3b3fe2..5adf398 100644 --- a/tests/sample_errors/warn_old_extern.err +++ b/tests/sample_errors/warn_old_extern.err @@ -1,3 +1,4 @@ 3,1,8,Use the '$' extern syntax introduced in blueprint 0.8.0 +4,15,15,Use angle bracket syntax introduced in blueprint 0.8.0 4,16,13,Use the '$' extern syntax introduced in blueprint 0.8.0 5,14,7,Use the '$' extern syntax introduced in blueprint 0.8.0 \ No newline at end of file diff --git a/tests/samples/expr_closure.blp b/tests/samples/expr_closure.blp index 99874e8..81c3f2c 100644 --- a/tests/samples/expr_closure.blp +++ b/tests/samples/expr_closure.blp @@ -1,5 +1,5 @@ using Gtk 4.0; Label my-label { - label: bind ($my-closure(my-label.margin-bottom)) as (string); + label: bind ($my-closure(my-label.margin-bottom)) as ; } \ No newline at end of file diff --git a/tests/samples/expr_closure_args.blp b/tests/samples/expr_closure_args.blp index d09c881..5699094 100644 --- a/tests/samples/expr_closure_args.blp +++ b/tests/samples/expr_closure_args.blp @@ -1,5 +1,5 @@ using Gtk 4.0; Label { - label: bind $my-closure (true, 10, "Hello") as (string); + label: bind $my-closure (true, 10, "Hello") as ; } \ No newline at end of file diff --git a/tests/samples/expr_lookup.blp b/tests/samples/expr_lookup.blp index 2556f9a..12e2de1 100644 --- a/tests/samples/expr_lookup.blp +++ b/tests/samples/expr_lookup.blp @@ -5,5 +5,5 @@ Overlay { } Label { - label: bind (label.parent) as (Overlay).child as (Label).label; + label: bind (label.parent) as .child as