delorean_lang 1.0.0 → 1.1.0

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.
@@ -46,6 +46,16 @@ grammar Delorean
46
46
  getattr_exp
47
47
  end
48
48
 
49
+ rule block_args
50
+ sp4 sp4 sp? i:identifier sp? '=?' sp1? e:expression <BlockParameterDefault>
51
+ /
52
+ sp4 sp4 sp? i:identifier sp? '=?' <BlockParameter>
53
+ end
54
+
55
+ rule block_formulas
56
+ sp4 sp4 sp? i:identifier sp? '=' sp? e:expression <BlockFormula>
57
+ end
58
+
49
59
  rule getattr_exp
50
60
  v:value dotted:dotted <GetattrExp>
51
61
  /
@@ -61,7 +71,11 @@ grammar Delorean
61
71
  /
62
72
  '(' sp? al:kw_args? sp? ')' <NodeCall>
63
73
  /
74
+ '.' sp? i:identifier '(' sp? al:fn_args? sp? ')' b_args:block_args* expressions:block_formulas+ <BlockExpression>
75
+ /
64
76
  '.' sp? i:identifier '(' sp? al:fn_args? sp? ')' <Call>
77
+ /
78
+ '.' sp? i:identifier b_args:block_args* expressions:block_formulas+ <BlockExpression>
65
79
  /
66
80
  '.' sp? i:(identifier / integer) <GetAttr>
67
81
  end
@@ -159,6 +173,10 @@ grammar Delorean
159
173
  args_rest:(sp? ',' sp? al:kw_args?)? <KwArgs>
160
174
  end
161
175
 
176
+ # rule block_args
177
+ # '|' sp? args:unpack_args sp? '|'
178
+ # end
179
+
162
180
  rule decimal
163
181
  i:integer '.' [0-9]+ <Literal>
164
182
  end
@@ -168,7 +186,7 @@ grammar Delorean
168
186
  end
169
187
 
170
188
  rule identifier
171
- [a-z] [a-zA-Z0-9_]* <Identifier>
189
+ [a-z] [a-zA-Z0-9_]* '?'? <Identifier>
172
190
  end
173
191
 
174
192
  rule boolean
@@ -192,10 +210,15 @@ grammar Delorean
192
210
  ' '
193
211
  end
194
212
 
213
+ rule sp1
214
+ ' '
215
+ end
216
+
195
217
  rule sp
196
218
  [\s]+
197
219
  end
198
220
 
221
+
199
222
  rule string
200
223
  '"' ('\"' / !'"' .)* '"' <IString>
201
224
  /
@@ -252,7 +252,9 @@ module Delorean
252
252
  multi_line = nil
253
253
  @multi_no = nil
254
254
 
255
- source.each_line do |line|
255
+ lines = source.each_line.to_a
256
+
257
+ lines.each_with_index do |line, index|
256
258
  @line_no += 1
257
259
 
258
260
  # skip comments
@@ -279,6 +281,24 @@ module Delorean
279
281
  end
280
282
  end
281
283
 
284
+ # Initially Delorean code is parsed by single line.
285
+ # If line can not be parsed as valid Delorean expressions, parser
286
+ # would combine it with the following lines that are indented by more
287
+ # than 4 spaces and attempt to parse it again.
288
+
289
+ # However the first line of method with block can be parsed as a valid
290
+ # method or attribute call. In order to avoid that, we had to add this
291
+ # lookahead hack, that treats any expressions as multiline when
292
+ # the following line is indented by more that 4 spaces.
293
+ next_line = lines[index + 1] || ''
294
+
295
+ if /\A {5}/.match?(next_line)
296
+ multi_line ||= ''
297
+ multi_line += line
298
+ @multi_no ||= @line_no
299
+ next
300
+ end
301
+
282
302
  t = parser.parse(line)
283
303
 
284
304
  if !t
@@ -123,6 +123,14 @@ eos
123
123
 
124
124
  class Formula < SNode
125
125
  def check(context, *)
126
+ if i.text_value.include?('?')
127
+ raise Delorean::ParseError.new(
128
+ '? in formula names not supported',
129
+ context.module_name,
130
+ context.line_no
131
+ )
132
+ end
133
+
126
134
  context.parse_define_attr(i.text_value, e.check(context))
127
135
  end
128
136
 
@@ -410,6 +418,148 @@ eos
410
418
  end
411
419
  end
412
420
 
