AmberVM 0.0.19
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/README +38 -0
- data/bin/ambervm +278 -0
- data/lib/amber/acts_as_rvm_type.rb +157 -0
- data/lib/amber/classes/association.rb +36 -0
- data/lib/amber/classes/block.rb +52 -0
- data/lib/amber/classes/boolean.rb +40 -0
- data/lib/amber/classes/class.rb +50 -0
- data/lib/amber/classes/error.rb +22 -0
- data/lib/amber/classes/list.rb +96 -0
- data/lib/amber/classes/null.rb +35 -0
- data/lib/amber/classes/number.rb +95 -0
- data/lib/amber/classes/object.rb +56 -0
- data/lib/amber/classes/string.rb +79 -0
- data/lib/amber/classes.rb +113 -0
- data/lib/amber/environment.rb +251 -0
- data/lib/amber/fukubukuro/ecma_core.rb +409 -0
- data/lib/amber/fukubukuro.rb +866 -0
- data/lib/amber/functions/all.rb +3 -0
- data/lib/amber/functions/array/append.rb +50 -0
- data/lib/amber/functions/array/at.rb +50 -0
- data/lib/amber/functions/array/set_at.rb +50 -0
- data/lib/amber/functions/array.rb +30 -0
- data/lib/amber/functions/association/assoc_get.rb +55 -0
- data/lib/amber/functions/association/assoc_set.rb +56 -0
- data/lib/amber/functions/bitwise/bitwise_and.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_not.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_or.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_xor.rb +41 -0
- data/lib/amber/functions/bitwise.rb +3 -0
- data/lib/amber/functions/collection/get.rb +66 -0
- data/lib/amber/functions/collection/set.rb +67 -0
- data/lib/amber/functions/collection/size.rb +54 -0
- data/lib/amber/functions/general/cmp.rb +43 -0
- data/lib/amber/functions/general/eq.rb +45 -0
- data/lib/amber/functions/general/gt.rb +45 -0
- data/lib/amber/functions/general/gte.rb +45 -0
- data/lib/amber/functions/general/lt.rb +45 -0
- data/lib/amber/functions/general/lte.rb +45 -0
- data/lib/amber/functions/general/neq.rb +45 -0
- data/lib/amber/functions/general/type.rb +43 -0
- data/lib/amber/functions/general.rb +3 -0
- data/lib/amber/functions/io/print.rb +45 -0
- data/lib/amber/functions/io.rb +3 -0
- data/lib/amber/functions/list/align.rb +73 -0
- data/lib/amber/functions/list/join.rb +45 -0
- data/lib/amber/functions/list/map.rb +58 -0
- data/lib/amber/functions/list/split.rb +55 -0
- data/lib/amber/functions/list.rb +3 -0
- data/lib/amber/functions/logic/and.rb +55 -0
- data/lib/amber/functions/logic/not.rb +40 -0
- data/lib/amber/functions/logic/or.rb +50 -0
- data/lib/amber/functions/logic.rb +3 -0
- data/lib/amber/functions/math/abs.rb +39 -0
- data/lib/amber/functions/math/acos.rb +39 -0
- data/lib/amber/functions/math/add.rb +40 -0
- data/lib/amber/functions/math/asin.rb +39 -0
- data/lib/amber/functions/math/atan.rb +39 -0
- data/lib/amber/functions/math/ceil.rb +39 -0
- data/lib/amber/functions/math/cos.rb +39 -0
- data/lib/amber/functions/math/dec.rb +39 -0
- data/lib/amber/functions/math/div.rb +44 -0
- data/lib/amber/functions/math/exp.rb +39 -0
- data/lib/amber/functions/math/floor.rb +39 -0
- data/lib/amber/functions/math/inc.rb +39 -0
- data/lib/amber/functions/math/log.rb +39 -0
- data/lib/amber/functions/math/mod.rb +41 -0
- data/lib/amber/functions/math/mul.rb +43 -0
- data/lib/amber/functions/math/neg.rb +43 -0
- data/lib/amber/functions/math/power.rb +43 -0
- data/lib/amber/functions/math/rand.rb +36 -0
- data/lib/amber/functions/math/round.rb +39 -0
- data/lib/amber/functions/math/shl.rb +41 -0
- data/lib/amber/functions/math/shr.rb +41 -0
- data/lib/amber/functions/math/sin.rb +39 -0
- data/lib/amber/functions/math/sub.rb +43 -0
- data/lib/amber/functions/math/tan.rb +39 -0
- data/lib/amber/functions/math.rb +3 -0
- data/lib/amber/functions/objects/send.rb +22 -0
- data/lib/amber/functions/rails/print.rb +44 -0
- data/lib/amber/functions/rails.rb +3 -0
- data/lib/amber/functions/string/ansi.rb +24 -0
- data/lib/amber/functions/string/capstr.rb +23 -0
- data/lib/amber/functions/string/center.rb +25 -0
- data/lib/amber/functions/string/chr.rb +16 -0
- data/lib/amber/functions/string/ljust.rb +26 -0
- data/lib/amber/functions/string/regmatch.rb +34 -0
- data/lib/amber/functions/string/rjust.rb +26 -0
- data/lib/amber/functions/string.rb +3 -0
- data/lib/amber/functions.rb +103 -0
- data/lib/amber/interpreter.rb +1380 -0
- data/lib/amber/languages/brainfuck.rb +153 -0
- data/lib/amber/languages/ecma/compiler.rb +1661 -0
- data/lib/amber/languages/ecma/core-math.js +67 -0
- data/lib/amber/languages/ecma/core-objects.js +57 -0
- data/lib/amber/languages/ecma.rb +9 -0
- data/lib/amber/languages/ecma_fuku/compiler.rb +1622 -0
- data/lib/amber/languages/ecma_fuku/core-math.js +67 -0
- data/lib/amber/languages/ecma_fuku/core-objects.js +56 -0
- data/lib/amber/languages/ecma_fuku.rb +13 -0
- data/lib/amber/languages/math/compiler.rb +70 -0
- data/lib/amber/languages/math/tokenizer.rb +69 -0
- data/lib/amber/languages/math/tree.rb +110 -0
- data/lib/amber/languages/math.rb +26 -0
- data/lib/amber/languages.rb +99 -0
- data/lib/amber/library.rb +79 -0
- data/lib/amber/optimisation.rb +299 -0
- data/lib/amber/plugin.rb +337 -0
- data/lib/amber/rails.rb +90 -0
- data/lib/amber.rb +106 -0
- data/spec/amber/class_spec.rb +27 -0
- data/spec/amber/enviroment_spec.rb +61 -0
- data/spec/amber/function_spec.rb +25 -0
- data/spec/amber/functions/association/assoc_get_spec.rb +41 -0
- data/spec/amber/functions/association/assoc_set_spec.rb +43 -0
- data/spec/amber/functions/collection/get_spec.rb +12 -0
- data/spec/amber/functions/collection/set_spec.rb +10 -0
- data/spec/amber/functions/collection/size_spec.rb +10 -0
- data/spec/amber/functions/list/split_spec.rb +47 -0
- data/spec/amber/functions/string/ansi_spec.rb +44 -0
- data/spec/amber/functions/string/capstr_spec.rb +42 -0
- data/spec/amber/functions/string/center_spec.rb +49 -0
- data/spec/amber/functions/string/ljust_spec.rb +49 -0
- data/spec/amber/functions/string/regmatch_spec.rb +52 -0
- data/spec/amber/functions/string/rjust_spec.rb +49 -0
- data/spec/amber/interpreter/assignment_spec.rb +22 -0
- data/spec/amber/interpreter/condition_spec.rb +103 -0
- data/spec/amber/interpreter/constant_spec.rb +31 -0
- data/spec/amber/interpreter/core_call_spec.rb +72 -0
- data/spec/amber/interpreter/interpreter_spec.rb +11 -0
- data/spec/amber/interpreter/parameter_spec.rb +24 -0
- data/spec/amber/interpreter/sequence_spec.rb +47 -0
- data/spec/amber/interpreter/variable_spec.rb +24 -0
- data/spec/amber/plugin_spec.rb +10 -0
- data/spec/classes/atom/association_spec.rb +39 -0
- data/spec/classes/atom/block_spec.rb +25 -0
- data/spec/classes/atom/boolean_spec.rb +67 -0
- data/spec/classes/atom/error_spec.rb +43 -0
- data/spec/classes/atom/list_spec.rb +68 -0
- data/spec/classes/atom/number_spec.rb +132 -0
- data/spec/classes/atom/string_spec.rb +175 -0
- data/spec/languages/ecma/ecma_array_spec.rb +79 -0
- data/spec/languages/ecma/ecma_closure_spec.rb +38 -0
- data/spec/languages/ecma/ecma_literals_spec.rb +71 -0
- data/spec/languages/ecma/ecma_objects_spec.rb +165 -0
- data/spec/languages/ecma/ecma_old_spec.rb +540 -0
- data/spec/languages/ecma/ecma_spec.rb +64 -0
- data/spec/languages/ecma_fuku/ecma_array_spec.rb +61 -0
- data/spec/languages/ecma_fuku/ecma_closure_spec.rb +33 -0
- data/spec/languages/ecma_fuku/ecma_function_spec.rb +84 -0
- data/spec/languages/ecma_fuku/ecma_literals_spec.rb +55 -0
- data/spec/languages/ecma_fuku/ecma_objects_spec.rb +133 -0
- data/spec/languages/ecma_fuku/ecma_old_spec.rb +415 -0
- data/spec/languages/ecma_fuku/ecma_operator_spec.rb +33 -0
- data/spec/languages/ecma_fuku/ecma_spec.rb +52 -0
- data/spec/languages/math/compiler_spec.rb +49 -0
- data/spec/languages/math/tokenizer_spec.rb +73 -0
- data/spec/languages/math/tree_spec.rb +153 -0
- 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
|