delorean_lang 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDc1Y2Y0NzUxOGNkMzlmNmE2Y2M5OGM3YjBiOGNiNjBjZTM5OTY1Ng==
4
+ YWFmZDRkMDU1OTkwMWE1NjVmN2NjYTQ2Yzg3MDZiYjQwMTFkYTM2OQ==
5
5
  data.tar.gz: !binary |-
6
- ZDgxMGNiOTM4NDhhM2Q3NDM0ZWQ4NjU3NDIzMDc4NzNlNDE4YzUxZg==
6
+ NTY5YmVjNmY3NDgwNDUzOTU0NjIxODhlZmJhZTdmNzVmN2FiNDMyMQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MjM0ODI5NmY0NmU4MGE1YWQ5ZmVlMDFkNThmYzdiNGQxNjJmZmE3OGZiNzNl
10
- NmRlYzQwZTcyZjNmOThlNTExNDNmZmRiZmQ1MTMyNWFlODMzOTk2NjQzYWNi
11
- ZDNjNmNlYzlmNzk5ZTU0Nzk4Y2Q5YzYwNmEzOWFlOWQyYWI0ODk=
9
+ YmVjYWJlMmRmYzFjNTZkOThjYTg4YzM1MzMxODFmNThjNTNkOWZmNTllNTEy
10
+ MDJmNWUyZjY5ZjQxZWRlNmJkZmQyZDU4MDI2OTZkMzExMDFkYmMyOTY0MmQ2
11
+ Mzc5ZTQyZjdlODM0OWU0OWE3ZTkyMjQyZWQ5NzgwMTBjYmEzNmE=
12
12
  data.tar.gz: !binary |-
13
- NGQwM2M5YWU2MTAwNTlhNGE0ZmU4YjI4NmU5OWE4OTkwNjk0MGRlYTVhZGUz
14
- ZDQ3ZTFlNjQ1OTU1MWExZDM0YjI0ZDRiZmMzMzFmNzkwNGM1YThhMjg2MmEz
15
- NjZjMjAxZmM1ZmIwNjBjMjY0ZDAyMTc5NTk3ZGFlMzE0MzZlZmU=
13
+ YmIzN2IxNGU0OTQ2MGVmYzVjMTUzZWJiMjRjM2VhYmQyNGNiNmEzNDk5YzNm
14
+ NmI2ZDU1M2JlZmY2YmM4ZDllOTIzNzZhNGNmM2FlOTNiNTBmODk4OTQyY2Y1
15
+ ODBlZDJmYWNkOGFkNWYwM2U2ZjQ2MjdhODNhNGIzNTU4ZmFiYzE=
@@ -7,62 +7,65 @@ module Delorean
7
7
  # hash. The whole whitelist mechanism should be eventually
8
8
  # rethought.
9
9
  RUBY_WHITELIST = {
10
- compact: [Array],
11
- flatten: [Array, [Fixnum, nil]],
12
- length: [[Array, String]],
13
- max: [Array],
14
- member: "member?",
15
- member?: [Array, [Fixnum, String]],
16
- reverse: [Array],
17
- slice: [Array, Fixnum, Fixnum],
18
- sort: [Array],
19
- split: [String, String],
20
- uniq: [Array],
21
- sum: [Array],
22
- zip: [Array, [Array, Array, Array]],
23
- index: [Array, [Integer, Numeric, String, Array, Fixnum]],
24
- product: [Array, Array],
25
- first: [Enumerable, [nil, Fixnum]],
26
-
27
- keys: [Hash],
28
- values: [Hash],
29
- upcase: [String],
30
- downcase: [String],
31
- match: [String, [String], [nil, Fixnum]],
32
-
33
- hour: [[Date, Time, ActiveSupport::TimeWithZone]],
34
- min: [[Date, Time, ActiveSupport::TimeWithZone, Array]],
35
- sec: [[Date, Time, ActiveSupport::TimeWithZone]],
36
- to_date: [[Date, Time, ActiveSupport::TimeWithZone]],
37
-
38
- month: [[Date, Time, ActiveSupport::TimeWithZone]],
39
- day: [[Date, Time, ActiveSupport::TimeWithZone]],
40
- year: [[Date, Time, ActiveSupport::TimeWithZone]],
41
-
42
- next_month: [[Date, Time, ActiveSupport::TimeWithZone],
43
- [nil, Fixnum],
44
- ],
45
- prev_month: [[Date, Time, ActiveSupport::TimeWithZone],
46
- [nil, Fixnum],
47
- ],
10
+ compact: [Array],
11
+ to_set: [Array],
12
+ flatten: [Array, [Fixnum, nil]],
13
+ length: [[Array, String]],
14
+ max: [Array],
15
+ member: "member?",
16
+ member?: [Array, [Fixnum, String]],
17
+ reverse: [Array],
18
+ slice: [Array, Fixnum, Fixnum],
19
+ sort: [Array],
20
+ split: [String, String],
21
+ uniq: [Array],
22
+ sum: [Array],
23
+ zip: [Array, [Array, Array, Array]],
24
+ index: [Array, [Integer, Numeric, String, Array, Fixnum]],
25
+ product: [Array, Array],
26
+ first: [Enumerable, [nil, Fixnum]],
27
+ intersection: [Set, Enumerable],
28
+ union: [Set, Enumerable],
29
+
30
+ keys: [Hash],
31
+ values: [Hash],
32
+ upcase: [String],
33
+ downcase: [String],
34
+ match: [String, [String], [nil, Fixnum]],
35
+
36
+ hour: [[Date, Time, ActiveSupport::TimeWithZone]],
37
+ min: [[Date, Time, ActiveSupport::TimeWithZone, Array]],
38
+ sec: [[Date, Time, ActiveSupport::TimeWithZone]],
39
+ to_date: [[Date, Time, ActiveSupport::TimeWithZone]],
40
+
41
+ month: [[Date, Time, ActiveSupport::TimeWithZone]],
42
+ day: [[Date, Time, ActiveSupport::TimeWithZone]],
43
+ year: [[Date, Time, ActiveSupport::TimeWithZone]],
44
+
45
+ next_month: [[Date, Time, ActiveSupport::TimeWithZone],
46
+ [nil, Fixnum],
47
+ ],
48
+ prev_month: [[Date, Time, ActiveSupport::TimeWithZone],
49
+ [nil, Fixnum],
50
+ ],
48
51
 
49
52
  beginning_of_month: [[Date, Time, ActiveSupport::TimeWithZone]],
50
53
 
51
54
  end_of_month: [[Date, Time, ActiveSupport::TimeWithZone]],
52
55
 
53
- next_day: [[Date, Time, ActiveSupport::TimeWithZone],
54
- [nil, Fixnum],
55
- ],
56
- prev_day: [[Date, Time, ActiveSupport::TimeWithZone],
57
- [nil, Fixnum],
58
- ],
59
-
60
- to_i: [[Numeric, String]],
61
- to_f: [[Numeric, String]],
62
- to_d: [[Numeric, String]],
63
- to_s: [Object],
64
- abs: [Numeric],
65
- round: [Numeric, [nil, Integer]],
56
+ next_day: [[Date, Time, ActiveSupport::TimeWithZone],
57
+ [nil, Fixnum],
58
+ ],
59
+ prev_day: [[Date, Time, ActiveSupport::TimeWithZone],
60
+ [nil, Fixnum],
61
+ ],
62
+
63
+ to_i: [[Numeric, String]],
64
+ to_f: [[Numeric, String]],
65
+ to_d: [[Numeric, String]],
66
+ to_s: [Object],
67
+ abs: [Numeric],
68
+ round: [Numeric, [nil, Integer]],
66
69
  }
