diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-05-27 18:28:23 -0700 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-05-27 18:29:23 -0700 |
| commit | 2e15c0fd5067318601e2f3b70ee6fc16ef58200d (patch) | |
| tree | 0006e0825b2680d457bb531c3d079661b16d6bc8 | |
| parent | 6ce32bdd25694d71dc232c50a008f8824f8a75ce (diff) | |
Some tweaks/cleanup on the nomsu code as well as adding variable
mangling to 'parse % as %' to make almost hygienic macros.
| -rw-r--r-- | code_obj.lua | 2 | ||||
| -rw-r--r-- | code_obj.moon | 1 | ||||
| -rw-r--r-- | core/collections.nom | 44 | ||||
| -rw-r--r-- | core/math.nom | 26 | ||||
| -rw-r--r-- | core/metaprogramming.nom | 19 | ||||
| -rw-r--r-- | core/operators.nom | 16 | ||||
| -rw-r--r-- | examples/how_do_i.nom | 8 | ||||
| -rw-r--r-- | nomsu.lua | 2 | ||||
| -rwxr-xr-x | nomsu.moon | 2 | ||||
| -rw-r--r-- | nomsu.peg | 2 | ||||
| -rw-r--r-- | tests/collections.nom | 6 | ||||
| -rw-r--r-- | tests/math.nom | 2 | ||||
| -rw-r--r-- | tests/metaprogramming.nom | 15 |
13 files changed, 94 insertions, 51 deletions
diff --git a/code_obj.lua b/code_obj.lua index e8e86fa..e77af5c 100644 --- a/code_obj.lua +++ b/code_obj.lua @@ -17,6 +17,8 @@ Source = immutable({ end if stop then assert(start <= stop + 1, "Invalid range: " .. tostring(start) .. ", " .. tostring(stop)) + else + error("HUH?") end return filename, start, stop end, diff --git a/code_obj.moon b/code_obj.moon index 14bc74a..d764430 100644 --- a/code_obj.moon +++ b/code_obj.moon @@ -9,6 +9,7 @@ Source = immutable {"filename","start","stop"}, { if not start start, stop = 1, #FILE_CACHE[filename] if stop then assert(start <= stop+1, "Invalid range: #{start}, #{stop}") + else error("HUH?") return filename, start, stop from_string: (str)=> filename,start,stop = str\match("^(.-)%[(%d+):(%d+)%]$") diff --git a/core/collections.nom b/core/collections.nom index 7922a4f..81ff3d2 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -113,23 +113,39 @@ immediately parse [keys in %dict] as: %k for %k = %v in %dict parse [values in %dict] as: %v for %k = %v in %dict +# Metatable stuff +immediately + compile [set %dict's metatable to %metatable] to + Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));" + + compile [%dict with fallback %key -> %value] to + Lua value ".." + setmetatable(\(%dict as lua expr), {__index=function(self, \(%key as lua expr)) + local value = \(%value as lua expr) + self[\(%key as lua expr)] = value + return value + end}) + +immediately + parse [new counter] as: {} with fallback % -> 0 + parse [new default dict] as: {} with fallback % -> {} + # Sorting immediately compile [sort %items] to: Lua "table.sort(\(%items as lua expr));" - compile [sort %items by %key_expr] to - Lua ".." - utils.sort(\(%items as lua expr), function(_) - return \(%key_expr as lua expr); - end); + parse [sort %items by %item = %key_expr] as + do + %keys <- ({} with fallback %item -> %key_expr) + lua> "table.sort(\%items, function(x,y) return \%keys[x] < \%keys[y] end)" immediately action [%items sorted, sorted %items] %copy <- (% for % in %items) sort %copy return %copy - action [%items sorted by %key] + action [%items sorted by %item = %key] %copy <- (% for % in %items) - sort %copy by %key + sort %copy by %item = %key return %copy action [unique %items] @@ -141,19 +157,5 @@ immediately (% in %seen) <- (yes) return %unique -immediately - # Metatable stuff - compile [set %dict's metatable to %metatable] to - Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));" - - compile [new counter] to: Lua value "setmetatable({}, {__index=function() return 0; end})" - - compile [new default dict] to - Lua value ".." - setmetatable({}, {__index=function(self, key) - t = {}; - self[key] = t; - return t; - end}) # TODO: maybe make a generator/coroutine? diff --git a/core/math.nom b/core/math.nom index ed2cdb6..677230b 100644 --- a/core/math.nom +++ b/core/math.nom @@ -74,16 +74,22 @@ compile [min of %items, smallest of %items, lowest of %items] to Lua value "utils.min(\(%items as lua expr))" compile [max of %items, biggest of %items, largest of %items, highest of %items] to Lua value "utils.max(\(%items as lua expr))" -compile [min of %items by %value_expr] to - Lua value ".." - utils.min(\(%items as lua expr), function(_) - return \(%value_expr as lua expr) - end) -compile [max of %items by %value_expr] to - Lua value ".." - utils.max(\(%items as lua expr), function(_) - return \(%value_expr as lua expr) - end) +parse [min of %items by %item = %value_expr] as + result of + <- {%best:nil, %best_key:nil} + for %item in %items + %key <- %value_expr + if: (%best = (nil)) or (%key < %best_key) + <- {%best:%item, %best_key:%key} + return %best +parse [max of %items by %item = %value_expr] as + result of + <- {%best:nil, %best_key:nil} + for %item in %items + %key <- %value_expr + if: (%best = (nil)) or (%key > %best_key) + <- {%best:%item, %best_key:%key} + return %best # Random functions action [seed random with %] diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index 76ba731..717690d 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -86,11 +86,14 @@ immediately lua:append(", ", 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.value] then return replacements[t.value] + elseif t.type == 'Var' then + return t.type.."("..repr(t.value.."#"..tostring(MANGLE_INDEX))..", "..repr(t.source)..")" elseif t.is_multi then local bits = {} for i, entry in ipairs(t.value) do @@ -104,14 +107,16 @@ immediately lua:append(")\n local tree = ", make_tree(\%longhand), "\n return nomsu:tree_to_lua(tree)\nend);") return lua -action [remove action %stub] - lua> ".." - local fn = ACTIONS[\%stub] - local stubs = ARG_ORDERS[fn] - for stub in pairs(stubs) do - ACTIONS[stub] = nil +compile [remove action %action] to + Lua ".." + do + local fn = ACTIONS[\(=lua "repr(\%action:get_stub())")] + local stubs = ARG_ORDERS[fn] + for stub in pairs(stubs) do + ACTIONS[stub] = nil + end + ARG_ORDERS[fn] = nil end - ARG_ORDERS[fn] = nil immediately action [%tree as nomsu] diff --git a/core/operators.nom b/core/operators.nom index 7f5c772..c3b56c6 100644 --- a/core/operators.nom +++ b/core/operators.nom @@ -47,9 +47,16 @@ immediately # Variable assignment operator immediately compile [%var <- %value] to - lua> "local \%var_lua = \(%var as lua);" + lua> "local \%var_lua = \(%var as lua)" assume %var_lua.is_value or barf "Invalid target for assignment: \%var" - lua> "local \%value_lua = \(%value as lua);" + lua> ".." + \%value = \%value:map(function(t) + if Action:is_instance(t) and t:get_stub() == "?" then + return \%var + end + end) + local \%value_lua = \(%value as lua) + assume %value_lua.is_value or barf "Invalid value for assignment: \%value" lua> ".." local lua = Lua(tree.source, \%var_lua, ' = ', \%value_lua, ';') @@ -67,6 +74,11 @@ immediately local lhs, rhs = Lua(tree.source), Lua(tree.source) for i, item in ipairs(\%assignments.value) do local \%target, \%value = item.value[1], item.value[2] + \%value = \%value:map(function(t) + if Action:is_instance(t) and t:get_stub() == "?" then + return \%target + end + end) local target_lua = \(%target as lua) if not target_lua.is_value then error("Invalid target for assignment: "..\(%target as text)) end local value_lua = \(%value as lua) diff --git a/examples/how_do_i.nom b/examples/how_do_i.nom index 13517fc..5269996 100644 --- a/examples/how_do_i.nom +++ b/examples/how_do_i.nom @@ -17,17 +17,17 @@ use "core" say "Hello world!" # How do I set a variable? -%x <- 1 +%foobar <- 1 %str <- "Hello world" # Expressions that are more than just literal values require parentheses: -%x <- (2 + 3) +%foobar <- (2 + 3) %one-two <- 12 say %one-two # How do I modify a variable? -%x <- (%x + 1) +%foobar <- (%foobar + 1) # Or, as a shorthand, you can do this to increment a variable: -%x +<- 1 +%foobar +<- 1 # How do I define a mutli-line string? %mutli-str <- ".." @@ -314,7 +314,7 @@ do _nomsu_chunk_counter = _nomsu_chunk_counter + 1 local filename = "<nomsu chunk #" .. tostring(_nomsu_chunk_counter) .. ">.nom" FILE_CACHE[filename] = nomsu_code - nomsu_code = Nomsu(filename, nomsu_code) + nomsu_code = Nomsu(Source(filename, 1, #nomsu_code), nomsu_code) end local userdata = { source_code = nomsu_code, @@ -325,7 +325,7 @@ class NomsuCompiler _nomsu_chunk_counter += 1 filename = "<nomsu chunk ##{_nomsu_chunk_counter}>.nom" FILE_CACHE[filename] = nomsu_code - nomsu_code = Nomsu(filename, nomsu_code) + nomsu_code = Nomsu(Source(filename,1,#nomsu_code), nomsu_code) userdata = { source_code:nomsu_code, indent: 0, errors: {}, @@ -88,7 +88,7 @@ number (Number): (("-"? (([0-9]+ "." [0-9]+) / ("." [0-9]+) / ([0-9]+)))-> tonum -- Variables can be nameless (i.e. just %) and can't contain operators like apostrophe -- which is a hack to allow %'s to parse as "%" and "' s" separately -variable (Var): "%" { ((!"'" %operator) / plain_word)* } +variable (Var): "%" { (plain_word ((!"'" %operator) / plain_word)*)? } inline_list (List): !('[..]') diff --git a/tests/collections.nom b/tests/collections.nom index 04b8a78..6329d00 100644 --- a/tests/collections.nom +++ b/tests/collections.nom @@ -31,15 +31,15 @@ assume ((values in {x:1}) = [1]) %x <- [3,1,2] sort %x assume (%x = [1,2,3]) -sort %x by (-%) +sort %x by % = (-%) assume (%x = [3,2,1]) %keys <- {1:999,2:0,3:50} -sort %x by (% in %keys) +sort %x by % = %keys.% assume (%x = [2,3,1]) assume ((unique [1,2,1,3,2,3]) = [1,2,3]) %c <- (new counter) for % in ["x","y","x","x","y"] - (% in %c) +<- 1 + %c.% +<- 1 assume (%c = {x:3,y:2}) say "Collections test passed." diff --git a/tests/math.nom b/tests/math.nom index 4232d81..8cfd0f4 100644 --- a/tests/math.nom +++ b/tests/math.nom @@ -15,5 +15,7 @@ assume ..or barf "math functions failed" assume ((463 to the nearest 100) = 500) or barf "rounding failed" assume ((2.6 to the nearest 0.25) = 2.5) or barf "rounding failed" +assume ((min of [3,-4,1,2] by % = (%*%)) = 1) +assume ((max of [3,-4,1,2] by % = (%*%)) = -4) say "Math test passed" diff --git a/tests/metaprogramming.nom b/tests/metaprogramming.nom index 9a4c9b2..26a750a 100644 --- a/tests/metaprogramming.nom +++ b/tests/metaprogramming.nom @@ -36,7 +36,20 @@ immediately parse [V] as: five assume ((V) = 5) or barf "Parse as compile action failed." -remove action "foo %" +immediately + parse [swap %x and %y] as + do + %tmp <- %x + %x <- %y + %y <- %tmp +<- {%1:1, %2:2} +swap %1 and %2 +assume ((%1 = 2) and (%2 = 1)) or barf "'parse % as %' failed on 'swap % and %'" +<- {%tmp:1, %tmp2:2} +swap %tmp and %tmp2 +assume ((%tmp = 2) and (%tmp2 = 1)) or barf "'parse % as %' variable mangling failed." + +remove action (foo %) try: foo 99 ..and if it succeeds: barf "Failed to delete action" |
