aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-05-15 16:36:21 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-05-15 16:36:38 -0700
commit01aa199f7acfe9af57c5970793259b36e060fd11 (patch)
tree0af9fd009d820053f83dd60eed862886bfb3eb5c
parent28cd9ae0b7a09d8f2cd0cd929f1ebdce4b081502 (diff)
Adding support for coroutines, and cleaning up comment syntax.
-rw-r--r--core/control_flow.nom18
-rw-r--r--core/metaprogramming.nom4
-rw-r--r--examples/how_do_i.nom4
-rw-r--r--nomsu.lua40
-rwxr-xr-xnomsu.moon22
-rw-r--r--nomsu.peg10
-rw-r--r--tests/control_flow.nom12
7 files changed, 93 insertions, 17 deletions
diff --git a/core/control_flow.nom b/core/control_flow.nom
index 2816dfb..c3b5b2b 100644
--- a/core/control_flow.nom
+++ b/core/control_flow.nom
@@ -74,11 +74,9 @@ immediately
compile [%tree has subtree %subtree where %condition] to
Lua value ".."
(function()
- for \(%subtree as lua expr) in coroutine.wrap(function() nomsu:walk_tree(\(%tree as lua expr)) end) do
- if Types.is_node(\(%subtree as lua expr)) then
- if \(%condition as lua expr) then
- return true;
- end
+ for \(%subtree as lua expr) in coroutine.wrap(function() \(%tree as lua expr):map(coroutine.yield) end) do
+ if \(%condition as lua expr) then
+ return true;
end
end
return false;
@@ -431,3 +429,13 @@ immediately
\(%body as lua statements)
end)()
+# Coroutines:
+immediately
+ compile [values %body, coroutine %body, generator %body] to
+ Lua value ".."
+ (function()
+ \(%body as lua statements)
+ end)
+ compile [->] to: Lua "coroutine.yield(true);"
+ compile [-> %] to: Lua "coroutine.yield(true, \(% as lua expr));"
+ compile [-> %k = %v] to: Lua "coroutine.yield(\(%k as lua expr), \(%v as lua expr));"
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 475cdeb..a2c3820 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -95,7 +95,7 @@ immediately
replacements = "{"..table.concat(replacements, ", ").."}";
lua:append([[)
local template = nomsu:parse(Nomsu(]]..repr(tree.source)..[[, ]]..template..[[));
- local replacement = nomsu:tree_with_replaced_vars(template, ]]..replacements..[[);
+ local replacement = nomsu:tree_with_replacements(template, ]]..replacements..[[);
return replacement:as_lua(nomsu);
end);]]);
return lua;
@@ -125,7 +125,7 @@ immediately
=lua "\%tree:as_lua(nomsu):as_statements()"
action [%tree with vars %vars]
- =lua "nomsu:tree_with_replaced_vars(\%tree, \%vars)"
+ =lua "nomsu:tree_with_replacements(\%tree, \%vars)"
compile [declare locals in %code] to
Lua value "\(%code as lua expr):declare_locals()"
diff --git a/examples/how_do_i.nom b/examples/how_do_i.nom
index f7b5c0b..0ffee38 100644
--- a/examples/how_do_i.nom
+++ b/examples/how_do_i.nom
@@ -271,8 +271,10 @@ immediately
\(%body as lua statements)
end
- # Constants can be defined as macros (but they need to be parenthesized when invoked)
+ # Constants can be defined as macros
parse [TWENTY] as: 20
+ # When they're invoked, they'll need parentheses just like a function call
+ parse [TWENTY ONE] as: 21
if (1 > (TWENTY)) is untrue
say "Nomsu parsing macros work!"
diff --git a/nomsu.lua b/nomsu.lua
index e835562..3c2fc4e 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -1,7 +1,7 @@
+local _pairs, _ipairs = pairs, ipairs
if jit then
package.cpath = "./luajit_lpeg/?.so;" .. package.cpath
bit32 = require('bit')
- local _pairs, _ipairs = pairs, ipairs
pairs = function(x)
do
local mt = getmetatable(x)
@@ -486,7 +486,7 @@ do
end
return nil
end,
- tree_with_replaced_vars = function(self, tree, replacements)
+ tree_with_replacements = function(self, tree, replacements)
if not (next(replacements)) then
return tree
end
@@ -669,6 +669,42 @@ do
return #x
end)
end
+ self.environment.ipairs = function(x)
+ if type(x) == 'function' then
+ return coroutine.wrap(x)
+ elseif type(x) == 'thread' then
+ return coroutine.resume, x, nil
+ else
+ do
+ local mt = getmetatable(x)
+ if mt then
+ if mt.__ipairs then
+ return mt.__ipairs(x)
+ end
+ else
+ return _ipairs(x)
+ end
+ end
+ end
+ end
+ self.environment.pairs = function(x)
+ if type(x) == 'function' then
+ return coroutine.wrap(x)
+ elseif type(x) == 'thread' then
+ return coroutine.resume, x, nil
+ else
+ do
+ local mt = getmetatable(x)
+ if mt then
+ if mt.__pairs then
+ return mt.__pairs(x)
+ end
+ else
+ return _pairs(x)
+ end
+ end
+ end
+ end
for k, v in pairs(Types) do
self.environment[k] = v
end
diff --git a/nomsu.moon b/nomsu.moon
index bd15a08..21aff00 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -11,13 +11,13 @@
-- Or from the command line:
-- lua nomsu.lua [input_file [output_file or -]]
export lpeg, re
+_pairs, _ipairs = pairs, ipairs
if jit
package.cpath = "./luajit_lpeg/?.so;"..package.cpath
export bit32
bit32 = require('bit')
- _pairs, _ipairs = pairs, ipairs
export pairs, ipairs
pairs = (x)->
if mt = getmetatable(x)
@@ -259,6 +259,24 @@ class NomsuCompiler
return mt.__len(x)
return #x
else ((x) -> #x)
+ @environment.ipairs = (x)->
+ if type(x) == 'function'
+ return coroutine.wrap(x)
+ elseif type(x) == 'thread'
+ return coroutine.resume, x, nil
+ elseif mt = getmetatable(x)
+ if mt.__ipairs
+ return mt.__ipairs(x)
+ else return _ipairs(x)
+ @environment.pairs = (x)->
+ if type(x) == 'function'
+ return coroutine.wrap(x)
+ elseif type(x) == 'thread'
+ return coroutine.resume, x, nil
+ elseif mt = getmetatable(x)
+ if mt.__pairs
+ return mt.__pairs(x)
+ else return _pairs(x)
for k,v in pairs(Types) do @environment[k] = v
@environment.Tuple = Tuple
@environment.Lua = Lua
@@ -422,7 +440,7 @@ class NomsuCompiler
else @walk_tree(tree.value, depth+1)
return nil
- tree_with_replaced_vars: (tree, replacements)=>
+ tree_with_replacements: (tree, replacements)=>
return tree unless next(replacements)
if next(replacements).type == "Var"
replacements = {tostring(k\as_lua(@)),v for k,v in pairs(replacements)}
diff --git a/nomsu.peg b/nomsu.peg
index 4deb4ef..4ebf6c2 100644
--- a/nomsu.peg
+++ b/nomsu.peg
@@ -124,12 +124,12 @@ inline_dict_item:
dict_key:
text_word / inline_expression
-block_comment: "#.." [^%nl]* (%nl+ %indent [^%nl]* (%nl+ %nodent [^%nl]*)* %dedent)?
-line_comment: "#" [^%nl]*
+comment: "#" [^%nl]* (%nl+ %indent [^%nl]* (%nl+ %nodent [^%nl]*)* %dedent)?
+eol_comment: "#" [^%nl]*
-eol: %ws* line_comment? (!. / &%nl)
-ignored_line: (%nodent (block_comment / line_comment)) / (%ws* (!. / &%nl))
-indent: eol (%nl ignored_line)* %nl %indent ((block_comment/line_comment) (%nl ignored_line)* nodent)?
+eol: %ws* eol_comment? (!. / &%nl)
+ignored_line: (%nodent comment) / (%ws* (!. / &%nl))
+indent: eol (%nl ignored_line)* %nl %indent (comment (%nl ignored_line)* nodent)?
nodent: eol (%nl ignored_line)* %nl %nodent
dedent: eol (%nl ignored_line)* (((!.) &%dedent) / (&(%nl %dedent)))
non_dedent_error: (!dedent .)* eol (%nl ignored_line)* (!. / &%nl)
diff --git a/tests/control_flow.nom b/tests/control_flow.nom
index 4fed7b4..899da22 100644
--- a/tests/control_flow.nom
+++ b/tests/control_flow.nom
@@ -200,3 +200,15 @@ assume
for all [1,2,3]: %n +<- %
return %n
..= 6
+
+%nums <- []
+for all
+ values
+ -> 4
+ -> 5
+ -> 6
+..
+ add % to %nums
+
+assume (%nums = [4,5,6]) or barf "Coroutine iteration failed"
+