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.
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,866 @@
1
+ # Define true? and false? methods on Ruby classes that behaves like JavaScript's truthyness.
2
+ class Object
3
+ def false?; false; end
4
+ def true?; !false?; end
5
+ end
6
+ class TrueClass
7
+ def true?; true; end
8
+ def false?; false; end
9
+ end
10
+ class Symbol
11
+ def false?; self == :undefined; end
12
+ end
13
+ [FalseClass, NilClass].each do |klass|
14
+ klass.class_eval do
15
+ def false?; true; end
16
+ def true?; false; end
17
+ end
18
+ end
19
+ [Fixnum, Bignum, Float].each do |klass|
20
+ klass.class_eval do
21
+ alias false? zero?
22
+ end
23
+ end
24
+ [Array, Hash, String].each do |klass|
25
+ klass.class_eval do
26
+ alias false? empty?
27
+ end
28
+ end
29
+
30
+ class Numeric
31
+ def inc; self + 1; end
32
+ def dec; self - 1; end
33
+ end
34
+
35
+ class Integer
36
+ def logical_shift_right positions = 1, bit_size = 32
37
+ raise ArgumentError, 'negative argument for logical_shift_right' if positions < 0
38
+ positions = positions.to_i if positions.is_a? Float
39
+ positions = bit_size if positions > bit_size
40
+ bits = (0...bit_size).map { |i| self[i] }.reverse
41
+ bits = [0] * positions + bits[0, bit_size - positions]
42
+ bits.join.to_i(2)
43
+ end
44
+ alias lsr logical_shift_right
45
+ end
46
+ class Float
47
+ def logical_shift_right positions = 1, bit_size = 32
48
+ (to_i % 2 ** bit_size).logical_shift_right positions, bit_size
49
+ end
50
+ alias lsr logical_shift_right
51
+ end
52
+
53
+ # automatic type cast for JavaScript
54
+ class Float
55
+ def to_str
56
+ to_s.chomp('.0')
57
+ end
58
+ end
59
+
60
+ unless defined? define_singleton_method()
61
+ module Kernel
62
+ def define_singleton_method name, &block
63
+ (class << self; self; end).send :define_method, name, &block
64
+ end
65
+ end
66
+ end
67
+
68
+ module Fukubukuro
69
+
70
+ module VM
71
+ class << self
72
+ def print *args
73
+ $stdout.print(*args)
74
+ end
75
+ def new_array
76
+ []
77
+ end
78
+ def sin a
79
+ Math.sin a
80
+ end
81
+ def cos a
82
+ Math.cos a
83
+ end
84
+ def power base, exp
85
+ base ** exp
86
+ end
87
+ end
88
+ end
89
+
90
+ class Sequence < Array
91
+ def call
92
+ for statement in self
93
+ value = statement.call
94
+ end
95
+ value
96
+ end
97
+ alias value call
98
+ def inspect
99
+ self.class.inspect + super
100
+ end
101
+ def pretty_print q
102
+ q.text self.class.inspect
103
+ super
104
+ end
105
+ def self.inspect
106
+ 'Sequence'
107
+ end
108
+ end
109
+
110
+ class Environment < Hash
111
+ def self.new
112
+ super do |h, k|
113
+ h[k] = Variable.new
114
+ end
115
+ end
116
+ end
117
+
118
+ class Program < Sequence
119
+ attr_accessor :environment
120
+ def initialize statements = Sequence[], environment = Environment.new
121
+ super(statements)
122
+ self.environment = environment
123
+ end
124
+ def self.inspect
125
+ 'Program'
126
+ end
127
+ def ruby_to_amber object
128
+ raise NotImplementedError
129
+ end
130
+ def amber_to_ruby container
131
+ if container.respond_to? :to_ruby
132
+ container.to_ruby
133
+ else
134
+ container
135
+ end
136
+ end
137
+ def execute env
138
+ if env.is_a? Hash
139
+ for name in env.keys
140
+ environment[name.to_sym].value = ruby_to_amber env[name]
141
+ end
142
+ else
143
+ raise 'Expected Hash as environment, got %p' % [env]
144
+ end
145
+ result = call
146
+ if env.is_a? Hash
147
+ for name, variable in environment
148
+ env[name] = env[name.to_s] = amber_to_ruby(variable.value)
149
+ end
150
+ end
151
+ amber_to_ruby result
152
+ end
153
+ def optimize
154
+ self
155
+ end
156
+ end
157
+
158
+ class Statement < Proc
159
+ alias value call
160
+ end
161
+
162
+ # class MathStatement < Statement
163
+ # def self.new method, *args
164
+ # if args.size == 1
165
+ # arg = args.first
166
+ # super() do
167
+ # ::Math.send method, arg.value
168
+ # end
169
+ # else
170
+ # super() do
171
+ # ::Math.send method, *args.map { |a| a.value }
172
+ # end
173
+ # end
174
+ # end
175
+ # end
176
+
177
+ # class DebugStatement < Statement
178
+ # def self.new *args
179
+ # super() do
180
+ # puts 'fuku-debug: ' + args.map { |a| a.value }.join(', ')
181
+ # end
182
+ # end
183
+ # end
184
+
185
+ # def debug *args
186
+ # DebugStatement.new(*args)
187
+ # end
188
+
189
+ class CoreCall < Statement
190
+ def self.new method, *args
191
+ super() do
192
+ ECMA.make_core_object_from VM.send(method, *args.map { |arg| arg.value.to_ruby })
193
+ end
194
+ end
195
+ end
196
+
197
+ class IfCondition < Statement
198
+ def self.new condition, true_block, false_block = nil
199
+ if true_block && false_block
200
+ super() do
201
+ if condition.call.true?
202
+ true_block.call
203
+ else
204
+ false_block.call
205
+ end
206
+ end
207
+ elsif true_block
208
+ super() do
209
+ true_block.call if condition.call.true?
210
+ end
211
+ elsif false_block
212
+ super() do
213
+ false_block.call if condition.call.false?
214
+ end
215
+ else
216
+ super() do
217
+ condition.call
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ class ShortCircuitAnd < Statement
224
+ def self.new first, second
225
+ super() do
226
+ if (first_value = first.value).true?
227
+ if (second_value = second.value).true?
228
+ second_value
229
+ else
230
+ first_value
231
+ end
232
+ else
233
+ first_value
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ class ShortCircuitOr < Statement
240
+ def self.new first, second
241
+ super() do
242
+ if (first_value = first.value).true?
243
+ value
244
+ else
245
+ second.value
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ class ConditionalLoop < Statement
252
+ attr_accessor :condition, :block
253
+ def inspect
254
+ self.class.inspect + '(%p) {}' % [condition, block]
255
+ end
256
+ def pretty_print q
257
+ q.text self.class.inspect
258
+ q.group 2, '(', ')' do
259
+ q.pp condition
260
+ end
261
+ q.group 2, ' { ', ' }' do
262
+ q.pp block
263
+ end
264
+ end
265
+ end
266
+
267
+ class WhileLoop < ConditionalLoop
268
+ def self.new condition, block
269
+ if block.is_a? Sequence
270
+ case block.size
271
+ when 0
272
+ loop = super() do
273
+ until condition.call.false?
274
+ end
275
+ end
276
+ when 1
277
+ statement = block[0]
278
+ loop = super() do
279
+ until condition.call.false?
280
+ statement.call
281
+ end
282
+ end
283
+ when 2
284
+ statement1 = block[0]
285
+ statement2 = block[1]
286
+ loop = super() do
287
+ until condition.call.false?
288
+ statement1.call
289
+ statement2.call
290
+ end
291
+ end
292
+ else
293
+ loop = super() do
294
+ until condition.call.false?
295
+ for statement in block
296
+ statement.call
297
+ end
298
+ end
299
+ end
300
+ end
301
+ else
302
+ loop = super() do
303
+ until condition.call.false?
304
+ block.call
305
+ end
306
+ end
307
+ end
308
+ loop.condition = condition
309
+ loop.block = block
310
+ loop
311
+ end
312
+ def self.inspect
313
+ 'WhileLoop'
314
+ end
315
+ end
316
+
317
+ class DoWhileLoop < ConditionalLoop
318
+ def self.new condition, block
319
+ loop = super() do
320
+ if block.is_a? Sequence
321
+ begin
322
+ for statement in block
323
+ statement.call
324
+ end
325
+ end until condition.call.false?
326
+ else
327
+ raise 'Expected Sequence, got %p' % block
328
+ begin
329
+ block.call
330
+ end until condition.call.false?
331
+ end
332
+ end
333
+ loop.condition = condition
334
+ loop.block = block
335
+ loop
336
+ end
337
+ def self.inspect
338
+ 'DoWhileLoop'
339
+ end
340
+ end
341
+
342
+ # Just for convenience. Call like this:
343
+ #
344
+ # ForLoop.new(
345
+ # Assignment.new(i, 1),
346
+ # MethodCall.new(i, :<=, n),
347
+ # Assignment.new(i, MethodCall.new(i, :+, C(1)))),
348
+ # Sequence[
349
+ # ...
350
+ # ]
351
+ class ForLoop
352
+ def self.new start, condition, increment, block
353
+ Sequence[
354
+ start,
355
+ WhileLoop.new(condition,
356
+ Sequence[
357
+ block,
358
+ increment
359
+ ]
360
+ )
361
+ ]
362
+ end
363
+ end
364
+
365
+ class Assignment < Statement
366
+ attr_accessor :receiver, :statement
367
+ def self.new receiver, statement
368
+ if receiver.is_a? MethodCall
369
+ if receiver.meth == :[]
370
+ index = receiver.args.first
371
+ MethodCall.new(receiver.object, :[]=, index, statement)
372
+ elsif receiver.meth == :fuku_send
373
+ getter = receiver.args.first.value
374
+ setter = Constant.new(:"#{getter}=")
375
+ MethodCall.new(receiver.object, :fuku_send, setter, statement)
376
+ else
377
+ raise 'Cannot assign to method calls.'
378
+ end
379
+ elsif statement.is_a? MethodCall
380
+ MethodCallAssignment.new receiver, statement.object, statement.meth, *statement.args
381
+ else
382
+ assignment = super() do
383
+ receiver.value = statement.call
384
+ end
385
+ assignment.receiver = receiver
386
+ assignment.statement = statement
387
+ assignment
388
+ end
389
+ end
390
+ def inspect
391
+ 'Assignment(%p = %p)' % [receiver, statement]
392
+ end
393
+ def pretty_print q
394
+ q.group 2, 'Assignment(', ')' do
395
+ q.pp receiver
396
+ q.text ' = '
397
+ q.pp statement
398
+ end
399
+ end
400
+ end
401
+
402
+ def ass *args
403
+ Assignment.new(*args)
404
+ end
405
+
406
+ VARIABLE_IMPLEMENTATION_METHOD = ENV.fetch 'fuku_container', 'object'
407
+ # puts "using #{VARIABLE_IMPLEMENTATION_METHOD} for variable containers"
408
+
409
+ case VARIABLE_IMPLEMENTATION_METHOD
410
+ when 'object'
411
+ class Variable
412
+ attr_accessor :value
413
+ def initialize value = nil
414
+ @value = value
415
+ end
416
+ end
417
+ when 'container'
418
+ class Variable < Container
419
+ end
420
+ when 'array'
421
+ class Variable < Array
422
+ class << self
423
+ alias new []
424
+ end
425
+ alias value first
426
+ if false && [].respond_to?(:first=)
427
+ puts 'using Array#first='
428
+ alias value= first=
429
+ else
430
+ def value= value
431
+ self[0] = value
432
+ end
433
+ end
434
+ end
435
+ else
436
+ raise
437
+ end
438
+
439
+ class Variable
440
+ class << self
441
+ attr_reader :running_numbers
442
+ end
443
+ running_number = 0
444
+ @running_numbers = Hash.new do |h, k|
445
+ h[k] = running_number += 1
446
+ end
447
+ alias call value
448
+ def inspect
449
+ 'Variable%p(%p)' % [
450
+ name ? name.to_sym : Variable.running_numbers[self],
451
+ value
452
+ ]
453
+ end
454
+ def pretty_print q
455
+ q.text inspect
456
+ end
457
+ attr_accessor :name
458
+ end
459
+
460
+ def Variables count
461
+ # Array.new(count) { StackVariable[nil] }
462
+ Array.new(count) { Variable.new nil }
463
+ end
464
+
465
+ def var
466
+ Variable.new
467
+ end
468
+
469
+ class Constant < Variable
470
+ def inspect
471
+ 'Constant(' + value.inspect + ')'
472
+ end
473
+ end
474
+
475
+ class CastException < ::RuntimeError
476
+ attr_accessor :new_value, :result
477
+ def initialize new_value, result
478
+ self.new_value = new_value
479
+ self.result = result
480
+ end
481
+ end
482
+
483
+ class MethodCall < Statement
484
+ attr_accessor :object, :meth, :args
485
+ def self.new object, method, *args
486
+ if method == :fuku_call && object.is_a?(MethodCall) && object.meth == :fuku_send
487
+ return new(object.object, :fuku_method_call, object.args.first, *args)
488
+ end
489
+ method_call =
490
+ if args.empty?
491
+ super() do
492
+ begin
493
+ object.value.send method
494
+ rescue CastException => boom
495
+ object.value = boom.new_value
496
+ boom.result
497
+ end
498
+ end
499
+ elsif args.all? { |arg| arg.is_a? Constant }
500
+ if args.size == 1
501
+ arg = args.first.value
502
+ super() do
503
+ begin
504
+ object.value.send method, arg
505
+ rescue ::NoMethodError
506
+ if object.value == nil
507
+ raise 'Variable %s not defined' % object.name
508
+ else
509
+ raise
510
+ end
511
+ end
512
+ end
513
+ else
514
+ args = args.map { |a| a.value }
515
+ super() do
516
+ object.value.send method, *args
517
+ end
518
+ end
519
+ else
520
+ if args.size == 1
521
+ arg = args.first
522
+ super() do
523
+ object.value.send method, arg.value
524
+ end
525
+ else
526
+ super() do
527
+ object.value.send method, *args.map { |a| a.value }
528
+ end
529
+ end
530
+ end
531
+ method_call.object = object
532
+ method_call.meth = method
533
+ method_call.args = args
534
+ method_call
535
+ end
536
+ alias value call
537
+ def inspect
538
+ 'MethodCall:%p.%p(%p)' % [object, meth, args.join(', ')]
539
+ end
540
+ def pretty_print q
541
+ q.text 'MethodCall:'
542
+ q.pp object
543
+ q.text '.'
544
+ q.pp meth
545
+ q.group 2, '(', ')' do
546
+ q.pp args
547
+ end
548
+ end
549
+ end
550
+
551
+ def meth *args
552
+ MethodCall.new(*args)
553
+ end
554
+
555
+ class MethodCallAssignment < Statement
556
+ attr_accessor :receiver, :object, :meth, :args
557
+ def self.new receiver, object, meth, *args
558
+ method_call_assignment = if args.empty?
559
+ super() do
560
+ receiver.value = object.value.send meth
561
+ end
562
+ elsif args.all? { |arg| arg.is_a? Constant }
563
+ if args.size == 1
564
+ value = args.first.value
565
+ super() do
566
+ receiver.value = object.value.send meth, value
567
+ end
568
+ else
569
+ raise
570
+ args = args.map(&:value)
571
+ super() do
572
+ receiver.value = object.value.send meth, *args
573
+ end
574
+ end
575
+ else
576
+ if args.size == 1
577
+ arg = args.first
578
+ super() do
579
+ receiver.value = object.value.send meth, arg.value
580
+ end
581
+ else
582
+ super() do
583
+ receiver.value = object.value.send meth, *args.map { |a| a.value }
584
+ end
585
+ end
586
+ end
587
+ method_call_assignment.receiver = receiver
588
+ method_call_assignment.object = object
589
+ method_call_assignment.meth = meth
590
+ method_call_assignment.args = args
591
+ method_call_assignment
592
+ end
593
+ alias value call
594
+ def inspect
595
+ 'MethodCallAssignment(%p = %p.%p(%p))' % [receiver, object, meth, args]
596
+ end
597
+ def pretty_print q
598
+ q.group 2, 'MethodCallAssignment(', ')' do
599
+ q.pp receiver
600
+ q.text ' = '
601
+ q.pp object
602
+ q.text '.'
603
+ q.pp meth
604
+ q.group 2, '(', ')' do
605
+ q.pp args
606
+ end
607
+ end
608
+ end
609
+ end
610
+
611
+ class FunctionDefinition < Statement
612
+ attr_accessor :signature, :block
613
+ def self.new signature, block
614
+ function_definition = super() do
615
+ Function.new signature, block
616
+ end
617
+ function_definition.signature = signature
618
+ function_definition.block = block
619
+ function_definition
620
+ end
621
+ def inspect
622
+ 'FunctionDefintion(%p) { %p }' % [signature, block]
623
+ end
624
+ def pretty_print q
625
+ q.group 2, 'FunctionDefintion(', ')' do
626
+ q.pp signature
627
+ end
628
+ q.group 2, ' { ', ' }' do
629
+ q.pp block
630
+ end
631
+ end
632
+ end
633
+
634
+ class Function < Statement
635
+ def self.new signature, block
636
+ case signature.size
637
+ when 0
638
+ super() do
639
+ catch :return do
640
+ block.call
641
+ raise 'no return'
642
+ end
643
+ end
644
+ when 1
645
+ param = signature.first
646
+ super() do |arg|
647
+ param.value = arg
648
+ catch :return do
649
+ block.call
650
+ raise 'no return'
651
+ end
652
+ end
653
+ else
654
+ super() do |*arguments|
655
+ for i in 0...signature.size
656
+ signature[i].value = arguments[i]
657
+ end
658
+ catch :return do
659
+ block.call
660
+ raise 'no return'
661
+ end
662
+ end
663
+ end
664
+ end
665
+ alias fuku_call call
666
+ def to_ruby
667
+ function = self
668
+ proc do |*args|
669
+ function.call(*args).to_ruby
670
+ end
671
+ end
672
+ end
673
+
674
+ # class CachingFunction < Statement
675
+ # def self.new signature, block
676
+ # raise
677
+ # case signature.size
678
+ # when 0
679
+ # cache = nil
680
+ # super() do
681
+ # cache ||= block.call
682
+ # end
683
+ # when 1
684
+ # signature_first = signature.first
685
+ # cache = {}
686
+ # super() do |value|
687
+ # cache.delete cache.first.first if cache.size >= 16
688
+ # cache[value] ||= begin
689
+ # signature_first.value = value
690
+ # block.call
691
+ # end
692
+ # end
693
+ # else
694
+ # cache = {}
695
+ # super() do |values|
696
+ # cache.delete cache.first.first if cache.size >= 16
697
+ # cache[values] ||= begin
698
+ # for i in 0...signature.size
699
+ # signature[i].value = values[i]
700
+ # end
701
+ # block.call
702
+ # end
703
+ # end
704
+ # end
705
+ # end
706
+ # end
707
+
708
+ # class StackVariable < Array
709
+ # alias value last
710
+ # def value= value
711
+ # self[-1] = value
712
+ # end
713
+ # alias call value
714
+ # end
715
+
716
+ # class RecursiveFunction
717
+ # attr_accessor :signature
718
+ # def initialize signature, block = nil
719
+ # @signature = signature
720
+ # self.block = block
721
+ # end
722
+ # def block= block
723
+ # case signature.size
724
+ # when 0
725
+ # define_singleton_method :call do
726
+ # block.call
727
+ # end
728
+ # when 1
729
+ # param = signature.first
730
+ # define_singleton_method :call do |value|
731
+ # param.push value
732
+ # result = block.call
733
+ # param.pop
734
+ # result
735
+ # end
736
+ # else
737
+ # raise
738
+ # define_singleton_method :call do |values|
739
+ # for i in 0...signature.size
740
+ # signature[i].push values[i]
741
+ # end
742
+ # result = block.call
743
+ # for var in signature
744
+ # var.pop
745
+ # end
746
+ # result
747
+ # end
748
+ # end
749
+ # end
750
+ # end
751
+
752
+ # class CachingRecursiveFunction
753
+ # attr_accessor :signature
754
+ # def initialize signature
755
+ # @signature = signature
756
+ # end
757
+ # def block= block
758
+ # case signature.size
759
+ # when 0
760
+ # raise
761
+ # cache = nil
762
+ # define_singleton_method :call do
763
+ # cache ||= block.call
764
+ # end
765
+ # when 1
766
+ # signature_first = signature.first
767
+ # cache = {}
768
+ # define_singleton_method :call do |value|
769
+ # value = cache[value] ||= begin
770
+ # signature_first.push value
771
+ # result = block.call
772
+ # signature_first.pop
773
+ # result
774
+ # end
775
+ # cache.delete cache.first.first if cache.size >= 8
776
+ # value
777
+ # end
778
+ # else
779
+ # cache = {}
780
+ # define_singleton_method :call do |values|
781
+ # values = cache[values] ||= begin
782
+ # for i in 0...signature.size
783
+ # signature[i].push values[i]
784
+ # end
785
+ # result = block.call
786
+ # for var in signature
787
+ # var.pop
788
+ # end
789
+ # result
790
+ # end
791
+ # cache.delete cache.first.first if cache.size >= 8
792
+ # values
793
+ # end
794
+ # end
795
+ # end
796
+ # end
797
+
798
+ # class FunctionCall < Statement
799
+ # def self.new function, *arguments
800
+ # if false # cacheable?
801
+ # case arguments.size
802
+ # when 0
803
+ # raise
804
+ # cache = nil
805
+ # super() do
806
+ # cache ||= function.call
807
+ # end
808
+ # when 1
809
+ # arg = arguments.first
810
+ # super() do
811
+ # function.call(arg.value)
812
+ # end
813
+ # else
814
+ # raise
815
+ # cache = {}
816
+ # super() do
817
+ # cache.delete cache.first.first if cache.size >= 16
818
+ # values = arguments.map { |a| a.value }
819
+ # cache[values] ||= function.call(values)
820
+ # end
821
+ # end
822
+ # else
823
+ # case arguments.size
824
+ # when 0
825
+ # super() do
826
+ # function.call
827
+ # end
828
+ # when 1
829
+ # arg = arguments.first
830
+ # super() do
831
+ # function.call(arg.value)
832
+ # end
833
+ # else
834
+ # super() do
835
+ # function.call(*arguments.map { |a| a.value })
836
+ # end
837
+ # end
838
+ # end
839
+ # end
840
+ # end
841
+
842
+ class ReturnStatement < Statement
843
+ def self.new result
844
+ super() do
845
+ throw :return, result.value
846
+ end
847
+ end
848
+ end
849
+
850
+ class << CurrentReceiver = Object.new
851
+ attr_accessor :value
852
+ def set value
853
+ # puts 'CurrentReceiver set to %p.' % [value]
854
+ self.value = value
855
+ end
856
+ def inspect
857
+ 'CurrentReceiver(%p)' % [
858
+ value
859
+ ]
860
+ end
861
+ def pretty_print q
862
+ q.text inspect
863
+ end
864
+ end
865
+
866
+ end