421
+ class BlockParameter < Parameter
422
+ def check(context)
423
+ context.parse_define_var(i.text_value)
424
+ context.parse_undef_var(i.text_value)
425
+ end
426
+
427
+ def rewrite(context)
428
+ a_name = i.text_value
429
+ expr = defined?(e) ? e.rewrite(context) : ''
430
+ expr = expr.strip
431
+
432
+ return "#{a_name}#{POST}" if expr.empty?
433
+
434
+ "#{a_name}#{POST} = #{expr}"
435
+ end
436
+
437
+ def force_def(context)
438
+ context.parse_define_var(i.text_value)
439
+ end
440
+
441
+ def force_undef(context)
442
+ context.parse_undef_var(i.text_value)
443
+ end
444
+ end
445
+
446
+ class BlockParameterDefault < BlockParameter
447
+ def check(context)
448
+ context.parse_define_var(i.text_value)
449
+
450
+ e.check(context)
451
+ context.parse_undef_var(i.text_value)
452
+ end
453
+ end
454
+
455
+ class BlockFormula < SNode
456
+ def check(context, *)
457
+ if i.text_value.include?('?')
458
+ raise Delorean::ParseError.new(
459
+ '? in formula names not supported',
460
+ context.module_name,
461
+ context.line_no
462
+ )
463
+ end
464
+
465
+ context.parse_define_var(i.text_value)
466
+ context.parse_undef_var(i.text_value)
467
+ end
468
+
469
+ def rewrite(context)
470
+ "#{i.text_value}#{POST} = #{e.rewrite(context)}"
471
+ end
472
+
473
+ def force_def(context)
474
+ context.parse_define_var(i.text_value)
475
+ end
476
+
477
+ def force_undef(context)
478
+ context.parse_undef_var(i.text_value)
479
+ end
480
+ end
481
+
482
+ class BlockExpression < SNode
483
+ def check(context, *)
484
+ if respond_to?(:al)
485
+ al.text_value.empty? ? [] : al.check(context)
486
+ end
487
+
488
+ b_args.elements.each do |element|
489
+ element.check(context)
490
+ element.force_def(context)
491
+ end
492
+
493
+ formulas = expressions.elements.select do |elem|
494
+ elem.is_a? BlockFormula
495
+ end
496
+
497
+ result_formula = formulas.find do |formula|
498
+ formula.i.text_value == 'result'
499
+ end
500
+
501
+ unless result_formula
502
+ raise Delorean::ParseError.new(
503
+ 'result formula is required in blocks',
504
+ context.module_name,
505
+ context.line_no
506
+ )
507
+ end
508
+
509
+ expressions.elements.each do |element|
510
+ element.check(context)
511
+ end
512
+
513
+ b_args.elements.each do |element|
514
+ element.force_undef(context)
515
+ end
516
+ end
517
+
518
+ def rewrite(context, vcode)
519
+ if !respond_to?(:al) || al.text_value.empty?
520
+ args_str = ''
521
+ arg_count = 0
522
+ else
523
+ args_str = al.rewrite(context)
524
+ arg_count = al.arg_count
525
+ end
526
+ if vcode.is_a?(ClassText)
527
+ # FIXME: Do we really need this check here?
528
+ # ruby class call
529
+ class_name = vcode.text
530
+ context.parse_check_call_fn(i.text_value, arg_count, class_name)
531
+ end
532
+
533
+ b_args.elements.each do |element|
534
+ element.force_def(context)
535
+ end
536
+
537
+ block_args_str = if b_args.elements.any?
538
+ block_args = b_args.elements.map do |v|
539
+ v.rewrite(context)
540
+ end
541
+
542
+ "|#{block_args.join(', ')}|"
543
+ else
544
+ ''
545
+ end
546
+
547
+ expr_arr = expressions.elements.map do |v|
548
+ v.rewrite(context)
549
+ end + ["result#{POST}"]
550
+
551
+ expression_str = expr_arr.join('; ')
552
+
553
+ b_args.elements.each do |element|
554
+ element.force_undef(context)
555
+ end
556
+
557
+ block = "{ #{block_args_str} #{expression_str} }"
558
+
559
+ "_instance_call(#{vcode}, '#{i.text_value}', [#{args_str}], _e) #{block}"
560
+ end
561
+ end
562
+
413
563
  class NodeCall < SNode
414
564
  def check(context, *)
415
565
  al.text_value.empty? ? [] : al.check(context)
@@ -18,44 +18,59 @@ module Delorean
18
18
  private
19
19
 
20
20
  def _add_default_methods