67
70
 
68
71
  module BaseModule
@@ -110,14 +113,6 @@ module Delorean
110
113
 
111
114
  return obj.send(attr.to_sym) if
112
115
  klass.reflect_on_all_associations.map(&:name).member? attr.to_sym
113
-
114
- # FIXME: should call _instance_call for other types as well.
115
- # Too lazy to implement this now.
116
- begin
117
- return _instance_call(obj, attr, [])
118
- rescue
119
- raise InvalidGetAttribute, "ActiveRecord lookup '#{attr}' on #{obj}"
120
- end
121
116
  elsif obj.instance_of?(NodeCall)
122
117
  return obj.evaluate(attr)
123
118
  elsif obj.instance_of?(Hash)
@@ -126,8 +121,13 @@ module Delorean
126
121
  elsif obj.instance_of?(Class) && (obj < BaseClass)
127
122
  return obj.send((attr + POST).to_sym, _e)
128
123
  end
129
- raise InvalidGetAttribute,
130
- "bad attribute lookup '#{attr}' on <#{obj.class}> #{obj}"
124
+
125
+ begin
126
+ return _instance_call(obj, attr, [], _e)
127
+ rescue
128
+ raise InvalidGetAttribute,
129
+ "bad attribute lookup '#{attr}' on <#{obj.class}> #{obj}"
130
+ end
131
131
  end
132
132
 
133
133
  ######################################################################
@@ -156,7 +156,7 @@ module Delorean
156
156
  def self._sanitize_hash(_e)
157
157
  _e.each_with_object({}) do
158
158
  |(k,v), h|
159
- h[k] = v if k =~ /\A[a-z][A-Za-z0-9_]*\z/
159
+ h[k] = v if k.is_a?(Integer) || k =~ /\A[a-z][A-Za-z0-9_]*\z/
160
160
  end
161
161
  end
162
162
 
@@ -182,19 +182,26 @@ module Delorean
182
182
 
183
183
  ######################################################################
184
184
 
185
- def self._instance_call(obj, method, args)
185
+ def self._instance_call(obj, method, args, _e)
186
186
  begin
187
187
  msg = method.to_sym
188
188
  rescue NoMethodError
189
189
  raise "bad method #{method}"
190
190
  end
191
191
 
192
+ # FIXME: this is pretty hacky -- should probably merge
193
+ # RUBY_WHITELIST and SIG mechanisms.
194
+ if obj.is_a?(Class)
195
+ _e[:_engine].parse_check_call_fn(method, args.count, obj)
196
+ return obj.send(msg, *args)
197
+ end
198
+
192
199
  sig = RUBY_WHITELIST[msg]
193
200
 
194
201
  raise "no such method #{method}" unless sig
195
202
 
196
203
  # if sig is a string, then method mapped to another name
197
- return _instance_call(obj, sig, args) if sig.is_a? String
204
+ return _instance_call(obj, sig, args, _e) if sig.is_a? String
198
205
 
