diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-01-08 18:53:57 -0800 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-01-08 18:53:57 -0800 |
| commit | f97ab858edae5495f8ebfef46656e86150665888 (patch) | |
| tree | ed47620eba2365192ba54950647d6307223cac29 /lib | |
| parent | 568a44ef191e1f4072d379700e3b6f599150a92b (diff) | |
Modernized the codebase a bit to include "immediately:" for immediately
running code before further parsing takes place. That means that in the
default case, whole files can be run at once, which makes all but the
weirdest edge cases make a lot more sense and operate smoothly.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/control_flow.nom | 40 | ||||
| -rw-r--r-- | lib/metaprogramming.nom | 196 | ||||
| -rw-r--r-- | lib/operators.nom | 4 |
3 files changed, 126 insertions, 114 deletions
diff --git a/lib/control_flow.nom b/lib/control_flow.nom index 33f72ab..5169ac2 100644 --- a/lib/control_flow.nom +++ b/lib/control_flow.nom @@ -43,7 +43,7 @@ rule [tree %tree has function call %call] =: return true; end end - do return false; end + return false; # While loops compile [do next repeat-loop] to code: "goto continue_repeat;" @@ -100,12 +100,14 @@ compile [..] %stop_labels join= "\n::stop_for::;" if (tree %body has function call (tree \(stop %) with {""=%var})): %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;" - if (%stop_labels != ""): ".." - do --for-loop label scope - \%code\ - ..\%stop_labels - end --for-loop label scope - ..else: %code + return (..) + ".." + do --for-loop label scope + \%code\ + ..\%stop_labels + end --for-loop label scope + ..if %stop_labels != "" else %code + 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 @@ -131,11 +133,12 @@ compile [for %var in %iterable %body] to code: %stop_labels join= "\n::stop_for::;" if (tree %body has function call (tree \(stop %) with {""=%var})): %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;" - if (%stop_labels != ""): ".." - do --for-loop label scope - \%code\%stop_labels - end --for-loop label scope - ..else: %code + return (..) + ".." + do --for-loop label scope + \%code\%stop_labels + end --for-loop label scope + ..if %stop_labels != "" else %code parse [for all %iterable %body] as: for % in %iterable %body # Dict iteration (lua's "pairs()") @@ -161,12 +164,13 @@ compile [for %key = %value in %iterable %body] to code: %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%key])::;" if (tree %body has function call (tree \(stop %) with {""=%value})): %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%value])::;" - if (%stop_labels != ""): ".." - do --for-loop label scope - \%code\ - ..\%stop_labels - end --for-loop label scope - ..else: %code + return (..) + ".." + do --for-loop label scope + \%code\ + ..\%stop_labels + end --for-loop label scope + ..if %stop_labels != "" else %code # Switch statement/multi-branch if compile [when %body] to code: diff --git a/lib/metaprogramming.nom b/lib/metaprogramming.nom index 325f102..f59ce04 100644 --- a/lib/metaprogramming.nom +++ b/lib/metaprogramming.nom @@ -3,74 +3,93 @@ that easier. # Rule to make rules: -lua> ".." - nomsu:defmacro("rule %signature = %body", (function(nomsu, vars) - nomsu:assert(\%signature.type == "List", - "Invalid type for rule definition signature. Expected List, but got: "..tostring(\%signature.type)); - nomsu:assert(\%body.type == "Thunk", - "Invalid type for rule definition body. Expected Thunk, but got: "..tostring(\%body.type)); - local signature = {}; - for i, alias in ipairs(\%signature.value) do - signature[i] = alias.src; - end - local src = nomsu:source_code(0); - return nil, ([[ - nomsu:def(%s, %s, %s) - ]]):format(nomsu:repr(signature), nomsu:tree_to_lua(\%body), nomsu:repr(nomsu:dedent(src))); - end), \(__src__ 1)); - -# Rule to make lua macros: -rule [compile \%macro_def to \%body] =: +immediately: lua> ".." - nomsu:assert(\%macro_def.type == "List", - "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type)); - nomsu:assert(\%body.type == "Thunk", - "Invalid type for compile definition body. Expected Thunk, but got: "..tostring(\%body.type)); - local signature = {}; - for i, alias in ipairs(\%macro_def.value) do - signature[i] = alias.src; - end - local thunk = nomsu:tree_to_value(\%body); - nomsu:defmacro(signature, thunk, ("compile %s\\n..to %s"):format(\%macro_def.src, \%body.src)); + nomsu:defmacro("rule %signature = %body", (function(nomsu, vars) + nomsu:assert(\%signature.type == "List", + "Invalid type for rule definition signature. Expected List, but got: "..tostring(\%signature.type)); + nomsu:assert(\%body.type == "Block", + "Invalid type for rule definition body. Expected Block, but got: "..tostring(\%body.type)); + local signature = {}; + for i, alias in ipairs(\%signature.value) do + signature[i] = alias.src; + end + local src = nomsu:source_code(0); + local body_lua = nomsu:tree_to_lua(\%body); + local fn_src = ([[ + function(nomsu, vars) + %s + end]]):format(body_lua.statements or ("return "..body_lua.expr..";")); + return {statements=([[ + nomsu:def(%s, %s, %s) + ]]):format(nomsu:repr(signature), fn_src, nomsu:repr(nomsu:dedent(src)))}; + end), \(__src__ 1)); -rule [compile \%macro_def to code \%body] =: - lua> ".." - nomsu:assert(\%macro_def.type == "List", - "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type)); - nomsu:assert(\%body.type == "Thunk", - "Invalid type for compile definition body. Expected Thunk, but got: "..tostring(\%body.type)); - local signature = {}; - for i, alias in ipairs(\%macro_def.value) do - signature[i] = alias.src; - end - local thunk = nomsu:tree_to_value(\%body); - local thunk_wrapper = function(...) return nil, thunk(...); end - nomsu:defmacro(signature, thunk_wrapper, ("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)); +# Rules to make lua macros: +immediately: + rule [compile \%macro_def to \%body] =: + lua> ".." + nomsu:assert(\%macro_def.type == "List", + "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type)); + nomsu:assert(\%body.type == "Block", + "Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type)); + local signature = {}; + for i, alias in ipairs(\%macro_def.value) do + signature[i] = alias.src; + end + local body_lua = nomsu:tree_to_lua(\%body); + local fn_src = ([[ + function(nomsu, vars) + %s + end]]):format(body_lua.statements or ("return "..body_lua.expr..";")); + local fn = nomsu:run_lua("return "..fn_src..";"); + local fn_wrapper = function(...) return {expr=fn(...)}; end; + nomsu:defmacro(signature, fn_wrapper, ("compile %s\\n..to %s"):format(\%macro_def.src, \%body.src)); + + rule [compile \%macro_def to code \%body] =: + lua> ".." + nomsu:assert(\%macro_def.type == "List", + "Invalid type for compile definition signature. Expected List, but got: "..tostring(\%macro_def.type)); + nomsu:assert(\%body.type == "Block", + "Invalid type for compile definition body. Expected Block, but got: "..tostring(\%body.type)); + local signature = {}; + for i, alias in ipairs(\%macro_def.value) do + signature[i] = alias.src; + end + local body_lua = nomsu:tree_to_lua(\%body); + local fn_src = ([[ + function(nomsu, vars) + %s + end]]):format(body_lua.statements or ("return "..body_lua.expr..";")); + local fn = nomsu:run_lua("return "..fn_src..";"); + local fn_wrapper = function(...) return {statements=fn(...)}; end; + nomsu:defmacro(signature, fn_wrapper, ("compile %s\\n..to code %s"):format(\%macro_def.src, \%body.src)); # Rule to make nomsu macros: -lua> ".." - nomsu:defmacro("parse %shorthand as %longhand", (function(nomsu, vars) - nomsu:assert(\%shorthand.type == "List", - "Invalid type for parse definition signature. Expected List, but got: "..tostring(\%shorthand.type)); - nomsu:assert(\%longhand.type == "Thunk", - "Invalid type for parse definition body. Expected Thunk, but got: "..tostring(\%longhand.type)); - local signature = {}; - for i, alias in ipairs(\%shorthand.value) do - signature[i] = alias.src; - end - local template = {}; - for i, line in ipairs(\%longhand.value) do - template[i] = nomsu:dedent(line.src); - end - signature, template = nomsu:repr(signature), nomsu:repr(table.concat(template, "\\n")); - return nil, ([[ - nomsu:defmacro(%s, (function(nomsu, vars) - local template = nomsu:parse(%s, %s); - if #template.value == 1 then template = template.value[1]; end - local replacement = nomsu:replaced_vars(template, vars); - return nomsu:tree_to_lua(replacement); - end), %s)]]):format(signature, template, nomsu:repr(\%shorthand.line_no), nomsu:repr(nomsu:source_code(0))); - end), \(__src__ 1)); +immediately: + lua> ".." + nomsu:defmacro("parse %shorthand as %longhand", (function(nomsu, vars) + nomsu:assert(\%shorthand.type == "List", + "Invalid type for parse definition signature. Expected List, but got: "..tostring(\%shorthand.type)); + nomsu:assert(\%longhand.type == "Block", + "Invalid type for parse definition body. Expected Block, but got: "..tostring(\%longhand.type)); + local signature = {}; + for i, alias in ipairs(\%shorthand.value) do + signature[i] = alias.src; + end + local template = {}; + for i, line in ipairs(\%longhand.value) do + template[i] = nomsu:dedent(line.src); + end + signature, template = nomsu:repr(signature), nomsu:repr(table.concat(template, "\\n")); + return {expr=([[ + nomsu:defmacro(%s, (function(nomsu, vars) + local template = nomsu:parse(%s, %s); + if #template.value == 1 then template = template.value[1]; end + local replacement = nomsu:replaced_vars(template, vars); + return nomsu:tree_to_lua(replacement); + end), %s)]]):format(signature, template, nomsu:repr(\%shorthand.line_no), nomsu:repr(nomsu:source_code(0)))}; + end), \(__src__ 1)); rule [remove rule %stub] =: lua> ".." @@ -79,40 +98,29 @@ rule [remove rule %stub] =: nomsu.defs[alias] = false; end -rule [%tree as lua] =: - =lua "nomsu:tree_to_lua(\%tree)" -rule [%tree as value] =: - =lua "nomsu:tree_to_value(\%tree, vars)" -compile [repr %obj] to: - "nomsu:repr(\(%obj as lua))" -compile [indented %obj] to: - "nomsu:indent(\(%obj as lua))" -compile [dedented %obj] to: - "nomsu:dedent(\(%obj as lua))" -compile [type %obj, type of %obj] to: - "type(\(%obj as lua))" +immediately: + rule [%tree as lua] =: + =lua "nomsu:tree_to_lua(\%tree).expr" + rule [%tree as lua statements] =: + lua> ".." + local lua = nomsu:tree_to_lua(\%tree); + return lua.statements or (lua.expr..";"); + rule [%tree as value] =: + =lua "nomsu:tree_to_value(\%tree, vars)" + compile [repr %obj] to: + "nomsu:repr(\(%obj as lua))" + compile [indented %obj] to: + "nomsu:indent(\(%obj as lua))" + compile [dedented %obj] to: + "nomsu:dedent(\(%obj as lua))" + compile [type %obj, type of %obj] to: + "type(\(%obj as lua))" parse [lua do> %block] as: lua> "do" lua> %block lua> "end" -rule [%tree as lua statement] =: - lua do> ".." - local _,statement = nomsu:tree_to_lua(\%tree); - return statement; -rule [%tree as lua statements] =: - lua do> ".." - local lua_bits = {}; - nomsu:assert(type(\%tree) == 'table' and \%tree.type == "Thunk", - "Invalid type. Expected Thunk."); - for _,bit in ipairs(\%tree.value) do - local expr, statement = nomsu:tree_to_lua(bit); - if statement then table.insert(lua_bits, statement); end - if expr then table.insert(lua_bits, "ret = "..expr..";"); end - end - return table.concat(lua_bits, "\\n"); - compile [nomsu] to: "nomsu" compile [nomsu's %key] to: "nomsu[\(%key as lua)]" compile [nomsu %method %args] to: "nomsu[\(%method as lua)](nomsu, unpack(\(%args as lua)))" @@ -124,7 +132,7 @@ parse [rule %signature] as: # Get the source code for a function rule [help %rule] =: - lua do> ".." + lua> ".." local fn_def = nomsu.defs[nomsu:get_stub(\%rule)] if not fn_def then nomsu:writeln("Rule not found: "..nomsu:repr(\%rule)); @@ -135,7 +143,7 @@ rule [help %rule] =: # Compiler tools parse [eval %code, run %code] as: nomsu "run" [%code] rule [source code from tree %tree] =: - lua do> ".." + lua> ".." local _,_,leading_space = \%tree.src:find("\\n(%s*)%S"); if leading_space then local chunk1, chunk2 = \%tree.src:match(":%s*([^\\n]*)(\\n.*)"); diff --git a/lib/operators.nom b/lib/operators.nom index 59a9ad2..2f08089 100644 --- a/lib/operators.nom +++ b/lib/operators.nom @@ -51,9 +51,9 @@ compile [%var = %val] to code: lua> ".." if \%var.type == 'List' and \%val.type == 'List' then local lhs = {}; - for i,x in ipairs(\%var.value) do lhs[i] = nomsu:tree_to_lua(x); end + for i,x in ipairs(\%var.value) do lhs[i] = nomsu:tree_to_lua(x).expr; end local rhs = {}; - for i,x in ipairs(\%val.value) do rhs[i] = nomsu:tree_to_lua(x); end + for i,x in ipairs(\%val.value) do rhs[i] = nomsu:tree_to_lua(x).expr; end return table.concat(lhs, ", ").." = "..table.concat(rhs, ", ")..";"; else return \(%var as lua).." = "..\(%val as lua)..";"; |
