mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
Add for loops
This commit is contained in:
parent
a212dd7fd1
commit
efb99a9ed7
28 changed files with 284 additions and 21 deletions
|
|
@ -28,7 +28,7 @@ Typed = ast.abstract.Runtime {
|
|||
return custom_format:call(state, d_args):format(state, prio, ...)
|
||||
end
|
||||
end
|
||||
return ("type(%s, %s)"):format(self.type_expression:format(state, operator_priority["_,_"], ...), self.expression:format_right(state, operator_priority["_,_"], ...))
|
||||
return ("type(%s, %s)"):format(self.expression:format(state, operator_priority["_,_"], ...), self.type_expression:format_right(state, operator_priority["_,_"], ...))
|
||||
end,
|
||||
|
||||
traverse = function(self, fn, ...)
|
||||
|
|
|
|||
|
|
@ -11,12 +11,17 @@ return {
|
|||
function(state, level, keep_return)
|
||||
-- level 2: env of the function that called the function that called attached block
|
||||
local env = calling_environment_manager:get_level(state, level:to_lua(state)+1)
|
||||
local r = env:get(state, block_identifier)
|
||||
local block = env:get(state, block_identifier).expression
|
||||
local fn
|
||||
if keep_return:truthy() then
|
||||
return Function:new(ParameterTuple:new(), r.expression):eval(state)
|
||||
fn = Function:new(ParameterTuple:new(), block)
|
||||
else
|
||||
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state)
|
||||
fn = Function:with_return_boundary(ParameterTuple:new(), block)
|
||||
end
|
||||
state.scope:push(env)
|
||||
fn = fn:eval(state) -- make closure
|
||||
state.scope:pop()
|
||||
return fn
|
||||
end
|
||||
},
|
||||
{
|
||||
|
|
@ -25,12 +30,17 @@ return {
|
|||
-- level 2: env of the function that called the function that called attached block
|
||||
local env = calling_environment_manager:get_level(state, level:to_lua(state)+1)
|
||||
if env:defined(state, block_identifier) then
|
||||
local r = env:get(state, block_identifier)
|
||||
local block = env:get(state, block_identifier).expression
|
||||
local fn
|
||||
if keep_return:truthy() then
|
||||
return Function:new(ParameterTuple:new(), r.expression):eval(state)
|
||||
fn = Function:new(ParameterTuple:new(), block)
|
||||
else
|
||||
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state)
|
||||
fn = Function:with_return_boundary(ParameterTuple:new(), block)
|
||||
end
|
||||
state.scope:push(env)
|
||||
fn = fn:eval(state) -- make closure
|
||||
state.scope:pop()
|
||||
return fn
|
||||
else
|
||||
return default
|
||||
end
|
||||
|
|
|
|||
50
anselme/stdlib/for.lua
Normal file
50
anselme/stdlib/for.lua
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
return [[
|
||||
/* For loop */
|
||||
:@$for(symbol::symbol, var, block=attached block(keep return=true))
|
||||
:iterator = iter(var)
|
||||
:value = iterator()
|
||||
:name = symbol!to string
|
||||
block.(symbol) = value
|
||||
while($value != ())
|
||||
:r = block!
|
||||
value = iterator()
|
||||
block.(name) = value
|
||||
r
|
||||
|
||||
/* Range iterables */
|
||||
:@$range(stop)
|
||||
[1, stop, 1]!type("range")
|
||||
:@$range(start, stop, step=1)
|
||||
[start, stop, step]!type("range")
|
||||
:@$iter(range::is("range"))
|
||||
:v = range!value
|
||||
:start = v(1)
|
||||
:stop = v(2)
|
||||
:step = v(3)
|
||||
:i = start
|
||||
if(step > 0)
|
||||
return($_)
|
||||
if(i <= stop)
|
||||
i += step
|
||||
return(i-step)
|
||||
else!
|
||||
return($_)
|
||||
if(i >= stop)
|
||||
i += step
|
||||
return(i-step)
|
||||
|
||||
/* List/tuple iterables */
|
||||
:tuple or list = $(x) x!type == "tuple" | x!type == "list"
|
||||
:@$iter(tuple::tuple or list)
|
||||
:n = tuple!len
|
||||
:i = 0
|
||||
$
|
||||
if(i < n)
|
||||
i += 1
|
||||
return(tuple(i))
|
||||
|
||||
/* Table */
|
||||
:@$iter(table::table)
|
||||
:s = table!to struct
|
||||
iter(s)
|
||||
]]
|
||||
|
|
@ -26,6 +26,7 @@ return function(main_state)
|
|||
"boot",
|
||||
"number",
|
||||
"string",
|
||||
"symbol",
|
||||
"text",
|
||||
"pair",
|
||||
"structures",
|
||||
|
|
@ -34,6 +35,7 @@ return function(main_state)
|
|||
"function",
|
||||
"resume",
|
||||
"persist",
|
||||
"for",
|
||||
"script"
|
||||
})
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
local ast = require("anselme.ast")
|
||||
local Nil, List, Table, Number = ast.Nil, ast.List, ast.Table, ast.Number
|
||||
local Nil, List, Table, Number, LuaFunction, ParameterTuple, Boolean = ast.Nil, ast.List, ast.Table, ast.Number, ast.LuaFunction, ast.ParameterTuple, ast.Boolean
|
||||
|
||||
return {
|
||||
-- tuple
|
||||
|
|
@ -112,6 +112,23 @@ return {
|
|||
return s:get(k)
|
||||
end
|
||||
},
|
||||
{
|
||||
"has", "(s::struct, key)",
|
||||
function(state, s, k)
|
||||
return Boolean:new(s:has(k))
|
||||
end
|
||||
},
|
||||
{
|
||||
"iter", "(s::struct)",
|
||||
function(state, struct)
|
||||
local iter = struct:iter()
|
||||
return LuaFunction:new(ParameterTuple:new(), function()
|
||||
local k = iter()
|
||||
if k == nil then return Nil:new()
|
||||
else return k end
|
||||
end)
|
||||
end
|
||||
},
|
||||
|
||||
-- table
|
||||
{
|
||||
|
|
@ -127,6 +144,12 @@ return {
|
|||
return Nil:new()
|
||||
end
|
||||
},
|
||||
{
|
||||
"has", "(t::table, key)",
|
||||
function(state, t, k)
|
||||
return Boolean:new(t:has(state, k))
|
||||
end
|
||||
},
|
||||
{
|
||||
"to struct", "(t::table)",
|
||||
function(state, t)
|
||||
|
|
|
|||
9
anselme/stdlib/symbol.lua
Normal file
9
anselme/stdlib/symbol.lua
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
return {
|
||||
|
||||
{
|
||||
"to string", "(symbol::symbol)",
|
||||
function(state, sym)
|
||||
return sym:to_string()
|
||||
end
|
||||
},
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"type(\"kg\", 5)" {}"" |
|
||||
| {}"" {}"type(5, \"kg\")" {}"" |
|
||||
--- text ---
|
||||
| {}"" {}"type(\"kg\", 12)" {}"" |
|
||||
| {}"" {}"type(12, \"kg\")" {}"" |
|
||||
--- error ---
|
||||
[0m[31m[0m[31mtype check failure for weigh; 32 does not satisfy $(x) type(x) == t[0m
|
||||
↳ from [4mtest/tests/constrained variable assignement.ans:9:7[0m in assignment: [2mweigh = 32[0m[0m
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"type(\"kg\", 5)" {}"" |
|
||||
| {}"" {}"type(5, \"kg\")" {}"" |
|
||||
--- text ---
|
||||
| {}"" {}"12" {}"" |
|
||||
--- return ---
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
--- text ---
|
||||
| {}"" {}"42" {}"" |
|
||||
--- error ---
|
||||
[0m[31m[0m[31m[0m[31midentifier "z" is undefined in branch cf017f8a-7c86-4871-109af-6658231331e6[0m
|
||||
[0m[31m[0m[31m[0m[31midentifier "z" is undefined in branch 7dfcaa5b-2163-4f36-116ed-c4ab6bc8d28b[0m
|
||||
↳ from [4mtest/tests/exported variable nested.ans:12:3[0m in identifier: [2mz[0m[0m
|
||||
↳ from [4mtest/tests/exported variable nested.ans:12:1[0m in text interpolation: [2m| {z} |[0m[0m
|
||||
↳ from [4m?[0m in block: [2m:f = ($() _)…[0m
|
||||
|
|
|
|||
8
test/results/for break.ans
Normal file
8
test/results/for break.ans
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"1" {}"" |
|
||||
| {}"" {}"2" {}"" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
9
test/results/for continue.ans
Normal file
9
test/results/for continue.ans
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"1" {}"" |
|
||||
| {}"" {}"2" {}"" |
|
||||
| {}"" {}"4" {}"" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
15
test/results/for invalid iterator.ans
Normal file
15
test/results/for invalid iterator.ans
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
--# run #--
|
||||
--- error ---
|
||||
[0m[31m[0m[31m[0m[31m[0m[31m[0m[31m[0m[31mcan't call overload overload<($(table::($(x) <lua function>)) _), ($(tuple::($(x) type(x) == "tuple" | type(x) == "list")) _), ($(range::($(x) type(x) == t)) _), ($(s::($(x) <lua function>)) <lua function>)>: no function match (42), possible functions were:
|
||||
• (table::($(x) <lua function>)): type check failure for parameter table in function (table::($(x) <lua function>))
|
||||
• (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) <lua function>)): type check failure for parameter s in function (s::($(x) <lua function>))[0m
|
||||
↳ from [4mfor.ans:3:18[0m in call: [2miter(var)[0m[0m
|
||||
↳ from [4mfor.ans:3:12[0m in definition: [2m:iterator = iter(var)[0m[0m
|
||||
↳ from [4mfor.ans:2:1[0m in block: [2m:iterator = iter(var)…[0m[0m
|
||||
↳ from [4mfor.ans:2:68[0m in call: [2m_[0m[0m
|
||||
↳ from [4mtest/tests/for invalid iterator.ans:1:4[0m in call: [2mfor(:x, 42)[0m[0m
|
||||
↳ from [4m?[0m in block: [2mfor(:x, 42)…[0m
|
||||
--# saved #--
|
||||
{}
|
||||
10
test/results/for list.ans
Normal file
10
test/results/for list.ans
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"7" {}"" |
|
||||
| {}"" {}"96" {}"" |
|
||||
| {}"" {}"a" {}"" |
|
||||
| {}"" {}"3" {}"" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
38
test/results/for range.ans
Normal file
38
test/results/for range.ans
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"-" |
|
||||
| {}"" {}"1" {}"" |
|
||||
| {}"" {}"2" {}"" |
|
||||
| {}"" {}"3" {}"" |
|
||||
| {}"" {}"4" {}"" |
|
||||
| {}"" {}"5" {}"" |
|
||||
--- text ---
|
||||
| {}"-" |
|
||||
| {}"" {}"2" {}"" |
|
||||
| {}"" {}"3" {}"" |
|
||||
| {}"" {}"4" {}"" |
|
||||
| {}"" {}"5" {}"" |
|
||||
| {}"" {}"6" {}"" |
|
||||
| {}"" {}"7" {}"" |
|
||||
--- text ---
|
||||
| {}"-" |
|
||||
| {}"" {}"2" {}"" |
|
||||
| {}"" {}"5" {}"" |
|
||||
--- text ---
|
||||
| {}"-" |
|
||||
| {}"" {}"4" {}"" |
|
||||
| {}"" {}"3" {}"" |
|
||||
| {}"" {}"2" {}"" |
|
||||
| {}"" {}"1" {}"" |
|
||||
| {}"" {}"0" {}"" |
|
||||
--- text ---
|
||||
| {}"-" |
|
||||
--- text ---
|
||||
| {}"-" |
|
||||
--- text ---
|
||||
| {}"-" |
|
||||
| {}"" {}"4" {}"" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
10
test/results/for struct.ans
Normal file
10
test/results/for struct.ans
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"true" |
|
||||
| {}"" {}"true" |
|
||||
| {}"" {}"true" |
|
||||
| {}"" {}"true" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
10
test/results/for table.ans
Normal file
10
test/results/for table.ans
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"true" |
|
||||
| {}"" {}"true" |
|
||||
| {}"" {}"true" |
|
||||
| {}"" {}"true" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
11
test/results/for tuple.ans
Normal file
11
test/results/for tuple.ans
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"" {}"2" {}"" |
|
||||
| {}"" {}"5" {}"" |
|
||||
| {}"" {}"7" {}"" |
|
||||
| {}"" {}"1" {}"" |
|
||||
| {}"" {}"8" {}"" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
--- text ---
|
||||
| {}"" {}"idk" {}" is esperanto" |
|
||||
--- error ---
|
||||
[0m[31m[0m[31mcan't call overload overload<($(name::($(x) type(x) == t)) _), ($(name::($(x) type(x) == t)) _)>: no function match (type("nope", 5)), possible functions were:
|
||||
[0m[31m[0m[31mcan'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))[0m
|
||||
↳ from [4mtest/tests/function custom type dispatch error.ans:14:2[0m in call: [2ma(type(5, "nope"))[0m[0m
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
--# run #--
|
||||
--- text ---
|
||||
| {}"c" |
|
||||
--- text ---
|
||||
| {}"b" |
|
||||
--- text ---
|
||||
| {}"a" |
|
||||
--- text ---
|
||||
| {}"b" |
|
||||
| {}"c" |
|
||||
--- text ---
|
||||
| {}"b" |
|
||||
| {}"a" |
|
||||
--- text ---
|
||||
| {}"a" |
|
||||
--- text ---
|
||||
| {}"c" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{"a.checkpoint":false, "a.run":1, "b.checkpoint":false, "b.run":3, "c.checkpoint":false, "c.run":1}
|
||||
{"a.checkpoint":false, "a.run":3, "c.checkpoint":false, "c.run":2}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
--# run #--
|
||||
--- error ---
|
||||
[0m[31m[0m[31m[0m[31midentifier "b" is undefined in branch cf017f8a-7c86-4871-109af-6658231331e6[0m
|
||||
[0m[31m[0m[31m[0m[31midentifier "b" is undefined in branch 7dfcaa5b-2163-4f36-116ed-c4ab6bc8d28b[0m
|
||||
↳ from [4mtest/tests/function scope wrong.ans:4:7[0m in identifier: [2mb[0m[0m
|
||||
↳ from [4mtest/tests/function scope wrong.ans:4:1[0m in text interpolation: [2m| a: {b} |[0m[0m
|
||||
↳ from [4m?[0m in block: [2m:a = ($() _)…[0m
|
||||
|
|
|
|||
4
test/tests/for break.ans
Normal file
4
test/tests/for break.ans
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
for(:x, range(10))
|
||||
if(x == 3)
|
||||
break!
|
||||
|{x}
|
||||
4
test/tests/for continue.ans
Normal file
4
test/tests/for continue.ans
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
for(:x, range(4))
|
||||
if(x == 3)
|
||||
continue!
|
||||
|{x}
|
||||
2
test/tests/for invalid iterator.ans
Normal file
2
test/tests/for invalid iterator.ans
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
for(:x, 42)
|
||||
|{x}
|
||||
4
test/tests/for list.ans
Normal file
4
test/tests/for list.ans
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
:l = *[7,96,"a",3]
|
||||
|
||||
for(:x, l)
|
||||
|{x}
|
||||
27
test/tests/for range.ans
Normal file
27
test/tests/for range.ans
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|-
|
||||
for(:x, range(5))
|
||||
|{x}
|
||||
|
||||
|-
|
||||
for(:y, range(2, 7))
|
||||
|{y}
|
||||
|
||||
|-
|
||||
for(:z, range(2, 7, 3))
|
||||
|{z}
|
||||
|
||||
|-
|
||||
for(:x, range(4, 0, -1))
|
||||
|{x}
|
||||
|
||||
|-
|
||||
for(:x, range(4, 8, -1))
|
||||
|{x}
|
||||
|
||||
|-
|
||||
for(:x, range(8, 4))
|
||||
|{x}
|
||||
|
||||
|-
|
||||
for(:x, range(4, 4))
|
||||
|{x}
|
||||
7
test/tests/for struct.ans
Normal file
7
test/tests/for struct.ans
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
:s = { "a":"b", 6:"c", 98:5, true:3 }
|
||||
:t = *s
|
||||
|
||||
/* struct iteration is non deterministic, too lazy to sort, so we check if we have 4 key that each appear at most once */
|
||||
for(:k, s)
|
||||
|{t!has(k)}|
|
||||
t(k) = ()
|
||||
6
test/tests/for table.ans
Normal file
6
test/tests/for table.ans
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
:s = *{ "a":"b", 6:"c", 98:5, true:3 }
|
||||
|
||||
/* struct iteration is non deterministic, too lazy to sort, so we check if we have 4 key that each appear at most once */
|
||||
for(:k, s)
|
||||
|{s!has(k)}|
|
||||
s(k) = ()
|
||||
4
test/tests/for tuple.ans
Normal file
4
test/tests/for tuple.ans
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
:t = [2,5,7,1,8]
|
||||
|
||||
for(:x, t)
|
||||
|{x}
|
||||
Loading…
Add table
Add a link
Reference in a new issue