delorean_lang 0.0.34 → 0.0.38
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +2 -2
- data/README.md +8 -6
- data/delorean.gemspec +1 -1
- data/lib/delorean/base.rb +22 -10
- data/lib/delorean/const.rb +5 -0
- data/lib/delorean/delorean.rb +570 -416
- data/lib/delorean/delorean.treetop +35 -47
- data/lib/delorean/engine.rb +42 -25
- data/lib/delorean/functions.rb +53 -45
- data/lib/delorean/model.rb +3 -1
- data/lib/delorean/nodes.rb +68 -28
- data/lib/delorean/version.rb +1 -1
- data/spec/dev_spec.rb +4 -6
- data/spec/eval_spec.rb +114 -10
- data/spec/func_spec.rb +22 -18
- data/spec/parse_spec.rb +21 -0
- metadata +7 -6
@@ -10,27 +10,33 @@ grammar Delorean
|
|
10
10
|
/
|
11
11
|
sp i:identifier sp? '=' sp? e:expression <Formula>
|
12
12
|
/
|
13
|
-
n:
|
13
|
+
n:class_name ':' sp? mod:(m:class_name '::')? p:class_name <SubNode>
|
14
14
|
/
|
15
|
-
n:
|
15
|
+
n:class_name ':' <BaseNode>
|
16
16
|
/
|
17
|
-
'import' sp n:
|
17
|
+
'import' sp n:class_name sp v:integer <Import>
|
18
18
|
end
|
19
19
|
|
20
|
-
rule
|
20
|
+
rule class_name
|
21
21
|
[A-Z] [a-zA-Z0-9_]*
|
22
22
|
end
|
23
23
|
|
24
24
|
rule expression
|
25
25
|
op:unary_op sp? e:expression <UnOp>
|
26
26
|
/
|
27
|
-
'if'
|
28
|
-
'then'
|
29
|
-
'else'
|
27
|
+
'if' sp? v:expression sp?
|
28
|
+
'then' sp? e1:expression sp?
|
29
|
+
'else' sp? e2:expression <IfElse>
|
30
|
+
/
|
31
|
+
v:getattr_exp sp? op:binary_op sp? e:expression <BinOp>
|
30
32
|
/
|
31
|
-
v:
|
33
|
+
v:getattr_exp sp? '[' sp? args:fn_args sp? ']' <IndexOp>
|
32
34
|
/
|
33
|
-
|
35
|
+
getattr_exp
|
36
|
+
end
|
37
|
+
|
38
|
+
rule getattr_exp
|
39
|
+
v:value ga:(('.' identifier)*) <ExpGetAttr>
|
34
40
|
end
|
35
41
|
|
36
42
|
rule list_expr
|
@@ -47,6 +53,11 @@ grammar Delorean
|
|
47
53
|
rule hash_expr
|
48
54
|
'{}' <HashExpr>
|
49
55
|
/
|
56
|
+
'{' sp? el:expression sp? ':' sp? er:expression sp
|
57
|
+
'for' sp i:identifier sp 'in' sp e1:expression sp?
|
58
|
+
ifexp:('if' sp ei:expression sp?)?
|
59
|
+
'}' <HashComprehension>
|
60
|
+
/
|
50
61
|
'{' sp? args:hash_args sp? '}' <HashExpr>
|
51
62
|
end
|
52
63
|
|
@@ -61,26 +72,23 @@ grammar Delorean
|
|
61
72
|
end
|
62
73
|
|
63
74
|
rule value
|
64
|
-
number
|
65
|
-
string
|
66
|
-
boolean
|
67
|
-
nil_val
|
68
|
-
script_call
|
69
|
-
fn
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
'(' sp? e:expression sp? ')' <Expr>
|
75
|
+
number /
|
76
|
+
string /
|
77
|
+
boolean /
|
78
|
+
nil_val /
|
79
|
+
script_call /
|
80
|
+
fn /
|
81
|
+
model_fn /
|
82
|
+
identifier /
|
83
|
+
list_expr /
|
84
|
+
hash_expr /
|
85
|
+
mod:(m:class_name '::')? c:class_name <NodeAsValue> /
|
86
|
+
'(' sp? e:expression sp? ')' <Expr>
|
77
87
|
end
|
78
88
|
|
79
89
|
# built-in functions
|
80
90
|
rule fn
|
81
|
-
fn:fn_name '(' sp? ')' <Fn>
|
82
|
-
/
|
83
|
-
fn:fn_name '(' sp? args:fn_args sp? ')' <Fn>
|
91
|
+
fn:fn_name '(' sp? args:fn_args? sp? ')' <Fn>
|
84
92
|
end
|
85
93
|
|
86
94
|
rule fn_args
|
@@ -94,22 +102,16 @@ grammar Delorean
|
|
94
102
|
end
|
95
103
|
|
96
104
|
rule model_name
|
97
|
-
class_name '::' model_name
|
98
|
-
/
|
99
|
-
class_name
|
105
|
+
class_name ('::' model_name)?
|
100
106
|
end
|
101
107
|
|
102
108
|
rule fn_name
|
103
109
|
[A-Z] [A-Z0-9]*
|
104
110
|
end
|
105
111
|
|
106
|
-
rule class_name
|
107
|
-
[A-Z] [a-zA-Z0-9]*
|
108
|
-
end
|
109
|
-
|
110
112
|
# script calling
|
111
113
|
rule script_call
|
112
|
-
'@' mod:(m:
|
114
|
+
'@' mod:(m:class_name '::')? c:class_name '(' sp? al:kw_args sp? ')' <ScriptCallNode>
|
113
115
|
/
|
114
116
|
'@' i:identifier? '(' sp? al:kw_args sp? ')' <ScriptCall>
|
115
117
|
end
|
@@ -122,20 +124,6 @@ grammar Delorean
|
|
122
124
|
k:(i:identifier ':' sp?)? arg0:expression args_rest:(sp? ',' sp? al:kw_args)? <KwArgs>
|
123
125
|
end
|
124
126
|
|
125
|
-
rule node_getattr
|
126
|
-
n:node_name '.' i:identifier <NodeGetAttr>
|
127
|
-
end
|
128
|
-
|
129
|
-
rule model_fn_getattr
|
130
|
-
mfn:model_fn '.' i:identifier <ModelFnGetAttr>
|
131
|
-
end
|
132
|
-
|
133
|
-
rule getattr
|
134
|
-
i:identifier '.' ga:getattr <GetAttr>
|
135
|
-
/
|
136
|
-
identifier
|
137
|
-
end
|
138
|
-
|
139
127
|
rule number
|
140
128
|
decimal / integer
|
141
129
|
end
|
data/lib/delorean/engine.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
+
require 'delorean/const'
|
1
2
|
require 'delorean/base'
|
2
3
|
|
3
4
|
module Delorean
|
4
|
-
SIG = "_SIG"
|
5
|
-
MOD = "DELOREAN__"
|
6
|
-
POST = "__D"
|
7
|
-
|
8
5
|
class Engine
|
9
6
|
attr_reader :last_node, :module_name, :line_no, :comp_set, :pm, :m, :imports
|
10
7
|
|
@@ -281,24 +278,36 @@ module Delorean
|
|
281
278
|
|
282
279
|
# enumerate all nodes
|
283
280
|
def enumerate_nodes
|
284
|
-
|
285
|
-
@node_attrs.keys.each {|k| n.add(k) }
|
286
|
-
n
|
281
|
+
SortedSet[* @node_attrs.keys]
|
287
282
|
end
|
288
283
|
|
289
284
|
# enumerate qualified list of all attrs
|
290
285
|
def enumerate_attrs
|
291
|
-
|
286
|
+
@node_attrs.keys.inject({}) { |h, node|
|
287
|
+
h[node] = enumerate_attrs_by_node(node)
|
288
|
+
h
|
289
|
+
}
|
292
290
|
end
|
293
291
|
|
294
|
-
# enumerate qualified list of attrs by node
|
292
|
+
# enumerate qualified list of attrs by node
|
295
293
|
def enumerate_attrs_by_node(node)
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
294
|
+
raise "bad node" unless node
|
295
|
+
|
296
|
+
# FIXME: for some reason, in rspec we get nodes which are String
|
297
|
+
# but .is_a?(String) fails.
|
298
|
+
begin
|
299
|
+
klass = node.class.name=="String" ? @m.module_eval(node) : node
|
300
|
+
rescue NameError
|
301
|
+
# FIXME: a little hacky. Should raise an exception.
|
302
|
+
return []
|
303
|
+
end
|
304
|
+
|
305
|
+
raise "bad node class #{klass}" unless klass.is_a?(Class)
|
306
|
+
|
307
|
+
klass.methods.map(&:to_s).select { |x|
|
308
|
+
x.end_with?(POST)
|
309
|
+
}.map { |x|
|
310
|
+
x.sub(/#{POST}$/, '')
|
302
311
|
}
|
303
312
|
end
|
304
313
|
|
@@ -310,9 +319,7 @@ module Delorean
|
|
310
319
|
# enumerate params by a single node
|
311
320
|
def enumerate_params_by_node(node)
|
312
321
|
attrs = enumerate_attrs_by_node(node)
|
313
|
-
|
314
|
-
attrs.each_value {|v| v.map {|p| ps.add(p) if @param_set.include?(p.to_s)}}
|
315
|
-
ps
|
322
|
+
Set.new( attrs.select {|a| @param_set.include?(a)} )
|
316
323
|
end
|
317
324
|
|
318
325
|
######################################################################
|
@@ -323,18 +330,29 @@ module Delorean
|
|
323
330
|
evaluate_attrs(node, [attr], params)[0]
|
324
331
|
end
|
325
332
|
|
333
|
+
def evaluate_attrs_hash(node, attrs, params={})
|
334
|
+
res = evaluate_attrs(node, attrs, params)
|
335
|
+
Hash[* attrs.zip(res).flatten(1)]
|
336
|
+
end
|
337
|
+
|
326
338
|
def evaluate_attrs(node, attrs, params={})
|
327
|
-
raise "bad
|
339
|
+
raise "bad params" unless params.is_a?(Hash)
|
328
340
|
|
329
|
-
|
330
|
-
klass =
|
331
|
-
|
332
|
-
|
341
|
+
if node.is_a?(Class)
|
342
|
+
klass = node
|
343
|
+
else
|
344
|
+
raise "bad node '#{node}'" unless node =~ /^[A-Z][a-zA-Z0-9_]*$/
|
345
|
+
|
346
|
+
begin
|
347
|
+
klass = @m.module_eval(node)
|
348
|
+
rescue NameError
|
349
|
+
err(UndefinedNodeError, "node #{node} is undefined")
|
350
|
+
end
|
333
351
|
end
|
334
352
|
|
335
353
|
params[:_engine] = self
|
336
354
|
|
337
|
-
attrs.map {|attr|
|
355
|
+
attrs.map { |attr|
|
338
356
|
raise "bad attribute '#{attr}'" unless attr =~ /^[a-z][A-Za-z0-9_]*$/
|
339
357
|
klass.send("#{attr}#{POST}".to_sym, params)
|
340
358
|
}
|
@@ -355,5 +373,4 @@ module Delorean
|
|
355
373
|
######################################################################
|
356
374
|
|
357
375
|
end
|
358
|
-
|
359
376
|
end
|
data/lib/delorean/functions.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module Delorean
|
2
2
|
module Functions
|
3
|
+
|
3
4
|
######################################################################
|
4
5
|
|
5
|
-
def MAX(*args)
|
6
|
+
def MAX(_e, *args)
|
6
7
|
args.max
|
7
8
|
end
|
8
9
|
|
@@ -10,7 +11,7 @@ module Delorean
|
|
10
11
|
|
11
12
|
######################################################################
|
12
13
|
|
13
|
-
def MIN(*args)
|
14
|
+
def MIN(_e, *args)
|
14
15
|
args.min
|
15
16
|
end
|
16
17
|
|
@@ -18,14 +19,14 @@ module Delorean
|
|
18
19
|
|
19
20
|
######################################################################
|
20
21
|
|
21
|
-
def MAXLIST(arg)
|
22
|
+
def MAXLIST(_e, arg)
|
22
23
|
raise "argument must be list" unless arg.is_a? Array
|
23
24
|
arg.max
|
24
25
|
end
|
25
26
|
|
26
27
|
MAXLIST_SIG = [ 1, 1 ]
|
27
28
|
|
28
|
-
def MINLIST(arg)
|
29
|
+
def MINLIST(_e, arg)
|
29
30
|
raise "argument must be list" unless arg.is_a? Array
|
30
31
|
arg.min
|
31
32
|
end
|
@@ -34,7 +35,7 @@ module Delorean
|
|
34
35
|
|
35
36
|
######################################################################
|
36
37
|
|
37
|
-
def ROUND(number, *args)
|
38
|
+
def ROUND(_e, number, *args)
|
38
39
|
number.round(*args)
|
39
40
|
end
|
40
41
|
|
@@ -42,7 +43,27 @@ module Delorean
|
|
42
43
|
|
43
44
|
######################################################################
|
44
45
|
|
45
|
-
def
|
46
|
+
def NUMBER(_e, s)
|
47
|
+
return s if s.is_a?(Float) || s.is_a?(Fixnum)
|
48
|
+
raise "Can't convert #{s} to number" unless
|
49
|
+
s =~ /^\d+(\.\d+)?$/
|
50
|
+
|
51
|
+
s.to_f
|
52
|
+
end
|
53
|
+
|
54
|
+
NUMBER_SIG = [ 1, 1 ]
|
55
|
+
|
56
|
+
######################################################################
|
57
|
+
|
58
|
+
def STRING(_e, obj)
|
59
|
+
obj.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
STRING_SIG = [ 1, 1 ]
|
63
|
+
|
64
|
+
######################################################################
|
65
|
+
|
66
|
+
def TIMEPART(_e, time, part)
|
46
67
|
if time == Float::INFINITY
|
47
68
|
return time if part == "d"
|
48
69
|
raise "Can only access date part of Infinity"
|
@@ -50,58 +71,54 @@ module Delorean
|
|
50
71
|
|
51
72
|
raise "non-time arg to TIMEPART" unless time.is_a?(Time)
|
52
73
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
74
|
+
case part
|
75
|
+
when "h" then time.hour
|
76
|
+
when "m" then time.min
|
77
|
+
when "s" then time.sec
|
78
|
+
when "d" then time.to_date
|
79
|
+
else
|
80
|
+
raise "unknown part arg to TIMEPART"
|
81
|
+
end
|
59
82
|
end
|
60
83
|
|
61
84
|
TIMEPART_SIG = [ 2, 2 ]
|
62
85
|
|
63
86
|
######################################################################
|
64
87
|
|
65
|
-
def DATEPART(date, part)
|
88
|
+
def DATEPART(_e, date, part)
|
66
89
|
raise "non-date arg to DATEPART" unless date.is_a?(Date)
|
67
90
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
91
|
+
case part
|
92
|
+
when "m" then date.month
|
93
|
+
when "d" then date.day
|
94
|
+
when "y" then date.year
|
95
|
+
else
|
96
|
+
raise "unknown part arg to DATEPART"
|
97
|
+
end
|
73
98
|
end
|
74
99
|
|
75
100
|
DATEPART_SIG = [ 2, 2 ]
|
76
101
|
|
77
102
|
######################################################################
|
78
103
|
|
79
|
-
def DATEADD(date, interval, part)
|
104
|
+
def DATEADD(_e, date, interval, part)
|
80
105
|
raise "non-date arg to DATEADD" unless date.is_a?(Date)
|
81
106
|
raise "non-integer interval arg to DATEADD" unless interval.is_a?(Fixnum)
|
82
107
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
108
|
+
case part
|
109
|
+
when "m" then date >> interval
|
110
|
+
when "d" then date + interval
|
111
|
+
when "y" then date >> (interval * 12)
|
112
|
+
else
|
113
|
+
raise "unknown part arg to DATEADD"
|
114
|
+
end
|
88
115
|
end
|
89
116
|
|
90
117
|
DATEADD_SIG = [ 3, 3 ]
|
91
118
|
|
92
119
|
######################################################################
|
93
120
|
|
94
|
-
def
|
95
|
-
raise "non-array arg to INDEX" unless array.is_a?(Array)
|
96
|
-
raise "non-integer index on call to INDEX" unless i.is_a?(Fixnum)
|
97
|
-
array.at(i)
|
98
|
-
end
|
99
|
-
|
100
|
-
INDEX_SIG = [ 2, 2 ]
|
101
|
-
|
102
|
-
######################################################################
|
103
|
-
|
104
|
-
def FLATTEN(array, *args)
|
121
|
+
def FLATTEN(_e, array, *args)
|
105
122
|
raise "non-array arg to FLATTEN" unless array.is_a?(Array)
|
106
123
|
raise "non-integer flatten on call to FLATTEN" unless
|
107
124
|
(args.empty? || args[0].is_a?(Fixnum))
|
@@ -112,7 +129,7 @@ module Delorean
|
|
112
129
|
|
113
130
|
######################################################################
|
114
131
|
|
115
|
-
def ERR(*args)
|
132
|
+
def ERR(_e, *args)
|
116
133
|
str = args.map(&:to_s).join(", ")
|
117
134
|
raise str
|
118
135
|
end
|
@@ -121,14 +138,5 @@ module Delorean
|
|
121
138
|
|
122
139
|
######################################################################
|
123
140
|
|
124
|
-
def TOSYM(s)
|
125
|
-
# raise "non-String arg to SYM" unless s.is_a?(String)
|
126
|
-
s.to_sym
|
127
|
-
end
|
128
|
-
|
129
|
-
TOSYM_SIG = [ 1, 1 ]
|
130
|
-
|
131
|
-
######################################################################
|
132
|
-
|
133
141
|
end
|
134
142
|
end
|
data/lib/delorean/model.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'delorean/const'
|
2
|
+
|
1
3
|
module Delorean
|
2
4
|
module Model
|
3
5
|
def self.included(base)
|
@@ -17,7 +19,7 @@ module Delorean
|
|
17
19
|
if sig
|
18
20
|
sig = [sig, sig] if sig.is_a? Fixnum
|
19
21
|
raise "Bad signature" unless (sig.is_a? Array and sig.length==2)
|
20
|
-
self.const_set(name.to_s.upcase+SIG, sig)
|
22
|
+
self.const_set(name.to_s.upcase+Delorean::SIG, sig)
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
data/lib/delorean/nodes.rb
CHANGED
@@ -80,7 +80,6 @@ eos
|
|
80
80
|
class SubNode < SNode
|
81
81
|
def check(context, *)
|
82
82
|
mname = mod.m.text_value if defined?(mod.m)
|
83
|
-
|
84
83
|
context.parse_define_node(n.text_value, p.text_value, mname)
|
85
84
|
end
|
86
85
|
|
@@ -117,6 +116,20 @@ eos
|
|
117
116
|
end
|
118
117
|
end
|
119
118
|
|
119
|
+
class NodeAsValue < SNode
|
120
|
+
def check(context, *)
|
121
|
+
mname = mod.m.text_value if defined?(mod.m)
|
122
|
+
context.parse_check_defined_mod_node(c.text_value, mname)
|
123
|
+
[]
|
124
|
+
end
|
125
|
+
|
126
|
+
def rewrite(context)
|
127
|
+
node_name = c.text_value
|
128
|
+
mname = mod.m.text_value if defined?(mod.m)
|
129
|
+
context.super_name(node_name, mname)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
120
133
|
# unary operator
|
121
134
|
class UnOp < SNode
|
122
135
|
def check(context, *)
|
@@ -140,6 +153,17 @@ eos
|
|
140
153
|
end
|
141
154
|
end
|
142
155
|
|
156
|
+
class IndexOp < SNode
|
157
|
+
def check(context, *)
|
158
|
+
vc, ac = v.check(context), args.check(context)
|
159
|
+
ac + vc
|
160
|
+
end
|
161
|
+
|
162
|
+
def rewrite(context)
|
163
|
+
"_index(#{v.rewrite(context)}, [#{args.rewrite(context)}], _e)"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
143
167
|
class Literal < SNode
|
144
168
|
def check(context, *)
|
145
169
|
[]
|
@@ -175,36 +199,19 @@ eos
|
|
175
199
|
end
|
176
200
|
end
|
177
201
|
|
178
|
-
class
|
179
|
-
def check(context, *)
|
180
|
-
context.parse_call_attr(n.text_value, i.text_value)
|
181
|
-
[text_value]
|
182
|
-
end
|
183
|
-
|
184
|
-
def rewrite(context)
|
185
|
-
text_value + POST + '(_e)'
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
class GetAttr < SNode
|
202
|
+
class ExpGetAttr < SNode
|
190
203
|
def check(context, *)
|
191
|
-
|
204
|
+
v.check(context)
|
192
205
|
end
|
193
206
|
|
194
207
|
def rewrite(context)
|
195
208
|
attr_list = ga.text_value.split('.')
|
196
|
-
attr_list.inject(i.rewrite(context)) {|x, y| "_get_attr(#{x}, '#{y}')"}
|
197
|
-
end
|
198
|
-
end
|
199
209
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
end
|
210
|
+
# If ga.text_value is not "", then we need to drop the 1st
|
211
|
+
# element since it'll be "".
|
212
|
+
attr_list.shift
|
204
213
|
|
205
|
-
|
206
|
-
x = mfn.rewrite(context)
|
207
|
-
"_get_attr(#{x}, '#{i.text_value}')"
|
214
|
+
attr_list.inject(v.rewrite(context)) {|x, y| "_get_attr(#{x}, '#{y}', _e)"}
|
208
215
|
end
|
209
216
|
end
|
210
217
|
|
@@ -218,7 +225,7 @@ eos
|
|
218
225
|
end
|
219
226
|
|
220
227
|
def rewrite(context)
|
221
|
-
fn.text_value + "(" + (defined?(args) ? args.rewrite(context) : "") + ")"
|
228
|
+
fn.text_value + "(_e, " + (defined?(args) ? args.rewrite(context) : "") + ")"
|
222
229
|
end
|
223
230
|
end
|
224
231
|
|
@@ -297,13 +304,46 @@ eos
|
|
297
304
|
end
|
298
305
|
|
299
306
|
def rewrite(context)
|
300
|
-
res = "(#{e1.rewrite(context)})
|
307
|
+
res = "(#{e1.rewrite(context)})"
|
301
308
|
context.parse_define_var(i.text_value)
|
302
|
-
res += "|#{i.rewrite(context)}| (#{e2.rewrite(context)}) }"
|
303
|
-
|
304
309
|
res += ".select{|#{i.rewrite(context)}| (#{ifexp.e3.rewrite(context)}) }" if
|
305
310
|
defined?(ifexp.e3)
|
311
|
+
res += ".map{"
|
312
|
+
res += "|#{i.rewrite(context)}| (#{e2.rewrite(context)}) }"
|
313
|
+
context.parse_undef_var(i.text_value)
|
314
|
+
res
|
315
|
+
end
|
316
|
+
end
|
306
317
|
|
318
|
+
class HashComprehension < SNode
|
319
|
+
def check(context, *)
|
320
|
+
vname = i.text_value
|
321
|
+
|
322
|
+
e1c = e1.check(context)
|
323
|
+
context.parse_define_var(vname)
|
324
|
+
# need to check el/er/ei in a context where the comprehension var
|
325
|
+
# is defined.
|
326
|
+
elc = el.check(context)
|
327
|
+
erc = er.check(context)
|
328
|
+
eic = defined?(ifexp.ei) ? ifexp.ei.check(context) : []
|
329
|
+
|
330
|
+
context.parse_undef_var(vname)
|
331
|
+
elc.delete(vname)
|
332
|
+
erc.delete(vname)
|
333
|
+
eic.delete(vname)
|
334
|
+
|
335
|
+
e1c + elc + erc + eic
|
336
|
+
end
|
337
|
+
|
338
|
+
def rewrite(context)
|
339
|
+
res = "(#{e1.rewrite(context)})"
|
340
|
+
context.parse_define_var(i.text_value)
|
341
|
+
iw = i.rewrite(context)
|
342
|
+
res += ".select{|#{iw}| (#{ifexp.ei.rewrite(context)}) }" if
|
343
|
+
defined?(ifexp.ei)
|
344
|
+
res += ".inject({}){"
|
345
|
+
res += "|_h#{iw}, #{iw}| "+
|
346
|
+
"_h#{iw}[#{el.rewrite(context)}]=(#{er.rewrite(context)}); _h#{iw}}"
|
307
347
|
context.parse_undef_var(i.text_value)
|
308
348
|
res
|
309
349
|
end
|