21
+ add_method :abs do |method|
22
+ method.called_on Numeric
23
+ end
24
+
25
+ add_method :all? do |method|
26
+ method.called_on Enumerable
27
+ end
28
+
29
+ add_method :any, match_to: :any?
30
+
31
+ add_method :any? do |method|
32
+ method.called_on Enumerable
33
+ end
34
+
21
35
  add_method :attributes do |method|
22
36
  method.called_on ActiveRecord::Base
23
37
  method.called_on ActiveRecord::Relation
24
38
  end
25
39
 
40
+ add_method :beginning_of_month do |method|
41
+ DT_TYPES.each do |type|
42
+ method.called_on type
43
+ end
44
+ end
45
+
46
+ add_method :between, match_to: :between?
47
+
26
48
  add_method :between? do |method|
27
49
  method.called_on String, with: [String, String]
28
50
  method.called_on Numeric, with: [Numeric, Numeric]
29
51
  end
30
52
 
31
- add_method :between, match_to: :between?
53
+ add_method :ceil do |method|
54
+ method.called_on Numeric
55
+ end
32
56
 
33
57
  add_method :compact do |method|
34
58
  method.called_on Array
35
59
  method.called_on Hash
36
60
  end
37
61
 
38
- add_method :to_set do |method|
39
- method.called_on Array
40
- end
41
-
42
- add_method :flatten do |method|
43
- method.called_on Array, with: [NUM_OR_NIL]
62
+ add_method :day do |method|
63
+ DT_TYPES.each do |type|
64
+ method.called_on type
65
+ end
44
66
  end
45
67
 
46
- add_method :length do |method|
68
+ add_method :downcase do |method|
47
69
  method.called_on String
48
- method.called_on Enumerable
49
70
  end
50
71
 
51
- add_method :max do |method|
52
- method.called_on Array
53
- end
54
-
55
- add_method :member, match_to: :member?
56
-
57
- add_method :member? do |method|
58
- method.called_on Enumerable, with: [Object]
72
+ add_method :each_slice do |method|
73
+ method.called_on Array, with: [Integer]
59
74
  end
60
75
 
61
76
  add_method :empty, match_to: :empty?
@@ -64,134 +79,101 @@ module Delorean
64
79
  method.called_on Enumerable
65
80
  end
66
81
 
67
- add_method :except do |method|
68
- method.called_on Hash, with: [String] + [[nil, String]] * 9
69
- end
70
-
71
- add_method :reverse do |method|
72
- method.called_on Array
73
- end
74
-
75
- add_method :slice do |method|
76
- method.called_on Array, with: [Integer, Integer]
77
- end
78
-
79
- add_method :each_slice do |method|
80
- method.called_on Array, with: [Integer]
82
+ add_method :end_of_month do |method|
83
+ DT_TYPES.each do |type|
84
+ method.called_on type
85
+ end
81
86
  end
82
87
 
83
- add_method :sort do |method|
84
- method.called_on Array
88
+ add_method :except do |method|
89
+ method.called_on Hash, with: [String] + [[nil, String]] * 9
85
90
  end
86
91
 
87
- add_method :split do |method|
88
- method.called_on String, with: [String]
92
+ add_method :fetch do |method|
93
+ method.called_on Hash, with: [Object, [Object]]
89
94
  end
90
95
 
91
- add_method :uniq do |method|
92
- method.called_on Array
96
+ add_method :find do |method|
97
+ method.called_on Enumerable
93
98
  end
94
99
 
95
- add_method :sum do |method|
96
- method.called_on Array
100
+ add_method :first do |method|
101
+ method.called_on ActiveRecord::Relation, with: [NUM_OR_NIL]
102
+ method.called_on Enumerable, with: [NUM_OR_NIL]
97
103
  end
98
104
 
99
- add_method :transpose do |method|
100
- method.called_on Array
105
+ add_method :flatten do |method|
106
+ method.called_on Array, with: [NUM_OR_NIL]
101
107
  end
102
108
 
103
- add_method :join do |method|
104
- method.called_on Array, with: [String]
109
+ add_method :floor do |method|
110
+ method.called_on Numeric
105
111
  end
106
112
 
107
- add_method :zip do |method|
108
- method.called_on Array, with: [Array, [Array, nil], [Array, nil]]
113
+ add_method :hour do |method|
114
+ DT_TYPES.each do |type|
115
+ method.called_on type
116
+ end
109
117
  end
110
118
 
111
119
  add_method :index do |method|
112
120
  method.called_on Array, with: [[Object]]
113
121
  end
114
122
 
115
- add_method :product do |method|
116
- method.called_on Array, with: [Array]
117
- end
118
-
119
- add_method :first do |method|
120
- method.called_on ActiveRecord::Relation, with: [NUM_OR_NIL]
121
- method.called_on Enumerable, with: [NUM_OR_NIL]
122
- end
123
-
124
- add_method :last do |method|
125
- method.called_on ActiveRecord::Relation, with: [NUM_OR_NIL]
126
- method.called_on Enumerable, with: [NUM_OR_NIL]
127
- end
128
-
129
123
  add_method :intersection do |method|
130
124
  method.called_on Set, with: [Enumerable]
131
125
  end
132
126
 
133
- add_method :union do |method|
134
- method.called_on Set, with: [Enumerable]
127
+ add_method :iso8601 do |method|
128
+ DT_TYPES.each do |type|
129
+ method.called_on type
130
+ end
135
131
  end
136
132
 
137
- add_method :keys do |method|
138
- method.called_on Hash
133
+ add_method :join do |method|
134
+ method.called_on Array, with: [String]
139
135
  end
140
136
 
141
- add_method :values do |method|
137
+ add_method :keys do |method|
142
138
  method.called_on Hash
143
139
  end
144
140
 
145
- add_method :fetch do |method|
146
- method.called_on Hash, with: [Object, [Object]]
147
- end
148
-
149
- add_method :upcase do |method|
150
- method.called_on String
141
+ add_method :last do |method|
142
+ method.called_on ActiveRecord::Relation, with: [NUM_OR_NIL]
143
+ method.called_on Enumerable, with: [NUM_OR_NIL]
151
144
  end
152
145
 
153
- add_method :downcase do |method|
146
+ add_method :length do |method|
154
147
  method.called_on String
148
+ method.called_on Enumerable
155
149
  end
156
150
 
157
151
  add_method :match do |method|
158
152
  method.called_on String, with: [[String], NUM_OR_NIL]
159
153
  end
160
154
 
161
- add_method :iso8601 do |method|
162
- DT_TYPES.each do |type|
163
- method.called_on type
164
- end
155
+ add_method :max do |method|
156
+ method.called_on Array
165
157
  end
166
158
 
167
- add_method :hour do |method|
168
- DT_TYPES.each do |type|
169
- method.called_on type
170
- end
159
+ add_method :max_by do |method|
160
+ method.called_on Enumerable
171
161
  end
172
162
 
173
- add_method :min do |method|
174
- (DT_TYPES + [Array]).each do |type|
175
- method.called_on type
176
- end
177
- end
163
+ add_method :member, match_to: :member?
178
164
 
179
- add_method :sec do |method|
180
- DT_TYPES.each do |type|
181
- method.called_on type
182
- end
165
+ add_method :member? do |method|
166
+ method.called_on Enumerable, with: [Object]
183
167
  end
184
168
 
185
- add_method :to_date do |method|
186
- (DT_TYPES + [String]).each do |type|
169
+ add_method :min do |method|
170
+ (DT_TYPES + [Array]).each do |type|
187
171
  method.called_on type
188
172
  end
189
173
  end
190
174
 
191
- add_method :to_time do |method|
192
- (DT_TYPES + [String]).each do |type|
193
- method.called_on type
194
- end
175
+ add_method :min_by do |method|
176
+ method.called_on Enumerable
195
177
  end
196
178
 
197
179
  add_method :month do |method|
@@ -200,19 +182,23 @@ module Delorean
200
182
  end
201
183
  end
202
184
 
203
- add_method :day do |method|
185
+ add_method :next_day do |method|
204
186
  DT_TYPES.each do |type|
205
- method.called_on type
187
+ method.called_on type, with: [NUM_OR_NIL]
206
188
  end
207
189
  end
208
190
 
209
- add_method :year do |method|
191
+ add_method :next_month do |method|
210
192
  DT_TYPES.each do |type|
211
- method.called_on type
193
+ method.called_on type, with: [NUM_OR_NIL]
212
194
  end
213
195
  end
214
196
 
215
- add_method :next_month do |method|
197
+ add_method :none? do |method|
198
+ method.called_on Enumerable
199
+ end
200
+
201
+ add_method :prev_day do |method|
216
202
  DT_TYPES.each do |type|
217
203
  method.called_on type, with: [NUM_OR_NIL]
218
204
  end
@@ -224,32 +210,64 @@ module Delorean
224
210
  end
225
211
  end
226
212
 
