aboutsummaryrefslogtreecommitdiff
path: root/core
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 /core
parentdcb380f1f6ec67c52364b1246546f1f6b2c168d3 (diff)
All tests passing (except object)
Diffstat (limited to 'core')
-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
6 files changed, 249 insertions, 240 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