A fork of Crisp for HARP
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

74 lines
1.9 KiB

require "colorize"
require "readline"
require "./reader"
require "./printer"
require "./expr"
require "./env"
require "./core"
require "./error"
require "./evaluator"
module Crisp
class Interpreter
def initialize(args = nil)
@printer = Printer.new
@evaluator = Evaluator.new
@env = Crisp::Env.new
Crisp::NameSpace.each { |k, v| @env.set(k, Crisp::Expr.new(v)) }
@env.set("eval", Crisp::Expr.new ->(args : Array(Crisp::Expr)) { @evaluator.eval(args[0], @env) })
eval_string "(def! not (fn* (a) (if a false true)))"
eval_string "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"
eval_string "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"
eval_string "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))"
eval_string "(def! *host-language* \"crystal\")"
argv = Crisp::List.new
if args
args.each do |a|
argv << Crisp::Expr.new a
end
end
@env.set("*ARGV*", Crisp::Expr.new argv)
end
def read(str)
Crisp.read_str str
end
def print(result)
@printer.print(result)
end
def eval_string(str)
@evaluator.eval(read(str), @env)
end
def eval(t : Crisp::Expr)
@evaluator.eval(t, @env)
end
def eval(val)
@evaluator.eval(Crisp::Expr.new val, @env)
end
def run(filename = nil)
if filename
eval_string "(load-file \"#{filename}\")"
return
end
while line = Readline.readline("Crisp> ", true)
begin
puts self.print(eval_string(line))
rescue e
puts e.message
end
end
end
end
end