-
-
Save atton/5300354 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require './lisp_base.rb' | |
LISP do (cons 1,2) end | |
LISP do (cond true,(cond false,(cons 1,2),(cons 3,4)),(cons 5,6)) end | |
LISP do (defun :fact,:x,(cond (eq :x,0),1,(mult (sqrt (square :x)),(fact (minus :x,1))))) end | |
LISP do (defun :abs,:x,(cond (lt :x,0),(minus 0,:x),:x)) end | |
LISP do | |
(defun :sqrtrec,:x,:y,:d, | |
(cond (lt :d,0.0000000001), | |
:y, | |
(cond (lt (mult :y,:y),:x), | |
(sqrtrec :x,(add :y,:d),(mult :d,0.5)), | |
(sqrtrec :x,(minus :y,:d),(mult :d,0.5)) | |
) | |
) | |
) | |
end | |
LISP do (defun :sqrt,:x,(sqrtrec :x,:x,:x)) end | |
LISP do (defun :square,(mult :x,:x)) end | |
LISP do (fact 5) end | |
LISP do (defun :x, 3) end # likes to let ...? | |
LISP do (x) end # can call | |
# LISP do (defun) end # raise argument error | |
# LISP do (defun :method) end # raise argument error | |
LISP do (defun :run, :x, (cond (lt :x,10),"lt 10","ge 10")) end # can define 'run' method | |
LISP do (run 100) end # can call | |
LISP do (run 1) end # can call |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LispEvaluator | |
class Parser < BasicObject | |
def method_missing name,*args | |
{name:name,args:args} | |
end | |
end | |
class ChainHash | |
def initialize hash | |
@parent = hash | |
@hash = { } | |
end | |
def []= key,value | |
@hash[key] = value | |
end | |
def [] key | |
@hash[key] || @parent[key] | |
end | |
end | |
def run code, hash | |
if code.class == Symbol | |
hash[code] | |
elsif code.class == Hash | |
@methods[code[:name]].call hash, *code[:args] | |
else | |
code | |
end | |
end | |
def parse &block | |
@parser.instance_eval(&block) | |
end | |
def initialize_embedded_methods | |
@methods[:defun] = -> (hash, *definitions) { | |
raise "defun arguments require method_name, *args(optional), code" if definitions.size < 2 | |
method_name = definitions.shift | |
method_code = definitions.pop | |
method_args = definitions | |
@methods[method_name] = -> (hash, *args) { | |
hash = ChainHash.new hash | |
method_args.zip(args).each{ |key, code| | |
hash[key] = run code, hash | |
} | |
run method_code, hash | |
} | |
true | |
} | |
@methods[:cond]=->(hash,a,b,c){ | |
if run a,hash | |
run b,hash | |
else | |
run c,hash | |
end | |
} | |
@methods[:cons]=->(hash,a,b){ | |
[run(a,hash),run(b,hash)] | |
} | |
@methods[:eq]=->(hash,a,b){ | |
run(a,hash)==run(b,hash) | |
} | |
@methods[:mult]=->(hash,a,b){ | |
run(a,hash)*run(b,hash) | |
} | |
@methods[:minus]=->(hash,a,b){ | |
run(a,hash)-run(b,hash) | |
} | |
@methods[:add]=->(hash,a,b){ | |
run(a,hash)+run(b,hash) | |
} | |
@methods[:lt]=->(hash,a,b){ | |
run(a,hash)<run(b,hash) | |
} | |
@methods[:le]=->(hash,a,b){ | |
run(a,hash)>run(b,hash) | |
} | |
end | |
def initialize | |
@parser = Parser.new | |
@methods={ } | |
initialize_embedded_methods | |
end | |
end | |
@lispevaluator = LispEvaluator.new | |
def LISP(&block) | |
code = @lispevaluator.parse(&block) | |
p @lispevaluator.run(code,{}) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment