diff --git a/src/lang/lang.h b/src/lang/lang.h index 8b72bbd..93c65fc 100644 --- a/src/lang/lang.h +++ b/src/lang/lang.h @@ -30,12 +30,13 @@ inline const TokenDef Compile{"compile"}; namespace verona::wf { + inline const auto cond = Eq | Neq; inline const auto lv = Ident | Lookup; - inline const auto rv = lv | Empty | Null | String | Call | Method | Take; + inline const auto rv = + lv | Empty | Null | String | Call | Method | Take | cond; inline const auto cmp_values = Ident | Lookup | Null | Call | Method; inline const auto key = Ident | Lookup | String; inline const auto operand = Lookup | Call | Method | Ident; - inline const auto cond = Eq | Neq; inline const auto grouping = (Top <<= File) | (File <<= Body) | (Body <<= Block) | @@ -63,13 +64,13 @@ namespace verona::wf (Func <<= Body) | (Label <<= Ident)[Ident]; } +inline const auto COND = T(Eq, Neq); inline const auto LV = T(Ident, Lookup); inline const auto RV = - T(Empty, Ident, Lookup, Null, String, Call, Method, Take); + T(Empty, Ident, Lookup, Null, String, Call, Method, Take, Eq, Neq); inline const auto CMP_V = T(Ident, Lookup, Null, Call, Method); inline const auto KEY = T(Ident, Lookup, String); inline const auto OPERAND = T(Lookup, Call, Method, Ident); -inline const auto COND = T(Eq, Neq); // Parsing && AST construction Parse parser(); diff --git a/src/lang/passes/grouping.cc b/src/lang/passes/grouping.cc index 3b4a0eb..9f50bbc 100644 --- a/src/lang/passes/grouping.cc +++ b/src/lang/passes/grouping.cc @@ -62,6 +62,11 @@ PassDef grouping() ((T(Group) << (RV[Rhs] * End)) / (RV[Rhs] * End)) * End) >> [](auto& _) { return Assign << _[Lhs] << _[Rhs]; }, + // Normalize `if x:` -> `if x == True` + In(If, While) * ((T(Group) << End) * (!COND)[Op]) >> + [](auto& _) { + return Seq << Group << (Eq << _(Op) << (Ident ^ "True")); + }, COND[Op] << (Any[Lhs] * (T(Group) << CMP_V[Rhs] * End) * End) >> [](auto& _) { return create_from(_(Op)->type(), _(Op)) << _[Lhs] << _[Rhs]; @@ -97,10 +102,6 @@ PassDef grouping() return create_from(For, _(For)) << _(Key) << _(Value) << _(Op) << _(Block); }, - In(While) * ((T(Group) << End) * (!COND)[Op]) >> - [](auto& _) { - return Seq << Group << (Eq << _(Op) << (Ident ^ "True")); - }, (T(While) << (T(Group) * COND[Op] * (T(Group) << T(Block)[Block]))) >> [](auto& _) { return While << _(Op) << _(Block); }, diff --git a/src/lang/passes/parse.cc b/src/lang/passes/parse.cc index 3420929..b5857ec 100644 --- a/src/lang/passes/parse.cc +++ b/src/lang/passes/parse.cc @@ -10,14 +10,15 @@ namespace verona::wf Group | Assign | If | Else | Block | For | Func | List | Return | While; inline const auto parser = (Top <<= File) | (File <<= parse_groups++) | - (Assign <<= Group++) | (If <<= Group * (Op >>= (cond | Group)) * Group) | + (Assign <<= Group * (Lhs >>= (Group | cond))) | + (If <<= Group * (Op >>= (cond | Group)) * Group) | (Else <<= Group * Group) | (Group <<= (parse_tokens | Block | List)++) | (Block <<= (parse_tokens | parse_groups)++) | (Eq <<= Group * Group) | (Neq <<= Group * Group) | (Lookup <<= Group) | (For <<= Group * List * Group * Group) | (While <<= Group * (Op >>= (cond | Group)) * Group) | (List <<= Group++) | (Parens <<= (Group | List)++) | (Func <<= Group * Group * Group) | - (Return <<= Group++); + (Return <<= (Group | cond)++); } struct Indent @@ -34,7 +35,7 @@ trieste::Parse parser() indent->push_back({0, File}); auto update_indent = [indent](detail::Make& m, size_t this_indent) { - m.term({Assign, Return}); + m.term({Eq, Neq, Assign, Return}); if (this_indent > indent->back().indent) { diff --git a/tests/exprs/ifs.vpy b/tests/exprs/ifs.vpy index 8f5b9e1..236dd24 100644 --- a/tests/exprs/ifs.vpy +++ b/tests/exprs/ifs.vpy @@ -1,4 +1,3 @@ - # Build a region a = {} a["self"] = a @@ -21,5 +20,15 @@ else: d = {} drop d +cond = f.a != a +if cond: + dummy = "created" + +def check(): + c = False + return c == True +if check(): + this = "is false" + drop a drop f