199
206
  raise "too many args to #{method}" if args.length>(sig.length-1)
200
207
 
@@ -1133,7 +1133,19 @@ module Delorean
1133
1133
  end
1134
1134
  s31 << r33
1135
1135
  if r33
1136
- r35 = _nt_identifier
1136
+ i35 = index
1137
+ r36 = _nt_identifier
1138
+ if r36
1139
+ r35 = r36
1140
+ else
1141
+ r37 = _nt_integer
1142
+ if r37
1143
+ r35 = r37
1144
+ else
1145
+ @index = i35
1146
+ r35 = nil
1147
+ end
1148
+ end
1137
1149
  s31 << r35
1138
1150
  end
1139
1151
  end
@@ -2288,136 +2300,141 @@ module Delorean
2288
2300
  end
2289
2301
 
2290
2302
  i0 = index
2291
- r1 = _nt_number
2303
+ r1 = _nt_decimal
2292
2304
  if r1
2293
2305
  r0 = r1
2294
2306
  else
2295
- r2 = _nt_string
2307
+ r2 = _nt_integer
2296
2308
  if r2
2297
2309
  r0 = r2
2298
2310
  else
2299
- r3 = _nt_boolean
2311
+ r3 = _nt_string
2300
2312
  if r3
2301
2313
  r0 = r3
2302
2314
  else
2303
- r4 = _nt_nil_val
2315
+ r4 = _nt_boolean
2304
2316
  if r4
2305
2317
  r0 = r4
2306
2318
  else
2307
- r5 = _nt_identifier
2319
+ r5 = _nt_nil_val
2308
2320
  if r5
2309
2321
  r0 = r5
2310
2322
  else
2311
- r6 = _nt_self
2323
+ r6 = _nt_identifier
2312
2324
  if r6
2313
2325
  r0 = r6
2314
2326
  else
2315
- r7 = _nt_list_expr
2327
+ r7 = _nt_self
2316
2328
  if r7
2317
2329
  r0 = r7
2318
2330
  else
2319
- r8 = _nt_set_expr
2331
+ r8 = _nt_list_expr
2320
2332
  if r8
2321
2333
  r0 = r8
2322
2334
  else
2323
- r9 = _nt_hash_expr
2335
+ r9 = _nt_set_expr
2324
2336
  if r9
2325
2337
  r0 = r9
2326
2338
  else
2327
- i10, s10 = index, []
2328
- i12, s12 = index, []
2329
- r13 = _nt_class_name
2330
- s12 << r13
2331
- if r13
2332
- if has_terminal?('::', false, index)
2333
- r14 = instantiate_node(SyntaxNode,input, index...(index + 2))
2334
- @index += 2
2335
- else
2336
- terminal_parse_failure('::')
2337
- r14 = nil
2338
- end
2339
- s12 << r14
2340
- end
2341
- if s12.last
2342
- r12 = instantiate_node(SyntaxNode,input, i12...index, s12)
2343
- r12.extend(Value0)
2344
- else
2345
- @index = i12
2346
- r12 = nil
2347
- end
2348
- if r12
2349
- r11 = r12
2350
- else
2351
- r11 = instantiate_node(SyntaxNode,input, index...index)
2352
- end
2353
- s10 << r11
2354
- if r11
2355
- r15 = _nt_class_name
2356
- s10 << r15
2357
- end
2358
- if s10.last
2359
- r10 = instantiate_node(NodeAsValue,input, i10...index, s10)
2360
- r10.extend(Value1)
2361
- else
2362
- @index = i10
2363
- r10 = nil
2364
- end
2339
+ r10 = _nt_hash_expr
2365
2340
  if r10
2366
2341
  r0 = r10
2367
2342
  else
2368
- i16, s16 = index, []
2369
- if has_terminal?('(', false, index)
2370
- r17 = instantiate_node(SyntaxNode,input, index...(index + 1))
2371
- @index += 1
2343
+ i11, s11 = index, []
2344
+ i13, s13 = index, []
2345
+ r14 = _nt_class_name
2346
+ s13 << r14
2347
+ if r14
2348
+ if has_terminal?('::', false, index)
2349
+ r15 = instantiate_node(SyntaxNode,input, index...(index + 2))
2350
+ @index += 2
2351
+ else
2352
+ terminal_parse_failure('::')
2353
+ r15 = nil
2354
+ end
2355
+ s13 << r15
2356
+ end
2357
+ if s13.last
2358
+ r13 = instantiate_node(SyntaxNode,input, i13...index, s13)
2359
+ r13.extend(Value0)
2360
+ else
2361
+ @index = i13
2362
+ r13 = nil
2363
+ end
2364
+ if r13
2365
+ r12 = r13
2366
+ else
2367
+ r12 = instantiate_node(SyntaxNode,input, index...index)
2368
+ end
2369
+ s11 << r12
2370
+ if r12
2371
+ r16 = _nt_class_name
2372
+ s11 << r16
2373
+ end
2374
+ if s11.last
2375
+ r11 = instantiate_node(NodeAsValue,input, i11...index, s11)
2376
+ r11.extend(Value1)
2372
2377
  else
2373
- terminal_parse_failure('(')
2374
- r17 = nil
2378
+ @index = i11
2379
+ r11 = nil
2375
2380
  end
