aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-04-19 17:23:44 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-04-19 17:23:54 -0700
commitda33269c307c8a045e548cb1df2a3281a7a0f99e (patch)
tree9451b857633b0869b4589a73107056815aa560c7
parentdcb380f1f6ec67c52364b1246546f1f6b2c168d3 (diff)
All tests passing (except object)
-rw-r--r--core/collections.nom58
-rw-r--r--core/control_flow.nom240
-rw-r--r--core/math.nom90
-rw-r--r--core/metaprogramming.nom37
-rw-r--r--core/operators.nom44
-rw-r--r--core/text.nom20
-rw-r--r--lib/object2.nom49
-rw-r--r--lua_obj.lua112
-rw-r--r--lua_obj.moon67
-rw-r--r--nomsu.lua5
-rwxr-xr-xnomsu.moon5
-rw-r--r--nomsu_tree.moon11
-rw-r--r--tests/collections.nom2
-rw-r--r--tests/metaprogramming.nom8
-rw-r--r--tests/object.nom37
-rw-r--r--tests/operators.nom16
16 files changed, 411 insertions, 390 deletions
diff --git a/core/collections.nom b/core/collections.nom
index 481d283..d4d4c5b 100644
--- a/core/collections.nom
+++ b/core/collections.nom
@@ -13,7 +13,7 @@ immediately:
compile [..]
%index st to last in %list, %index nd to last in %list, %index rd to last in %list
%index th to last in %list
- ..to {expr:"utils.nth_to_last(\(%list as lua expr), \(%index as lua expr))"}
+ ..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
@@ -37,35 +37,35 @@ immediately:
immediately:
# Note: it's important to have the space after "[" to prevent confusion if %index is a string
- compile [%list has key %index, %list has index %index] to {..}
- expr: ".."
+ compile [%list has key %index, %list has index %index] to
+ Lua value ".."
((\(%list as lua expr))[ \(%index as lua expr)] ~= nil)
# Note: it's important to have the space after "[" to prevent confusion if %index is a string
compile [..]
%list doesn't have key %index, %list does not have key %index
%list doesn't have index %index, %list does not have index %index
- ..to {expr:"((\(%list as lua expr))[ \(%index as lua expr)] == nil)"}
+ ..to: Lua value "((\(%list as lua expr))[ \(%index as lua expr)] == nil)"
- compile [length of %list, size of %list, size %list, number of %list, len %list] to:
- {expr:"utils.size(\(%list as lua expr))"}
+ compile [number of keys in %list] to:
+ Lua value "utils.size(\(%list as lua expr))"
compile [append %item to %list, add %item to %list, to %list add %item, to %list append %item] to:
- {statements:"table.insert(\(%list as lua expr), \(%item as lua expr))"}
+ Lua "table.insert(\(%list as lua expr), \(%item as lua expr))"
compile [pop from %list, remove last from %list] to:
- {statements:"table.remove(\(%list as lua expr))"}
+ Lua "table.remove(\(%list as lua expr))"
compile [remove index %index from %list] to:
- {statements:"table.remove(\(%list as lua expr), \(%index as lua expr))"}
+ Lua "table.remove(\(%list as lua expr), \(%index as lua expr))"
# List Comprehension
immediately:
compile [%expression for %item in %iterable] to:
assume (%item.type is "Var") or barf ".."
List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item.type)
- return {..}
- expr:".."
+ return
+ Lua value ".."
(function()
local comprehension = {};
for i,\(%item as lua expr) in ipairs(\(%iterable as lua expr)) do
@@ -81,8 +81,8 @@ immediately:
..to:
assume (%index.type is "Var") or barf ".."
List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%index.type)
- return {..}
- expr:".."
+ return
+ Lua value ".."
(function()
local comprehension = {};
for \(%index as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(%step as lua expr) do
@@ -103,8 +103,8 @@ immediately:
List comprehension has the wrong type for the key loop variable. Expected Var, but got: \(%key.type)
assume (%value.type is "Var") or barf ".."
List comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%value.type)
- return {..}
- expr: ".."
+ return
+ Lua value ".."
(function()
local comprehension = {};
for \(%key as lua expr), \(%value as lua expr) in pairs(\(%iterable as lua expr)) do
@@ -119,8 +119,8 @@ immediately:
assume (%item.type is "Var") or barf ".."
Dict comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item.type)
# Note: it's important to have the space after "[" to prevent confusion if %key is a string
- return {..}
- expr: ".."
+ return
+ Lua value ".."
(function()
local comprehension = {};
for i,\(%item as lua expr) in ipairs(\(%iterable as lua expr)) do
@@ -136,8 +136,8 @@ immediately:
assume (%src_value.type is "Var") or barf ".."
Dict comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%src_value.type)
# Note: it's important to have the space after "[" to prevent confusion if %key is a string
- return {..}
- expr: ".."
+ return
+ Lua value ".."
(function()
local comprehension = {};
for \(%src_key as lua expr), \(%src_value as lua expr) in pairs(\(%iterable as lua expr)) do
@@ -160,12 +160,12 @@ immediately:
# Sorting:
immediately:
- compile [sort %items] to {statements:"table.sort(\(%items as lua expr))"}
- compile [sort %items by %key_expr] to {..}
- statements: ".."
- utils.sort(\(%items as lua expr), function(\(\% as lua expr))
+ 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)
+ end);
immediately:
action [%items sorted, sorted %items]:
@@ -188,13 +188,13 @@ immediately:
immediately:
# Metatable stuff
- compile [set %dict's metatable to %metatable] to {..}
- statements: "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
+ compile [set %dict's metatable to %metatable] to
+ Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
- compile [new counter] to {expr:"setmetatable({}, {__index=function() return 0; end})"}
+ compile [new counter] to: Lua value "setmetatable({}, {__index=function() return 0; end})"
- compile [new default dict] to {..}
- expr: ".."
+ compile [new default dict] to
+ Lua value ".."
setmetatable({}, {__index=function(self, key)
t = {};
self[key] = t;
diff --git a/core/control_flow.nom b/core/control_flow.nom
index 39d496d..0f081fc 100644
--- a/core/control_flow.nom
+++ b/core/control_flow.nom
@@ -41,14 +41,14 @@ immediately
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}
return:
- Lua ".."
+ Lua value ".."
(\(%condition as lua expr) and \(%when_true_expr as lua expr) or \(%when_false_expr as lua expr))
..else:
#.. Otherwise, need to do an anonymous inline function (yuck, too bad lua
doesn't have a proper ternary operator!)
To see why this is necessary consider: (random()<.5 and false or 99)
return:
- Lua ".."
+ Lua value ".."
(function()
if \(%condition as lua expr) then
return \(%when_true_expr as lua expr);
@@ -87,14 +87,15 @@ immediately:
compile [do next repeat] to: Lua "goto continue_repeat;"
compile [stop repeating] to: Lua "goto stop_repeat;"
compile [repeat while %condition %body] to
- %lua <-: Lua "while \(%condition as lua expr) do"
+ %lua <-
+ Lua ".."
+ while \(%condition as lua expr) do
+ \(%body as lua statements)
if %body has subtree % where:
(%.type = "Action") and ((%'s stub) is "do next repeat")
..:
- %lua <-write "\n::continue_repeat::;"
- %lua <-write "\n"
- %lua <-write (%body as lua statements)
- %lua <-write "\nend --while-loop"
+ to %lua write "\n::continue_repeat::;"
+ to %lua write "\nend --while-loop"
if %body has subtree % where:
(%.type = "Action") and ((%'s stub) is "stop repeating")
..:
@@ -110,11 +111,14 @@ immediately:
compile [..]
repeat %n times %body
..to:
- %lua <-: Lua "for i=1,\(%n as lua expr) do"
+ %lua <-
+ Lua ".."
+ for i=1,\(%n as lua expr) do
+ \(%body as lua statements)
if %body has subtree % where
(%.type = "Action") and ((%'s stub) is "do next repeat")
- ..: %lua <-write "\n::continue_repeat::;"
- %lua <-write "\n\(%body as lua statements)\nend --numeric for-loop"
+ ..: to %lua write "\n::continue_repeat::;"
+ to %lua write "\nend --numeric for-loop"
if %body has subtree % where:
(%.type = "Action") and ((%'s stub) is "stop repeating")
..:
@@ -143,20 +147,21 @@ immediately:
assume (%var.type is "Var") or barf "Loop expected variable, not: \(%var's source code)"
%lua <-
Lua ".."
- for \(%var as lua expr)=\(%start as lua expr),\(%n as lua expr) do
+ for \(%var as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(%step as lua expr) do
+ \(%body as lua statements)
if %body has subtree % where:
(%.type = "Action") and
((%'s stub) is "do next %") and
%.value.3.value is %var.value
- ..: %lua <-write "\n::continue_\(%var as lua identifier)::;"
- %lua <-write "\n\(%body as lua statements)\nend --numeric for-loop"
+ ..: to %lua write "\n::continue_\(%var as lua identifier)::;"
+ to %lua write "\nend --numeric for-loop"
if %body has subtree % where:
(%.type = "Action") and:
((%'s stub) is "stop %") and:
%.value.2.value is %var.value
..:
- %lua <-write ".."
+ to %lua write ".."
do -- scope for stopping for-loop
\%lua
::stop_\(%var as lua identifier)::;
@@ -177,13 +182,16 @@ immediately:
compile [for %var in %iterable %body] to:
# This uses Lua's approach of only allowing loop-scoped variables in a loop
assume (%var.type is "Var") or barf "Loop expected variable, not: \(%var's source code)"
- %lua <-: Lua "for i,\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do"
+ %lua <-
+ Lua ".."
+ for i,\(%var as lua identifier) in ipairs(\(%iterable as lua expr)) do
+ \(%body as lua statements)
if %body has subtree % where:
(%.type = "Action") and
((%'s stub) is "do next %") and
%.value.3.value is %var.value
- ..: %lua <-write (Lua "\n::continue_\(%var as lua identifier)::;")
- %lua <-write (Lua "\n\(%body as lua statements)\nend --foreach-loop")
+ ..: to %lua write (Lua "\n::continue_\(%var as lua identifier)::;")
+ to %lua write "\nend --foreach-loop"
if %body has subtree % where:
(%.type = "Action") and
((%'s stub) is "stop %") and
@@ -205,34 +213,37 @@ immediately:
# This uses Lua's approach of only allowing loop-scoped variables in a loop
assume (%key.type is "Var") or barf "Loop expected variable, not: \(%key's source code)"
assume (%value.type is "Var") or barf "Loop expected variable, not: \(%value's source code)"
- %lua <- (Lua "for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(%iterable as lua expr)) do")
+ %lua <-
+ Lua ".."
+ for \(%key as lua identifier),\(%value as lua identifier) in pairs(\(%iterable as lua expr)) do
+ \(%body as lua statements)
if %body has subtree % where:
(%.type = "Action") and
((%'s stub) is "do next %") and
%.value.3.value is %key.value
- ..: %lua <-write (Lua "\n::continue_\(%key as lua identifier)::;")
+ ..: to %lua write (Lua "\n::continue_\(%key as lua identifier)::;")
if %body has subtree % where:
(%.type = "Action") and
((%'s stub) is "do next %") and
%.value.3.value is %value.value
- ..: %lua <-write (Lua "\n::continue_\(%value as lua identifier)::;")
- %lua <-write (Lua "\n\(%body as lua statements)\nend --foreach-loop")
+ ..: to %lua write (Lua "\n::continue_\(%value as lua identifier)::;")
+ to %lua write "\nend --foreach-loop"
- %stop_labels <- ""
+ %stop_labels <- (Lua "")
if %body has subtree % where:
(%.type = "Action") and
((%'s stub) is "stop %") and
%.value.2.value is %key.value
- ..: %stop_labels <-write "\n::stop_\(%key as lua identifier)::;"
+ ..: to %stop_labels write "\n::stop_\(%key as lua identifier)::;"
if %body has subtree % where:
(%.type = "Action") and
((%'s stub) is "stop %") and
%.value.2.value is %value.value
- ..: %stop_labels <-write "\n::stop_\(%value as lua identifier)::;"
+ ..: to %stop_labels write "\n::stop_\(%value as lua identifier)::;"
- if: %stop_labels is not ""
+ if: (length of %stop_labels) > 0
%lua <-
Lua ".."
do -- scope for stopping for % = % loop
@@ -243,63 +254,57 @@ immediately:
# Switch statement/multi-branch if
immediately:
compile [when %body] to:
- %code <- ""
+ %code <- (Lua "")
%fallthroughs <- []
- %locals <- []
%is_first <- (yes)
%seen_else <- (no)
for %func_call in %body.value:
assume (%func_call.type is "Action") or barf ".."
Invalid format for 'when' statement. Only '*' blocks are allowed.
+ %tokens <- %func_call.value
with {..}
- %tokens: %func_call.value
%star: %tokens.1
%condition: %tokens.2
%action: %tokens.3
..:
- assume (=lua "\%star and \%star.type == 'Word' and \%star.value == '*'") or barf ".."
+ assume ((%star and (%star.type is "Word")) and (%star.value is "*")) or barf ".."
Invalid format for 'when' statement. Lines must begin with '*'
assume %condition or barf ".."
Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
if: %action is (nil)
lua> "table.insert(\%fallthroughs, \(%condition as lua expr));"
do next %func_call
- %action <- (%action as lua)
- %action_statements <- (%action.statements or "\(%action.expr);")
- for %local in (%action.locals or []):
- lua> "table.insert(\%locals, \%local);"
- if: =lua "\%condition.type == 'Word' and \%condition.value == 'else'"
+ if: (%condition.type is "Word") and (%condition.value is "else")
assume (not %is_first) or barf "'else' clause cannot be first in 'when % = ?' block"
- %code <-write ".."
+ to %code write ".."
else
- \%action_statements
+ \(%action as lua statements)
%seen_else <- (yes)
..else:
assume (not %seen_else) or barf "'else' clause needs to be last in 'when' block"
lua> "table.insert(\%fallthroughs, \(%condition as lua expr));"
- %condition_code <- (%fallthroughs joined with " or ")
- %code <-write ".."
-
- \("if" if %is_first else "elseif") \%condition_code then
- \%action_statements
+ to %code write "\("if" if %is_first else "\nelseif") "
+ for %i=%condition in %fallthroughs:
+ if (%i > 1): to %code write " or "
+ to %code write %condition
+ to %code write " then\n"
+ to %code write (%action as lua statements)
%fallthroughs <- []
%is_first <- (no)
assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block"
- if: %code is not ""
- %code <-write "\nend"
- lua> "utils.deduplicate(\%locals);"
- return {statements:%code, locals:%locals}
+ assume ((length of %code) > 0) or barf "Empty body for 'when' block"
+ to %code write "\nend"
+ return %code
# Switch statement
immediately:
compile [when %branch_value = ? %body, when %branch_value is ? %body] to:
- %code <- ""
+ %code <- (Lua "")
%fallthroughs <- []
- %locals <- []
%is_first <- (yes)
%seen_else <- (no)
for %func_call in %body.value:
@@ -307,7 +312,7 @@ immediately:
Invalid format for 'when' statement. Only '*' blocks are allowed.
%tokens <- %func_call.value
with {%star:%tokens.1, %condition:%tokens.2, %action:%tokens.3}:
- assume (=lua "\%star and \%star.type == 'Word' and \%star.value == '*'") or barf ".."
+ assume ((%star and (%star.type is "Word")) and (%star.value is "*")) or barf ".."
Invalid format for 'when' statement. Lines must begin with '*'
assume %condition or barf ".."
Invalid format for 'when' statement. Lines must begin with '*' and have a condition or the word "else"
@@ -315,47 +320,39 @@ immediately:
lua> "table.insert(\%fallthroughs, \(%condition as lua expr))"
do next %func_call
- %action <- (%action as lua)
- %action_statements <- (%action.statements or "\(%action.expr);")
- for %local in (%action.locals or []):
- lua> "table.insert(\%locals, \%local);"
-
- if: =lua "\%condition.type == 'Word' and \%condition.value == 'else'"
+ if: (%condition.type is "Word") and (%condition.value is "else")
assume (not %is_first) or barf "'else' clause cannot be first in 'when % = ?' block"
- %code <-write ".."
+ to %code write ".."
else
- \%action_statements
- end
- %seen_else <- (yes)
+ \(%action as lua statements)
..else:
assume (not %seen_else) or barf "'else' clause needs to be last in 'when % = ?' block"
+ to %code write "\("if" if %is_first else "\nelseif") "
lua> "table.insert(\%fallthroughs, \(%condition as lua expr));"
for %i = % in %fallthroughs
+ if: %i > 1
+ to %code write " or "
if: (%.type is "Text") or (%.type is "Number")
- (%i'th in %fallthroughs) <- "branch_value == \%"
- ..else
- (%i'th in %fallthroughs) <- "utils.equivalent(branch_value, \%)"
- %clause <- (%fallthroughs joined with " or ")
- %code <-write ".."
-
- \("if" if %is_first else "elseif") \%clause then
- \%action_statements
+ to %code write "branch_value == \%"
+ ..else:
+ to %code write "utils.equivalent(branch_value, \%)"
+ to %code write "then\n"
+ to %code write (%action as lua statements)
%fallthroughs <- []
%is_first <- (no)
assume (%fallthroughs = []) or barf "Unfinished fallthrough conditions in 'when' block"
- assume (%code is not "") or barf "No body for 'when % = ?' block!"
- unless %seen_else
- %code <-write "\nend"
- %code <- ".."
- do --when % = ?
- local branch_value = \(%branch_value as lua expr);\
- ..\%code
- end --when % = ?
- lua> "utils.deduplicate(\%locals);"
- return {statements:%code, locals:%locals}
+ assume ((length of %code) > 0) or barf "No body for 'when % = ?' block!"
+ to %code write "\nend"
+ %code <-
+ Lua ".."
+ do --when % = ?
+ local branch_value = \(%branch_value as lua expr);
+ \%code
+ end --when % = ?
+ return %code
# Try/except
immediately:
@@ -363,33 +360,22 @@ immediately:
try %action and if it succeeds %success or if it barfs %fallback
try %action and if it barfs %fallback or if it succeeds %success
..to:
- %locals <- []
- %action_lua <- (%action as lua)
- %success_lua <- (%success as lua)
- %fallback_lua <- (%fallback as lua)
- %fallback <- (%fallback as lua)
- for %block in [%action_lua, %success_lua, %fallback_lua]:
- for %local in (%block.locals or []):
- lua> "table.insert(\%locals, \%local);"
- lua> "utils.deduplicate(\%locals);"
- return {..}
- locals: %locals
- statements: ".."
- do
- local fell_through = false;
- local ok, ret = pcall(function()
- \(%action_lua.statements or "\(%action_lua.expr);")
- fell_through = true;
- end);
- if ok then
- \(%success_lua.statements or "\(%success_lua.expr);")
- end
- if not ok then
- \(%fallback_lua.statements or "\(%fallback_lua.expr);")
- elseif not fell_through then
- return ret;
- end
+ Lua ".."
+ do
+ local fell_through = false;
+ local ok, ret = pcall(function()
+ \(%action as lua statements)
+ fell_through = true;
+ end);
+ if ok then
+ \(%success as lua statements)
+ end
+ if not ok then
+ \(%fallback as lua statements)
+ elseif not fell_through then
+ return ret;
end
+ end
parse [try %action] as:
try %action and if it succeeds: do nothing
..or if it barfs: do nothing
@@ -402,38 +388,26 @@ immediately:
# Do/finally:
immediately:
compile [do %action] to:
- %action <- (%action as lua)
- return {..}
- locals: %action.locals
- statements: ".."
- do
- \(%action.statements or "\(%action.expr);")
- end
+ Lua ".."
+ do
+ \(%action as lua statements)
+ end
compile [do %action then always %final_action] to:
- %action <- (%action as lua)
- %final_action <- (%final_action as lua)
- %locals <- []
- for %sub_locals in [%action.locals, %final_action.locals]:
- for %local in %sub_locals:
- lua> "table.insert(\%locals, \%local);"
- lua> "utils.deduplicate(\%locals);"
- return {..}
- locals: %locals
- statements: ".."
- do
- local fell_through = false;
- local ok, ret1 = pcall(function()
- \(%action.statements or "\(%action.expr);")
- fell_through = true;
- end);
- local ok2, ret2 = pcall(function()
- \(%final_action.statements or "\(%final_action.expr);")
- end);
- if not ok then error(ret1); end
- if not ok2 then error(ret2); end
- if not fell_through then
- return ret1;
- end
+ Lua ".."
+ do
+ local fell_through = false;
+ local ok, ret1 = pcall(function()
+ \(%action as lua statements)
+ fell_through = true;
+ end);
+ local ok2, ret2 = pcall(function()
+ \(%final_action as lua statements)
+ end);
+ if not ok then error(ret1); end
+ if not ok2 then error(ret2); end
+ if not fell_through then
+ return ret1;
end
+ end
diff --git a/core/math.nom b/core/math.nom
index 31be658..0df8f16 100644
--- a/core/math.nom
+++ b/core/math.nom
@@ -7,77 +7,77 @@ use "core/operators.nom"
use "core/control_flow.nom"
# Literals:
-compile [infinity, inf] to {expr:"math.huge"}
-compile [not a number, NaN, nan] to {expr:"(0/0)"}
-compile [pi, Pi, PI] to {expr:"math.pi"}
-compile [tau, Tau, TAU] to {expr:"(2*math.pi)"}
-compile [golden ratio] to {expr:"((1+math.sqrt(5))/2)"}
-compile [e] to {expr:"math.exp(1)"}
+compile [infinity, inf] to: Lua value "math.huge"
+compile [not a number, NaN, nan] to: Lua value "(0/0)"
+compile [pi, Pi, PI] to: Lua value "math.pi"
+compile [tau, Tau, TAU] to: Lua value "(2*math.pi)"
+compile [golden ratio] to: Lua value "((1+math.sqrt(5))/2)"
+compile [e] to: Lua value "math.exp(1)"
# Functions:
-compile [% as a number] to {expr:"tonumber(\(% as lua expr))"}
-compile [absolute value %, | % |, abs %] to {expr:"math.abs(\(% as lua expr))"}
-compile [square root %, square root of %, √%, sqrt %] to {expr:"math.sqrt(\(% as lua expr))"}
-compile [sine %, sin %] to {expr:"math.sin(\(% as lua expr))"}
-compile [cosine %, cos %] to {expr:"math.cos(\(% as lua expr))"}
-compile [tangent %, tan %] to {expr:"math.tan(\(% as lua expr))"}
-compile [arc sine %, asin %] to {expr:"math.asin(\(% as lua expr))"}
-compile [arc cosine %, acos %] to {expr:"math.acos(\(% as lua expr))"}
-compile [arc tangent %, atan %] to {expr:"math.atan(\(% as lua expr))"}
-compile [arc tangent %y/%x, atan2 %y %x] to {expr:"math.atan2(\(%y as lua expr), \(%x as lua expr))"}
-compile [hyperbolic sine %, sinh %] to {expr:"math.sinh(\(% as lua expr))"}
-compile [hyperbolic cosine %, cosh %] to {expr:"math.cosh(\(% as lua expr))"}
-compile [hyperbolic tangent %, tanh %] to {expr:"math.tanh(\(% as lua expr))"}
-compile [e^%, exp %] to {expr:"math.exp(\(% as lua expr))"}
-compile [natural log %, ln %, log %] to {expr:"math.log(\(% as lua expr))"}
-compile [log % base %base, log_%base %, log base %base %] to {expr:"math.log(\(% as lua expr), \(%base as lua expr))"}
-compile [floor %] to {expr:"math.floor(\(% as lua expr))"}
-compile [ceiling %, ceil %] to {expr:"math.ceil(\(% as lua expr))"}
-compile [round %, % rounded] to {expr:"math.floor(\(% as lua expr) + .5)"}
+compile [% as a number] to: Lua value "tonumber(\(% as lua expr))"
+compile [absolute value %, | % |, abs %] to: Lua value "math.abs(\(% as lua expr))"
+compile [square root %, square root of %, √%, sqrt %] to: Lua value "math.sqrt(\(% as lua expr))"
+compile [sine %, sin %] to: Lua value "math.sin(\(% as lua expr))"
+compile [cosine %, cos %] to: Lua value "math.cos(\(% as lua expr))"
+compile [tangent %, tan %] to: Lua value "math.tan(\(% as lua expr))"
+compile [arc sine %, asin %] to: Lua value "math.asin(\(% as lua expr))"
+compile [arc cosine %, acos %] to: Lua value "math.acos(\(% as lua expr))"
+compile [arc tangent %, atan %] to: Lua value "math.atan(\(% as lua expr))"
+compile [arc tangent %y/%x, atan2 %y %x] to: Lua value "math.atan2(\(%y as lua expr), \(%x as lua expr))"
+compile [hyperbolic sine %, sinh %] to: Lua value "math.sinh(\(% as lua expr))"
+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 [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)"
action [%n to the nearest %rounder]:
=lua "(\%rounder)*math.floor((\%n / \%rounder) + .5)"
# Any/all/none
compile [all of %items, all %items] to:
unless: (%items' "type") is "List"
- return {expr:"utils.all(\(%items as lua expr))"}
+ return: Lua value "utils.all(\(%items as lua expr))"
%clauses <- []
for all (%items' "value"): lua> "table.insert(\%clauses, \(% as lua expr));"
- return {expr:"(\(%clauses joined with " and "))"}
+ 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"
- return {expr:"utils.any(\(%items as lua expr))"}
+ return: Lua value "utils.any(\(%items as lua expr))"
%clauses <- []
for all (%items' "value"): lua> "table.insert(\%clauses, \(% as lua expr));"
- return {expr:"(\(%clauses joined with " or "))"}
+ 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"
- return {expr:"utils.sum(\(%items as lua expr))"}
+ return: Lua value "utils.sum(\(%items as lua expr))"
%clauses <- []
for all (%items' "value"): lua> "table.insert(\%clauses, \(% as lua expr));"
- return {expr:"(\(%clauses joined with " + "))"}
+ return: Lua value "(\(%clauses joined with " + "))"
compile [product of %items, product %items] to:
unless: (%items' "type") is "List"
- return {expr:"utils.product(\(%items as lua expr))"}
+ return: Lua value "utils.product(\(%items as lua expr))"
%clauses <- []
for all (%items' "value"): lua> "table.insert(\%clauses, \(% as lua expr));"
- return {expr:"(\(%clauses joined with " * "))"}
+ return: Lua value "(\(%clauses joined with " * "))"
action [avg of %items, average of %items]:
=lua "(utils.sum(\%items)/#\%items)"
-compile [min of %items, smallest of %items, lowest of %items] to {..}
- expr:"utils.min(\(%items as lua expr))"
-compile [max of %items, biggest of %items, largest of %items, highest of %items] to {..}
- expr:"utils.max(\(%items as lua expr))"
-compile [min of %items by %value_expr] to {..}
- expr: ".."
- utils.min(\(%items as lua expr), function(\(\% as lua expr))
+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 {..}
- expr: ".."
- utils.max(\(%items as lua expr), function(\(\% as lua expr))
+compile [max of %items by %value_expr] to
+ Lua value ".."
+ utils.max(\(%items as lua expr), function(_)
return \(%value_expr as lua expr)
end)
@@ -87,8 +87,8 @@ action [seed random with %]:
math.randomseed(\%);
for i=1,20 do math.random(); end
parse [seed random] as: seed random with (=lua "os.time()")
-compile [random number, random, rand] to {expr:"math.random()"}
-compile [random int %n, random integer %n, randint %n] to {expr:"math.random(\(%n as lua expr))"}
+compile [random number, random, rand] to: Lua value "math.random()"
+compile [random int %n, random integer %n, randint %n] to: Lua value "math.random(\(%n as lua expr))"
compile [random from %low to %high, random number from %low to %high, rand %low %high] to
"math.random(\(%low as lua expr), \(%high as lua expr))"
action [random choice from %elements, random choice %elements, random %elements]:
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 7ea437e..a446f42 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -25,7 +25,8 @@ immediately:
end
local body_lua = \%lua:as_lua(nomsu);
body_lua:convert_to_statements("return ");
- body_lua:declare_locals(args);
+ body_lua:remove_free_vars(args);
+ body_lua:declare_locals();
lua:append(")\\n ", body_lua, "\\nend);");
return lua;
end);
@@ -50,7 +51,8 @@ immediately:
end
local body_lua = \%body:as_lua(nomsu);
body_lua:convert_to_statements("return ");
- body_lua:declare_locals(args);
+ body_lua:remove_free_vars(args);
+ body_lua:declare_locals();
lua:append(")\\n ", body_lua, "\\nend);")
return lua;
@@ -72,14 +74,7 @@ immediately:
lua:append(", ");
lua:append(arg);
end
- local template;
- if \%longhand.type == "Block" then
- local lines = {};
- for i, line in ipairs(\%longhand.value) do lines[i] = tostring(line.source:get_text()); end
- template = repr(table.concat(lines, "\\n"));
- else
- template = repr(tostring(\%longhand.source:get_text()));
- end
+ local template = repr(tostring(\%longhand:as_nomsu()));
local replacements = {};
for i, a in ipairs(args) do replacements[i] = a.."="..a; end
replacements = "{"..table.concat(replacements, ", ").."}";
@@ -117,22 +112,34 @@ immediately:
lua> ".."
local lua = \%tree:as_lua(nomsu);
lua:convert_to_statements();
- --lua:declare_locals();
return lua;
+
+ compile [declare locals in %tree] to
+ Lua "\(%tree as lua expr):declare_locals();"
+
+ compile [declare locals %locals in %tree] to
+ Lua "\(%tree as lua expr):declare_locals(\(%locals as lua expr));"
+
+ compile [remove free vars %vars from %tree] to:
+ Lua "\(%tree as lua expr):remove_free_vars(unpack(\(%vars as lua expr)));"
action [%tree as value]:
=lua "nomsu:tree_to_value(\%tree)"
+
action [%tree's stub]:
=lua "nomsu:tree_to_stub(\%tree)"
immediately:
parse [%var <-write %code] as: lua> "\%var:append(\%code);"
+ parse [to %var write %code] as: lua> "\%var:append(\%code);"
immediately:
- compile [%tree's source code, %tree' source code] to: Lua value "\(%tree as lua expr).source:get_text()"
+ action [%tree's source code, %tree' source code]:
+ =lua "\%tree.source:get_text()"
compile [repr %obj] to: Lua value "repr(\(%obj as lua expr))"
+ compile [%obj as text] to: Lua value "tostring(\(%obj as lua expr))"
compile [type of %obj] to: Lua value "type(\(%obj as lua expr))"
immediately:
@@ -190,10 +197,10 @@ immediately:
# Error functions
immediately:
- compile [barf] to: Lua value "error(nil, 0);"
- compile [barf %msg] to: Lua value "error(\(%msg as lua expr), 0);"
+ compile [barf] to: Lua "error(nil, 0);"
+ compile [barf %msg] to: Lua "error(\(%msg as lua expr), 0);"
compile [assume %condition] to:
- lua> "local \%assumption = 'Assumption failed: '..\%condition.source:get_text();"
+ lua> "local \%assumption = 'Assumption failed: '..tostring(\%condition.source:get_text());"
return:
Lua ".."
if not \(%condition as lua expr) then
diff --git a/core/operators.nom b/core/operators.nom
index 63819da..1ea1df2 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -54,7 +54,6 @@ immediately:
lua> ".."
local lua = Lua(tree.source, \%var_lua, ' = ', \%value_lua, ';');
if \%var.type == 'Var' then
- print("Added var from assignment: "..tostring(\%var:as_lua(nomsu)));
lua:add_free_vars(\%var);
end
return lua;
@@ -93,15 +92,43 @@ immediately:
return: Lua "\(%var_lua) = \(%value_lua);"
compile [exporting %exported %body] to:
- %body_lua <- (%body as lua)
- lua> "\%body_lua:declare_locals(\%exported);"
+ %body_lua <- (%body as lua statements)
+ lua> "\%body_lua:remove_free_vars(unpack(\(%exported.value)));"
return %body_lua
- parse [with %assignments %body] as:
- # TODO: clean up and handle: with {%x:1}: %y <- 2
- lua> "do"
- <- %assignments
- lua> "end"
+ compile [with %assignments %body] to:
+ %lua <- (%body as lua statements)
+ lua> ".."
+ local lhs, rhs = Lua(tree.source), Lua(\%assignments.source);
+ local vars = {};
+ for i, item in ipairs(\%assignments.value) do
+ local target, value = item.key, item.value;
+ if not target.type == "Var" then
+ error("Invalid target for 'with' assignment: "..tostring(target.source:get_text()));
+ end
+ local target_lua = nomsu:tree_to_lua(target);
+ local value_lua = nomsu:tree_to_lua(value);
+ if not value_lua.is_value then
+ error("Invalid value for assignment: "..tostring(value.source:get_text()));
+ end
+ if target.type == "Var" then
+ lhs:add_free_vars(target);
+ end
+ if i > 1 then
+ lhs:append(", ");
+ rhs:append(", ");
+ end
+ lhs:append(target_lua);
+ rhs:append(value_lua);
+ vars[i] = tostring(target_lua);
+ end
+ \%lua:remove_free_vars(vars);
+ \%lua:prepend("local ", lhs, " = ", rhs, ";\\n");
+ return
+ Lua ".."
+ do
+ \%lua
+ end -- 'with' block
immediately:
# Math Operators
@@ -141,6 +168,7 @@ immediately:
# Unary operators
compile [- %] to: Lua value "(- \(% as lua expr))"
compile [not %] to: Lua value "(not \(% as lua expr))"
+ compile [length of %list] to: Lua value "(#\(%list as lua expr))"
# Update operators
immediately:
diff --git a/core/text.nom b/core/text.nom
index 8213988..d877de7 100644
--- a/core/text.nom
+++ b/core/text.nom
@@ -12,16 +12,16 @@ action [%texts joined with %glue]:
return table.concat(text_bits, \%glue)
parse [joined %texts, %texts joined] as: %texts joined with ""
-compile [capitalized %text, %text capitalized] to {..}
- expr:"((\(%text as lua expr)):gsub('%l', string.upper, 1))"
+compile [capitalized %text, %text capitalized] to
+ Lua value "((\(%text as lua expr)):gsub('%l', string.upper, 1))"
-compile [%text with %sub instead of %patt, %text s/%patt/%sub] to {..}
- expr:"((\(%text as lua expr)):gsub(\(%patt as lua expr), \(%sub as lua expr)))"
+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)))"
# TODO: figure out whether indent/dedent should affect first line
-compile [indented %text, %text indented] to {expr:"((\%text):gsub('\\n','\\n'..(' ')))"}
-compile [dedented %obj, %obj dedented] to {expr:"nomsu:dedent(\(%obj as lua expr))"}
-compile [%text indented %n times] to {expr:"((\%text):gsub('\\n','\\n'..(' '):rep(\%n)))"}
+compile [indented %text, %text indented] to: Lua value "((\%text):gsub('\\n','\\n'..(' ')))"
+compile [dedented %obj, %obj dedented] to: Lua value "nomsu:dedent(\(%obj as lua expr))"
+compile [%text indented %n times] to: Lua value "((\%text):gsub('\\n','\\n'..(' '):rep(\%n)))"
# Text literals
lua> ".."
@@ -32,7 +32,7 @@ lua> ".."
};
for name, e in pairs(escapes) do
local lua = "'"..e.."'";
- nomsu:define_compile_action(name, \(!! code location !!), function() return {expr=lua}; end);
+ nomsu:define_compile_action(name, \(!! code location !!), 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",
@@ -47,9 +47,9 @@ lua> ".."
for name, c in pairs(colors) do
local color = "'"..c.."'";
local reset = "'"..colors["reset color"].."'";
- nomsu:define_compile_action(name, \(!! code location !!), function() return {expr=color}; end);
+ nomsu:define_compile_action(name, \(!! code location !!), function(tree) return Lua.Value(tree.source, color); end);
nomsu:define_compile_action(name.." %", \(!! code location !!), function(\%)
- return {expr=color..".."..nomsu:tree_to_lua(\%).expr..".."..reset};
+ return Lua.Value(tree.source, color, "..", nomsu:tree_to_lua(\%), "..", reset);
end);
end
end
diff --git a/lib/object2.nom b/lib/object2.nom
index e7770bc..762ab4d 100644
--- a/lib/object2.nom
+++ b/lib/object2.nom
@@ -1,6 +1,6 @@
use "core"
-compile [@] to {expr:"self"}
+compile [@] to: Lua value "self"
compile [@%var] to:
lua> ".."
@@ -8,11 +8,11 @@ compile [@%var] to:
local key_attr = (key_lua:match("'([a-zA-Z][a-zA-Z0-9]*)'")
or key_lua:match('"([a-zA-Z][a-zA-Z0-9]*)"'));
if key_attr then
- return {expr="self."..key_attr};
+ return Lua.value(tree.source, "self."..key_attr);
elseif key_lua:sub(1,1) == "[" then
- key_lua = " "..key_lua.." ";
+ key_lua = " "..key_lua;
end
- return {expr="self["..key_lua.."]"};
+ return Lua.Value(tree.source, "self["..key_lua.."]");
compile [@%var <- %val] to:
lua> ".."
@@ -21,16 +21,17 @@ compile [@%var <- %val] to:
local key_attr = (key_lua:match("'([a-zA-Z][a-zA-Z0-9]*)'")
or key_lua:match('"([a-zA-Z][a-zA-Z0-9]*)"'));
if key_attr then
- return {statements="self."..key_attr.." = "..val_lua..";"};
+ return Lua(tree.source, "self.", key_attr, " = ", val_lua, ";");
elseif key_lua:sub(1,1) == "[" then
key_lua = " "..key_lua.." ";
end
- return {statements="self["..key_lua.."] = "..val_lua..";"};
+ return Lua(tree.source, "self[", key_lua, "] = ", val_lua, ";");
compile [as %instance %body] to:
%body_lua <- (%body as lua)
- return {..}
- statements: ".."
+ lua> "\%body_lua:convert_to_statements();"
+ return
+ Lua ".."
do
local self = \(%instance as lua expr);
local global_actions = ACTIONS;
@@ -39,9 +40,8 @@ compile [as %instance %body] to:
if method then return (function(...) return method(self, ...); end); end
return global_actions[key];
end});
- \((%body_lua's "statements") or "\(%body_lua's "expr");")
+ \%body_lua
end
- locals: %body_lua's "locals"
compile [define object %classname %class_body] to:
%class_identifier <- (=lua "nomsu:var_to_lua_identifier(\(%classname as value)):sub(2,-1)")
@@ -56,7 +56,7 @@ compile [define object %classname %class_body] to:
if: ((%line's "type") is "FunctionCall") and ((%line's stub) is "slots %")
%slot_index_clauses <- []
%slot_newindex_clauses <- []
- %slots <- ("value" in (2nd in (%line's "value")))
+ %slots <- %line.value.2.value
for %slot_index = %slot_var in %slots:
to %slot_index_clauses add ".."
if key == \(repr (%slot_var's "value")) or key == \(repr (%slot_var as lua expr)) then
@@ -78,10 +78,10 @@ compile [define object %classname %class_body] to:
error("Attempt to store data in "..repr(key)..", which is not a valid slot on "..tostring(self.class));
end
do next %line
- assume (((%line's "type") is "FunctionCall") and ((%line's stub) is "action % %"))
+ assume ((%line.type is "FunctionCall") and ((%line's stub) is "action % %"))
..or barf "Only action definitions are supported inside 'define object % %', not \(%line's "src")"
- %actions <- (2nd in (%line's "value"))
- %body <- (3rd in (%line's "value"))
+ %actions <- %line.value.2
+ %body <- %line.value.3
lua> ".."
local stubs = {};
for i, action in ipairs(\%actions.value) do
@@ -94,23 +94,14 @@ compile [define object %classname %class_body] to:
local arg_set = {};
for i, arg in ipairs(args) do arg_set[arg] = true; end
local body_lua = nomsu:tree_to_lua(\%body);
- local body_code = body_lua.statements or ("return "..body_lua.expr..";");
- local undeclared_locals = {};
- for i, body_local in ipairs(body_lua.locals or {}) do
- if not arg_set[body_local] then
- table.insert(undeclared_locals, body_local);
- end
- end
- if #undeclared_locals > 0 then
- body_code = "local "..table.concat(undeclared_locals, ", ")..";\\n"..body_code;
- end
+ body_lua:convert_to_statements();
+ body_lua:declare_locals();
local lua_fn_args = table.concat({"self", unpack(args)}, ", ");
local def_tree = nomsu.compilestack[#nomsu.compilestack];
- local code_location = ("%s:%s,%s"):format(def_tree.filename, def_tree.start, def_tree.stop);
local compiled_args = {};
for i, arg in ipairs(args) do
- compiled_args[i] = "nomsu:tree_to_lua("..arg..").expr";
+ compiled_args[i] = "nomsu:tree_to_lua("..arg..")";
end
compiled_args = table.concat(compiled_args, "..', '..");
table.insert(\%methods, ([==[
@@ -119,10 +110,10 @@ compile [define object %classname %class_body] to:
end
]==]):format(
\%class_identifier, repr(stubs[1]), lua_fn_args,
- body_code));
+ body_lua));
- return {..}
- statements:".."
+ return
+ Lua ".."
do -- \%class_identifier
-- Create the class object:
local \%class_identifier = setmetatable({
diff --git a/lua_obj.lua b/lua_obj.lua
index 68c1cc7..c4bbb32 100644
--- a/lua_obj.lua
+++ b/lua_obj.lua
@@ -49,19 +49,13 @@ Source = immutable({
return Source(self.filename, self.start + offset, self.stop)
end,
sub = function(self, start, stop)
+ start = start or 1
+ assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported")
if not self.stop then
assert(not stop, "cannot subscript non-range with range")
- assert(start > 0, "cannot subscript non-range with negative index")
- return Source(self.filename, self.start + (start or 0))
+ return Source(self.filename, self.start + start - 1)
else
- start = start or 1
- if start < 0 then
- start = self.stop + start + 1
- end
- stop = stop or -1
- if stop < 0 then
- stop = self.stop + stop + 1
- end
+ stop = stop or self.stop
return Source(self.filename, self.start + start - 1, self.start + stop - 1)
end
end,
@@ -126,7 +120,7 @@ do
sub = function(self, start, stop)
local str = tostring(self):sub(start, stop)
local cls = self.__class
- return cls(self.source:sub(start - self.source.start + 1, stop - self.source.start + 1), str)
+ return cls(self.source:sub(start, stop), str)
end,
append = function(self, ...)
local n = select("#", ...)
@@ -206,6 +200,34 @@ do
end
end
end,
+ remove_free_vars = function(self, ...)
+ local removals = { }
+ for i = 1, select("#", ...) do
+ local var = select(i, ...)
+ if type(var) == 'userdata' and var.type == "Var" then
+ var = tostring(var:as_lua())
+ elseif type(var) ~= 'string' then
+ var = tostring(var)
+ end
+ removals[var] = true
+ end
+ local remove_from
+ remove_from = function(self)
+ for i = #self.free_vars, 1, -1 do
+ if removals[self.free_vars[i]] then
+ remove(self.free_vars, i)
+ end
+ end
+ local _list_0 = self.bits
+ for _index_0 = 1, #_list_0 do
+ local b = _list_0[_index_0]
+ if type(b) ~= 'string' then
+ remove_from(b)
+ end
+ end
+ end
+ return remove_from(self)
+ end,
convert_to_statements = function(self, prefix, suffix)
if prefix == nil then
prefix = ""
@@ -223,57 +245,37 @@ do
return self:append(suffix)
end
end,
- declare_locals = function(self, skip)
- if skip == nil then
- skip = { }
+ declare_locals = function(self, to_declare)
+ if to_declare == nil then
+ to_declare = nil
end
- if next(skip) == 1 then
- do
- local _tbl_0 = { }
- for _index_0 = 1, #skip do
- local s = skip[_index_0]
- local _key_0, _val_0 = {
- [s] = true
- }
- _tbl_0[_key_0] = _val_0
+ if to_declare == nil then
+ local seen
+ to_declare, seen = { }, { }
+ local gather_from
+ gather_from = function(self)
+ local _list_0 = self.free_vars
+ for _index_0 = 1, #_list_0 do
+ local var = _list_0[_index_0]
+ if not (seen[var]) then
+ seen[var] = true
+ to_declare[#to_declare + 1] = var
+ end
end
- skip = _tbl_0
- end
- end
- local to_declare = { }
- local walk
- walk = function(self)
- local _list_0 = self.free_vars
- for _index_0 = 1, #_list_0 do
- local var = _list_0[_index_0]
- if not (skip[var]) then
- skip[var] = true
- to_declare[#to_declare + 1] = var
+ local _list_1 = self.bits
+ for _index_0 = 1, #_list_1 do
+ local bit = _list_1[_index_0]
+ if bit.__class == Lua then
+ gather_from(bit)
+ end
end
end
- local _list_1 = self.bits
- for _index_0 = 1, #_list_1 do
- local bit = _list_1[_index_0]
- if bit.__class == Lua then
- walk(bit)
- end
- end
- if #self.free_vars > 0 then
- self.free_vars = { }
- end
+ gather_from(self)
end
- walk(self)
+ self:remove_free_vars(to_declare)
if #to_declare > 0 then
- self:prepend("local " .. tostring(concat(to_declare, ", ")) .. ";\n")
+ return self:prepend("local " .. tostring(concat(to_declare, ", ")) .. ";\n")
end
- return [[ if #@free_vars > 0
- @prepend "local #{concat @free_vars, ", "};\n"
- for var in *@free_vars do skip[var] = true
- @free_vars = {}
- for bit in *@bits
- if bit.__class == Lua
- bit\declare_locals(skip)
- ]]
end,
__tostring = function(self)
local buff = { }
diff --git a/lua_obj.moon b/lua_obj.moon
index 4a06414..46d5639 100644
--- a/lua_obj.moon
+++ b/lua_obj.moon
@@ -29,15 +29,13 @@ Source = immutable {"filename","start","stop"}, {
else assert(type(offset) == 'number', "Cannot add Source and #{type(offset)}")
return Source(@filename, @start+offset, @stop)
sub: (start, stop)=>
+ start or= 1
+ assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported")
if not @stop
assert(not stop, "cannot subscript non-range with range")
- assert(start > 0, "cannot subscript non-range with negative index")
- return Source(@filename, @start + (start or 0))
+ return Source(@filename, @start + start - 1)
else
- start or= 1
- if start < 0 then start = @stop + start + 1
- stop or= -1
- if stop < 0 then stop = @stop + stop + 1
+ stop or= @stop
return Source(@filename, @start + start - 1, @start + stop - 1)
get_text: =>
FILE_CACHE[@filename]\sub(@start,@stop)
@@ -94,7 +92,7 @@ class Code
sub: (start,stop)=>
str = tostring(self)\sub(start,stop)
cls = @__class
- return cls(@source\sub(start-@source.start+1,stop-@source.start+1), str)
+ return cls(@source\sub(start,stop), str)
append: (...)=>
n = select("#",...)
@@ -132,6 +130,24 @@ class Lua extends Code
unless seen[var]
@free_vars[#@free_vars+1] = var
seen[var] = true
+
+ remove_free_vars: (...)=>
+ removals = {}
+ for i=1,select("#",...)
+ var = select(i, ...)
+ if type(var) == 'userdata' and var.type == "Var"
+ var = tostring(var\as_lua!)
+ elseif type(var) != 'string'
+ var = tostring(var)
+ removals[var] = true
+ remove_from = =>
+ for i=#@free_vars,1,-1
+ if removals[@free_vars[i]]
+ remove @free_vars, i
+ for b in *@bits
+ if type(b) != 'string'
+ remove_from b
+ remove_from self
convert_to_statements: (prefix="", suffix=";")=>
unless @is_value
@@ -141,32 +157,21 @@ class Lua extends Code
if suffix != ""
@append suffix
- declare_locals: (skip={})=>
- if next(skip) == 1
- skip = {[s]:true for s in *skip}
- to_declare = {}
- walk = =>
- for var in *@free_vars
- unless skip[var]
- skip[var] = true
- to_declare[#to_declare+1] = var
- for bit in *@bits
- if bit.__class == Lua
- walk bit
- if #@free_vars > 0
- @free_vars = {}
- walk self
+ declare_locals: (to_declare=nil)=>
+ if to_declare == nil
+ to_declare, seen = {}, {}
+ gather_from = =>
+ for var in *@free_vars
+ unless seen[var]
+ seen[var] = true
+ to_declare[#to_declare+1] = var
+ for bit in *@bits
+ if bit.__class == Lua
+ gather_from bit
+ gather_from self
+ @remove_free_vars to_declare
if #to_declare > 0
@prepend "local #{concat to_declare, ", "};\n"
- [[
- if #@free_vars > 0
- @prepend "local #{concat @free_vars, ", "};\n"
- for var in *@free_vars do skip[var] = true
- @free_vars = {}
- for bit in *@bits
- if bit.__class == Lua
- bit\declare_locals(skip)
- ]]
__tostring: =>
buff = {}
diff --git a/nomsu.lua b/nomsu.lua
index 9b273d1..b76a929 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -17,7 +17,7 @@ local colors = setmetatable({ }, {
return ""
end
})
-local colored = setmetatable({ }, {
+colored = setmetatable({ }, {
__index = function(_, color)
return (function(msg)
return colors[color] .. tostring(msg or '') .. colors.reset
@@ -170,6 +170,7 @@ do
local line_no = 1
local text_loc = lpeg.userdata.source_code.source:sub(pos, pos)
line_no = text_loc:get_line_number()
+ src = FILE_CACHE[text_loc.filename]
local prev_line = src:sub(LINE_STARTS[src][line_no - 1] or 1, LINE_STARTS[src][line_no] - 1)
local err_line = src:sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no + 1] or 0) - 1)
local next_line = src:sub(LINE_STARTS[src][line_no + 1] or -1, (LINE_STARTS[src][line_no + 2] or 0) - 1)
@@ -187,7 +188,7 @@ setmetatable(NOMSU_DEFS, {
if type(value) == 'table' then
error("Not a tuple: " .. tostring(repr(value)))
end
- local source = lpeg.userdata.source_code.source:sub(start, stop)
+ local source = lpeg.userdata.source_code.source:sub(start, stop - 1)
local node = Types[key](value, source)
return node
end
diff --git a/nomsu.moon b/nomsu.moon
index 9471e31..680621f 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -22,6 +22,7 @@ export Tuple
Tuple = immutable(nil, {name:"Tuple"})
{:repr, :stringify, :min, :max, :equivalent, :set, :is_list, :sum} = utils
colors = setmetatable({}, {__index:->""})
+export colored
colored = setmetatable({}, {__index:(_,color)-> ((msg)-> colors[color]..tostring(msg or '')..colors.reset)})
{:insert, :remove, :concat} = table
debug_getinfo = debug.getinfo
@@ -154,11 +155,13 @@ NOMSU_DEFS = with {}
return start + #nodent
.error = (src,pos,err_msg)->
+ --src = tostring(FILE_CACHE[lpeg.userdata.source_code.source.filename])
if src\sub(pos,pos)\match("[\r\n]")
pos += #src\match("[ \t\n\r]*", pos)
line_no = 1
text_loc = lpeg.userdata.source_code.source\sub(pos,pos)
line_no = text_loc\get_line_number!
+ src = FILE_CACHE[text_loc.filename]
prev_line = src\sub(LINE_STARTS[src][line_no-1] or 1, LINE_STARTS[src][line_no]-1)
err_line = src\sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no+1] or 0)-1)
next_line = src\sub(LINE_STARTS[src][line_no+1] or -1, (LINE_STARTS[src][line_no+2] or 0)-1)
@@ -170,7 +173,7 @@ NOMSU_DEFS = with {}
setmetatable(NOMSU_DEFS, {__index:(key)=>
make_node = (start, value, stop)->
if type(value) == 'table' then error("Not a tuple: #{repr value}")-- = Tuple(value)
- source = lpeg.userdata.source_code.source\sub(start,stop)
+ source = lpeg.userdata.source_code.source\sub(start,stop-1)
node = Types[key](value, source)
return node
self[key] = make_node
diff --git a/nomsu_tree.moon b/nomsu_tree.moon
index 23ad830..1c41906 100644
--- a/nomsu_tree.moon
+++ b/nomsu_tree.moon
@@ -27,6 +27,15 @@ Tree = (name, methods)->
.with_value = (value)=> getmetatable(self)(value, @source)
.type = name
.name = name
+ .as_nomsu = =>
+ leading_space = 0
+ src_file = FILE_CACHE[@source.filename]
+ while src_file\sub(@source.start-leading_space-1, @source.start-leading_space-1) == " "
+ leading_space += 1
+ if src_file\sub(@source.start-leading_space-1, @source.start-leading_space-1) != "\n"
+ leading_space = 0
+ ret = tostring(@source\get_text!)\gsub("\n"..((" ")\rep(leading_space)), "\n")
+ return ret
Types[name] = immutable {"value","source"}, methods
@@ -49,7 +58,7 @@ Tree "File",
Tree "Nomsu",
as_lua: (nomsu)=>
- Lua.Value(@source, "nomsu:parse(Nomsu(",repr(@source),", ",repr(@source\get_text!),"))")
+ Lua.Value(@source, "nomsu:parse(Nomsu(",repr(@value.source),", ",repr(tostring(@value.source\get_text!)),")).value[1]")
Tree "Block",
as_lua: (nomsu)=>
diff --git a/tests/collections.nom b/tests/collections.nom
index 855baea..60b2d25 100644
--- a/tests/collections.nom
+++ b/tests/collections.nom
@@ -11,7 +11,7 @@ assume (99 isn't in [1,2,3])
assume ({x:no} has key "x")
assume ({x:no} doesn't have key "y")
assume (not ({x:no} doesn't have key "x"))
-assume ((size of [1,2,3]) = 3)
+assume ((length of [1,2,3]) = 3)
%list <- [1,2,3,4,5]
append 6 to %list
assume ((last in %list) = 6)
diff --git a/tests/metaprogramming.nom b/tests/metaprogramming.nom
index 360771e..c6aa719 100644
--- a/tests/metaprogramming.nom
+++ b/tests/metaprogramming.nom
@@ -4,11 +4,11 @@
use "core"
immediately
- compile [five] to {expr:"5"}
+ compile [five] to: Lua value "5"
assume ((five) = 5) or barf "Compile to expression failed."
immediately
- compile [loc x] to {statements:"_x = 99", locals:["_x"]}
+ compile [loc x] to: Lua "local _x = 99;"
lua> "do"
loc x
assume (%x is 99) or barf "Compile to statements with locals failed."
@@ -18,7 +18,7 @@ assume (%x is (nil)) or barf "Failed to properly localize a variable."
immediately
compile [asdf] to
%tmp <- ""
- return {statements:%tmp}
+ return: Lua %tmp
asdf
assume (%tmp is (nil)) or barf "compile to is leaking variables"
@@ -42,7 +42,7 @@ try: foo 99
assume ((\(5 + 5) as value) = 10) or barf "%tree as value failed."
-assume ((\(foo %x)'s source code) = "foo %x") or barf "source code failed."
+assume (((\(foo %x)'s source code) as text) = "foo %x") or barf "source code failed."
assume ((repr [1,2]) = "{1, 2}") or barf "repr failed."
diff --git a/tests/object.nom b/tests/object.nom
index 84524e5..ab87fc7 100644
--- a/tests/object.nom
+++ b/tests/object.nom
@@ -1,23 +1,24 @@
use "core"
use "lib/object2.nom"
-immediately:
- define object "Dog":
- action [bark]:
- %barks <- ("Bark!" for all 1 to (@%barks))
- return (%barks joined with " ")
- action [get pissed off]:
- (@%barks) +<- 1
+#..
+ immediately:
+ define object "Dog":
+ action [bark]:
+ %barks <- ("Bark!" for all 1 to (@%barks))
+ return (%barks joined with " ")
+ action [get pissed off]:
+ (@%barks) +<- 1
-%d <- (new Dog {barks:2})
-as %d:
- assume ((@) = %d)
- assume ((@%barks) = 2)
- assume ((bark) = "Bark! Bark!")
- get pissed off
- assume ((@%barks) = 3)
- assume ((bark) = "Bark! Bark! Bark!")
-assume ("\(%d's "class")" = "Dog")
-assume ((%d's "barks") = 3)
+ %d <- (new Dog {barks:2})
+ as %d:
+ assume ((@) = %d)
+ assume ((@%barks) = 2)
+ assume ((bark) = "Bark! Bark!")
+ get pissed off
+ assume ((@%barks) = 3)
+ assume ((bark) = "Bark! Bark! Bark!")
+ assume ("\(%d's "class")" = "Dog")
+ assume ((%d's "barks") = 3)
-say "Object test passed."
+ say "Object test passed."
diff --git a/tests/operators.nom b/tests/operators.nom
index 1a138cb..40c503f 100644
--- a/tests/operators.nom
+++ b/tests/operators.nom
@@ -17,23 +17,23 @@ assume ((%y = 10) and (%x = 20)) or barf "swapping vars failed."
assume ({} is {}) or barf "Equality check failed."
assume (({}'s id) is not ({}'s id)) or barf "Identity check failed."
-<-{%x:"outer",%y:"outer"}
+<-{%foozle:"outer",%y:"outer"}
action [set global x local y]
- export %x <- "inner"
+ export %foozle <- "inner"
%y <- "inner"
set global x local y
-assume ((%x = "inner") and (%y = "outer")) or barf "export failed."
+assume ((%foozle = "inner") and (%y = "outer")) or barf "export failed."
-<-{%x:"outer",%y:"outer"}
+<-{%foozle:"outer",%y:"outer"}
action [set global x local y]
- exporting [%x]
- %x <- "inner"
+ exporting [%foozle]
+ %foozle <- "inner"
%y <- "inner"
set global x local y
-assume ((%x = "inner") and (%y = "outer")) or barf "export failed."
+assume ((%foozle = "inner") and (%y = "outer")) or barf "exporting failed."
<-{%x:1,%y:2}
-with [%z, %x<-999]
+with {%z:nil, %x:999}
%z <- 999
assume (%z = 999) or barf "'with' failed."
assume (%x = 999) or barf "'with' assignment failed."