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/metaprogramming.nom | |
| 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/metaprogramming.nom')
| -rw-r--r-- | lib/metaprogramming.nom | 196 |
1 files changed, 102 insertions, 94 deletions
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.*)"); |
