-module(l4u@l4u). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([bispform_bindf/2, bispform_case/2, bispform_cond/2, l4u_eval/2, l4u_read_eval/2, l4u_add_defs/2, l4u_get_main_process/0, l4u_get_process/1, l4u_rep/2, l4u_rep_native/2, l4u_rep_str/2, main_l4u/0, l4u_repl/2, make_new_l4u_env/2, generate_l4u_process/2, start_and_generate_main_l4u/1, start_with_defs/1, main/0]). -spec bindf(l4u@l4u_type:expr(), l4u@l4u_type:expr(), l4u@l4u_type:env()) -> l4u@l4u_type:env(). bindf(Bind_to, Bind_from, Env) -> Bind_from@1 = l4u@l4u_core:uneval(Bind_from), case l4u@l4u_core:uneval(Bind_to) of {custom_type, Name, Data} -> {custom_type, Name2, Data2} = case Bind_from@1 of {custom_type, _, _} -> Bind_from@1; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"bindf"/utf8>>, line => 62}) end, case Name =:= Name2 of true -> bindf(Data, Data2, Env); false -> l4u@sys_bridge_ffi:throw_err( <<<<<<"bindf: custom type name not match: "/utf8, Name/binary>>/binary, " != "/utf8>>/binary, Name2/binary>> ), Env end; {list, [{symbol, <<"custom-type"/utf8>>}, Name@1, Data@1]} -> Name@2 = l4u@l4u_core:pstr(Name@1), {custom_type, Name2@1, Data2@1} = case Bind_from@1 of {custom_type, _, _} -> Bind_from@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"l4u/l4u"/utf8>>, function => <<"bindf"/utf8>>, line => 76}) end, case Name@2 =:= Name2@1 of true -> bindf(Data@1, Data2@1, Env); false -> l4u@sys_bridge_ffi:throw_err( <<<<<<"bindf: custom type name not match: "/utf8, Name@2/binary>>/binary, " != "/utf8>>/binary, Name2@1/binary>> ), Env end; {symbol, Name@3} -> New_env = l4u@l4u_core:env_set_local(Env, Name@3, Bind_from@1); {list, []} -> case Bind_from@1 of {list, []} -> Env; _ -> l4u@sys_bridge_ffi:throw_err( <<"bindf: empty list != bind_from"/utf8>> ), Env end; {list, [{symbol, <<"quote"/utf8>>}, X]} -> case X =:= Bind_from@1 of true -> Env; false -> l4u@sys_bridge_ffi:throw_err( <<"bindf: quoted bind_to != bind_from"/utf8>> ), Env end; {list, [Bind_to@1 | Rest_bind_to]} -> _assert_subject = l4u@l4u_core:uneval(Bind_from@1), {list, [Bind_from@2 | Rest_bind_from]} = case _assert_subject of {list, [_ | _]} -> _assert_subject; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@2, module => <<"l4u/l4u"/utf8>>, function => <<"bindf"/utf8>>, line => 109}) end, New_env@1 = bindf(Bind_to@1, Bind_from@2, Env), bindf({list, Rest_bind_to}, {list, Rest_bind_from}, New_env@1); _ -> case Bind_to =:= Bind_from@1 of true -> Env; false -> l4u@sys_bridge_ffi:throw_err( <<"bindf: bind_to != bind_from"/utf8>> ), Env end end. -spec bispform_bindf(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bispform_bindf(Exprs, Env) -> [Bind_to, Bind_from] = case Exprs of [_, _] -> Exprs; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"bispform_bindf"/utf8>>, line => 50}) end, _assert_subject = l4u@l4u_core:eval([Bind_from], undefined, Env), {with_env, Evalue, New_env} = case _assert_subject of {with_env, _, _} -> _assert_subject; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"l4u/l4u"/utf8>>, function => <<"bispform_bindf"/utf8>>, line => 51}) end, {with_env, undefined, bindf(Bind_to, Evalue, New_env)}. -spec case_(l4u@l4u_type:expr(), list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). case_(Value, Cases, Env) -> case Cases of [] -> l4u@sys_bridge_ffi:throw_err(<<"case: empty cases"/utf8>>), {with_env, undefined, Env}; [{vector, [Pattern | Body]} | Rest_cases] -> Bind_result = l4u@sys_bridge_ffi:catch_ex( fun() -> bindf(Pattern, Value, Env) end ), case Bind_result of {ok, New_env} -> _assert_subject = l4u@l4u_core:eval( Body, undefined, New_env ), {with_env, Result, New_env@1} = case _assert_subject of {with_env, _, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"case_"/utf8>>, line => 140}) end; {error, _} -> case_(Value, Rest_cases, Env) end; [{list, [Pattern | Body]} | Rest_cases] -> Bind_result = l4u@sys_bridge_ffi:catch_ex( fun() -> bindf(Pattern, Value, Env) end ), case Bind_result of {ok, New_env} -> _assert_subject = l4u@l4u_core:eval( Body, undefined, New_env ), {with_env, Result, New_env@1} = case _assert_subject of {with_env, _, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"case_"/utf8>>, line => 140}) end; {error, _} -> case_(Value, Rest_cases, Env) end; _ -> l4u@sys_bridge_ffi:throw_err(<<"case: invalid cases"/utf8>>), {with_env, undefined, Env} end. -spec bispform_case(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bispform_case(Exprs, Env) -> [Value | Cases] = case Exprs of [_ | _] -> Exprs; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"bispform_case"/utf8>>, line => 155}) end, _assert_subject = l4u@l4u_core:eval([Value], undefined, Env), {with_env, Evalue, New_env} = case _assert_subject of {with_env, _, _} -> _assert_subject; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"l4u/l4u"/utf8>>, function => <<"bispform_case"/utf8>>, line => 156}) end, case_(Evalue, Cases, New_env). -spec cond_(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). cond_(Exprs, Env) -> case Exprs of [] -> l4u@sys_bridge_ffi:throw_err(<<"cond: empty exprs"/utf8>>), {with_env, undefined, Env}; [{list, [Condition | Rest]}] -> _assert_subject = l4u@l4u_core:eval([Condition], undefined, Env), {with_env, Result, New_env} = case _assert_subject of {with_env, _, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"cond_"/utf8>>, line => 168}) end, case l4u@l4u_core:is_true_condition(Result) of true -> _assert_subject@1 = l4u@l4u_core:eval( Rest, undefined, New_env ), {with_env, Result@1, New_env@1} = case _assert_subject@1 of {with_env, _, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"l4u/l4u"/utf8>>, function => <<"cond_"/utf8>>, line => 171}) end, {with_env, Result@1, New_env@1}; false -> cond_(Exprs, New_env) end; _ -> l4u@sys_bridge_ffi:throw_err(<<"cond: invalid exprs"/utf8>>), {with_env, undefined, Env} end. -spec bispform_cond(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bispform_cond(Exprs, Env) -> cond_(Exprs, Env). -spec bif_unwrap_ok(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bif_unwrap_ok(Exprs, Env) -> Expr = case Exprs of [{native_value, _, Value}] -> {native_value, <<""/utf8>>, gleam@dynamic:from({ok, Value})}; _ -> nil end, {with_env, Expr, Env}. -spec bif_native_value(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bif_native_value(Exprs, Env) -> [Name, Value] = case Exprs of [_, _] -> Exprs; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"bif_native_value"/utf8>>, line => 203}) end, {with_env, {native_value, l4u@l4u_core:show(Name), gleam@dynamic:from(Value)}, Env}. -spec bif_l4u_processes(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bif_l4u_processes(Exprs, Env) -> _assert_subject = l4u@union_term:get_map(<<"*l4u_processes*"/utf8>>), Dict = case _assert_subject of _ -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"bif_l4u_processes"/utf8>>, line => 208}) end, _assert_subject@1 = gleam@dict:keys(Dict), Keys = case _assert_subject@1 of _ -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"l4u/l4u"/utf8>>, function => <<"bif_l4u_processes"/utf8>>, line => 209}) end, {with_env, {list, gleam@list:map(Keys, fun(Field@0) -> {string, Field@0} end)}, Env}. -spec bif_repl_switch(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bif_repl_switch(Exprs, Env) -> [Name] = case Exprs of [_] -> Exprs; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"bif_repl_switch"/utf8>>, line => 226}) end, Name@1 = l4u@l4u_core:show(Name), _assert_subject = l4u@union_term:get_map_value( <<"*l4u_processes*"/utf8>>, Name@1, undefined ), L4u = case _assert_subject of _ -> _assert_subject; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"l4u/l4u"/utf8>>, function => <<"bif_repl_switch"/utf8>>, line => 228}) end, {repl_command, <<"repl-switch"/utf8>>, L4u}. -spec l4u_eval(l4u@l4u_obj:l4u_obj(), list(l4u@l4u_type:expr())) -> l4u@l4u_type:expr(). l4u_eval(L4u, Exprs) -> _assert_subject = (erlang:element(5, L4u))(Exprs), {ok, Rexpr} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"l4u_eval"/utf8>>, line => 305}) end, Rexpr. -spec l4u_read_eval(l4u@l4u_obj:l4u_obj(), binary()) -> {ok, l4u@l4u_type:expr()} | {error, binary()}. l4u_read_eval(L4u, Src) -> _assert_subject = (erlang:element(6, L4u))(Src), {ok, Exprs} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"l4u/l4u"/utf8>>, function => <<"l4u_read_eval"/utf8>>, line => 311}) end, (erlang:element(5, L4u))(Exprs). -spec l4u_add_defs(l4u@l4u_obj:l4u_obj(), list({binary(), l4u@l4u_type:expr()})) -> {ok, l4u@l4u_type:expr()} | {error, any()}. l4u_add_defs(L4u, Defs) -> F = fun(Env) -> gleam@list:map( Defs, fun(Item) -> {K, V} = Item, l4u@sys_bridge_ffi:dbgout4( <<"l4u_add_defs: "/utf8>>, K, <<" = "/utf8>>, l4u@l4u_core:inspect(V) ), l4u@sys_bridge_ffi:process_dict_set( erlang:element(3, (erlang:element(4, L4u))()), K, V ), l4u@sys_bridge_ffi:dbgout2( <<"verify: "/utf8>>, l4u@sys_bridge_ffi:process_dict_get( erlang:element(3, (erlang:element(4, L4u))()), K ) ) end ), {with_env, nil, Env} end, Result = l4u@process:exec(erlang:element(3, L4u), F), Result. -spec l4u_get_main_process() -> l4u@l4u_obj:l4u_obj(). l4u_get_main_process() -> _pipe = persistent_term:get(<<"*main-l4u*"/utf8>>, undefined), l4u_ffi:unsafe_corece(_pipe). -spec l4u_get_process(binary()) -> {ok, l4u@l4u_obj:l4u_obj()} | {error, binary()}. l4u_get_process(Name) -> case persistent_term:get(Name, undefined) of undefined -> {error, <<"l4u_get_process: not found"/utf8>>}; L4u -> {ok, l4u_ffi:unsafe_corece(L4u)} end. -spec l4u_rep(binary(), l4u@l4u_obj:l4u_obj()) -> {ok, l4u@l4u_type:expr()} | {error, binary()}. l4u_rep(Src, L4u) -> Result = l4u_read_eval(L4u, Src), Result. -spec l4u_rep_native(binary(), l4u@l4u_obj:l4u_obj()) -> any(). l4u_rep_native(Src, L4u) -> case l4u_rep(Src, L4u) of {ok, Result} -> l4u_ffi:l4u_to_native(Result); {error, Err} -> l4u_ffi:unsafe_corece(<<"Error: "/utf8, Err/binary>>) end. -spec l4u_rep_str(binary(), l4u@l4u_obj:l4u_obj()) -> binary(). l4u_rep_str(Src, L4u) -> case l4u_rep(Src, L4u) of {ok, Result} -> l4u@l4u_core:print(Result); {error, Err} -> <<"Error: "/utf8, Err/binary>> end. -spec main_l4u() -> l4u@l4u_obj:l4u_obj(). main_l4u() -> _pipe = persistent_term:get(<<"*main-l4u*"/utf8>>, undefined), l4u_ffi:unsafe_corece(_pipe). -spec repl_loop( l4u@l4u_obj:l4u_obj(), {ok, l4u@l4u_type:expr()} | {error, l4u@l4u_type:expr()}, binary() ) -> binary(). repl_loop(L4u, Result, Prompt) -> case Result of {ok, Retval} -> case Retval of {repl_command, <<"repl-switch"/utf8>>, {native_value, <<"l4u"/utf8>>, New_l4u}} -> l4u_repl(l4u_ffi:unsafe_corece(New_l4u), Prompt); _ -> l4u@l4u_core:repl_print(Retval), l4u_repl(L4u, Prompt) end; {error, Err} -> Print_error = fun(Env) -> l4u@sys_bridge_ffi:console_writeln( <<"Error: "/utf8, (l4u@sys_bridge_ffi:error_to_string(Err, false))/binary>> ), case erlang:element( 2, erlang:element(7, (erlang:element(4, L4u))()) ) of true -> l4u@l4u_core:dump_env( <<"repl"/utf8>>, (erlang:element(4, L4u))() ), l4u@sys_bridge_ffi:dbgout2( <<"last funcall:"/utf8>>, l4u@sys_bridge_ffi:process_dict_get( erlang:element(3, (erlang:element(4, L4u))()), <<"last_funcall"/utf8>> ) ), l4u@sys_bridge_ffi:dbgout2( <<"last expr:"/utf8>>, l4u@sys_bridge_ffi:process_dict_get( erlang:element(3, (erlang:element(4, L4u))()), <<"last_expr"/utf8>> ) ); false -> false end end, l4u@process:exec_native(erlang:element(3, L4u), Print_error), l4u_repl(L4u, Prompt) end. -spec l4u_repl(l4u@l4u_obj:l4u_obj(), binary()) -> binary(). l4u_repl(L4u, Prompt) -> false andalso l4u@l4u_core:trace_set_last_funcall( undefined, (erlang:element(4, L4u))() ), Str_prompt = <<<<<<<<(begin _pipe = l4u@sys_bridge_ffi:stringify( erlang:element(3, L4u) ), _pipe@1 = gleam@string:replace( _pipe, <<"<"/utf8>>, <<"|"/utf8>> ), gleam@string:replace( _pipe@1, <<">"/utf8>>, <<"|"/utf8>> ) end)/binary, ""/utf8>>/binary, (erlang:element(2, L4u))/binary>>/binary, "|"/utf8>>/binary, Prompt/binary>>, Line = l4u@sys_bridge_ffi:console_readline(Str_prompt), case gleam@string:trim(Line) of <<""/utf8>> -> l4u@sys_bridge_ffi:console_writeln(<<""/utf8>>), l4u_repl(L4u, Prompt); <<":exit"/utf8>> -> <<""/utf8>>; <<":quit"/utf8>> -> <<""/utf8>>; _ -> Result@1 = l4u@sys_bridge_ffi:catch_ex( fun() -> l4u@sys_bridge_ffi:process_dict_set( erlang:element(3, (erlang:element(4, L4u))()), <<"*trace_ip"/utf8>>, 0 ), Result = l4u_rep(Line, L4u), case Result of {ok, Res} -> Res; {error, Err} -> gleam@io:println( <<"Error: "/utf8, (l4u@sys_bridge_ffi:error_to_string( Err, false ))/binary>> ), {printable, {string, <<""/utf8>>}} end end ), repl_loop(L4u, Result@1, Prompt) end. -spec make_new_l4u_env(list({binary(), l4u@l4u_type:expr()}), list(binary())) -> l4u@l4u_type:env(). make_new_l4u_env(Additional_defs, Additional_files) -> Pdic = l4u@sys_bridge_ffi:unique_pdic(), 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, Defs = [Bsf(<<"bindf"/utf8>>, fun bispform_bindf/2), Bsf(<<"case*"/utf8>>, fun bispform_case/2), Bsf(<<"cond*"/utf8>>, fun bispform_cond/2), Bif(<<"unwrap-ok"/utf8>>, fun bif_unwrap_ok/2), Bif(<<"native-value"/utf8>>, fun bif_native_value/2), Bif(<<"l4u-processes"/utf8>>, fun bif_l4u_processes/2), Bif(<<"spawn"/utf8>>, fun bif_spawn/2), Bif(<<"repl-switch"/utf8>>, fun bif_repl_switch/2)], Files = [], l4u@l4u_core:make_new_l4u_core_env( Pdic, gleam@list:concat( [Defs, l4u@erlang_bifs:erlang_bifs(), l4u@bif_lib:bif_lib_def(), l4u@bif_string:bif_string_def(), l4u@bif_file:bif_file_def(), l4u@bif_std:bif_std_def(), l4u@bif_datetime:bif_datetime_def(), l4u@bif_template:bif_template_def(), Additional_defs] ), gleam@list:append(Files, Additional_files) ). -spec bif_spawn(list(l4u@l4u_type:expr()), l4u@l4u_type:env()) -> l4u@l4u_type:expr(). bif_spawn(Exprs, Env) -> Name@1 = case Exprs of [Name] -> l4u@l4u_core:show(Name); _ -> l4u@sys_bridge_ffi:unique_str() end, {L4u, Expr_l4u} = generate_l4u_process(Name@1, []), {with_env, Expr_l4u, Env}. -spec generate_l4u_process(binary(), list({binary(), l4u@l4u_type:expr()})) -> {l4u@l4u_obj:l4u_obj(), l4u@l4u_type:expr()}. generate_l4u_process(Name, Additional_defs) -> Initializer = fun() -> _pipe = make_new_l4u_env(Additional_defs, []), l4u@l4u_core:env_set_global( _pipe, <<"*ARGV*"/utf8>>, {list, gleam@list:map( l4u@sys_bridge_ffi:get_command_line_args(), fun(X) -> {string, X} end )} ) end, L4u = l4u@l4u_obj:generate_new_l4u_obj(Name, Initializer), Expr_l4u = {native_value, <<"l4u"/utf8>>, gleam@dynamic:from(L4u)}, l4u@union_term:set_map_value( <<"*l4u_processes*"/utf8>>, Name, gleam@dynamic:from(Expr_l4u) ), {L4u, Expr_l4u}. -spec start_and_generate_main_l4u(list({binary(), l4u@l4u_type:expr()})) -> l4u@l4u_obj:l4u_obj(). start_and_generate_main_l4u(Additional_defs) -> l4u@l4u_core:initialize(), {L4u, _} = generate_l4u_process(<<"main"/utf8>>, Additional_defs), persistent_term:put(<<"*main-l4u*"/utf8>>, gleam@dynamic:from(L4u)), L4u. -spec start_with_defs(list({binary(), l4u@l4u_type:expr()})) -> binary(). start_with_defs(Defs) -> L4u = start_and_generate_main_l4u(Defs), case false of true -> l4u@l4u_core:repl((erlang:element(4, L4u))(), <<"lisp> "/utf8>>); false -> l4u_repl(L4u, <<"l4u> "/utf8>>) end. -spec main() -> binary(). main() -> l4u@sys_bridge_ffi:dbgout1( <<"## l4u: main --------------------------------------------"/utf8>> ), start_with_defs([]).