Packages

A simple Lisp interpreter implemented in Gleam. Features a REPL, basic Lisp functionality including arithmetic operations, list manipulation, conditionals, and variable definitions.

Current section

Files

Jump to
glisp src glisp@eval.erl
Raw

src/glisp@eval.erl

-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.