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,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