dslisprb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +0 -0
- data/README.rdoc +63 -0
- data/Rakefile +44 -0
- data/TODO +3 -0
- data/bin/dslisprb +44 -0
- data/lib/dslisprb.rb +201 -0
- data/lib/dslisprb.rb~ +201 -0
- data/spec/ast.rb +55 -0
- data/spec/ast.rb~ +55 -0
- data/spec/defun.rb +27 -0
- data/spec/defun.rb~ +27 -0
- data/spec/execution.rb +25 -0
- data/spec/execution.rb~ +25 -0
- data/spec/functions.rb +132 -0
- data/spec/functions.rb~ +132 -0
- data/spec/macro.rb +11 -0
- data/spec/macro.rb~ +11 -0
- metadata +62 -0
data/CHANGELOG
ADDED
File without changes
|
data/README.rdoc
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
dslisprb (dseminara 'lisp)
|
2
|
+
http://github.com/tario/dslisprb
|
3
|
+
Dario Seminara (http://tario-project.blogspot.com.ar/)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
dseminara 'lisp is my own implementation of lisp on ruby, created as an excercise in preparation for finals
|
8
|
+
|
9
|
+
dslisprb try to be minimalist (only 200 lines of ruby code including parser, default
|
10
|
+
functions and macros and about 30 lines for the repl) by using ruby code generation where possible
|
11
|
+
|
12
|
+
For example, lisp lambdas are represented as ruby lambdas defined with the code translated from lisp to ruby
|
13
|
+
and lisp variables (including those where default functions/lambda are stored) are translated as ruby variables
|
14
|
+
allowing reuse of the ruby stack instead of reimplement it
|
15
|
+
|
16
|
+
== FEATURES:
|
17
|
+
|
18
|
+
* dslisprb executable with readline
|
19
|
+
* Basic common lisp functions
|
20
|
+
|
21
|
+
== TODO:
|
22
|
+
|
23
|
+
* MAPCAR
|
24
|
+
* Defined functions and variable persistent between multiple evaluate calls
|
25
|
+
* caaaar, cdadar, cddra, etc...
|
26
|
+
|
27
|
+
== SYNOPSIS:
|
28
|
+
|
29
|
+
See 'dslisprb --help' for usage information.
|
30
|
+
|
31
|
+
== REQUIREMENTS:
|
32
|
+
|
33
|
+
* Ruby
|
34
|
+
|
35
|
+
== INSTALL:
|
36
|
+
|
37
|
+
* gem install dslisprb
|
38
|
+
|
39
|
+
== LICENSE:
|
40
|
+
|
41
|
+
(The MIT License)
|
42
|
+
|
43
|
+
Copyright (c) 2012 Dario Seminara
|
44
|
+
|
45
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
46
|
+
a copy of this software and associated documentation files (the
|
47
|
+
'Software'), to deal in the Software without restriction, including
|
48
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
49
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
50
|
+
permit persons to whom the Software is furnished to do so, subject to
|
51
|
+
the following conditions:
|
52
|
+
|
53
|
+
The above copyright notice and this permission notice shall be
|
54
|
+
included in all copies or substantial portions of the Software.
|
55
|
+
|
56
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
57
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
58
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
59
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
60
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
61
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
62
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
63
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rdoc/task'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require "rspec/core/rake_task"
|
7
|
+
|
8
|
+
spec = Gem::Specification.new do |s|
|
9
|
+
s.name = 'dslisprb'
|
10
|
+
s.version = '0.0.1'
|
11
|
+
s.author = 'Dario Seminara'
|
12
|
+
s.email = 'robertodarioseminara@gmail.com'
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.summary = 'Lisp interpreter written in ruby, using code generation'
|
15
|
+
s.homepage = "http://github.com/tario/dslisprb"
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.executables = ["dslisprb"]
|
18
|
+
s.files = Dir.glob("{lib,spec}/**/*") + [ 'README.rdoc', 'Rakefile', 'TODO', 'CHANGELOG' ]
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Run tests'
|
22
|
+
|
23
|
+
RSpec::Core::RakeTask.new("test:units") do |t|
|
24
|
+
t.pattern= 'spec/**/*.rb'
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Generate RDoc'
|
28
|
+
Rake::RDocTask.new :rdoc do |rd|
|
29
|
+
rd.rdoc_dir = 'doc'
|
30
|
+
rd.rdoc_files.add 'lib', 'README.rdoc'
|
31
|
+
rd.main = 'README.rdoc'
|
32
|
+
end
|
33
|
+
|
34
|
+
desc 'Build Gem'
|
35
|
+
Rake::GemPackageTask.new spec do |pkg|
|
36
|
+
pkg.need_tar = true
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'Clean up'
|
40
|
+
task :clean => [ :clobber_rdoc, :clobber_package ]
|
41
|
+
|
42
|
+
desc 'Clean up'
|
43
|
+
task :clobber => [ :clean ]
|
44
|
+
|
data/TODO
ADDED
data/bin/dslisprb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "dslisprb"
|
3
|
+
|
4
|
+
dslisp = DsLisp.new
|
5
|
+
if ARGV[0]
|
6
|
+
if ARGV[0] == '--help'
|
7
|
+
print "
|
8
|
+
dslisprb --help
|
9
|
+
show this message
|
10
|
+
dslisprb <lisp expression>
|
11
|
+
evaluate lisp expression, shows the result on standard output and exit
|
12
|
+
|
13
|
+
Example:
|
14
|
+
dslisprb \"(car '(1 2 3))\"
|
15
|
+
(2 3)
|
16
|
+
|
17
|
+
dslisprb without arguments starts the repl
|
18
|
+
"
|
19
|
+
|
20
|
+
else
|
21
|
+
# execute and exit
|
22
|
+
print dslisp.evaluate(ARGV[0]).lisp_inspect,"\n"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
# repl
|
26
|
+
require 'readline'
|
27
|
+
print "enter lisp commands or quit to exit\n"
|
28
|
+
|
29
|
+
stty_save = `stty -g`.chomp
|
30
|
+
trap('INT') { system('stty', stty_save); exit }
|
31
|
+
|
32
|
+
while cmd = Readline.readline('> ', true)
|
33
|
+
if cmd == "quit"
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
begin
|
38
|
+
print dslisp.evaluate(cmd).lisp_inspect,"\n"
|
39
|
+
rescue Exception => e
|
40
|
+
p e
|
41
|
+
print e.backtrace.join("\n"),"\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/dslisprb.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
class DsLisp
|
2
|
+
class ToRuby
|
3
|
+
class << self
|
4
|
+
def name_convert(name)
|
5
|
+
{:< => "lt", :> => "ht", :+ => "plus", :* => "mult" , :/ => "divide", :- => "minus" }[name] || "_" + name.to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_ruby(code)
|
9
|
+
if Array === code
|
10
|
+
# lisp call
|
11
|
+
|
12
|
+
function_name = code.first
|
13
|
+
|
14
|
+
if (CommonLispOperators.methods - Class.methods).include?(function_name)
|
15
|
+
CommonLispOperators.send(function_name, code)
|
16
|
+
else
|
17
|
+
strargs = code[1..-1].map{|x|
|
18
|
+
if Symbol === x
|
19
|
+
"(local_variables.include?(:#{x}) ? #{x} : (#{to_ruby(x)}))"
|
20
|
+
else
|
21
|
+
"(#{to_ruby(x)})"
|
22
|
+
end
|
23
|
+
}.join(",")
|
24
|
+
|
25
|
+
if Symbol === function_name
|
26
|
+
"#{name_convert(function_name)}.call(#{strargs})"
|
27
|
+
else
|
28
|
+
"#{to_ruby(code.first)}.call(#{strargs})"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
else
|
32
|
+
code.inspect
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module CommonLispOperators
|
39
|
+
class << self
|
40
|
+
def quote(code)
|
41
|
+
code[1].inspect
|
42
|
+
end
|
43
|
+
|
44
|
+
def lambda(code)
|
45
|
+
arguments = code[1].map(&:to_s).join(",")
|
46
|
+
"lambda{|#{arguments}| #{ToRuby.to_ruby(code[2])}}.lisp_inner_code(#{code.lisp_inspect.inspect})"
|
47
|
+
end
|
48
|
+
|
49
|
+
def block(code)
|
50
|
+
code[1..-1].map(&ToRuby.method(:to_ruby)).join(";")
|
51
|
+
end
|
52
|
+
|
53
|
+
def set(code)
|
54
|
+
"#{ToRuby.name_convert(code[1])} = #{ToRuby.to_ruby(code[2])}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def defun(code)
|
58
|
+
newcode = [:set, code[1], [:lambda, code[2], code[3]]]
|
59
|
+
ToRuby.to_ruby(newcode)
|
60
|
+
end
|
61
|
+
|
62
|
+
def defmacro(code)
|
63
|
+
name = code[1]
|
64
|
+
arguments = code[2]
|
65
|
+
impl = code[3][1]
|
66
|
+
|
67
|
+
subsl = Kernel.lambda{|_code, rplmap|
|
68
|
+
_code.map{|subcode|
|
69
|
+
if Array === subcode
|
70
|
+
subsl.call(subcode, rplmap)
|
71
|
+
else
|
72
|
+
rplmap[subcode] || subcode
|
73
|
+
end
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
CommonLispOperators.define_singleton_method(name) do |_code|
|
78
|
+
rplmap = {}
|
79
|
+
(0..arguments.size-1).each do |i|
|
80
|
+
rplmap[arguments[i]] = _code[i+1]
|
81
|
+
end
|
82
|
+
|
83
|
+
ToRuby.to_ruby subsl.call(impl, rplmap)
|
84
|
+
end
|
85
|
+
|
86
|
+
""
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse(str)
|
92
|
+
if str.count("(") != str.count(")")
|
93
|
+
raise "Parentheshis count does not match, try adding parenthesis at the end of string :P"
|
94
|
+
end
|
95
|
+
|
96
|
+
if matchdata = /^\s*\'(.*)\s*$/.match(str)
|
97
|
+
[:quote, parse(matchdata[1].sub("'",""))]
|
98
|
+
elsif matchdata = /^\s*\((.*)\)\s*$/.match(str)
|
99
|
+
inside_code = matchdata[1]
|
100
|
+
if inside_code =~ /^\s*$/
|
101
|
+
[]
|
102
|
+
else
|
103
|
+
# split tokens preserving parenthesis count
|
104
|
+
tokens = []
|
105
|
+
newtoken = ""
|
106
|
+
inside_code.split.each do |str|
|
107
|
+
newtoken << " "
|
108
|
+
newtoken << str
|
109
|
+
if newtoken.count("(") == newtoken.count(")")
|
110
|
+
tokens << newtoken
|
111
|
+
newtoken = ""
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
tokens.map(&method(:parse))
|
116
|
+
end
|
117
|
+
else
|
118
|
+
if str =~ /^\s*\d+\s*$/
|
119
|
+
str.to_i
|
120
|
+
else
|
121
|
+
str.strip.to_sym
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def evaluate(code)
|
127
|
+
if String === code
|
128
|
+
return evaluate(parse code)
|
129
|
+
end
|
130
|
+
# arithmethic
|
131
|
+
plus = lambda{|x,y| x+y}
|
132
|
+
mult = lambda{|x,y| x*y}
|
133
|
+
divide = lambda{|x,y| x/y}
|
134
|
+
minus = lambda{|x,y| x-y}
|
135
|
+
|
136
|
+
lt = lambda{|x,y| x<y || nil}
|
137
|
+
ht = lambda{|x,y| x>y || nil}
|
138
|
+
_eq = lambda{|x,y| x==y || nil}
|
139
|
+
|
140
|
+
|
141
|
+
# list selectors
|
142
|
+
_car = lambda{|x| x.first}
|
143
|
+
_cdr = lambda{|x| x[1..-1]}
|
144
|
+
_nth = lambda{|index,list| list[index-1]}
|
145
|
+
|
146
|
+
# list constructors
|
147
|
+
_cons = lambda{|element, list| [element]+list}
|
148
|
+
_append = plus
|
149
|
+
_list = lambda{|*args| args}
|
150
|
+
|
151
|
+
# recognizers
|
152
|
+
_null = lambda{|element| (element == nil or element == []) || nil}
|
153
|
+
_atom = lambda{|element| (not Array === element) || nil}
|
154
|
+
_numberp = lambda{|element| Numeric === element || nil}
|
155
|
+
_symbolp = lambda{|element| Symbol === element || nil}
|
156
|
+
_listp = lambda{|element| Array === element || nil}
|
157
|
+
_length = lambda{|list| list.size}
|
158
|
+
|
159
|
+
# nil
|
160
|
+
_nil = lambda{nil}
|
161
|
+
|
162
|
+
# boolean
|
163
|
+
_not = lambda{|a| (not a) || nil}
|
164
|
+
_and = lambda{|a,b| (a and b) || nil}
|
165
|
+
_or = lambda{|a,b| (a or b) || nil}
|
166
|
+
|
167
|
+
# generate ruby code for lisp ast
|
168
|
+
ruby_code = ToRuby.to_ruby(code)
|
169
|
+
eval(ruby_code)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class Object
|
174
|
+
def lisp_inspect
|
175
|
+
inspect
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class Symbol
|
180
|
+
def lisp_inspect
|
181
|
+
to_s
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class Array
|
186
|
+
def lisp_inspect
|
187
|
+
"(" + map(&:lisp_inspect).join(" ") + ")"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class Proc
|
192
|
+
def lisp_inspect
|
193
|
+
@inner_code
|
194
|
+
end
|
195
|
+
|
196
|
+
def lisp_inner_code(code)
|
197
|
+
@inner_code = code
|
198
|
+
self
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
data/lib/dslisprb.rb~
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
class DsLisp
|
2
|
+
class ToRuby
|
3
|
+
class << self
|
4
|
+
def name_convert(name)
|
5
|
+
{:< => "lt", :> => "ht", :+ => "plus", :* => "mult" , :/ => "divide", :- => "minus" }[name] || "_" + name.to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_ruby(code)
|
9
|
+
if Array === code
|
10
|
+
# lisp call
|
11
|
+
|
12
|
+
function_name = code.first
|
13
|
+
|
14
|
+
if (CommonLispOperators.methods - Class.methods).include?(function_name)
|
15
|
+
CommonLispOperators.send(function_name, code)
|
16
|
+
else
|
17
|
+
strargs = code[1..-1].map{|x|
|
18
|
+
if Symbol === x
|
19
|
+
"(local_variables.include?(:#{x}) ? #{x} : (#{to_ruby(x)}))"
|
20
|
+
else
|
21
|
+
"(#{to_ruby(x)})"
|
22
|
+
end
|
23
|
+
}.join(",")
|
24
|
+
|
25
|
+
if Symbol === function_name
|
26
|
+
"#{name_convert(function_name)}.call(#{strargs})"
|
27
|
+
else
|
28
|
+
"#{to_ruby(code.first)}.call(#{strargs})"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
else
|
32
|
+
code.inspect
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module CommonLispOperators
|
39
|
+
class << self
|
40
|
+
def quote(code)
|
41
|
+
code[1].inspect
|
42
|
+
end
|
43
|
+
|
44
|
+
def lambda(code)
|
45
|
+
arguments = code[1].map(&:to_s).join(",")
|
46
|
+
"lambda{|#{arguments}| #{ToRuby.to_ruby(code[2])}}.lisp_inner_code(#{code.lisp_inspect.inspect})"
|
47
|
+
end
|
48
|
+
|
49
|
+
def block(code)
|
50
|
+
code[1..-1].map(&ToRuby.method(:to_ruby)).join(";")
|
51
|
+
end
|
52
|
+
|
53
|
+
def set(code)
|
54
|
+
"#{ToRuby.name_convert(code[1])} = #{ToRuby.to_ruby(code[2])}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def defun(code)
|
58
|
+
newcode = [:set, code[1], [:lambda, code[2], code[3]]]
|
59
|
+
ToRuby.to_ruby(newcode)
|
60
|
+
end
|
61
|
+
|
62
|
+
def defmacro(code)
|
63
|
+
name = code[1]
|
64
|
+
arguments = code[2]
|
65
|
+
impl = code[3][1]
|
66
|
+
|
67
|
+
subsl = Kernel.lambda{|_code, rplmap|
|
68
|
+
_code.map{|subcode|
|
69
|
+
if Array === subcode
|
70
|
+
subsl.call(subcode, rplmap)
|
71
|
+
else
|
72
|
+
rplmap[subcode] || subcode
|
73
|
+
end
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
CommonLispOperators.define_singleton_method(name) do |_code|
|
78
|
+
rplmap = {}
|
79
|
+
(0..arguments.size-1).each do |i|
|
80
|
+
rplmap[arguments[i]] = _code[i+1]
|
81
|
+
end
|
82
|
+
|
83
|
+
ToRuby.to_ruby subsl.call(impl, rplmap)
|
84
|
+
end
|
85
|
+
|
86
|
+
""
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse(str)
|
92
|
+
if str.count("(") != str.count(")")
|
93
|
+
raise "Parentheshis count does not match, try adding parenthesis to the end :P"
|
94
|
+
end
|
95
|
+
|
96
|
+
if matchdata = /^\s*\'(.*)\s*$/.match(str)
|
97
|
+
[:quote, parse(matchdata[1].sub("'",""))]
|
98
|
+
elsif matchdata = /^\s*\((.*)\)\s*$/.match(str)
|
99
|
+
inside_code = matchdata[1]
|
100
|
+
if inside_code =~ /^\s*$/
|
101
|
+
[]
|
102
|
+
else
|
103
|
+
# split tokens preserving parenthesis count
|
104
|
+
tokens = []
|
105
|
+
newtoken = ""
|
106
|
+
inside_code.split.each do |str|
|
107
|
+
newtoken << " "
|
108
|
+
newtoken << str
|
109
|
+
if newtoken.count("(") == newtoken.count(")")
|
110
|
+
tokens << newtoken
|
111
|
+
newtoken = ""
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
tokens.map(&method(:parse))
|
116
|
+
end
|
117
|
+
else
|
118
|
+
if str =~ /^\s*\d+\s*$/
|
119
|
+
str.to_i
|
120
|
+
else
|
121
|
+
str.strip.to_sym
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def evaluate(code)
|
127
|
+
if String === code
|
128
|
+
return evaluate(parse code)
|
129
|
+
end
|
130
|
+
# arithmethic
|
131
|
+
plus = lambda{|x,y| x+y}
|
132
|
+
mult = lambda{|x,y| x*y}
|
133
|
+
divide = lambda{|x,y| x/y}
|
134
|
+
minus = lambda{|x,y| x-y}
|
135
|
+
|
136
|
+
lt = lambda{|x,y| x<y || nil}
|
137
|
+
ht = lambda{|x,y| x>y || nil}
|
138
|
+
_eq = lambda{|x,y| x==y || nil}
|
139
|
+
|
140
|
+
|
141
|
+
# list selectors
|
142
|
+
_car = lambda{|x| x.first}
|
143
|
+
_cdr = lambda{|x| x[1..-1]}
|
144
|
+
_nth = lambda{|index,list| list[index-1]}
|
145
|
+
|
146
|
+
# list constructors
|
147
|
+
_cons = lambda{|element, list| [element]+list}
|
148
|
+
_append = plus
|
149
|
+
_list = lambda{|*args| args}
|
150
|
+
|
151
|
+
# recognizers
|
152
|
+
_null = lambda{|element| (element == nil or element == []) || nil}
|
153
|
+
_atom = lambda{|element| (not Array === element) || nil}
|
154
|
+
_numberp = lambda{|element| Numeric === element || nil}
|
155
|
+
_symbolp = lambda{|element| Symbol === element || nil}
|
156
|
+
_listp = lambda{|element| Array === element || nil}
|
157
|
+
_length = lambda{|list| list.size}
|
158
|
+
|
159
|
+
# nil
|
160
|
+
_nil = lambda{nil}
|
161
|
+
|
162
|
+
# boolean
|
163
|
+
_not = lambda{|a| (not a) || nil}
|
164
|
+
_and = lambda{|a,b| (a and b) || nil}
|
165
|
+
_or = lambda{|a,b| (a or b) || nil}
|
166
|
+
|
167
|
+
# generate ruby code for lisp ast
|
168
|
+
ruby_code = ToRuby.to_ruby(code)
|
169
|
+
eval(ruby_code)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class Object
|
174
|
+
def lisp_inspect
|
175
|
+
inspect
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class Symbol
|
180
|
+
def lisp_inspect
|
181
|
+
to_s
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class Array
|
186
|
+
def lisp_inspect
|
187
|
+
"(" + map(&:lisp_inspect).join(" ") + ")"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class Proc
|
192
|
+
def lisp_inspect
|
193
|
+
@inner_code
|
194
|
+
end
|
195
|
+
|
196
|
+
def lisp_inner_code(code)
|
197
|
+
@inner_code = code
|
198
|
+
self
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
data/spec/ast.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp" do
|
4
|
+
|
5
|
+
(1..10).each do |i|
|
6
|
+
it "should parse simple numeric atom #{i}" do
|
7
|
+
DsLisp.new.parse(i.to_s).should be == i
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
(1..10).each do |i|
|
12
|
+
it "should parse simple numeric atom #{i} with spaces around" do
|
13
|
+
DsLisp.new.parse(" " + i.to_s + " ").should be == i
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
[:x,:y,:z].each do |symbol|
|
18
|
+
it "should parse simple symbolic atom #{symbol}" do
|
19
|
+
DsLisp.new.parse(symbol.to_s).should be == symbol
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse empty list" do
|
24
|
+
DsLisp.new.parse('()').should be == []
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse list with atom inside" do
|
28
|
+
DsLisp.new.parse('(1)').should be == [1]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse list with two atoms inside" do
|
32
|
+
DsLisp.new.parse('(1 2)').should be == [1, 2]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should parse list with a list with two atoms inside" do
|
36
|
+
DsLisp.new.parse('((1 2))').should be == [[1, 2]]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should parse list with two list with two atoms inside" do
|
40
|
+
DsLisp.new.parse('((1 2) (3 4))').should be == [[1, 2],[3, 4]]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should parse list with two list with two symbolic atoms inside" do
|
44
|
+
DsLisp.new.parse('((a b) (c d))').should be == [[:a, :b],[:c, :d]]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should parse quote with atoms" do
|
48
|
+
DsLisp.new.parse("'car").should be == [:quote, :car]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should parse quote with lists" do
|
52
|
+
DsLisp.new.parse("'(1 2 3)").should be == [:quote, [1,2,3]]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/spec/ast.rb~
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp" do
|
4
|
+
|
5
|
+
(1..10).each do |i|
|
6
|
+
it "should parse simple numeric atom #{i}" do
|
7
|
+
DsLisp.new.parse(i.to_s).should be == i
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
(1..10).each do |i|
|
12
|
+
it "should parse simple numeric atom #{i} with spaces around" do
|
13
|
+
DsLisp.new.parse(" " + i.to_s + " ").should be == i
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
[:x,:y,:z].each do |symbol|
|
18
|
+
it "should parse simple symbolic atom #{symbol}" do
|
19
|
+
DsLisp.new.parse(symbol.to_s).should be == symbol
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse empty list" do
|
24
|
+
DsLisp.new.parse('()').should be == []
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse list with atom inside" do
|
28
|
+
DsLisp.new.parse('(1)').should be == [1]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse list with two atoms inside" do
|
32
|
+
DsLisp.new.parse('(1 2)').should be == [1, 2]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should parse list with a list with two atoms inside" do
|
36
|
+
DsLisp.new.parse('((1 2))').should be == [[1, 2]]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should parse list with two list with two atoms inside" do
|
40
|
+
DsLisp.new.parse('((1 2) (3 4))').should be == [[1, 2],[3, 4]]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should parse list with two list with two symbolic atoms inside" do
|
44
|
+
DsLisp.new.parse('((a b) (c d))').should be == [[:a, :b],[:c, :d]]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should parse quote with atoms" do
|
48
|
+
DsLisp.new.parse("'car").should be == [:quote, :car]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should parse quote with lists" do
|
52
|
+
DsLisp.new.parse("'(1,2,3)").should be == [:quote, [1,2,3]]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/spec/defun.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp defun" do
|
4
|
+
it "should allow lambda" do
|
5
|
+
DsLisp.new.evaluate([:lambda, [:x], [:+, :x, 1]]).call(1).should be == 2
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should allow lambda assign and call" do
|
9
|
+
DsLisp.new.evaluate([:block,
|
10
|
+
[:set, :lambda_test, [:lambda, [:x], [:+, :x, 1]]],
|
11
|
+
[:lambda_test, 1]
|
12
|
+
]).should be == 2
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should allow lambda returning 3" do
|
16
|
+
DsLisp.new.evaluate([:lambda, [:x], [:+, :x, 2]]).call(1).should be == 3
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should allow defun as brief for lambda assign" do
|
20
|
+
DsLisp.new.evaluate([:block,
|
21
|
+
[:defun, :lambda_test, [:x], [:+, :x, 1]],
|
22
|
+
[:lambda_test, 1]
|
23
|
+
]).should be == 2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
data/spec/defun.rb~
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp defun" do
|
4
|
+
it "should allow lambda" do
|
5
|
+
DsLisp.new.evaluate([:lambda, [:x], [:+, :x, 1]]).call(1).should be == 2
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should allow lambda assign and call" do
|
9
|
+
DsLisp.new.evaluate([:block,
|
10
|
+
[:set, :lambda_test, [:lambda, [:x], [:+, :x, 1]]],
|
11
|
+
[:lambda_test, 1]
|
12
|
+
]).should be == 2
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should allow lambda returning 3" do
|
16
|
+
DsLisp.new.evaluate([:lambda, [:x], [:+, :x, 2]]).call(1).should be == 3
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should allow defun as brief for lambda assign" do
|
20
|
+
DsLisp.new.evaluate([:block,
|
21
|
+
[:defun, :lambda_test, [:x], [:+, :x, 1]],
|
22
|
+
[:lambda_test, 1]
|
23
|
+
]).should be == 2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
data/spec/execution.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp execution" do
|
4
|
+
|
5
|
+
(1..10).each do |i|
|
6
|
+
it "should evaluate simple numeric atom #{i}" do
|
7
|
+
DsLisp.new.evaluate(i).should be == i
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
[:x,:y,:z].each do |symbol|
|
12
|
+
it "should parse simple symbolic atom #{symbol}" do
|
13
|
+
DsLisp.new.evaluate(symbol).should be == symbol
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should evaluate call to arithmetic method +" do
|
18
|
+
DsLisp.new.evaluate([:+, 1, 2]).should be == 3
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should evaluate quote call to define literals" do
|
22
|
+
DsLisp.new.evaluate([:quote, [1, 2, 3]]).should be == [1, 2, 3]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/spec/execution.rb~
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp execution" do
|
4
|
+
|
5
|
+
(1..10).each do |i|
|
6
|
+
it "should evaluate simple numeric atom #{i}" do
|
7
|
+
DsLisp.new.evaluate(i).should be == i
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
[:x,:y,:z].each do |symbol|
|
12
|
+
it "should parse simple symbolic atom #{symbol}" do
|
13
|
+
DsLisp.new.evaluate(symbol).should be == symbol
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should evaluate call to arithmetic method +" do
|
18
|
+
DsLisp.new.evaluate([:+, 1, 2]).should be == 3
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should evaluate quote call to define literals" do
|
22
|
+
DsLisp.new.evaluate([:quote, [1, 2, 3]).should be == [1, 2, 3]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/spec/functions.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp functions" do
|
4
|
+
|
5
|
+
# selectors
|
6
|
+
it "should return 1 for (car (quote (1 2)))" do
|
7
|
+
DsLisp.new.evaluate([:car, [:quote, [1, 2]]]).should be == 1
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return (2 3) for (cdr (quote (1 2 3)))" do
|
11
|
+
DsLisp.new.evaluate([:cdr, [:quote, [1, 2, 3]]]).should be == [2, 3]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return 5 for (nth 2 (quote (4 5 6)))" do
|
15
|
+
DsLisp.new.evaluate([:nth, 2, [:quote, [4, 5, 6]]]).should be == 5
|
16
|
+
end
|
17
|
+
|
18
|
+
# constructors
|
19
|
+
it "should return (1 2 3 4) for (cons 1 (quote (2 3 4)))" do
|
20
|
+
DsLisp.new.evaluate([:cons, 1, [:quote, [2, 3, 4]]]).should be == [1,2,3,4]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return (1 2 3 4 5) for (append (quote (1 2)) (quote (3 4 5)))" do
|
24
|
+
DsLisp.new.evaluate([:append, [:quote, [1,2]], [:quote, [3, 4, 5]]]).should be == [1,2,3,4,5]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return (1 2) for (list 1 2)" do
|
28
|
+
DsLisp.new.evaluate([:list, 1, 2]).should be == [1,2]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return (1 2 3) for (list 1 2 3)" do
|
32
|
+
DsLisp.new.evaluate([:list, 1, 2, 3]).should be == [1,2,3]
|
33
|
+
end
|
34
|
+
|
35
|
+
# type recognizers
|
36
|
+
[:a, 1, [1,2,3,4], [], nil].each do |obj|
|
37
|
+
result = (obj == nil or obj == []) ? true : nil
|
38
|
+
it "should return #{result} for (null #{obj})" do
|
39
|
+
DsLisp.new.evaluate([:null, [:quote, obj]]).should be == result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
[:a, 1, [1,2,3,4]].each do |obj|
|
44
|
+
result = (not Array === obj) ? true : nil
|
45
|
+
it "should return #{result} for (atom #{obj})" do
|
46
|
+
DsLisp.new.evaluate([:atom, [:quote, obj]]).should be == result
|
47
|
+
end
|
48
|
+
|
49
|
+
numberp_result = (Numeric === obj) ? true : nil
|
50
|
+
it "should return #{result} for (numberp #{obj})" do
|
51
|
+
DsLisp.new.evaluate([:numberp, [:quote, obj]]).should be == numberp_result
|
52
|
+
end
|
53
|
+
|
54
|
+
symbolp_result = (Symbol === obj) ? true : nil
|
55
|
+
it "should return #{result} for (symbolp #{obj})" do
|
56
|
+
DsLisp.new.evaluate([:symbolp, [:quote, obj]]).should be == symbolp_result
|
57
|
+
end
|
58
|
+
|
59
|
+
listp_result = (Array === obj) ? true : nil
|
60
|
+
it "should return #{result} for (listp #{obj})" do
|
61
|
+
DsLisp.new.evaluate([:listp, [:quote, obj]]).should be == listp_result
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
[[1], [1,2], [1,2,3], [1,2,3,4]].each do |obj|
|
66
|
+
result = obj.size
|
67
|
+
it "should return #{result} for (length #{obj})" do
|
68
|
+
DsLisp.new.evaluate([:length, [:quote, obj]]).should be == result
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return nil on nil function" do
|
73
|
+
DsLisp.new.evaluate([:nil]).should be == nil
|
74
|
+
end
|
75
|
+
|
76
|
+
# arithmetic
|
77
|
+
it "should call +" do
|
78
|
+
DsLisp.new.evaluate([:+,1,2]).should be == 3
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should call -" do
|
82
|
+
DsLisp.new.evaluate([:-,7,4]).should be == 3
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should call *" do
|
86
|
+
DsLisp.new.evaluate([:*,5,6]).should be == 30
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should call /" do
|
90
|
+
DsLisp.new.evaluate([:/,10,2]).should be == 5
|
91
|
+
end
|
92
|
+
|
93
|
+
# relational
|
94
|
+
[[3,2],[3,3],[3,4]].each do |pair|
|
95
|
+
result = pair.first < pair.last || nil
|
96
|
+
it "should call <" do
|
97
|
+
DsLisp.new.evaluate([:<,pair.first,pair.last]).should be == result
|
98
|
+
end
|
99
|
+
|
100
|
+
resultht = pair.first > pair.last || nil
|
101
|
+
it "should call >" do
|
102
|
+
DsLisp.new.evaluate([:>,pair.first,pair.last]).should be == resultht
|
103
|
+
end
|
104
|
+
|
105
|
+
resulteq = pair.first == pair.last || nil
|
106
|
+
it "should call eq" do
|
107
|
+
DsLisp.new.evaluate([:eq,pair.first,pair.last]).should be == resulteq
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# boolean
|
112
|
+
[[true,true],[true,nil],[nil,true],[nil,nil]].each do |pair|
|
113
|
+
resultor = (pair.first or pair.last) || nil
|
114
|
+
resultand = (pair.first and pair.last) || nil
|
115
|
+
resultnot = (not pair.first) || nil
|
116
|
+
|
117
|
+
it "should call or with #{pair} and return #{resultor}" do
|
118
|
+
DsLisp.new.evaluate([:or,pair.first,pair.last]).should be == resultor
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should call and with #{pair} and return #{resultand}" do
|
122
|
+
DsLisp.new.evaluate([:and,pair.first,pair.last]).should be == resultand
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should call not" do
|
126
|
+
DsLisp.new.evaluate([:not,pair.first]).should be == resultnot
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
|
data/spec/functions.rb~
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp::CommonLispFunctions, "ds lisp functions" do
|
4
|
+
|
5
|
+
# selectors
|
6
|
+
it "should return 1 for (car (quote (1 2)))" do
|
7
|
+
DsLisp.new.evaluate([:car, [:quote, [1, 2]]]).should be == 1
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return (2 3) for (cdr (quote (1 2 3)))" do
|
11
|
+
DsLisp.new.evaluate([:cdr, [:quote, [1, 2, 3]]]).should be == [2, 3]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return 5 for (nth 2 (quote (4 5 6)))" do
|
15
|
+
DsLisp.new.evaluate([:nth, 2, [:quote, [4, 5, 6]]]).should be == 5
|
16
|
+
end
|
17
|
+
|
18
|
+
# constructors
|
19
|
+
it "should return (1 2 3 4) for (cons 1 (quote (2 3 4)))" do
|
20
|
+
DsLisp.new.evaluate([:cons, 1, [:quote, [2, 3, 4]]]).should be == [1,2,3,4]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return (1 2 3 4 5) for (append (quote (1 2)) (quote (3 4 5)))" do
|
24
|
+
DsLisp.new.evaluate([:append, [:quote, [1,2]], [:quote, [3, 4, 5]]]).should be == [1,2,3,4,5]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return (1 2) for (list 1 2)" do
|
28
|
+
DsLisp.new.evaluate([:list, 1, 2]).should be == [1,2]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return (1 2 3) for (list 1 2 3)" do
|
32
|
+
DsLisp.new.evaluate([:list, 1, 2, 3]).should be == [1,2,3]
|
33
|
+
end
|
34
|
+
|
35
|
+
# type recognizers
|
36
|
+
[:a, 1, [1,2,3,4], [], nil].each do |obj|
|
37
|
+
result = (obj == nil or obj == []) ? true : nil
|
38
|
+
it "should return #{result} for (null #{obj})" do
|
39
|
+
DsLisp.new.evaluate([:null, [:quote, obj]]).should be == result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
[:a, 1, [1,2,3,4]].each do |obj|
|
44
|
+
result = (not Array === obj) ? true : nil
|
45
|
+
it "should return #{result} for (atom #{obj})" do
|
46
|
+
DsLisp.new.evaluate([:atom, [:quote, obj]]).should be == result
|
47
|
+
end
|
48
|
+
|
49
|
+
numberp_result = (Numeric === obj) ? true : nil
|
50
|
+
it "should return #{result} for (numberp #{obj})" do
|
51
|
+
DsLisp.new.evaluate([:numberp, [:quote, obj]]).should be == numberp_result
|
52
|
+
end
|
53
|
+
|
54
|
+
symbolp_result = (Symbol === obj) ? true : nil
|
55
|
+
it "should return #{result} for (symbolp #{obj})" do
|
56
|
+
DsLisp.new.evaluate([:symbolp, [:quote, obj]]).should be == symbolp_result
|
57
|
+
end
|
58
|
+
|
59
|
+
listp_result = (Array === obj) ? true : nil
|
60
|
+
it "should return #{result} for (listp #{obj})" do
|
61
|
+
DsLisp.new.evaluate([:listp, [:quote, obj]]).should be == listp_result
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
[[1], [1,2], [1,2,3], [1,2,3,4]].each do |obj|
|
66
|
+
result = obj.size
|
67
|
+
it "should return #{result} for (length #{obj})" do
|
68
|
+
DsLisp.new.evaluate([:length, [:quote, obj]]).should be == result
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return nil on nil function" do
|
73
|
+
DsLisp.new.evaluate([:nil]).should be == nil
|
74
|
+
end
|
75
|
+
|
76
|
+
# arithmetic
|
77
|
+
it "should call +" do
|
78
|
+
DsLisp.new.evaluate([:+,1,2]).should be == 3
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should call -" do
|
82
|
+
DsLisp.new.evaluate([:-,7,4]).should be == 3
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should call *" do
|
86
|
+
DsLisp.new.evaluate([:*,5,6]).should be == 30
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should call /" do
|
90
|
+
DsLisp.new.evaluate([:/,10,2]).should be == 5
|
91
|
+
end
|
92
|
+
|
93
|
+
# relational
|
94
|
+
[[3,2],[3,3],[3,4]].each do |pair|
|
95
|
+
result = pair.first < pair.last || nil
|
96
|
+
it "should call <" do
|
97
|
+
DsLisp.new.evaluate([:<,pair.first,pair.last]).should be == result
|
98
|
+
end
|
99
|
+
|
100
|
+
resultht = pair.first > pair.last || nil
|
101
|
+
it "should call >" do
|
102
|
+
DsLisp.new.evaluate([:>,pair.first,pair.last]).should be == resultht
|
103
|
+
end
|
104
|
+
|
105
|
+
resulteq = pair.first == pair.last || nil
|
106
|
+
it "should call eq" do
|
107
|
+
DsLisp.new.evaluate([:eq,pair.first,pair.last]).should be == resulteq
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# boolean
|
112
|
+
[[true,true],[true,nil],[nil,true],[nil,nil]].each do |pair|
|
113
|
+
resultor = (pair.first or pair.last) || nil
|
114
|
+
resultand = (pair.first and pair.last) || nil
|
115
|
+
resultnot = (not pair.first) || nil
|
116
|
+
|
117
|
+
it "should call or with #{pair} and return #{resultor}" do
|
118
|
+
DsLisp.new.evaluate([:or,pair.first,pair.last]).should be == resultor
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should call and with #{pair} and return #{resultand}" do
|
122
|
+
DsLisp.new.evaluate([:and,pair.first,pair.last]).should be == resultand
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should call not" do
|
126
|
+
DsLisp.new.evaluate([:not,pair.first]).should be == resultnot
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
|
data/spec/macro.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp macro" do
|
4
|
+
it "should allow defmacro and use on different call" do
|
5
|
+
dslisp = DsLisp.new
|
6
|
+
dslisp.evaluate([:defmacro, :square, [:x], [:quote, [:*, :x, :x]]])
|
7
|
+
dslisp.evaluate([:square, 5]).should be == 25
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
|
data/spec/macro.rb~
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "dslisprb"
|
2
|
+
|
3
|
+
describe DsLisp, "ds lisp macro" do
|
4
|
+
it "should allow defmacro and use on different call" do
|
5
|
+
dslisp = DsLisp.new
|
6
|
+
dslisp.evaluate([:defmacro, :square, [:z], [:quote, [:*, :x, :x]]])
|
7
|
+
dslisp.evaluate([:square, 5]).should be == 25
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dslisprb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dario Seminara
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-25 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: robertodarioseminara@gmail.com
|
16
|
+
executables:
|
17
|
+
- dslisprb
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/dslisprb.rb
|
22
|
+
- lib/dslisprb.rb~
|
23
|
+
- spec/macro.rb
|
24
|
+
- spec/ast.rb
|
25
|
+
- spec/defun.rb~
|
26
|
+
- spec/execution.rb~
|
27
|
+
- spec/execution.rb
|
28
|
+
- spec/defun.rb
|
29
|
+
- spec/functions.rb~
|
30
|
+
- spec/macro.rb~
|
31
|
+
- spec/functions.rb
|
32
|
+
- spec/ast.rb~
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- TODO
|
36
|
+
- CHANGELOG
|
37
|
+
- bin/dslisprb
|
38
|
+
homepage: http://github.com/tario/dslisprb
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.8.10
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Lisp interpreter written in ruby, using code generation
|
62
|
+
test_files: []
|