yadriggy 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +108 -0
- data/Rakefile +10 -0
- data/lib/yadriggy.rb +32 -0
- data/lib/yadriggy/algebra.rb +497 -0
- data/lib/yadriggy/ast.rb +1839 -0
- data/lib/yadriggy/ast_location.rb +73 -0
- data/lib/yadriggy/ast_value.rb +428 -0
- data/lib/yadriggy/c.rb +11 -0
- data/lib/yadriggy/c/c.rb +220 -0
- data/lib/yadriggy/c/codegen.rb +481 -0
- data/lib/yadriggy/c/config.rb +51 -0
- data/lib/yadriggy/c/ctype.rb +118 -0
- data/lib/yadriggy/c/ctypecheck.rb +449 -0
- data/lib/yadriggy/c/ffi.rb +301 -0
- data/lib/yadriggy/c/opencl.rb +458 -0
- data/lib/yadriggy/c/program.rb +86 -0
- data/lib/yadriggy/c1.rb +10 -0
- data/lib/yadriggy/checker.rb +216 -0
- data/lib/yadriggy/eval.rb +200 -0
- data/lib/yadriggy/eval_all.rb +159 -0
- data/lib/yadriggy/pretty_print.rb +492 -0
- data/lib/yadriggy/printer.rb +82 -0
- data/lib/yadriggy/ruby_typecheck.rb +468 -0
- data/lib/yadriggy/ruby_typeinfer.rb +335 -0
- data/lib/yadriggy/source_code.rb +168 -0
- data/lib/yadriggy/syntax.rb +524 -0
- data/lib/yadriggy/type.rb +754 -0
- data/lib/yadriggy/typecheck.rb +277 -0
- data/lib/yadriggy/version.rb +5 -0
- data/yadriggy.gemspec +33 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aa5e75505e86183390b717e3559e79528a06dab1
|
4
|
+
data.tar.gz: 6103b4d010e666693876526d6e425ae1bccf6a21
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cc3de4fdd6886598cefb8cfac86c8423cd5dda187d124b94495feae4bfd998d60f0f4d269cb659026bfa62625199ab284de67ec3690cc497004f0f7ff0fb0679
|
7
|
+
data.tar.gz: cd047b260fe5e66c1775f1532a51cfaf321304b309187ac7214d3d5f5110b05eead8f8806f91a6a810e84a4a361fd76778b36164eff4dbc9cee395c61f120522
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018- Shigeru Chiba
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# Yadriggy
|
2
|
+
|
3
|
+
Yadriggy (mistletoe in Japanese) is a library for building a
|
4
|
+
domain-specific language (DSL) embedded in Ruby. It was developed for
|
5
|
+
a particular kind of embedded DSLs, which we call hemiparasitic DSLs.
|
6
|
+
These DSLs borrow the syntax from the host language, Ruby, and the
|
7
|
+
code written in the DSLs is embedded in normal Ruby code. However,
|
8
|
+
the execution of the DSL code is independent of Ruby. Its semantics
|
9
|
+
can be totally different from Ruby and the code can be run out of the
|
10
|
+
Ruby VM. Hemiparasitic DSLs look like Ruby but they are different
|
11
|
+
languages except their syntax.
|
12
|
+
They parasitize Ruby by borrowing the syntax but their parasitism is
|
13
|
+
hemi; their execution engines are their own.
|
14
|
+
|
15
|
+
For details, the documentation is available from [Wiki](https://github.com/csg-tokyo/yadriggy/wiki).
|
16
|
+
|
17
|
+
## Hemiparasitic DSLs
|
18
|
+
|
19
|
+
A typical example of hemiparasitic DSL is computation offloading from
|
20
|
+
Ruby. For example, Yadriggy provides a simple DSL to offload
|
21
|
+
from Ruby to native C language.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'yadriggy/c'
|
25
|
+
|
26
|
+
include Yadriggy::C::CType
|
27
|
+
|
28
|
+
def fib(n) ! Integer
|
29
|
+
typedecl n: Integer
|
30
|
+
if n > 1
|
31
|
+
return fib(n - 1) + fib(n - 2)
|
32
|
+
else
|
33
|
+
return 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
puts Yadriggy::C.run { return fib(32) }
|
38
|
+
```
|
39
|
+
|
40
|
+
When this code is run, the block given to `Yadriggy::C.run` is
|
41
|
+
translated into C code with the definition of `fib` method.
|
42
|
+
Then the C code is compiled into a dynamic library, loaded the
|
43
|
+
library through ruby-ffi, and executed. Since the block given to
|
44
|
+
`run` calls `fib`, the definition of `fib` is also translated
|
45
|
+
into C.
|
46
|
+
|
47
|
+
An external variable is accessible from the compiled block:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
n = 32
|
51
|
+
puts Yadriggy::C.run { return fib(n) }
|
52
|
+
```
|
53
|
+
|
54
|
+
The argument to `fib` is take from the variable `n` that exists
|
55
|
+
outside of the block. `n` is passed to the compiled block by _copying_.
|
56
|
+
It is not passed by _reference_. Thus, when a new value is assigned to
|
57
|
+
`n` within the compiled block, it is not visible from the Ruby code.
|
58
|
+
The variable `n` in the Ruby code keeps the old value.
|
59
|
+
|
60
|
+
Note that the definition of `fib` contains type declarations
|
61
|
+
since this DSL is not Ruby.
|
62
|
+
A hemiparasitic DSL looks like Ruby but it is a different language.
|
63
|
+
`! Integer` following `def fib(n)` specifies the return type.
|
64
|
+
`typedecl` specifies the types of the parameters (and local variables
|
65
|
+
if any). In this DSL, most types have to be statically given
|
66
|
+
although the DSL performs simple type inference and some types
|
67
|
+
can be omitted.
|
68
|
+
|
69
|
+
## Library
|
70
|
+
|
71
|
+
Yadriggy provides a method for obtaining the abstract syntax tree (AST)
|
72
|
+
of the given method, lambda, or Proc.
|
73
|
+
It also provides a syntax checker that determines whether or not an AST
|
74
|
+
satisfies the syntax described in the BNF-like language, which is
|
75
|
+
a DSL embedded in Ruby by Yadriggy.
|
76
|
+
|
77
|
+
You can even obtain the AST of a piece of source code:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
require 'yadriggy'
|
81
|
+
ast = Yadriggy.reify {|a| a + 1 }
|
82
|
+
```
|
83
|
+
|
84
|
+
`reify` returns the AST of the given block `{|a| a + 1 }`.
|
85
|
+
It takes not only a block but also a `Method` or `Proc` object.
|
86
|
+
|
87
|
+
The idea of `reify` was proposed in the following paper:
|
88
|
+
|
89
|
+
- Shigeru Chiba, YungYu Zhuang, Maximilian Scherr, "Deeply Reifying Running Code for Constructing a Domain-Specific Language", PPPJ'16, Article No. 1, ACM, August 2016.
|
90
|
+
|
91
|
+
## Installation
|
92
|
+
|
93
|
+
To install, run:
|
94
|
+
|
95
|
+
$ gem install yadriggy
|
96
|
+
|
97
|
+
or, download this repository and run:
|
98
|
+
|
99
|
+
$ bundle exec rake install
|
100
|
+
|
101
|
+
## Contributing
|
102
|
+
|
103
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/csg-tokyo/yadriggy.
|
104
|
+
|
105
|
+
|
106
|
+
## License
|
107
|
+
|
108
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/lib/yadriggy.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright (C) 2017- Shigeru Chiba. All rights reserved.
|
2
|
+
|
3
|
+
require 'yadriggy/version'
|
4
|
+
|
5
|
+
require 'yadriggy/source_code'
|
6
|
+
require 'yadriggy/ast'
|
7
|
+
require 'yadriggy/ast_value'
|
8
|
+
require 'yadriggy/ast_location'
|
9
|
+
require 'yadriggy/eval'
|
10
|
+
require 'yadriggy/eval_all'
|
11
|
+
require 'yadriggy/algebra'
|
12
|
+
require 'yadriggy/syntax'
|
13
|
+
require 'yadriggy/checker'
|
14
|
+
require 'yadriggy/typecheck'
|
15
|
+
require 'yadriggy/ruby_typecheck'
|
16
|
+
require 'yadriggy/ruby_typeinfer'
|
17
|
+
require 'yadriggy/printer'
|
18
|
+
require 'yadriggy/pretty_print'
|
19
|
+
|
20
|
+
module Yadriggy
|
21
|
+
@@debug = 0
|
22
|
+
|
23
|
+
# Current debug level (0, 1, or 2).
|
24
|
+
# @return [Integer] the current level.
|
25
|
+
def self.debug() @@debug end
|
26
|
+
|
27
|
+
# Sets the current debug level.
|
28
|
+
# @param [Integer] level.
|
29
|
+
def self.debug=(level)
|
30
|
+
@@debug = level
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,497 @@
|
|
1
|
+
# Copyright (C) 2017- Shigeru Chiba. All rights reserved.
|
2
|
+
|
3
|
+
require 'yadriggy/eval'
|
4
|
+
|
5
|
+
module Yadriggy
|
6
|
+
|
7
|
+
# An interface inspired by object algebra (and tag-less final)
|
8
|
+
#
|
9
|
+
class Algebra
|
10
|
+
|
11
|
+
def initialize(expr)
|
12
|
+
EvalAlgebra.new(self).evaluate(expr)
|
13
|
+
end
|
14
|
+
|
15
|
+
def nil_value()
|
16
|
+
raise NotImplementedError.new('nil_value')
|
17
|
+
end
|
18
|
+
|
19
|
+
def name(name, line_no, column)
|
20
|
+
raise NotImplementedError.new('name')
|
21
|
+
end
|
22
|
+
|
23
|
+
def identifier_or_call(name, line_no, column)
|
24
|
+
name(name, line_no, column)
|
25
|
+
end
|
26
|
+
|
27
|
+
def identifier(name, line_no, column)
|
28
|
+
identifier_or_call(name, line_no, column)
|
29
|
+
end
|
30
|
+
|
31
|
+
def reserved(name, line_no, column)
|
32
|
+
name(name, line_no, column)
|
33
|
+
end
|
34
|
+
|
35
|
+
def const(name, line_no, column)
|
36
|
+
name(name, line_no, column)
|
37
|
+
end
|
38
|
+
|
39
|
+
def label(name, line_no, column)
|
40
|
+
name(name, line_no, column)
|
41
|
+
end
|
42
|
+
|
43
|
+
def symbol(name, line_no, column)
|
44
|
+
raise NotImplementedError.new('symbol')
|
45
|
+
end
|
46
|
+
|
47
|
+
def global_variable(name, line_no, column)
|
48
|
+
name(name, line_no, column)
|
49
|
+
end
|
50
|
+
|
51
|
+
def instance_variable(name, line_no, column)
|
52
|
+
name(name, line_no, column)
|
53
|
+
end
|
54
|
+
|
55
|
+
def variable_call(name, line_no, column)
|
56
|
+
identifier_or_call(name, line_no, column)
|
57
|
+
end
|
58
|
+
|
59
|
+
def super_method(expr)
|
60
|
+
raise NotImplementedError.new('super_method')
|
61
|
+
end
|
62
|
+
|
63
|
+
def number(value, line_no, column)
|
64
|
+
raise NotImplementedError.new('number')
|
65
|
+
end
|
66
|
+
|
67
|
+
# exprs() sequentially processes each expression in a series
|
68
|
+
# of expressions.
|
69
|
+
# So, for example, { e1, e2, ..., e_n } is
|
70
|
+
# processed by exprs(.. exprs(exprs(nil, e1), e2).., e_n).
|
71
|
+
# In other words, it is by
|
72
|
+
# [e1, e2, ..., e_n].inject(nil) {|r,e| exprs(r, evaluate(e))}.
|
73
|
+
#
|
74
|
+
# RESULT specifies the result of the previous expression.
|
75
|
+
# It is nil if EXPR is the first expression.
|
76
|
+
#
|
77
|
+
def exprs(result, expr)
|
78
|
+
raise NotImplementedError.new('exprs')
|
79
|
+
end
|
80
|
+
|
81
|
+
# CONTENTS is an array of the results of evaluating
|
82
|
+
# each component.
|
83
|
+
#
|
84
|
+
def string_interpolation(contents)
|
85
|
+
raise NotImplementedError.new('string_interpolation')
|
86
|
+
end
|
87
|
+
|
88
|
+
def string_literal(value, line_no, column)
|
89
|
+
raise NotImplementedError.new('string_literal')
|
90
|
+
end
|
91
|
+
|
92
|
+
# A constant value in a scope, such as Foo::Bar.
|
93
|
+
#
|
94
|
+
def const_path_ref(scope, name)
|
95
|
+
raise NotImplementedError.new('const_path_ref')
|
96
|
+
end
|
97
|
+
|
98
|
+
# A constant value in a scope as a L-value.
|
99
|
+
#
|
100
|
+
def const_path_field(scope, name)
|
101
|
+
const_path_ref(scope, name)
|
102
|
+
end
|
103
|
+
|
104
|
+
def unary(op, expr)
|
105
|
+
raise NotImplementedError.new('unary')
|
106
|
+
end
|
107
|
+
|
108
|
+
def binary(left, op, right)
|
109
|
+
raise NotImplementedError.new('binary')
|
110
|
+
end
|
111
|
+
|
112
|
+
def dots(left, op, right)
|
113
|
+
binary(left, op, right)
|
114
|
+
end
|
115
|
+
|
116
|
+
def assign(left, op, right)
|
117
|
+
binary(left, op, right)
|
118
|
+
end
|
119
|
+
|
120
|
+
def array_ref(array, index)
|
121
|
+
raise NotImplementedError.new('array')
|
122
|
+
end
|
123
|
+
|
124
|
+
# Array reference as L-value
|
125
|
+
#
|
126
|
+
def array_ref_field(array, index)
|
127
|
+
array_ref(array, index)
|
128
|
+
end
|
129
|
+
|
130
|
+
# An expression surrounded with ().
|
131
|
+
#
|
132
|
+
def paren(element)
|
133
|
+
raise NotImplementedError.new('paren')
|
134
|
+
end
|
135
|
+
|
136
|
+
# An array literal.
|
137
|
+
# ELEMENTS is an array.
|
138
|
+
#
|
139
|
+
def array(elements)
|
140
|
+
raise NotImplementedError.new('array')
|
141
|
+
end
|
142
|
+
|
143
|
+
# PAIRS is an array of pairs. Each pair is
|
144
|
+
# an array where the first element is a key
|
145
|
+
# and the second element is a value.
|
146
|
+
#
|
147
|
+
def hash(pairs)
|
148
|
+
raise NotImplementedError.new('hash')
|
149
|
+
end
|
150
|
+
|
151
|
+
# Method call.
|
152
|
+
# ARGS is an array. BLOCK is a thunk.
|
153
|
+
#
|
154
|
+
def call(receiver, op, name, args, block_arg, block)
|
155
|
+
raise NotImplementedError.new('call')
|
156
|
+
end
|
157
|
+
|
158
|
+
# Method call without parentheses.
|
159
|
+
# ARGS is an array. BLOCK is a thunk.
|
160
|
+
#
|
161
|
+
def command(receiver, op, name, args, block_arg, block)
|
162
|
+
call(receiver, op, name, args, block_arg, block)
|
163
|
+
end
|
164
|
+
|
165
|
+
# if, unless, modifier if/unless, and ternary if (?:)
|
166
|
+
# THEN_EXPRS is a thunk.
|
167
|
+
# ALL_ELSIF is an array of pairs of elsif condition and its body.
|
168
|
+
# Both are thunks.
|
169
|
+
# ELSE_EXPRS is a thiuk or nil.
|
170
|
+
#
|
171
|
+
def conditional(op, cond, then_exprs, all_elsif, else_exprs)
|
172
|
+
raise NotImplementedError.new('conditional')
|
173
|
+
end
|
174
|
+
|
175
|
+
# while, until, and modifier while/until.
|
176
|
+
# COND and BODY are thunks.
|
177
|
+
#
|
178
|
+
def loop(op, cond, body)
|
179
|
+
raise NotImplementedError.new('loop')
|
180
|
+
end
|
181
|
+
|
182
|
+
# for loop.
|
183
|
+
# BODY is a thunk.
|
184
|
+
#
|
185
|
+
def for_loop(var, set, body)
|
186
|
+
raise NotImplementedError.new('for_loop')
|
187
|
+
end
|
188
|
+
|
189
|
+
# break, next, redo, retry.
|
190
|
+
#
|
191
|
+
def break_out(op, values)
|
192
|
+
raise NotImplementedError.new('break_out')
|
193
|
+
end
|
194
|
+
|
195
|
+
# An expression with return.
|
196
|
+
#
|
197
|
+
def return_values(values)
|
198
|
+
raise NotImplementedError.new('return_values')
|
199
|
+
end
|
200
|
+
|
201
|
+
# A block.
|
202
|
+
# BODY is a thunk.
|
203
|
+
#
|
204
|
+
def block(params, optionals, rest_params, params_after_rest, keywords,
|
205
|
+
rest_of_keywords, block_param, body)
|
206
|
+
raise NotImplementedError.new('block')
|
207
|
+
end
|
208
|
+
|
209
|
+
# A lambda expression.
|
210
|
+
# BODY is a thunk.
|
211
|
+
#
|
212
|
+
def lambda_expr(params, optionals, rest_params, params_after_rest,
|
213
|
+
keywords, rest_of_keywords, block_param, body)
|
214
|
+
block(params, optionals, rest_params, params_after_rest,
|
215
|
+
keywords, rest_of_keywords, block_param, body)
|
216
|
+
end
|
217
|
+
|
218
|
+
# rescue-else-ensure-end.
|
219
|
+
# BODY, NESTED_RESCUE, ELSE_CLAUSE, and ENSURE_CLAUSE are
|
220
|
+
# thunks.
|
221
|
+
#
|
222
|
+
def rescue_end(types, parameter, body, nested_rescue,
|
223
|
+
else_clause, ensure_clause)
|
224
|
+
raise NotImplementedError.new('rescue_end')
|
225
|
+
end
|
226
|
+
|
227
|
+
def begin_end(body, rescue_clause)
|
228
|
+
raise NotImplementedError.new('begin_end')
|
229
|
+
end
|
230
|
+
|
231
|
+
# def.
|
232
|
+
#
|
233
|
+
# BODY and RESCUE_CLAUSE are thunks.
|
234
|
+
#
|
235
|
+
def define(name, params, optionals, rest_of_params, params_after_rest,
|
236
|
+
keywords, rest_of_keywords, block_param,
|
237
|
+
body, rescue_clause)
|
238
|
+
raise NotImplementedError.new('define')
|
239
|
+
end
|
240
|
+
|
241
|
+
def module_def(name, body, rescue_clause)
|
242
|
+
raise NotImplementedError.new('module_def')
|
243
|
+
end
|
244
|
+
|
245
|
+
def class_def(name, superclass, body, rescue_clause)
|
246
|
+
raise NotImplementedError.new('class_def')
|
247
|
+
end
|
248
|
+
|
249
|
+
def singular_class_def(name, body, rescue_clause)
|
250
|
+
raise NotImplementedError.new('singular_class_def')
|
251
|
+
end
|
252
|
+
|
253
|
+
# A whole program.
|
254
|
+
#
|
255
|
+
# ELEMENTS is the result of processing the program elements.
|
256
|
+
#
|
257
|
+
def program(elements)
|
258
|
+
raise NotImplementedError.new('program')
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# evaluator for Algebra
|
263
|
+
#
|
264
|
+
class EvalAlgebra < Eval
|
265
|
+
def initialize(algebra)
|
266
|
+
@algebra = algebra
|
267
|
+
end
|
268
|
+
|
269
|
+
def nil_value(expr)
|
270
|
+
@algebra.nil_value
|
271
|
+
end
|
272
|
+
|
273
|
+
def name(expr)
|
274
|
+
raise 'should never happen'
|
275
|
+
end
|
276
|
+
|
277
|
+
def identifier(expr)
|
278
|
+
@algebra.identifier(expr.name, expr.line_no, expr.column)
|
279
|
+
end
|
280
|
+
|
281
|
+
def reserved(expr)
|
282
|
+
@algebra.reserved(expr.name, expr.line_no, expr.column)
|
283
|
+
end
|
284
|
+
|
285
|
+
def const(expr)
|
286
|
+
@algebra.const(expr.name, expr.line_no, expr.column)
|
287
|
+
end
|
288
|
+
|
289
|
+
def label(expr)
|
290
|
+
@algebra.label(expr.name, expr.line_no, expr.column)
|
291
|
+
end
|
292
|
+
|
293
|
+
def symbol(expr)
|
294
|
+
@algebra.symbol(expr.name, expr.line_no, expr.column)
|
295
|
+
end
|
296
|
+
|
297
|
+
def global_variable(expr)
|
298
|
+
@algebra.global_variable(expr.name, expr.line_no, expr.column)
|
299
|
+
end
|
300
|
+
|
301
|
+
def instance_variable(expr)
|
302
|
+
@algebra.instance_variable(expr.name, expr.line_no, expr.column)
|
303
|
+
end
|
304
|
+
|
305
|
+
def variable_call(expr)
|
306
|
+
@algebra.variable_call(expr.name, expr.line_no, expr.column)
|
307
|
+
end
|
308
|
+
|
309
|
+
def super_method(expr) @algebra.super_method end
|
310
|
+
|
311
|
+
def number(expr)
|
312
|
+
@algebra.number(expr.value, expr.line_no, expr.column)
|
313
|
+
end
|
314
|
+
|
315
|
+
def exprs(expr)
|
316
|
+
expr.expressions.inject(nil) do |result, e|
|
317
|
+
@algebra.exprs(result, evaluate(e))
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def paren(expr)
|
322
|
+
@algebra.paren(evaluate(expr.expression))
|
323
|
+
end
|
324
|
+
|
325
|
+
def array(expr)
|
326
|
+
@algebra.array(expr.elements.map {|e| evaluate(e)})
|
327
|
+
end
|
328
|
+
|
329
|
+
def string_interpolation(expr)
|
330
|
+
@algebra.string_interpolation(expr.contents.map {|e| evaluate(e) })
|
331
|
+
end
|
332
|
+
|
333
|
+
def string_literal(expr)
|
334
|
+
@algebra.string_literal(expr.value, expr.line_no, expr.column)
|
335
|
+
end
|
336
|
+
|
337
|
+
def const_path_ref(expr)
|
338
|
+
@algebra.const_path_ref(expr.scope, expr.name)
|
339
|
+
end
|
340
|
+
|
341
|
+
def const_path_field(expr)
|
342
|
+
@algebra.const_path_field(expr.scope, expr.name)
|
343
|
+
end
|
344
|
+
|
345
|
+
def unary(expr)
|
346
|
+
@algebra.unary(expr.op, evaluate(expr.expr))
|
347
|
+
end
|
348
|
+
|
349
|
+
def binary(expr)
|
350
|
+
@algebra.binary(evaluate(expr.left), expr.op, evaluate(expr.right))
|
351
|
+
end
|
352
|
+
|
353
|
+
def dots(expr)
|
354
|
+
@algebra.dots(evaluate(expr.left), expr.op, evaluate(expr.right))
|
355
|
+
end
|
356
|
+
|
357
|
+
def assign(expr)
|
358
|
+
@algebra.assign(evaluate(expr.left), expr.op, evaluate(expr.right))
|
359
|
+
end
|
360
|
+
|
361
|
+
def array_ref(expr)
|
362
|
+
@algebra.array_ref(evaluate(expr.array),
|
363
|
+
expr.indexes.map {|e| evaluate(e) })
|
364
|
+
end
|
365
|
+
|
366
|
+
def array_ref_field(expr)
|
367
|
+
@algebra.array_ref_field(evaluate(expr.array),
|
368
|
+
expr.indexes.map {|e| evaluate(e) })
|
369
|
+
end
|
370
|
+
|
371
|
+
def hash(expr)
|
372
|
+
@algebra.hash(expr.pairs.map {|p| p.map {|e| evaluate(e) }})
|
373
|
+
end
|
374
|
+
|
375
|
+
def call(expr)
|
376
|
+
@algebra.call(evaluate(expr.receiver), expr.op, expr.name,
|
377
|
+
expr.args.map {|e| evaluate(e) },
|
378
|
+
evaluate(expr.block_arg),
|
379
|
+
lambda { evaluate(expr.block) })
|
380
|
+
end
|
381
|
+
|
382
|
+
def command(expr)
|
383
|
+
@algebra.command(evaluate(expr.receiver), expr.op, expr.name,
|
384
|
+
expr.args.map {|e| evaluate(e) },
|
385
|
+
evaluate(expr.block_arg),
|
386
|
+
lambda { evaluate(expr.block) })
|
387
|
+
end
|
388
|
+
|
389
|
+
def conditional(expr)
|
390
|
+
@algebra.conditional(expr.op, evaluate(expr.cond),
|
391
|
+
lambda { evaluate(expr.then) },
|
392
|
+
expr.all_elsif.map do |e|
|
393
|
+
[lambda { evaluate(e[0]) },
|
394
|
+
lambda { evaluate(e[1]) }]
|
395
|
+
end,
|
396
|
+
if expr.else.nil?
|
397
|
+
nil
|
398
|
+
else
|
399
|
+
lambda { evaluate(expr.else) }
|
400
|
+
end)
|
401
|
+
end
|
402
|
+
|
403
|
+
def loop(expr)
|
404
|
+
@algebra.loop(expr.op, lambda { evaluate(expr.cond) },
|
405
|
+
lambda { evaluate(expr.body) })
|
406
|
+
end
|
407
|
+
|
408
|
+
def for_loop(expr)
|
409
|
+
@algebra.for_loop(expr.vars, evaluate(expr.set),
|
410
|
+
lambda { evaluate(expr.body) })
|
411
|
+
end
|
412
|
+
|
413
|
+
def break_out(expr)
|
414
|
+
@algebra.break_out(expr.op, expr.values.map {|e| evaluate(e) })
|
415
|
+
end
|
416
|
+
|
417
|
+
def return_values(expr)
|
418
|
+
@algebra.return_values(expr.values.map {|e| evaluate(e) })
|
419
|
+
end
|
420
|
+
|
421
|
+
def block(expr)
|
422
|
+
@algebra.block(expr.params, expr.optionals, expr.rest_of_params,
|
423
|
+
expr.params_after_rest, expr.keywords,
|
424
|
+
expr.rest_of_keywords,
|
425
|
+
expr.block_param, lambda { evaluate(expr.body) })
|
426
|
+
end
|
427
|
+
|
428
|
+
def lambda_expr(expr)
|
429
|
+
@algebra.lambda_expr(expr.params, expr.optionals, expr.rest_of_params,
|
430
|
+
expr.params_after_rest, expr.keywords,
|
431
|
+
expr.rest_of_keywords,
|
432
|
+
expr.block_param, lambda { evaluate(expr.body) })
|
433
|
+
end
|
434
|
+
|
435
|
+
def rescue_end(expr)
|
436
|
+
@algebra.rescue_end(expr.types, expr.parameter,
|
437
|
+
lambda { evaluate(expr.body) },
|
438
|
+
lambda { evaluate(expr.nested_rescue) },
|
439
|
+
lambda { evaluate(expr.else) },
|
440
|
+
lambda { evaluate(expr.ensure) })
|
441
|
+
end
|
442
|
+
|
443
|
+
def begin_end(expr)
|
444
|
+
@algebra.begin_end(lambda { evaluate(expr.body) },
|
445
|
+
if expr.rescue.nil?
|
446
|
+
nil
|
447
|
+
else
|
448
|
+
lambda { evaluate(expr.rescue) }
|
449
|
+
end)
|
450
|
+
end
|
451
|
+
|
452
|
+
def define(expr)
|
453
|
+
@algebra.define(expr.name, expr.params, expr.optionals,
|
454
|
+
expr.rest_of_params, expr.params_after_rest,
|
455
|
+
expr.keywords, expr.rest_of_keywords,
|
456
|
+
expr.block_param, lambda { evaluate(expr.body) },
|
457
|
+
if expr.rescue.nil?
|
458
|
+
nil
|
459
|
+
else
|
460
|
+
lambda { evaluate(expr.rescue) }
|
461
|
+
end)
|
462
|
+
end
|
463
|
+
|
464
|
+
def module_def(expr)
|
465
|
+
@algebra.module_def(expr.name, lambda { evaluate(expr.body) },
|
466
|
+
if expr.rescue.nil?
|
467
|
+
nil
|
468
|
+
else
|
469
|
+
lambda { evaluate(expr.rescue) }
|
470
|
+
end)
|
471
|
+
end
|
472
|
+
|
473
|
+
def class_def(expr)
|
474
|
+
@algebra.class_def(expr.name, expr.superclass,
|
475
|
+
lambda { evaluate(expr.body) },
|
476
|
+
if expr.rescue.nil?
|
477
|
+
nil
|
478
|
+
else
|
479
|
+
lambda { evaluate(expr.rescue) }
|
480
|
+
end)
|
481
|
+
end
|
482
|
+
|
483
|
+
def singular_class_def(expr)
|
484
|
+
@algebra.singular_class_def(expr.name,
|
485
|
+
lambda { evaluate(expr.body) },
|
486
|
+
if expr.rescue.nil?
|
487
|
+
nil
|
488
|
+
else
|
489
|
+
lambda { evaluate(expr.rescue) }
|
490
|
+
end)
|
491
|
+
end
|
492
|
+
|
493
|
+
def program(expr)
|
494
|
+
@algebra.program(evaluate(expr.elements))
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|