From c8ccbe5f42b5a197010b5ee95491dce5b9bbcbf4 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 6 Nov 2018 15:13:55 -0800 Subject: Removed utils.lua, simplified some metaprogramming stuff, added native support for calling functions with (%a %b %c) instead of (call %a with [%b, %c]), renamed _List -> List, _Dict -> Dict, improved example code. --- core/control_flow.nom | 2 +- core/math.nom | 81 +++++++++++++++++++++++++++++-------------- core/metaprogramming.nom | 90 ++++++++++++++++++++++++++++-------------------- core/text.nom | 4 +-- 4 files changed, 110 insertions(+), 67 deletions(-) (limited to 'core') diff --git a/core/control_flow.nom b/core/control_flow.nom index bbc98f1..a692f95 100644 --- a/core/control_flow.nom +++ b/core/control_flow.nom @@ -560,7 +560,7 @@ test: %lua = (..) Lua "\ ..do - local \(mangle "stack \(%var.1)") = _List{\(%structure as lua expr)} + local \(mangle "stack \(%var.1)") = List{\(%structure as lua expr)} while #\(mangle "stack \(%var.1)") > 0 do \(%var as lua expr) = table.remove(\(mangle "stack \(%var.1)"), 1)" %lua::append "\n " diff --git a/core/math.nom b/core/math.nom index 66f5aba..3bad78a 100644 --- a/core/math.nom +++ b/core/math.nom @@ -76,27 +76,54 @@ test: externally (%n to the nearest %rounder) means (..) =lua "(\%rounder)*math.floor((\%n / \%rounder) + .5)" -# Any/all/none +# Any/all +externally [all of %items, all %items] all mean: + for % in %items: + unless %: return (no) + return (yes) [all of %items, all %items] all compile to: unless (%items.type is "List"): - return (Lua value "utils.all(\(%items as lua expr))") + return %tree %clauses = (((% as lua expr)::text) for % in %items) return (Lua value "(\(%clauses::joined with " and "))") - [not all of %items, not all %items] all parse as (not (all of %items)) + +externally [any of %items, any %items] all mean: + for % in %items: + if %: return (yes) + return (no) [any of %items, any %items] all compile to: unless (%items.type is "List"): - return (Lua value "utils.any(\(%items as lua expr))") + return %tree %clauses = (((% as lua expr)::text) for % in %items) return (Lua value "(\(%clauses::joined with " or "))") - [none of %items, none %items] all parse as (not (any of %items)) + +# Sum/product +externally [sum of %items, sum %items] all mean: + %total = 0 + for % in %items: %total += % + return %total [sum of %items, sum %items] all compile to: unless (%items.type is "List"): - return (Lua value "utils.sum(\(%items as lua expr))") + return %tree %clauses = (((% as lua expr)::text) for % in %items) return (Lua value "(\(%clauses::joined with " + "))") +externally [product of %items, product %items] all mean: + %prod = 1 + for % in %items: %prod *= % + return %prod +[product of %items, product %items] all compile to: + unless (%items.type is "List"): + return %tree + %clauses = (((% as lua expr)::text) for % in %items) + return (Lua value "(\(%clauses::joined with " * "))") + +externally [avg of %items, average of %items] all mean (..) + (sum of %items) / (size of %items) + +# Shorthand for control flow [if all of %items %body, if all of %items then %body] all parse as (..) if (all of %items) %body @@ -136,42 +163,44 @@ externally (%n to the nearest %rounder) means (..) unless none of %items %body else %else, unless none of %items then %body else %else ..all parse as (if (any of %items) %body else %else) -[product of %items, product %items] all compile to: - unless (%items.type is "List"): - return (Lua value "utils.product(\(%items as lua expr))") - %clauses = (((% as lua expr)::text) for % in %items) - return (Lua value "(\(%clauses::joined with " * "))") - -externally [avg of %items, average of %items] all mean (..) - =lua "(utils.sum(\%items)/#\%items)" - -[min of %items, smallest of %items, lowest of %items] all compile to (..) - Lua value "utils.min(\(%items as lua expr))" - -[max of %items, biggest of %items, largest of %items, highest of %items] all compile \ -..to (Lua value "utils.max(\(%items as lua expr))") +# Min/max +externally [min of %items, smallest of %items, lowest of %items] all mean: + %best = (nil) + for % in %items: + if ((%best == (nil)) or (% < %best)): + %best = % + return %best + +externally [max of %items, biggest of %items, largest of %items, highest of %items] all mean: + %best = (nil) + for % in %items: + if ((%best == (nil)) or (% > %best)): + %best = % + return %best test: assume ((min of [3, -4, 1, 2] by % = (% * %)) == 1) assume ((max of [3, -4, 1, 2] by % = (% * %)) == -4) (min of %items by %item = %value_expr) parses as (..) result of: - set {%best:nil, %best_key:nil} + %best = (nil) + %best_key = (nil) for %item in %items: %key = %value_expr if ((%best == (nil)) or (%key < %best_key)): - set {%best:%item, %best_key:%key} - + %best = %item + %best_key = %key return %best (max of %items by %item = %value_expr) parses as (..) result of: - set {%best:nil, %best_key:nil} + %best = (nil) + %best_key = (nil) for %item in %items: %key = %value_expr if ((%best == (nil)) or (%key > %best_key)): - set {%best:%item, %best_key:%key} - + %best = %item + %best_key = %key return %best # Random functions diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index 61c877f..b104987 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -63,29 +63,33 @@ test: asdf assume (%tmp is (nil)) or barf "compile to is leaking variables" lua> "\ - ..COMPILE_ACTIONS["1 compiles to"] = function(nomsu, tree, \%actions, \%body) - if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end - local \%args = {"nomsu", "tree", unpack(table.map(\%actions[1]:get_args(), function(a) return nomsu:compile(a):text() end))} - local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), + ..COMPILE_ACTIONS["1 compiles to"] = function(nomsu, tree, \%action, \%body) + local \%args = List{\(\%nomsu), \(\%tree), unpack(\%action:get_args())} + local lua = LuaCode(tree.source, "COMPILE_ACTIONS[", \%action.stub:as_lua(), "] = ", \(what (%args -> %body) compiles to)) + return lua + end" + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(%actions all compile to %body) compiles to: + lua> "\ + ..if \%actions.type ~= "List" then + nomsu:compile_error(\%actions, "This should be a list of actions.") + end + local lua = LuaCode(tree.source, \(what (%actions.1 compiles to %body) compiles to)) + local \%args = List{\(\%nomsu), \(\%tree), unpack(\%actions[1]:get_args())} for i=2,#\%actions do local alias = \%actions[i] - local \%alias_args = {"nomsu", "tree", unpack(table.map(alias:get_args(), function(a) return nomsu:compile(a):text() \ - ..end))} + local \%alias_args = List{\(\%nomsu), \(\%tree), unpack(alias:get_args())} lua:append("\\nCOMPILE_ACTIONS[", alias.stub:as_lua(), "] = ") - if utils.equivalent(\%args, \%alias_args) then + if \%alias_args == \%args then lua:append("COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "]") else - lua:append("function(") - lua:concat_append(\%alias_args, ", ") - lua:append(")\\n return COMPILE_ACTIONS[", \%actions[1].stub:as_lua(), "](") - lua:concat_append(\%args, ", ") - lua:append(")\\nend") + lua:append(\(what (%alias_args -> \(what %actions.1 compiles to)) compiles to)) end end - return lua - end - COMPILE_ACTIONS["1 all compile to"] = COMPILE_ACTIONS["1 compiles to"]" + return lua" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -112,27 +116,29 @@ test: (baz %) parses as (foo %) assume ((foo 1) == "outer") -[%actions means %body, %actions all mean %body] all compile to: + +(%action means %body) compiles to: lua> "\ - ..if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end - local fn_name = \%actions[1].stub:as_lua_id() - local \%args = table.map(\%actions[1]:get_args(), function(a) return nomsu:compile(a):text() end) + ..local fn_name = \%action.stub:as_lua_id() + local \%args = \%action:get_args() local lua = LuaCode(tree.source, fn_name, " = ", \(what (%args -> %body) compiles to)) lua:add_free_vars({fn_name}) + return lua" +(%actions all mean %body) compiles to: + lua> "\ + ..local fn_name = \%actions[1].stub:as_lua_id() + local \%args = List(\%actions[1]:get_args()) + local lua = LuaCode(tree.source, \(what (%actions.1 means %body) compiles to)) for i=2,#\%actions do local alias = \%actions[i] local alias_name = alias.stub:as_lua_id() lua:add_free_vars({alias_name}) - local \%alias_args = table.map(alias:get_args(), function(a) return nomsu:compile(a):text() end) + local \%alias_args = List(alias:get_args()) lua:append("\\n", alias_name, " = ") - if utils.equivalent(\%args, \%alias_args) then + if \%args == \%alias_args then lua:append(fn_name) else - lua:append("function(") - lua:concat_append(\%alias_args, ", ") - lua:append(")\\n return ", fn_name, "(") - lua:concat_append(\%args, ", ") - lua:append(")\\nend") + lua:append(\(what (%alias_args -> %actions.1) compiles to)) end end return lua" @@ -143,10 +149,14 @@ test: test: assume ((baz1) == "baz1") assume ((baz2) == "baz2") -[externally %actions means %body, externally %actions all mean %body] all compile to: +(externally %action means %body) compiles to: + lua> "\ + ..local lua = \(what (%action means %body) compiles to) + lua:remove_free_vars({\%action.stub:as_lua_id()}) + return lua" +(externally %actions all mean %body) compiles to: lua> "\ - ..local lua = \(what (%actions means %body) compiles to) - if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end + ..local lua = \(what (%actions all mean %body) compiles to) lua:remove_free_vars(table.map(\%actions, function(a) return a.stub:as_lua_id() end)) return lua" @@ -169,10 +179,12 @@ test: swap %tmp and %tmp2 assume ((%tmp == 2) and (%tmp2 == 1)) or barf "\ ..'parse % as %' variable mangling failed." -[%actions parses as %body, %actions all parse as %body] all compile to: +(%actions all parse as %body) compiles to: lua> "\ ..local replacements = {} - if \%actions.type ~= "List" then \%actions = {\%actions, type="List"} end + if \%actions.type ~= "List" then + nomsu:compile_error(\%actions, "This should be a list.") + end for i,arg in ipairs(\%actions[1]:get_args()) do replacements[arg[1]] = nomsu:compile(arg):text() end @@ -208,10 +220,12 @@ test: local \%new_body = LuaCode(\%body.source, "local mangle = mangler()", "\\nreturn ", make_tree(\%body)) - local ret = \(what (%actions compiles to %new_body) compiles to) + local ret = \(what (%actions all compile to %new_body) compiles to) return ret" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[%action parses as %body] all parse as ([%action] all parse as %body) # TODO: add check for .is_value (%tree as lua expr) compiles to (..) @@ -287,10 +301,10 @@ externally (%tree with vars %replacements) means (..) externally (match %tree with %patt) means: lua> "\ - ..if \%patt.type == "Var" then return _Dict{[\%patt[1]]=\%tree} end + ..if \%patt.type == "Var" then return Dict{[\%patt[1]]=\%tree} end if \%patt.type == "Action" and \%patt.stub ~= \%tree.stub then return nil end if #\%patt ~= #\%tree then return nil end - local matches = _Dict{} + local matches = Dict{} for \%i=1,#\%patt do if SyntaxTree:is_instance(\%tree[\%i]) then local submatch = \(match %tree.%i with %patt.%i) @@ -341,11 +355,11 @@ externally (type of %) means: lua> "\ ..local lua_type = \(lua type of %) if lua_type == 'string' then return 'Text' - elseif lua_type == 'table' then + elseif lua_type == 'table' or lua_type == 'userdata' then local mt = getmetatable(\%) if mt and mt.__type then return mt.__type end - return 'Lua table' - else return lua_type end" + end + return lua_type" [% is a %type, % is an %type] all parse as ((type of %) == %type) [% isn't a %type, % isn't an %type, % is not a %type, % is not an %type] all parse as (..) diff --git a/core/text.nom b/core/text.nom index 05ec409..40eb895 100644 --- a/core/text.nom +++ b/core/text.nom @@ -22,10 +22,10 @@ test: assume ("asdf"::uppercase) == "ASDF" assume ("asdf"::with "s" -> "X") == "aXdf" assume ("one\ntwo\n"::lines) == ["one", "two", ""] - (アクション %spec %body) parses as (externally %spec means %body) + (%spec とは %body) parses as (%spec means %body) test: %こんにちは = "こんにちは" - アクション [% と言う] "\(%)世界" + (% と言う) とは "\(%)世界" assume (%こんにちは と言う) == "こんにちは世界" (%expr for %match in %text matching %patt) compiles to (..) Lua value "\ -- cgit v1.2.3