ajlisp 0.0.0

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.
Files changed (88) hide show
  1. data/LICENSE +23 -0
  2. data/README.md +33 -0
  3. data/ajlisp.gemspec +20 -0
  4. data/lib/ajlisp.rb +128 -0
  5. data/lib/ajlisp/at_constant_atom.rb +30 -0
  6. data/lib/ajlisp/context.rb +27 -0
  7. data/lib/ajlisp/dot_verb_atom.rb +31 -0
  8. data/lib/ajlisp/file_source.rb +10 -0
  9. data/lib/ajlisp/fprimitive.rb +23 -0
  10. data/lib/ajlisp/fprimitive_closure.rb +48 -0
  11. data/lib/ajlisp/fprimitive_define.rb +30 -0
  12. data/lib/ajlisp/fprimitive_definef.rb +30 -0
  13. data/lib/ajlisp/fprimitive_definem.rb +30 -0
  14. data/lib/ajlisp/fprimitive_do.rb +25 -0
  15. data/lib/ajlisp/fprimitive_flambda.rb +21 -0
  16. data/lib/ajlisp/fprimitive_if.rb +34 -0
  17. data/lib/ajlisp/fprimitive_lambda.rb +21 -0
  18. data/lib/ajlisp/fprimitive_let.rb +38 -0
  19. data/lib/ajlisp/fprimitive_macro_closure.rb +13 -0
  20. data/lib/ajlisp/fprimitive_mlambda.rb +21 -0
  21. data/lib/ajlisp/fprimitive_quote.rb +19 -0
  22. data/lib/ajlisp/input_source.rb +37 -0
  23. data/lib/ajlisp/lexer.rb +132 -0
  24. data/lib/ajlisp/list.rb +106 -0
  25. data/lib/ajlisp/named_atom.rb +34 -0
  26. data/lib/ajlisp/nil_atom.rb +39 -0
  27. data/lib/ajlisp/parser.rb +80 -0
  28. data/lib/ajlisp/primitive.rb +19 -0
  29. data/lib/ajlisp/primitive_add.rb +29 -0
  30. data/lib/ajlisp/primitive_closure.rb +49 -0
  31. data/lib/ajlisp/primitive_comparisons.rb +84 -0
  32. data/lib/ajlisp/primitive_cons.rb +19 -0
  33. data/lib/ajlisp/primitive_divide.rb +25 -0
  34. data/lib/ajlisp/primitive_eval.rb +19 -0
  35. data/lib/ajlisp/primitive_first.rb +19 -0
  36. data/lib/ajlisp/primitive_list.rb +19 -0
  37. data/lib/ajlisp/primitive_load.rb +34 -0
  38. data/lib/ajlisp/primitive_multiply.rb +25 -0
  39. data/lib/ajlisp/primitive_predicates.rb +58 -0
  40. data/lib/ajlisp/primitive_rest.rb +19 -0
  41. data/lib/ajlisp/primitive_subtract.rb +25 -0
  42. data/lib/ajlisp/string_source.rb +28 -0
  43. data/lib/ajlisp/token.rb +23 -0
  44. data/lib/core.lsp +40 -0
  45. data/test/and.lsp +1 -0
  46. data/test/append.lsp +1 -0
  47. data/test/backquote.lsp +7 -0
  48. data/test/cond.lsp +1 -0
  49. data/test/define123.lsp +4 -0
  50. data/test/definem.lsp +1 -0
  51. data/test/dodefine123.lsp +5 -0
  52. data/test/mapcond.lsp +13 -0
  53. data/test/mapfirst.lsp +10 -0
  54. data/test/mycons.lsp +3 -0
  55. data/test/test.rb +42 -0
  56. data/test/test_at_constant_atom.rb +34 -0
  57. data/test/test_context.rb +37 -0
  58. data/test/test_dot_verb_atom.rb +29 -0
  59. data/test/test_evaluate.rb +289 -0
  60. data/test/test_evaluate_files.rb +136 -0
  61. data/test/test_file_source.rb +11 -0
  62. data/test/test_fprimitive_closure.rb +29 -0
  63. data/test/test_fprimitive_define.rb +65 -0
  64. data/test/test_fprimitive_definef.rb +20 -0
  65. data/test/test_fprimitive_definem.rb +20 -0
  66. data/test/test_fprimitive_do.rb +18 -0
  67. data/test/test_fprimitive_flambda.rb +15 -0
  68. data/test/test_fprimitive_if.rb +29 -0
  69. data/test/test_fprimitive_lambda.rb +15 -0
  70. data/test/test_fprimitive_let.rb +18 -0
  71. data/test/test_fprimitive_macro_closure.rb +17 -0
  72. data/test/test_fprimitive_mlambda.rb +12 -0
  73. data/test/test_fprimitive_quote.rb +35 -0
  74. data/test/test_lexer.rb +208 -0
  75. data/test/test_list.rb +102 -0
  76. data/test/test_load.rb +74 -0
  77. data/test/test_named_atom.rb +33 -0
  78. data/test/test_parser.rb +252 -0
  79. data/test/test_primitive_add.rb +26 -0
  80. data/test/test_primitive_closure.rb +29 -0
  81. data/test/test_primitive_cons.rb +39 -0
  82. data/test/test_primitive_eval.rb +13 -0
  83. data/test/test_primitive_first.rb +25 -0
  84. data/test/test_primitive_list.rb +27 -0
  85. data/test/test_primitive_rest.rb +29 -0
  86. data/test/test_string_source.rb +10 -0
  87. data/test/test_token.rb +14 -0
  88. metadata +131 -0
@@ -0,0 +1,29 @@
1
+
2
+ require 'ajlisp'
3
+ require 'test/unit'
4
+
5
+ module AjLisp
6
+
7
+ class TestDotVerbAtom < Test::Unit::TestCase
8
+ def test_initialize
9
+ atom = AjLisp::DotVerbAtom.new(".do")
10
+ assert_equal ".do".intern, atom.name
11
+ assert_equal :do, atom.symbol
12
+ end
13
+
14
+ def test_evaluate
15
+ atom = AjLisp::DotVerbAtom.new(".do")
16
+ method = atom.evaluate nil
17
+ assert method.is_a? PrimitiveNativeMethod
18
+ end
19
+
20
+ def test_apply_arity_0
21
+ atom = AjLisp::DotVerbAtom.new(".length")
22
+ method = atom.evaluate nil
23
+ result = method.apply(nil, ["foo"])
24
+ assert_equal 3, result
25
+ end
26
+ end
27
+
28
+ end
29
+
@@ -0,0 +1,289 @@
1
+ require 'ajlisp'
2
+ require 'test/unit'
3
+
4
+ module AjLisp
5
+
6
+ class TestEvaluate < Test::Unit::TestCase
7
+ def test_evaluate_integer
8
+ result = evaluateText("1")
9
+
10
+ assert_not_nil result
11
+ assert result.is_a? Fixnum
12
+ assert_equal 1, result
13
+ end
14
+
15
+ def test_evaluate_string
16
+ result = evaluateText('"foo"')
17
+
18
+ assert_not_nil result
19
+ assert result.is_a? String
20
+ assert_equal "foo", result
21
+ end
22
+
23
+ def test_evaluate_simple_quote
24
+ result = evaluateText('(quote a)')
25
+
26
+ assert_not_nil result
27
+ assert result.is_a? NamedAtom
28
+ assert_equal :a, result.name
29
+ end
30
+
31
+ def test_evaluate_quoted_list
32
+ result = evaluateText('(quote (a b))')
33
+
34
+ assert_not_nil result
35
+ assert result.is_a? List
36
+ assert_equal :a, result.first.name
37
+ assert_equal :b, result.rest.first.name
38
+ assert_nil result.rest.rest
39
+ end
40
+
41
+ def test_evaluate_simple_cons
42
+ result = evaluateText('(cons (quote a) (quote (b)))')
43
+
44
+ assert_not_nil result
45
+ assert result.is_a? List
46
+ assert_equal :a, result.first.name
47
+ assert_equal :b, result.rest.first.name
48
+ assert_nil result.rest.rest
49
+ end
50
+
51
+ def test_evaluate_simple_list
52
+ result = evaluateText("(list (quote a) (quote b))")
53
+
54
+ assert_not_nil result
55
+ assert result.is_a? List
56
+ assert_equal :a, result.first.name
57
+ assert_equal :b, result.rest.first.name
58
+ assert_nil result.rest.rest
59
+ end
60
+
61
+ def test_evaluate_simple_list_with_character_quote
62
+ result = evaluateText("(list 'a 'b))")
63
+
64
+ assert_not_nil result
65
+ assert result.is_a? List
66
+ assert_equal :a, result.first.name
67
+ assert_equal :b, result.rest.first.name
68
+ assert_nil result.rest.rest
69
+ end
70
+
71
+ def test_evaluate_simple_define
72
+ result = evaluateText("(define one 1)")
73
+
74
+ assert_not_nil result
75
+ assert_equal 1, AjLisp::context.getValue(:one)
76
+ end
77
+
78
+ def test_define_and_evaluate_simple_form
79
+ evaluateText("(define mycons (a b) (cons a b))")
80
+ result = evaluateText('(mycons (quote a) (quote (b)))')
81
+
82
+ assert_not_nil result
83
+ assert result.is_a? List
84
+ assert_equal :a, result.first.name
85
+ assert_equal :b, result.rest.first.name
86
+ assert_nil result.rest.rest
87
+ end
88
+
89
+ def test_evaluate_simple_add
90
+ result = evaluateText("(+ 1 2)")
91
+ assert_not_nil result
92
+ assert result.is_a? Fixnum
93
+ assert_equal 3, result
94
+ end
95
+
96
+ def test_define_form_with_closure
97
+ evaluateText("(define addx (x) (lambda (a) (+ a x)))")
98
+ evaluateText("(define addone (addx 1))")
99
+ result = evaluateText('(addone 3)')
100
+
101
+ assert_not_nil result
102
+ assert result.is_a? Fixnum
103
+ assert_equal 4, result
104
+ end
105
+
106
+ def test_define_form_with_free_variable
107
+ evaluateText("(define one 1)")
108
+ evaluateText("(define addone (x) (+ x one))")
109
+ assert_equal 4, evaluateText('(addone 3)')
110
+ evaluateText("(define one 2)")
111
+ assert_equal 5, evaluateText('(addone 3)')
112
+ end
113
+
114
+ def test_evaluate_native_method_arity_0
115
+ result = evaluateText('(.length "foo")')
116
+ assert_equal 3, result
117
+ end
118
+
119
+ def test_evaluate_native_method_arity_1
120
+ result = evaluateText('(.include? "foo" "o")')
121
+ assert_equal true, result
122
+ end
123
+
124
+ def test_evaluate_simple_constant
125
+ result = evaluateText('@String')
126
+ assert_equal String, result
127
+ end
128
+
129
+ def test_evaluate_nested_constant
130
+ result = evaluateText('@AjLisp::List')
131
+ assert_equal AjLisp::List, result
132
+ end
133
+
134
+ def test_evaluate_add
135
+ assert_equal 3, evaluateText('(+ 1 2)')
136
+ assert_equal 6, evaluateText('(+ 1 2 3)')
137
+ assert_equal 1, evaluateText('(+ 1)')
138
+ assert_equal 0, evaluateText('(+)')
139
+ end
140
+
141
+ def test_evaluate_add_string
142
+ assert_equal "foobar", evaluateText('(+ "foo" "bar")')
143
+ end
144
+
145
+ def test_evaluate_subtract
146
+ assert_equal -1, evaluateText('(- 1 2)')
147
+ assert_equal -4, evaluateText('(- 1 2 3)')
148
+ assert_equal 1, evaluateText('(- 1)')
149
+ end
150
+
151
+ def test_evaluate_multiply
152
+ assert_equal 2, evaluateText('(* 1 2)')
153
+ assert_equal 6, evaluateText('(* 1 2 3)')
154
+ assert_equal 1, evaluateText('(* 1)')
155
+ assert_equal 1, evaluateText('(*)')
156
+ end
157
+
158
+ def test_evaluate_divide
159
+ assert_equal 2, evaluateText('(/ 4 2)')
160
+ assert_equal 2, evaluateText('(/ 8 2 2)')
161
+ assert_equal 1, evaluateText('(/ 1)')
162
+ end
163
+
164
+ def test_evaluate_equal
165
+ assert evaluateText('(= 2 2)')
166
+ assert !evaluateText('(= 2 3)')
167
+ assert evaluateText('(= "foo" "foo")')
168
+ assert !evaluateText('(= "foo" "bar")')
169
+ end
170
+
171
+ def test_evaluate_less_than
172
+ assert evaluateText('(< 2 3)')
173
+ assert !evaluateText('(< 2 2)')
174
+ assert evaluateText('(< "bar" "foo")')
175
+ assert !evaluateText('(< "foo" "bar")')
176
+ end
177
+
178
+ def test_evaluate_greater_than
179
+ assert evaluateText('(> 4 3)')
180
+ assert !evaluateText('(> 2 2)')
181
+ assert evaluateText('(> "foo" "bar")')
182
+ assert !evaluateText('(> "bar" "foo")')
183
+ end
184
+
185
+ def test_evaluate_less_equal_than
186
+ assert evaluateText('(<= 2 3)')
187
+ assert evaluateText('(<= 2 2)')
188
+ assert !evaluateText('(<= 2 1)')
189
+ assert evaluateText('(<= "bar" "foo")')
190
+ assert evaluateText('(<= "bar" "bar")')
191
+ assert !evaluateText('(<= "foo" "bar")')
192
+ end
193
+
194
+ def test_evaluate_greater_equal_than
195
+ assert evaluateText('(>= 4 3)')
196
+ assert evaluateText('(>= 4 4)')
197
+ assert !evaluateText('(>= 1 2)')
198
+ assert evaluateText('(>= "foo" "bar")')
199
+ assert evaluateText('(>= "foo" "foo")')
200
+ assert !evaluateText('(>= "bar" "foo")')
201
+ end
202
+
203
+ def test_equal_on_atoms
204
+ assert evaluateText("(= 'a 'a)")
205
+ assert !evaluateText("(= 'a 'b)")
206
+ assert !evaluateText("(= 'a 1)")
207
+ assert !evaluateText("(= 1 'a)")
208
+ end
209
+
210
+ def test_equal_on_list
211
+ assert evaluateText("(= '(a b (c d)) '(a b (c d)))")
212
+ assert !evaluateText("(= '(a b (c d)) 'b)")
213
+ assert !evaluateText("(= '(a b (c d)) '(a b))")
214
+ assert !evaluateText("(= '(a b (c d)) 1)")
215
+ assert !evaluateText("(= 1 '(a b (c d)))")
216
+ end
217
+
218
+ def test_booleans
219
+ assert_equal true, evaluateText("true")
220
+ assert_equal false, evaluateText("false")
221
+ end
222
+
223
+ def test_nil_predicate
224
+ assert evaluateText("(nil? nil)")
225
+ assert !evaluateText("(nil? 0)")
226
+ assert !evaluateText("(nil? false)")
227
+ assert !evaluateText("(nil? true)")
228
+ assert !evaluateText("(nil? 'a)")
229
+ assert !evaluateText("(nil? '(a b))")
230
+ end
231
+
232
+ def test_atom_predicate
233
+ assert evaluateText("(atom? 'a)")
234
+ assert evaluateText("(atom? 1)")
235
+ assert evaluateText("(atom? true)")
236
+ assert evaluateText("(atom? false)")
237
+ assert evaluateText('(atom? "foo")')
238
+ assert !evaluateText("(atom? nil)")
239
+ assert !evaluateText("(atom? '())")
240
+ assert !evaluateText("(atom? '(a b))")
241
+ end
242
+
243
+ def test_get_empty_list
244
+ assert evaluateText("'()").is_a? EmptyList
245
+ end
246
+
247
+ def test_list_predicate
248
+ assert evaluateText("(list? '(a b))")
249
+ assert !evaluateText("(list? false)")
250
+ assert evaluateText("(list? '())")
251
+ assert !evaluateText("(list? true)")
252
+ assert !evaluateText("(list? nil)")
253
+ assert !evaluateText("(list? 1)")
254
+ assert !evaluateText("(list? 'a)")
255
+ end
256
+
257
+ def test_define_and_apply_append
258
+ evaluateText("(define append (x y) (if (nil? x) y (cons (first x) (append (rest x) y))))")
259
+ assert_equal "(1 2 3 4 5)", evaluateText("(append (list 1 2) (list 3 4 5))").to_s
260
+ assert_equal "(1 2)", evaluateText("(append (list 1 2) nil)").to_s
261
+ evaluateText("(define x '(b b))")
262
+ assert_equal "(b b)", evaluateText("(append x nil)").to_s
263
+ assert_equal "(b b b b)", evaluateText("(append x x)").to_s
264
+ end
265
+
266
+ def test_nil_to_s
267
+ assert_equal "nil", AjLisp::to_s(evaluateText("nil"))
268
+ end
269
+
270
+ def test_cons_nil_nil
271
+ assert_equal "(nil)", evaluateText("(cons nil nil)").to_s
272
+ end
273
+
274
+ def test_define_and_evaluate_mylist
275
+ evaluateText("(define mylist x x)")
276
+
277
+ assert_equal "(1 2 3)", evaluateText("(mylist 1 2 3)").to_s
278
+ end
279
+
280
+ def evaluateText(text)
281
+ source = StringSource.new text
282
+ lexer = Lexer.new source
283
+ parser = Parser.new lexer
284
+ expr = parser.parseExpression
285
+ return AjLisp::evaluate AjLisp::context, expr
286
+ end
287
+ end
288
+
289
+ end
@@ -0,0 +1,136 @@
1
+ require 'ajlisp'
2
+ require 'test/unit'
3
+
4
+ module AjLisp
5
+
6
+ class TestEvaluate < Test::Unit::TestCase
7
+ def test_evaluate_define123
8
+ result = evaluateFile("define123.lsp")
9
+
10
+ assert_equal 3, result
11
+ assert_equal 1, AjLisp::context.getValue(:one)
12
+ assert_equal 2, AjLisp::context.getValue(:two)
13
+ assert_equal 3, AjLisp::context.getValue(:three)
14
+ end
15
+
16
+ def test_evaluate_dodefine123
17
+ result = evaluateFile("dodefine123.lsp")
18
+
19
+ assert_equal 3, result
20
+ assert_equal 1, AjLisp::context.getValue(:one)
21
+ assert_equal 2, AjLisp::context.getValue(:two)
22
+ assert_equal 3, AjLisp::context.getValue(:three)
23
+ end
24
+
25
+ def test_evaluate_mycons
26
+ result = evaluateFile("mycons.lsp")
27
+
28
+ assert_not_nil result
29
+ assert result.is_a? List
30
+ assert_equal :a, result.first.name
31
+ assert_equal :b, result.rest.first.name
32
+ assert_nil result.rest.rest
33
+ end
34
+
35
+ def test_evaluate_append
36
+ evaluateFile("append.lsp")
37
+
38
+ assert_equal "(1 2 3 4 5)", evaluateText("(append (list 1 2) (list 3 4 5))").to_s
39
+ assert_equal "(1 2)", evaluateText("(append (list 1 2) nil)").to_s
40
+ evaluateText("(define x '(b b))")
41
+ assert_equal "(b b)", evaluateText("(append x nil)").to_s
42
+ assert_equal "(b b b b)", evaluateText("(append x x)").to_s
43
+ end
44
+
45
+ def test_evaluate_mapfirst
46
+ evaluateFile("mapfirst.lsp")
47
+
48
+ assert_equal "((1) (2) (3))", evaluateText("(mapfirst list (list 1 2 3))").to_s
49
+ assert_equal "(1 2 3)", evaluateText("(mapfirst first (quote ((1) (2) (3))))").to_s
50
+ end
51
+
52
+ def test_evaluate_mapcond
53
+ evaluateFile("mapcond.lsp")
54
+
55
+ assert_equal "((2))", evaluateText("(mapcond list? (list 1 (list 2) 3))").to_s
56
+ assert_equal "(nil)", evaluateText("(mapcond nil? (list 1 nil 3))").to_s
57
+ end
58
+
59
+ def test_evaluate_definem
60
+ evaluateFile("definem.lsp")
61
+
62
+ evaluateText("(definem myquote (x) (list 'quote x))")
63
+
64
+ assert_equal "x", evaluateText("(myquote x)").to_s
65
+ assert_equal "(1 2 3)", evaluateText("(myquote (1 2 3))").to_s
66
+
67
+ evaluateText("(definem myfirst (x) (list 'first x))")
68
+
69
+ assert_equal "a", evaluateText("(myfirst '(a b c))").to_s
70
+ end
71
+
72
+ def test_evaluate_cond
73
+ evaluateFile("cond.lsp")
74
+
75
+ assert_equal false, evaluateText("(cond)")
76
+ assert_equal false, evaluateText("(cond (nil 'a))")
77
+ assert_equal "a", evaluateText("(cond (true 'a))").to_s
78
+ assert_equal "b", evaluateText("(cond (nil 'a) (true 'b))").to_s
79
+ assert_equal "c", evaluateText("(cond (nil 'a) (true 'b 'c))").to_s
80
+ end
81
+
82
+ def test_evaluate_and
83
+ evaluateFile("cond.lsp")
84
+ evaluateFile("and.lsp")
85
+
86
+ assert_equal true, evaluateText("(and)")
87
+ assert_equal true, evaluateText("(and true)")
88
+ assert_equal false, evaluateText("(and true false)")
89
+ assert_equal false, evaluateText("(and false)")
90
+ end
91
+
92
+ def test_evaluate_backquote
93
+ evaluateFile("append.lsp")
94
+ evaluateFile("definem.lsp")
95
+ evaluateFile("cond.lsp")
96
+ evaluateFile("and.lsp")
97
+ evaluateFile("backquote.lsp")
98
+
99
+ assert_equal "(a b c)", evaluateText("(backquote (a b c))").to_s
100
+ assert_equal "(a (b c) d)", evaluateText("(backquote (a (b c) d))").to_s
101
+ evaluateText("(define x '(b b))")
102
+ assert_equal "(b b)", evaluateText("(backquote (unquote x))").to_s
103
+ assert_equal "((b b))", evaluateText("(backquote ((unquote x)))").to_s
104
+ assert_equal "(a (b b) c)", evaluateText("(backquote (a (unquote x) c))").to_s
105
+ assert_equal "(a ((b b)) c)", evaluateText("(backquote (a ((unquote x)) c))").to_s
106
+
107
+ assert_equal "(b b)", evaluateText("(backquote ((unquote-slice x)))").to_s
108
+ assert_equal "(a b b c)", evaluateText("(backquote (a (unquote-slice x) c))").to_s
109
+ end
110
+
111
+ def evaluateFile(filename)
112
+ source = FileSource.new File.expand_path(filename, File.dirname(__FILE__))
113
+ lexer = Lexer.new source
114
+ parser = Parser.new lexer
115
+ expr = parser.parseExpression
116
+
117
+ result = nil
118
+
119
+ while expr
120
+ result = AjLisp::evaluate AjLisp::context, expr
121
+ expr = parser.parseExpression
122
+ end
123
+
124
+ return result
125
+ end
126
+
127
+ def evaluateText(text)
128
+ source = StringSource.new text
129
+ lexer = Lexer.new source
130
+ parser = Parser.new lexer
131
+ expr = parser.parseExpression
132
+ return AjLisp::evaluate AjLisp::context, expr
133
+ end
134
+ end
135
+
136
+ end