-module(glisp@eval). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([eval/2]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -file("src/glisp/eval.gleam", 56). -spec apply_function(glisp@ast:expr(), list(glisp@ast:expr())) -> {ok, glisp@ast:expr()} | {error, binary()}. apply_function(Func, Args) -> case Func of {builtin, Fn_impl} -> Fn_impl(Args); _ -> {error, <<"Not a function "/utf8, (glisp@ast:expr_to_string(Func))/binary>>} end. -file("src/glisp/eval.gleam", 63). -spec is_truthy(glisp@ast:expr()) -> boolean(). is_truthy(Expr) -> case Expr of {number, 0} -> false; {list, []} -> false; _ -> true end. -file("src/glisp/eval.gleam", 52). ?DOC(" Evaluate a list of expressions\n"). -spec eval_list( list(glisp@ast:expr()), gleam@dict:dict(binary(), glisp@ast:expr()) ) -> {ok, list(glisp@ast:expr())} | {error, binary()}. eval_list(Exprs, Env) -> gleam@list:try_map(Exprs, fun(Expr) -> eval(Expr, Env) end). -file("src/glisp/eval.gleam", 13). ?DOC( " Evaluate an expression in the given environment\n" "\n" " This function is the core of the interpreter, handling different expression types:\n" " - Numbers evaluate to themselves\n" " - Atoms are looked up in the environment\n" " - Built-in functions return themselves\n" " - Lists handle special forms (`define`, `if`) or function application\n" ). -spec eval(glisp@ast:expr(), gleam@dict:dict(binary(), glisp@ast:expr())) -> {ok, glisp@ast:expr()} | {error, binary()}. eval(Expr, Env) -> case Expr of {number, _} -> {ok, Expr}; {atom, Name} -> glisp@environment:get(Env, Name); {builtin, _} -> {ok, Expr}; {list, Elements} -> case Elements of [] -> {ok, Expr}; [{atom, <<"define"/utf8>>}, {atom, Name@1}, Value_expr] -> _pipe = eval(Value_expr, Env), gleam@result:map( _pipe, fun(Value) -> _ = glisp@environment:set(Env, Name@1, Value), Value end ); [{atom, <<"if"/utf8>>}, Condition, Then_expr, Else_expr] -> _pipe@1 = eval(Condition, Env), gleam@result:then( _pipe@1, fun(Cond_val) -> case is_truthy(Cond_val) of true -> eval(Then_expr, Env); false -> eval(Else_expr, Env) end end ); [Func_expr | Args] -> _pipe@2 = eval(Func_expr, Env), gleam@result:then( _pipe@2, fun(Func) -> _pipe@3 = eval_list(Args, Env), gleam@result:then( _pipe@3, fun(Evaluated_args) -> apply_function(Func, Evaluated_args) end ) end ) end end.