mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 08:39:30 +00:00
Add object type, dot operator can return function references
This commit is contained in:
parent
69b9e17020
commit
47f95fc04a
18 changed files with 599 additions and 49 deletions
|
|
@ -948,7 +948,7 @@ This only works on strings:
|
|||
|
||||
`a # b`: evaluates b, then evaluates a whith b added to the active tags. Returns a.
|
||||
|
||||
`a.b`: if a is a function reference, returns the variable named `b` in the referenced function namespace. When overloading this operator, if `b` is an identifier, the operator will interpret it as a string (and not returns the evaluated value of the variable eventually associated to the identifier).
|
||||
`a.b`: if a is a function reference, returns the first found variable (or reference to a subfunction) named `b` in the referenced function namespace. When overloading this operator, if `b` is an identifier, the operator will interpret it as a string (instead of returning the evaluated value of the variable eventually associated to the identifier).
|
||||
|
||||
`a(b)`: evaluate b (number), returns the value with this index in a (list). Use 1-based indexing. If b is a string, will search the first pair in the list with this string as its name. Operator is named `()`.
|
||||
|
||||
|
|
|
|||
20
anselme.lua
20
anselme.lua
|
|
@ -577,8 +577,24 @@ local vm_mt = {
|
|||
save = function(self)
|
||||
local vars = {}
|
||||
for k, v in pairs(self.state.variables) do
|
||||
if should_keep_variable(self.state, k) then
|
||||
vars[k] = v
|
||||
if should_keep_variable(self.state, k, v) then
|
||||
if v.type == "object" then -- filter object attributes
|
||||
local attributes = {}
|
||||
for kk, vv in pairs(v.value.attributes) do
|
||||
if should_keep_variable(self.state, kk, vv) then
|
||||
attributes[kk] = vv
|
||||
end
|
||||
end
|
||||
vars[k] = {
|
||||
type = "object",
|
||||
value = {
|
||||
class = v.value.class,
|
||||
attributes = attributes
|
||||
}
|
||||
}
|
||||
else
|
||||
vars[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -189,9 +189,8 @@ common = {
|
|||
end,
|
||||
--- returns true if a variable should be persisted on save
|
||||
-- will exclude: undefined variables, variables in scoped functions, internal anselme variables
|
||||
should_keep_variable = function(state, name)
|
||||
local v = state.variables[name]
|
||||
return v.type ~= "undefined argument" and v.type ~= "pending definition" and name:match("^"..identifier_pattern.."$") and not name:match("^anselme%.")
|
||||
should_keep_variable = function(state, name, value)
|
||||
return value.type ~= "undefined argument" and value.type ~= "pending definition" and name:match("^"..identifier_pattern.."$") and not name:match("^anselme%.")
|
||||
end,
|
||||
--- check truthyness of an anselme value
|
||||
truthy = function(val)
|
||||
|
|
|
|||
|
|
@ -208,16 +208,10 @@ local function eval(state, exp)
|
|||
local tried_function_error_messages = {}
|
||||
local selected_variant = { depths = { assignment = nil }, variant = nil, args_to_set = nil }
|
||||
for _, fn in ipairs(variants) do
|
||||
-- checkpoint: no args, nothing to select on
|
||||
if fn.type == "checkpoint" then
|
||||
if not selected_variant.variant then
|
||||
selected_variant.depths = {}
|
||||
selected_variant.variant = fn
|
||||
else
|
||||
return nil, ("checkpoint call %q is ambigous; may be at least either:\n\t%s\n\t%s"):format(exp.called_name, fn.pretty_signature, selected_variant.variant.pretty_signature)
|
||||
end
|
||||
-- function
|
||||
elseif fn.type == "function" then
|
||||
if fn.type ~= "function" then
|
||||
return nil, ("unknown function type %q"):format(fn.type)
|
||||
-- functions
|
||||
else
|
||||
if not fn.assignment or exp.assignment then
|
||||
local ok = true
|
||||
-- get and set args
|
||||
|
|
@ -342,18 +336,20 @@ local function eval(state, exp)
|
|||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
return nil, ("unknown function type %q"):format(fn.type)
|
||||
end
|
||||
end
|
||||
-- function successfully selected: run
|
||||
if selected_variant.variant then
|
||||
local fn = selected_variant.variant
|
||||
if fn.type == "checkpoint" then
|
||||
if fn.type ~= "function" then
|
||||
return nil, ("unknown function type %q"):format(fn.type)
|
||||
-- checkpoint: no args and resume execution
|
||||
elseif fn.subtype == "checkpoint" then
|
||||
local r, e = run(state, fn.child, not paren_call)
|
||||
if not r then return r, e end
|
||||
return r
|
||||
elseif fn.type == "function" then
|
||||
-- other functions
|
||||
else
|
||||
local ret
|
||||
-- push scope
|
||||
-- NOTE: if error happens between here and scope:pop, will leave the stack a mess
|
||||
|
|
@ -452,6 +448,28 @@ local function eval(state, exp)
|
|||
type = "number",
|
||||
value = seen.value + 1
|
||||
})
|
||||
-- for classes: build resulting object
|
||||
if fn.subtype == "class" then
|
||||
local object = {
|
||||
type = "type",
|
||||
value = {
|
||||
{
|
||||
type = "object",
|
||||
value = {
|
||||
class = fn.name,
|
||||
attributes = {}
|
||||
}
|
||||
},
|
||||
{
|
||||
type = "function reference",
|
||||
value = { fn.name }
|
||||
}
|
||||
}
|
||||
}
|
||||
if ret and ret.type == "nil" then
|
||||
ret = object
|
||||
end
|
||||
end
|
||||
-- pop scope
|
||||
if fn.scoped then
|
||||
scope:pop(state, fn)
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ run_line = function(state, line)
|
|||
elseif line.type == "flush_events" then
|
||||
local v, e = events:flush(state)
|
||||
if not v then return v, ("%s; in event flush at %s"):format(e, line.source) end
|
||||
elseif line.type == "checkpoint" then
|
||||
elseif line.type == "function" and line.subtype == "checkpoint" then
|
||||
local reached, reachede = get_variable(state, line.namespace.."🏁")
|
||||
if not reached then return nil, reachede end
|
||||
set_variable(state, line.namespace.."🏁", {
|
||||
|
|
@ -150,9 +150,9 @@ run_block = function(state, block, resume_from_there, i, j)
|
|||
i = i + 1
|
||||
end
|
||||
-- if we are exiting a checkpoint block, mark it as ran and update checkpoint
|
||||
-- (when resuming from a checkpoint, execution is resumed from inside the checkpoint, the line.type=="checkpoint" check in run_line is never called)
|
||||
-- (when resuming from a checkpoint, execution is resumed from inside the checkpoint, the line.subtype=="checkpoint" check in run_line is never called)
|
||||
-- (and we want this to be done after executing the checkpoint block anyway)
|
||||
if block.parent_line and block.parent_line.type == "checkpoint" then
|
||||
if block.parent_line and block.parent_line.type == "function" and block.parent_line.subtype == "checkpoint" then
|
||||
local parent_line = block.parent_line
|
||||
local reached, reachede = get_variable(state, parent_line.namespace.."🏁")
|
||||
if not reached then return nil, reachede end
|
||||
|
|
@ -183,7 +183,7 @@ run_block = function(state, block, resume_from_there, i, j)
|
|||
-- if parent is a choice, will ignore choices that belong to the same block (like the whole block was executed naturally from a higher parent)
|
||||
-- if parent if a condition, will mark it as a success (skipping following else-conditions) (for the same reasons as for choices)
|
||||
-- if parent pushed a tag, will pop it (tags from parents are added to the stack in run())
|
||||
if resume_from_there and block.parent_line and block.parent_line.type ~= "function" then
|
||||
if resume_from_there and block.parent_line and not block.parent_line.resume_boundary then
|
||||
local parent_line = block.parent_line
|
||||
if parent_line.type == "choice" then
|
||||
state.interpreter.skip_choices_until_flush = true
|
||||
|
|
@ -209,7 +209,7 @@ local function run(state, block, resume_from_there, i, j)
|
|||
local tags_to_add = {}
|
||||
-- go up in hierarchy in ascending order until function boundary
|
||||
local parent_line = block.parent_line
|
||||
while parent_line and parent_line.type ~= "function" do
|
||||
while parent_line and not parent_line.resume_boundary do
|
||||
if parent_line.type == "tag" then
|
||||
local v, e = eval(state, parent_line.expression)
|
||||
if not v then return v, ("%s; at %s"):format(e, parent_line.source) end
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ Reserved symbols that are still not used as a line type: `^+-=</[]*{}|\_!?.,;)"&
|
|||
|
||||
Broad goals and ideas that may never be implemented. Mostly used as personal post-it notes.
|
||||
|
||||
TODO: type system is not super nice to use
|
||||
|
||||
TODO: distinguish between list and argument list to confuse less pairs with named arguments
|
||||
|
||||
TODO: some sensible way to capture text event in string litterals (string interpolation)? -> meh, this means we can capture choice events, and choice events contain their code block, and we don't want to store code blocks in the save file (as code can be updated/translated/whatever)
|
||||
|
|
@ -83,7 +85,7 @@ TODO: perform seen/reached/etc default variable not in interpreter but using par
|
|||
TODO: no function call without () (reference to fn instead?). Fn could be stored in save but replaced with new versions on code reload... -> how to track these references?
|
||||
if we make fn first class this means anonymous fn, is it ok?
|
||||
|
||||
TODO: make language simple enough to be able to reimplement it in, say, nim. Especially the interpreter (we could precompile a lot of stuff...)
|
||||
TODO: make language simple enough to be able to reimplement it in, say, nim. Especially the AST interpreter (we could precompile a lot of stuff...)
|
||||
|
||||
TODO: test reacheability of script paths
|
||||
|
||||
|
|
|
|||
|
|
@ -54,24 +54,41 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
r.child = true
|
||||
r.text = l:match("^>%s*(.-)$")
|
||||
-- function & checkpoint
|
||||
elseif l:match("^%$") or l:match("^§") then -- § is a 2-bytes caracter, DO NOT USE LUA PATTERN OPERATORS as they operate on single bytes
|
||||
r.type = l:match("^%$") and "function" or "checkpoint"
|
||||
elseif l:match("^%$") or l:match("^§") or l:match("^%%") then -- § is a 2-bytes caracter, DO NOT USE LUA PATTERN OPERATORS as they operate on single bytes
|
||||
r.type = "function"
|
||||
r.child = true
|
||||
-- store parent function and run checkpoint when line is read
|
||||
if r.type == "checkpoint" then
|
||||
r.parent_function = parent_function
|
||||
-- subtype options
|
||||
local allow_params = true
|
||||
local allow_assign = true
|
||||
local keep_in_ast = false
|
||||
if l:match("^%$") then
|
||||
r.subtype = "function"
|
||||
r.resume_boundary = true
|
||||
elseif l:match("^%%") then
|
||||
r.subtype = "class"
|
||||
r.resume_boundary = true
|
||||
allow_params = false
|
||||
allow_assign = false
|
||||
elseif l:match("^§") then
|
||||
r.subtype = "checkpoint"
|
||||
allow_params = false
|
||||
allow_assign = false
|
||||
keep_in_ast = true
|
||||
r.parent_function = parent_function -- store parent function and run checkpoint when line is read
|
||||
else
|
||||
error("unknown function line type")
|
||||
end
|
||||
-- don't keep function node in block AST
|
||||
if r.type == "function" then
|
||||
if not keep_in_ast then
|
||||
r.remove_from_block_ast = true
|
||||
-- lua function
|
||||
if state.global_state.link_next_function_definition_to_lua_function then
|
||||
r.lua_function = state.global_state.link_next_function_definition_to_lua_function
|
||||
state.global_state.link_next_function_definition_to_lua_function = nil
|
||||
end
|
||||
end
|
||||
-- lua function
|
||||
if r.subtype == "function" and state.global_state.link_next_function_definition_to_lua_function then
|
||||
r.lua_function = state.global_state.link_next_function_definition_to_lua_function
|
||||
state.global_state.link_next_function_definition_to_lua_function = nil
|
||||
end
|
||||
-- get identifier
|
||||
local lc = l:match("^%$(.-)$") or l:match("^§(.-)$")
|
||||
local lc = l:match("^[%$%%](.-)$") or l:match("^§(.-)$")
|
||||
local identifier, rem = lc:match("^("..identifier_pattern..")(.-)$")
|
||||
if not identifier then
|
||||
for _, name in ipairs(special_functions_names) do
|
||||
|
|
@ -80,7 +97,7 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
end
|
||||
end
|
||||
if not identifier then
|
||||
return nil, ("no valid identifier in checkpoint/function definition line %q; at %s"):format(lc, line.source)
|
||||
return nil, ("no valid identifier in function definition line %q; at %s"):format(lc, line.source)
|
||||
end
|
||||
-- format identifier
|
||||
local fqm = ("%s%s"):format(namespace, format_identifier(identifier))
|
||||
|
|
@ -101,7 +118,7 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
r.name = fqm
|
||||
-- get params
|
||||
r.params = {}
|
||||
if r.type == "function" and rem:match("^%b()") then
|
||||
if allow_params and rem:match("^%b()") then
|
||||
r.scoped = true
|
||||
local content
|
||||
content, rem = rem:match("^(%b())%s*(.*)$")
|
||||
|
|
@ -131,7 +148,7 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
end
|
||||
end
|
||||
-- get assignment param
|
||||
if r.type == "function" and rem:match("^%:%=") then
|
||||
if allow_assign and rem:match("^%:%=") then
|
||||
local param = rem:match("^%:%=(.*)$")
|
||||
-- get identifier
|
||||
local param_identifier, param_rem = param:match("^("..identifier_pattern..")(.-)$")
|
||||
|
|
@ -153,7 +170,7 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
-- add parameter
|
||||
r.assignment = { name = param_identifier, alias = param_alias, full_name = param_fqm, type_annotation = type_annotation, default = nil, vararg = nil }
|
||||
elseif rem:match("[^%s]") then
|
||||
return nil, ("expected end-of-line at end of checkpoint/function definition line, but got %q; at %s"):format(rem, line.source)
|
||||
return nil, ("expected end-of-line at end of function definition line, but got %q; at %s"):format(rem, line.source)
|
||||
end
|
||||
-- calculate arity
|
||||
local minarity, maxarity = #r.params, #r.params
|
||||
|
|
@ -190,7 +207,7 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
else
|
||||
table.insert(line.children, 1, { content = ":👁️=0", source = line.source })
|
||||
end
|
||||
if r.type == "function" then
|
||||
if r.subtype ~= "checkpoint" then
|
||||
-- define 🔖 variable
|
||||
local checkpoint_alias = state.global_state.builtin_aliases["🔖"]
|
||||
if checkpoint_alias then
|
||||
|
|
@ -222,7 +239,7 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
end
|
||||
end
|
||||
end
|
||||
elseif r.type == "checkpoint" then
|
||||
elseif r.subtype == "checkpoint" then
|
||||
-- define 🏁 variable
|
||||
local reached_alias = state.global_state.builtin_aliases["🏁"]
|
||||
if reached_alias then
|
||||
|
|
@ -372,7 +389,7 @@ local function parse_block(indented, state, namespace, parent_function)
|
|||
if not ast.child then
|
||||
return nil, ("line %s (%s) can't have children"):format(ast.source, ast.type)
|
||||
else
|
||||
local r, e = parse_block(l.children, state, ast.namespace or namespace, ast.type == "function" and ast or parent_function)
|
||||
local r, e = parse_block(l.children, state, ast.namespace or namespace, (ast.type == "function" and ast.subtype ~= "checkpoint") and ast or parent_function)
|
||||
if not r then return r, e end
|
||||
r.parent_line = ast
|
||||
ast.child = r
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ return [[
|
|||
:pair="pair"
|
||||
:function reference="function reference"
|
||||
:variable reference="variable reference"
|
||||
:object="object"
|
||||
|
||||
:pi=3.1415926535898
|
||||
]]
|
||||
|
|
|
|||
|
|
@ -76,28 +76,37 @@ lua_functions = {
|
|||
},
|
||||
-- namespace
|
||||
["_._(r::function reference, name::string)"] = {
|
||||
mode = "raw",
|
||||
mode = "untyped raw",
|
||||
value = function(r, n)
|
||||
local state = anselme.running.state
|
||||
local rval = r.value
|
||||
local name = n.value
|
||||
for _, ffqm in ipairs(rval) do
|
||||
local var, vfqm = find(state.aliases, state.interpreter.global_state.variables, ffqm..".", name)
|
||||
local var, vfqm = find(state.aliases, state.interpreter.global_state.variables, "", ffqm.."."..name)
|
||||
if var then
|
||||
return get_variable(state, vfqm)
|
||||
end
|
||||
end
|
||||
for _, ffqm in ipairs(rval) do
|
||||
local fn, fnfqm = find(state.aliases, state.functions, "", ffqm.."."..name)
|
||||
if fn then
|
||||
return {
|
||||
type = "function reference",
|
||||
value = { fnfqm }
|
||||
}
|
||||
end
|
||||
end
|
||||
return nil, ("can't find variable %q in function reference (searched in namespaces: %s)"):format(name, table.concat(rval, ", "))
|
||||
end
|
||||
},
|
||||
["_._(r::function reference, name::string) := v"] = {
|
||||
mode = "raw",
|
||||
mode = "untyped raw",
|
||||
value = function(r, n, v)
|
||||
local state = anselme.running.state
|
||||
local rval = r.value
|
||||
local name = n.value
|
||||
for _, ffqm in ipairs(rval) do
|
||||
local var, vfqm = find(state.aliases, state.interpreter.global_state.variables, ffqm..".", name)
|
||||
local var, vfqm = find(state.aliases, state.interpreter.global_state.variables, "", ffqm.."."..name)
|
||||
if var then
|
||||
set_variable(state, vfqm, v)
|
||||
return v
|
||||
|
|
@ -106,6 +115,52 @@ lua_functions = {
|
|||
return nil, ("can't find variable %q in function reference (searched in namespaces: %s)"):format(name, table.concat(rval, ", "))
|
||||
end
|
||||
},
|
||||
["_._(r::object, name::string)"] = {
|
||||
mode = "untyped raw",
|
||||
value = function(r, n)
|
||||
local state = anselme.running.state
|
||||
local obj = r.value
|
||||
local name = n.value
|
||||
-- attribute already present in object
|
||||
local var = find(state.aliases, obj.attributes, "", obj.class.."."..name)
|
||||
if var then return var end
|
||||
-- search for attribute in base class
|
||||
local cvar, cvfqm = find(state.aliases, state.interpreter.global_state.variables, "", obj.class.."."..name)
|
||||
if cvar then return get_variable(state, cvfqm) end
|
||||
-- search for method in base class
|
||||
local fn, fnfqm = find(state.aliases, state.functions, "", obj.class.."."..name)
|
||||
if fn then
|
||||
return {
|
||||
type = "function reference",
|
||||
value = { fnfqm }
|
||||
}
|
||||
end
|
||||
return nil, ("can't find attribute %q in object"):format(name)
|
||||
end
|
||||
},
|
||||
["_._(r::object, name::string) := v"] = {
|
||||
mode = "untyped raw",
|
||||
value = function(r, n, v)
|
||||
local state = anselme.running.state
|
||||
local obj = r.value
|
||||
local name = n.value
|
||||
-- attribute already present in object
|
||||
local var, vfqm = find(state.aliases, obj.attributes, "", obj.class.."."..name)
|
||||
if var then
|
||||
obj.attributes[vfqm] = v
|
||||
mark_as_modified(anselme.running.state, obj.attributes)
|
||||
return v
|
||||
end
|
||||
-- search for attribute in base class
|
||||
local cvar, cvfqm = find(state.aliases, state.interpreter.global_state.variables, "", obj.class.."."..name)
|
||||
if cvar then
|
||||
obj.attributes[cvfqm] = v
|
||||
mark_as_modified(anselme.running.state, obj.attributes)
|
||||
return v
|
||||
end
|
||||
return nil, ("can't find attribute %q in object"):format(name)
|
||||
end
|
||||
},
|
||||
-- index
|
||||
["()(l::list, i::number)"] = {
|
||||
mode = "untyped raw",
|
||||
|
|
|
|||
|
|
@ -166,6 +166,12 @@ types.anselme = {
|
|||
end,
|
||||
to_lua = nil
|
||||
},
|
||||
object = {
|
||||
format = function(val)
|
||||
return ("%%%s"):format(val.class)
|
||||
end,
|
||||
to_lua = nil
|
||||
},
|
||||
-- internal types
|
||||
["event buffer"] = {
|
||||
format = function(val) -- triggered from subtexts
|
||||
|
|
|
|||
9
test/tests/function reference dot operator function.ans
Normal file
9
test/tests/function reference dot operator function.ans
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
$ f
|
||||
$ a
|
||||
@12
|
||||
|
||||
:x = &f
|
||||
|
||||
{x.a}
|
||||
|
||||
{x.a!}
|
||||
22
test/tests/function reference dot operator function.lua
Normal file
22
test/tests/function reference dot operator function.lua
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
local _={}
|
||||
_[9]={}
|
||||
_[8]={}
|
||||
_[7]={tags=_[9],text="12"}
|
||||
_[6]={tags=_[8],text="&function reference dot operator function.f.a"}
|
||||
_[5]={_[7]}
|
||||
_[4]={_[6]}
|
||||
_[3]={"return"}
|
||||
_[2]={"text",_[5]}
|
||||
_[1]={"text",_[4]}
|
||||
return {_[1],_[2],_[3]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "&function reference dot operator function.f.a"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "12"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
15
test/tests/object constructor.ans
Normal file
15
test/tests/object constructor.ans
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
% class
|
||||
:a:b = "foo"
|
||||
:c = "bar"
|
||||
|
||||
$ new(o::&class, x)
|
||||
~ o.c := x
|
||||
@o
|
||||
|
||||
:o = class
|
||||
:p = class!new("hoho")
|
||||
|
||||
{o}, {p}
|
||||
|
||||
{o.c} == {class.c}
|
||||
{p.c} != {class.c}
|
||||
57
test/tests/object constructor.lua
Normal file
57
test/tests/object constructor.lua
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
local _={}
|
||||
_[23]={}
|
||||
_[22]={}
|
||||
_[21]={}
|
||||
_[20]={}
|
||||
_[19]={}
|
||||
_[18]={}
|
||||
_[17]={}
|
||||
_[16]={}
|
||||
_[15]={}
|
||||
_[14]={tags=_[23],text="bar"}
|
||||
_[13]={tags=_[22],text=" != "}
|
||||
_[12]={tags=_[21],text="hoho"}
|
||||
_[11]={tags=_[20],text="bar"}
|
||||
_[10]={tags=_[19],text=" == "}
|
||||
_[9]={tags=_[18],text="bar"}
|
||||
_[8]={tags=_[17],text="%object constructor.class::&object constructor.class"}
|
||||
_[7]={tags=_[16],text=", "}
|
||||
_[6]={tags=_[15],text="%object constructor.class::&object constructor.class"}
|
||||
_[5]={_[9],_[10],_[11],_[12],_[13],_[14]}
|
||||
_[4]={_[6],_[7],_[8]}
|
||||
_[3]={"return"}
|
||||
_[2]={"text",_[5]}
|
||||
_[1]={"text",_[4]}
|
||||
return {_[1],_[2],_[3]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "%object constructor.class::&object constructor.class"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ", "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "%object constructor.class::&object constructor.class"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
}, {
|
||||
tags = {},
|
||||
text = "hoho"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " != "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
26
test/tests/object several.ans
Normal file
26
test/tests/object several.ans
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
% class
|
||||
:a:b = "foo"
|
||||
:c = "bar"
|
||||
|
||||
:o = class
|
||||
:p = class
|
||||
|
||||
{o}, {p}
|
||||
|
||||
{o.a} == {class.a}
|
||||
{o.b} == {class.b}
|
||||
|
||||
{p.a} == {class.a}
|
||||
{p.b} == {class.b}
|
||||
|
||||
~ o.b := "haha"
|
||||
|
||||
{o.a} != {class.a}
|
||||
{o.b} != {class.b}
|
||||
|
||||
{p.a} == {class.a}
|
||||
{p.b} == {class.b}
|
||||
|
||||
{o.c} == {class.c}
|
||||
|
||||
{p.c} == {class.c}
|
||||
192
test/tests/object several.lua
Normal file
192
test/tests/object several.lua
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
local _={}
|
||||
_[81]={}
|
||||
_[80]={}
|
||||
_[79]={}
|
||||
_[78]={}
|
||||
_[77]={}
|
||||
_[76]={}
|
||||
_[75]={}
|
||||
_[74]={}
|
||||
_[73]={}
|
||||
_[72]={}
|
||||
_[71]={}
|
||||
_[70]={}
|
||||
_[69]={}
|
||||
_[68]={}
|
||||
_[67]={}
|
||||
_[66]={}
|
||||
_[65]={}
|
||||
_[64]={}
|
||||
_[63]={}
|
||||
_[62]={}
|
||||
_[61]={}
|
||||
_[60]={}
|
||||
_[59]={}
|
||||
_[58]={}
|
||||
_[57]={}
|
||||
_[56]={}
|
||||
_[55]={}
|
||||
_[54]={}
|
||||
_[53]={}
|
||||
_[52]={}
|
||||
_[51]={}
|
||||
_[50]={}
|
||||
_[49]={}
|
||||
_[48]={tags=_[81],text="bar"}
|
||||
_[47]={tags=_[80],text=" == "}
|
||||
_[46]={tags=_[79],text="bar"}
|
||||
_[45]={tags=_[78],text="bar"}
|
||||
_[44]={tags=_[77],text=" == "}
|
||||
_[43]={tags=_[76],text="bar"}
|
||||
_[42]={tags=_[75],text="foo"}
|
||||
_[41]={tags=_[74],text=" == "}
|
||||
_[40]={tags=_[73],text="foo"}
|
||||
_[39]={tags=_[72],text="foo"}
|
||||
_[38]={tags=_[71],text=" == "}
|
||||
_[37]={tags=_[70],text="foo"}
|
||||
_[36]={tags=_[69],text="foo"}
|
||||
_[35]={tags=_[68],text=" != "}
|
||||
_[34]={tags=_[67],text="haha"}
|
||||
_[33]={tags=_[66],text="foo"}
|
||||
_[32]={tags=_[65],text=" != "}
|
||||
_[31]={tags=_[64],text="haha"}
|
||||
_[30]={tags=_[63],text="foo"}
|
||||
_[29]={tags=_[62],text=" == "}
|
||||
_[28]={tags=_[61],text="foo"}
|
||||
_[27]={tags=_[60],text="foo"}
|
||||
_[26]={tags=_[59],text=" == "}
|
||||
_[25]={tags=_[58],text="foo"}
|
||||
_[24]={tags=_[57],text="foo"}
|
||||
_[23]={tags=_[56],text=" == "}
|
||||
_[22]={tags=_[55],text="foo"}
|
||||
_[21]={tags=_[54],text="foo"}
|
||||
_[20]={tags=_[53],text=" == "}
|
||||
_[19]={tags=_[52],text="foo"}
|
||||
_[18]={tags=_[51],text="%object several.class::&object several.class"}
|
||||
_[17]={tags=_[50],text=", "}
|
||||
_[16]={tags=_[49],text="%object several.class::&object several.class"}
|
||||
_[15]={_[46],_[47],_[48]}
|
||||
_[14]={_[43],_[44],_[45]}
|
||||
_[13]={_[37],_[38],_[39],_[40],_[41],_[42]}
|
||||
_[12]={_[31],_[32],_[33],_[34],_[35],_[36]}
|
||||
_[11]={_[25],_[26],_[27],_[28],_[29],_[30]}
|
||||
_[10]={_[19],_[20],_[21],_[22],_[23],_[24]}
|
||||
_[9]={_[16],_[17],_[18]}
|
||||
_[8]={"return"}
|
||||
_[7]={"text",_[15]}
|
||||
_[6]={"text",_[14]}
|
||||
_[5]={"text",_[13]}
|
||||
_[4]={"text",_[12]}
|
||||
_[3]={"text",_[11]}
|
||||
_[2]={"text",_[10]}
|
||||
_[1]={"text",_[9]}
|
||||
return {_[1],_[2],_[3],_[4],_[5],_[6],_[7],_[8]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "%object several.class::&object several.class"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ", "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "%object several.class::&object several.class"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "haha"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " != "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = "haha"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " != "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
17
test/tests/object simple.ans
Normal file
17
test/tests/object simple.ans
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
% class
|
||||
:a:b = "foo"
|
||||
:c = "bar"
|
||||
|
||||
:o = class
|
||||
|
||||
{o}
|
||||
|
||||
{o.a} == {class.a}
|
||||
{o.b} == {class.b}
|
||||
|
||||
~ o.b := "haha"
|
||||
|
||||
{o.a} != {class.a}
|
||||
{o.b} != {class.b}
|
||||
|
||||
{o.c} == {class.c}
|
||||
98
test/tests/object simple.lua
Normal file
98
test/tests/object simple.lua
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
local _={}
|
||||
_[41]={}
|
||||
_[40]={}
|
||||
_[39]={}
|
||||
_[38]={}
|
||||
_[37]={}
|
||||
_[36]={}
|
||||
_[35]={}
|
||||
_[34]={}
|
||||
_[33]={}
|
||||
_[32]={}
|
||||
_[31]={}
|
||||
_[30]={}
|
||||
_[29]={}
|
||||
_[28]={}
|
||||
_[27]={}
|
||||
_[26]={}
|
||||
_[25]={tags=_[41],text="bar"}
|
||||
_[24]={tags=_[40],text=" == "}
|
||||
_[23]={tags=_[39],text="bar"}
|
||||
_[22]={tags=_[38],text="foo"}
|
||||
_[21]={tags=_[37],text=" != "}
|
||||
_[20]={tags=_[36],text="haha"}
|
||||
_[19]={tags=_[35],text="foo"}
|
||||
_[18]={tags=_[34],text=" != "}
|
||||
_[17]={tags=_[33],text="haha"}
|
||||
_[16]={tags=_[32],text="foo"}
|
||||
_[15]={tags=_[31],text=" == "}
|
||||
_[14]={tags=_[30],text="foo"}
|
||||
_[13]={tags=_[29],text="foo"}
|
||||
_[12]={tags=_[28],text=" == "}
|
||||
_[11]={tags=_[27],text="foo"}
|
||||
_[10]={tags=_[26],text="%object simple.class::&object simple.class"}
|
||||
_[9]={_[23],_[24],_[25]}
|
||||
_[8]={_[17],_[18],_[19],_[20],_[21],_[22]}
|
||||
_[7]={_[11],_[12],_[13],_[14],_[15],_[16]}
|
||||
_[6]={_[10]}
|
||||
_[5]={"return"}
|
||||
_[4]={"text",_[9]}
|
||||
_[3]={"text",_[8]}
|
||||
_[2]={"text",_[7]}
|
||||
_[1]={"text",_[6]}
|
||||
return {_[1],_[2],_[3],_[4],_[5]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "%object simple.class::&object simple.class"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "haha"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " != "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
}, {
|
||||
tags = {},
|
||||
text = "haha"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " != "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "foo"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "bar"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
Loading…
Add table
Add a link
Reference in a new issue