From b55fd39029a5a3471bc0f7fd233cbf44e35c200a Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 1 Nov 2017 17:08:44 -0200 Subject: [PATCH 1/3] Syntactic support for `for-in` construct --- spec/parser_spec.lua | 10 ++++++++++ testfiles/statements.titan | 4 ++++ titan-compiler/ast.lua | 1 + titan-compiler/parser.lua | 3 +++ 4 files changed, 18 insertions(+) diff --git a/spec/parser_spec.lua b/spec/parser_spec.lua index 66e10bf..32a6b9b 100644 --- a/spec/parser_spec.lua +++ b/spec/parser_spec.lua @@ -187,6 +187,16 @@ describe("Titan parser", function() inc = { _tag = "Exp_Integer", value = 3 }, start = { _tag = "Exp_Integer", value = 1 } }, + { _tag = "Stat_ForIn", + block = { + stats = { + { _tag = "Stat_Assign", + exp = { var = { _tag = "Var_Name", name = "i" } }, + var = { _tag = "Var_Name", name = "i" } } } }, + decl = { _tag = "Decl_Decl", name = "i", type = false }, + exp = { _tag = "Stat_Call", + callexp = { _tag = "Exp_Call" } } }, + { _tag = "Stat_Return", exp = { _tag = "Exp_Var" } }, }) end) diff --git a/testfiles/statements.titan b/testfiles/statements.titan index 79b611d..a1de261 100644 --- a/testfiles/statements.titan +++ b/testfiles/statements.titan @@ -18,5 +18,9 @@ local function statements(): nil i = i end + for i in each() do + i = i + end + return x end diff --git a/titan-compiler/ast.lua b/titan-compiler/ast.lua index aad2908..677c3e8 100644 --- a/titan-compiler/ast.lua +++ b/titan-compiler/ast.lua @@ -23,6 +23,7 @@ types.Stat = { Repeat = {"block", "condition"}, If = {"thens", "elsestat"}, For = {"decl", "start", "finish", "inc", "block"}, + ForIn = {"decl", "exp", "block"}, Assign = {"var", "exp"}, Decl = {"decl", "exp"}, Call = {"callexp"}, diff --git a/titan-compiler/parser.lua b/titan-compiler/parser.lua index a2f959d..adbf6fa 100644 --- a/titan-compiler/parser.lua +++ b/titan-compiler/parser.lua @@ -202,6 +202,9 @@ local grammar = re.compile([[ ASSIGN exp COMMA exp (COMMA exp)? -> opt DO block END) -> Stat_For + / ({} FOR decl + IN exp + DO block END) -> Stat_ForIn / ({} LOCAL decl ASSIGN exp) -> defstat / ({} var ASSIGN exp) -> Stat_Assign / ({} (suffixedexp => exp_is_call)) -> Stat_Call From 986a6c569f6398404e880a51fe1767c816727370 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 1 Nov 2017 17:10:14 -0200 Subject: [PATCH 2/3] Begin writing type checking for `for-in` --- titan-compiler/checker.lua | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/titan-compiler/checker.lua b/titan-compiler/checker.lua index a116734..c523141 100644 --- a/titan-compiler/checker.lua +++ b/titan-compiler/checker.lua @@ -232,6 +232,24 @@ local function checkfor(node, st, errors) return false end +-- Typechecks a for-in statement +-- node: Stat_For AST node +-- st: symbol table +-- errors: list of compile-time errors +-- returns whether statement always returns from its function (always false for 'for' loop) +local function checkforin(node, st, errors) + checkstat(node.decl, st, errors) + checkexp(node.exp, st, errors) + if node.decl.type then + checkstat(node.decl, st, errors) + local dtype = node.decl._type + node.exp = trycoerce(node.exp, dtype) + checkmatch("'for' expression", dtype, node.exp._type, errors, node.exp._pos) + end + checkstat(node.block, st, errors) + return false +end + -- Typechecks a block statement -- node: Stat_Block AST node -- st: symbol table @@ -276,6 +294,8 @@ function checkstat(node, st, errors) st:with_block(checkrepeat, node, st, errors) elseif tag == "Stat_For" then st:with_block(checkfor, node, st, errors) + elseif tag == "Stat_ForIn" then + st:with_block(checkforin, node, st, errors) elseif tag == "Stat_Assign" then checkexp(node.var, st, errors) -- mark this variable as assigned to From 46410a1ffa89d53813d33289622dcda803184c31 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 1 Nov 2017 18:02:13 -0200 Subject: [PATCH 3/3] Fix test for parsing `for-in` --- spec/parser_spec.lua | 3 +-- testfiles/statements.titan | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/parser_spec.lua b/spec/parser_spec.lua index 32a6b9b..7843092 100644 --- a/spec/parser_spec.lua +++ b/spec/parser_spec.lua @@ -194,8 +194,7 @@ describe("Titan parser", function() exp = { var = { _tag = "Var_Name", name = "i" } }, var = { _tag = "Var_Name", name = "i" } } } }, decl = { _tag = "Decl_Decl", name = "i", type = false }, - exp = { _tag = "Stat_Call", - callexp = { _tag = "Exp_Call" } } }, + exp = { _tag = "Exp_Call" } }, { _tag = "Stat_Return", exp = { _tag = "Exp_Var" } }, }) diff --git a/testfiles/statements.titan b/testfiles/statements.titan index a1de261..6e6e206 100644 --- a/testfiles/statements.titan +++ b/testfiles/statements.titan @@ -18,7 +18,7 @@ local function statements(): nil i = i end - for i in each() do + for i in pairs(t) do i = i end