require "lib/metaprogramming.nom" require "lib/operators.nom" require "lib/utils.nom" # Conditionals parse (if %condition %if_body) as lua code ".." |if \(%condition) then | \(lua expr "vars.if_body.value") |end parse (if %condition %if_body else %else_body) as lua code ".." |if \(%condition) then | \(lua expr "vars.if_body.value") |else | \(lua expr "vars.else_body.value") |end # Return parse (return) as lua code "do return end" parse (return %return-value) as lua code "do return \(%return-value)" parse (do %action) as lua expr ".." |(\(%action))(nomsu, setmetatable({}, {__index=vars})) # GOTOs parse (-> %label) as lua code ".." |::label_\(nomsu "var_to_lua_identifier" [%label]):: parse (go to %label) as lua code ".." |goto label_\(nomsu "var_to_lua_identifier" [%label]) # Loop control flow parse (stop; stop loop; break) as lua code "break" parse (stop for; stop for-loop; break for) as lua code "goto break_for" parse (stop repeat; stop repeat-loop; break repeat) as lua code "goto break_repeat" parse (stop %var; break %var) as lua code ".." |goto break_\(nomsu "var_to_lua_identifier" [%var]) parse (continue; continue loop) as lua code "continue" parse (continue for; continue for-loop) as lua code "goto continue_for" parse (continue repeat; continue repeat-loop) as lua code "goto continue_repeat" parse (continue %var; go to next %var; on to the next %var) as lua code ".." |goto continue_\(nomsu "var_to_lua_identifier" [%var]) # While loops parse (repeat %body) as lua block ".." |while true do | \(lua expr "vars.body.value") | ::continue_repeat:: |end |::break_repeat:: parse (repeat while %condition %body) as lua block ".." |while \(%condition) do | \(lua expr "vars.body.value") | ::continue_repeat:: |end |::break_repeat:: parse (repeat until %condition %body) as lua block ".." |while not (\(%condition)) do | \(lua expr "vars.body.value") | ::continue_repeat:: |end |::break_repeat:: # Numeric range for loops parse: for %var from %start to %stop by %step %body for %var from %start to %stop via %step %body ..as lua block ".." |for i=\(%start),\(%stop),\(%step) do # This trashes the loop variables, just like in Python. | \(%var) = i | \(lua expr "vars.body.value") | ::continue_for:: | ::continue_\(nomsu "var_to_lua_identifier" [%var]):: |end |::break_for:: |::break_\(nomsu "var_to_lua_identifier" [%var]):: parse (for %var from %start to %stop %body) as: for %var from %start to %stop via 1 %body parse: for all %start to %stop by %step %body for all %start to %stop via %step %body ..as: for % from %start to %stop via %step %body parse (for all %start to %stop %body) as: for all %start to %stop via 1 %body parse (for %var in %iterable %body) as lua block ".." |for i,value in ipairs(\(%iterable)) do # This trashes the loop variables, just like in Python. | \(%var) = value | \(lua expr "vars.body.value") | ::continue_for:: | ::continue_\(nomsu "var_to_lua_identifier" [%var]):: |end |::break_for:: |::break_\(nomsu "var_to_lua_identifier" [%var]):: parse (for all %iterable %body) as: for % in %iterable %body # Switch statement/multi-branch if parse (when %body) as lua block: %result =: "" %fallthroughs =: [] 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" %star =: lua expr "vars.tokens[1]" assert (lua expr "vars.star and vars.star.type == 'Word' and vars.star.value == '*'") ".." |Invalid format for 'when' statement. Lines must begin with '*' %condition =: lua expr "vars.tokens[2]" assert %condition ".." |Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else" %thunk =: lua expr "vars.tokens[3]" if (%thunk == (nil)): lua block "table.insert(vars.fallthroughs, vars.condition)" go to next %statement if (lua expr "vars.condition.type == 'Word' and vars.condition.value == 'else'"): %result join=: ".." | |do ..else: %condition =: %condition as lua for all %fallthroughs: %condition join= " or \(%)" %result join=: ".." | |if \(%condition) then %result join=: ".." | | \(lua expr "vars.thunk.value") | goto finished_when |end %fallthroughs =: [] %result join=: "\n::finished_when::" %result # Switch statement parse (when %branch-value == ? %body) as lua block: %result =: "local branch_value = \(%branch-value)" %fallthroughs =: [] 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" %star =: lua expr "vars.tokens[1]" assert (lua expr "vars.star and vars.star.type == 'Word' and vars.star.value == '*'") ".." |Invalid format for 'when' statement. Lines must begin with '*' %condition =: lua expr "vars.tokens[2]" assert %condition ".." |Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else" %thunk =: lua expr "vars.tokens[3]" if (%thunk == (nil)): lua block "table.insert(vars.fallthroughs, vars.condition)" go to next %statement if (lua expr "vars.condition.type == 'Word' and vars.condition.value == 'else'"): %result join=: ".." | |do ..else: %condition =: "branch_value == (\(%condition))" for all %fallthroughs: %condition join= " or (branch_value == \(%))" %result join=: ".." | |if \%condition\ then %result join=: ".." | | \((lua expr "vars.thunk.value")) | goto finished_when |end %fallthroughs =: [] %result join=: "\n::finished_when::" %result