aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-05-27 18:28:23 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-05-27 18:29:23 -0700
commit2e15c0fd5067318601e2f3b70ee6fc16ef58200d (patch)
tree0006e0825b2680d457bb531c3d079661b16d6bc8
parent6ce32bdd25694d71dc232c50a008f8824f8a75ce (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.lua2
-rw-r--r--code_obj.moon1
-rw-r--r--core/collections.nom44
-rw-r--r--core/math.nom26
-rw-r--r--core/metaprogramming.nom19
-rw-r--r--core/operators.nom16
-rw-r--r--examples/how_do_i.nom8
-rw-r--r--nomsu.lua2
-rwxr-xr-xnomsu.moon2
-rw-r--r--nomsu.peg2
-rw-r--r--tests/collections.nom6
-rw-r--r--tests/math.nom2
-rw-r--r--tests/metaprogramming.nom15
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 <- ".."
diff --git a/nomsu.lua b/nomsu.lua
index cc95de4..fcd8d38 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -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,
diff --git a/nomsu.moon b/nomsu.moon
index 7d9a2bb..1da214b 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -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: {},
diff --git a/nomsu.peg b/nomsu.peg
index e5f6c56..90becb7 100644
--- a/nomsu.peg
+++ b/nomsu.peg
@@ -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"