1
0
Fork 0
mirror of https://github.com/Reuh/anselme.git synced 2025-10-27 16:49:31 +00:00

stdlib cleanup

This commit is contained in:
Étienne Fildadut 2024-01-04 20:45:23 +01:00
parent dac5b74fa6
commit a212dd7fd1
17 changed files with 212 additions and 190 deletions

View file

@ -0,0 +1,39 @@
local ast = require("anselme.ast")
local Function, ParameterTuple, Identifier = ast.Function, ast.ParameterTuple, ast.Identifier
local calling_environment_manager = require("anselme.state.calling_environment_manager")
local block_identifier = Identifier:new("_")
return {
{
"attached block", "(level::number=1, keep return=false)",
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)
if keep_return:truthy() then
return Function:new(ParameterTuple:new(), r.expression):eval(state)
else
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state)
end
end
},
{
"attached block", "(level::number=1, keep return=false, default)",
function(state, level, keep_return, default)
-- 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)
if keep_return:truthy() then
return Function:new(ParameterTuple:new(), r.expression):eval(state)
else
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state)
end
else
return default
end
end
},
}

View file

@ -1,21 +1,10 @@
local ast = require("anselme.ast")
local Pair, ArgumentTuple, Nil, String, Typed, Boolean = ast.Pair, ast.ArgumentTuple, ast.Nil, ast.String, ast.Typed, ast.Boolean
local Nil, String = ast.Nil, ast.String
return {
{ "_;_", "(left, right)", function(state, left, right) return right end },
{ "_;", "(left)", function(state, left) return Nil:new() end },
{ "_:_", "(name, value)", function(state, a, b) return Pair:new(a,b) end },
{
"_::_", "(value, check)",
function(state, value, check)
local r = check:call(state, ArgumentTuple:new(value))
if r:truthy() then
return value
else
error(("type check failure: %s does not satisfy %s"):format(value:format(state), check:format(state)), 0)
end
end
},
{
"print", "(a)",
function(state, a)
@ -29,35 +18,6 @@ return {
return String:new(a:hash())
end
},
{
"type", "(value)",
function(state, v)
if v.type == "typed" then
return v.type_expression
else
return String:new(v.type)
end
end
},
{
"value", "(value)",
function(state, v)
if v.type == "typed" then
return v.expression
else
return v
end
end
},
{
"type", "(value, type)",
function(state, v, t)
return Typed:new(v, t)
end
},
{ "true", Boolean:new(true) },
{ "false", Boolean:new(false) },
{
"error", "(message=\"error\")",
function(state, message)

View file

@ -2,6 +2,9 @@ local ast = require("anselme.ast")
local Boolean, ArgumentTuple = ast.Boolean, ast.ArgumentTuple
return {
{ "true", Boolean:new(true) },
{ "false", Boolean:new(false) },
{
"_==_", "(a, b)",
function(state, a, b)

View file

@ -1,122 +0,0 @@
local ast = require("anselme.ast")
local Nil, Boolean, Definition, Call, Function, ParameterTuple, FunctionParameter, Identifier, Overload, Assignment, Return = ast.Nil, ast.Boolean, ast.Definition, ast.Call, ast.Function, ast.ParameterTuple, ast.FunctionParameter, ast.Identifier, ast.Overload, ast.Assignment, ast.Return
local assert0 = require("anselme.common").assert0
local calling_environment_manager = require("anselme.state.calling_environment_manager")
local block_identifier = Identifier:new("_")
return {
{
"defined", "(c::function, s::string)",
function(state, c, s)
return Boolean:new(c.scope:defined_in_current(state, s:to_identifier()))
end
},
{
"has upvalue", "(c::function, s::string)",
function(state, c, s)
return Boolean:new(c.scope:defined(state, s:to_identifier()))
end
},
{
"_._", "(c::function, s::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))
return c.scope:get(state, identifier)
end
},
{
"_._", "(c::function, s::string) = v",
function(state, c, s, v)
local identifier = s:to_identifier()
assert0(c.scope:defined(state, identifier), ("no variable %q defined in closure"):format(s.string))
c.scope:set(state, identifier, v)
return Nil:new()
end
},
{
"_._", "(c::function, s::symbol) = v",
function(state, c, s, v)
state.scope:push(c.scope)
local r = Definition:new(s, v):eval(state)
state.scope:pop()
return r
end
},
{
">_", "(q::is(\"quote\"))",
function(state, q)
local exp = q.expression
local get = Function:with_return_boundary(ParameterTuple:new(), exp):eval(state)
local set_exp
if Call:is(exp) then
set_exp = Call:new(exp.func, exp.arguments:with_assignment(Identifier:new("value")))
elseif Identifier:is(exp) then
set_exp = Assignment:new(exp, Identifier:new("value"))
end
if set_exp then
local set_param = ParameterTuple:new()
set_param:insert_assignment(FunctionParameter:new(Identifier:new("value")))
local set = Function:with_return_boundary(set_param, set_exp):eval(state)
return Overload:new(get, set)
else
return get
end
end
},
{
"return", "(value=())",
function(state, val)
if Return:is(val) then val = val.expression end
return Return:new(val)
end
},
{
"break", "(value=())",
function(state, val)
if Return:is(val) then val = val.expression end
return Return:new(val, "break")
end
},
{
"continue", "(value=())",
function(state, val)
if Return:is(val) then val = val.expression end
return Return:new(val, "continue")
end
},
{
"attached block", "(level::number=1, keep return=false)",
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)
if keep_return:truthy() then
return Function:new(ParameterTuple:new(), r.expression):eval(state)
else
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state)
end
end
},
{
"attached block", "(level::number=1, keep return=false, default)",
function(state, level, keep_return, default)
-- 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)
if keep_return:truthy() then
return Function:new(ParameterTuple:new(), r.expression):eval(state)
else
return Function:with_return_boundary(ParameterTuple:new(), r.expression):eval(state)
end
else
return default
end
end
},
}

View file

@ -66,6 +66,7 @@ return {
end
end
},
{
"while", "(condition, expression=attached block(keep return=true))",
function(state, condition, expression)
@ -94,4 +95,18 @@ return {
return r
end
},
{
"break", "(value=())",
function(state, val)
if Return:is(val) then val = val.expression end
return Return:new(val, "break")
end
},
{
"continue", "(value=())",
function(state, val)
if Return:is(val) then val = val.expression end
return Return:new(val, "continue")
end
},
}

View file

@ -0,0 +1,53 @@
local ast = require("anselme.ast")
local Nil, Boolean, Definition, Return = ast.Nil, ast.Boolean, ast.Definition, ast.Return
local assert0 = require("anselme.common").assert0
return {
{
"defined", "(c::function, s::string)",
function(state, c, s)
return Boolean:new(c.scope:defined_in_current(state, s:to_identifier()))
end
},
{
"has upvalue", "(c::function, s::string)",
function(state, c, s)
return Boolean:new(c.scope:defined(state, s:to_identifier()))
end
},
{
"_._", "(c::function, s::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))
return c.scope:get(state, identifier)
end
},
{
"_._", "(c::function, s::string) = v",
function(state, c, s, v)
local identifier = s:to_identifier()
assert0(c.scope:defined(state, identifier), ("no variable %q defined in closure"):format(s.string))
c.scope:set(state, identifier, v)
return Nil:new()
end
},
{
"_._", "(c::function, s::symbol) = v",
function(state, c, s, v)
state.scope:push(c.scope)
local r = Definition:new(s, v):eval(state)
state.scope:pop()
return r
end
},
{
"return", "(value=())",
function(state, val)
if Return:is(val) then val = val.expression end
return Return:new(val)
end
},
}

View file

@ -7,7 +7,12 @@ local function define_lua(state, list)
end
local function load(state, l)
for _, m in ipairs(l) do
define_lua(state, require("anselme.stdlib."..m))
local mod = require("anselme.stdlib."..m)
if type(mod) == "string" then
parser(mod, m..".ans"):eval(state)
else
define_lua(state, mod)
end
end
end
@ -17,21 +22,18 @@ return function(main_state)
"tag",
"conditionals",
"base",
"type_check"
})
parser(require("anselme.stdlib.boot_script"), "boot.ans"):eval(main_state)
load(main_state, {
"types",
"boot",
"number",
"string",
"text",
"pair",
"structures",
"closure",
"checkpoint",
"wrap",
"attached block",
"function",
"resume",
"persist",
"script"
})
parser(require("anselme.stdlib.script_script"), "script.ans"):eval(main_state)
end

View file

@ -2,6 +2,8 @@ local ast = require("anselme.ast")
local Boolean, Number = ast.Boolean, ast.Number
return {
{ "pi", Number:new(math.pi) },
{
"_<_", "(a::number, b::number)",
function(state, a, b)
@ -64,6 +66,4 @@ return {
end
end
},
{ "pi", Number:new(math.pi) }
}

View file

@ -1,4 +1,9 @@
local ast = require("anselme.ast")
local Pair = ast.Pair
return {
{ "_:_", "(name, value)", function(state, a, b) return Pair:new(a,b) end },
{
"name", "(pair::pair)",
function(state, pair)

View file

@ -6,13 +6,13 @@ local calling_environment_manager = require("anselme.state.calling_environment_m
return {
{
"resume", "(function::function, anchor::anchor)",
"from", "(function::function, anchor::anchor)",
function(state, func, anchor)
return func:resume(state, anchor)
end
},
{
"resume", "(function::function, anchor::nil)",
"from", "(function::function, anchor::nil)",
function(state, func)
return func:call(state, ArgumentTuple:new())
end

View file

@ -4,30 +4,30 @@ return [[
fn.:&reached => "{name}.reached"!persist(*{})
fn.:&run => "{name}.run"!persist(0)
:resumed from = ()
:resume target = ()
fn.:check = $(anchor::anchor)
fn.reached(anchor) = (fn.reached(anchor) | 0) + 1
fn.:checkpoint = $(anchor::anchor, on resume=attached block(default=()))
if(on resume)
fn.current checkpoint = anchor
if(resumed from == anchor | resuming(4))
if(resume target == anchor | resuming(4))
on resume!
else!
fn.reached(anchor) = (fn.reached(anchor) | 0) + 1
merge branch!
else!
fn.current checkpoint = anchor
if(resumed from != anchor)
if(resume target != anchor)
fn.reached(anchor) = (fn.reached(anchor) | 0) + 1
merge branch!
:f = $
if(fn.current checkpoint)
resumed from = fn.current checkpoint
fn!resume(fn.current checkpoint)
resume target = fn.current checkpoint
fn!from(fn.current checkpoint)
else!
resumed from = ()
resume target = ()
fn!
fn.run += 1
@ -52,7 +52,7 @@ return [[
s.current checkpoint = ()
return(s!)
/*Additionnal helpers*/
/* Additionnal helpers */
:@$ cycle(l::tuple)
:i = 2
while($i <= l!len)

View file

@ -1,7 +1,46 @@
local ast = require("anselme.ast")
local Boolean = ast.Boolean
local ArgumentTuple, Boolean, String, Typed = ast.ArgumentTuple, ast.Boolean, ast.String, ast.Typed
return {
{
"_::_", "(value, check)",
function(state, value, check)
local r = check:call(state, ArgumentTuple:new(value))
if r:truthy() then
return value
else
error(("type check failure: %s does not satisfy %s"):format(value:format(state), check:format(state)), 0)
end
end
},
{
"type", "(value)",
function(state, v)
if v.type == "typed" then
return v.type_expression
else
return String:new(v.type)
end
end
},
{
"type", "(value, type)",
function(state, v, t)
return Typed:new(v, t)
end
},
{
"value", "(value)",
function(state, v)
if v.type == "typed" then
return v.expression
else
return v
end
end
},
{ "nil", "(x)", function(state, x) return Boolean:new(x.type == "nil") end },
{ "number", "(x)", function(state, x) return Boolean:new(x.type == "number") end },
{ "string", "(x)", function(state, x) return Boolean:new(x.type == "string") end },

28
anselme/stdlib/wrap.lua Normal file
View file

@ -0,0 +1,28 @@
local ast = require("anselme.ast")
local Call, Function, ParameterTuple, FunctionParameter, Identifier, Overload, Assignment = ast.Call, ast.Function, ast.ParameterTuple, ast.FunctionParameter, ast.Identifier, ast.Overload, ast.Assignment
return {
{
">_", "(q::is(\"quote\"))",
function(state, q)
local exp = q.expression
local get = Function:with_return_boundary(ParameterTuple:new(), exp):eval(state)
local set_exp
if Call:is(exp) then
set_exp = Call:new(exp.func, exp.arguments:with_assignment(Identifier:new("value")))
elseif Identifier:is(exp) then
set_exp = Assignment:new(exp, Identifier:new("value"))
end
if set_exp then
local set_param = ParameterTuple:new()
set_param:insert_assignment(FunctionParameter:new(Identifier:new("value")))
local set = Function:with_return_boundary(set_param, set_exp):eval(state)
return Overload:new(get, set)
else
return get
end
end
},
}

View file

@ -5,7 +5,7 @@
↳ 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: resumed from = ()…
↳ 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: _

View file

@ -5,7 +5,7 @@
↳ 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: resumed from = ()…
↳ 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: _

View file

@ -8,7 +8,7 @@
:f = $(anchor=())
:x = 8
($_)!resume(anchor)
($_)!from(anchor)
|a
| A |>
| b