require "lib/metaprogramming.nom" require "lib/operators.nom" require "lib/utils.nom" # Conditionals macro statement [if %condition %if_body] =: ".."|if \%condition as lua\ then | \(lua expr "vars.if_body.value") as lua\ |end macro statement [if %condition %if_body else %else_body] =: ".."|if \%condition as lua\ then | \(lua expr "vars.if_body.value") as lua\ |else | \(lua expr "vars.else_body.value") as lua\ |end # Return macro statement [return] =: "do return end" macro block [return %return-value] =: ".." |return \%return-value as lua\ macro [do %action] =: ".." |(\%action as lua\)(nomsu, setmetatable({}, {__index=vars})) # GOTOs macro statement [-> %label] =: ".." |::label_\nomsu "var_to_lua_identifier" [%label]\:: macro statement [go to %label] =: ".." |goto label_\nomsu "var_to_lua_identifier" [%label]\ # Loop control flow macro statement [break] =: "break" macro statement [break for] =: "goto break_for" macro statement [break for-all] =: "goto break_for_all" macro statement [break repeat] =: "goto break_repeat" macro statement [break repeat-until] =: "goto break_repeat_until" macro statement [break repeat-while] =: "goto break_repeat_while" macro statement [break %var, stop getting %var, no more %var] =: ".." |goto break_\nomsu "var_to_lua_identifier" [%var]\ macro statement [continue] =: "continue" macro statement [continue for] =: "goto continue_for" macro statement [continue for-all] =: "goto continue_for_all" macro statement [continue repeat] =: "goto continue_repeat" macro statement [continue repeat-until] =: "goto continue_repeat_until" macro statement [continue repeat-while] =: "goto continue_repeat_while" macro statement [continue %var, go to next %var, on to the next %var] =: ".." |goto continue_\nomsu "var_to_lua_identifier" [%var]\ # While loops macro block [repeat %body] =: ".."|while true do | \(lua expr "vars.body.value") as lua\ | ::continue_repeat:: |end |::break_repeat:: macro block [repeat while %condition %body] =: ".."|while \%condition as lua\ do | \(lua expr "vars.body.value") as lua\ | ::continue_repeat_while:: |end |::break_repeat_while:: macro block [repeat until %condition %body] =: ".."|while not (\%condition as lua\) do | \(lua expr "vars.body.value") as lua\ | ::continue_repeat_until:: |end |::break_repeat_until:: # For loops macro block [for %var in %iterable %body] =: %var-type =: lua expr "vars.var.type" assert (%var-type == "Var") ".." |For loop has the wrong type for the loop variable. Expected Var, but got: \%var-type\ # This trashes the loop variables, just like in Python. ".." |for i,value in ipairs(\%iterable as lua\) do | \%var as lua\ = value | \(lua expr "vars.body.value") as lua\ | ::continue_for:: | ::continue_\nomsu "var_to_lua_identifier" [%var]\:: |end |::break_for:: |::break_\nomsu "var_to_lua_identifier" [%var]\:: macro block [for all %iterable %body] =: pass # TODO: fix compiler bug # This trashes the loop variables, just like in Python. ".."|for i,value in ipairs(\%iterable as lua\) do | vars.it = value | \(lua expr "vars.body.value") as lua\ | ::continue_for_all:: |end |::break_for_all:: # Switch statement/multi-branch if macro block [when %body] =: %result =: "" for %statement in (lua expr "vars.body.value.value"): %func-call =: lua expr "vars.statement.value" assert ((lua expr "vars['func-call'].type") == "FunctionCall") ".." |Invalid format for 'when' statement. Only '?' blocks are allowed. %tokens =: lua expr "vars['func-call'].value" %q =: lua expr "vars.tokens[1]" assert (((lua expr "vars.q.type") == "Word") and ((lua expr "vars.q.value") == "?")) ".." |Invalid format for 'when' statement. Lines must begin with '?' %thunk =: lua expr "vars.tokens[#vars.tokens]" assert ((lua expr "vars.thunk.type") == "Thunk") ".." |Invalid format for 'when' statement. Lines must have a body. %condition_bits =: [] for %i in (2 up to (lua expr "#vars.tokens")): lua block "table.insert(vars['condition_bits'], vars.tokens[vars.i])" if (lua expr "#vars.condition_bits == 0"): %result join=: ".." | |do | \(lua expr "vars.thunk.value") as lua\ | goto finished_when |end ..else: if (lua expr "#vars.condition_bits == 1 and vars.condition_bits[1].type ~= 'Word'"): %condition =: lua expr "vars.condition_bits[1]" ..else: %condition =: dict [..] ["type",lua expr "vars['func-call'].type"] ["src",lua expr "vars['func-call'].src"] ["value", %condition_bits] %result join=: ".." | |if \%condition as lua\ then | \(lua expr "vars.thunk.value") as lua\ | goto finished_when |end %result join=: "\n::finished_when::" %result # Switch statement macro block [when %branch-value %body] =: %result =: ".."|local branch_value = \%branch-value as lua\ for %statement in (lua expr "vars.body.value.value"): %func-call =: lua expr "vars.statement.value" assert ((lua expr "vars['func-call'].type") == "FunctionCall") ".." |Invalid format for 'when' statement. Only == blocks are allowed. %tokens =: lua expr "vars['func-call'].value" %eq =: lua expr "vars.tokens[1]" assert (((lua expr "vars.eq.type") == "Word") and ((lua expr "vars.eq.value") == "==")) ".." |Invalid format for 'when' statement. Lines must begin with '==' %thunk =: lua expr "vars.tokens[#vars.tokens]" assert ((lua expr "vars.thunk.type") == "Thunk") ".." |Invalid format for 'when' statement. Lines must have a body. %condition_bits =: [] for %i in (2 up to (lua expr "#vars.tokens")): lua block "table.insert(vars.condition_bits, vars.tokens[vars.i])" if (lua expr "#vars.condition_bits == 0"): %result join=: ".." | |do | \(lua expr "vars.thunk.value") as lua\ | goto finished_when |end ..else: if (lua expr "#vars.condition_bits == 1 and vars.condition_bits[1].type ~= 'Word'"): %condition =: (lua expr "vars.condition_bits[1]") ..else: %condition =: dict [..] ["type",lua expr "vars['func-call'].type"] ["src",lua expr "vars['func-call'].src"] ["value", %condition_bits] %result join=: ".." | |if nomsu.utils.equivalent(branch_condition, \%condition as lua\) then | \(lua expr "vars.thunk.value") as lua\ | goto finished_when |end %result join=: "\n::finished_when::" %result