Misc changes, fixed up Object lib and tests.

This commit is contained in:
Bruce Hill 2018-05-24 14:57:24 -07:00
parent ad94ed3653
commit 2e345e271f
9 changed files with 175 additions and 337 deletions

View File

@ -21,6 +21,8 @@ say "Hello world!"
%str <- "Hello world" %str <- "Hello world"
# Expressions that are more than just literal values require parentheses: # Expressions that are more than just literal values require parentheses:
%x <- (2 + 3) %x <- (2 + 3)
%one-two <- 12
say %one-two
# How do I modify a variable? # How do I modify a variable?
%x <- (%x + 1) %x <- (%x + 1)
@ -28,50 +30,50 @@ say "Hello world!"
%x +<- 1 %x +<- 1
# How do I define a mutli-line string? # How do I define a mutli-line string?
%mutli_str <- ".." %mutli-str <- ".."
Start with "..", then put lines below it Start with "..", then put lines below it
that are indented one level. that are indented one level.
The string will continue until the indentation ends. The string will continue until the indentation ends.
# How do I put values inside a string? # 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 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: expression. This escaped value will be converted to a readable string, like so:
The value of %x is \%x, isn't that nice? The value of %x is \%x, isn't that nice?
These are some numbers: \[1+1,2+1,3+1] These are some numbers: \[1+1,2+1,3+1]
The sum of 2 and 4 is \(2 + 4). The sum of 2 and 4 is \(2 + 4).
If you need to use a plain ol' backslash, you can do \\ <-- that 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? # 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 # Really long lists can use [..] followed by a bunch of indented values delimited
by commas and/or newlines by commas and/or newlines
%my_really_long_list <- [..] %my-really-long-list <- [..]
1,2,3,4 1,2,3,4
5,6 5,6
7 7
8,9,10 8,9,10
# How do I use a list? # 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" # 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: # List entries can be modified like this:
%my_list.1 <- "ONE!!!" %my-list.1 <- "ONE!!!"
say (length of %my_list) say (length of %my-list)
# How do I define a dictionary/hash map? # How do I define a dictionary/hash map?
%my_dict <- {x: 99, y: 101} %my-dict <- {x: 99, y: 101}
%my_dict <- {..} %my-dict <- {..}
x: 101, y: 2 x: 101, y: 2
"99 bottles": 99 "99 bottles": 99
653: 292 653: 292
# How do I use a dict? # How do I use a dict?
# Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists # Dicts are also implemented as Lua tables, so they're accessed and modified the same way as lists
say %my_dict.x say %my-dict.x
%my_dict.x <- 9999 %my-dict.x <- 9999
# How do I do conditional branching? # How do I do conditional branching?
if: 1 < 10 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 # Actions can have aliases, which may or may not have the arguments in different order
action [..] action [..]
I hate %worse_things more than %better_things I hate %worse-things more than %better-things
I think %worse_things are worse than %better_things I think %worse-things are worse than %better-things
I like %better_things more than %worse_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 like "dogs" more than "cats"
I think "chihuahuas" are worse than "corgis" I think "chihuahuas" are worse than "corgis"
@ -188,16 +190,16 @@ I think "chihuahuas" are worse than "corgis"
say both "Hello" and also "again!" say both "Hello" and also "again!"
# Actions can even start with a parameter # Actions can even start with a parameter
action [%what_she_said is what she said] action [%what-she-said is what she said]
say %what_she_said say %what-she-said
say "-- she said" say "-- she said"
"Howdy pardner" is what she said "Howdy pardner" is what she said
# The language only reserves []{}().,:;% as special characters, so actions # The language only reserves []{}().,:;% as special characters, so actions
can have really funky names! can have really funky names!
action [>> %foo_bar $$$^ --> % @& _~-^-~_~-^ %1 !] action [>> %foo-bar $$$^ --> % @& _~-^-~_~-^ %1 !]
say %foo_bar say %foo-bar
say % say %
say %1 say %1
@ -283,12 +285,12 @@ if (1 > (TWENTY)) on opposite day
# How do I use an action as a value? # How do I use an action as a value?
# Well... it's always *possible* to fall back to Lua behavior for something like this: # Well... it's always *possible* to fall back to Lua behavior for something like this:
action [best of %items according to %key_fn] action [best of %items according to %key-fn]
<- {%best:nil, %best_key:nil} <- {%best:nil, %best-key:nil}
for % in %items for % in %items
%key <- (=lua "\%key_fn(\%)") %key <- (=lua "\%key-fn(\%)")
if: (%best is (nil)) or (%key > %best_key) if: (%best is (nil)) or (%key > %best-key)
<- {%best:%, %best_key:%key} <- {%best:%, %best-key:%key}
return %best return %best
immediately 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 could use a macro to generate a single block of code that inlines the expression you
want to use: want to use:
immediately immediately
parse [best of %items according to %key_expr] as parse [best of %items according to %key-expr] as
result of result of
<- {%best:nil, %best_key:nil} <- {%best:nil, %best-key:nil}
for % in %items for % in %items
%key <- %key_expr %key <- %key-expr
if: (%best is (nil)) or (%key > %best_key) if: (%best is (nil)) or (%key > %best-key)
<- {%best:%, %best_key:%key} <- {%best:%, %best-key:%key}
return %best return %best
# This results in generated code that is more efficient (no function calls in the # This results in generated code that is more efficient (no function calls in the
inner loop) 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 to get a new list with every entry multiplied by 2, but it's *much* more readable to
do something like: do something like:
%nums <- [1,2,3,4,5] %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 # Nomsu comes with built-in list comprehensions, but the flexible macro system makes it
incredibly easy to make similar constructs. incredibly easy to make similar constructs.
@ -335,5 +337,5 @@ immediately
%result.(%N - %i + 1) <- %expr %result.(%N - %i + 1) <- %expr
return %result return %result
%double_nums <- ((2 * %num) for %num in %nums BACKWARDS!) %double-nums <- ((2 * %num) for %num in %nums BACKWARDS!)
say %double_nums say %double-nums

