1
0
Fork 0
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:
Étienne Fildadut 2024-01-05 01:36:37 +01:00
parent a212dd7fd1
commit efb99a9ed7
28 changed files with 284 additions and 21 deletions

View file

@ -28,7 +28,7 @@ Typed = ast.abstract.Runtime {
return custom_format:call(state, d_args):format(state, prio, ...) return custom_format:call(state, d_args):format(state, prio, ...)
end end
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, end,
traverse = function(self, fn, ...) traverse = function(self, fn, ...)

View file

@ -11,12 +11,17 @@ return {
function(state, level, keep_return) function(state, level, keep_return)
-- level 2: env of the function that called the function that called attached block -- 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 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 if keep_return:truthy() then
return Function:new(ParameterTuple:new(), r.expression):eval(state) fn = Function:new(ParameterTuple:new(), block)
else else
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state) fn = Function:with_return_boundary(ParameterTuple:new(), block)
end end
state.scope:push(env)
fn = fn:eval(state) -- make closure
state.scope:pop()
return fn
end end
}, },
{ {
@ -25,12 +30,17 @@ return {
-- level 2: env of the function that called the function that called attached block -- 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 env = calling_environment_manager:get_level(state, level:to_lua(state)+1)
if env:defined(state, block_identifier) then 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 if keep_return:truthy() then
return Function:new(ParameterTuple:new(), r.expression):eval(state) fn = Function:new(ParameterTuple:new(), block)
else else
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state) fn = Function:with_return_boundary(ParameterTuple:new(), block)
end end
state.scope:push(env)
fn = fn:eval(state) -- make closure
state.scope:pop()
return fn
else else
return default return default
end end

50
anselme/stdlib/for.lua Normal file
View 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)
]]

View file

@ -26,6 +26,7 @@ return function(main_state)
"boot", "boot",
"number", "number",
"string", "string",
"symbol",
"text", "text",
"pair", "pair",
"structures", "structures",
@ -34,6 +35,7 @@ return function(main_state)
"function", "function",
"resume", "resume",
"persist", "persist",
"for",
"script" "script"
}) })
end end

View file

