nomsu/lib/control_flow.nom

184 lines
6.5 KiB
Plaintext
Raw Normal View History

require "lib/metaprogramming.nom"
require "lib/operators.nom"
require "lib/utils.nom"
# Conditionals
2017-09-26 15:27:01 -07:00
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
2017-09-26 15:27:01 -07:00
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
2017-09-26 15:27:01 -07:00
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
2017-09-26 15:27:01 -07:00
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
2017-09-26 15:27:01 -07:00
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
2017-09-26 15:27:01 -07:00
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.
2017-09-26 15:27:01 -07:00
| \(%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.
2017-09-26 15:27:01 -07:00
| \(%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
2017-09-26 15:27:01 -07:00
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'"):
2017-09-26 15:27:01 -07:00
%result join=: ".."
|
|do
..else:
%condition =: %condition as lua
2017-09-26 15:27:01 -07:00
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
2017-09-26 15:27:01 -07:00
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'"):
2017-09-26 15:27:01 -07:00
%result join=: ".."
|
|do
..else:
2017-09-26 15:27:01 -07:00
%condition =: "branch_value == (\(%condition))"
for all %fallthroughs: %condition join= " or (branch_value == \(%))"
%result join=: ".."
|
|if \%condition\ then
2017-09-26 15:27:01 -07:00
%result join=: ".."
|
| \((lua expr "vars.thunk.value"))
| goto finished_when
|end
%fallthroughs =: []
%result join=: "\n::finished_when::"
%result