2376
- s16 << r17
2377
- if r17
2378
- r19 = _nt_sp
2379
- if r19
2380
- r18 = r19
2381
+ if r11
2382
+ r0 = r11
2383
+ else
2384
+ i17, s17 = index, []
2385
+ if has_terminal?('(', false, index)
2386
+ r18 = instantiate_node(SyntaxNode,input, index...(index + 1))
2387
+ @index += 1
2381
2388
  else
2382
- r18 = instantiate_node(SyntaxNode,input, index...index)
2389
+ terminal_parse_failure('(')
2390
+ r18 = nil
2383
2391
  end
2384
- s16 << r18
2392
+ s17 << r18
2385
2393
  if r18
2386
- r20 = _nt_expression
2387
- s16 << r20
2394
+ r20 = _nt_sp
2388
2395
  if r20
2389
- r22 = _nt_sp
2390
- if r22
2391
- r21 = r22
2392
- else
2393
- r21 = instantiate_node(SyntaxNode,input, index...index)
2394
- end
2395
- s16 << r21
2396
+ r19 = r20
2397
+ else
2398
+ r19 = instantiate_node(SyntaxNode,input, index...index)
2399
+ end
2400
+ s17 << r19
2401
+ if r19
2402
+ r21 = _nt_expression
2403
+ s17 << r21
2396
2404
  if r21
2397
- if has_terminal?(')', false, index)
2398
- r23 = instantiate_node(SyntaxNode,input, index...(index + 1))
2399
- @index += 1
2405
+ r23 = _nt_sp
2406
+ if r23
2407
+ r22 = r23
2400
2408
  else
2401
- terminal_parse_failure(')')
2402
- r23 = nil
2409
+ r22 = instantiate_node(SyntaxNode,input, index...index)
2410
+ end
2411
+ s17 << r22
2412
+ if r22
2413
+ if has_terminal?(')', false, index)
2414
+ r24 = instantiate_node(SyntaxNode,input, index...(index + 1))
2415
+ @index += 1
2416
+ else
2417
+ terminal_parse_failure(')')
2418
+ r24 = nil
2419
+ end
2420
+ s17 << r24
2403
2421
  end
2404
- s16 << r23
2405
2422
  end
2406
2423
  end
2407
2424
  end
2408
- end
2409
- if s16.last
2410
- r16 = instantiate_node(Expr,input, i16...index, s16)
2411
- r16.extend(Value2)
2412
- else
2413
- @index = i16
2414
- r16 = nil
2415
- end
2416
- if r16
2417
- r0 = r16
2418
- else
2419
- @index = i0
2420
- r0 = nil
2425
+ if s17.last
2426
+ r17 = instantiate_node(Expr,input, i17...index, s17)
2427
+ r17.extend(Value2)
2428
+ else
2429
+ @index = i17
2430
+ r17 = nil
2431
+ end
2432
+ if r17
2433
+ r0 = r17
2434
+ else
2435
+ @index = i0
2436
+ r0 = nil
2437
+ end
2421
2438
  end
2422
2439
  end
2423
2440
  end
@@ -2810,37 +2827,11 @@ module Delorean
2810
2827
  r0
2811
2828
  end
2812
2829
 
2813
- def _nt_number
2814
- start_index = index
2815
- if node_cache[:number].has_key?(index)
2816
- cached = node_cache[:number][index]
2817
- if cached
2818
- cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
2819
- @index = cached.interval.end
2820
- end
2821
- return cached
2822
- end
2823
-
2824
- i0 = index
2825
- r1 = _nt_decimal
2826
- if r1
2827
- r0 = r1
2828
- else
2829
- r2 = _nt_integer
2830
- if r2
2831
- r0 = r2
2832
- else
2833
- @index = i0
2834
- r0 = nil
2835
- end
2830
+ module Decimal0
2831
+ def i
2832
+ elements[0]
2836
2833
  end
2837
2834
 
2838
- node_cache[:number][start_index] = r0
2839
-
2840
- r0
2841
- end
2842
-
2843
- module Decimal0
2844
2835
  end
2845
2836
 
2846
2837
  def _nt_decimal
@@ -2855,58 +2846,39 @@ module Delorean
2855
2846
  end
2856
2847
 
2857
2848
  i0, s0 = index, []
2858
- s1, i1 = [], index
2859
- loop do
2860
- if has_terminal?('\G[0-9]', true, index)
2861
- r2 = true
2862
- @index += 1
2863
- else
2864
- r2 = nil
2865
- end
2866
- if r2
2867
- s1 << r2
2868
- else
2869
- break
2870
- end
2871
- end
2872
- if s1.empty?
2873
- @index = i1
2874
- r1 = nil
2875
- else
2876
- r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
2877
- end
2849
+ r1 = _nt_integer
2878
2850
  s0 << r1
2879
2851
  if r1
2880
2852
  if has_terminal?('.', false, index)
2881
- r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
2853
+ r2 = instantiate_node(SyntaxNode,input, index...(index + 1))
2882
2854
  @index += 1
2883
2855
  else
2884
2856
  terminal_parse_failure('.')
2885
- r3 = nil
2857
+ r2 = nil
2886
2858
  end
2887
- s0 << r3
2888
- if r3
2889
- s4, i4 = [], index
2859
+ s0 << r2
2860
+ if r2
2861
+ s3, i3 = [], index
2890
2862
  loop do
