diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-06-14 21:59:25 -0700 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-06-14 21:59:43 -0700 |
| commit | 82cfd3e54b5910843c091a9fb6ef3ad6b64ba757 (patch) | |
| tree | aed04a3910646c82447b9b4b515169005b3010af /core | |
| parent | 282565a309aef632502a64fef0a67b0b7efcfaaa (diff) | |
More streamlining and cleanup. Especially for core/metaprogramming.nom
Diffstat (limited to 'core')
| -rw-r--r-- | core/collections.nom | 12 | ||||
| -rw-r--r-- | core/control_flow.nom | 2 | ||||
| -rw-r--r-- | core/math.nom | 27 | ||||
| -rw-r--r-- | core/metaprogramming.nom | 243 | ||||
| -rw-r--r-- | core/operators.nom | 15 | ||||
| -rw-r--r-- | core/text.nom | 20 |
6 files changed, 133 insertions, 186 deletions
diff --git a/core/collections.nom b/core/collections.nom index a8a28b2..8a59852 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -16,8 +16,8 @@ immediately ..to: Lua value "utils.nth_to_last(\(%list as lua expr), \(%index as lua expr))" immediately - parse [first in %list, first %list] as: 1 st in %list - parse [last in %list, last %list] as: 1 st to last in %list + parse [last in %list] as: 1st to last in %list + parse [first in %list] as: %list.1 # Membership testing immediately @@ -62,8 +62,8 @@ immediately parse [%expression for %item in %iterable] as result of %comprehension <- [] - for %i = %item in %iterable - %comprehension.%i <- %expression + for %item in %iterable + add %expression to %comprehension return %comprehension parse [..] @@ -163,8 +163,8 @@ immediately %unique <- [] %seen <- {} for % in %items - unless: % in %seen + unless: %seen.% add % to %unique - (% in %seen) <- (yes) + %seen.% <- (yes) return %unique diff --git a/core/control_flow.nom b/core/control_flow.nom index f0238a4..2c85221 100644 --- a/core/control_flow.nom +++ b/core/control_flow.nom @@ -39,7 +39,7 @@ immediately ..to # If %when_true_expr is guaranteed to be truthy, we can use Lua's idiomatic equivalent of a conditional expression: (cond and if_true or if_false) - if: %when_true_expr.type in {Text:yes, List:yes, Dict:yes, Number:yes} + if: {Text:yes, List:yes, Dict:yes, Number:yes}.(%when_true_expr.type) return Lua value ".." (\(%condition as lua expr) and \(%when_true_expr as lua expr) or \(%when_false_expr as lua expr)) diff --git a/core/math.nom b/core/math.nom index 1e733e7..57088eb 100644 --- a/core/math.nom +++ b/core/math.nom @@ -5,6 +5,7 @@ use "core/metaprogramming.nom" use "core/text.nom" use "core/operators.nom" use "core/control_flow.nom" +use "core/collections.nom" # Literals: compile [infinity, inf] to: Lua value "math.huge" @@ -30,7 +31,7 @@ compile [hyperbolic cosine %, cosh %] to: Lua value "math.cosh(\(% as lua expr)) compile [hyperbolic tangent %, tanh %] to: Lua value "math.tanh(\(% as lua expr))" compile [e^%, exp %] to: Lua value "math.exp(\(% as lua expr))" compile [natural log %, ln %, log %] to: Lua value "math.log(\(% as lua expr))" -compile [log % base %base, log_%base %, log base %base %] to: Lua value "math.log(\(% as lua expr), \(%base as lua expr))" +compile [log % base %base, log base %base of %] to: Lua value "math.log(\(% as lua expr), \(%base as lua expr))" compile [floor %] to: Lua value "math.floor(\(% as lua expr))" compile [ceiling %, ceil %] to: Lua value "math.ceil(\(% as lua expr))" compile [round %, % rounded] to: Lua value "math.floor(\(% as lua expr) + .5)" @@ -39,34 +40,26 @@ action [%n to the nearest %rounder] # Any/all/none compile [all of %items, all %items] to - unless: (%items' "type") is "List" + unless: %items.type is "List" return: Lua value "utils.all(\(%items as lua expr))" - %clauses <- [] - for % in %items - lua> "table.insert(\%clauses, \(% as lua expr));" + %clauses <- ((% as lua expr) for % in %items) return: Lua value "(\(%clauses joined with " and "))" parse [not all of %items, not all %items] as: not (all of %items) compile [any of %items, any %items] to - unless: (%items' "type") is "List" + unless: %items.type is "List" return: Lua value "utils.any(\(%items as lua expr))" - %clauses <- [] - for % in %items - lua> "table.insert(\%clauses, \(% as lua expr));" + %clauses <- ((% as lua expr) for % in %items) return: Lua value "(\(%clauses joined with " or "))" parse [none of %items, none %items] as: not (any of %items) compile [sum of %items, sum %items] to - unless: (%items' "type") is "List" + unless: %items.type is "List" return: Lua value "utils.sum(\(%items as lua expr))" - %clauses <- [] - for % in %items - lua> "table.insert(\%clauses, \(% as lua expr));" + %clauses <- ((% as lua expr) for % in %items) return: Lua value "(\(%clauses joined with " + "))" compile [product of %items, product %items] to - unless: (%items' "type") is "List" + unless: %items.type is "List" return: Lua value "utils.product(\(%items as lua expr))" - %clauses <- [] - for % in %items - lua> "table.insert(\%clauses, \(% as lua expr));" + %clauses <- ((% as lua expr) for % in %items) return: Lua value "(\(%clauses joined with " * "))" action [avg of %items, average of %items] =lua "(utils.sum(\%items)/#\%items)" diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index 83179f5..15c5817 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -5,161 +5,109 @@ # Compile-time action to make compile-time actions: immediately lua> ".." - _ENV['ACTION'..string.as_lua_id("compile % to %")] = compile_time(function(tree, \%actions, \%lua) - local lua = Lua(tree.source) - local canonical = \%actions[1] - lua:append("ACTION", string.as_lua_id(canonical.stub), ' = compile_time(function(tree') - local args = {} - for i,tok in ipairs(canonical) do - if tok.type == "Var" then args[#args+1] = tok end + A_give_1_nickname_2 = compile_time(function(tree, \%action, \%nickname, is_compile_time) + local function arg_to_string(a) return tostring(nomsu:tree_to_lua(a)) end + local action_args = table.map(\%action:get_args(), arg_to_string) + local nickname_args = table.map(\%nickname:get_args(), arg_to_string) + if utils.equivalent(action_args, nickname_args) then + return Lua(tree.source, "A", string.as_lua_id(\%nickname.stub), " = A", string.as_lua_id(\%action.stub)) + end + local lua = Lua(tree.source, "A", string.as_lua_id(\%nickname.stub), " = ") + if is_compile_time or COMPILE_TIME[_ENV["A"..string.as_lua_id(\%action.stub)]] then + lua:append("compile_time") + table.insert(action_args, 1, "tree") + table.insert(nickname_args, 1, "tree") + end + lua:append("(function(") + lua:concat_append(nickname_args, ", ") + lua:append(")\n return A", string.as_lua_id(\%action.stub), "(") + lua:concat_append(action_args, ", ") + lua:append(")\nend)") + return lua + end) + + __MANGLE_INDEX = 0 + A_parse_1_as_2 = compile_time(function(tree, \%actions, \%body) + local replacements = {} + for i,arg in ipairs(\%actions[1]:get_args()) do + replacements[arg[1]] = tostring(nomsu:tree_to_lua(arg)) + end + local function make_tree(t) + if not AST.is_syntax_tree(t) then + return repr(t) + elseif t.type ~= 'Var' then + local args = table.map(t, make_tree) + table.insert(args, 1, repr(tostring(t.source))) + return t.type.."("..table.concat(args, ", ")..")" + elseif replacements[t[1]] then + return replacements[t[1]] + else + return t.type.."("..repr(tostring(t.source))..", "..repr(t[1].." \\0").."..('%X'):format(__MANGLE_INDEX))" + end end - local canonical_arg_positions = {} - for i, arg in ipairs(args) do - canonical_arg_positions[arg[1]] = i + local lua = Lua(tree.source, "A", string.as_lua_id(\%actions[1].stub), " = compile_time(function(tree") + for _,arg in ipairs(\%actions[1]:get_args()) do lua:append(", ", nomsu:tree_to_lua(arg)) end - local body_lua = nomsu:tree_to_lua(\%lua):as_statements("return ") - body_lua:remove_free_vars(args) - body_lua:declare_locals() - lua:append(")\n ", body_lua, "\nend)") + lua:append(")\n __MANGLE_INDEX = __MANGLE_INDEX + 1", + "\n local tree = ", make_tree(\%body), + "\n local lua = nomsu:tree_to_lua(tree)", + "\n lua:remove_free_vars({") + local vars = table.map(\%actions[1]:get_args(), function(a) + return "Var("..repr(tostring(a.source))..", "..repr(a[1])..")" + end) + lua:concat_append(vars, ", ") + lua:append("})\n return lua\nend)") for i=2,#\%actions do - local action = \%actions[i] - lua:append("\n", "ACTION", string.as_lua_id(action.stub), " = ACTION", string.as_lua_id(canonical.stub)) - - local arg_positions = {} - for _,tok in ipairs(action) do - if tok.type == 'Var' then - arg_positions[#arg_positions+1] = canonical_arg_positions[tok[1]] - end - end - lua:append("\n", "ARG_ORDERS[", repr(action.stub), "] = ", repr(arg_positions)) + lua:append("\n", A_give_1_nickname_2(\%actions[i], \%actions[1], \%actions[i], true)) end - lua:append("\nALIASES[ACTION", string.as_lua_id(canonical.stub), "] = {") - for i,action in ipairs(\%actions) do - if i > 1 then lua:append(", ") end - lua:append(repr(action.stub)) - end - lua:append("}") return lua end) -# Compile-time action to make actions -immediately - compile [action %actions %body] to - lua> ".." - local lua = Lua(tree.source) - local canonical = \%actions[1] - lua:append("ACTION", string.as_lua_id(canonical.stub), ' = function(') - local args = {} - for i,tok in ipairs(canonical) do - if tok.type == "Var" then args[#args+1] = tok end - end - local canonical_arg_positions = {} - for i, arg in ipairs(args) do - canonical_arg_positions[arg[1]] = i - lua:append(nomsu:tree_to_lua(arg)) - if i < #args then lua:append(", ") end - end + A_action_1_2 = compile_time(function(tree, \%actions, \%body, is_compile_time) + local lua = Lua(tree.source, "A", string.as_lua_id(\%actions[1].stub), " = ") + if is_compile_time then lua:append("compile_time") end + lua:append("(function(") + local args = \%actions[1]:get_args() + local lua_args = table.map(args, function(a) return nomsu:tree_to_lua(a) end) + if is_compile_time then table.insert(lua_args, 1, "tree") end + lua:concat_append(lua_args, ", ") local body_lua = nomsu:tree_to_lua(\%body):as_statements("return ") body_lua:remove_free_vars(args) body_lua:declare_locals() - lua:append(")\n ", body_lua, "\nend") - + lua:append(")\n ", body_lua, "\nend)") for i=2,#\%actions do - local action = \%actions[i] - lua:append("\n", "ACTION", string.as_lua_id(action.stub), " = ACTION", string.as_lua_id(canonical.stub)) - - local arg_positions = {} - for _,tok in ipairs(action) do - if tok.type == 'Var' then - arg_positions[#arg_positions+1] = canonical_arg_positions[tok[1]] - end - end - lua:append("\n", "ARG_ORDERS[", repr(action.stub), "] = ", repr(arg_positions)) - end - lua:append("\nALIASES[ACTION", string.as_lua_id(canonical.stub), "] = {") - for i,action in ipairs(\%actions) do - if i > 1 then lua:append(", ") end - lua:append(repr(action.stub)) + lua:append("\n", A_give_1_nickname_2(\%actions[i], \%actions[1], \%actions[i], is_compile_time)) end - lua:append("}") return lua + end) -# Macro to make nomsu macros -immediately - compile [parse %shorthand as %longhand] to - lua> ".." - local lua = Lua(tree.source) - local canonical = \%shorthand[1] - lua:append("ACTION", string.as_lua_id(canonical.stub), ' = compile_time(function(tree') - local args = {} - for i,tok in ipairs(canonical) do - if tok.type == "Var" then args[#args+1] = tok end - end - local canonical_arg_positions = {} - for i, arg in ipairs(args) do - canonical_arg_positions[arg[1]] = i - lua:append(", ", nomsu:tree_to_lua(arg)) - end - - local replacements = {} - for i,tok in ipairs(canonical) do - if tok.type == "Var" then - local lua_var = tostring(nomsu:tree_to_lua(tok)) - replacements[tok[1]] = lua_var - end - end - MANGLE_INDEX = (MANGLE_INDEX or 0) + 1 - local function make_tree(t) - if type(t) ~= 'table' and type(t) ~= 'userdata' then - return repr(t) - elseif t.type == 'Var' and replacements[t[1]] then - return replacements[t[1]] - elseif t.type == 'Var' then - return t.type.."("..repr(tostring(t.source))..", "..repr(t[1].."#"..tostring(MANGLE_INDEX))..")" - else - local bits = {repr(tostring(t.source))} - for i, entry in ipairs(t) do - bits[#bits+1] = make_tree(entry) - end - return t.type.."("..table.concat(bits, ", ")..")" - end - end - lua:append(")\n local tree = ", make_tree(\%longhand), "\n return nomsu:tree_to_lua(tree)\nend)") - - for i=2,#\%shorthand do - local action = \%shorthand[i] - lua:append("\n", "ACTION", string.as_lua_id(action.stub), " = ACTION", string.as_lua_id(canonical.stub)) - - local arg_positions = {} - for _,tok in ipairs(action) do - if tok.type == 'Var' then - arg_positions[#arg_positions+1] = canonical_arg_positions[tok[1]] - end - end - lua:append("\n", "ARG_ORDERS[", repr(action.stub), "] = ", repr(arg_positions)) - end - lua:append("\nALIASES[ACTION", string.as_lua_id(canonical.stub), "] = {") - for i,action in ipairs(\%shorthand) do - if i > 1 then lua:append(", ") end - lua:append(repr(action.stub)) - end - lua:append("}") - return lua + A_compile_1_to_2 = compile_time(function(tree, \%actions, \%body) + return A_action_1_2(tree, \%actions, \%body, true) + end) compile [remove action %action] to Lua ".." - do - local fn = ACTION\(=lua "string.as_lua_id(\(%action.stub))") - for stub in pairs(ALIASES[fn]) do - _ENV['ACTION'..string.as_lua_id(stub)] = nil - end - ARG_ORDERS[fn] = nil - COMPILE_TIME[fn] = nil - end + A\(=lua "string.as_lua_id(\(%action.stub))") = nil + ARG_ORDERS[fn] = nil + COMPILE_TIME[fn] = nil immediately + action [read file %filename] + lua> ".." + local file = io.open(\%filename) + local contents = file:read("*a") + file:close() + return contents + + action [sh> %cmd] + lua> ".." + local result = io.popen(\%cmd) + local contents = result:read("*a") + result:close() + return contents + action [%tree as nomsu] =lua "nomsu:tree_to_nomsu(\%tree)" @@ -182,11 +130,16 @@ immediately action [%tree as lua return] =lua "nomsu:tree_to_lua(\%tree):as_statements('return ')" + + action [%var as lua identifier] + =lua "type(\%var) == 'string' and string.as_lua_id(\%var) or nomsu:tree_to_lua(\%var)" + +immediately + compile [parse %text] to + Lua value ".." + nomsu:parse(Nomsu("\("\(%text.source)")", \(%text as lua expr))) immediately - compile [%tree with vars %vars] to - barf "Deprecated" - compile [%tree with %t -> %replacement] to Lua value ".." \(%tree as lua expr):map(function(\(%t as lua expr)) @@ -211,8 +164,7 @@ immediately return nomsu:run_lua(lua) immediately - parse [%var <-write %code] as: lua> "\%var:append(\%code);" - parse [to %var write %code] as: lua> "\%var:append(\%code);" + parse [%lua <-write %code, to %lua write %code] as: lua> "\%lua:append(\%code);" immediately compile [quote %s] to @@ -222,7 +174,6 @@ immediately immediately compile [nomsu] to: Lua value "nomsu" - compile [%var as lua identifier] to: Lua value "nomsu:tree_to_lua(\(%var as lua expr))" # Compiler tools immediately @@ -239,9 +190,17 @@ immediately compile [say %message] to lua> ".." if \%message.type == "Text" then - return Lua(tree.source, "print(", \(%message as lua expr), ");"); + return Lua(tree.source, "io.write(", \(%message as lua expr), ", '\\\\n');"); + else + return Lua(tree.source, "io.write(tostring(", \(%message as lua expr), "), '\\\\n');"); + end + + compile [ask %prompt] to + lua> ".." + if \%prompt.type == "Text" then + return Lua.Value(tree.source, "(io.write(", \(%prompt as lua expr), ") and io.read())"); else - return Lua(tree.source, "print(tostring(", \(%message as lua expr), "));"); + return Lua.Value(tree.source, "(io.write(tostring(", \(%prompt as lua expr), ")) and io.read())"); end # Return diff --git a/core/operators.nom b/core/operators.nom index 555a636..3ea0fe1 100644 --- a/core/operators.nom +++ b/core/operators.nom @@ -3,19 +3,6 @@ use "core/metaprogramming.nom" -# Indexing -immediately - # NOTE!!! It's critical that there are spaces around %key if it's a string, - otherwise, Lua will get confused and interpret %obj[[[foo]]] as %obj("[foo]") - instead of %obj[ "foo" ]. - It's also critical to have parens around %obj, otherwise Lua is too dumb to - realize that {x=1}["x"] is the same as ({x=1})["x"] or that - {x=1}.x is the same as ({x=1}).x - parse [..] - %obj' %key, %obj's %key, %key in %obj, %key'th in %obj, %key of %obj, - %key st in %obj, %key nd in %obj, %key rd in %obj, %key th in %obj, - ..as: %obj.%key - # Comparison Operators immediately compile [%x < %y] to: Lua value "(\(%x as lua expr) < \(%y as lua expr))" @@ -53,7 +40,7 @@ immediately immediately # Simultaneous mutli-assignments like: x,y,z = 1,x,3; compile [<- %assignments] to - assume ((%assignments' "type") is "Dict") or barf ".." + assume (%assignments.type is "Dict") or barf ".." Expected a Dict for the assignments part of '<- %' statement, not \%assignments lua> ".." local lhs, rhs = Lua(tree.source), Lua(tree.source) diff --git a/core/text.nom b/core/text.nom index 8b75ca4..e6065c1 100644 --- a/core/text.nom +++ b/core/text.nom @@ -18,6 +18,14 @@ compile [capitalized %text, %text capitalized] to compile [%text with %sub instead of %patt, %text s/%patt/%sub] to Lua value "((\(%text as lua expr)):gsub(\(%patt as lua expr), \(%sub as lua expr)))" +action [lines in %text, lines of %text] + lua> ".." + local result = {} + for line in (\%text):gmatch('[^\n]+') do + result[#result+1] = line + end + return result + # Text literals lua> ".." do @@ -26,8 +34,8 @@ lua> ".." backspace="\\\\b", ["form feed"]="\\\\f", formfeed="\\\\f", ["vertical tab"]="\\\\v", }; for name, e in pairs(escapes) do - local lua = "'"..e.."'"; - nomsu:define_compile_action(name, function(tree) return Lua.Value(tree.source, lua); end); + local lua = "'"..e.."'" + _ENV["A"..name:as_lua_id()] = compile_time(function(tree) return Lua.Value(tree.source, lua) end) end local colors = { ["reset color"]="\\\\27[0m", bright="\\\\27[1m", dim="\\\\27[2m", underscore="\\\\27[4m", @@ -42,10 +50,10 @@ lua> ".." for name, c in pairs(colors) do local color = "'"..c.."'"; local reset = "'"..colors["reset color"].."'"; - nomsu:define_compile_action(name, function(tree) return Lua.Value(tree.source, color); end); - nomsu:define_compile_action(name.." %", function(\%) - return Lua.Value(tree.source, color, "..", \(% as lua), "..", reset); - end); + _ENV["A"..name:as_lua_id()] = compile_time(function(tree) return Lua.Value(tree.source, color) end) + _ENV["A"..name:as_lua_id().."_1"] = compile_time(function(tree, text) + return Lua.Value(tree.source, color, "..", nomsu:tree_to_lua(text), "..", reset); + end) end end |
