1
1
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:
ekmartin 2015-09-09 17:32:48 +02:00
parent ced3f0d09c
commit 9dd9dd2f59
4 changed files with 17 additions and 10 deletions

View File

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

View File

@ -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)

View File

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

View File

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