2891
2863
  if has_terminal?('\G[0-9]', true, index)
2892
- r5 = true
2864
+ r4 = true
2893
2865
  @index += 1
2894
2866
  else
2895
- r5 = nil
2867
+ r4 = nil
2896
2868
  end
2897
- if r5
2898
- s4 << r5
2869
+ if r4
2870
+ s3 << r4
2899
2871
  else
2900
2872
  break
2901
2873
  end
2902
2874
  end
2903
- if s4.empty?
2904
- @index = i4
2905
- r4 = nil
2875
+ if s3.empty?
2876
+ @index = i3
2877
+ r3 = nil
2906
2878
  else
2907
- r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
2879
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
2908
2880
  end
2909
- s0 << r4
2881
+ s0 << r3
2910
2882
  end
2911
2883
  end
2912
2884
  if s0.last
@@ -2922,6 +2894,9 @@ module Delorean
2922
2894
  r0
2923
2895
  end
2924
2896
 
2897
+ module Integer0
2898
+ end
2899
+
2925
2900
  def _nt_integer
2926
2901
  start_index = index
2927
2902
  if node_cache[:integer].has_key?(index)
@@ -2933,25 +2908,56 @@ module Delorean
2933
2908
  return cached
2934
2909
  end
2935
2910
 
2936
- s0, i0 = [], index
2937
- loop do
2938
- if has_terminal?('\G[0-9]', true, index)
2939
- r1 = true
2911
+ i0 = index
2912
+ if has_terminal?('0', false, index)
2913
+ r1 = instantiate_node(Literal,input, index...(index + 1))
2914
+ @index += 1
2915
+ else
2916
+ terminal_parse_failure('0')
2917
+ r1 = nil
2918
+ end
2919
+ if r1
2920
+ r0 = r1
2921
+ else
2922
+ i2, s2 = index, []
2923
+ if has_terminal?('\G[1-9]', true, index)
2924
+ r3 = true
2940
2925
  @index += 1
2941
2926
  else
2942
- r1 = nil
2927
+ r3 = nil
2943
2928
  end
2944
- if r1
2945
- s0 << r1
2929
+ s2 << r3
2930
+ if r3
2931
+ s4, i4 = [], index
2932
+ loop do
2933
+ if has_terminal?('\G[0-9]', true, index)
2934
+ r5 = true
2935
+ @index += 1
2936
+ else
2937
+ r5 = nil
2938
+ end
2939
+ if r5
2940
+ s4 << r5
2941
+ else
2942
+ break
2943
+ end
2944
+ end
2945
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
2946
+ s2 << r4
2947
+ end
2948
+ if s2.last
2949
+ r2 = instantiate_node(Literal,input, i2...index, s2)
2950
+ r2.extend(Integer0)
2946
2951
  else
2947
- break
2952
+ @index = i2
2953
+ r2 = nil
2954
+ end
2955
+ if r2
2956
+ r0 = r2
2957
+ else
2958
+ @index = i0
2959
+ r0 = nil
2948
2960
  end
2949
- end
2950
- if s0.empty?
2951
- @index = i0
2952
- r0 = nil
2953
- else
2954
- r0 = instantiate_node(Literal,input, i0...index, s0)
2955
2961
  end
2956
2962
 
2957
2963
  node_cache[:integer][start_index] = r0
@@ -3267,7 +3273,7 @@ module Delorean
3267
3273
  end
3268
3274
  end
3269
3275
  if s1.last
3270
- r1 = instantiate_node(DString,input, i1...index, s1)
3276
+ r1 = instantiate_node(IString,input, i1...index, s1)
3271
3277
  r1.extend(String1)
3272
3278
  else
3273
3279
  @index = i1
@@ -52,7 +52,7 @@ grammar Delorean
52
52
  /
53
53
  '.' sp? i:identifier '(' sp? al:kw_args? sp? ')' <Call>
54
54
  /
55
- '.' sp? i:identifier <GetAttr>
55
+ '.' sp? i:(identifier / integer) <GetAttr>
56
56
  end
57
57
 
58
58
  rule list_expr
@@ -92,7 +92,8 @@ grammar Delorean
92
92
  # Arrays). So, be cautious about which opertaions are added.
93
93
  rule binary_op
94
94
  '==' / '!=' / '>=' / '<=' / '&&' / '||' /
95
- '>' / '<' / '+' / '-' / '*' / '/' / '%' / '&' / '^' / '|'
95
+ '>' / '<' / '+' / '-' / '*' / '/' / '%' /
96
+ '&' / '^' / '|'
96
97
  end
97
98
 
98
99
  rule unary_op
@@ -100,7 +101,8 @@ grammar Delorean
100
101
  end
101
102
 
102
103
  rule value
103
- number /
104
+ decimal /
105
+ integer /
104
106
  string /
105
107
  boolean /
106
108
  nil_val /
@@ -110,7 +112,7 @@ grammar Delorean
110
112
  set_expr /
111
113
  hash_expr /
112
114
  mod:(m:class_name '::')? c:class_name <NodeAsValue> /
113
- '(' sp? e:expression sp? ')' <Expr>
115
+ '(' sp? e:expression sp? ')' <Expr>
114
116
  end
115
117
 
116
118
  rule fn_args
@@ -118,23 +120,21 @@ grammar Delorean
118
120
  end
