Current section
Files
Jump to
Current section
Files
lib/elxlisp.ex
defmodule Elxlisp do
@moduledoc """
Simple Lisp interpreter
To invoke interpreter repl()
"""
@doc """
REPL(read eval print loop)
"""
def repl(arg) do
IO.write("Lisp 1.5 in Elixir ")
message(arg)
cond do
Enum.member?(arg, "para") and Enum.member?(arg, "mexp") ->
repl1([], [], :para, :mexp, [], [])
Enum.member?(arg, "seq") and Enum.member?(arg, "mexp") ->
repl1([], [], :seq, :mexp, [], [])
Enum.member?(arg, "para") and Enum.member?(arg, "sexp") ->
repl1([], [], :para, :sexp, [], [])
Enum.member?(arg, "seq") and Enum.member?(arg, "sexp") ->
repl1([], [], :seq, :sexp, [], [])
Enum.member?(arg, "para") ->
repl1([], [], :para, :mexp, [], [])
Enum.member?(arg, "seq") ->
repl1([], [], :seq, :mexp, [], [])
Enum.member?(arg, "sexp") ->
repl1([], [], :seq, :sexp, [], [])
Enum.member?(arg, "mexp") ->
repl1([], [], :seq, :mexp, [], [])
true ->
repl1([], [], :seq, :mexp, [], [])
end
end
# repl1 is helper function for repl
# It has environment buffer mode expression trace property
# The environment is association list. e.g. [[:a,1],[;b,2]]
# the buffer is list. Each elements are string
# trace is keyward-list e.g. [{foo,0},{boo,0}] {name,nestlebel}
# property is keyward-list e.g. [{foo,[{a,1}{b,2}]},{bar,[{a,2},{c,3}]}]
defp repl1(env, buf, mode, exp, tr, prop) do
try do
if exp == :mexp do
IO.write("? ")
{s, buf1} = Read.read(buf, :stdin)
{s1, env1, tr1, prop1} = Eval.eval(s, env, mode, tr, prop)
Print.print(s1)
repl1(env1, buf1, mode, exp, tr1, prop1)
else
if exp == :sexp do
IO.write("S? ")
{s, buf1} = Read.sread(buf, :stdin)
{s1, env1, tr1, prop1} = Eval.eval(s, env, mode, tr, prop)
Print.print(s1)
repl1(env1, buf1, mode, exp, tr1, prop1)
end
end
catch
x ->
IO.inspect(x)
if x != "goodbye" do
repl1(env, buf, mode, exp, tr, prop)
else
true
end
end
end
def message([]) do
IO.puts("M-expression in sequential")
end
def message(l) do
message1(l)
end
def message1([]) do
IO.puts("")
end
def message1([l | ls]) do
cond do
l == "mexp" -> IO.write("M-expression ")
l == "sexp" -> IO.write("S-expression ")
l == "para" -> IO.write("in parallel ")
l == "seq" -> IO.write("in sequential ")
end
message1(ls)
end
def error(msg, dt) do
IO.write("Error ")
IO.write(msg)
IO.write(" ")
throw(dt)
end
# for test M-expression
def foo(x) do
{s, _} = x |> Read.tokenize() |> Read.read(:stdin)
{s1, _, _, _} = Eval.eval(s, [], :seq, [], [])
s1
end
# for test S-expression
def bar(x) do
{s, _} = x |> Read.stokenize() |> Read.sread(:stdin)
{s1, _, _, _} = Eval.eval(s, [], :seq, [], [])
s1
end
def stop() do
raise("stop")
end
end