Skip to content

Commit 3bce149

Browse files
feat(ast): Add (undefined-behavior-)support for list literals everywhere
(Too much hassle to disallow it properly, will be caught in later parsing steps, temporary until proper list desugaring is done)
1 parent 0aecc03 commit 3bce149

File tree

2 files changed

+19
-19
lines changed

2 files changed

+19
-19
lines changed

parser/astgen/astgen.py

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -134,27 +134,15 @@ def _walk_smt(self, smt: AnyNode) -> list[AstNode]:
134134
f"the root level.", smt.region)
135135

136136
def _walk_var_decl(self, smt: DeclNode):
137-
decls = [(self._walk_ident(d.ident), self._walk_decl_value(d.value))
137+
decls = [(self._walk_ident(d.ident),
138+
None if d.value is None else self._walk_expr(d.value))
138139
for d in smt.decl_list.decls]
139140
scope = (VarDeclScope.LET if isinstance(smt.decl_scope, DeclScope_Let)
140141
else VarDeclScope.GLOBAL)
141142
tp = (VarType.LIST if isinstance(smt.decl_type, DeclType_List)
142143
else VarType.VARIABLE)
143144
return [AstDeclNode(smt.region, scope, tp, decls)]
144145

145-
def _walk_decl_value(self, value: AnyNode | None):
146-
if value is None:
147-
return None
148-
if isinstance(value, ListNode):
149-
# Special check (for now): list literals are disallowed everywhere
150-
# but here so _parse_expr raises an error when it finds a list
151-
# literal so we add this extra check as they *are* allowed here
152-
return self._walk_list_literal_decl(value)
153-
return self._walk_expr(value)
154-
155-
def _walk_list_literal_decl(self, ls: ListNode):
156-
return AstListLiteral(ls.region, [self._walk_expr(i) for i in ls.items])
157-
158146
def _walk_assign_left(self, lhs: AnyNode) -> AstNode:
159147
if isinstance(lhs, IdentNode):
160148
return self._walk_ident(lhs)
@@ -207,11 +195,12 @@ def _walk_attr_name(self, attr_name: AttrNameNode) -> AstAttrName:
207195
return AstAttrName(
208196
attr_name.region, self.node_str(attr_name, intern=True))
209197

210-
@_register_autowalk_expr # (we do a check in _parse_var_decl before calling _parse_expr)
211-
def _walk_list_literal_expr(self, node: ListNode):
212-
raise self.err("List literals are (for now) only supported in variable"
213-
" decls/initializers. (Note: nested list are not "
214-
"supported)", node)
198+
@_register_autowalk_expr
199+
def _walk_list_literal(self, ls: ListNode):
200+
# For now it is UB to use this anywhere but in variable decls
201+
# (until proper syntax desugar-ing for literal arrays is done).
202+
# Anyway, for now the codegen/typechecker/desugar step will check this
203+
return AstListLiteral(ls.region, [self._walk_expr(i) for i in ls.items])
215204

216205
@_register_autowalk_expr
217206
def _walk_getattr(self, node: GetattrNode) -> AstAttribute:

test/test_astgen/test_astgen.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import unittest
2+
13
from parser.common import StrRegion
24
from test.common import CommonTestCase
35

@@ -52,3 +54,12 @@ def test_decl(self):
5254
'global d = "STRING", e;\n'
5355
'let[] local_list=list(), other;\n'
5456
'global[] STACK;')
57+
58+
def test_list_literal_decl(self):
59+
self.assertAstMatchesSnapshot('let[] loc = [5, 6.,], b, c=[];\n'
60+
'global [] STACK = [foo(bar), 8];')
61+
62+
def test_list_literal_decl_paren(self):
63+
self.assertAstMatchesSnapshot('let[] a = ([1]);')
64+
# We only test for lists in variable decls (as them being allowed
65+
# elsewhere is UB for now).

0 commit comments

Comments
 (0)