Revisions
-
p8 revised this gist
Jan 28, 2012 . 2 changed files with 79 additions and 78 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -14,4 +14,83 @@ def self.parse fn, *sexp args = sexp.map { |a| Fs[:atom].call(a) ? a : parse(*a) } Fs.key?(fn) ? Fs[fn].call(*args) : fn end end describe Lisp do it "works with nested sexps" do Lisp.parse(:eq, [:quote, [1, 2, 3]], [:cons, 1, [:quote, [2,3]]]).should == true Lisp.parse(*Lisp.parse(:quote, [:cons, 1, [:quote, [2,3]]])).should == [1, 2, 3] end describe ":quote" do it "returns the sexp" do Lisp.parse(:quote, [:eq, 1, 2]).should == [:eq, 1, 2] end it "returns the value" do Lisp.parse(:quote, [1, 2]).should == [1, 2] end end describe ":car" do it "returns the head of the sexp" do Lisp.parse(:car, [:quote, [1, 2]]).should == 1 end end describe ":cdr" do it "returns the tail of the sexp" do Lisp.parse(:cdr, [:quote, [1, 2, 3]]).should == [2, 3] end end describe ":cons" do it "concats the the first argument to the second" do Lisp.parse(:cons, 1, [:quote, [2, 3]]).should == [1, 2, 3] end end describe ":if" do it "returns the third sexp if the first is true" do Lisp.parse(:if, [:eq, 2, 2], 42, 43).should == 42 end it "returns the second sexp if the first is false" do Lisp.parse(:if, [:eq, 1, 2], 42, 43).should == 43 end end describe ":atom" do it "returns true if it's an atom" do Lisp.parse(:atom, 42).should == true end it "returns false if it's not an atom" do Lisp.parse(:atom, [:quote, [42]]).should == false end it "returns false if it's not an atom" do Lisp.parse(:atom, [:quote, [42, 43]]).should == false end end describe ":eq" do it "returns true if values are equal" do Lisp.parse(:eq, 42, 42).should == true end it "returns false if values are equal" do Lisp.parse(:eq, 42, 43).should == false end end describe ":label" do it "sets the value" do Lisp.parse(:label, :a, 42) Lisp.parse(:a).should == 42 end end end 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 charactersOriginal file line number Diff line number Diff line change @@ -1,78 +0,0 @@ -
p8 revised this gist
Jan 28, 2012 . 2 changed files with 78 additions and 33 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,21 +1,17 @@ class Lisp Fs = { :label => lambda {|name,value| Fs[name] = lambda { value } }, :car => lambda {|sexp| sexp.first }, :cdr => lambda {|sexp| sexp.slice(1, sexp.size) }, :cons => lambda {|head,tail| [head] + tail }, :atom => lambda {|sexp| !sexp.is_a?(Array) }, :eq => lambda {|a,b| a == b }, :if => lambda {|cnd,thn,els| cnd ? thn : els } } def self.parse fn, *sexp return sexp.flatten(1) if fn == :quote args = sexp.map { |a| Fs[:atom].call(a) ? a : parse(*a) } Fs.key?(fn) ? Fs[fn].call(*args) : fn end end 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 charactersOriginal file line number Diff line number Diff line change @@ -1,29 +1,78 @@ describe Lisp do it "works with nested sexps" do Lisp.parse(:eq, [:quote, [1, 2, 3]], [:cons, 1, [:quote, [2,3]]]).should == true Lisp.parse(*Lisp.parse(:quote, [:cons, 1, [:quote, [2,3]]])).should == [1, 2, 3] end describe ":quote" do it "returns the sexp" do Lisp.parse(:quote, [:eq, 1, 2]).should == [:eq, 1, 2] end it "returns the value" do Lisp.parse(:quote, [1, 2]).should == [1, 2] end end describe ":car" do it "returns the head of the sexp" do Lisp.parse(:car, [:quote, [1, 2]]).should == 1 end end describe ":cdr" do it "returns the tail of the sexp" do Lisp.parse(:cdr, [:quote, [1, 2, 3]]).should == [2, 3] end end describe ":cons" do it "concats the the first argument to the second" do Lisp.parse(:cons, 1, [:quote, [2, 3]]).should == [1, 2, 3] end end describe ":if" do it "returns the third sexp if the first is true" do Lisp.parse(:if, [:eq, 2, 2], 42, 43).should == 42 end it "returns the second sexp if the first is false" do Lisp.parse(:if, [:eq, 1, 2], 42, 43).should == 43 end end describe ":atom" do it "returns true if it's an atom" do Lisp.parse(:atom, 42).should == true end it "returns false if it's not an atom" do Lisp.parse(:atom, [:quote, [42]]).should == false end it "returns false if it's not an atom" do Lisp.parse(:atom, [:quote, [42, 43]]).should == false end end describe ":eq" do it "returns true if values are equal" do Lisp.parse(:eq, 42, 42).should == true end it "returns false if values are equal" do Lisp.parse(:eq, 42, 43).should == false end end describe ":label" do it "sets the value" do Lisp.parse(:label, :a, 42) Lisp.parse(:a).should == 42 end end end -
p8 revised this gist
Jan 26, 2012 . 2 changed files with 33 additions and 47 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,32 +1,21 @@ class Lisp Fs = Hash.new(lambda {|fn, *sexp| [fn] + sexp }).merge({ :label => lambda {|name, value| Fs[name] = lambda { value } }, :eq => lambda {|a,b| a == b }, :quote => lambda {|value| value }, :car => lambda {|list| list[0] }, :cdr => lambda {|list| list.slice(1, list.size) }, :cons => lambda {|value, list| [value[0]] + list }, :if => lambda {|condition, thn, els| condition ? thn : els }, :atom => lambda {|value| !value.is_a? Array }, :apply => lambda {|*sexp| Fs.key?(sexp[0]) ? Fs[sexp[0]].call(*sexp.slice(1, sexp.size)) : sexp[0] } }) def self.eval sexp fn, *args = sexp if Fs.key?(fn) sexp = args.map{|a| Fs[:atom].call(a) ? Fs[:apply].call(a) : eval(a) } end Fs[fn].call(*sexp) end end 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 charactersOriginal file line number Diff line number Diff line change @@ -1,32 +1,29 @@ def assert_equal(a, b) a == b or raise "#{a.inspect} should equal #{b.inspect}" end l = Lisp l.eval [:label, :a, 42] assert_equal 42, l.eval([:a]) assert_equal true, l.eval([:eq, 42, :a]) assert_equal true, l.eval([:eq, :a, 42]) assert_equal [1,2], l.eval([:quote, [1, 2]]) assert_equal 1, l.eval([:car, [:quote, [1, 2]]]) assert_equal [2], l.eval([:cdr, [:quote, [1, 2]]]) assert_equal [1,2,3], l.eval([:cons, 1, [:quote, [2,3]]]) assert_equal 43, l.eval([:if, [:eq, 1, 2], 42, 43]) assert_equal false, l.eval([:atom, [:quote, [1,2]]]) assert_equal true, l.eval([:atom, 1]) assert_equal true, l.eval([:eq, [:quote, [1, 2, 3]], [:cons, 1, [:quote, [2,3]]]]) -
fogus revised this gist
Jan 25, 2012 . 2 changed files with 6 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -15,7 +15,7 @@ def initialize def apply fn, args, ctx=@env return @env[fn].call(args, ctx) if @env[fn].respond_to? :call self.eval @env[fn][2], Hash[*(@env[fn][1].zip args).flatten(1)] end def eval sexpr, ctx=@env 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 charactersOriginal file line number Diff line number Diff line change @@ -25,3 +25,8 @@ l.eval [:atom, [:quote, [1,2]]] #=> false l.eval [:label, :second, [:quote, [:lambda, [:x], [:car, [:cdr, :x]]]]] l.eval [:second, [:quote, [1, 2, 3]]] #=> 2 -
fogus revised this gist
Jan 25, 2012 . 1 changed file with 4 additions and 12 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -8,18 +8,18 @@ def initialize :cons => lambda { |(e,cell), _| [e] + cell }, :eq => lambda { |(l,r), _| l == r }, :if => lambda { |(cond, thn, els), ctx| eval(cond, ctx) ? eval(thn, ctx) : eval(els, ctx) }, :atom => lambda { |(sexpr), _| (sexpr.is_a? Symbol) or (sexpr.is_a? Numeric) } } end def apply fn, args, ctx=@env return @env[fn].call(args, ctx) if @env[fn].respond_to? :call self.eval @env[fn][2], Hash[*(@env[fn][1].zip args).flatten] end def eval sexpr, ctx=@env if @env[:atom].call [sexpr], ctx return ctx[sexpr] if ctx[sexpr] return sexpr end @@ -29,12 +29,4 @@ def eval sexpr, ctx=@env args = args.map { |a| self.eval(a, ctx) } if not [:quote, :if].member? fn apply(fn, args, ctx) end end -
fogus revised this gist
Jan 25, 2012 . 2 changed files with 27 additions and 32 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -38,35 +38,3 @@ def atom? sexpr sexpr.is_a? Symbol or sexpr.is_a? Numeric end end 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,27 @@ l = Lisp.new l.eval [:label, :a, 42] l.eval :a #=> 42 l.eval [:eq, 42, :a] #=> true l.eval [:quote, [1, 2]] #=> [1, 2] l.eval [:car, [:quote, [1, 2]]] #=> 1 l.eval [:cdr, [:quote, [1, 2]]] #=> [2] l.eval [:cons, 1, [:quote, [2,3]]] #=> [1, 2, 3] l.eval [:if, [:eq, 1, 2], 42, 43] #=> 43 l.eval [:atom, [:quote, [1,2]]] #=> false -
fogus created this gist
Jan 25, 2012 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,72 @@ class Lisp def initialize @env = { :label => lambda { |(name,val), _| @env[name] = val }, :quote => lambda { |sexpr, _| sexpr[0] }, :car => lambda { |(list), _| list[0] }, :cdr => lambda { |(list), _| list.drop 1 }, :cons => lambda { |(e,cell), _| [e] + cell }, :eq => lambda { |(l,r), _| l == r }, :if => lambda { |(cond, thn, els), ctx| eval(cond, ctx) ? eval(thn, ctx) : eval(els, ctx) }, :atom => lambda { |(thing), _| atom? thing } } end def apply fn, args, ctx=@env return @env[fn].call(args, ctx) if primitive? fn self.eval @env[fn][2], Hash[*(@env[fn][1].zip args).flatten] end def eval sexpr, ctx=@env if atom? sexpr return ctx[sexpr] if ctx[sexpr] return sexpr end fn = sexpr[0] args = (sexpr.drop 1) args = args.map { |a| self.eval(a, ctx) } if not [:quote, :if].member? fn apply(fn, args, ctx) end def primitive? name @env[name].respond_to? :call end def atom? sexpr sexpr.is_a? Symbol or sexpr.is_a? Numeric end end <<-LISP l = Lisp.new l.eval [:label, :a, 42] l.eval :a #=> 42 l.eval [:eq, 42, :a] #=> true l.eval [:quote, [1, 2]] #=> [1, 2] l.eval [:car, [:quote, [1, 2]]] #=> 1 l.eval [:cdr, [:quote, [1, 2]]] #=> [2] l.eval [:cons, 1, [:quote, [2,3]]] #=> [1, 2, 3] l.eval [:if, [:eq, 1, 2], 42, 43] #=> 43 l.eval [:atom, [:quote, [1,2]]] #=> false LISP