227
- add_method :beginning_of_month do |method|
228
- DT_TYPES.each do |type|
229
- method.called_on type
230
- end
213
+ add_method :product do |method|
214
+ method.called_on Array, with: [Array]
231
215
  end
232
216
 
233
- add_method :end_of_month do |method|
217
+ add_method :reduce do |method|
218
+ method.called_on Enumerable, with: [[nil, Object]]
219
+ end
220
+
221
+ add_method :reject do |method|
222
+ method.called_on Enumerable
223
+ end
224
+
225
+ add_method :reverse do |method|
226
+ method.called_on Array
227
+ end
228
+
229
+ add_method :round do |method|
230
+ method.called_on Numeric, with: [[nil, Integer]]
231
+ end
232
+
233
+ add_method :sec do |method|
234
234
  DT_TYPES.each do |type|
235
235
  method.called_on type
236
236
  end
237
237
  end
238
238
 
239
- add_method :next_day do |method|
240
- DT_TYPES.each do |type|
241
- method.called_on type, with: [NUM_OR_NIL]
242
- end
239
+ add_method :select do |method|
240
+ method.called_on Enumerable
243
241
  end
244
242
 
245
- add_method :prev_day do |method|
246
- DT_TYPES.each do |type|
247
- method.called_on type, with: [NUM_OR_NIL]
243
+ add_method :slice do |method|
244
+ method.called_on Array, with: [Integer, Integer]
245
+ end
246
+
247
+ add_method :sort do |method|
248
+ method.called_on Array
249
+ end
250
+
251
+ add_method :split do |method|
252
+ method.called_on String, with: [String]
253
+ end
254
+
255
+ add_method :sum do |method|
256
+ method.called_on Array
257
+ end
258
+
259
+ add_method :to_a do |method|
260
+ method.called_on Object
261
+ end
262
+
263
+ add_method :to_d do |method|
264
+ NUM_OR_STR.each do |type|
265
+ method.called_on type
248
266
  end
249
267
  end
250
268
 
251
- add_method :to_i do |method|
252
- (NUM_OR_STR + TI_TYPES).each do |type|
269
+ add_method :to_date do |method|
270
+ (DT_TYPES + [String]).each do |type|
253
271
  method.called_on type
254
272
  end
255
273
  end
@@ -260,42 +278,62 @@ module Delorean
260
278
  end
261
279
  end
262
280
 
263
- add_method :to_d do |method|
264
- NUM_OR_STR.each do |type|
281
+ add_method :to_i do |method|
282
+ (NUM_OR_STR + TI_TYPES).each do |type|
265
283
  method.called_on type
266
284
  end
267
285
  end
268
286
 
269
- add_method :to_s do |method|
287
+ add_method :to_json do |method|
270
288
  method.called_on Object
271
289
  end
272
290
 
273
- add_method :to_a do |method|
291
+ add_method :to_s do |method|
274
292
  method.called_on Object
275
293
  end
276
294
 
277
- add_method :to_json do |method|
278
- method.called_on Object
295
+ add_method :to_set do |method|
296
+ method.called_on Array
279
297
  end
280
298
 
281
- add_method :abs do |method|
282
- method.called_on Numeric
299
+ add_method :to_time do |method|
300
+ (DT_TYPES + [String]).each do |type|
301
+ method.called_on type
302
+ end
283
303
  end
284
304
 
285
- add_method :round do |method|
305
+ add_method :transpose do |method|
306
+ method.called_on Array
307
+ end
308
+
309
+ add_method :truncate do |method|
286
310
  method.called_on Numeric, with: [[nil, Integer]]
287
311
  end
288
312
 
289
- add_method :ceil do |method|
290
- method.called_on Numeric
313
+ add_method :union do |method|
314
+ method.called_on Set, with: [Enumerable]
291
315
  end
292
316
 
293
- add_method :floor do |method|
294
- method.called_on Numeric
317
+ add_method :uniq do |method|
318
+ method.called_on Enumerable
295
319
  end
296
320
 
297
- add_method :truncate do |method|
298
- method.called_on Numeric, with: [[nil, Integer]]
321
+ add_method :upcase do |method|
322
+ method.called_on String
323
+ end
324
+
325
+ add_method :values do |method|
326
+ method.called_on Hash
327
+ end
328
+
329
+ add_method :year do |method|
330
+ DT_TYPES.each do |type|
331
+ method.called_on type
332
+ end
333
+ end
334
+
335
+ add_method :zip do |method|
336
+ method.called_on Array, with: [Array, [Array, nil], [Array, nil]]
299
337
  end
300
338
  end
301
339
  end