mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
Add scoped functions
This commit is contained in:
parent
3d32f35d67
commit
fef498b3d7
16 changed files with 1164 additions and 58 deletions
29
REFERENCE.md
29
REFERENCE.md
|
|
@ -153,6 +153,33 @@ $ f(a, b...)
|
|||
~ f("discarded")
|
||||
```
|
||||
|
||||
When a parameter list is given (or just empty parentheses `()`), the function is considered `scoped` - this means that any variable defined in it will only be defined in a call to the function and can only be accessed from this specific call:
|
||||
|
||||
```
|
||||
(Non-scoped function: usual behaviour, variables are accessible from everywhere and always.)
|
||||
$ f
|
||||
:a = 1
|
||||
~ a += 1
|
||||
|
||||
{f.a} is 1
|
||||
|
||||
~ f
|
||||
{f.a} is 2
|
||||
|
||||
(Scoped function: can't access g.a from outside the function)
|
||||
$ g()
|
||||
:a = 1
|
||||
{a}
|
||||
~ a += 1
|
||||
|
||||
(Each time the function is called, it has access to its own version of g.a, and don't share it - so this display 1 both times:)
|
||||
~ g
|
||||
|
||||
~ g
|
||||
```
|
||||
|
||||
This is basically the behaviour you'd expect from functions in most other programming languages, and what you would use in Anselme any time you don't care about storing the function variables or want the exact same initial function variables each time you call the function (e.g. recursion). Scoped variables are not kept in save files, and are not affected by checkpointing.
|
||||
|
||||
Functions with the same name can be defined, as long as they have a different arguments. Functions will be selected based on the number of arguments given, their name and their type annotation:
|
||||
|
||||
```
|
||||
|
|
@ -891,7 +918,7 @@ This only works on strings:
|
|||
|
||||
##### Sequential execution
|
||||
|
||||
`cycle(...)`: given function/checkpoint identifiers as string as arguments, will execute them in the order given each time the function is ran; e.g., `cycle("a", "b")` will execute a on the first execution, then b, then a again, etc.
|
||||
`cycle(...)`: given function/checkpoint references as arguments, will execute them in the order given each time the function is ran; e.g., `cycle(&a, &b)` will execute a on the first execution, then b, then a again, etc.
|
||||
|
||||
`next(...)`: same as cycle, but will not cycle; once the end of sequence is reached, will keep executing the last element.
|
||||
|
||||
|
|
|
|||
11
anselme.lua
11
anselme.lua
|
|
@ -6,11 +6,11 @@ local anselme = {
|
|||
-- api is incremented a each update which may break Lua API compatibility
|
||||
versions = {
|
||||
save = 1,
|
||||
language = 20,
|
||||
language = 21,
|
||||
api = 4
|
||||
},
|
||||
-- version is incremented at each update
|
||||
version = 21,
|
||||
version = 22,
|
||||
--- currently running interpreter
|
||||
running = nil
|
||||
}
|
||||
|
|
@ -198,6 +198,7 @@ local interpreter_methods = {
|
|||
if not success then
|
||||
return nil, event
|
||||
elseif event == "error" then
|
||||
self.end_event = "error"
|
||||
return nil, data
|
||||
elseif event ~= "return" then
|
||||
return nil, ("evaluated expression generated an %q event; at %s"):format(event, self.state.interpreter.running_line.source)
|
||||
|
|
@ -479,8 +480,7 @@ local vm_mt = {
|
|||
functions = self.state.functions, -- no need for a cache as we can't define or modify any function from the interpreter for now
|
||||
variables = setmetatable({}, {
|
||||
__index = function(variables, k)
|
||||
local mt = getmetatable(variables)
|
||||
local cache = mt.cache
|
||||
local cache = getmetatable(variables).cache
|
||||
if cache[k] == nil then
|
||||
cache[k] = copy(self.state.variables[k], getmetatable(variables).copy_cache)
|
||||
end
|
||||
|
|
@ -490,6 +490,9 @@ local vm_mt = {
|
|||
copy_cache = {}, -- table of [original table] = copied table
|
||||
modified_tables = {}, -- list of modified tables (copies) that should be merged with global state on next checkpoint
|
||||
cache = {}, -- cache of previously read values (copies), to get repeatable reads & handle mutable types without changing global state
|
||||
-- keep track of scoped variables in scoped functions [fn line] = {{scoped variables}, next scope, ...}
|
||||
-- (scoped variables aren't merged on checkpoint, shouldn't be cleared at checkpoints)
|
||||
scoped = {}
|
||||
}),
|
||||
interpreter = {
|
||||
-- constant
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
local identifier_pattern
|
||||
|
||||
--- replace values recursively in table t according to to_replace ([old table] = new table)
|
||||
-- already_replaced is a temporary table to avoid infinite loop & duplicate processing, no need to give it
|
||||
local function replace_in_table(t, to_replace, already_replaced)
|
||||
|
|
@ -65,6 +63,5 @@ common = {
|
|||
}
|
||||
|
||||
package.loaded[...] = common
|
||||
identifier_pattern = require((...):gsub("common$", "parser.common")).identifier_pattern
|
||||
|
||||
return common
|
||||
|
|
|
|||
|
|
@ -58,9 +58,7 @@ common = {
|
|||
mt.cache = {}
|
||||
-- merge modified re-assigned variables
|
||||
for var, value in pairs(state.variables) do
|
||||
if common.should_keep_variable(state, var) then
|
||||
global.variables[var] = value
|
||||
end
|
||||
global.variables[var] = value
|
||||
state.variables[var] = nil
|
||||
end
|
||||
end,
|
||||
|
|
@ -81,16 +79,62 @@ common = {
|
|||
return var
|
||||
end
|
||||
end,
|
||||
--- set the value of a variable
|
||||
set_variable = function(state, name, val)
|
||||
state.variables[name] = val
|
||||
end,
|
||||
--- handle scoped function
|
||||
scope = {
|
||||
push = function(self, state, fn)
|
||||
local scoped = getmetatable(state.variables).scoped
|
||||
if not fn.scoped then error("trying to push a scope for a non-scoped function") end
|
||||
-- add scope
|
||||
if not scoped[fn] then
|
||||
scoped[fn] = {}
|
||||
end
|
||||
local last_scope = scoped[fn][#scoped[fn]]
|
||||
local fn_scope = {}
|
||||
table.insert(scoped[fn], fn_scope)
|
||||
-- add scoped variables to scope
|
||||
for _, name in ipairs(fn.scoped) do
|
||||
-- preserve current values in last scope
|
||||
if last_scope then
|
||||
last_scope[name] = state.variables[name]
|
||||
end
|
||||
-- set last value to nil to force to copy again from global variables in new scope
|
||||
state.variables[name] = nil
|
||||
local value = state.variables[name]
|
||||
fn_scope[name] = value
|
||||
end
|
||||
end,
|
||||
pop = function(self, state, fn)
|
||||
local scoped = getmetatable(state.variables).scoped
|
||||
if not scoped[fn] then error("trying to pop a scope without any pushed scope") end
|
||||
-- remove current scope
|
||||
table.remove(scoped[fn])
|
||||
-- set scopped variables to previous scope
|
||||
local last_scope = scoped[fn][#scoped[fn]]
|
||||
if last_scope then
|
||||
for _, name in ipairs(fn.scoped) do
|
||||
state.variables[name] = last_scope[name]
|
||||
end
|
||||
else -- no previous scope
|
||||
for _, name in ipairs(fn.scoped) do
|
||||
state.variables[name] = nil
|
||||
end
|
||||
-- no need to remove this I think, there's not going to be a million different functions in a single game so we can keep the tables
|
||||
-- (anselme's performance is already bad enough, let's not create tables at each function call...)
|
||||
-- scoped[fn] = nil
|
||||
end
|
||||
end
|
||||
},
|
||||
--- mark a table as modified, so it will be merged on the next checkpoint if it appears somewhere in a value
|
||||
mark_as_modified = function(state, v)
|
||||
local modified = getmetatable(state.variables).modified_tables
|
||||
table.insert(modified, v)
|
||||
end,
|
||||
--- returns true if a variable should be persisted on save/merge
|
||||
-- will exclude: undefined variables, variables in functions defined with parentheses, internal anselme variables
|
||||
--- 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%.")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
local expression
|
||||
local to_lua, from_lua, eval_text, is_of_type, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, flatten_list, set_variable
|
||||
local to_lua, from_lua, eval_text, is_of_type, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, flatten_list, set_variable, scope
|
||||
|
||||
local run
|
||||
|
||||
|
|
@ -65,20 +65,6 @@ local function eval(state, exp)
|
|||
type = "list",
|
||||
value = l
|
||||
}
|
||||
-- event buffer (internal type, only issued from a text or choice line)
|
||||
elseif exp.type == "text" then
|
||||
local l = {}
|
||||
events:push_buffer(state, l)
|
||||
local current_tags = tags:current(state)
|
||||
local v, e = eval_text_callback(state, exp.text, function(text)
|
||||
events:append(state, "text", { text = text, tags = current_tags })
|
||||
end)
|
||||
events:pop_buffer(state)
|
||||
if not v then return v, e end
|
||||
return {
|
||||
type = "event buffer",
|
||||
value = l
|
||||
}
|
||||
-- assignment
|
||||
elseif exp.type == ":=" then
|
||||
if exp.left.type == "variable" then
|
||||
|
|
@ -203,7 +189,7 @@ local function eval(state, exp)
|
|||
end
|
||||
-- try to select a function
|
||||
local tried_function_error_messages = {}
|
||||
local selected_variant = { depths = { assignment = nil }, variant = nil }
|
||||
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
|
||||
|
|
@ -218,6 +204,7 @@ local function eval(state, exp)
|
|||
if not fn.assignment or exp.assignment then
|
||||
local ok = true
|
||||
-- get and set args
|
||||
local variant_args = {}
|
||||
local used_args = {}
|
||||
local depths = { assignment = nil }
|
||||
for j, param in ipairs(fn.params) do
|
||||
|
|
@ -257,11 +244,11 @@ local function eval(state, exp)
|
|||
depths[j] = math.huge
|
||||
end
|
||||
-- set
|
||||
set_variable(state, param.full_name, val)
|
||||
variant_args[param.full_name] = val
|
||||
-- default: evaluate once function is selected
|
||||
-- there's no need to type check because the type annotation is already the default value's type, because of syntax
|
||||
elseif param.default then
|
||||
set_variable(state, param.full_name, { type = "pending definition", value = { expression = param.default, source = fn.source } })
|
||||
variant_args[param.full_name] = { type = "pending definition", value = { expression = param.default, source = fn.source } }
|
||||
else
|
||||
ok = false
|
||||
table.insert(tried_function_error_messages, ("%s: missing mandatory argument %q in function %q call"):format(fn.pretty_signature, param.name, fn.name))
|
||||
|
|
@ -300,12 +287,13 @@ local function eval(state, exp)
|
|||
depths.assignment = math.huge
|
||||
end
|
||||
-- set
|
||||
set_variable(state, param.full_name, assignment)
|
||||
variant_args[param.full_name] = assignment
|
||||
end
|
||||
if ok then
|
||||
if not selected_variant.variant then
|
||||
selected_variant.depths = depths
|
||||
selected_variant.variant = fn
|
||||
selected_variant.args_to_set = variant_args
|
||||
else
|
||||
-- check specificity order
|
||||
local lower
|
||||
|
|
@ -330,6 +318,7 @@ local function eval(state, exp)
|
|||
if lower then
|
||||
selected_variant.depths = depths
|
||||
selected_variant.variant = fn
|
||||
selected_variant.args_to_set = variant_args
|
||||
elseif lower == nil then -- equal, ambigous dispatch
|
||||
return nil, ("function 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
|
||||
|
|
@ -349,6 +338,17 @@ local function eval(state, exp)
|
|||
return r
|
||||
elseif fn.type == "function" then
|
||||
local ret
|
||||
-- push scope
|
||||
-- NOTE: if error happens between here and scope:pop, will leave the stack a mess
|
||||
-- should not be an issue since an interpreter is supposed to be discarded after an error, but should change this if we ever
|
||||
-- add some excepetion handling in anselme at some point
|
||||
if fn.scoped then
|
||||
scope:push(state, fn)
|
||||
end
|
||||
-- set arguments
|
||||
for name, val in pairs(selected_variant.args_to_set) do
|
||||
set_variable(state, name, val)
|
||||
end
|
||||
-- get function vars
|
||||
local checkpoint, checkpointe = get_variable(state, fn.namespace.."🔖")
|
||||
if not checkpoint then return nil, checkpointe end
|
||||
|
|
@ -435,6 +435,10 @@ local function eval(state, exp)
|
|||
type = "number",
|
||||
value = seen.value + 1
|
||||
})
|
||||
-- pop scope
|
||||
if fn.scoped then
|
||||
scope:pop(state, fn)
|
||||
end
|
||||
-- return value
|
||||
if not ret then return nil, ("function %q didn't return a value"):format(exp.called_name) end
|
||||
return ret
|
||||
|
|
@ -456,6 +460,20 @@ local function eval(state, exp)
|
|||
called_name = called_name .. " := " .. pretty_type(assignment)
|
||||
end
|
||||
return nil, ("no compatible function found for call to %s; potential candidates were:\n\t%s"):format(called_name, table.concat(tried_function_error_messages, "\n\t"))
|
||||
-- event buffer (internal type, only issued from a text or choice line)
|
||||
elseif exp.type == "text" then
|
||||
local l = {}
|
||||
events:push_buffer(state, l)
|
||||
local current_tags = tags:current(state)
|
||||
local v, e = eval_text_callback(state, exp.text, function(text)
|
||||
events:append(state, "text", { text = text, tags = current_tags })
|
||||
end)
|
||||
events:pop_buffer(state)
|
||||
if not v then return v, e end
|
||||
return {
|
||||
type = "event buffer",
|
||||
value = l
|
||||
}
|
||||
else
|
||||
return nil, ("unknown expression %q"):format(tostring(exp.type))
|
||||
end
|
||||
|
|
@ -466,6 +484,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, is_of_type, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, set_variable = common.to_lua, common.from_lua, common.eval_text, common.is_of_type, common.truthy, common.format, common.pretty_type, common.get_variable, common.tags, common.eval_text_callback, common.events, common.set_variable
|
||||
to_lua, from_lua, eval_text, is_of_type, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, set_variable, scope = common.to_lua, common.from_lua, common.eval_text, common.is_of_type, common.truthy, common.format, common.pretty_type, common.get_variable, common.tags, common.eval_text_callback, common.events, common.set_variable, common.scope
|
||||
|
||||
return eval
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ 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: rewrite cycle, ... using function references
|
||||
TODO: a way to make loops
|
||||
|
||||
TODO: consider something like :identifier to create a string "identifier", might simplify the identifier=value special syntax and free up the = operator
|
||||
|
||||
|
|
@ -53,10 +53,6 @@ TODO: the function decorator feels a bit glued-on to the current syntax
|
|||
|
||||
TODO: simplify language, it is much too complicated. Less line types? (var def, func, checkpoint, tag). Rewrite some ad hoc syntax using the expression system?
|
||||
|
||||
TODO: functions: might be nice to have actual scoping for functions that are called with arguments; to allow proper recursion & stuff (as right now if you call the same function from itself both instances will share variables...). Would require a fair amount of changes to the code though.
|
||||
|
||||
TODO: a way to make loops
|
||||
|
||||
TODO: fn/checkpoint/tag: maybe consider them a regular func call that takes children as arg; can keep compatibility using $/§ as shortcut for the actual call.
|
||||
would allow more flexibility esp. for tags...
|
||||
a func def would be:
|
||||
|
|
|
|||
|
|
@ -43,6 +43,16 @@ local function parse(state)
|
|||
end
|
||||
line.assignment.type_annotation = type_exp
|
||||
end
|
||||
-- get list of scoped variables
|
||||
-- (note includes every variables in the namespace of subnamespace, so subfunctions are scoped alongside this function)
|
||||
if line.scoped then
|
||||
line.scoped = {}
|
||||
for name in pairs(state.variables) do
|
||||
if name:sub(1, #namespace) == namespace then
|
||||
table.insert(line.scoped, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- expressions
|
||||
if line.expression then
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ local function parse_line(line, state, namespace)
|
|||
-- get params
|
||||
r.params = {}
|
||||
if r.type == "function" and rem:match("^%b()") then
|
||||
r.scoped = true
|
||||
local content
|
||||
content, rem = rem:match("^(%b())%s*(.*)$")
|
||||
content = content:gsub("^%(", ""):gsub("%)$", "")
|
||||
|
|
|
|||
|
|
@ -296,18 +296,7 @@ lua_functions = {
|
|||
value = is_of_type(v, t) or 0
|
||||
}
|
||||
end
|
||||
},
|
||||
["cycle(l...)"] = function(l)
|
||||
local f, fseen = l[1], assert(anselme.running:eval(l[1]..".👁️", anselme.running:current_namespace()))
|
||||
for j=2, #l do
|
||||
local seen = assert(anselme.running:eval(l[j]..".👁️", anselme.running:current_namespace()))
|
||||
if seen < fseen then
|
||||
f = l[j]
|
||||
break
|
||||
end
|
||||
end
|
||||
return anselme.running:run(f, anselme.running:current_namespace())
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
||||
local anselme_functions = [[
|
||||
|
|
@ -315,13 +304,25 @@ $ random(l...)
|
|||
~ l(rand(1, l!len))!
|
||||
|
||||
$ next(l...)
|
||||
~ l!len == 1 | l(1).👁️ == 0
|
||||
~ l(1)!
|
||||
~~
|
||||
~ l!remove(1)
|
||||
~ next(l=l)
|
||||
:f = l(len(l))
|
||||
$ find first not seen(j)
|
||||
~ l(j).👁️ == 0
|
||||
~ f := l(j)
|
||||
~~ j < len(l)
|
||||
~ find first not seen(j+1)
|
||||
~ find first not seen(1)
|
||||
~ f!
|
||||
|
||||
(TODO: cycle)
|
||||
$ cycle(l...)
|
||||
:f = l(1)
|
||||
$ find first smaller(j)
|
||||
~ l(j).👁️ < f.👁️
|
||||
~ f := l(j)
|
||||
~~ j < len(l)
|
||||
~ find first smaller(j+1)
|
||||
~ len(l) > 1
|
||||
~ find first smaller(2)
|
||||
~ f!
|
||||
]]
|
||||
|
||||
local functions = {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,14 @@ $ f
|
|||
b
|
||||
$ c
|
||||
c
|
||||
~ cycle("a","b","c")
|
||||
~ cycle(&a,&b,&c)
|
||||
|
||||
~ f
|
||||
|
||||
~ f
|
||||
|
||||
~ f
|
||||
|
||||
~ f
|
||||
|
||||
~ f
|
||||
40
test/tests/function scoped mutable.ans
Normal file
40
test/tests/function scoped mutable.ans
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
:n = 0
|
||||
|
||||
$ f(c=1)
|
||||
:a = []
|
||||
|
||||
start: {a}
|
||||
|
||||
~ a!insert(c)
|
||||
|
||||
~ n += 1
|
||||
|
||||
before recursion {c}: {a}
|
||||
|
||||
~ n < 5
|
||||
~ f(c+1)
|
||||
|
||||
after recursion {c}: {a}
|
||||
|
||||
new list each time:
|
||||
|
||||
~ f
|
||||
|
||||
$ g(c=1, a=[])
|
||||
start: {a}
|
||||
|
||||
~ a!insert(c)
|
||||
|
||||
~ n += 1
|
||||
|
||||
before recursion {c}: {a}
|
||||
|
||||
~ n < 5
|
||||
~ g(c+1, a)
|
||||
|
||||
after recursion {c}: {a}
|
||||
|
||||
pass list:
|
||||
|
||||
~ n := 0
|
||||
~ g
|
||||
566
test/tests/function scoped mutable.lua
Normal file
566
test/tests/function scoped mutable.lua
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
local _={}
|
||||
_[249]={}
|
||||
_[248]={}
|
||||
_[247]={}
|
||||
_[246]={}
|
||||
_[245]={}
|
||||
_[244]={}
|
||||
_[243]={}
|
||||
_[242]={}
|
||||
_[241]={}
|
||||
_[240]={}
|
||||
_[239]={}
|
||||
_[238]={}
|
||||
_[237]={}
|
||||
_[236]={}
|
||||
_[235]={}
|
||||
_[234]={}
|
||||
_[233]={}
|
||||
_[232]={}
|
||||
_[231]={}
|
||||
_[230]={}
|
||||
_[229]={}
|
||||
_[228]={}
|
||||
_[227]={}
|
||||
_[226]={}
|
||||
_[225]={}
|
||||
_[224]={}
|
||||
_[223]={}
|
||||
_[222]={}
|
||||
_[221]={}
|
||||
_[220]={}
|
||||
_[219]={}
|
||||
_[218]={}
|
||||
_[217]={}
|
||||
_[216]={}
|
||||
_[215]={}
|
||||
_[214]={}
|
||||
_[213]={}
|
||||
_[212]={}
|
||||
_[211]={}
|
||||
_[210]={}
|
||||
_[209]={}
|
||||
_[208]={}
|
||||
_[207]={}
|
||||
_[206]={}
|
||||
_[205]={}
|
||||
_[204]={}
|
||||
_[203]={}
|
||||
_[202]={}
|
||||
_[201]={}
|
||||
_[200]={}
|
||||
_[199]={}
|
||||
_[198]={}
|
||||
_[197]={}
|
||||
_[196]={}
|
||||
_[195]={}
|
||||
_[194]={}
|
||||
_[193]={}
|
||||
_[192]={}
|
||||
_[191]={}
|
||||
_[190]={}
|
||||
_[189]={}
|
||||
_[188]={}
|
||||
_[187]={}
|
||||
_[186]={}
|
||||
_[185]={}
|
||||
_[184]={}
|
||||
_[183]={}
|
||||
_[182]={}
|
||||
_[181]={}
|
||||
_[180]={}
|
||||
_[179]={}
|
||||
_[178]={}
|
||||
_[177]={}
|
||||
_[176]={}
|
||||
_[175]={}
|
||||
_[174]={}
|
||||
_[173]={}
|
||||
_[172]={}
|
||||
_[171]={}
|
||||
_[170]={}
|
||||
_[169]={}
|
||||
_[168]={}
|
||||
_[167]={}
|
||||
_[166]={}
|
||||
_[165]={}
|
||||
_[164]={}
|
||||
_[163]={}
|
||||
_[162]={}
|
||||
_[161]={}
|
||||
_[160]={}
|
||||
_[159]={}
|
||||
_[158]={}
|
||||
_[157]={}
|
||||
_[156]={}
|
||||
_[155]={tags=_[249],text="[1, 2, 3, 4, 5]"}
|
||||
_[154]={tags=_[248],text=": "}
|
||||
_[153]={tags=_[247],text="1"}
|
||||
_[152]={tags=_[246],text="after recursion "}
|
||||
_[151]={tags=_[245],text="[1, 2, 3, 4, 5]"}
|
||||
_[150]={tags=_[244],text=": "}
|
||||
_[149]={tags=_[243],text="2"}
|
||||
_[148]={tags=_[242],text="after recursion "}
|
||||
_[147]={tags=_[241],text="[1, 2, 3, 4, 5]"}
|
||||
_[146]={tags=_[240],text=": "}
|
||||
_[145]={tags=_[239],text="3"}
|
||||
_[144]={tags=_[238],text="after recursion "}
|
||||
_[143]={tags=_[237],text="[1, 2, 3, 4, 5]"}
|
||||
_[142]={tags=_[236],text=": "}
|
||||
_[141]={tags=_[235],text="4"}
|
||||
_[140]={tags=_[234],text="after recursion "}
|
||||
_[139]={tags=_[233],text="[1, 2, 3, 4, 5]"}
|
||||
_[138]={tags=_[232],text=": "}
|
||||
_[137]={tags=_[231],text="5"}
|
||||
_[136]={tags=_[230],text="before recursion "}
|
||||
_[135]={tags=_[229],text="[1, 2, 3, 4]"}
|
||||
_[134]={tags=_[228],text="start: "}
|
||||
_[133]={tags=_[227],text="[1, 2, 3, 4]"}
|
||||
_[132]={tags=_[226],text=": "}
|
||||
_[131]={tags=_[225],text="4"}
|
||||
_[130]={tags=_[224],text="before recursion "}
|
||||
_[129]={tags=_[223],text="[1, 2, 3]"}
|
||||
_[128]={tags=_[222],text="start: "}
|
||||
_[127]={tags=_[221],text="[1, 2, 3]"}
|
||||
_[126]={tags=_[220],text=": "}
|
||||
_[125]={tags=_[219],text="3"}
|
||||
_[124]={tags=_[218],text="before recursion "}
|
||||
_[123]={tags=_[217],text="[1, 2]"}
|
||||
_[122]={tags=_[216],text="start: "}
|
||||
_[121]={tags=_[215],text="[1, 2]"}
|
||||
_[120]={tags=_[214],text=": "}
|
||||
_[119]={tags=_[213],text="2"}
|
||||
_[118]={tags=_[212],text="before recursion "}
|
||||
_[117]={tags=_[211],text="[1]"}
|
||||
_[116]={tags=_[210],text="start: "}
|
||||
_[115]={tags=_[209],text="[1]"}
|
||||
_[114]={tags=_[208],text=": "}
|
||||
_[113]={tags=_[207],text="1"}
|
||||
_[112]={tags=_[206],text="before recursion "}
|
||||
_[111]={tags=_[205],text="[]"}
|
||||
_[110]={tags=_[204],text="start: "}
|
||||
_[109]={tags=_[203],text="pass list:"}
|
||||
_[108]={tags=_[202],text="[1]"}
|
||||
_[107]={tags=_[201],text=": "}
|
||||
_[106]={tags=_[200],text="1"}
|
||||
_[105]={tags=_[199],text="after recursion "}
|
||||
_[104]={tags=_[198],text="[2]"}
|
||||
_[103]={tags=_[197],text=": "}
|
||||
_[102]={tags=_[196],text="2"}
|
||||
_[101]={tags=_[195],text="after recursion "}
|
||||
_[100]={tags=_[194],text="[3]"}
|
||||
_[99]={tags=_[193],text=": "}
|
||||
_[98]={tags=_[192],text="3"}
|
||||
_[97]={tags=_[191],text="after recursion "}
|
||||
_[96]={tags=_[190],text="[4]"}
|
||||
_[95]={tags=_[189],text=": "}
|
||||
_[94]={tags=_[188],text="4"}
|
||||
_[93]={tags=_[187],text="after recursion "}
|
||||
_[92]={tags=_[186],text="[5]"}
|
||||
_[91]={tags=_[185],text=": "}
|
||||
_[90]={tags=_[184],text="5"}
|
||||
_[89]={tags=_[183],text="before recursion "}
|
||||
_[88]={tags=_[182],text="[]"}
|
||||
_[87]={tags=_[181],text="start: "}
|
||||
_[86]={tags=_[180],text="[4]"}
|
||||
_[85]={tags=_[179],text=": "}
|
||||
_[84]={tags=_[178],text="4"}
|
||||
_[83]={tags=_[177],text="before recursion "}
|
||||
_[82]={tags=_[176],text="[]"}
|
||||
_[81]={tags=_[175],text="start: "}
|
||||
_[80]={tags=_[174],text="[3]"}
|
||||
_[79]={tags=_[173],text=": "}
|
||||
_[78]={tags=_[172],text="3"}
|
||||
_[77]={tags=_[171],text="before recursion "}
|
||||
_[76]={tags=_[170],text="[]"}
|
||||
_[75]={tags=_[169],text="start: "}
|
||||
_[74]={tags=_[168],text="[2]"}
|
||||
_[73]={tags=_[167],text=": "}
|
||||
_[72]={tags=_[166],text="2"}
|
||||
_[71]={tags=_[165],text="before recursion "}
|
||||
_[70]={tags=_[164],text="[]"}
|
||||
_[69]={tags=_[163],text="start: "}
|
||||
_[68]={tags=_[162],text="[1]"}
|
||||
_[67]={tags=_[161],text=": "}
|
||||
_[66]={tags=_[160],text="1"}
|
||||
_[65]={tags=_[159],text="before recursion "}
|
||||
_[64]={tags=_[158],text="[]"}
|
||||
_[63]={tags=_[157],text="start: "}
|
||||
_[62]={tags=_[156],text="new list each time:"}
|
||||
_[61]={_[152],_[153],_[154],_[155]}
|
||||
_[60]={_[148],_[149],_[150],_[151]}
|
||||
_[59]={_[144],_[145],_[146],_[147]}
|
||||
_[58]={_[140],_[141],_[142],_[143]}
|
||||
_[57]={_[136],_[137],_[138],_[139]}
|
||||
_[56]={_[134],_[135]}
|
||||
_[55]={_[130],_[131],_[132],_[133]}
|
||||
_[54]={_[128],_[129]}
|
||||
_[53]={_[124],_[125],_[126],_[127]}
|
||||
_[52]={_[122],_[123]}
|
||||
_[51]={_[118],_[119],_[120],_[121]}
|
||||
_[50]={_[116],_[117]}
|
||||
_[49]={_[112],_[113],_[114],_[115]}
|
||||
_[48]={_[110],_[111]}
|
||||
_[47]={_[109]}
|
||||
_[46]={_[105],_[106],_[107],_[108]}
|
||||
_[45]={_[101],_[102],_[103],_[104]}
|
||||
_[44]={_[97],_[98],_[99],_[100]}
|
||||
_[43]={_[93],_[94],_[95],_[96]}
|
||||
_[42]={_[89],_[90],_[91],_[92]}
|
||||
_[41]={_[87],_[88]}
|
||||
_[40]={_[83],_[84],_[85],_[86]}
|
||||
_[39]={_[81],_[82]}
|
||||
_[38]={_[77],_[78],_[79],_[80]}
|
||||
_[37]={_[75],_[76]}
|
||||
_[36]={_[71],_[72],_[73],_[74]}
|
||||
_[35]={_[69],_[70]}
|
||||
_[34]={_[65],_[66],_[67],_[68]}
|
||||
_[33]={_[63],_[64]}
|
||||
_[32]={_[62]}
|
||||
_[31]={"return"}
|
||||
_[30]={"text",_[61]}
|
||||
_[29]={"text",_[60]}
|
||||
_[28]={"text",_[59]}
|
||||
_[27]={"text",_[58]}
|
||||
_[26]={"text",_[57]}
|
||||
_[25]={"text",_[56]}
|
||||
_[24]={"text",_[55]}
|
||||
_[23]={"text",_[54]}
|
||||
_[22]={"text",_[53]}
|
||||
_[21]={"text",_[52]}
|
||||
_[20]={"text",_[51]}
|
||||
_[19]={"text",_[50]}
|
||||
_[18]={"text",_[49]}
|
||||
_[17]={"text",_[48]}
|
||||
_[16]={"text",_[47]}
|
||||
_[15]={"text",_[46]}
|
||||
_[14]={"text",_[45]}
|
||||
_[13]={"text",_[44]}
|
||||
_[12]={"text",_[43]}
|
||||
_[11]={"text",_[42]}
|
||||
_[10]={"text",_[41]}
|
||||
_[9]={"text",_[40]}
|
||||
_[8]={"text",_[39]}
|
||||
_[7]={"text",_[38]}
|
||||
_[6]={"text",_[37]}
|
||||
_[5]={"text",_[36]}
|
||||
_[4]={"text",_[35]}
|
||||
_[3]={"text",_[34]}
|
||||
_[2]={"text",_[33]}
|
||||
_[1]={"text",_[32]}
|
||||
return {_[1],_[2],_[3],_[4],_[5],_[6],_[7],_[8],_[9],_[10],_[11],_[12],_[13],_[14],_[15],_[16],_[17],_[18],_[19],_[20],_[21],_[22],_[23],_[24],_[25],_[26],_[27],_[28],_[29],_[30],_[31]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "new list each time:"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[2]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "3"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[3]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[4]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "5"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[5]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[4]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "3"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[3]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[2]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "pass list:"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "3"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3, 4]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3, 4]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "5"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3, 4, 5]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3, 4, 5]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "3"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3, 4, 5]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3, 4, 5]"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "[1, 2, 3, 4, 5]"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
19
test/tests/function scoped recursive.ans
Normal file
19
test/tests/function scoped recursive.ans
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
:n = 0
|
||||
|
||||
$ f(c=1)
|
||||
:a = 1
|
||||
|
||||
start: {a}
|
||||
|
||||
~ a := a + 1
|
||||
|
||||
~ n += 1
|
||||
|
||||
before recursion {c}: {a}
|
||||
|
||||
~ n < 5
|
||||
~ f(c+1)
|
||||
|
||||
after recursion {c}: {a}
|
||||
|
||||
~ f
|
||||
278
test/tests/function scoped recursive.lua
Normal file
278
test/tests/function scoped recursive.lua
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
local _={}
|
||||
_[121]={}
|
||||
_[120]={}
|
||||
_[119]={}
|
||||
_[118]={}
|
||||
_[117]={}
|
||||
_[116]={}
|
||||
_[115]={}
|
||||
_[114]={}
|
||||
_[113]={}
|
||||
_[112]={}
|
||||
_[111]={}
|
||||
_[110]={}
|
||||
_[109]={}
|
||||
_[108]={}
|
||||
_[107]={}
|
||||
_[106]={}
|
||||
_[105]={}
|
||||
_[104]={}
|
||||
_[103]={}
|
||||
_[102]={}
|
||||
_[101]={}
|
||||
_[100]={}
|
||||
_[99]={}
|
||||
_[98]={}
|
||||
_[97]={}
|
||||
_[96]={}
|
||||
_[95]={}
|
||||
_[94]={}
|
||||
_[93]={}
|
||||
_[92]={}
|
||||
_[91]={}
|
||||
_[90]={}
|
||||
_[89]={}
|
||||
_[88]={}
|
||||
_[87]={}
|
||||
_[86]={}
|
||||
_[85]={}
|
||||
_[84]={}
|
||||
_[83]={}
|
||||
_[82]={}
|
||||
_[81]={}
|
||||
_[80]={}
|
||||
_[79]={}
|
||||
_[78]={}
|
||||
_[77]={}
|
||||
_[76]={}
|
||||
_[75]={tags=_[121],text="2"}
|
||||
_[74]={tags=_[120],text=": "}
|
||||
_[73]={tags=_[119],text="1"}
|
||||
_[72]={tags=_[118],text="after recursion "}
|
||||
_[71]={tags=_[117],text="2"}
|
||||
_[70]={tags=_[116],text=": "}
|
||||
_[69]={tags=_[115],text="2"}
|
||||
_[68]={tags=_[114],text="after recursion "}
|
||||
_[67]={tags=_[113],text="2"}
|
||||
_[66]={tags=_[112],text=": "}
|
||||
_[65]={tags=_[111],text="3"}
|
||||
_[64]={tags=_[110],text="after recursion "}
|
||||
_[63]={tags=_[109],text="2"}
|
||||
_[62]={tags=_[108],text=": "}
|
||||
_[61]={tags=_[107],text="4"}
|
||||
_[60]={tags=_[106],text="after recursion "}
|
||||
_[59]={tags=_[105],text="2"}
|
||||
_[58]={tags=_[104],text=": "}
|
||||
_[57]={tags=_[103],text="5"}
|
||||
_[56]={tags=_[102],text="before recursion "}
|
||||
_[55]={tags=_[101],text="1"}
|
||||
_[54]={tags=_[100],text="start: "}
|
||||
_[53]={tags=_[99],text="2"}
|
||||
_[52]={tags=_[98],text=": "}
|
||||
_[51]={tags=_[97],text="4"}
|
||||
_[50]={tags=_[96],text="before recursion "}
|
||||
_[49]={tags=_[95],text="1"}
|
||||
_[48]={tags=_[94],text="start: "}
|
||||
_[47]={tags=_[93],text="2"}
|
||||
_[46]={tags=_[92],text=": "}
|
||||
_[45]={tags=_[91],text="3"}
|
||||
_[44]={tags=_[90],text="before recursion "}
|
||||
_[43]={tags=_[89],text="1"}
|
||||
_[42]={tags=_[88],text="start: "}
|
||||
_[41]={tags=_[87],text="2"}
|
||||
_[40]={tags=_[86],text=": "}
|
||||
_[39]={tags=_[85],text="2"}
|
||||
_[38]={tags=_[84],text="before recursion "}
|
||||
_[37]={tags=_[83],text="1"}
|
||||
_[36]={tags=_[82],text="start: "}
|
||||
_[35]={tags=_[81],text="2"}
|
||||
_[34]={tags=_[80],text=": "}
|
||||
_[33]={tags=_[79],text="1"}
|
||||
_[32]={tags=_[78],text="before recursion "}
|
||||
_[31]={tags=_[77],text="1"}
|
||||
_[30]={tags=_[76],text="start: "}
|
||||
_[29]={_[72],_[73],_[74],_[75]}
|
||||
_[28]={_[68],_[69],_[70],_[71]}
|
||||
_[27]={_[64],_[65],_[66],_[67]}
|
||||
_[26]={_[60],_[61],_[62],_[63]}
|
||||
_[25]={_[56],_[57],_[58],_[59]}
|
||||
_[24]={_[54],_[55]}
|
||||
_[23]={_[50],_[51],_[52],_[53]}
|
||||
_[22]={_[48],_[49]}
|
||||
_[21]={_[44],_[45],_[46],_[47]}
|
||||
_[20]={_[42],_[43]}
|
||||
_[19]={_[38],_[39],_[40],_[41]}
|
||||
_[18]={_[36],_[37]}
|
||||
_[17]={_[32],_[33],_[34],_[35]}
|
||||
_[16]={_[30],_[31]}
|
||||
_[15]={"return"}
|
||||
_[14]={"text",_[29]}
|
||||
_[13]={"text",_[28]}
|
||||
_[12]={"text",_[27]}
|
||||
_[11]={"text",_[26]}
|
||||
_[10]={"text",_[25]}
|
||||
_[9]={"text",_[24]}
|
||||
_[8]={"text",_[23]}
|
||||
_[7]={"text",_[22]}
|
||||
_[6]={"text",_[21]}
|
||||
_[5]={"text",_[20]}
|
||||
_[4]={"text",_[19]}
|
||||
_[3]={"text",_[18]}
|
||||
_[2]={"text",_[17]}
|
||||
_[1]={"text",_[16]}
|
||||
return {_[1],_[2],_[3],_[4],_[5],_[6],_[7],_[8],_[9],_[10],_[11],_[12],_[13],_[14],_[15]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "3"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "start: "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "before recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "5"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "4"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "3"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "after recursion "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "1"
|
||||
}, {
|
||||
tags = {},
|
||||
text = ": "
|
||||
}, {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
32
test/tests/function scoped.ans
Normal file
32
test/tests/function scoped.ans
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
(FIXME compare with fe/janet types
|
||||
|
||||
|
||||
$ f()
|
||||
:a = 1
|
||||
|
||||
{a}
|
||||
|
||||
~ a := a + 1
|
||||
|
||||
$ g
|
||||
:a = 1
|
||||
|
||||
{a}
|
||||
|
||||
~ a := a + 1
|
||||
|
||||
scoped:
|
||||
|
||||
~ f
|
||||
|
||||
~ f
|
||||
|
||||
~ f
|
||||
|
||||
unscoped:
|
||||
|
||||
~ g
|
||||
|
||||
~ g
|
||||
|
||||
~ g
|
||||
70
test/tests/function scoped.lua
Normal file
70
test/tests/function scoped.lua
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
local _={}
|
||||
_[33]={}
|
||||
_[32]={}
|
||||
_[31]={}
|
||||
_[30]={}
|
||||
_[29]={}
|
||||
_[28]={}
|
||||
_[27]={}
|
||||
_[26]={}
|
||||
_[25]={text="3",tags=_[33]}
|
||||
_[24]={text="2",tags=_[32]}
|
||||
_[23]={text="1",tags=_[31]}
|
||||
_[22]={text="unscoped:",tags=_[30]}
|
||||
_[21]={text="1",tags=_[29]}
|
||||
_[20]={text="1",tags=_[28]}
|
||||
_[19]={text="1",tags=_[27]}
|
||||
_[18]={text="scoped:",tags=_[26]}
|
||||
_[17]={_[25]}
|
||||
_[16]={_[24]}
|
||||
_[15]={_[23]}
|
||||
_[14]={_[22]}
|
||||
_[13]={_[21]}
|
||||
_[12]={_[20]}
|
||||
_[11]={_[19]}
|
||||
_[10]={_[18]}
|
||||
_[9]={"return"}
|
||||
_[8]={"text",_[17]}
|
||||
_[7]={"text",_[16]}
|
||||
_[6]={"text",_[15]}
|
||||
_[5]={"text",_[14]}
|
||||
_[4]={"text",_[13]}
|
||||
_[3]={"text",_[12]}
|
||||
_[2]={"text",_[11]}
|
||||
_[1]={"text",_[10]}
|
||||
return {_[1],_[2],_[3],_[4],_[5],_[6],_[7],_[8],_[9]}
|
||||
--[[
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "scoped:"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "unscoped:"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "1"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "2"
|
||||
} } }
|
||||
{ "text", { {
|
||||
tags = {},
|
||||
text = "3"
|
||||
} } }
|
||||
{ "return" }
|
||||
]]--
|
||||
Loading…
Add table
Add a link
Reference in a new issue