diff --git a/anselme/ast/ArgumentTuple.lua b/anselme/ast/ArgumentTuple.lua index 66b7803..41219db 100644 --- a/anselme/ast/ArgumentTuple.lua +++ b/anselme/ast/ArgumentTuple.lua @@ -159,7 +159,7 @@ ArgumentTuple = ast.abstract.Node { -- type check (assume ok for default values) if param.type_check and arg ~= param.default then local r = param.type_check:call(state, ArgumentTuple:new(arg)) - if not r:truthy() then return false, ("type check failure for parameter %s in function %s"):format(param.identifier:format(state), params:format(state)) end + if not r:truthy() then return false, ("type check failure for parameter %s"):format(param.identifier:format(state)) end if Number:is(r) then specificity = specificity + r.number else diff --git a/anselme/ast/Environment.lua b/anselme/ast/Environment.lua index ab8eacd..1a2b31f 100644 --- a/anselme/ast/Environment.lua +++ b/anselme/ast/Environment.lua @@ -19,6 +19,7 @@ local VariableMetadata = ast.abstract.Runtime { if self.symbol.alias then return v:call(state, ArgumentTuple:new()) else + v.from_symbol = self.symbol return v end end, @@ -31,11 +32,11 @@ local VariableMetadata = ast.abstract.Runtime { end, set = function(self, state, value) if self.symbol.constant then - error(("trying to change the value of constant %s"):format(self.symbol.string), 0) + error(("trying to change the value of constant %s"):format(self.symbol.string:format(state)), 0) end if self.symbol.type_check then local r = self.symbol.type_check:call(state, ArgumentTuple:new(value)) - if not r:truthy() then error(("type check failure for %s; %s does not satisfy %s"):format(self.symbol.string, value, self.symbol.type_check), 0) end + if not r:truthy() then error(("type check failure for %s; %s does not satisfy %s"):format(self.symbol.string:format(state), value, self.symbol.type_check:format(state)), 0) end end if self.symbol.alias then local assign_args = ArgumentTuple:new() @@ -223,7 +224,9 @@ local Environment = ast.abstract.Runtime { local e = self while e.parent do e = e.parent - d = d + 1 + if not (e.partial or e.export) then -- only count full layers + d = d + 1 + end end return d end, diff --git a/anselme/ast/Function.lua b/anselme/ast/Function.lua index 77c3e4d..71e778b 100644 --- a/anselme/ast/Function.lua +++ b/anselme/ast/Function.lua @@ -39,9 +39,9 @@ Function = Overloadable { _format = function(self, ...) if self.parameters.assignment then - return "$"..self.parameters:format(...).."; "..self.expression:format_right(...) + return "$"..self.parameters:format_short(...).."; "..self.expression:format_right(...) else - return "$"..self.parameters:format(...).." "..self.expression:format_right(...) + return "$"..self.parameters:format_short(...).." "..self.expression:format_right(...) end end, _format_priority = function(self) @@ -77,7 +77,7 @@ Function = Overloadable { return args:match_parameter_tuple(state, self.parameters) end, format_signature = function(self, state) - return self.parameters:format(state) + return "$"..self.parameters:format_short(state) end, hash_signature = function(self) return self.parameters:hash() diff --git a/anselme/ast/LuaFunction.lua b/anselme/ast/LuaFunction.lua index 820c489..5ee4046 100644 --- a/anselme/ast/LuaFunction.lua +++ b/anselme/ast/LuaFunction.lua @@ -41,7 +41,7 @@ LuaFunction = ast.abstract.Runtime(Overloadable) { return args:match_parameter_tuple(state, self.parameters) end, format_signature = function(self, state) - return self.parameters:format(state) + return "$"..self.parameters:format_short(state) end, hash_signature = function(self) return self.parameters:hash() diff --git a/anselme/ast/Overload.lua b/anselme/ast/Overload.lua index 6400e9d..400cd50 100644 --- a/anselme/ast/Overload.lua +++ b/anselme/ast/Overload.lua @@ -23,12 +23,12 @@ Overload = ast.abstract.Node { end, _format = function(self, ...) - local s = "overload<" + local s = "overload([" for i, e in ipairs(self.list) do s = s .. e:format(...) if i < #self.list then s = s .. ", " end end - return s..">" + return s.."])" end, traverse = function(self, fn, ...) @@ -50,18 +50,18 @@ Overload = ast.abstract.Node { if secondary_specificity > success_secondary_specificity then success, success_specificity, success_secondary_specificity = fn, specificity, secondary_specificity elseif secondary_specificity == success_secondary_specificity then - return nil, ("more than one function match %s, matching functions were at least (specificity %s.%s):\n\t• %s\n\t• %s"):format(args:format(state), specificity, secondary_specificity, fn:format_signature(state), success:format_signature(state)) + return nil, ("more than one function match arguments %s, matching functions were at least (specificity %s.%s):\n\t• %s (from %s)\n\t• %s (from %s)"):format(args:format(state), specificity, secondary_specificity, fn:format_signature(state), fn.source, success:format_signature(state), success.source) end end -- no need to add error message for less specific function since we already should have at least one success elseif not success then - table.insert(failure, fn:format_signature(state) .. ": " .. secondary_specificity) + table.insert(failure, ("%s (from %s):\n\t\t%s"):format(fn:format_signature(state), fn.source, secondary_specificity)) end end if success then return success, args else - return nil, ("no function match %s, possible functions were:\n\t• %s"):format(args:format(state), table.concat(failure, "\n\t• ")) + return nil, ("no function match arguments %s, possible functions were:\n\t• %s"):format(args:format(state), table.concat(failure, "\n\t• ")) end end } diff --git a/anselme/ast/Tuple.lua b/anselme/ast/Tuple.lua index 87687b1..7d8448f 100644 --- a/anselme/ast/Tuple.lua +++ b/anselme/ast/Tuple.lua @@ -66,7 +66,7 @@ Tuple = ast.abstract.Node { if index > #self.list or index == 0 then error("tuple index out of bounds", 0) end self.list[index] = value end, - len = function(self) + len = function(self) return #self.list end, iter = function(self) diff --git a/anselme/ast/abstract/Node.lua b/anselme/ast/abstract/Node.lua index 79dceeb..2d1e0e2 100644 --- a/anselme/ast/abstract/Node.lua +++ b/anselme/ast/abstract/Node.lua @@ -134,7 +134,7 @@ Node = class { end, -- generate a list of translatable nodes that appear in this node - -- should only be called on non-runtime nodes + -- should only be called on non-evaluated nodes -- if a node is translatable, redefine this to add it to the table - note that it shouldn't call :traverse or :list_translatable on its children, as nested translations should not be needed list_translatable = function(self, t) t = t or {} @@ -235,7 +235,7 @@ Node = class { if dispatched then return dispatched:call_dispatched(state, dispatched_arg) else - error(("can't call %s %s: %s"):format(self.type, self:format(state), dispatched_arg), 0) + error(("can't call %s %s: %s"):format(self.type, self:format_short(state), dispatched_arg), 0) end end, -- find a function that can be called with the given arguments @@ -300,21 +300,26 @@ Node = class { end, -- return a pretty string representation of the node. - -- for non-runtime nodes (what was generated by a parse without any evaluation), this should return valid Anselme code that is functionnally equivalent to the parsed code. note that it currently does not preserve comment. + -- for non-evaluated nodes, this should return valid Anselme code that is functionnally equivalent to the parsed code. note that it currently does not preserve comment. -- assuming nothing was mutated in the node, the returned string should remain the same - so if make sure the function is deterministic, e.g. sort if you use pairs() -- redefine _format, not this - note that _format is a mandary method for all nodes. - -- state is optional and should only be relevant for runtime nodes; if specified, only show what is relevant for the current branch. + -- state is optional and should only have an effect on evaluated nodes; if specified, only show what is relevant for the current branch. -- indentation_level and parent_priority are optional value that respectively keep track in nester :format calls of the indentation level (number) and parent operator priority (number); if the node has a strictly lower priority than the parent node, parentheses will be added -- also remember that execution is done left-to-right, so in case of priority equality, all is fine if the term appear left of the operator, but parentheses will need to be added if the term is right of the operator - so make sure to call :format_right for such cases + -- short_mode, if set to true, will use the identifier the expression was last retrieved from instead of calling :_format. Should have no effect on non-evaluated nodes. -- (:format is not cached as even immutable nodes may contain mutable children) - format = function(self, state, parent_priority, indentation_level) + format = function(self, state, parent_priority, indentation_level, short_mode, right) indentation_level = indentation_level or 0 parent_priority = parent_priority or 0 - local s = self:_format(state, self:format_priority(), indentation_level) - - if self:format_priority() < parent_priority then - s = ("(%s)"):format(s) + local s + if short_mode and self.from_symbol then + s = self.from_symbol.string + else + s = self:_format(state, self:format_priority(), indentation_level, short_mode) + if self:format_priority() < parent_priority or (right and self:format_priority() <= parent_priority) then + s = ("(%s)"):format(s) + end end local indentation = ("\t"):rep(indentation_level) @@ -323,23 +328,15 @@ Node = class { return s end, -- same as :format, but should be called only for nodes right of the current operator - format_right = function(self, state, parent_priority, indentation_level) - indentation_level = indentation_level or 0 - parent_priority = parent_priority or 0 - - local s = self:_format(state, self:format_priority(), indentation_level) - - if self:format_priority() <= parent_priority then - s = ("(%s)"):format(s) - end - - local indentation = (" "):rep(indentation_level) - s = indentation..s:gsub("\n", "\n"..indentation) - - return s + format_right = function(self, state, parent_priority, indentation_level, short_mode) + return self:format(state, parent_priority, indentation_level, short_mode, true) + end, + -- same as :format, but enable short mode + format_short = function(self, state, parent_priority, indentation_level) + return self:format(state, parent_priority, indentation_level, true) end, -- redefine this to provide a custom :format. returns a string. - _format = function(self, state, self_priority, identation) + _format = function(self, state, self_priority, identation, short_mode) error("format not implemented for "..self.type) end, -- compute the priority of the node that will be used in :format to add eventually needed parentheses. @@ -356,6 +353,7 @@ Node = class { return math.huge -- by default, assumes primary node, i.e. never wrap in parentheses end, _format_priority_cache = nil, -- cached priority + from_symbol = nil, -- last symbol this node was retrived from -- return Lua value -- this should probably be only called on a Node that is already evaluated diff --git a/anselme/ast/abstract/Overloadable.lua b/anselme/ast/abstract/Overloadable.lua index 7e0cf55..cdda730 100644 --- a/anselme/ast/abstract/Overloadable.lua +++ b/anselme/ast/abstract/Overloadable.lua @@ -12,11 +12,11 @@ return ast.abstract.Node { error("not implemented for "..self.type) end, - -- return string + -- return string, friendly representation of the function signature format_signature = function(self, state) error("not implemented for "..self.type) end, - -- return string + -- return string, unique hash for this function signature hash_signature = function(self) error("not implemented for "..self.type) end, diff --git a/anselme/stdlib/function.lua b/anselme/stdlib/function.lua index a8c9158..d35c8f6 100644 --- a/anselme/stdlib/function.lua +++ b/anselme/stdlib/function.lua @@ -1,5 +1,5 @@ local ast = require("anselme.ast") -local Nil, Boolean, Definition, Return = ast.Nil, ast.Boolean, ast.Definition, ast.Return +local Nil, Boolean, Definition, Return, Overload, Overloadable = ast.Nil, ast.Boolean, ast.Definition, ast.Return, ast.Overload, ast.abstract.Overloadable local assert0 = require("anselme.common").assert0 return { @@ -17,7 +17,19 @@ return { }, { - "_._", "(c::function, s::string)", + "overload", "(l::is sequence)", + function(state, l) + local r = Overload:new() + for _, fn in l:iter(state) do + assert0(Overloadable:issub(fn), ("trying to add a non overloadable %s to an overload"):format(fn:format(state))) + r:insert(fn) + end + return r + end + }, + + { + "_._", "(c::is function, s::is string)", function(state, c, s) local identifier = s:to_identifier() assert0(c.scope:defined(state, identifier), ("no variable %q defined in closure"):format(s.string)) diff --git a/test/results/exported variable nested.ans b/test/results/exported variable nested.ans index d355df6..8f7dcea 100644 --- a/test/results/exported variable nested.ans +++ b/test/results/exported variable nested.ans @@ -5,7 +5,7 @@ --- text --- | {}"" {}"42" {}"" | --- error --- -identifier "z" is undefined in branch 7dfcaa5b-2163-4f36-116ed-c4ab6bc8d28b +identifier "z" is undefined in branch 46991f07-7340-4104-9f35-c1fb62e95088 ↳ from test/tests/exported variable nested.ans:12:3 in identifier: z ↳ from test/tests/exported variable nested.ans:12:1 in text interpolation: | {z} | ↳ from ? in block: :f = ($() _)… diff --git a/test/results/for invalid iterator.ans b/test/results/for invalid iterator.ans index 23f29df..edf81d0 100644 --- a/test/results/for invalid iterator.ans +++ b/test/results/for invalid iterator.ans @@ -1,14 +1,18 @@ --# run #-- --- error --- -can't call overload overload<($(table::($(x) )) _), ($(tuple::($(x) type(x) == "tuple" | type(x) == "list")) _), ($(range::($(x) type(x) == t)) _), ($(s::($(x) )) )>: no function match (42), possible functions were: - • (table::($(x) )): type check failure for parameter table in function (table::($(x) )) - • (tuple::($(x) type(x) == "tuple" | type(x) == "list")): type check failure for parameter tuple in function (tuple::($(x) type(x) == "tuple" | type(x) == "list")) - • (range::($(x) type(x) == t)): type check failure for parameter range in function (range::($(x) type(x) == t)) - • (s::($(x) )): type check failure for parameter s in function (s::($(x) )) - ↳ from for.ans:3:18 in call: iter(var) - ↳ from for.ans:3:12 in definition: :iterator = iter(var) - ↳ from for.ans:2:1 in block: :iterator = iter(var)… - ↳ from for.ans:2:68 in call: _ +can't call overload iter: no function match arguments (42), possible functions were: + • $(table::is table) (from stdlib/for.ans:46:1): + type check failure for parameter table + • $(tuple::is sequence) (from stdlib/for.ans:37:1): + type check failure for parameter tuple + • $(range::is range) (from stdlib/for.ans:19:1): + type check failure for parameter range + • $(s::is struct) (from stdlib/for.ans:3:14): + type check failure for parameter s + ↳ from stdlib/for.ans:3:18 in call: iter(var) + ↳ from stdlib/for.ans:3:12 in definition: :iterator = iter(var) + ↳ from stdlib/for.ans:2:1 in block: :iterator = iter(var)… + ↳ from stdlib/for.ans:2:71 in call: _ ↳ from test/tests/for invalid iterator.ans:1:4 in call: for(:x, 42) ↳ from ? in block: for(:x, 42)… --# saved #-- diff --git a/test/results/function args arity check fail.ans b/test/results/function args arity check fail.ans index dea819f..a559e70 100644 --- a/test/results/function args arity check fail.ans +++ b/test/results/function args arity check fail.ans @@ -1,6 +1,6 @@ --# run #-- --- error --- -can't call function $(a, b) _: expected 2 arguments, received 1 +can't call function f: expected 2 arguments, received 1 ↳ from test/tests/function args arity check fail.ans:4:2 in call: f("ok") ↳ from ? in block: :f = ($(a, b) _)… --# saved #-- diff --git a/test/results/function conflict.ans b/test/results/function conflict.ans index 3b84880..b4bf4f2 100644 --- a/test/results/function conflict.ans +++ b/test/results/function conflict.ans @@ -1,6 +1,6 @@ --# run #-- --- error --- -a function with parameters (a, b) is already defined in the overload +a function with parameters $(a, b) is already defined in the overload ↳ from test/tests/function conflict.ans:5:1 in definition: :f = ($(a, b) 0) ↳ from ? in block: :f = ($(a, b) 0)… --# saved #-- diff --git a/test/results/function custom type dispatch error.ans b/test/results/function custom type dispatch error.ans index 69da3e9..7124d50 100644 --- a/test/results/function custom type dispatch error.ans +++ b/test/results/function custom type dispatch error.ans @@ -4,9 +4,11 @@ --- text --- | {}"" {}"idk" {}" is esperanto" | --- error --- -can't call overload overload<($(name::($(x) type(x) == t)) _), ($(name::($(x) type(x) == t)) _)>: no function match (type(5, "nope")), possible functions were: - • (name::($(x) type(x) == t)): type check failure for parameter name in function (name::($(x) type(x) == t)) - • (name::($(x) type(x) == t)): type check failure for parameter name in function (name::($(x) type(x) == t)) +can't call overload a: no function match arguments (type(5, "nope")), possible functions were: + • $(name::($(x) type(x) == t)) (from test/tests/function custom type dispatch error.ans:7:1): + type check failure for parameter name + • $(name::($(x) type(x) == t)) (from test/tests/function custom type dispatch error.ans:4:1): + type check failure for parameter name ↳ from test/tests/function custom type dispatch error.ans:14:2 in call: a(type(5, "nope")) ↳ from ? in block: :french name = "french name"… --# saved #-- diff --git a/test/results/function random.ans b/test/results/function random.ans index 15a5220..7cc973b 100644 --- a/test/results/function random.ans +++ b/test/results/function random.ans @@ -2,14 +2,14 @@ --- text --- | {}"a" | --- text --- +| {}"b" | +--- text --- | {}"c" | --- text --- | {}"a" | --- text --- -| {}"a" | ---- text --- -| {}"c" | +| {}"b" | --- return --- () --# saved #-- -{"a.checkpoint":false, "a.run":3, "c.checkpoint":false, "c.run":2} \ No newline at end of file +{"a.checkpoint":false, "a.run":2, "b.checkpoint":false, "b.run":2, "c.checkpoint":false, "c.run":1} \ No newline at end of file diff --git a/test/results/function scope wrong.ans b/test/results/function scope wrong.ans index 7bfde1c..f716317 100644 --- a/test/results/function scope wrong.ans +++ b/test/results/function scope wrong.ans @@ -1,6 +1,6 @@ --# run #-- --- error --- -identifier "b" is undefined in branch 7dfcaa5b-2163-4f36-116ed-c4ab6bc8d28b +identifier "b" is undefined in branch 46991f07-7340-4104-9f35-c1fb62e95088 ↳ from test/tests/function scope wrong.ans:4:7 in identifier: b ↳ from test/tests/function scope wrong.ans:4:1 in text interpolation: | a: {b} | ↳ from ? in block: :a = ($() _)… diff --git a/test/results/function separate variable from variants.ans b/test/results/function separate variable from variants.ans index 9b36243..a22c3bd 100644 --- a/test/results/function separate variable from variants.ans +++ b/test/results/function separate variable from variants.ans @@ -1,12 +1,18 @@ --# run #-- --- error --- -can't call overload overload<($(s::($(x) type(x) == t), k::($(x) )) = val; _), ($(s::($(x) type(x) == t), k::($(x) )) = val; _), ($(s::($(x) type(x) == t), k::($(x) )) _), ($(c::($(x) ), s::($(x) )) = v; ), ($(c::($(x) ), s::($(x) )) = v; ), ($(c::($(x) ), s::($(x) )) )>: no function match (overload<($(b) _), ($(x) _), ($() _)>, "a"), possible functions were: - • (s::($(x) type(x) == t), k::($(x) )) = val: expected 3 arguments, received 2 - • (s::($(x) type(x) == t), k::($(x) )) = val: expected 3 arguments, received 2 - • (s::($(x) type(x) == t), k::($(x) )): type check failure for parameter s in function (s::($(x) type(x) == t), k::($(x) )) - • (c::($(x) ), s::($(x) )) = v: expected 3 arguments, received 2 - • (c::($(x) ), s::($(x) )) = v: expected 3 arguments, received 2 - • (c::($(x) ), s::($(x) )): type check failure for parameter c in function (c::($(x) ), s::($(x) )) +can't call overload _._: no function match arguments (overload([($(b) _), ($(x) _), ($() _)]), "a"), possible functions were: + • $(s::is script, k::is symbol) = val (from stdlib/script.ans:44:1): + expected 3 arguments, received 2 + • $(s::is script, k::is string) = val (from stdlib/script.ans:42:1): + expected 3 arguments, received 2 + • $(s::is script, k::is string) (from stdlib/script.ans:40:1): + type check failure for parameter s + • $(c::is function, s::is symbol) = v (from test/tests/function separate variable from variants.ans:10:4): + expected 3 arguments, received 2 + • $(c::is function, s::is string) = v (from test/tests/function separate variable from variants.ans:10:4): + expected 3 arguments, received 2 + • $(c::is function, s::is string) (from test/tests/function separate variable from variants.ans:10:4): + type check failure for parameter c ↳ from test/tests/function separate variable from variants.ans:10:4 in call: f . "a" ↳ from test/tests/function separate variable from variants.ans:10:1 in text interpolation: | {f . "a"} = 2 | ↳ from ? in block: :f = ($() _)… diff --git a/test/results/function type dispatch ambigous.ans b/test/results/function type dispatch ambigous.ans index 8d6a596..08cded7 100644 --- a/test/results/function type dispatch ambigous.ans +++ b/test/results/function type dispatch ambigous.ans @@ -1,9 +1,9 @@ --# run #-- --- error --- -can't call overload overload<($(a::($(x) )) _), ($(x::($(x) )) _)>: more than one function match (5), matching functions were at least (specificity 1.3): - • (x::($(x) )) - • (a::($(x) )) +can't call overload fn: more than one function match arguments (5), matching functions were at least (specificity 1.2): + • $(x::is number) (from test/tests/function type dispatch ambigous.ans:1:1) + • $(a::is number) (from test/tests/function type dispatch ambigous.ans:4:1) ↳ from test/tests/function type dispatch ambigous.ans:7:3 in call: fn(5) - ↳ from ? in block: :fn = ($(x::number) _)… + ↳ from ? in block: :fn = ($(x::is number) _)… --# saved #-- {} \ No newline at end of file diff --git a/test/results/merge nested mutable error bis.ans b/test/results/merge nested mutable error bis.ans index 6873006..2bbed04 100644 --- a/test/results/merge nested mutable error bis.ans +++ b/test/results/merge nested mutable error bis.ans @@ -4,14 +4,14 @@ ↳ from test/tests/merge nested mutable error bis.ans:14:7 in call: error("abort") ↳ from test/tests/merge nested mutable error bis.ans:3:1 in block: insert(a, b)… ↳ from test/tests/merge nested mutable error bis.ans:3:18 in call: _ - ↳ from script.ans:30:6 in call: fn! - ↳ from script.ans:28:3 in block: resume target = ()… - ↳ from script.ans:28:7 in call: else! - ↳ from script.ans:24:2 in block: if(fn . "current checkpoint")… - ↳ from script.ans:24:9 in call: _ - ↳ from script.ans:38:9 in call: value(s)! - ↳ from script.ans:37:1 in block: value(s)! - ↳ from script.ans:37:20 in call: _ + ↳ from stdlib/script.ans:30:6 in call: fn! + ↳ from stdlib/script.ans:28:3 in block: resume target = ()… + ↳ from stdlib/script.ans:28:7 in call: else! + ↳ from stdlib/script.ans:24:2 in block: if(fn . "current checkpoint")… + ↳ from stdlib/script.ans:24:9 in call: _ + ↳ from stdlib/script.ans:38:9 in call: value(s)! + ↳ from stdlib/script.ans:37:1 in block: value(s)! + ↳ from stdlib/script.ans:37:20 in call: _ ↳ from test/tests/merge nested mutable error bis.ans:19:2 in call: f! ↳ from ? in block: :a = *[1]… --# post run check #-- diff --git a/test/results/merge nested mutable error.ans b/test/results/merge nested mutable error.ans index 7e3dbfd..467b0e0 100644 --- a/test/results/merge nested mutable error.ans +++ b/test/results/merge nested mutable error.ans @@ -4,14 +4,14 @@ ↳ from test/tests/merge nested mutable error.ans:14:7 in call: error("abort") ↳ from test/tests/merge nested mutable error.ans:3:1 in block: insert(a, b)… ↳ from test/tests/merge nested mutable error.ans:3:18 in call: _ - ↳ from script.ans:30:6 in call: fn! - ↳ from script.ans:28:3 in block: resume target = ()… - ↳ from script.ans:28:7 in call: else! - ↳ from script.ans:24:2 in block: if(fn . "current checkpoint")… - ↳ from script.ans:24:9 in call: _ - ↳ from script.ans:38:9 in call: value(s)! - ↳ from script.ans:37:1 in block: value(s)! - ↳ from script.ans:37:20 in call: _ + ↳ from stdlib/script.ans:30:6 in call: fn! + ↳ from stdlib/script.ans:28:3 in block: resume target = ()… + ↳ from stdlib/script.ans:28:7 in call: else! + ↳ from stdlib/script.ans:24:2 in block: if(fn . "current checkpoint")… + ↳ from stdlib/script.ans:24:9 in call: _ + ↳ from stdlib/script.ans:38:9 in call: value(s)! + ↳ from stdlib/script.ans:37:1 in block: value(s)! + ↳ from stdlib/script.ans:37:20 in call: _ ↳ from test/tests/merge nested mutable error.ans:19:2 in call: f! ↳ from ? in block: :a = *[1]… --# post run check #--