aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-05-24 14:57:24 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-05-24 14:57:35 -0700
commit2e345e271f27147051b8ce1f2981ba728b14394a (patch)
tree5f56bc1886ed887ad87ffb86b7591fcc5bf09368
parentad94ed3653e2b7a9f68855670a32617aa80a637c (diff)
Misc changes, fixed up Object lib and tests.
-rw-r--r--core/control_flow.nom2
-rw-r--r--core/math.nom2
-rw-r--r--examples/how_do_i.nom70
-rw-r--r--lib/object.nom206
-rw-r--r--lib/object2.nom175
-rw-r--r--nomsu.lua6
-rwxr-xr-xnomsu.moon4
-rw-r--r--nomsu.peg4
-rw-r--r--tests/object.nom43
9 files changed, 175 insertions, 337 deletions
diff --git a/core/control_flow.nom b/core/control_flow.nom
index 129f236..9f23e07 100644
--- a/core/control_flow.nom
+++ b/core/control_flow.nom
@@ -288,7 +288,7 @@ immediately
assume (not %seen_else) or barf "'else' clause needs to be last in 'when' block"
lua> "table.insert(\%fallthroughs, \(%condition as lua expr));"
to %code write "\("if" if %is_first else "\nelseif") "
- for %i=%condition in %fallthroughs
+ for %i = %condition in %fallthroughs
if (%i > 1): to %code write " or "
to %code write %condition
to %code write " then\n "
diff --git a/core/math.nom b/core/math.nom
index 120c210..8d484b4 100644
--- a/core/math.nom
+++ b/core/math.nom
@@ -24,7 +24,7 @@ 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 [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))"
diff --git a/examples/how_do_i.nom b/examples/how_do_i.nom
index 3abaf46..13517fc 100644
--- a/examples/how_do_i.nom
+++ b/examples/how_do_i.nom
@@ -21,6 +21,8 @@ say "Hello world!"
%str <- "Hello world"
# Expressions that are more than just literal values require parentheses:
%x <- (2 + 3)
+%one-two <- 12
+say %one-two
# How do I modify a variable?
%x <- (%x + 1)
@@ -28,50 +30,50 @@ say "Hello world!"
%x +<- 1
# How do I define a mutli-line string?
-%mutli_str <- ".."
+%mutli-str <- ".."
Start with "..", then put lines below it
that are indented one level.
The string will continue until the indentation ends.
# How do I put values inside a string?
-%format_str <- ".."
+%format-str <- ".."
Strings can contain a backslash followed by a variable, list, dict, or parenthesized
expression. This escaped value will be converted to a readable string, like so:
The value of %x is \%x, isn't that nice?
These are some numbers: \[1+1,2+1,3+1]
The sum of 2 and 4 is \(2 + 4).
If you need to use a plain ol' backslash, you can do \\ <-- that
-%format_str2 <- "Single-line strings can contain escape sequences like \", \\, \n, \065, and \x0A"
+%format-str2 <- "Single-line strings can contain escape sequences like \", \\, \n, \065, and \x0A"
# How do I define a list?
-%my_list <- [1,2,"hello"]
+%my-list <- [1,2,"hello"]
# Really long lists can use [..] followed by a bunch of indented values delimited
by commas and/or newlines
-%my_really_long_list <- [..]
+%my-really-long-list <- [..]
1,2,3,4
5,6
7
8,9,10
# How do I use a list?
-%my_list <- ["first item", "second item", "third item"]
+%my-list <- ["first item", "second item", "third item"]
# Lists are 1-indexed because they're implemented as Lua tables, so this prints "first item"
-say %my_list.1
+say %my-list.1
# List entries can be modified like this:
-%my_list.1 <- "ONE!!!"
-say (length of %my_list)
+%my-list.1 <- "ONE!!!"
+say (length of %my-list)
# How do I define a dictionary/hash map?
-%my_dict <- {x: 99, y: 101}
-%my_dict <- {..}
+%my-dict <- {x: 99, y: 101}
+%my-dict <- {..}
x: 101, y: 2
"99 bottles": 99
653: 292
# How do I use a dict?
# Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists
-say %my_dict.x
-%my_dict.x <- 9999
+say %my-dict.x
+%my-dict.x <- 9999
# How do I do conditional branching?
if: 1 < 10
@@ -173,11 +175,11 @@ say (first fibonacci above 10)
# Actions can have aliases, which may or may not have the arguments in different order
action [..]
- I hate %worse_things more than %better_things
- I think %worse_things are worse than %better_things
- I like %better_things more than %worse_things
+ I hate %worse-things more than %better-things
+ I think %worse-things are worse than %better-things
+ I like %better-things more than %worse-things
..
- say "\(%better_things capitalized) rule and \%worse_things drool!"
+ say "\(%better-things capitalized) rule and \%worse-things drool!"
I like "dogs" more than "cats"
I think "chihuahuas" are worse than "corgis"
@@ -188,16 +190,16 @@ I think "chihuahuas" are worse than "corgis"
say both "Hello" and also "again!"
# Actions can even start with a parameter
-action [%what_she_said is what she said]
- say %what_she_said
+action [%what-she-said is what she said]
+ say %what-she-said
say "-- she said"
"Howdy pardner" is what she said
# The language only reserves []{}().,:;% as special characters, so actions
can have really funky names!
-action [>> %foo_bar $$$^ --> % @& _~-^-~_~-^ %1 !]
- say %foo_bar
+action [>> %foo-bar $$$^ --> % @& _~-^-~_~-^ %1 !]
+ say %foo-bar
say %
say %1
@@ -283,12 +285,12 @@ if (1 > (TWENTY)) on opposite day
# How do I use an action as a value?
# Well... it's always *possible* to fall back to Lua behavior for something like this:
-action [best of %items according to %key_fn]
- <- {%best:nil, %best_key:nil}
+action [best of %items according to %key-fn]
+ <- {%best:nil, %best-key:nil}
for % in %items
- %key <- (=lua "\%key_fn(\%)")
- if: (%best is (nil)) or (%key > %best_key)
- <- {%best:%, %best_key:%key}
+ %key <- (=lua "\%key-fn(\%)")
+ if: (%best is (nil)) or (%key > %best-key)
+ <- {%best:%, %best-key:%key}
return %best
immediately
@@ -305,13 +307,13 @@ say: best of [2,-3,4,-8] according to (function %: % * %)
could use a macro to generate a single block of code that inlines the expression you
want to use:
immediately
- parse [best of %items according to %key_expr] as
+ parse [best of %items according to %key-expr] as
result of
- <- {%best:nil, %best_key:nil}
+ <- {%best:nil, %best-key:nil}
for % in %items
- %key <- %key_expr
- if: (%best is (nil)) or (%key > %best_key)
- <- {%best:%, %best_key:%key}
+ %key <- %key-expr
+ if: (%best is (nil)) or (%key > %best-key)
+ <- {%best:%, %best-key:%key}
return %best
# This results in generated code that is more efficient (no function calls in the
inner loop)
@@ -322,7 +324,7 @@ say: best of [2,-3,4,-8] according to (% * %)
to get a new list with every entry multiplied by 2, but it's *much* more readable to
do something like:
%nums <- [1,2,3,4,5]
-%double_nums <- ((2 * %num) for %num in %nums)
+%double-nums <- ((2 * %num) for %num in %nums)
# Nomsu comes with built-in list comprehensions, but the flexible macro system makes it
incredibly easy to make similar constructs.
@@ -335,5 +337,5 @@ immediately
%result.(%N - %i + 1) <- %expr
return %result
-%double_nums <- ((2 * %num) for %num in %nums BACKWARDS!)
-say %double_nums
+%double-nums <- ((2 * %num) for %num in %nums BACKWARDS!)
+say %double-nums
diff --git a/lib/object.nom b/lib/object.nom
index 0bb2538..5c73046 100644
--- a/lib/object.nom
+++ b/lib/object.nom
@@ -1,100 +1,91 @@
use "core"
-compile [@%var] to
- lua> ".."
- local key_lua = repr(\%var.value);
- 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="_me."..key_attr};
- elseif key_lua:sub(1,1) == "[" then
- key_lua = " "..key_lua.." ";
- end
- return {expr="_me["..key_lua.."]"};
+compile [@, me] to: Lua value "self"
-compile [@%var <- %val] to
- lua> ".."
- local val_lua = \(%val as lua expr);
- local key_lua = repr(\%var.value);
- 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="_me."..key_attr.." = "..val_lua..";"};
- elseif key_lua:sub(1,1) == "[" then
- key_lua = " "..key_lua.." ";
+compile [as %instance %body] to
+ Lua ".."
+ do
+ local self = \(%instance as lua expr);
+ local global_actions = ACTIONS;
+ local ACTIONS = setmetatable({}, {__index=function(_,key)
+ local method = self[key];
+ if method then return (function(...) return method(self, ...); end); end
+ return global_actions[key];
+ end});
+ \(%body as lua statements)
end
- return {statements="_me["..key_lua.."] = "..val_lua..";"};
-compile [define object %classname %class_body] to
- %class_identifier <- (=lua "nomsu:var_to_lua_identifier(\(%classname as value)):sub(2,-1)")
- if: %class_identifier is ""
- %class_identifier <- "class"
- %methods <- []
- for %line in (%class_body's "value")
- if: (%line's "type") is "Comment"
+compile [object %classname %class_body] to
+ %class_id <- (=lua "Var(\(%classname as value)):as_lua_id():sub(2,-1)")
+ if: %class_id is ""
+ %class_id <- "class"
+ %methods <-: Lua ""
+ %__index <- %class_id
+ %__newindex <- "nil"
+ for %line in %class_body
+ if: %line.type is "Comment"
+ do next %line
+ if: (%line.type is "Action") and ((%line's stub) is "slots %")
+ %slot_index_clauses <- []
+ %slot_newindex_clauses <- []
+ %slots <- %line.2
+ for %slot_index = %slot_var in %slots
+ to %slot_index_clauses add ".."
+ if key == \(repr %slot_var.value) or key == \(repr (%slot_var as lua expr)) then
+ return rawget(self, \%slot_index);
+ end
+ to %slot_newindex_clauses add ".."
+ if key == \(repr %slot_var.value) or key == \(repr (%slot_var as lua expr)) or key == \%slot_index then
+ rawset(self, \%slot_index, value);
+ end
+
+ %__index <- ".."
+ function(self, key)
+ \(%slot_index_clauses joined with "\n")
+ return \%class_id[key];
+ end
+ %__newindex <- ".."
+ function(self, key, value)
+ \(%slot_newindex_clauses joined with "\n")
+ 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") == "FunctionCall") and ((%line's stub) == "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"))
+ assume ((%line.type is "Action") and ((%line's stub) is "action % %"))
+ ..or barf "Only action definitions are supported inside 'object % %'"
+ %actions <- %line.2
+ %body <- %line.3
lua> ".."
- local stubs = {};
- for i, action in ipairs(\%actions.value) do
- stubs[i] = nomsu:tree_to_named_stub(action);
- end
- local args = {};
- for i,tok in ipairs(\%actions.value[1].value) do
- if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
- end
- 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);
+ do
+ local stubs = {}
+ for i, action in ipairs(\%actions) do
+ stubs[i] = action:get_stub(true)
end
- end
- if #undeclared_locals > 0 then
- body_code = "local "..table.concat(undeclared_locals, ", ")..";\\n"..body_code;
- end
- local lua_fn_args = table.concat(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";
- end
- compiled_args = table.concat(compiled_args, "..', '..");
- table.insert(\%methods, ([==[
- %s[ %s] = function(%s)
- %s
+ local lua = Lua(nil, \%class_id, "[ ", repr(stubs[1]), "] = function(self")
+ local args = {}
+ for i,tok in ipairs(\%actions[1]) do
+ if tok.type == "Var" then args[#args+1] = tok end
end
- nomsu:define_compile_action(%s, %s, function(%s)
- return {expr="("..nomsu:tree_to_lua(_me).expr..")[ "..%s.."]("..%s..")"};
- end);
- ACTION_METADATA[%s[ %s]] = ACTION_METADATA[ACTION[ %s]];
- ]==]):format(
- \%class_identifier, repr(stubs[1]), lua_fn_args,
- body_code,
- repr(stubs), repr(code_location), lua_fn_args,
- repr(repr(stubs[1])), compiled_args,
- \%class_identifier, repr(stubs[1]), repr(stubs[1])));
+ for i, arg in ipairs(args) do
+ lua:append(", ", nomsu:tree_to_lua(arg))
+ end
+ local body_lua = nomsu:tree_to_lua(\%body):as_statements("return ")
+ body_lua:remove_free_vars(args)
+ body_lua:declare_locals()
+ lua:append(")\n ", body_lua, "\nend;\n")
+ \%methods:append(lua)
+ end
- return {..}
- statements:".."
- do -- \%class_identifier
+ return
+ Lua ".."
+ do -- \%class_id
-- Create the class object
- local \%class_identifier = setmetatable({
+ local \%class_id = setmetatable({
name=\(%classname as lua expr), instances=setmetatable({}, {__mode="k"}),
}, {
__tostring=function(c) return c.name; end,
- __call=function(cls, inst)
- inst = inst or {};
- inst.id = tostring(inst):match('table: (.*)');
- setmetatable(inst, cls.instance_metatable);
+ __call=function(cls, initial_values)
+ local inst = setmetatable({}, cls.instance_metatable);
+ for k,v in pairs(initial_values) do inst[k] = v; end
cls.instances[inst] = true;
if inst['set % up'] then
inst['set % up'](inst);
@@ -102,27 +93,44 @@ compile [define object %classname %class_body] to
return inst;
end,
});
- \%class_identifier.class = \%class_identifier;
+ \%class_id.class = \%class_id;
-- Define the methods
- \(%methods joined with "\n")
+ \%methods
-- Define class methods for instantiating and accessing instances
- \%class_identifier.instance_metatable = {
- __index=\%class_identifier,
- __tostring=\%class_identifier['% as text'] or function(inst)
- return "<"..inst.class.name..": "..inst.id..">";
+ \%class_id.instance_metatable = {
+ __index=\%__index,
+ __newindex=\%__newindex,
+ __tostring=\%class_id['as text'] or function(inst)
+ return "<"..inst.class.name..": "..nomsu.ids[inst]..">";
end,
+ __len=\%class_id['size of'],
+ __unm=\%class_id['-'],
+ __add=\%class_id['+ %'],
+ __sub=\%class_id['- %'],
+ __mul=\%class_id['* %'],
+ __div=\%class_id['/ %'],
+ __mod=\%class_id['wrapped around %'],
+ __pow=\%class_id['^ %'],
+ __band=\%class_id['AND %'],
+ __bor=\%class_id['OR %'],
+ __bxor=\%class_id['XOR %'],
+ __bshl=\%class_id['<< %'],
+ __bshr=\%class_id['>> %'],
+ __eq=\%class_id['= %'],
+ __lt=\%class_id['< %'],
+ __le=\%class_id['<= %'],
};
- nomsu:define_action("instances of "..\%class_identifier.name, "lib/class.nom", function()
- return utils.keys(\%class_identifier.instances);
- end, "");
- nomsu:define_action("new "..\%class_identifier.name.." %instance", "lib/class.nom", function(_instance)
- return \%class_identifier(_instance);
- end, "");
- nomsu:define_action("new "..\%class_identifier.name, "lib/class.nom", function()
- return \%class_identifier({});
- end, "");
- end -- End of definition of \%class_identifier
+ nomsu:define_action("instances of "..\%class_id.name, function()
+ return utils.keys(\%class_id.instances);
+ end);
+ nomsu:define_action("new "..\%class_id.name.." %instance", function(_instance)
+ return \%class_id(_instance);
+ end);
+ nomsu:define_action("new "..\%class_id.name, function()
+ return \%class_id({});
+ end);
+ end -- End of definition of \%class_id
\("\n\n")
diff --git a/lib/object2.nom b/lib/object2.nom
deleted file mode 100644
index 3916fa2..0000000
--- a/lib/object2.nom
+++ /dev/null
@@ -1,175 +0,0 @@
-use "core"
-
-compile [@] to: Lua value "self"
-
-compile [@%var] to
- lua> ".."
- local key_lua = repr(\%var.value);
- 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 Lua.value(tree.source, "self."..key_attr);
- elseif key_lua:sub(1,1) == "[" then
- key_lua = " "..key_lua;
- end
- return Lua.Value(tree.source, "self["..key_lua.."]");
-
-compile [@%var <- %val] to
- lua> ".."
- local val_lua = \(%val as lua expr);
- local key_lua = repr(\%var.value);
- 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 Lua(tree.source, "self.", key_attr, " = ", val_lua, ";");
- elseif key_lua:sub(1,1) == "[" then
- key_lua = " "..key_lua.." ";
- end
- return Lua(tree.source, "self[", key_lua, "] = ", val_lua, ";");
-
-compile [as %instance %body] to
- %body_lua <- (%body as lua)
- lua> "\%body_lua:convert_to_statements();"
- return
- Lua ".."
- do
- local self = \(%instance as lua expr);
- local global_actions = ACTIONS;
- local ACTIONS = setmetatable({}, {__index=function(_,key)
- local method = self[key];
- if method then return (function(...) return method(self, ...); end); end
- return global_actions[key];
- end});
- \%body_lua
- end
-
-compile [define object %classname %class_body] to
- %class_identifier <- (=lua "nomsu:var_to_lua_identifier(\(%classname as value)):sub(2,-1)")
- if: %class_identifier is ""
- %class_identifier <- "class"
- %methods <- []
- %__index <- %class_identifier
- %__newindex <- "nil"
- for %line in (%class_body's "value")
- if: (%line's "type") is "Comment"
- do next %line
- if: ((%line's "type") is "FunctionCall") and ((%line's stub) is "slots %")
- %slot_index_clauses <- []
- %slot_newindex_clauses <- []
- %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
- return rawget(self, \%slot_index);
- end
- to %slot_newindex_clauses add ".."
- if key == \(repr (%slot_var's "value")) or key == \(repr (%slot_var as lua expr)) or key == \%slot_index then
- rawset(self, \%slot_index, value);
- end
-
- %__index <- ".."
- function(self, key)
- \(%slot_index_clauses joined with "\n")
- return \%class_identifier[key];
- end
- %__newindex <- ".."
- function(self, key, value)
- \(%slot_newindex_clauses joined with "\n")
- error("Attempt to store data in "..repr(key)..", which is not a valid slot on "..tostring(self.class));
- end
- do next %line
- 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 <- %line.value.2
- %body <- %line.value.3
- lua> ".."
- do
- local stubs = {};
- for i, action in ipairs(\%actions.value) do
- stubs[i] = nomsu:tree_to_named_stub(action);
- end
- local args = {};
- for i,tok in ipairs(\%actions.value[1].value) do
- if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
- end
- local arg_set = {};
- for i, arg in ipairs(args) do arg_set[arg] = true; end
- local body_lua = nomsu:tree_to_lua(\%body);
- 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 compiled_args = {};
- for i, arg in ipairs(args) do
- compiled_args[i] = "nomsu:tree_to_lua("..arg..")";
- end
- compiled_args = table.concat(compiled_args, "..', '..");
- table.insert(\%methods, ([==[
- %s[ %s] = function(%s)
- %s
- end
- ]==]):format(
- \%class_identifier, repr(stubs[1]), lua_fn_args,
- body_lua));
- end
-
- return
- Lua ".."
- do -- \%class_identifier
- -- Create the class object
- local \%class_identifier = setmetatable({
- name=\(%classname as lua expr), instances=setmetatable({}, {__mode="k"}),
- }, {
- __tostring=function(c) return c.name; end,
- __call=function(cls, initial_values)
- local inst = setmetatable({}, cls.instance_metatable);
- for k,v in pairs(initial_values) do inst[k] = v; end
- cls.instances[inst] = true;
- if inst['set % up'] then
- inst['set % up'](inst);
- end
- return inst;
- end,
- });
- \%class_identifier.class = \%class_identifier;
-
- -- Define the methods
- \(%methods joined with "\n")
-
- -- Define class methods for instantiating and accessing instances
- \%class_identifier.instance_metatable = {
- __index=\%__index,
- __newindex=\%__newindex,
- __tostring=\%class_identifier['as text'] or function(inst)
- return "<"..inst.class.name..": "..nomsu.ids[inst]..">";
- end,
- __len=\%class_identifier['size of'],
- __unm=\%class_identifier['-'],
- __add=\%class_identifier['+ %'],
- __sub=\%class_identifier['- %'],
- __mul=\%class_identifier['* %'],
- __div=\%class_identifier['/ %'],
- __mod=\%class_identifier['wrapped around %'],
- __pow=\%class_identifier['^ %'],
- __band=\%class_identifier['AND %'],
- __bor=\%class_identifier['OR %'],
- __bxor=\%class_identifier['XOR %'],
- __bshl=\%class_identifier['<< %'],
- __bshr=\%class_identifier['>> %'],
- __eq=\%class_identifier['= %'],
- __lt=\%class_identifier['< %'],
- __le=\%class_identifier['<= %'],
- };
- nomsu:define_action("instances of "..\%class_identifier.name, "lib/class.nom", function(__callsite)
- return utils.keys(\%class_identifier.instances);
- end, "");
- nomsu:define_action("new "..\%class_identifier.name.." %instance", "lib/class.nom", function(__callsite, _instance)
- return \%class_identifier(_instance);
- end, "");
- nomsu:define_action("new "..\%class_identifier.name, "lib/class.nom", function(__callsite)
- return \%class_identifier({});
- end, "");
- end -- End of definition of \%class_identifier
- \("\n\n")
-
diff --git a/nomsu.lua b/nomsu.lua
index 2b0b6dc..cc335ec 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -28,8 +28,8 @@ end
re = require('re')
lpeg = require('lpeg')
lpeg.setmaxstack(10000)
-local P, R, V, S, Cg, C, Cp, B, Cmt
-P, R, V, S, Cg, C, Cp, B, Cmt = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C, lpeg.Cp, lpeg.B, lpeg.Cmt
+local P, R, V, S, Cg, C, Cp, B
+P, R, V, S, Cg, C, Cp, B = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C, lpeg.Cp, lpeg.B
local utils = require('utils')
local new_uuid = require('uuid')
local immutable = require('immutable')
@@ -1303,7 +1303,7 @@ do
stub_defs = {
space = (P(' ') + P('\n..')) ^ 0,
word = (NOMSU_DEFS.ident_char ^ 1 + NOMSU_DEFS.operator),
- varname = (R('az', 'AZ', '09') + P('_') + NOMSU_DEFS.utf8_char) ^ 0
+ varname = (R('az', 'AZ', '09') + P('_') + NOMSU_DEFS.utf8_char + (-P("'") * NOMSU_DEFS.operator)) ^ 0
}
stub_pattern = re.compile([=[ {~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~}
]=], stub_defs)
diff --git a/nomsu.moon b/nomsu.moon
index 196bedf..52c8af0 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -33,7 +33,7 @@ if jit
re = require 're'
lpeg = require 'lpeg'
lpeg.setmaxstack 10000
-{:P,:R,:V,:S,:Cg,:C,:Cp,:B,:Cmt} = lpeg
+{:P,:R,:V,:S,:Cg,:C,:Cp,:B} = lpeg
utils = require 'utils'
new_uuid = require 'uuid'
immutable = require 'immutable'
@@ -285,7 +285,7 @@ class NomsuCompiler
stub_defs = {
space:(P(' ') + P('\n..'))^0
word:(NOMSU_DEFS.ident_char^1 + NOMSU_DEFS.operator)
- varname:(R('az','AZ','09') + P('_') + NOMSU_DEFS.utf8_char)^0
+ varname:(R('az','AZ','09') + P('_') + NOMSU_DEFS.utf8_char + (-P("'") * NOMSU_DEFS.operator))^0
}
stub_pattern = re.compile [=[
{~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~}
diff --git a/nomsu.peg b/nomsu.peg
index 14689fc..afc5580 100644
--- a/nomsu.peg
+++ b/nomsu.peg
@@ -87,7 +87,7 @@ number (Number): (("-"? (([0-9]+ "." [0-9]+) / ("." [0-9]+) / ([0-9]+)))-> tonum
-- Variables can be nameless (i.e. just %) and can't contain operators like apostrophe
-- which is a hack to allow %'s to parse as "%" and "' s" separately
-variable (Var): "%" { plain_word? }
+variable (Var): "%" { ((!"'" %operator) / plain_word)* }
inline_list (List):
!('[..]')
@@ -132,4 +132,4 @@ dedent: eol (%nl ignored_line)* (((!.) &%dedent) / (&(%nl %dedent)))
non_dedent_error: (!dedent .)* eol (%nl ignored_line)* (!. / &%nl)
comma: %ws* "," %ws*
dotdot: nodent ".."
-plain_word: ([a-zA-Z0-9_] / %utf8_char)+
+plain_word: ([a-zA-Z0-9_-] / %utf8_char)+
diff --git a/tests/object.nom b/tests/object.nom
index a986abf..6433c86 100644
--- a/tests/object.nom
+++ b/tests/object.nom
@@ -1,24 +1,27 @@
use "core"
-use "lib/object2.nom"
+use "lib/object.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
+ object "Dog"
+ action [bark]
+ %barks <- ("Bark!" for % in 1 to ((me).barks))
+ return: %barks joined with " "
- %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)
+ action [get pissed off]
+ ((me).barks) +<- 1
- say "Object test passed."
+%d <-: new Dog {barks:2}
+as %d
+ assume: (me) = %d
+ assume: ((me).barks) = 2
+ assume: (bark) = "Bark! Bark!"
+ get pissed off
+ assume: ((me).barks) = 3
+ assume: (bark) = "Bark! Bark! Bark!"
+assume: "\(%d's "class")" = "Dog"
+assume: (%d's "barks") = 3
+
+as: new Dog {barks:1}
+ assume: (bark) = "Bark!"
+
+say "Object test passed."