@ -1,5 +1,5 @@
local ast = require("anselme.ast") 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 { return {
-- tuple -- tuple
@ -112,6 +112,23 @@ return {
return s:get(k) return s:get(k)
end 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 -- table
{ {
@ -127,6 +144,12 @@ return {
return Nil:new() return Nil:new()
end end
}, },
{
"has", "(t::table, key)",
function(state, t, k)
return Boolean:new(t:has(state, k))
end
},
{ {
"to struct", "(t::table)", "to struct", "(t::table)",
function(state, t) function(state, t)

View file

@ -0,0 +1,9 @@
return {
{
"to string", "(symbol::symbol)",
function(state, sym)
return sym:to_string()
end
},
}

View file

@ -1,8 +1,8 @@
--# run #-- --# run #--
--- text --- --- text ---
| {}"" {}"type(\"kg\", 5)" {}"" | | {}"" {}"type(5, \"kg\")" {}"" |
--- text --- --- text ---
| {}"" {}"type(\"kg\", 12)" {}"" | | {}"" {}"type(12, \"kg\")" {}"" |
--- error --- --- error ---
type check failure for weigh; 32 does not satisfy $(x) type(x) == t type check failure for weigh; 32 does not satisfy $(x) type(x) == t
↳ from test/tests/constrained variable assignement.ans:9:7 in assignment: weigh = 32 ↳ from test/tests/constrained variable assignement.ans:9:7 in assignment: weigh = 32

View file

@ -1,6 +1,6 @@
--# run #-- --# run #--
--- text --- --- text ---
| {}"" {}"type(\"kg\", 5)" {}"" | | {}"" {}"type(5, \"kg\")" {}"" |
--- text --- --- text ---
| {}"" {}"12" {}"" | | {}"" {}"12" {}"" |
--- return --- --- return ---

View file

@ -5,7 +5,7 @@
--- text --- --- text ---
| {}"" {}"42" {}"" | | {}"" {}"42" {}"" |
--- error --- --- error ---
identifier "z" is undefined in branch cf017f8a-7c86-4871-109af-6658231331e6 identifier "z" is undefined in branch 7dfcaa5b-2163-4f36-116ed-c4ab6bc8d28b
↳ from test/tests/exported variable nested.ans:12:3 in identifier: z ↳ 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 test/tests/exported variable nested.ans:12:1 in text interpolation: | {z} |
↳ from ? in block: :f = ($() _)… ↳ from ? in block: :f = ($() _)…

View file

@ -0,0 +1,8 @@
--# run #--
--- text ---
| {}"" {}"1" {}"" |
| {}"" {}"2" {}"" |
--- return ---
()
--# saved #--
{}

View file

@ -0,0 +1,9 @@
--# run #--
--- text ---
| {}"" {}"1" {}"" |
| {}"" {}"2" {}"" |
| {}"" {}"4" {}"" |
--- return ---
()
--# saved #--
{}

View file

@ -0,0 +1,15 @@
--# run #--
--- error ---
can'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>))
↳ 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: _
↳ from test/tests/for invalid iterator.ans:1:4 in call: for(:x, 42)
↳ from ? in block: for(:x, 42)…
--# saved #--
{}

10
test/results/for list.ans Normal file
View file

@ -0,0 +1,10 @@
--# run #--
--- text ---
| {}"" {}"7" {}"" |
| {}"" {}"96" {}"" |
| {}"" {}"a" {}"" |
| {}"" {}"3" {}"" |
--- return ---
()
--# saved #--
{}

View 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 #--
{}

View file

@ -0,0 +1,10 @@
--# run #--
--- text ---
| {}"" {}"true" |
| {}"" {}"true" |
| {}"" {}"true" |
| {}"" {}"true" |
--- return ---
()
--# saved #--
{}

View file

@ -0,0 +1,10 @@
--# run #--
--- text ---
| {}"" {}"true" |
| {}"" {}"true" |
| {}"" {}"true" |
| {}"" {}"true" |
--- return ---
()
--# saved #--
{}

View file

@ -0,0 +1,11 @@
--# run #--
--- text ---
| {}"" {}"2" {}"" |
| {}"" {}"5" {}"" |
| {}"" {}"7" {}"" |
| {}"" {}"1" {}"" |
| {}"" {}"8" {}"" |
--- return ---
()
--# saved #--
{}

View file

@ -4,7 +4,7 @@
--- text --- --- text ---
| {}"" {}"idk" {}" is esperanto" | | {}"" {}"idk" {}" is esperanto" |
--- error --- --- error ---
can't call overload overload<($(name::($(x) type(x) == t)) _), ($(name::($(x) type(x) == t)) _)>: no function match (type("nope", 5)), possible functions were: 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))
• (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))
↳ from test/tests/function custom type dispatch error.ans:14:2 in call: a(type(5, "nope")) ↳ from test/tests/function custom type dispatch error.ans:14:2 in call: a(type(5, "nope"))

View file

@ -1,15 +1,15 @@
--# run #-- --# run #--
--- text --- --- text ---
| {}"c" |
--- text ---
| {}"b" |
--- text ---
| {}"a" | | {}"a" |
--- text --- --- text ---
| {}"b" | | {}"c" |
--- text --- --- text ---
| {}"b" | | {}"a" |
--- text ---
| {}"a" |
--- text ---
| {}"c" |
--- return --- --- return ---
() ()
--# saved #-- --# 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}

View file

@ -1,6 +1,6 @@
--# run #-- --# run #--
--- error --- --- error ---
identifier "b" is undefined in branch cf017f8a-7c86-4871-109af-6658231331e6 identifier "b" is undefined in branch 7dfcaa5b-2163-4f36-116ed-c4ab6bc8d28b
↳ from test/tests/function scope wrong.ans:4:7 in identifier: b ↳ 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 test/tests/function scope wrong.ans:4:1 in text interpolation: | a: {b} |
↳ from ? in block: :a = ($() _)… ↳ from ? in block: :a = ($() _)…

4
test/tests/for break.ans Normal file
View file

@ -0,0 +1,4 @@
for(:x, range(10))
if(x == 3)
break!
|{x}

View file

@ -0,0 +1,4 @@
for(:x, range(4))
if(x == 3)
continue!
|{x}

View file

@ -0,0 +1,2 @@
for(:x, 42)
|{x}

4
test/tests/for list.ans Normal file
View file

@ -0,0 +1,4 @@
:l = *[7,96,"a",3]
for(:x, l)
|{x}

27
test/tests/for range.ans Normal file
View 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}

View 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
View 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
View file

@ -0,0 +1,4 @@
:t = [2,5,7,1,8]
for(:x, t)
|{x}