Skip to content

Instantly share code, notes, and snippets.

@tompng
Last active December 15, 2015 04:50
Show Gist options
  • Save tompng/5204548 to your computer and use it in GitHub Desktop.
Save tompng/5204548 to your computer and use it in GitHub Desktop.
lispもどき
require './lisp_base'
LISPRUN [:cdr,[:cons,L(1,2,3),L(4,5,6)]]
LISPRUN [:cdr,D(L(1,2,3,D(4,5)),L(6,7,8))]
LISPRUN [:do,
[:print,[:car,[:cons,3,[:cons,4,5]]]],
[:print,[:+,3,[:+,6,3]]],
[:defun,:dist2,[:a,:b],[:+,[:*,:a,:a],[:*,:b,:b]]],
[:print,[:dist2,3,4]],
[:defun,:fact,[:a],[:ifelse,[:==,:a,0],1,[:*,:a,[:fact,[:-,:a,1]]]]],
[:print,[:fact,10]],
[:loop,10,:n,[:do,[:ruby,:printf,"%d!=%d\n",:n,[:fact,:n]],[:ruby,:sleep,1]]],
[:ruby,:sleep,1],
[:ruby,:printf,"hello world!\n"],
[:ruby,:exit]
]
def L(*arr)
arr=parse arr
def arr.eval hash
self
end
arr
end
def D(a,b)
arr=[a,b]
def arr.eval hash
self
end
arr
end
def args(hash,tree)
return nil if tree.nil?
first=tree[0]
first=first.eval hash if first.class==Array
first=hash[first] if first.class==Symbol
[first,*args(hash,tree[1])]
end
def parse arr,index=0
if index<arr.size
prev=arr[index]
if prev.class==Array
unless prev.respond_to? :eval
prev=parse prev
end
end
code=[prev,parse(arr,index+1)]
def code.eval hash
lispeval(self,hash)
end
code
end
end
def lispeval tree,hash
method=tree[0]
if hash[method]
hash[method].call(hash,tree[1])
else
method.to_proc.call(hash,tree[1])
end
end
class ChainHash
def initialize(parent)
@parent=parent
@hash={}
end
def [] key
@hash[key]||@parent[key]
end
def []=key,value
@hash[key]=value
end
end
def defun(hash,tree)
def arglistparse(tree)
[tree[0],*arglistparse(tree[1])] unless tree.nil?
end
name=tree[0]
arglist=arglistparse(tree[1][0])
code=tree[1][1][0]
hash[name]=->(hash,tree){
hash=ChainHash.new hash
arglist.zip(args(hash,tree)).each do|key,value|
hash[key]=value
end
if code.class==Array
code.eval hash
else
code
end
}
end
@hash={}
@hash[:+]=->(hash,tree){
a,b=args(hash,tree)
a+b
}
@hash[:*]=->(hash,tree){
a,b=args(hash,tree)
a*b
}
@hash[:-]=->(hash,tree){
a,b=args(hash,tree)
a-b
}
@hash[:/]=->(hash,tree){
a,b=args(hash,tree)
a/b
}
@hash[:do]=->(hash,tree){
args(hash,tree).last
}
@hash[:if]=->(hash,tree){
if tree[0].eval hash
code=tree[1][0]
if code.class==Array
code.eval hash
else
code
end
end
}
@hash[:ifelse]=->(hash,tree){
if tree[0].eval hash
code=tree[1][0]
else
code=tree[1][1][0]
end
if code.class==Array
code.eval hash
else
code
end
}
@hash[:==]=->(hash,tree){
a,b=args(hash,tree)
a==b
}
@hash[:p]=@hash[:print]=->(hash,tree){
p *args(hash,tree)
}
@hash[:defun]=->(hash,tree){
defun hash,tree
}
@hash[:ruby]=->(hash,tree){
func=tree[0]
arguments=args(hash,tree[1])
self.method(func).call *arguments
}
@hash[:loop]=->(hash,tree){
count=tree[0]
count=count.eval hash if count.class==Array
name=tree[1][0]
code=tree[1][1][0]
count.times do |i|
hash[name]=i
if code.class==Array
code.eval hash
else
code
end
end
}
@hash[:car]=->(hash,tree){
tree,=args(hash,tree)
tree[0]
}
@hash[:cdr]=->(hash,tree){
tree,=args(hash,tree)
tree[1]
}
@hash[:cons]=->(hash,tree){
a,b=args(hash,tree)
[a,b]
}
def LISPRUN(x)
p parse(x).eval @hash
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment