mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
stdlib cleanup
This commit is contained in:
parent
dac5b74fa6
commit
a212dd7fd1
17 changed files with 212 additions and 190 deletions
39
anselme/stdlib/attached block.lua
Normal file
39
anselme/stdlib/attached block.lua
Normal 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
|
||||
},
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
}
|
||||
|
|
@ -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
|
||||
},
|
||||
}
|
||||
|
|
|
|||
53
anselme/stdlib/function.lua
Normal file
53
anselme/stdlib/function.lua
Normal 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
|
||||
},
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
28
anselme/stdlib/wrap.lua
Normal 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
|
||||
},
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
↳ from [4mtest/tests/merge nested mutable error bis.ans:3:1[0m in block: [2minsert(a, b)…[0m[0m
|
||||
↳ from [4mtest/tests/merge nested mutable error bis.ans:3:18[0m in call: [2m_[0m[0m
|
||||
↳ from [4mscript.ans:30:6[0m in call: [2mfn![0m[0m
|
||||
↳ from [4mscript.ans:28:3[0m in block: [2mresumed from = ()…[0m[0m
|
||||
↳ from [4mscript.ans:28:3[0m in block: [2mresume target = ()…[0m[0m
|
||||
↳ from [4mscript.ans:28:7[0m in call: [2melse![0m[0m
|
||||
↳ from [4mscript.ans:24:2[0m in block: [2mif(fn . "current checkpoint")…[0m[0m
|
||||
↳ from [4mscript.ans:24:9[0m in call: [2m_[0m[0m
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
↳ from [4mtest/tests/merge nested mutable error.ans:3:1[0m in block: [2minsert(a, b)…[0m[0m
|
||||
↳ from [4mtest/tests/merge nested mutable error.ans:3:18[0m in call: [2m_[0m[0m
|
||||
↳ from [4mscript.ans:30:6[0m in call: [2mfn![0m[0m
|
||||
↳ from [4mscript.ans:28:3[0m in block: [2mresumed from = ()…[0m[0m
|
||||
↳ from [4mscript.ans:28:3[0m in block: [2mresume target = ()…[0m[0m
|
||||
↳ from [4mscript.ans:28:7[0m in call: [2melse![0m[0m
|
||||
↳ from [4mscript.ans:24:2[0m in block: [2mif(fn . "current checkpoint")…[0m[0m
|
||||
↳ from [4mscript.ans:24:9[0m in call: [2m_[0m[0m
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
:f = $(anchor=())
|
||||
:x = 8
|
||||
($_)!resume(anchor)
|
||||
($_)!from(anchor)
|
||||
|a
|
||||
| A |>
|
||||
| b
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue