AmberVM 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/README +38 -0
  2. data/bin/ambervm +278 -0
  3. data/lib/amber/acts_as_rvm_type.rb +157 -0
  4. data/lib/amber/classes/association.rb +36 -0
  5. data/lib/amber/classes/block.rb +52 -0
  6. data/lib/amber/classes/boolean.rb +40 -0
  7. data/lib/amber/classes/class.rb +50 -0
  8. data/lib/amber/classes/error.rb +22 -0
  9. data/lib/amber/classes/list.rb +96 -0
  10. data/lib/amber/classes/null.rb +35 -0
  11. data/lib/amber/classes/number.rb +95 -0
  12. data/lib/amber/classes/object.rb +56 -0
  13. data/lib/amber/classes/string.rb +79 -0
  14. data/lib/amber/classes.rb +113 -0
  15. data/lib/amber/environment.rb +251 -0
  16. data/lib/amber/fukubukuro/ecma_core.rb +409 -0
  17. data/lib/amber/fukubukuro.rb +866 -0
  18. data/lib/amber/functions/all.rb +3 -0
  19. data/lib/amber/functions/array/append.rb +50 -0
  20. data/lib/amber/functions/array/at.rb +50 -0
  21. data/lib/amber/functions/array/set_at.rb +50 -0
  22. data/lib/amber/functions/array.rb +30 -0
  23. data/lib/amber/functions/association/assoc_get.rb +55 -0
  24. data/lib/amber/functions/association/assoc_set.rb +56 -0
  25. data/lib/amber/functions/bitwise/bitwise_and.rb +41 -0
  26. data/lib/amber/functions/bitwise/bitwise_not.rb +41 -0
  27. data/lib/amber/functions/bitwise/bitwise_or.rb +41 -0
  28. data/lib/amber/functions/bitwise/bitwise_xor.rb +41 -0
  29. data/lib/amber/functions/bitwise.rb +3 -0
  30. data/lib/amber/functions/collection/get.rb +66 -0
  31. data/lib/amber/functions/collection/set.rb +67 -0
  32. data/lib/amber/functions/collection/size.rb +54 -0
  33. data/lib/amber/functions/general/cmp.rb +43 -0
  34. data/lib/amber/functions/general/eq.rb +45 -0
  35. data/lib/amber/functions/general/gt.rb +45 -0
  36. data/lib/amber/functions/general/gte.rb +45 -0
  37. data/lib/amber/functions/general/lt.rb +45 -0
  38. data/lib/amber/functions/general/lte.rb +45 -0
  39. data/lib/amber/functions/general/neq.rb +45 -0
  40. data/lib/amber/functions/general/type.rb +43 -0
  41. data/lib/amber/functions/general.rb +3 -0
  42. data/lib/amber/functions/io/print.rb +45 -0
  43. data/lib/amber/functions/io.rb +3 -0
  44. data/lib/amber/functions/list/align.rb +73 -0
  45. data/lib/amber/functions/list/join.rb +45 -0
  46. data/lib/amber/functions/list/map.rb +58 -0
  47. data/lib/amber/functions/list/split.rb +55 -0
  48. data/lib/amber/functions/list.rb +3 -0
  49. data/lib/amber/functions/logic/and.rb +55 -0
  50. data/lib/amber/functions/logic/not.rb +40 -0
  51. data/lib/amber/functions/logic/or.rb +50 -0
  52. data/lib/amber/functions/logic.rb +3 -0
  53. data/lib/amber/functions/math/abs.rb +39 -0
  54. data/lib/amber/functions/math/acos.rb +39 -0
  55. data/lib/amber/functions/math/add.rb +40 -0
  56. data/lib/amber/functions/math/asin.rb +39 -0
  57. data/lib/amber/functions/math/atan.rb +39 -0
  58. data/lib/amber/functions/math/ceil.rb +39 -0
  59. data/lib/amber/functions/math/cos.rb +39 -0
  60. data/lib/amber/functions/math/dec.rb +39 -0
  61. data/lib/amber/functions/math/div.rb +44 -0
  62. data/lib/amber/functions/math/exp.rb +39 -0
  63. data/lib/amber/functions/math/floor.rb +39 -0
  64. data/lib/amber/functions/math/inc.rb +39 -0
  65. data/lib/amber/functions/math/log.rb +39 -0
  66. data/lib/amber/functions/math/mod.rb +41 -0
  67. data/lib/amber/functions/math/mul.rb +43 -0
  68. data/lib/amber/functions/math/neg.rb +43 -0
  69. data/lib/amber/functions/math/power.rb +43 -0
  70. data/lib/amber/functions/math/rand.rb +36 -0
  71. data/lib/amber/functions/math/round.rb +39 -0
  72. data/lib/amber/functions/math/shl.rb +41 -0
  73. data/lib/amber/functions/math/shr.rb +41 -0
  74. data/lib/amber/functions/math/sin.rb +39 -0
  75. data/lib/amber/functions/math/sub.rb +43 -0
  76. data/lib/amber/functions/math/tan.rb +39 -0
  77. data/lib/amber/functions/math.rb +3 -0
  78. data/lib/amber/functions/objects/send.rb +22 -0
  79. data/lib/amber/functions/rails/print.rb +44 -0
  80. data/lib/amber/functions/rails.rb +3 -0
  81. data/lib/amber/functions/string/ansi.rb +24 -0
  82. data/lib/amber/functions/string/capstr.rb +23 -0
  83. data/lib/amber/functions/string/center.rb +25 -0
  84. data/lib/amber/functions/string/chr.rb +16 -0
  85. data/lib/amber/functions/string/ljust.rb +26 -0
  86. data/lib/amber/functions/string/regmatch.rb +34 -0
  87. data/lib/amber/functions/string/rjust.rb +26 -0
  88. data/lib/amber/functions/string.rb +3 -0
  89. data/lib/amber/functions.rb +103 -0
  90. data/lib/amber/interpreter.rb +1380 -0
  91. data/lib/amber/languages/brainfuck.rb +153 -0
  92. data/lib/amber/languages/ecma/compiler.rb +1661 -0
  93. data/lib/amber/languages/ecma/core-math.js +67 -0
  94. data/lib/amber/languages/ecma/core-objects.js +57 -0
  95. data/lib/amber/languages/ecma.rb +9 -0
  96. data/lib/amber/languages/ecma_fuku/compiler.rb +1622 -0
  97. data/lib/amber/languages/ecma_fuku/core-math.js +67 -0
  98. data/lib/amber/languages/ecma_fuku/core-objects.js +56 -0
  99. data/lib/amber/languages/ecma_fuku.rb +13 -0
  100. data/lib/amber/languages/math/compiler.rb +70 -0
  101. data/lib/amber/languages/math/tokenizer.rb +69 -0
  102. data/lib/amber/languages/math/tree.rb +110 -0
  103. data/lib/amber/languages/math.rb +26 -0
  104. data/lib/amber/languages.rb +99 -0
  105. data/lib/amber/library.rb +79 -0
  106. data/lib/amber/optimisation.rb +299 -0
  107. data/lib/amber/plugin.rb +337 -0
  108. data/lib/amber/rails.rb +90 -0
  109. data/lib/amber.rb +106 -0
  110. data/spec/amber/class_spec.rb +27 -0
  111. data/spec/amber/enviroment_spec.rb +61 -0
  112. data/spec/amber/function_spec.rb +25 -0
  113. data/spec/amber/functions/association/assoc_get_spec.rb +41 -0
  114. data/spec/amber/functions/association/assoc_set_spec.rb +43 -0
  115. data/spec/amber/functions/collection/get_spec.rb +12 -0
  116. data/spec/amber/functions/collection/set_spec.rb +10 -0
  117. data/spec/amber/functions/collection/size_spec.rb +10 -0
  118. data/spec/amber/functions/list/split_spec.rb +47 -0
  119. data/spec/amber/functions/string/ansi_spec.rb +44 -0
  120. data/spec/amber/functions/string/capstr_spec.rb +42 -0
  121. data/spec/amber/functions/string/center_spec.rb +49 -0
  122. data/spec/amber/functions/string/ljust_spec.rb +49 -0
  123. data/spec/amber/functions/string/regmatch_spec.rb +52 -0
  124. data/spec/amber/functions/string/rjust_spec.rb +49 -0
  125. data/spec/amber/interpreter/assignment_spec.rb +22 -0
  126. data/spec/amber/interpreter/condition_spec.rb +103 -0
  127. data/spec/amber/interpreter/constant_spec.rb +31 -0
  128. data/spec/amber/interpreter/core_call_spec.rb +72 -0
  129. data/spec/amber/interpreter/interpreter_spec.rb +11 -0
  130. data/spec/amber/interpreter/parameter_spec.rb +24 -0
  131. data/spec/amber/interpreter/sequence_spec.rb +47 -0
  132. data/spec/amber/interpreter/variable_spec.rb +24 -0
  133. data/spec/amber/plugin_spec.rb +10 -0
  134. data/spec/classes/atom/association_spec.rb +39 -0
  135. data/spec/classes/atom/block_spec.rb +25 -0
  136. data/spec/classes/atom/boolean_spec.rb +67 -0
  137. data/spec/classes/atom/error_spec.rb +43 -0
  138. data/spec/classes/atom/list_spec.rb +68 -0
  139. data/spec/classes/atom/number_spec.rb +132 -0
  140. data/spec/classes/atom/string_spec.rb +175 -0
  141. data/spec/languages/ecma/ecma_array_spec.rb +79 -0
  142. data/spec/languages/ecma/ecma_closure_spec.rb +38 -0
  143. data/spec/languages/ecma/ecma_literals_spec.rb +71 -0
  144. data/spec/languages/ecma/ecma_objects_spec.rb +165 -0
  145. data/spec/languages/ecma/ecma_old_spec.rb +540 -0
  146. data/spec/languages/ecma/ecma_spec.rb +64 -0
  147. data/spec/languages/ecma_fuku/ecma_array_spec.rb +61 -0
  148. data/spec/languages/ecma_fuku/ecma_closure_spec.rb +33 -0
  149. data/spec/languages/ecma_fuku/ecma_function_spec.rb +84 -0
  150. data/spec/languages/ecma_fuku/ecma_literals_spec.rb +55 -0
  151. data/spec/languages/ecma_fuku/ecma_objects_spec.rb +133 -0
  152. data/spec/languages/ecma_fuku/ecma_old_spec.rb +415 -0
  153. data/spec/languages/ecma_fuku/ecma_operator_spec.rb +33 -0
  154. data/spec/languages/ecma_fuku/ecma_spec.rb +52 -0
  155. data/spec/languages/math/compiler_spec.rb +49 -0
  156. data/spec/languages/math/tokenizer_spec.rb +73 -0
  157. data/spec/languages/math/tree_spec.rb +153 -0
  158. metadata +225 -0
@@ -0,0 +1,415 @@
1
+ $: << 'lib'
2
+ require 'amber'
3
+ require 'amber/languages'
4
+ require 'amber/languages/ecma_fuku'
5
+
6
+ describe AmberVM::Languages::ECMA_Fuku do
7
+ before(:each) do
8
+ @compiler = AmberVM::Languages::ECMA_Fuku.new
9
+ @env = {}
10
+ end
11
+
12
+ def run code
13
+ @compiler.compile(code).execute(@env)
14
+ end
15
+
16
+ describe "literals" do
17
+ describe "strings" do
18
+ it "should handle string literals" do
19
+ res = run <<-EOC
20
+ "Hallo!"
21
+ EOC
22
+ res.should == "Hallo!"
23
+ end
24
+
25
+ it "should handle newline replacements" do
26
+ res = run '"\n"'
27
+ res.should == "\n"
28
+ end
29
+
30
+ it "should handle newline replacements" do
31
+ res = run <<-'EOC'
32
+ "\t"
33
+ EOC
34
+ res.should == "\t"
35
+ end
36
+ it "should handle newline replacements" do
37
+ res = run <<-'EOC'
38
+ "\n"
39
+ EOC
40
+ res.should == "\n"
41
+ end
42
+
43
+ it "should handle double escapes" do
44
+ res = run <<-'EOC'
45
+ "\\t"
46
+ EOC
47
+ res.should == "\\t"
48
+ end
49
+
50
+ it "should handle double escapes followed by single escapes" do
51
+ res = run <<-'EOF'
52
+ "\\\t"
53
+ EOF
54
+ res.should == "\\\t"
55
+ end
56
+ end
57
+
58
+ it "should handle number literals" do
59
+ res = run <<-EOC
60
+ 42
61
+ EOC
62
+ res.should == 42
63
+ end
64
+
65
+ describe "array" do
66
+ it "should handle array literals with no elements" do
67
+ res = run <<-EOC
68
+ []
69
+ EOC
70
+ res.should == []
71
+ end
72
+
73
+ it "should handle array literals with one element" do
74
+ res = run <<-EOC
75
+ ["Kekse!"]
76
+ EOC
77
+ res.should == ["Kekse!"]
78
+ end
79
+
80
+ it "should handle array literals with arrays in it" do
81
+ res = run <<-EOC
82
+ [["Kekse!",2],1]
83
+ EOC
84
+ res.should == [["Kekse!",2],1]
85
+ end
86
+
87
+ it "should handle array literals with multiple elements" do
88
+ res = run <<-EOC
89
+ [42, "Kekse!"]
90
+ EOC
91
+ res.should == [42, "Kekse!"]
92
+ end
93
+
94
+ it "should allow to set array elements" do
95
+ res = run <<-EOC
96
+ array = [];
97
+ array[0] = 42;
98
+ array;
99
+ EOC
100
+ res.should == [42]
101
+ end
102
+ end
103
+
104
+ describe "Objects array" do
105
+ it "should handle an empty object" do
106
+ res = run <<-EOC
107
+ a = {}
108
+ EOC
109
+ @env['a'].should be_instance_of(OpenStruct)
110
+ end
111
+
112
+ it "should handle an object with variables" do
113
+ res = run <<-EOC
114
+ {a: 1}
115
+ EOC
116
+ res.should be_instance_of(OpenStruct)
117
+ res.a.should == 1
118
+ end
119
+ it "should handle an object with functions" do
120
+ res = run <<-EOC
121
+ {f: function(){1;}}
122
+ EOC
123
+ res.should be_instance_of(OpenStruct)
124
+ res.f.should be
125
+ res.f.call.should == :undefined
126
+ end
127
+ end
128
+
129
+ it "should handle true literals" do
130
+ res = run <<-EOC
131
+ true
132
+ EOC
133
+ res.should be_true
134
+ end
135
+
136
+ it "should handle false literals" do
137
+ res = run <<-EOC
138
+ false
139
+ EOC
140
+ res.should_not be_true
141
+ end
142
+ end
143
+
144
+ describe "array" do
145
+ it "should allow accessing elements" do
146
+ @env['a'] = [1,2,3]
147
+ res = run <<-EOC
148
+ a[0]
149
+ EOC
150
+ res.should == 1
151
+ end
152
+
153
+ it "should allow setting elements" do
154
+ @env['a'] = [1,2,3]
155
+ res = run <<-EOC
156
+ a[0] = 42;
157
+ EOC
158
+ res.should == 42
159
+ @env['a'][0].should == 42
160
+ end
161
+ it "should allow accessing the length" do
162
+ @env['a'] = [1,2,3]
163
+ res = run <<-EOC
164
+ a.length
165
+ EOC
166
+ res.should == 3
167
+ end
168
+ end
169
+
170
+ describe "variables" do
171
+ it "should recognize simple assignments" do
172
+ res = run <<-EOC
173
+ variable = 'value';
174
+ EOC
175
+ res.should == 'value'
176
+ @env['variable'].should == 'value'
177
+ end
178
+
179
+ it "should recognize local assignments" do
180
+ res = run <<-EOC
181
+ var variable = 'value';
182
+ EOC
183
+ res.should == 'value'
184
+ @env['variable'].should == 'value'
185
+ end
186
+
187
+ it "should recognize multiple local assignments" do
188
+ res = run <<-EOC
189
+ var i = 'a', j = 'b';
190
+ EOC
191
+ res.should == 'b'
192
+ @env['i'].should == 'a'
193
+ @env['j'].should == 'b'
194
+ end
195
+
196
+ it "should scope global assignments correctly" do
197
+ res = run <<-EOC
198
+ variable = 'outer scope';
199
+ {
200
+ var variable = 'inner scope';
201
+ }
202
+ EOC
203
+ res.should == 'inner scope'
204
+ @env['variable'].should == 'inner scope'
205
+ end
206
+ end
207
+
208
+ describe "conditions" do
209
+ describe "true condition" do
210
+ describe "without blocks" do
211
+
212
+ it "should handle loops without else" do
213
+ res = run <<-EOC
214
+ if (true)
215
+ 42
216
+ EOC
217
+ res.should == 42
218
+ end
219
+
220
+ it "should handle loops with else" do
221
+ res = run <<-EOC
222
+ if (true)
223
+ 42;
224
+ else
225
+ 23
226
+ EOC
227
+ res.should == 42
228
+ end
229
+
230
+ it "should handle loops with else and ugly ';'" do
231
+ res = run <<-EOC
232
+ if (true)
233
+ 42;
234
+ else
235
+ 23
236
+ EOC
237
+ res.should == 42
238
+ end
239
+ end
240
+
241
+ describe "with blocks" do
242
+ it "should handle condition without else" do
243
+ res = run <<-EOC
244
+ if (true) {
245
+ 42;
246
+ }
247
+ EOC
248
+ res.should == 42
249
+ end
250
+ it "should handle condition with else" do
251
+ res = run <<-EOC
252
+ if (true) {
253
+ 42;
254
+ } else {
255
+ 23;
256
+ }
257
+ EOC
258
+ res.should == 42
259
+ end
260
+ end
261
+ end
262
+ describe "false condition" do
263
+ describe "without blocks" do
264
+ it "should handle condition without else" do
265
+ res = run <<-EOC
266
+ if (false)
267
+ 42;
268
+ EOC
269
+ res.should == nil
270
+ end
271
+ it "should handle condition with else" do
272
+ res = run <<-EOC
273
+ if (false)
274
+ 42;
275
+ else
276
+ 23;
277
+ EOC
278
+ res.should == 23
279
+ end
280
+ end
281
+ describe "with blocks" do
282
+ it "should handle condition without else" do
283
+ res = run <<-EOC
284
+ if (false) {
285
+ 42;
286
+ }
287
+ EOC
288
+ res.should be_nil
289
+ end
290
+ it "should handle condition with else" do
291
+ res = run <<-EOC
292
+ if (false) {
293
+ 42;
294
+ } else {
295
+ 23;
296
+ }
297
+ EOC
298
+ res.should == 23
299
+ end
300
+ end
301
+ end
302
+ end
303
+
304
+ describe "loops" do
305
+ it "should handle for loops" do
306
+ res = run <<-EOC
307
+ variable = "";
308
+ for (i = 0; i <= 3; i = i + 1) {
309
+ variable = variable + i;
310
+ }
311
+ EOC
312
+ @env['variable'].should == '0123'
313
+ end
314
+
315
+ it "should handle for loops (bug prevention)" do
316
+ code = <<-EOC
317
+ function test() {for (var i = 1; i <= 2; i+=1) {};};
318
+ test();
319
+ EOC
320
+ proc { run(code) }.should_not raise_error
321
+ end
322
+
323
+ it "should handle while loops" do
324
+ res = run <<-EOC
325
+ variable = "";
326
+ i = 0;
327
+ while (i < 3) {
328
+ i = i + 1;
329
+ variable = variable + i;
330
+ }
331
+ EOC
332
+ @env['variable'].should == '123'
333
+ end
334
+
335
+ it "should handle do while loops" do
336
+ res = run <<-EOC
337
+ variable = "";
338
+ i = 0;
339
+ do {
340
+ i = i + 1;
341
+ variable = variable + i;
342
+ } while (i < 3)
343
+ EOC
344
+ @env['variable'].should == '123'
345
+ end
346
+ end
347
+ it "should execute do while loops at least once" do
348
+ res = run <<-EOC
349
+ variable = "";
350
+ i = 0;
351
+ do {
352
+ i = i + 1;
353
+ variable = variable + i;
354
+ } while (i < 0)
355
+ EOC
356
+ res.should be_nil
357
+ @env['variable'].should == '1'
358
+ end
359
+
360
+ describe "objects" do
361
+ it "should handle object variables" do
362
+ obj = mock('object mock')
363
+ obj.should_receive(:test).with(no_args).and_return('ok')
364
+ @env['obj'] = obj
365
+ res = run <<-EOC
366
+ obj.test;
367
+ EOC
368
+ res.should == 'ok'
369
+ end
370
+
371
+ it "should handle object functions" do
372
+ obj = mock('object mock')
373
+ function = mock('function mock')
374
+ obj.should_receive(:test).with(no_args).and_return(function)
375
+ function.should_receive(:call).once.with(no_args).and_return('ok')
376
+ @env['obj'] = obj
377
+ res = run <<-EOC
378
+ obj.test();
379
+ EOC
380
+ res.should == 'ok'
381
+ end
382
+ end
383
+
384
+
385
+ describe "opperators" do
386
+ it "should recognize ++" do
387
+ @env['i'] = 41
388
+ res = run <<-EOC
389
+ i++;
390
+ EOC
391
+ res.should == 41
392
+ end
393
+ it "should recognize --" do
394
+ @env['i'] = 43
395
+ res = run <<-EOC
396
+ i--;
397
+ EOC
398
+ res.should == 43
399
+ end
400
+ it "should recognize +=" do
401
+ @env['i'] = 40
402
+ res = run <<-EOC
403
+ i += 2;
404
+ EOC
405
+ res.should == 42
406
+ end
407
+ it "should recognize -=" do
408
+ @env['i'] = 44
409
+ res = run <<-EOC
410
+ i -= 2;
411
+ EOC
412
+ res.should == 42
413
+ end
414
+ end
415
+ end
@@ -0,0 +1,33 @@
1
+ $: << 'lib'
2
+ require 'amber'
3
+ require 'amber/languages'
4
+ require 'amber/languages/ecma_fuku'
5
+
6
+ describe AmberVM::Languages::ECMA_Fuku do
7
+ before(:each) do
8
+ @env = {}
9
+ @compiler = AmberVM::Languages::ECMA_Fuku.new
10
+ end
11
+
12
+ def run code
13
+ @compiler.compile(code).execute(@env)
14
+ end
15
+
16
+ describe "arithmetic" do
17
+ it "should handle >>>" do
18
+ result = run <<-CODE
19
+ -1766 >>> 12
20
+ CODE
21
+ result.should == 1048575
22
+ end
23
+ it "should handle >>>=" do
24
+ result = run <<-CODE
25
+ a = -8345;
26
+ a >>>= 4;
27
+ a
28
+ CODE
29
+ result.should == 268434934
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,52 @@
1
+ $: << 'lib'
2
+ require 'amber'
3
+ require 'amber/languages'
4
+ require 'amber/languages/ecma_fuku'
5
+
6
+ describe AmberVM::Languages::ECMA_Fuku do
7
+ before(:each) do
8
+ @env = {}
9
+ @compiler = AmberVM::Languages::ECMA_Fuku.new
10
+ end
11
+
12
+ def run code
13
+ @compiler.compile(code).execute(@env)
14
+ end
15
+
16
+ describe "variables" do
17
+ it "should get variables" do
18
+ @env['test'] = 42
19
+ result = run <<-CODE
20
+ test
21
+ CODE
22
+ result.should == 42
23
+ end
24
+
25
+ it "should allow to assign literals to variables" do
26
+ result = run <<-CODE
27
+ test = 23
28
+ CODE
29
+ result.should == 23
30
+ @env['test'].should == 23
31
+ end
32
+
33
+ it "should autocast strings when using <var>++" do
34
+ result = run <<-CODE
35
+ test = '1.2';
36
+ test++
37
+ CODE
38
+ result.should == 1.2
39
+ @env['test'].should == 2.2
40
+ end
41
+ end
42
+
43
+ describe '+ operator' do
44
+ it 'should behave like ECMA' do
45
+ result = run <<-CODE
46
+ 1 + "3"
47
+ CODE
48
+ result.should == "13"
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,49 @@
1
+ require 'amber/interpreter'
2
+ require 'amber/classes/number'
3
+ require 'amber/languages/math/compiler'
4
+ describe AmberVM::Languages::Math::Compiler do
5
+ before do
6
+ @c = AmberVM::Languages::Math::Compiler
7
+ end
8
+
9
+ it "should compile numbers to constants" do
10
+ @c.compile({:type=>:number, :number=>"5"}).should be_instance_of(AmberVM::Interpreter::Constant);
11
+ end
12
+
13
+ it "should ignore arrays" do
14
+ @c.compile([{:type=>:number, :number=>"5"}]).should be_instance_of(AmberVM::Interpreter::Constant);
15
+ end
16
+
17
+ it "should compile it ident to variables" do
18
+ @c.compile({:type => :ident, :ident => "x"}).should be_instance_of(AmberVM::Interpreter::Variable);
19
+ end
20
+
21
+ it "should compile functions" do
22
+ @c.compile({:type => :function, :op => "x", :params => []}).should be_instance_of(AmberVM::Interpreter::FunctionCall);
23
+ @c.compile({:type => :function, :op => "-", :params => []}).should be_instance_of(AmberVM::Interpreter::CoreCall);
24
+ end
25
+
26
+ it "should compile mathematical ooperators to function calls" do
27
+ @c.compile({:type => :op, :op => "+", :left => {:type=>:number, :number=>"5"}, :right => {:type=>:number, :number=>"5"}}).should be_instance_of(AmberVM::Interpreter::CoreCall);
28
+ end
29
+
30
+ it "should compile = operators to assignments if left side is a ident" do
31
+ @c.compile({:type => :op, :op => "=", :left => {:type => :ident, :ident=>"x"}, :right => {:type=>:number, :number=>"5"}}).should be_instance_of(AmberVM::Interpreter::Assignment);
32
+ end
33
+
34
+ it "should compile = operators to function declaratins if left side is a function" do
35
+ @c.compile({:type => :op, :op => "=", :left => {:type => :function, :op => "x", :params => []}, :right => {:type=>:number, :number=>"5"}}).should be_instance_of(AmberVM::Interpreter::FunctionDefinition);
36
+ @c.compile({:type => :op, :op => "=", :left => {:type => :function, :op => "x", :params => [{:type => :ident, :ident=>"x"}]}, :right => {:type=>:number, :number=>"5"}}).should be_instance_of(AmberVM::Interpreter::FunctionDefinition);
37
+ end
38
+
39
+ it "should raise an error of the = operators is used with a number on the left" do
40
+ lambda {
41
+ @c.compile({:type => :op, :op => "=", :left => {:type => :number, :ident=>"5"}, :right => {:type=>:number, :number=>"5"}})
42
+ }.should raise_error
43
+ end
44
+
45
+ it "should compile ; to sepperators of sequences" do
46
+ @c.compile({:type => :op, :op => ";", :left => {:type => :ident, :ident=>"x"}, :right => {:type=>:number, :number=>"5"}}).should be_instance_of(AmberVM::Interpreter::Sequence);
47
+ @c.compile({:type => :op, :op => ";", :left => {:type => :op, :op => ";", :left => {:type => :ident, :ident=>"x"}, :right => {:type=>:number, :number=>"5"}}, :right => {:type => :op, :op => ";", :left => {:type => :ident, :ident=>"x"}, :right => {:type=>:number, :number=>"5"}}}).should be_instance_of(AmberVM::Interpreter::Sequence);
48
+ end
49
+ end
@@ -0,0 +1,73 @@
1
+ require 'amber/languages/math/tokenizer'
2
+ describe AmberVM::Languages::Math::Tokenizer do
3
+ before do
4
+ @t = AmberVM::Languages::Math::Tokenizer
5
+ end
6
+
7
+ it "should tokenize numbers in it's forms" do
8
+ @t.tokenize("5").should == [['5', :number]]
9
+ @t.tokenize("42").should == [['42', :number]]
10
+ @t.tokenize("4.2").should == [['4.2', :number]]
11
+ @t.tokenize(".2").should == [['.2', :number]]
12
+ @t.tokenize("4.2e10").should == [['4.2e10', :number]]
13
+ @t.tokenize("4.2e-10").should == [['4.2e-10', :number]]
14
+ end
15
+
16
+ it "should tokenize idents" do
17
+ @t.tokenize("x").should == [['x', :ident]]
18
+ @t.tokenize("xy").should == [['xy', :ident]]
19
+ @t.tokenize("x42").should == [['x42', :ident]]
20
+ @t.tokenize("_x").should == [['_x', :ident]]
21
+ @t.tokenize("_x_").should == [['_x_', :ident]]
22
+ @t.tokenize("really_freaking_long_IdentWithA11KindOfOddStuff").should == [['really_freaking_long_IdentWithA11KindOfOddStuff', :ident]]
23
+ end
24
+
25
+ it "should ignore spaces between tokens" do
26
+ @t.tokenize("23 + 19").should == [['23', :number],['+', :opperator],['19', :number]]
27
+ end
28
+
29
+ it "should recognize mathematical opperators (+,-,*,/,^)" do
30
+ @t.tokenize("23+19").should == [['23', :number], ['+', :opperator], ['19', :number]]
31
+ @t.tokenize("43-1").should == [['43', :number], ['-', :opperator], ['1', :number]]
32
+ @t.tokenize("21*2").should == [['21', :number], ['*', :opperator], ['2', :number]]
33
+ @t.tokenize("84/2").should == [['84', :number], ['/', :opperator], ['2', :number]]
34
+ end
35
+
36
+ it "recognizes unary - and ü" do
37
+ @t.tokenize("+5").should == [['5', :number]]
38
+ @t.tokenize("++5").should == [['5', :number]]
39
+ @t.tokenize("-5").should == [['-', :function], ['5', :number]]
40
+ @t.tokenize("- 5").should == [['-', :function], ['5', :number]]
41
+ @t.tokenize("- - 5").should == [['-', :function], ['-', :function], ['5', :number]]
42
+ @t.tokenize("3 + - - 5").should == [['3', :number], ['+', :opperator], ['-', :function], ['-', :function], ['5', :number]]
43
+ end
44
+
45
+ it "should recognize functions" do
46
+ @t.tokenize("f(x)").should == [['f', :function], ['x', :ident], [')', :paren_close]]
47
+ @t.tokenize("f(x, y)").should == [['f', :function], ['x', :ident], [',', :function_sep], ['y', :ident], [')', :paren_close]]
48
+ @t.tokenize("f()").should == [['f', :function], [")", :paren_close]]
49
+ end
50
+
51
+ it "should recognize parentheethes" do
52
+ @t.tokenize("(42)").should == [["(", :paren_open], ["42", :number], [")", :paren_close]]
53
+ @t.tokenize("(f(x))").should == [["(", :paren_open], ['f', :function], ['x', :ident], [')', :paren_close], [")", :paren_close]]
54
+ @t.tokenize("(19+23)").should == [["(", :paren_open], ['19', :number], ['+', :opperator], ['23', :number], [")", :paren_close]]
55
+ end
56
+
57
+ it "should recognize semicolons" do
58
+ @t.tokenize("42;42").should == [["42", :number], [";", :opperator], ["42", :number]]
59
+ end
60
+
61
+ it "should not alow semicolons within brackets" do
62
+ lambda{@t.tokenize("(42;42)")}.should raise_error
63
+ end
64
+
65
+ it "should throw exeptions on unknown literals where numbers are expected" do
66
+ lambda{@t.tokenize("42that_is_not_valid!")}.should raise_error
67
+ end
68
+
69
+ it "should throw exeptions on unknown literals" do
70
+ lambda{@t.tokenize("42that_is_not_valid!")}.should raise_error
71
+ lambda{@t.tokenize("?")}.should raise_error
72
+ end
73
+ end