119
121
 
120
122
  rule hash_args
121
- e0:expression sp? ':' sp? e1:expression args_rest:(sp? ',' sp? al:hash_args?)? <HashArgs>
123
+ e0:expression sp? ':' sp? e1:expression
124
+ args_rest:(sp? ',' sp? al:hash_args?)? <HashArgs>
122
125
  end
123
126
 
124
127
  rule kw_args
125
- k:(i:identifier sp? '=' sp?)? arg0:expression args_rest:(sp? ',' sp? al:kw_args?)? <KwArgs>
126
- end
127
-
128
- rule number
129
- decimal / integer
128
+ k:(i:identifier sp? '=' sp?)? arg0:expression
129
+ args_rest:(sp? ',' sp? al:kw_args?)? <KwArgs>
130
130
  end
131
131
 
132
132
  rule decimal
133
- [0-9]+ '.' [0-9]+ <Literal>
133
+ i:integer '.' [0-9]+ <Literal>
134
134
  end
135
135
 
136
136
  rule integer
137
- [0-9]+ <Literal>
137
+ '0' <Literal> / [1-9] [0-9]* <Literal>
138
138
  end
139
139
 
140
140
  rule identifier
@@ -163,7 +163,7 @@ grammar Delorean
163
163
  end
164
164
 
165
165
  rule string
166
- '"' ('\"' / !'"' .)* '"' <DString>
166
+ '"' ('\"' / !'"' .)* '"' <IString>
167
167
  /
168
168
  "'" [^']* "'" <DString>
169
169
  end
@@ -189,7 +189,14 @@ module Delorean
189
189
  end
190
190
 
191
191
  def parse_check_call_fn(fn, argcount, class_name=nil)
192
- klass = class_name ? parse_class(class_name) : (@m::BaseClass)
192
+ klass = case class_name
193
+ when nil
194
+ @m::BaseClass
195
+ when String
196
+ parse_class(class_name)
197
+ else
198
+ class_name
199
+ end
193
200
 
194
201
  err(UndefinedFunctionError, "Function #{fn} not found") unless
195
202
  klass.methods.member? fn.to_sym
@@ -105,8 +105,7 @@ eos
105
105
  # an attr is defined as a class function on the node class.
106
106
  "class #{context.last_node}; " +
107
107
  "def self.#{i.text_value}#{POST}(_e); " +
108
- "_e[self.name+'.#{i.text_value}'] ||= " +
109
- e.rewrite(context) + "; end; end;"
108
+ "_e[self.name+'.#{i.text_value}'] ||= #{e.rewrite(context)}; end; end;"
110
109
  end
111
110
  end
112
111
 
@@ -116,7 +115,19 @@ eos
116
115
  end
117
116
 
118
117
  def rewrite(context)
119
- "(" + e.rewrite(context) + ")"
118
+ "(#{e.rewrite(context)})"
119
+ end
120
+ end
121
+
122
+ class ClassText
123
+ attr_reader :text
124
+
125
+ def initialize(text)
126
+ @text = text
127
+ end
128
+
129
+ def to_s
130
+ text
120
131
  end
121
132
  end
122
133
 
@@ -140,9 +151,9 @@ eos
140
151
  context.parse_check_defined_mod_node(node_name, mname)
141
152
  context.super_name(node_name, mname)
142
153
  rescue UndefinedError, ParseError
143
- # kind of hacky, we wrap the class name in a list so Call will
144
- # be able to tell it apart from a regular value.
145
- [text_value]
154
+ # FIXME: wrap the class name so Call will be able to tell it
155
+ # apart from a regular value.
156
+ ClassText.new(text_value)
146
157
  end
147
158
  end
148
159
  end
@@ -213,6 +224,16 @@ eos
213
224
  end
214
225
  end
215
226
 
227
+ class IString < Literal
228
+ def rewrite(context)
229
+ # FIXME: hacky to just fail
230
+ raise "String interpolation not supported" if text_value =~ /\#\{.*\}/
231
+
232
+ # FIXME: syntax check?
233
+ text_value
234
+ end
235
+ end
236
+
216
237
  class DString < Literal
217
238
  def rewrite(context)
218
239
  # remove the quotes and requote. We don't want the likes of #{}
@@ -275,7 +296,9 @@ eos
275
296
  end
276
297
 
277
298
  def rewrite(context, vcode)
278
- "_get_attr(#{vcode}, '#{i.text_value}', _e)"
299
+ attr = i.text_value
300
+ attr = "'#{attr}'" unless attr =~ /\A[0-9]+\z/
301
+ "_get_attr(#{vcode}, #{attr}, _e)"
279
302
  end
280
303
  end
281
304
 
@@ -293,13 +316,13 @@ eos
293
316
 
294
317
  args_str = args.reverse.join(',')
295
318
 
296
- if vcode.is_a? Array
319
+ if vcode.is_a?(ClassText)
297
320
  # ruby class call
298
- class_name = vcode[0]
321
+ class_name = vcode.text
299
322
  context.parse_check_call_fn(i.text_value, args.count, class_name)
300
323
  "#{class_name}.#{i.text_value}(#{args_str})"
301
324
  else
302
- "_instance_call(#{vcode}, '#{i.text_value}', [#{args_str}])"
325
+ "_instance_call(#{vcode}, '#{i.text_value}', [#{args_str}], _e)"
303
326
  end
304
327
 
305
328
  end
@@ -314,10 +337,9 @@ eos
314
337
  def rewrite(context, node_name)
315
338
  args, kw = al.text_value.empty? ? [[], {}] : al.rewrite(context)
316
339
 
317
- raise "No positional arguments to node call" unless
318
- args.empty?
319
-
320
- kw_str = kw.map {|k, v| "'#{k}' => #{v}"}.join(',')
340
+ kw_str =
341
+ (kw.map {|k, v| "'#{k}' => #{v}"} +
342
+ args.each_with_index.map {|v, i| "#{i} => #{v}"}).join(',')
321
343
 
322
344
  "_node_call(#{node_name}, _e, {#{kw_str}})"
323
345
  end
@@ -331,13 +353,13 @@ eos
331
353
  end
332
354
 
333
355
  def rewrite(context)
334
- attr_list = ga.text_value.split('.')
356
+ attrs = ga.text_value.split('.')
335
357
 
336
358
  # If ga.text_value is not "", then we need to drop the 1st
337
359
  # element since it'll be "".
338
- attr_list.shift
360
+ attrs.shift
339
361
 
340
- attr_list.inject(v.rewrite(context)) {|x, y| "_get_attr(#{x}, '#{y}', _e)"}
362
+ attrs.inject(v.rewrite(context)) {|x, y| "_get_attr(#{x}, '#{y}', _e)"}
341
363
  end
342
364
  end
343
365
 
@@ -403,7 +425,7 @@ eos
403
425
  def rewrite(context)
404
426
  res = "(#{e1.rewrite(context)})"
405
427
  context.parse_define_var(i.text_value)
406
- res += ".select{|#{i.rewrite(context)}| (#{ifexp.e3.rewrite(context)})}" if
428
+ res += ".select{|#{i.rewrite(context)}|(#{ifexp.e3.rewrite(context)})}" if
407
429
  defined?(ifexp.e3)
408
430
  res += ".map{|#{i.rewrite(context)}| (#{e2.rewrite(context)}) }"
409
431
  context.parse_undef_var(i.text_value)
@@ -1,3 +1,3 @@
1
1
  module Delorean
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
@@ -40,6 +40,15 @@ describe "Delorean" do
40
40
  r.should == -122
41
41
  end
42
42
 
43
+ it "proper string interpolation" do
44
+ engine.parse defn("A:",
45
+ ' a = "\n123\n"',
46
+ )
47
+
48
+ r = engine.evaluate("A", "a")
49
+ r.should == "\n123\n"
50
+ end
51
+
43
52
  it "should handle getattr in expressions" do
44
53
  engine.parse defn("A:",
45
54
  " a = {'x':123, 'y':456, 'z':789}",
@@ -48,6 +57,14 @@ describe "Delorean" do
48
57
  engine.evaluate_attrs("A", ["b"]).should == [123*456-789]
49
58
  end
50
59
 
60
+ it "should handle numeric getattr" do
61
+ engine.parse defn("A:",
62
+ " a = {1:123, 0:456, 'z':789, 2: {'a':444}}",
63
+ " b = A.a.1 * A.a.0 - A.a.z - A.a.2.a",
64
+ )
65
+ engine.evaluate_attrs("A", ["b"]).should == [123*456-789-444]
66
+ end
67
+
51
68
  it "should be able to evaluate multiple node attrs" do
52
69
  engine.parse defn("A:",
53
70
  " a =? 123",
@@ -63,7 +80,7 @@ describe "Delorean" do
63
80
  it "should give error when accessing undefined attr" do
64
81
  engine.parse defn("A:",
65
82
  " a = 1",
66
- " c = a.to_s",
83
+ " c = a.to_ss",
67
84
  )
68
85
 
69
86
  lambda {
@@ -71,6 +88,15 @@ describe "Delorean" do
71
88
  }.should raise_error(Delorean::InvalidGetAttribute)
72
89
  end
73
90
 
91
+ it "should be able to call 0-ary functions without ()" do
92
+ engine.parse defn("A:",
93
+ " a = 1",
94
+ " d = a.to_s",
95
+ )
96
+
97
+ engine.evaluate("A", "d").should == "1"
98
+ end
99
+
74
100
  it "should handle default param values" do
75
101
  engine.parse defn("A:",
76
102
  " a =? 123",
@@ -170,6 +196,16 @@ describe "Delorean" do
170
196
  res["backtrace"].should == [["XXX", 2, "b"]]
171
197
  end
172
198
 
199
+ it "should handle optional args to external fns" do
200
+ engine.parse defn("A:",
201
+ " b = Dummy.one_or_two(['a', 'b'])",
202
+ " c = Dummy.one_or_two([1,2,3], ['a', 'b'])",
203
+ )
204
+
205
+ engine.evaluate("A", "b").should == [['a', 'b'], nil]
206
+ engine.evaluate("A", "c").should == [[1,2,3], ['a', 'b']]
207
+ end
208
+
173
209
  it "should handle operator precedence properly" do
174
210
  engine.parse defn("A:",
175
211
  " b = 3+2*4-1",
@@ -216,6 +252,18 @@ describe "Delorean" do
216
252
  r.should == 123*123 + 5
217
253
  end
218
254
 
255
+ it "should be able to access nodes and node attrs dynamically " do
256
+ engine.parse defn("A:",
257
+ " b = 123",
258
+ "B:",
259
+ " b = A",
260
+ " c = b.b * 456",
261
+ )
262
+
263
+ r = engine.evaluate("B", "c")
264
+ r.should == 123*456
265
+ end
266
+
219
267
  it "should be able to call class methods on ActiveRecord classes" do
220
268
  engine.parse defn("A:",
221
269
  " b = Dummy.call_me_maybe(1, 2, 3, 4)",
@@ -324,13 +372,13 @@ eoc
324
372
  r.should == 867 + 5309
325
373
  end
326
374
 
327
- it "should not eval inside strings" do
375
+ it "should be able to use AR classes as values and call their methods" do
328
376
  engine.parse defn("A:",
329
- ' d = "#{this is a test}"',
377
+ " a = M::LittleDummy",
378
+ " b = a.heres_my_number(867, 5309)",
330
379
  )
331
-
332
- r = engine.evaluate("A", "d")
333
- r.should == '#{this is a test}'
380
+ r = engine.evaluate("A", "b")
381
+ r.should == 867 + 5309
334
382
  end
335
383
 
336
384
  it "should ignore undeclared params sent to eval which match attr names" do
@@ -827,4 +875,17 @@ eof
827
875
  engine.evaluate("A", "y", {"a"=>1, "b"=>2, "c"=>3}).should == h
828
876
  engine.evaluate("A", "z", {"a"=>1, "b"=>2, "c"=>3}).should == -1
829
877
  end
878
+
879
+ it "implements positional args in node calls" do
880
+ engine.parse defn("B:",
881
+ " a =?",
882
+ " b =?",
883
+ " x = (_.0 - _.1) * (a - b)",
884
+ "A:",
885
+ " a = _.0 - _.1",
886
+ " z = B(10, 20, a=3, b=7).x",
887
+ )
888
+ engine.evaluate_attrs("A", ["a", "z"], {0 => 123, 1 => 456}).should ==
889
+ [123-456, -40]
890
+ end
830
891
  end
@@ -60,7 +60,8 @@ describe "Delorean" do
60
60
  it "should accept default param definitions" do
61
61
  lambda {
62
62
  engine.parse defn("A:",
63
- " b =? 1",
63
+ " a =? 0.0123",
64
+ " b =? 0",
64
65
  " c =? -1.1",
65
66
  " d = b + c",
66
67
  )
@@ -83,6 +84,22 @@ describe "Delorean" do
83
84
  }.should raise_error(Delorean::ParseError)
84
85
  end
85
86
 
87
+ it "should disallow leading 0s in numbers" do
88
+ lambda {
89
+ engine.parse defn("A:",
90
+ " a = 00.123",
91
+ )
92
+ }.should raise_error(Delorean::ParseError)
93
+ end
94
+
95
+ it "should disallow leading 0s in numbers (2)" do
96
+ lambda {
97
+ engine.parse defn("A:",
98
+ " a = 0123",
99
+ )
100
+ }.should raise_error(Delorean::ParseError)
101
+ end
102
+
86
103
  it "should disallow bad attr names" do
87
104
  lambda {
88
105
  engine.parse defn("A:",
@@ -648,15 +665,10 @@ describe "Delorean" do
648
665
  )
649
666
  end
650
667
 
651
- it "should not allow positional args to node calls" do
652
- begin
653
- engine.parse defn("A:",
654
- " d = A(1, 2, 3)",
655
- )
656
- raise "fail"
657
- rescue Delorean::ParseError => exc
658
- exc.line.should == 2
659
- end
668
+ it "should allow positional args to node calls" do
669
+ engine.parse defn("A:",
670
+ " d = A(1, 2, 3, a=123, b=456)",
671
+ )
660
672
  end
661
673
 
662
674
  it "should parse instance calls" do
@@ -728,6 +740,18 @@ describe "Delorean" do
728
740
  end
729
741
  end
730
742
 
743
+ # this is a parsing limitation which should go away
744
+ it "should not parse interpolated strings" do
745
+ begin
746
+ engine.parse defn("A:",
747
+ ' d = "#{this is a test}"',
748
+ )
749
+ raise "fail"
750
+ rescue Delorean::ParseError => exc
751
+ exc.line.should == 2
752
+ end
753
+ end
754
+
731
755
  it "should parse imports" do
732
756
  engine.parse defn("import AAA",
733
757
  "A:",
@@ -30,6 +30,8 @@ ActiveRecord::Migration.create_table :dummies do |t|
30
30
  end
31
31
 
32
32
  class Dummy < ActiveRecord::Base
33
+ include Delorean::Model
34
+
33
35
  attr_accessible :name, :number, :dummy
34
36
  belongs_to :dummy
35
37
 
@@ -64,6 +66,14 @@ class Dummy < ActiveRecord::Base
64
66
  def name2
65
67
  "#{name}-#{number}"
66
68
  end
69
+
70
+ delorean_fn :one_or_two, sig: [1, 2] do
71
+ |*args|
72
+ # FIXME: |a,b| will not work properly with delorean_fn
73
+ a, b = args
74
+
75
+ [a, b]
76
+ end
67
77
  end
68
78
 
69
79
  module M
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delorean_lang
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arman Bostani
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-06 00:00:00.000000000 Z
11
+ date: 2014-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: treetop