View File

@ -1,100 +1,91 @@
use "core" use "core"
compile [@%var] to compile [@, me] to: Lua value "self"
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 [@%var <- %val] to compile [as %instance %body] to
lua> ".." Lua ".."
local val_lua = \(%val as lua expr); do
local key_lua = repr(\%var.value); local self = \(%instance as lua expr);
local key_attr = (key_lua:match("'([a-zA-Z][a-zA-Z0-9]*)'") local global_actions = ACTIONS;
or key_lua:match('"([a-zA-Z][a-zA-Z0-9]*)"')); local ACTIONS = setmetatable({}, {__index=function(_,key)
if key_attr then local method = self[key];
return {statements="_me."..key_attr.." = "..val_lua..";"}; if method then return (function(...) return method(self, ...); end); end
elseif key_lua:sub(1,1) == "[" then return global_actions[key];
key_lua = " "..key_lua.." "; end});
\(%body as lua statements)
end end
return {statements="_me["..key_lua.."] = "..val_lua..";"};
compile [define object %classname %class_body] to compile [object %classname %class_body] to
%class_identifier <- (=lua "nomsu:var_to_lua_identifier(\(%classname as value)):sub(2,-1)") %class_id <- (=lua "Var(\(%classname as value)):as_lua_id():sub(2,-1)")
if: %class_identifier is "" if: %class_id is ""
%class_identifier <- "class" %class_id <- "class"
%methods <- [] %methods <-: Lua ""
for %line in (%class_body's "value") %__index <- %class_id
if: (%line's "type") is "Comment" %__newindex <- "nil"
for %line in %class_body
if: %line.type is "Comment"
do next %line do next %line
assume (((%line's "type") == "FunctionCall") and ((%line's stub) == "action % %")) if: (%line.type is "Action") and ((%line's stub) is "slots %")
..or barf "Only action definitions are supported inside 'define object % %', not \(%line's "src")" %slot_index_clauses <- []
%actions <- (2nd in (%line's "value")) %slot_newindex_clauses <- []
%body <- (3rd in (%line's "value")) %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.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> ".." lua> ".."
local stubs = {}; do
for i, action in ipairs(\%actions.value) do local stubs = {}
stubs[i] = nomsu:tree_to_named_stub(action); for i, action in ipairs(\%actions) do
stubs[i] = action:get_stub(true)
end end
local args = {}; local lua = Lua(nil, \%class_id, "[ ", repr(stubs[1]), "] = function(self")
for i,tok in ipairs(\%actions.value[1].value) do local args = {}
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end for i,tok in ipairs(\%actions[1]) do
if tok.type == "Var" then args[#args+1] = tok end
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);
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 for i, arg in ipairs(args) do
compiled_args[i] = "nomsu:tree_to_lua("..arg..").expr"; lua:append(", ", nomsu:tree_to_lua(arg))
end end
compiled_args = table.concat(compiled_args, "..', '.."); local body_lua = nomsu:tree_to_lua(\%body):as_statements("return ")
table.insert(\%methods, ([==[ body_lua:remove_free_vars(args)
%s[ %s] = function(%s) body_lua:declare_locals()
%s lua:append(")\n ", body_lua, "\nend;\n")
\%methods:append(lua)
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])));
return {..} return
statements:".." Lua ".."
do -- \%class_identifier do -- \%class_id
-- Create the class object -- Create the class object
local \%class_identifier = setmetatable({ local \%class_id = setmetatable({
name=\(%classname as lua expr), instances=setmetatable({}, {__mode="k"}), name=\(%classname as lua expr), instances=setmetatable({}, {__mode="k"}),
}, { }, {
__tostring=function(c) return c.name; end, __tostring=function(c) return c.name; end,
__call=function(cls, inst) __call=function(cls, initial_values)
inst = inst or {}; local inst = setmetatable({}, cls.instance_metatable);
inst.id = tostring(inst):match('table: (.*)'); for k,v in pairs(initial_values) do inst[k] = v; end
setmetatable(inst, cls.instance_metatable);
cls.instances[inst] = true; cls.instances[inst] = true;
if inst['set % up'] then if inst['set % up'] then
inst['set % up'](inst); inst['set % up'](inst);
@ -102,27 +93,44 @@ compile [define object %classname %class_body] to
return inst; return inst;
end, end,
}); });
\%class_identifier.class = \%class_identifier; \%class_id.class = \%class_id;
-- Define the methods -- Define the methods
\(%methods joined with "\n") \%methods
-- Define class methods for instantiating and accessing instances -- Define class methods for instantiating and accessing instances
\%class_identifier.instance_metatable = { \%class_id.instance_metatable = {
__index=\%class_identifier, __index=\%__index,
__tostring=\%class_identifier['% as text'] or function(inst) __newindex=\%__newindex,
return "<"..inst.class.name..": "..inst.id..">"; __tostring=\%class_id['as text'] or function(inst)
return "<"..inst.class.name..": "..nomsu.ids[inst]..">";
end, 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() nomsu:define_action("instances of "..\%class_id.name, function()
return utils.keys(\%class_identifier.instances); return utils.keys(\%class_id.instances);
end, ""); end);
nomsu:define_action("new "..\%class_identifier.name.." %instance", "lib/class.nom", function(_instance) nomsu:define_action("new "..\%class_id.name.." %instance", function(_instance)
return \%class_identifier(_instance); return \%class_id(_instance);
end, ""); end);
nomsu:define_action("new "..\%class_identifier.name, "lib/class.nom", function() nomsu:define_action("new "..\%class_id.name, function()
return \%class_identifier({}); return \%class_id({});
end, ""); end);
end -- End of definition of \%class_identifier end -- End of definition of \%class_id
\("\n\n") \("\n\n")

View File

@ -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")

View File

@ -28,8 +28,8 @@ end
re = require('re') re = require('re')
lpeg = require('lpeg') lpeg = require('lpeg')
lpeg.setmaxstack(10000) lpeg.setmaxstack(10000)
local P, R, V, S, Cg, C, Cp, B, Cmt local P, R, V, S, Cg, C, Cp, B
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 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 utils = require('utils')
local new_uuid = require('uuid') local new_uuid = require('uuid')
local immutable = require('immutable') local immutable = require('immutable')
@ -1303,7 +1303,7 @@ do
stub_defs = { stub_defs = {
space = (P(' ') + P('\n..')) ^ 0, space = (P(' ') + P('\n..')) ^ 0,
word = (NOMSU_DEFS.ident_char ^ 1 + NOMSU_DEFS.operator), 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_pattern = re.compile([=[ {~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~}
]=], stub_defs) ]=], stub_defs)

View File

@ -33,7 +33,7 @@ if jit
re = require 're' re = require 're'
lpeg = require 'lpeg' lpeg = require 'lpeg'
lpeg.setmaxstack 10000 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' utils = require 'utils'
new_uuid = require 'uuid' new_uuid = require 'uuid'
immutable = require 'immutable' immutable = require 'immutable'
@ -285,7 +285,7 @@ class NomsuCompiler
stub_defs = { stub_defs = {
space:(P(' ') + P('\n..'))^0 space:(P(' ') + P('\n..'))^0
word:(NOMSU_DEFS.ident_char^1 + NOMSU_DEFS.operator) 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 [=[ stub_pattern = re.compile [=[
{~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~} {~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~}

View File

@ -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 -- 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 -- 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): inline_list (List):
!('[..]') !('[..]')
@ -132,4 +132,4 @@ dedent: eol (%nl ignored_line)* (((!.) &%dedent) / (&(%nl %dedent)))
non_dedent_error: (!dedent .)* eol (%nl ignored_line)* (!. / &%nl) non_dedent_error: (!dedent .)* eol (%nl ignored_line)* (!. / &%nl)
comma: %ws* "," %ws* comma: %ws* "," %ws*
dotdot: nodent ".." dotdot: nodent ".."
plain_word: ([a-zA-Z0-9_] / %utf8_char)+ plain_word: ([a-zA-Z0-9_-] / %utf8_char)+

View File

@ -1,24 +1,27 @@
use "core" use "core"
use "lib/object2.nom" use "lib/object.nom"
#..
immediately immediately
define object "Dog" object "Dog"
action [bark] action [bark]
%barks <- ("Bark!" for all 1 to (@%barks)) %barks <- ("Bark!" for % in 1 to ((me).barks))
return (%barks joined with " ") return: %barks joined with " "
action [get pissed off]
(@%barks) +<- 1
%d <- (new Dog {barks:2}) action [get pissed off]
((me).barks) +<- 1
%d <-: new Dog {barks:2}
as %d as %d
assume ((@) = %d) assume: (me) = %d
assume ((@%barks) = 2) assume: ((me).barks) = 2
assume ((bark) = "Bark! Bark!") assume: (bark) = "Bark! Bark!"
get pissed off get pissed off
assume ((@%barks) = 3) assume: ((me).barks) = 3
assume ((bark) = "Bark! Bark! Bark!") assume: (bark) = "Bark! Bark! Bark!"
assume ("\(%d's "class")" = "Dog") assume: "\(%d's "class")" = "Dog"
assume ((%d's "barks") = 3) assume: (%d's "barks") = 3
as: new Dog {barks:1}
assume: (bark) = "Bark!"
say "Object test passed." say "Object test passed."