mirror of
https://github.com/kanaka/mal.git
synced 2024-11-13 01:43:50 +03:00
Use a struct for functions
This commit is contained in:
parent
ced3f0d09c
commit
9dd9dd2f59
@ -1,5 +1,6 @@
|
||||
defmodule Mal.Core do
|
||||
import Mal.Types
|
||||
alias Mal.Function
|
||||
|
||||
def namespace do
|
||||
%{
|
||||
@ -124,7 +125,7 @@ defmodule Mal.Core do
|
||||
defp rest([{_type, [head | tail], _}]), do: list(tail)
|
||||
defp rest([{_type, [], _}]), do: list([])
|
||||
|
||||
defp map([{_function_type, function}, ast]), do: do_map(function, ast)
|
||||
defp map([%Function{value: function}, ast]), do: do_map(function, ast)
|
||||
defp map([function, ast]), do: do_map(function, ast)
|
||||
|
||||
defp do_map(function, {_type, ast, _meta}) do
|
||||
@ -133,7 +134,7 @@ defmodule Mal.Core do
|
||||
|> list
|
||||
end
|
||||
|
||||
defp apply([{_function_type, function} | tail]), do: do_apply(function, tail)
|
||||
defp apply([%Function{value: function} | tail]), do: do_apply(function, tail)
|
||||
defp apply([function | tail]), do: do_apply(function, tail)
|
||||
|
||||
defp do_apply(function, tail) do
|
||||
|
@ -1,10 +1,12 @@
|
||||
defmodule Mal.Printer do
|
||||
alias Mal.Function
|
||||
|
||||
def print_str(mal, print_readably \\ true)
|
||||
def print_str(mal, _) when is_atom(mal), do: inspect(mal)
|
||||
def print_str(mal, _) when is_integer(mal), do: Integer.to_string(mal)
|
||||
def print_str(mal, _) when is_function(mal), do: inspect(mal)
|
||||
def print_str({:closure, mal}, _), do: inspect(mal)
|
||||
def print_str({:macro, mal}, _), do: "#Macro<#{inspect(mal)}"
|
||||
def print_str(%Function{value: mal, macro: true}, _), do: "#Macro<#{inspect(mal)}"
|
||||
def print_str(%Function{value: mal}, _), do: inspect(mal)
|
||||
def print_str({:symbol, value}, _), do: value
|
||||
def print_str({:exception, exception}, print_readably) do
|
||||
print_str(exception, print_readably)
|
||||
|
@ -16,3 +16,7 @@ defmodule Mal.Types do
|
||||
|
||||
def vector(ast), do: {:vector, ast, nil}
|
||||
end
|
||||
|
||||
defmodule Mal.Function do
|
||||
defstruct value: nil, macro: false, meta: nil
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
defmodule Mix.Tasks.StepAMal do
|
||||
import Mal.Types
|
||||
alias Mal.Function
|
||||
|
||||
def run(args) do
|
||||
env = Mal.Env.initialize()
|
||||
@ -141,14 +142,14 @@ defmodule Mix.Tasks.StepAMal do
|
||||
|
||||
defp macro_call?({:list, [{:symbol, key} | _tail], _}, env) do
|
||||
case Mal.Env.get(env, key) do
|
||||
{:ok, {:macro, _}} -> true
|
||||
{:ok, %Function{value: macro, macro: true}} -> true
|
||||
_ -> false
|
||||
end
|
||||
end
|
||||
defp macro_call?(_ast, _env), do: false
|
||||
|
||||
defp do_macro_call({:list, [{:symbol, key} | tail], _}, env) do
|
||||
{:ok, {:macro, macro}} = Mal.Env.get(env, key)
|
||||
{:ok, %Function{value: macro, macro: true}} = Mal.Env.get(env, key)
|
||||
macro.(tail)
|
||||
|> macroexpand(env)
|
||||
end
|
||||
@ -198,8 +199,7 @@ defmodule Mix.Tasks.StepAMal do
|
||||
end
|
||||
|
||||
defp eval_list([{:symbol, "defmacro!"}, {:symbol, key}, function], env, _) do
|
||||
{:closure, evaluated} = eval(function, env)
|
||||
macro = {:macro, evaluated}
|
||||
macro = %{eval(function, env) | macro: true}
|
||||
Mal.Env.set(env, key, macro)
|
||||
macro
|
||||
end
|
||||
@ -220,7 +220,7 @@ defmodule Mix.Tasks.StepAMal do
|
||||
eval(body, inner)
|
||||
end
|
||||
|
||||
{:closure, closure}
|
||||
%Function{value: closure}
|
||||
end
|
||||
|
||||
defp eval_list([{:symbol, "quote"}, arg], _env, _), do: arg
|
||||
@ -241,7 +241,7 @@ defmodule Mix.Tasks.StepAMal do
|
||||
defp eval_list(ast, env, meta) do
|
||||
{:list, [func | args], _} = eval_ast({:list, ast, meta}, env)
|
||||
case func do
|
||||
{:closure, closure} -> closure.(args)
|
||||
%Function{value: closure} -> closure.(args)
|
||||
_ -> func.(args)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user