mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
Add maps; remove map emulation functionality from list; function and tags now internally use maps instead of lists
This commit is contained in:
parent
bac5cdde01
commit
95462391e3
20 changed files with 699 additions and 139 deletions
22
LANGUAGE.md
22
LANGUAGE.md
|
|
@ -303,7 +303,7 @@ $ show(object::&class)
|
|||
~ object!show
|
||||
```
|
||||
|
||||
* `#`: tag line. Can be followed by an [expression](#expressions); otherwise nil expression is assumed. The results of the [expression](#expressions) will be added to the tags send along with any `choice` or `text` event sent from its children. Can be nested.
|
||||
* `#`: tag line. Can be followed by an [expression](#expressions); otherwise nil expression is assumed. The results of the [expression](#expressions) will be wrapped in a map and added to the tags send along with any `choice` or `text` event sent from its children. Can be nested.
|
||||
|
||||
```
|
||||
# color="red"
|
||||
|
|
@ -636,9 +636,11 @@ Default types are:
|
|||
|
||||
* `list`: a list of values. Mutable. Types can be mixed. Can be defined between square brackets and use comma as a separator '[1,2,3,4]'.
|
||||
|
||||
* `map`: a map of keys-values. Mutable. Types can be mixed. Can be defined between curly braces and use comma as a separator, using pairs to define the key-values pairs (otherwise the numeric position of the element is used as a key). '{1=1,2=2,3,4="heh",foo="bar"}'.
|
||||
|
||||
* `object`: an object/record. Mutable. Can be created by calling a class function.
|
||||
|
||||
Every type is immutable, except `list` and `object`.
|
||||
Every type is immutable, except `list`, `map` and `object`.
|
||||
|
||||
How conversions are handled from Anselme to Lua:
|
||||
|
||||
|
|
@ -648,7 +650,9 @@ How conversions are handled from Anselme to Lua:
|
|||
|
||||
* `string` -> `string`
|
||||
|
||||
* `list` -> `table`. Pair elements in the list will be assigned as a key-value pair in the Lua list and its index skipped in the sequential part, e.g. `[1,2,"key"="value",3]` -> `{1,2,3,key="value"}`.
|
||||
* `list` -> `table` (purely sequential table).
|
||||
|
||||
* `map` -> `table` (will map each key to a key in the Lua table).
|
||||
|
||||
* `pair` -> `table`, with a single key-value pair.
|
||||
|
||||
|
|
@ -660,7 +664,7 @@ How conservions are handled from Lua to Anselme:
|
|||
|
||||
* `string` -> `string`
|
||||
|
||||
* `table` -> `list`. First add the sequential part of the table in the list, then add pairs for the remaining elements, e.g. `{1,2,key="value",3}` -> `[1,2,3,"key"="value"]`
|
||||
* `table` -> `list` or `map`. Converted to a list if the table is purely sequential, otherwise returns a map; e.g. `{1,2,key="value",3}` -> `{1=1,2=2,3=3,key="value"}` and `{1,2,3}` -> [1,2,3]
|
||||
|
||||
* `boolean` -> `number`, 0 for false, 1 for true.
|
||||
|
||||
|
|
@ -819,7 +823,7 @@ $ f(a, b, c)
|
|||
{f(1,2,3)} = {f(c=3,b=2,a=1)} = {f(1,2,c=3)}
|
||||
```
|
||||
|
||||
Anselme actually treat argument list are regular lists; named arguments are actually pairs. Arguments are evaluated left-to-right.
|
||||
Anselme actually treat argument maps are regular maps; named arguments are actually pairs and positional arguments are implicitely converted to pairs with their position as a key. Arguments are evaluated left-to-right. The call will error if one of the keys in the map is not a string or number.
|
||||
|
||||
This means that pairs can't be passed directly as arguments to a function (as they will be considered named arguments). If you want to use pairs, always wrap them in a list.
|
||||
|
||||
|
|
@ -953,7 +957,7 @@ Built-in operators:
|
|||
|
||||
`a := b`: evaluate b, assign its value to identifier `a`. Returns the new value.
|
||||
|
||||
`a(index) := b`: evaluate b, assign its value to element of specific index in list `a`. Element is searched using the same method as list index operator `a(b)`; if indexing using a string and an associated pair doesn't exist, add a new one at the end of the list. Returns the new value.
|
||||
`a(index) := b`: evaluate b, assign its value to element of specific index in list/map `a`. Element is searched using the same method as list/map index operator `a(b)`; in the case of list, also allows to add a new element to the list by giving `len(a)+1` as the index. In the case of a map, if b is nil `()`, deletes the key-value pair from the map. Returns the new value.
|
||||
|
||||
`a.b := v`: if a is a function reference or an object, modify the b variable in the reference function or object.
|
||||
|
||||
|
|
@ -1025,13 +1029,15 @@ This only works on strings:
|
|||
|
||||
`a :: b`: evaluate a and b, returns a new annotated value with a as value and b as the annotation. This annotation will be checked in type constraints.
|
||||
|
||||
`a # b`: evaluates b, then evaluates a whith b added to the active tags. Returns a.
|
||||
`a # b`: evaluates b, then evaluates a with b added to the active tags (wrap b in a map and merges it with the current tag map). Returns a.
|
||||
|
||||
`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).
|
||||
|
||||
`object.b`: if object is an object, returns the first found variable (or reference to a subfunction) named `b` in the object, or, if the object does not contain it, its base class.
|
||||
|
||||
`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 `()`.
|
||||
`list(b)`: evaluate b (number), returns the value with this index in the list. Use 1-based indexing. If a negative value is given, will look from the end of the list (`-1` is the last element, `-2` the one before, etc.). Error on invalid index. Operator is named `()`.
|
||||
|
||||
`map(b)`: evaluate b, returns the value with this key in the map. If the key is not present in the map, returns `nil`.
|
||||
|
||||
`{}(v)`: function called when formatting a value in a text interpolation for printing.
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,14 @@ local function post_process_text(state, text)
|
|||
return r
|
||||
end
|
||||
|
||||
local function random_identifier()
|
||||
local r = ""
|
||||
for _=1, 16 do -- that's live 10^31 possibilities, ought to be enough for anyone
|
||||
r = r .. string.char(math.random(32, 126))
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
common = {
|
||||
--- merge interpreter state with global state
|
||||
merge_state = function(state)
|
||||
|
|
@ -129,18 +137,11 @@ common = {
|
|||
end,
|
||||
--- mark a value as constant, recursively affecting all the potentially mutable subvalues
|
||||
mark_constant = function(v)
|
||||
if v.type == "list" then
|
||||
v.constant = true
|
||||
for _, item in ipairs(v.value) do
|
||||
common.mark_constant(item)
|
||||
end
|
||||
elseif v.type == "object" then
|
||||
v.constant = true
|
||||
elseif v.type == "pair" or v.type == "annotated" then
|
||||
common.mark_constant(v.value[1])
|
||||
common.mark_constant(v.value[2])
|
||||
elseif v.type ~= "nil" and v.type ~= "number" and v.type ~= "string" and v.type ~= "function reference" and v.type ~= "variable reference" then
|
||||
error("unknown type")
|
||||
if atypes[v.type] and atypes[v.type].mark_constant then
|
||||
atypes[v.type].mark_constant(v)
|
||||
if v.hash_id then v.hash_id = nil end -- no longer need to compare by id
|
||||
else
|
||||
error(("don't know how to mark type %s as constant"):format(v.type))
|
||||
end
|
||||
end,
|
||||
--- returns a variable's value, evaluating a pending expression if neccessary
|
||||
|
|
@ -311,6 +312,8 @@ common = {
|
|||
end
|
||||
end
|
||||
return true
|
||||
elseif a.constant and a.type == "map" then
|
||||
return common.hash(a) == common.hash(b)
|
||||
elseif a.constant and a.type == "object" then
|
||||
if a.value.class ~= b.value.class then
|
||||
return false
|
||||
|
|
@ -348,6 +351,35 @@ common = {
|
|||
return nil, ("no formatter for type %q"):format(val.type)
|
||||
end
|
||||
end,
|
||||
--- compute a hash for a value.
|
||||
-- A hash is a Lua string such as, given two values, they are considered equal by Anselme if and only if their hash are considered equal by Lua.
|
||||
-- Will generate random identifiers for mutable values (equality test by reference) in order for the identifier to stay the same accross checkpoints and
|
||||
-- other potential variable copies.
|
||||
-- str: if success
|
||||
-- nil, err: if error
|
||||
hash = function(val)
|
||||
if atypes[val.type] and atypes[val.type].hash then
|
||||
if atypes[val.type].mutable and not val.constant then
|
||||
if not val.hash_id then val.hash_id = random_identifier() end
|
||||
return ("mut(%s)"):format(val.hash_id)
|
||||
else
|
||||
return atypes[val.type].hash(val.value)
|
||||
end
|
||||
else
|
||||
return nil, ("no hasher for type %q"):format(val.type)
|
||||
end
|
||||
end,
|
||||
--- recompute all the hases in a map.
|
||||
-- str: if success
|
||||
-- nil, err: if error
|
||||
update_hashes = function(map)
|
||||
for k, v in pairs(map.value) do
|
||||
local hash, e = common.hash(v[1])
|
||||
if not hash then return nil, e end
|
||||
map[k] = nil
|
||||
map[hash] = v
|
||||
end
|
||||
end,
|
||||
--- convert anselme value to lua
|
||||
-- lua value: if success (may be nil!)
|
||||
-- nil, err: if error
|
||||
|
|
@ -373,7 +405,8 @@ common = {
|
|||
-- nil, err: if error
|
||||
eval_text = function(state, text)
|
||||
local l = {}
|
||||
common.eval_text_callback(state, text, function(str) table.insert(l, str) end)
|
||||
local s, e = common.eval_text_callback(state, text, function(str) table.insert(l, str) end)
|
||||
if not s then return nil, e end
|
||||
return table.concat(l)
|
||||
end,
|
||||
--- same as eval_text, but instead of building a Lua string, call callback for every evaluated part of the text
|
||||
|
|
@ -436,15 +469,14 @@ common = {
|
|||
end,
|
||||
--- tag management
|
||||
tags = {
|
||||
--- push new tags on top of the stack, from Anselme values
|
||||
--- push new tags on top of the stack, from Anselme values. val is expected to be a map.
|
||||
push = function(self, state, val)
|
||||
local new = { type = "list", value = {} }
|
||||
local new = { type = "map", value = {} }
|
||||
-- copy
|
||||
local last = self:current(state)
|
||||
for _, v in ipairs(last.value) do table.insert(new.value, v) end
|
||||
for k, v in pairs(last.value) do new.value[k] = v end
|
||||
-- append new values
|
||||
if val.type ~= "list" then val = { type = "list", value = { val } } end
|
||||
for _, v in ipairs(val.value) do table.insert(new.value, v) end
|
||||
for k, v in pairs(val.value) do new.value[k] = v end
|
||||
-- add
|
||||
table.insert(state.interpreter.tags, new)
|
||||
end,
|
||||
|
|
@ -458,7 +490,7 @@ common = {
|
|||
end,
|
||||
--- return current lua tags table
|
||||
current = function(self, state)
|
||||
return state.interpreter.tags[#state.interpreter.tags] or { type = "list", value = {} }
|
||||
return state.interpreter.tags[#state.interpreter.tags] or { type = "map", value = {} }
|
||||
end,
|
||||
--- returns length of tags stack
|
||||
len = function(self, state)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
local expression
|
||||
local to_lua, from_lua, eval_text, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, flatten_list, set_variable, scope, check_constraint
|
||||
local to_lua, from_lua, eval_text, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, flatten_list, set_variable, scope, check_constraint, hash
|
||||
|
||||
local run
|
||||
|
||||
|
|
@ -52,6 +52,30 @@ local function eval(state, exp)
|
|||
value = {}
|
||||
}
|
||||
end
|
||||
-- map defined in brackets
|
||||
elseif exp.type == "map_brackets" then
|
||||
-- get constructing list
|
||||
local list, e = eval(state, { type = "list_brackets", expression = exp.expression })
|
||||
if not list then return nil, e end
|
||||
-- make map
|
||||
local map = {}
|
||||
for i, v in ipairs(list.value) do
|
||||
local key, value
|
||||
if v.type == "pair" then
|
||||
key = v.value[1]
|
||||
value = v.value[2]
|
||||
else
|
||||
key = { type = "number", value = i }
|
||||
value = v
|
||||
end
|
||||
local h, err = hash(key)
|
||||
if not h then return nil, err end
|
||||
map[h] = { key, value }
|
||||
end
|
||||
return {
|
||||
type = "map",
|
||||
value = map
|
||||
}
|
||||
-- list defined using , operator
|
||||
elseif exp.type == "list" then
|
||||
local flat = flatten_list(exp)
|
||||
|
|
@ -142,7 +166,7 @@ local function eval(state, exp)
|
|||
}
|
||||
-- tag
|
||||
elseif exp.type == "#" then
|
||||
local right, righte = eval(state, exp.right)
|
||||
local right, righte = eval(state, { type = "map_brackets", expression = exp.right })
|
||||
if not right then return nil, righte end
|
||||
tags:push(state, right)
|
||||
local left, lefte = eval(state, exp.left)
|
||||
|
|
@ -165,12 +189,24 @@ local function eval(state, exp)
|
|||
}
|
||||
-- function
|
||||
elseif exp.type == "function call" then
|
||||
-- eval args: list_brackets
|
||||
-- eval args: map_brackets
|
||||
local args = {}
|
||||
local last_contiguous_positional = 0
|
||||
if exp.argument then
|
||||
local arg, arge = eval(state, exp.argument)
|
||||
if not arg then return nil, arge end
|
||||
args = arg.value
|
||||
-- map into args table
|
||||
for _, v in pairs(arg.value) do
|
||||
if v[1].type == "string" or v[1].type == "number" then
|
||||
args[v[1].value] = v[2]
|
||||
else
|
||||
return nil, ("unexpected key of type %s in argument map; keys must be string or number"):format(v[1].type)
|
||||
end
|
||||
end
|
||||
-- get length of contiguous positional arguments (#args may not be always be equal depending on implementation...)
|
||||
for i, _ in ipairs(args) do
|
||||
last_contiguous_positional = i
|
||||
end
|
||||
end
|
||||
-- function reference: call the referenced function
|
||||
local variants = exp.variants
|
||||
|
|
@ -191,13 +227,6 @@ local function eval(state, exp)
|
|||
end
|
||||
end
|
||||
end
|
||||
-- map named arguments
|
||||
local named_args = {}
|
||||
for i, arg in ipairs(args) do
|
||||
if arg.type == "pair" and arg.value[1].type == "string" then
|
||||
named_args[arg.value[1].value] = { i, arg.value[2] }
|
||||
end
|
||||
end
|
||||
-- eval assignment arg
|
||||
local assignment
|
||||
if exp.assignment then
|
||||
|
|
@ -222,21 +251,21 @@ local function eval(state, exp)
|
|||
for j, param in ipairs(fn.params) do
|
||||
local val
|
||||
-- named
|
||||
if param.alias and named_args[param.alias] then
|
||||
val = named_args[param.alias][2]
|
||||
used_args[named_args[param.alias][1]] = true
|
||||
elseif named_args[param.name] then
|
||||
val = named_args[param.name][2]
|
||||
used_args[named_args[param.name][1]] = true
|
||||
if param.alias and args[param.alias] then
|
||||
val = args[param.alias]
|
||||
used_args[param.alias] = true
|
||||
elseif args[param.name] then
|
||||
val = args[param.name]
|
||||
used_args[param.name] = true
|
||||
-- vararg
|
||||
elseif param.vararg then
|
||||
val = { type = "list", value = {} }
|
||||
for k=j, #args do
|
||||
for k=j, last_contiguous_positional do
|
||||
table.insert(val.value, args[k])
|
||||
used_args[k] = true
|
||||
end
|
||||
-- positional
|
||||
elseif args[j] and args[j].type ~= "pair" then
|
||||
elseif args[j] then
|
||||
val = args[j]
|
||||
used_args[j] = true
|
||||
end
|
||||
|
|
@ -264,8 +293,8 @@ local function eval(state, exp)
|
|||
end
|
||||
-- check for unused arguments
|
||||
if ok then
|
||||
for i, arg in ipairs(args) do
|
||||
if not used_args[i] then
|
||||
for key, arg in pairs(args) do
|
||||
if not used_args[key] then
|
||||
ok = false
|
||||
if arg.type == "pair" and arg.value[1].type == "string" then
|
||||
table.insert(tried_function_error_messages, ("%s: unexpected %s argument"):format(fn.pretty_signature, arg.value[1].value))
|
||||
|
|
@ -473,11 +502,10 @@ local function eval(state, exp)
|
|||
end
|
||||
-- no matching function found
|
||||
local args_txt = {}
|
||||
for _, arg in ipairs(args) do
|
||||
for key, arg in pairs(args) do
|
||||
local s = ""
|
||||
if arg.type == "pair" and arg.value[1].type == "string" then
|
||||
s = s .. ("%s="):format(arg.value[1].value)
|
||||
arg = arg.value[2]
|
||||
if type(key) == "string" or (type(key) == "number" and key > last_contiguous_positional) then
|
||||
s = s .. ("%s="):format(key)
|
||||
end
|
||||
s = s .. pretty_type(arg)
|
||||
table.insert(args_txt, s)
|
||||
|
|
@ -511,6 +539,6 @@ run = require((...):gsub("expression$", "interpreter")).run
|
|||
expression = require((...):gsub("interpreter%.expression$", "parser.expression"))
|
||||
flatten_list = require((...):gsub("interpreter%.expression$", "parser.common")).flatten_list
|
||||
local common = require((...):gsub("expression$", "common"))
|
||||
to_lua, from_lua, eval_text, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, set_variable, scope, check_constraint = common.to_lua, common.from_lua, common.eval_text, common.truthy, common.format, common.pretty_type, common.get_variable, common.tags, common.eval_text_callback, common.events, common.set_variable, common.scope, common.check_constraint
|
||||
to_lua, from_lua, eval_text, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, set_variable, scope, check_constraint, hash = common.to_lua, common.from_lua, common.eval_text, common.truthy, common.format, common.pretty_type, common.get_variable, common.tags, common.eval_text_callback, common.events, common.set_variable, common.scope, common.check_constraint, common.hash
|
||||
|
||||
return eval
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ common = {
|
|||
implicit_call = implicit_call, -- was call implicitely (no ! or parentheses)?
|
||||
variants = variants, -- list of potential variants
|
||||
argument = { -- wrap everything in a list literal to simplify later things (otherwise may be nil, single value, list constructor)
|
||||
type = "list_brackets",
|
||||
type = "map_brackets",
|
||||
expression = arg
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,21 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
type = "list_brackets",
|
||||
expression = exp
|
||||
})
|
||||
-- map parenthesis
|
||||
elseif s:match("^%b{}") then
|
||||
local content, r = s:match("^(%b{})(.*)$")
|
||||
content = content:gsub("^%{", ""):gsub("%}$", "")
|
||||
local exp
|
||||
if content:match("[^%s]") then
|
||||
local r_paren
|
||||
exp, r_paren = expression(content, state, namespace)
|
||||
if not exp then return nil, "invalid expression inside map parentheses: "..r_paren end
|
||||
if r_paren:match("[^%s]") then return nil, ("unexpected %q at end of map parenthesis expression"):format(r_paren) end
|
||||
end
|
||||
return expression(r, state, namespace, current_priority, {
|
||||
type = "map_brackets",
|
||||
expression = exp
|
||||
})
|
||||
-- identifier
|
||||
elseif s:match("^"..identifier_pattern) then
|
||||
local name, r = s:match("^("..identifier_pattern..")(.-)$")
|
||||
|
|
@ -182,7 +197,7 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
local err
|
||||
args, err = expression(content, state, namespace)
|
||||
if not args then return args, err end
|
||||
if err:match("[^%s]") then return nil, ("unexpected %q at end of argument list"):format(err) end
|
||||
if err:match("[^%s]") then return nil, ("unexpected %q at end of argument map"):format(err) end
|
||||
end
|
||||
else -- implicit call; will be changed if there happens to be a ! after in the suffix operator code
|
||||
implicit_call = true
|
||||
|
|
@ -267,7 +282,7 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
|||
local err
|
||||
args, err = expression(content, state, namespace)
|
||||
if not args then return args, err end
|
||||
if err:match("[^%s]") then return nil, ("unexpected %q at end of argument list"):format(err) end
|
||||
if err:match("[^%s]") then return nil, ("unexpected %q at end of argument map"):format(err) end
|
||||
end
|
||||
end
|
||||
-- add first argument
|
||||
|
|
|
|||
|
|
@ -332,11 +332,7 @@ local function parse_line(line, state, namespace, parent_function)
|
|||
r.type = "tag"
|
||||
r.child = true
|
||||
local expr = l:match("^%#(.*)$")
|
||||
if expr:match("[^%s]") then
|
||||
r.expression = expr
|
||||
else
|
||||
r.expression = "()"
|
||||
end
|
||||
r.expression = ("{%s}"):format(expr)
|
||||
-- return
|
||||
elseif l:match("^%@") then
|
||||
r.type = "return"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ return [[
|
|||
:number="number"
|
||||
:string="string"
|
||||
:list="list"
|
||||
:map="map"
|
||||
:pair="pair"
|
||||
:function reference="function reference"
|
||||
:variable reference="variable reference"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local truthy, anselme, compare, is_of_type, identifier_pattern, format_identifier, find, get_variable, mark_as_modified, set_variable, check_mutable, copy, mark_constant
|
||||
local truthy, anselme, compare, is_of_type, identifier_pattern, format_identifier, find, get_variable, mark_as_modified, set_variable, check_mutable, copy, mark_constant, hash
|
||||
|
||||
local lua_functions
|
||||
lua_functions = {
|
||||
|
|
@ -173,18 +173,24 @@ lua_functions = {
|
|||
["()(l::list, i::number)"] = {
|
||||
mode = "unannotated raw",
|
||||
value = function(l, i)
|
||||
return l.value[i.value] or { type = "nil", value = nil }
|
||||
local index = i.value
|
||||
if index < 0 then index = #l.value + 1 + index end
|
||||
if index > #l.value or index == 0 then return nil, "list index out of bounds" end
|
||||
return l.value[index] or { type = "nil", value = nil }
|
||||
end
|
||||
},
|
||||
["()(l::list, i::string)"] = {
|
||||
mode = "unannotated raw",
|
||||
["()(l::map, k)"] = {
|
||||
mode = "raw",
|
||||
value = function(l, i)
|
||||
for _, v in ipairs(l.value) do
|
||||
if v.type == "pair" and compare(v.value[1], i) then
|
||||
return v.value[2]
|
||||
end
|
||||
local lv = l.type == "annotated" and l.value[1] or l
|
||||
local h, err = hash(i)
|
||||
if not h then return nil, err end
|
||||
local v = lv.value[h]
|
||||
if v then
|
||||
return v[2]
|
||||
else
|
||||
return { type = "nil", value = nil }
|
||||
end
|
||||
return { type = "nil", value = nil }
|
||||
end
|
||||
},
|
||||
-- index assignment
|
||||
|
|
@ -194,30 +200,34 @@ lua_functions = {
|
|||
local lv = l.type == "annotated" and l.value[1] or l
|
||||
local iv = i.type == "annotated" and i.value[1] or i
|
||||
if lv.constant then return nil, "can't change the contents of a constant list" end
|
||||
lv.value[iv.value] = v
|
||||
local index = iv.value
|
||||
if index < 0 then index = #lv.value + 1 + index end
|
||||
if index > #lv.value + 1 or index == 0 then return nil, "list assignment index out of bounds" end
|
||||
lv.value[index] = v
|
||||
mark_as_modified(anselme.running.state, lv.value)
|
||||
return v
|
||||
end
|
||||
},
|
||||
["()(l::list, k::string) := v"] = {
|
||||
["()(l::map, k) := v::nil"] = {
|
||||
mode = "raw",
|
||||
value = function(l, k, v)
|
||||
local lv = l.type == "annotated" and l.value[1] or l
|
||||
local kv = k.type == "annotated" and k.value[1] or k
|
||||
if lv.constant then return nil, "can't change the contents of a constant list" end
|
||||
-- update index
|
||||
for _, x in ipairs(lv.value) do
|
||||
if x.type == "pair" and compare(x.value[1], kv) then
|
||||
x.value[2] = v
|
||||
mark_as_modified(anselme.running.state, x.value) -- FIXME i thought pairs were immutable...
|
||||
return v
|
||||
end
|
||||
end
|
||||
-- new index
|
||||
table.insert(lv.value, {
|
||||
type = "pair",
|
||||
value = { kv, v }
|
||||
})
|
||||
if lv.constant then return nil, "can't change the contents of a constant map" end
|
||||
local h, err = hash(k)
|
||||
if not h then return nil, err end
|
||||
lv.value[h] = nil
|
||||
mark_as_modified(anselme.running.state, lv.value)
|
||||
return v
|
||||
end
|
||||
},
|
||||
["()(l::map, k) := v"] = {
|
||||
mode = "raw",
|
||||
value = function(l, k, v)
|
||||
local lv = l.type == "annotated" and l.value[1] or l
|
||||
if lv.constant then return nil, "can't change the contents of a constant map" end
|
||||
local h, err = hash(k)
|
||||
if not h then return nil, err end
|
||||
lv.value[h] = { k, v }
|
||||
mark_as_modified(anselme.running.state, lv.value)
|
||||
return v
|
||||
end
|
||||
|
|
@ -435,7 +445,7 @@ local functions = {
|
|||
|
||||
package.loaded[...] = functions
|
||||
local icommon = require((...):gsub("stdlib%.functions$", "interpreter.common"))
|
||||
truthy, compare, is_of_type, get_variable, mark_as_modified, set_variable, check_mutable, mark_constant = icommon.truthy, icommon.compare, icommon.is_of_type, icommon.get_variable, icommon.mark_as_modified, icommon.set_variable, icommon.check_mutable, icommon.mark_constant
|
||||
truthy, compare, is_of_type, get_variable, mark_as_modified, set_variable, check_mutable, mark_constant, hash = icommon.truthy, icommon.compare, icommon.is_of_type, icommon.get_variable, icommon.mark_as_modified, icommon.set_variable, icommon.check_mutable, icommon.mark_constant, icommon.hash
|
||||
local pcommon = require((...):gsub("stdlib%.functions$", "parser.common"))
|
||||
identifier_pattern, format_identifier, find = pcommon.identifier_pattern, pcommon.format_identifier, pcommon.find
|
||||
anselme = require((...):gsub("stdlib%.functions$", "anselme"))
|
||||
|
|
|
|||
187
stdlib/types.lua
187
stdlib/types.lua
|
|
@ -1,4 +1,4 @@
|
|||
local format, to_lua, from_lua, events, anselme, escape
|
||||
local format, to_lua, from_lua, events, anselme, escape, hash, mark_constant, update_hashes
|
||||
|
||||
local types = {}
|
||||
types.lua = {
|
||||
|
|
@ -36,7 +36,9 @@ types.lua = {
|
|||
},
|
||||
table = {
|
||||
to_anselme = function(val)
|
||||
local is_map = false
|
||||
local l = {}
|
||||
local m = {}
|
||||
for _, v in ipairs(val) do
|
||||
local r, e = from_lua(v)
|
||||
if not r then return r, e end
|
||||
|
|
@ -44,20 +46,33 @@ types.lua = {
|
|||
end
|
||||
for k, v in pairs(val) do
|
||||
if not l[k] then
|
||||
is_map = true
|
||||
local kv, ke = from_lua(k)
|
||||
if not k then return k, ke end
|
||||
local vv, ve = from_lua(v)
|
||||
if not v then return v, ve end
|
||||
table.insert(l, {
|
||||
type = "pair",
|
||||
value = { kv, vv }
|
||||
})
|
||||
local h, err = hash(kv)
|
||||
if not h then return nil, err end
|
||||
m[h] = { kv, vv }
|
||||
end
|
||||
end
|
||||
return {
|
||||
type = "list",
|
||||
value = l
|
||||
}
|
||||
if is_map then
|
||||
for i, v in ipairs(l) do
|
||||
local key = { type = "number", value = i }
|
||||
local h, err = hash(key)
|
||||
if not h then return nil, err end
|
||||
m[h] = { key, v }
|
||||
end
|
||||
return {
|
||||
type = "map",
|
||||
value = m
|
||||
}
|
||||
else
|
||||
return {
|
||||
type = "list",
|
||||
value = l
|
||||
}
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +84,11 @@ types.anselme = {
|
|||
end,
|
||||
to_lua = function()
|
||||
return nil
|
||||
end
|
||||
end,
|
||||
hash = function()
|
||||
return "nil()"
|
||||
end,
|
||||
mark_constant = function() end,
|
||||
},
|
||||
number = {
|
||||
format = function(val)
|
||||
|
|
@ -77,7 +96,11 @@ types.anselme = {
|
|||
end,
|
||||
to_lua = function(val)
|
||||
return val
|
||||
end
|
||||
end,
|
||||
hash = function(val)
|
||||
return ("n(%s)"):format(val)
|
||||
end,
|
||||
mark_constant = function() end,
|
||||
},
|
||||
string = {
|
||||
format = function(val)
|
||||
|
|
@ -85,9 +108,14 @@ types.anselme = {
|
|||
end,
|
||||
to_lua = function(val)
|
||||
return val
|
||||
end
|
||||
end,
|
||||
hash = function(val)
|
||||
return ("s(%s)"):format(val)
|
||||
end,
|
||||
mark_constant = function() end,
|
||||
},
|
||||
list = {
|
||||
mutable = true,
|
||||
format = function(val)
|
||||
local l = {}
|
||||
for _, v in ipairs(val) do
|
||||
|
|
@ -99,25 +127,74 @@ types.anselme = {
|
|||
end,
|
||||
to_lua = function(val)
|
||||
local l = {}
|
||||
-- handle non-pair before pairs as LuaJIT's table.insert will always insert after the last element even if there are some nil before unlike PUC
|
||||
for _, v in ipairs(val) do
|
||||
if v.type ~= "pair" then
|
||||
local s, e = to_lua(v)
|
||||
if not s and e then return s, e end
|
||||
table.insert(l, s)
|
||||
end
|
||||
end
|
||||
for _, v in ipairs(val) do
|
||||
if v.type == "pair" then
|
||||
local k, ke = to_lua(v.value[1])
|
||||
if not k and ke then return k, ke end
|
||||
local x, xe = to_lua(v.value[2])
|
||||
if not x and xe then return x, xe end
|
||||
l[k] = x
|
||||
end
|
||||
local s, e = to_lua(v)
|
||||
if not s and e then return s, e end
|
||||
table.insert(l, s)
|
||||
end
|
||||
return l
|
||||
end,
|
||||
hash = function(val)
|
||||
local l = {}
|
||||
for _, v in ipairs(val) do
|
||||
local s, e = hash(v)
|
||||
if not s then return s, e end
|
||||
table.insert(l, s)
|
||||
end
|
||||
return ("l(%s)"):format(table.concat(l, ","))
|
||||
end,
|
||||
mark_constant = function(v)
|
||||
v.constant = true
|
||||
for _, item in ipairs(v.value) do
|
||||
mark_constant(item)
|
||||
end
|
||||
end
|
||||
},
|
||||
map = {
|
||||
mutable = true,
|
||||
format = function(val)
|
||||
local l = {}
|
||||
for _, v in pairs(val) do
|
||||
local ks, ke = format(v[1])
|
||||
if not ks then return ks, ke end
|
||||
local vs, ve = format(v[2])
|
||||
if not vs then return vs, ve end
|
||||
table.insert(l, ("%s=%s"):format(ks, vs))
|
||||
end
|
||||
table.sort(l)
|
||||
return ("{%s}"):format(table.concat(l, ", "))
|
||||
end,
|
||||
to_lua = function(val)
|
||||
local l = {}
|
||||
for _, v in pairs(val) do
|
||||
local kl, ke = to_lua(v[1])
|
||||
if not kl and ke then return kl, ke end
|
||||
local xl, xe = to_lua(v[2])
|
||||
if not xl and xe then return xl, xe end
|
||||
l[kl] = xl
|
||||
end
|
||||
return l
|
||||
end,
|
||||
hash = function(val)
|
||||
local l = {}
|
||||
for _, v in pairs(val) do
|
||||
local ks, ke = hash(v[1])
|
||||
if not ks then return ks, ke end
|
||||
local vs, ve = hash(v[2])
|
||||
if not vs then return vs, ve end
|
||||
table.insert(l, ("%s=%s"):format(ks, vs))
|
||||
end
|
||||
table.sort(l)
|
||||
return ("m(%s)"):format(table.concat(l, ","))
|
||||
end,
|
||||
mark_constant = function(v)
|
||||
v.constant = true
|
||||
for _, val in pairs(v.value) do
|
||||
mark_constant(val[1])
|
||||
mark_constant(val[2])
|
||||
end
|
||||
update_hashes(v)
|
||||
end,
|
||||
},
|
||||
pair = {
|
||||
format = function(val)
|
||||
|
|
@ -133,7 +210,18 @@ types.anselme = {
|
|||
local v, ve = to_lua(val[2])
|
||||
if not v and ve then return v, ve end
|
||||
return { [k] = v }
|
||||
end
|
||||
end,
|
||||
hash = function(val)
|
||||
local k, ke = hash(val[1])
|
||||
if not k then return k, ke end
|
||||
local v, ve = hash(val[2])
|
||||
if not v then return v, ve end
|
||||
return ("p(%s=%s)"):format(k, v)
|
||||
end,
|
||||
mark_constant = function(v)
|
||||
mark_constant(v.value[1])
|
||||
mark_constant(v.value[2])
|
||||
end,
|
||||
},
|
||||
annotated = {
|
||||
format = function(val)
|
||||
|
|
@ -147,7 +235,18 @@ types.anselme = {
|
|||
local k, ke = to_lua(val[1])
|
||||
if not k and ke then return k, ke end
|
||||
return k
|
||||
end
|
||||
end,
|
||||
hash = function(val)
|
||||
local k, ke = hash(val[1])
|
||||
if not k then return k, ke end
|
||||
local v, ve = hash(val[2])
|
||||
if not v then return v, ve end
|
||||
return ("a(%s::%s)"):format(k, v)
|
||||
end,
|
||||
mark_constant = function(v)
|
||||
mark_constant(v.value[1])
|
||||
mark_constant(v.value[2])
|
||||
end,
|
||||
},
|
||||
["function reference"] = {
|
||||
format = function(val)
|
||||
|
|
@ -157,27 +256,49 @@ types.anselme = {
|
|||
return ("&%s"):format(table.concat(val, ", "))
|
||||
end
|
||||
end,
|
||||
to_lua = nil
|
||||
to_lua = nil,
|
||||
hash = function(val)
|
||||
return ("&f(%s)"):format(table.concat(val, ", "))
|
||||
end,
|
||||
mark_constant = function() end,
|
||||
|
||||
},
|
||||
["variable reference"] = {
|
||||
format = function(val)
|
||||
return ("&%s"):format(val)
|
||||
end,
|
||||
to_lua = nil
|
||||
to_lua = nil,
|
||||
hash = function(val)
|
||||
return ("&v(%s)"):format(val)
|
||||
end,
|
||||
mark_constant = function() end,
|
||||
},
|
||||
object = {
|
||||
mutable = true,
|
||||
format = function(val)
|
||||
local attributes = {}
|
||||
for name, v in pairs(val.attributes) do
|
||||
table.insert(attributes, ("%s=%s"):format(name:gsub("^"..escape(val.class)..".", ""), format(v)))
|
||||
end
|
||||
if #attributes > 0 then
|
||||
table.sort(attributes)
|
||||
return ("%%%s(%s)"):format(val.class, table.concat(attributes, ", "))
|
||||
else
|
||||
return ("%%%s"):format(val.class)
|
||||
end
|
||||
end,
|
||||
to_lua = nil
|
||||
to_lua = nil,
|
||||
hash = function(val)
|
||||
local attributes = {}
|
||||
for name, v in pairs(val.attributes) do
|
||||
table.insert(attributes, ("%s=%s"):format(name:gsub("^"..escape(val.class)..".", ""), format(v)))
|
||||
end
|
||||
table.sort(attributes)
|
||||
return ("%%(%s;%s)"):format(val.class, table.concat(attributes, ","))
|
||||
end,
|
||||
mark_constant = function(v)
|
||||
v.constant = true
|
||||
end,
|
||||
},
|
||||
-- internal types
|
||||
["event buffer"] = {
|
||||
|
|
@ -191,7 +312,7 @@ types.anselme = {
|
|||
|
||||
package.loaded[...] = types
|
||||
local common = require((...):gsub("stdlib%.types$", "interpreter.common"))
|
||||
format, to_lua, from_lua, events = common.format, common.to_lua, common.from_lua, common.events
|
||||
format, to_lua, from_lua, events, hash, mark_constant, update_hashes = common.format, common.to_lua, common.from_lua, common.events, common.hash, common.mark_constant, common.update_hashes
|
||||
anselme = require((...):gsub("stdlib%.types$", "anselme"))
|
||||
escape = require((...):gsub("stdlib%.types$", "parser.common")).escape
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
:person = "personne"
|
||||
|
||||
$ Person(name, age)
|
||||
@[name=name, age=age]::person
|
||||
@{name=name, age=age}::person
|
||||
|
||||
:abject = Person("Darmanin", 38)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,16 @@
|
|||
|
||||
{x}
|
||||
|
||||
{x("foo") := "a"}
|
||||
{x(2) := 5}
|
||||
|
||||
{x}
|
||||
|
||||
{x("bar") := "b"}
|
||||
{x(-1) := 12}
|
||||
|
||||
{x}
|
||||
|
||||
{x("foo") := "c"}
|
||||
{x(3) := 99}
|
||||
|
||||
{x}
|
||||
|
||||
{x(5) := 0}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ _[32]={}
|
|||
_[31]={}
|
||||
_[30]={}
|
||||
_[29]={}
|
||||
_[28]={tags=_[37],text="[3, 2, foo=c, bar=b]"}
|
||||
_[27]={tags=_[36],text="c"}
|
||||
_[26]={tags=_[35],text="[3, 2, foo=a, bar=b]"}
|
||||
_[25]={tags=_[34],text="b"}
|
||||
_[24]={tags=_[33],text="[3, 2, foo=a]"}
|
||||
_[23]={tags=_[32],text="a"}
|
||||
_[28]={tags=_[37],text="[3, 12, 99]"}
|
||||
_[27]={tags=_[36],text="99"}
|
||||
_[26]={tags=_[35],text="[3, 12]"}
|
||||
_[25]={tags=_[34],text="12"}
|
||||
_[24]={tags=_[33],text="[3, 5]"}
|
||||
_[23]={tags=_[32],text="5"}
|
||||
_[22]={tags=_[31],text="[3, 2]"}
|
||||
_[21]={tags=_[30],text="3"}
|
||||
_[20]={tags=_[29],text="[1, 2]"}
|
||||
|
|
@ -26,7 +26,7 @@ _[14]={_[23]}
|
|||
_[13]={_[22]}
|
||||
_[12]={_[21]}
|
||||
_[11]={_[20]}
|
||||
_[10]={"return"}
|
||||
_[10]={"error","list assignment index out of bounds; in Lua function \"()\"; at test/tests/list assignement.ans:21"}
|
||||
_[9]={"text",_[19]}
|
||||
_[8]={"text",_[18]}
|
||||
_[7]={"text",_[17]}
|
||||
|
|
@ -52,27 +52,27 @@ return {_[1],_[2],_[3],_[4],_[5],_[6],_[7],_[8],_[9],_[10]}
|
|||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "a"
|
||||
text = "5"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "[3, 2, foo=a]"
|
||||
text = "[3, 5]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "b"
|
||||
text = "12"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "[3, 2, foo=a, bar=b]"
|
||||
text = "[3, 12]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "c"
|
||||
text = "99"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "[3, 2, foo=c, bar=b]"
|
||||
text = "[3, 12, 99]"
|
||||
} } }
|
||||
{ "return" }
|
||||
{ "error", 'list assignment index out of bounds; in Lua function "()"; at test/tests/list assignement.ans:21' }
|
||||
]]--
|
||||
11
test/tests/list index.ans
Normal file
11
test/tests/list index.ans
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
:x = [1,2,3]
|
||||
|
||||
{x}
|
||||
|
||||
{x(1)} == {x(-3)}
|
||||
|
||||
{x(2)} == {x(-2)}
|
||||
|
||||
{x(3)} == {x(-1)}
|
||||
|
||||
{x(-4)}
|
||||
68
test/tests/list index.lua
Normal file
68
test/tests/list index.lua
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
local _={}
|
||||
_[29]={}
|
||||
_[28]={}
|
||||
_[27]={}
|
||||
_[26]={}
|
||||
_[25]={}
|
||||
_[24]={}
|
||||
_[23]={}
|
||||
_[22]={}
|
||||
_[21]={}
|
||||
_[20]={}
|
||||
_[19]={text="3",tags=_[29]}
|
||||
_[18]={text=" == ",tags=_[28]}
|
||||
_[17]={text="3",tags=_[27]}
|
||||
_[16]={text="2",tags=_[26]}
|
||||
_[15]={text=" == ",tags=_[25]}
|
||||
_[14]={text="2",tags=_[24]}
|
||||
_[13]={text="1",tags=_[23]}
|
||||
_[12]={text=" == ",tags=_[22]}
|
||||
_[11]={text="1",tags=_[21]}
|
||||
_[10]={text="[1, 2, 3]",tags=_[20]}
|
||||
_[9]={_[17],_[18],_[19]}
|
||||
_[8]={_[14],_[15],_[16]}
|
||||
_[7]={_[11],_[12],_[13]}
|
||||
_[6]={_[10]}
|
||||
_[5]={"error","list index out of bounds; in Lua function \"()\"; at test/tests/list index.ans:11"}
|
||||
_[4]={"text",_[9]}
|
||||
_[3]={"text",_[8]}
|
||||
_[2]={"text",_[7]}
|
||||
_[1]={"text",_[6]}
|
||||
return {_[1],_[2],_[3],_[4],_[5]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "[1, 2, 3]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "1"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "2"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "3"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "3"
|
||||
} } }
|
||||
{ "error", 'list index out of bounds; in Lua function "()"; at test/tests/list index.ans:11' }
|
||||
]]--
|
||||
20
test/tests/map assignement.ans
Normal file
20
test/tests/map assignement.ans
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
:x = {1,2}
|
||||
|
||||
{x}
|
||||
|
||||
{x(1) := 3}
|
||||
|
||||
{x}
|
||||
|
||||
{x("foo") := "a"}
|
||||
|
||||
{x}
|
||||
|
||||
{x("bar") := "b"}
|
||||
|
||||
{x}
|
||||
|
||||
{x("foo") := "c"}
|
||||
|
||||
{x}
|
||||
|
||||
78
test/tests/map assignement.lua
Normal file
78
test/tests/map assignement.lua
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
local _={}
|
||||
_[37]={}
|
||||
_[36]={}
|
||||
_[35]={}
|
||||
_[34]={}
|
||||
_[33]={}
|
||||
_[32]={}
|
||||
_[31]={}
|
||||
_[30]={}
|
||||
_[29]={}
|
||||
_[28]={text="{1=3, 2=2, bar=b, foo=c}",tags=_[37]}
|
||||
_[27]={text="c",tags=_[36]}
|
||||
_[26]={text="{1=3, 2=2, bar=b, foo=a}",tags=_[35]}
|
||||
_[25]={text="b",tags=_[34]}
|
||||
_[24]={text="{1=3, 2=2, foo=a}",tags=_[33]}
|
||||
_[23]={text="a",tags=_[32]}
|
||||
_[22]={text="{1=3, 2=2}",tags=_[31]}
|
||||
_[21]={text="3",tags=_[30]}
|
||||
_[20]={text="{1=1, 2=2}",tags=_[29]}
|
||||
_[19]={_[28]}
|
||||
_[18]={_[27]}
|
||||
_[17]={_[26]}
|
||||
_[16]={_[25]}
|
||||
_[15]={_[24]}
|
||||
_[14]={_[23]}
|
||||
_[13]={_[22]}
|
||||
_[12]={_[21]}
|
||||
_[11]={_[20]}
|
||||
_[10]={"return"}
|
||||
_[9]={"text",_[19]}
|
||||
_[8]={"text",_[18]}
|
||||
_[7]={"text",_[17]}
|
||||
_[6]={"text",_[16]}
|
||||
_[5]={"text",_[15]}
|
||||
_[4]={"text",_[14]}
|
||||
_[3]={"text",_[13]}
|
||||
_[2]={"text",_[12]}
|
||||
_[1]={"text",_[11]}
|
||||
return {_[1],_[2],_[3],_[4],_[5],_[6],_[7],_[8],_[9],_[10]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "{1=1, 2=2}"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "3"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "{1=3, 2=2}"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "a"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "{1=3, 2=2, foo=a}"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "b"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "{1=3, 2=2, bar=b, foo=a}"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "c"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "{1=3, 2=2, bar=b, foo=c}"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
29
test/tests/map index accross checkpoints.ans
Normal file
29
test/tests/map index accross checkpoints.ans
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
:x = {4}
|
||||
|
||||
x={x}
|
||||
|
||||
:a = {1,2,3,(x)=4}
|
||||
|
||||
:c = a
|
||||
|
||||
1={a==c}
|
||||
|
||||
a(x)={a(x)}
|
||||
|
||||
§ ch a
|
||||
|
||||
a(x)={a(x)}
|
||||
|
||||
§ ch b
|
||||
|
||||
~ x(2) := 3
|
||||
|
||||
a(x)={a(x)}
|
||||
|
||||
§ ch c
|
||||
|
||||
a(x)={a(x)}
|
||||
|
||||
~ x:={4}
|
||||
|
||||
no={a(x)}
|
||||
92
test/tests/map index accross checkpoints.lua
Normal file
92
test/tests/map index accross checkpoints.lua
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
local _={}
|
||||
_[41]={}
|
||||
_[40]={}
|
||||
_[39]={}
|
||||
_[38]={}
|
||||
_[37]={}
|
||||
_[36]={}
|
||||
_[35]={}
|
||||
_[34]={}
|
||||
_[33]={}
|
||||
_[32]={}
|
||||
_[31]={}
|
||||
_[30]={}
|
||||
_[29]={}
|
||||
_[28]={tags=_[41],text="no="}
|
||||
_[27]={tags=_[40],text="4"}
|
||||
_[26]={tags=_[39],text="a(x)="}
|
||||
_[25]={tags=_[38],text="4"}
|
||||
_[24]={tags=_[37],text="a(x)="}
|
||||
_[23]={tags=_[36],text="4"}
|
||||
_[22]={tags=_[35],text="a(x)="}
|
||||
_[21]={tags=_[34],text="4"}
|
||||
_[20]={tags=_[33],text="a(x)="}
|
||||
_[19]={tags=_[32],text="1"}
|
||||
_[18]={tags=_[31],text="1="}
|
||||
_[17]={tags=_[30],text="{1=4}"}
|
||||
_[16]={tags=_[29],text="x="}
|
||||
_[15]={_[28]}
|
||||
_[14]={_[26],_[27]}
|
||||
_[13]={_[24],_[25]}
|
||||
_[12]={_[22],_[23]}
|
||||
_[11]={_[20],_[21]}
|
||||
_[10]={_[18],_[19]}
|
||||
_[9]={_[16],_[17]}
|
||||
_[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 = "x="
|
||||
}, {
|
||||
tags = {},
|
||||
text = "{1=4}"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "1="
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "a(x)="
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "a(x)="
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "a(x)="
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "a(x)="
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "no="
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
7
test/tests/map index.ans
Normal file
7
test/tests/map index.ans
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
:t = {ahah=23,k=23,12}
|
||||
|
||||
{t} == \{3=12, ahah=23, k=23}
|
||||
|
||||
{t(3)} == 12
|
||||
|
||||
{t("ahah")} == 23
|
||||
45
test/tests/map index.lua
Normal file
45
test/tests/map index.lua
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
local _={}
|
||||
_[19]={}
|
||||
_[18]={}
|
||||
_[17]={}
|
||||
_[16]={}
|
||||
_[15]={}
|
||||
_[14]={}
|
||||
_[13]={tags=_[19],text=" == 23"}
|
||||
_[12]={tags=_[18],text="23"}
|
||||
_[11]={tags=_[17],text=" == 12"}
|
||||
_[10]={tags=_[16],text="12"}
|
||||
_[9]={tags=_[15],text=" == {3=12, ahah=23, k=23}"}
|
||||
_[8]={tags=_[14],text="{3=12, ahah=23, k=23}"}
|
||||
_[7]={_[12],_[13]}
|
||||
_[6]={_[10],_[11]}
|
||||
_[5]={_[8],_[9]}
|
||||
_[4]={"return"}
|
||||
_[3]={"text",_[7]}
|
||||
_[2]={"text",_[6]}
|
||||
_[1]={"text",_[5]}
|
||||
return {_[1],_[2],_[3],_[4]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "{3=12, ahah=23, k=23}"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == {3=12, ahah=23, k=23}"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "12"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == 12"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "23"
|
||||
}, {
|
||||
tags = {},
|
||||
text = " == 23"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
Loading…
Add table
Add a link
Reference in a new issue