delorean_lang 0.3.2 → 0.3.3

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