Skip to content

Instantly share code, notes, and snippets.

@dcluna
Created April 5, 2012 02:06
Show Gist options
  • Select an option

  • Save dcluna/2307427 to your computer and use it in GitHub Desktop.

Select an option

Save dcluna/2307427 to your computer and use it in GitHub Desktop.
Lisp in Ruby
class Risp
@@envs = []
def initialize
define_environment({})
end
def eval(arg)
if arg.is_a? Symbol # accessor
@env[arg]
elsif !arg.is_a? Array # atom - is not a list
arg
elsif is_quote? arg # [:quote, <other-stuff>]
arg[1..-1] # 'quote' uses the list as-is (prevents evaluation)
elsif is_if? arg # [:]
body = eval(arg[1]) ? arg[2] : arg[3] # if 1 then do 2; else do 3
eval body
elsif is_set? arg
@env[arg[1]] = eval arg[2]
elsif is_lambda? arg # [:lambda, [<bindings, as symbols>], <body> ]
instance_eval "lambda {|#{arg[1].join ","}| eval arg[2]}" # cool trick bro
else
puts 'Command not recognized'
end
end
private
def define_environment(old_bindings)
@env = old_bindings
@@envs.push @env
end
def is_quote?(elem)
elem.first == :quote
end
def is_if?(elem)
elem.first == :if && elem.length >= 3
end
def is_set?(elem)
elem[0] == :set! && elem[1].is_a?(Symbol) && elem.length == 3
end
def is_lambda?(elem)
elem.first == :lambda &&
elem[1].is_a?(Array) && elem[1].all? {|binding| binding.is_a? Symbol }
end
end
def eval_sexp(sexp)
return sexp unless sexp.instance_of? Array
command = sexp.first
args = sexp.drop 1
if command.instance_of?(Symbol) # send msg to objects
args.map! { |arg| eval_sexp arg }
call_command command, :arguments => args
else
sexp.map { |arg| eval_sexp arg }
end
end
private
def call_command(command,params)
args = params[:arguments]
return command.call(args) if command.instance_of? Proc
if args.length > 2
argument = args.drop(1).first
other_arguments = args.drop(2)
partial_result = args.first.send(command,argument)
call_command command, :arguments => [partial_result,other_arguments].flatten
elsif args.length == 2
return args.first.send(command,args[1])
else
return args.first.send(command)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment