Packages

An embedded lisp interpreter based on the gleam implementation of MAL lisp.

Current section

Files

Jump to
kirala_l4u src l4u@bif_lib.erl
Raw

src/l4u@bif_lib.erl

-module(l4u@bif_lib).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([moddir_to_modulename/1, erlang_module_of/1, invoke_native_function/2, bif_lib_def/0]).
-spec bif_pr_str(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_pr_str(Exprs, Env) ->
Str = begin
_pipe = gleam@list:map(Exprs, fun l4u@l4u_core:print/1),
gleam@string:join(_pipe, <<" "/utf8>>)
end,
{with_env, {string, Str}, Env}.
-spec bif_seq(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_seq(Exprs, Env) ->
[X] = case Exprs of
[_] -> Exprs;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_seq"/utf8>>,
line => 45})
end,
Seq = case X of
nil ->
nil;
{string, <<""/utf8>>} ->
nil;
{string, S} ->
Graphemes = begin
_pipe = gleam@string:to_graphemes(S),
gleam@list:map(_pipe, fun(Field@0) -> {string, Field@0} end)
end,
{list, Graphemes};
{list, Xs} ->
case Xs of
[] ->
nil;
_ ->
{list, Xs}
end;
{vector, Xs} ->
case Xs of
[] ->
nil;
_ ->
{list, Xs}
end;
_ ->
l4u@sys_bridge_ffi:throw_err(
<<"seq: wrong number of arguments"/utf8>>
),
undefined
end,
{with_env, Seq, Env}.
-spec bif_os_cmd(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_os_cmd(Exprs, Env) ->
[{string, Cmd}] = case Exprs of
[{string, _}] -> Exprs;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_os_cmd"/utf8>>,
line => 70})
end,
Res_str = l4u@sys_bridge_ffi:os_cmd(Cmd),
{with_env, {string, Res_str}, Env}.
-spec bif_native_nodes(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_native_nodes(Exprs, Env) ->
Nodes = l4u@sys_bridge_ffi:erl_get_nodes(),
{with_env, Nodes, Env}.
-spec bif_native_processes(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_native_processes(Exprs, Env) ->
Processes = l4u@sys_bridge_ffi:erl_get_processes(),
{with_env, Processes, Env}.
-spec bif_erl_self(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_erl_self(Exprs, Env) ->
{with_env,
{native_value, <<"pid"/utf8>>, l4u_ffi:unsafe_corece(erlang:self())},
Env}.
-spec bif_erl_send(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_erl_send(Exprs, Env) ->
{with_env, undefined, Env}.
-spec bif_erl_receive_from(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_erl_receive_from(Exprs, Env) ->
{with_env, undefined, Env}.
-spec moddir_to_modulename(list(l4u@l4u_type:expr())) -> binary().
moddir_to_modulename(Moddir) ->
gleam@string:join(
gleam@list:map(Moddir, fun l4u@l4u_core:pstr/1),
<<"@"/utf8>>
).
-spec erlang_module_of(list(l4u@l4u_type:expr())) -> binary().
erlang_module_of(Exprs) ->
Module@1 = case Exprs of
[{string, Module}] ->
Module;
[{symbol, Module}] ->
Module;
[{keyword, Module}] ->
Module;
[{list, Moddirs}] ->
moddir_to_modulename(Moddirs);
[{vector, Moddirs}] ->
moddir_to_modulename(Moddirs);
_ ->
l4u@sys_bridge_ffi:throw_err(
<<"native-module-info: wrong number of arguments"/utf8>>
),
<<"err"/utf8>>
end,
Module@1.
-spec bif_native_module_info(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_native_module_info(Exprs, Env) ->
Module = erlang_module_of(Exprs),
Module_info = l4u@sys_bridge_ffi:erl_get_module_info(Module),
{with_env, {native_value, <<"module_info"/utf8>>, Module_info}, Env}.
-spec bif_import_native_module(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_import_native_module(Exprs, Env) ->
Exprs@1 = case Exprs of
[Moddir] ->
[Moddir, {string, <<""/utf8>>}, {list, []}];
[Moddir@1, Prefix] ->
[Moddir@1, Prefix, {list, []}];
[Moddir@2, Prefix@1, Options] ->
[Moddir@2, Prefix@1, Options];
Unhandable ->
l4u@sys_bridge_ffi:throw_err(
<<"import-native-module: wrong number of arguments"/utf8>>
),
[]
end,
Imported_functions = case Exprs@1 of
[Moddir@3, Prefix@2, Options@1] ->
_assert_subject = l4u@l4u_core:uneval(Moddir@3),
{list, Moddir@4} = case _assert_subject of
{list, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_import_native_module"/utf8>>,
line => 218})
end,
_assert_subject@1 = l4u@l4u_core:uneval(Options@1),
{list, Options@2} = case _assert_subject@1 of
{list, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_import_native_module"/utf8>>,
line => 219})
end,
Prefix@3 = l4u@l4u_core:pstr(Prefix@2),
Modname = moddir_to_modulename(Moddir@4),
Functions = l4u@sys_bridge_ffi:erl_get_module_functions(Modname),
Underscore_to_hyphen = gleam@list:contains(
Options@2,
{keyword, <<"underscore-to-hyphen"/utf8>>}
),
Delimiter = <<":"/utf8>>,
gleam@list:map(
Functions,
fun(Fnname_and_arity) ->
{Fnname, Arity} = case Fnname_and_arity of
{_, _} -> Fnname_and_arity;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@2,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_import_native_module"/utf8>>,
line => 234})
end,
Alias_name = case Prefix@3 of
<<""/utf8>> ->
Fnname;
_ ->
gleam@string:join([Prefix@3, Fnname], Delimiter)
end,
Fnname@1 = case Underscore_to_hyphen of
true ->
gleam@string:replace(
Fnname,
<<"_"/utf8>>,
<<"-"/utf8>>
);
_ ->
Fnname
end,
l4u@sys_bridge_ffi:process_dict_set(
erlang:element(3, Env),
Alias_name,
{native_function,
Alias_name,
l4u_ffi:unsafe_corece(
l4u@sys_bridge_ffi:erl_ref_native_fun(
Modname,
Fnname@1
)
)}
),
{string, Alias_name}
end
);
_ ->
l4u@sys_bridge_ffi:throw_err(
<<"import-native-module: wrong number of arguments"/utf8>>
),
[]
end,
{with_env, {list, Imported_functions}, Env}.
-spec bif_import_native_function(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_import_native_function(Exprs, Env) ->
case Exprs of
[Moddir, Fnname, Alias] ->
_assert_subject = l4u@l4u_core:uneval(Moddir),
{list, Moddir@1} = case _assert_subject of
{list, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_import_native_function"/utf8>>,
line => 269})
end,
Fnname@1 = l4u@l4u_core:pstr(Fnname),
Alias_name = l4u@l4u_core:pstr(Alias),
Modname = gleam@string:join(
gleam@list:map(Moddir@1, fun l4u@l4u_core:pstr/1),
<<"@"/utf8>>
),
l4u@sys_bridge_ffi:process_dict_set(
erlang:element(3, Env),
Alias_name,
{native_function,
Fnname@1,
l4u_ffi:unsafe_corece(
l4u@sys_bridge_ffi:erl_ref_native_fun(Modname, Fnname@1)
)}
);
[Moddir@2, Fnname@2] ->
_assert_subject@1 = l4u@l4u_core:uneval(Moddir@2),
{list, Moddir@3} = case _assert_subject@1 of
{list, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_import_native_function"/utf8>>,
line => 284})
end,
Fnname@3 = l4u@l4u_core:pstr(Fnname@2),
Alias_name@1 = Fnname@3,
Modname@1 = gleam@string:join(
gleam@list:map(Moddir@3, fun l4u@l4u_core:pstr/1),
<<"@"/utf8>>
),
l4u@sys_bridge_ffi:process_dict_set(
erlang:element(3, Env),
Alias_name@1,
{native_function,
Alias_name@1,
l4u_ffi:unsafe_corece(
l4u@sys_bridge_ffi:erl_ref_native_fun(
Modname@1,
Fnname@3
)
)}
);
Unhandable ->
l4u@sys_bridge_ffi:throw_err(
<<"import-native-function: wrong number of arguments"/utf8>>
)
end,
nil.
-spec bif_import_native_functions(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_import_native_functions(Exprs, Env) ->
case Exprs of
[Moddir, Fnnames] ->
_assert_subject = l4u@l4u_core:uneval(Moddir),
{list, Moddir@1} = case _assert_subject of
{list, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_import_native_functions"/utf8>>,
line => 308})
end,
_assert_subject@1 = l4u@l4u_core:uneval(Fnnames),
{list, Fnnames@1} = case _assert_subject@1 of
{list, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_import_native_functions"/utf8>>,
line => 309})
end,
Modname = gleam@string:join(
gleam@list:map(Moddir@1, fun l4u@l4u_core:pstr/1),
<<"@"/utf8>>
),
gleam@list:each(
Fnnames@1,
fun(Fnname) ->
Fnname@1 = l4u@l4u_core:pstr(Fnname),
Alias_name = Fnname@1,
l4u@sys_bridge_ffi:process_dict_set(
erlang:element(3, Env),
Alias_name,
{native_function,
Alias_name,
l4u_ffi:unsafe_corece(
l4u@sys_bridge_ffi:erl_ref_native_fun(
Modname,
Fnname@1
)
)}
)
end
);
_ ->
l4u@sys_bridge_ffi:throw_err(
<<"import-native-functions: wrong number of arguments"/utf8>>
)
end,
nil.
-spec bif_native_function(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_native_function(Exprs, Env) ->
case Exprs of
[Moddir, Fnname] ->
Modname = case l4u@l4u_core:uneval(Moddir) of
{vector, Moddir@1} ->
moddir_to_modulename(Moddir@1);
{list, Moddir@1} ->
moddir_to_modulename(Moddir@1);
Expr ->
l4u@l4u_core:pstr(Expr)
end,
Fnname@1 = l4u@l4u_core:pstr(l4u@l4u_core:uneval(Fnname)),
Alias_name = Fnname@1,
{native_function,
Alias_name,
l4u_ffi:unsafe_corece(
l4u@sys_bridge_ffi:erl_ref_native_fun(Modname, Fnname@1)
)};
_ ->
l4u@sys_bridge_ffi:throw_err(
<<"native-function: wrong number of arguments"/utf8>>
),
undefined
end.
-spec invoke_native_function(l4u@l4u_type:expr(), list(l4u@l4u_type:expr())) -> l4u@l4u_type:expr().
invoke_native_function(Native_fun, Args) ->
_assert_subject = l4u@l4u_core:uneval(Native_fun),
{native_function, _, Native_fundef} = case _assert_subject of
{native_function, _, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"invoke_native_function"/utf8>>,
line => 374})
end,
{Modpath, Fnname} = l4u_ffi:unsafe_corece(Native_fundef),
Native_args = gleam@list:map(Args, fun l4u_ffi:l4u_to_native/1),
Erl_result = l4u@sys_bridge_ffi:erl_fn_apply(Native_fundef, Native_args),
Cvl4u = l4u_ffi:native_to_l4u(Erl_result),
Cvl4u.
-spec bif_invoke_native_function(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_invoke_native_function(Exprs, Env) ->
[Native_fun, Args] = case Exprs of
[_, _] -> Exprs;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_invoke_native_function"/utf8>>,
line => 362})
end,
_assert_subject = l4u@l4u_core:uneval(Args),
{list, Args@1} = case _assert_subject of
{list, _} -> _assert_subject;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_invoke_native_function"/utf8>>,
line => 363})
end,
Rexpr = invoke_native_function(Native_fun, Args@1),
{with_env, Rexpr, Env}.
-spec bif_shared_put(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_shared_put(Exprs, Env) ->
[Key, Value] = case Exprs of
[_, _] -> Exprs;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_shared_put"/utf8>>,
line => 389})
end,
persistent_term:put(l4u@l4u_core:pstr(Key), Value),
{with_env, Value, Env}.
-spec bif_shared_get(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr().
bif_shared_get(Exprs, Env) ->
[Key, Default_value] = case Exprs of
[_, _] -> Exprs;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"l4u/bif_lib"/utf8>>,
function => <<"bif_shared_get"/utf8>>,
line => 395})
end,
Rval = persistent_term:get(l4u@l4u_core:pstr(Key), Default_value),
{with_env, Rval, Env}.
-spec bif_lib_def() -> list({binary(), l4u@l4u_type:expr()}).
bif_lib_def() ->
Bif = fun(Name, F) -> {Name, {bif, l4u@l4u_core:description(Name), F}} end,
Bsf = fun(Name@1, F@1) ->
{Name@1, {bispform, l4u@l4u_core:description(Name@1), F@1}}
end,
[Bif(<<"seq"/utf8>>, fun bif_seq/2),
Bif(<<"self"/utf8>>, fun bif_erl_self/2),
Bif(<<"send"/utf8>>, fun bif_erl_send/2),
Bif(<<"receive-from"/utf8>>, fun bif_erl_receive_from/2),
Bif(<<"import-native-module"/utf8>>, fun bif_import_native_module/2),
Bif(<<"import-native-function"/utf8>>, fun bif_import_native_function/2),
Bif(
<<"import-native-functions"/utf8>>,
fun bif_import_native_functions/2
),
Bif(<<"native-function"/utf8>>, fun bif_native_function/2),
Bif(<<"invoke-native-function"/utf8>>, fun bif_invoke_native_function/2),
Bif(<<"os-cmd"/utf8>>, fun bif_os_cmd/2),
Bif(<<"native-module-info"/utf8>>, fun bif_native_module_info/2),
Bif(<<"native-nodes"/utf8>>, fun bif_native_nodes/2),
Bif(<<"native-processes"/utf8>>, fun bif_native_processes/2),
Bif(<<"shared-put"/utf8>>, fun bif_shared_put/2),
Bif(<<"shared-get"/utf8>>, fun bif_shared_get/2)].