delorean_lang 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/delorean.gemspec +2 -2
- data/lib/delorean/base.rb +8 -4
- data/lib/delorean/delorean.rb +115 -204
- data/lib/delorean/delorean.treetop +8 -7
- data/lib/delorean/nodes.rb +55 -31
- data/lib/delorean/version.rb +1 -1
- data/spec/eval_spec.rb +17 -4
- data/spec/func_spec.rb +19 -2
- data/spec/parse_spec.rb +6 -0
- data/spec/spec_helper.rb +0 -1
- metadata +19 -20
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
OWYyZGNmYTFlY2I0YmM1ZDhlMDJlN2E5NzcwMDcxYWI3NDY0NmQwZA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4146a779b717256081386c0769bbd102ebfd63da
|
4
|
+
data.tar.gz: 82006f8a19e563ddf112ef647dd29d8be0490a4a
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZTkyOWM4ZGJiMzFlMWZjN2RlODQxZTYxOGRkMWY3ODQ5NGIzN2YwMWVkYTJj
|
11
|
-
NjdjMzJjNjBjMDAyYjcyZGQwNjkyNGQwZGVjMjc1ZTk2Mjc0Njc=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ZjliYWVkY2E2YTgzN2UyNDcyNTdmNGQ5ODg4MjY0MjVhNjcxNjZhNWI3ZGEx
|
14
|
-
NTlmYWUzZjg2NGI2M2NkNTY1YWJmN2U3YzljZDgwZTg5YmRiNTI2ZmFiYjFl
|
15
|
-
YmU3Zjc3YTNhYjg1NDljMWM0NmRiYjg4NmM2NmFhY2Y2YWE1NDk=
|
6
|
+
metadata.gz: b913c68e3a21abd3ca0dabaf5be811064e73f54bb3a7639daa7a55755c4aa2a743eb9df9a36c68464c8a76935d4607fc9ac4570cf75d99cd1436c2c1121daa17
|
7
|
+
data.tar.gz: ace534f8f6ffd10a0f27524e7afc595963e4d5b60f5e7ac2ce4423e65a808b399f730ff3263c2965fdf64d9ad214799c29fb84c23e94178f6441d1961ba593b9
|
data/delorean.gemspec
CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.require_paths = ["lib"]
|
15
15
|
gem.version = Delorean::VERSION
|
16
16
|
|
17
|
-
gem.add_dependency "treetop", "~> 1.4"
|
18
|
-
gem.add_dependency "activerecord"
|
17
|
+
gem.add_dependency "treetop", "~> 1.4.8"
|
18
|
+
gem.add_dependency "activerecord"
|
19
19
|
gem.add_development_dependency "rspec"
|
20
20
|
gem.add_development_dependency "sqlite3"
|
21
21
|
end
|
data/lib/delorean/base.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/time'
|
2
|
+
require 'bigdecimal'
|
2
3
|
|
3
4
|
module Delorean
|
4
5
|
|
@@ -10,10 +11,10 @@ module Delorean
|
|
10
11
|
compact: [Array],
|
11
12
|
to_set: [Array],
|
12
13
|
flatten: [Array, [Fixnum, nil]],
|
13
|
-
length: [
|
14
|
+
length: [Enumerable],
|
14
15
|
max: [Array],
|
15
16
|
member: "member?",
|
16
|
-
member?: [Array, [
|
17
|
+
member?: [Array, [Object]],
|
17
18
|
reverse: [Array],
|
18
19
|
slice: [Array, Fixnum, Fixnum],
|
19
20
|
sort: [Array],
|
@@ -21,10 +22,10 @@ module Delorean
|
|
21
22
|
uniq: [Array],
|
22
23
|
sum: [Array],
|
23
24
|
zip: [Array, [Array, Array, Array]],
|
24
|
-
index: [Array,
|
25
|
-
[Integer, Numeric, String, Array, Fixnum, Hash]],
|
25
|
+
index: [Array, [Object]],
|
26
26
|
product: [Array, Array],
|
27
27
|
first: [Enumerable, [nil, Fixnum]],
|
28
|
+
last: [Enumerable, [nil, Fixnum]],
|
28
29
|
intersection: [Set, Enumerable],
|
29
30
|
union: [Set, Enumerable],
|
30
31
|
|
@@ -117,6 +118,9 @@ module Delorean
|
|
117
118
|
elsif obj.instance_of?(NodeCall)
|
118
119
|
return obj.evaluate(attr)
|
119
120
|
elsif obj.instance_of?(Hash)
|
121
|
+
# FIXME: this implementation doesn't handle something like
|
122
|
+
# {}.length. i.e. length is a whitelisted function, but not
|
123
|
+
# an attr. This implementation returns nil instead of 0.
|
120
124
|
return obj[attr] if obj.member?(attr)
|
121
125
|
return attr.is_a?(String) ? obj[attr.to_sym] : nil
|
122
126
|
elsif obj.instance_of?(Class) && (obj < BaseClass)
|
data/lib/delorean/delorean.rb
CHANGED
@@ -1171,6 +1171,100 @@ module Delorean
|
|
1171
1171
|
r0
|
1172
1172
|
end
|
1173
1173
|
|
1174
|
+
module UnpackArgs0
|
1175
|
+
def args
|
1176
|
+
elements[3]
|
1177
|
+
end
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
module UnpackArgs1
|
1181
|
+
def arg0
|
1182
|
+
elements[0]
|
1183
|
+
end
|
1184
|
+
|
1185
|
+
def args_rest
|
1186
|
+
elements[1]
|
1187
|
+
end
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
def _nt_unpack_args
|
1191
|
+
start_index = index
|
1192
|
+
if node_cache[:unpack_args].has_key?(index)
|
1193
|
+
cached = node_cache[:unpack_args][index]
|
1194
|
+
if cached
|
1195
|
+
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
1196
|
+
@index = cached.interval.end
|
1197
|
+
end
|
1198
|
+
return cached
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
i0, s0 = index, []
|
1202
|
+
r1 = _nt_identifier
|
1203
|
+
s0 << r1
|
1204
|
+
if r1
|
1205
|
+
i3, s3 = index, []
|
1206
|
+
r5 = _nt_sp
|
1207
|
+
if r5
|
1208
|
+
r4 = r5
|
1209
|
+
else
|
1210
|
+
r4 = instantiate_node(SyntaxNode,input, index...index)
|
1211
|
+
end
|
1212
|
+
s3 << r4
|
1213
|
+
if r4
|
1214
|
+
if has_terminal?(',', false, index)
|
1215
|
+
r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
1216
|
+
@index += 1
|
1217
|
+
else
|
1218
|
+
terminal_parse_failure(',')
|
1219
|
+
r6 = nil
|
1220
|
+
end
|
1221
|
+
s3 << r6
|
1222
|
+
if r6
|
1223
|
+
r8 = _nt_sp
|
1224
|
+
if r8
|
1225
|
+
r7 = r8
|
1226
|
+
else
|
1227
|
+
r7 = instantiate_node(SyntaxNode,input, index...index)
|
1228
|
+
end
|
1229
|
+
s3 << r7
|
1230
|
+
if r7
|
1231
|
+
r10 = _nt_unpack_args
|
1232
|
+
if r10
|
1233
|
+
r9 = r10
|
1234
|
+
else
|
1235
|
+
r9 = instantiate_node(SyntaxNode,input, index...index)
|
1236
|
+
end
|
1237
|
+
s3 << r9
|
1238
|
+
end
|
1239
|
+
end
|
1240
|
+
end
|
1241
|
+
if s3.last
|
1242
|
+
r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
|
1243
|
+
r3.extend(UnpackArgs0)
|
1244
|
+
else
|
1245
|
+
@index = i3
|
1246
|
+
r3 = nil
|
1247
|
+
end
|
1248
|
+
if r3
|
1249
|
+
r2 = r3
|
1250
|
+
else
|
1251
|
+
r2 = instantiate_node(SyntaxNode,input, index...index)
|
1252
|
+
end
|
1253
|
+
s0 << r2
|
1254
|
+
end
|
1255
|
+
if s0.last
|
1256
|
+
r0 = instantiate_node(UnpackArgs,input, i0...index, s0)
|
1257
|
+
r0.extend(UnpackArgs1)
|
1258
|
+
else
|
1259
|
+
@index = i0
|
1260
|
+
r0 = nil
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
node_cache[:unpack_args][start_index] = r0
|
1264
|
+
|
1265
|
+
r0
|
1266
|
+
end
|
1267
|
+
|
1174
1268
|
module ListExpr0
|
1175
1269
|
def sp
|
1176
1270
|
elements[1]
|
@@ -1195,7 +1289,7 @@ module Delorean
|
|
1195
1289
|
elements[5]
|
1196
1290
|
end
|
1197
1291
|
|
1198
|
-
def
|
1292
|
+
def args
|
1199
1293
|
elements[6]
|
1200
1294
|
end
|
1201
1295
|
|
@@ -1282,7 +1376,7 @@ module Delorean
|
|
1282
1376
|
r9 = _nt_sp
|
1283
1377
|
s2 << r9
|
1284
1378
|
if r9
|
1285
|
-
r10 =
|
1379
|
+
r10 = _nt_unpack_args
|
1286
1380
|
s2 << r10
|
1287
1381
|
if r10
|
1288
1382
|
r11 = _nt_sp
|
@@ -1445,52 +1539,6 @@ module Delorean
|
|
1445
1539
|
end
|
1446
1540
|
|
1447
1541
|
module SetExpr0
|
1448
|
-
def sp
|
1449
|
-
elements[1]
|
1450
|
-
end
|
1451
|
-
|
1452
|
-
def e3
|
1453
|
-
elements[2]
|
1454
|
-
end
|
1455
|
-
|
1456
|
-
end
|
1457
|
-
|
1458
|
-
module SetExpr1
|
1459
|
-
def e2
|
1460
|
-
elements[2]
|
1461
|
-
end
|
1462
|
-
|
1463
|
-
def sp1
|
1464
|
-
elements[3]
|
1465
|
-
end
|
1466
|
-
|
1467
|
-
def sp2
|
1468
|
-
elements[5]
|
1469
|
-
end
|
1470
|
-
|
1471
|
-
def i
|
1472
|
-
elements[6]
|
1473
|
-
end
|
1474
|
-
|
1475
|
-
def sp3
|
1476
|
-
elements[7]
|
1477
|
-
end
|
1478
|
-
|
1479
|
-
def sp4
|
1480
|
-
elements[9]
|
1481
|
-
end
|
1482
|
-
|
1483
|
-
def e1
|
1484
|
-
elements[10]
|
1485
|
-
end
|
1486
|
-
|
1487
|
-
def ifexp
|
1488
|
-
elements[12]
|
1489
|
-
end
|
1490
|
-
|
1491
|
-
end
|
1492
|
-
|
1493
|
-
module SetExpr2
|
1494
1542
|
def args
|
1495
1543
|
elements[2]
|
1496
1544
|
end
|
@@ -1537,117 +1585,32 @@ module Delorean
|
|
1537
1585
|
end
|
1538
1586
|
s2 << r4
|
1539
1587
|
if r4
|
1540
|
-
r6 =
|
1588
|
+
r6 = _nt_fn_args
|
1541
1589
|
s2 << r6
|
1542
1590
|
if r6
|
1543
|
-
|
1591
|
+
r8 = _nt_sp
|
1592
|
+
if r8
|
1593
|
+
r7 = r8
|
1594
|
+
else
|
1595
|
+
r7 = instantiate_node(SyntaxNode,input, index...index)
|
1596
|
+
end
|
1544
1597
|
s2 << r7
|
1545
1598
|
if r7
|
1546
|
-
if has_terminal?('
|
1547
|
-
|
1548
|
-
@index +=
|
1599
|
+
if has_terminal?('}', false, index)
|
1600
|
+
r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
1601
|
+
@index += 1
|
1549
1602
|
else
|
1550
|
-
terminal_parse_failure('
|
1551
|
-
|
1552
|
-
end
|
1553
|
-
s2 << r8
|
1554
|
-
if r8
|
1555
|
-
r9 = _nt_sp
|
1556
|
-
s2 << r9
|
1557
|
-
if r9
|
1558
|
-
r10 = _nt_identifier
|
1559
|
-
s2 << r10
|
1560
|
-
if r10
|
1561
|
-
r11 = _nt_sp
|
1562
|
-
s2 << r11
|
1563
|
-
if r11
|
1564
|
-
if has_terminal?('in', false, index)
|
1565
|
-
r12 = instantiate_node(SyntaxNode,input, index...(index + 2))
|
1566
|
-
@index += 2
|
1567
|
-
else
|
1568
|
-
terminal_parse_failure('in')
|
1569
|
-
r12 = nil
|
1570
|
-
end
|
1571
|
-
s2 << r12
|
1572
|
-
if r12
|
1573
|
-
r13 = _nt_sp
|
1574
|
-
s2 << r13
|
1575
|
-
if r13
|
1576
|
-
r14 = _nt_expression
|
1577
|
-
s2 << r14
|
1578
|
-
if r14
|
1579
|
-
r16 = _nt_sp
|
1580
|
-
if r16
|
1581
|
-
r15 = r16
|
1582
|
-
else
|
1583
|
-
r15 = instantiate_node(SyntaxNode,input, index...index)
|
1584
|
-
end
|
1585
|
-
s2 << r15
|
1586
|
-
if r15
|
1587
|
-
i18, s18 = index, []
|
1588
|
-
if has_terminal?('if', false, index)
|
1589
|
-
r19 = instantiate_node(SyntaxNode,input, index...(index + 2))
|
1590
|
-
@index += 2
|
1591
|
-
else
|
1592
|
-
terminal_parse_failure('if')
|
1593
|
-
r19 = nil
|
1594
|
-
end
|
1595
|
-
s18 << r19
|
1596
|
-
if r19
|
1597
|
-
r20 = _nt_sp
|
1598
|
-
s18 << r20
|
1599
|
-
if r20
|
1600
|
-
r21 = _nt_expression
|
1601
|
-
s18 << r21
|
1602
|
-
if r21
|
1603
|
-
r23 = _nt_sp
|
1604
|
-
if r23
|
1605
|
-
r22 = r23
|
1606
|
-
else
|
1607
|
-
r22 = instantiate_node(SyntaxNode,input, index...index)
|
1608
|
-
end
|
1609
|
-
s18 << r22
|
1610
|
-
end
|
1611
|
-
end
|
1612
|
-
end
|
1613
|
-
if s18.last
|
1614
|
-
r18 = instantiate_node(SyntaxNode,input, i18...index, s18)
|
1615
|
-
r18.extend(SetExpr0)
|
1616
|
-
else
|
1617
|
-
@index = i18
|
1618
|
-
r18 = nil
|
1619
|
-
end
|
1620
|
-
if r18
|
1621
|
-
r17 = r18
|
1622
|
-
else
|
1623
|
-
r17 = instantiate_node(SyntaxNode,input, index...index)
|
1624
|
-
end
|
1625
|
-
s2 << r17
|
1626
|
-
if r17
|
1627
|
-
if has_terminal?('}', false, index)
|
1628
|
-
r24 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
1629
|
-
@index += 1
|
1630
|
-
else
|
1631
|
-
terminal_parse_failure('}')
|
1632
|
-
r24 = nil
|
1633
|
-
end
|
1634
|
-
s2 << r24
|
1635
|
-
end
|
1636
|
-
end
|
1637
|
-
end
|
1638
|
-
end
|
1639
|
-
end
|
1640
|
-
end
|
1641
|
-
end
|
1642
|
-
end
|
1603
|
+
terminal_parse_failure('}')
|
1604
|
+
r9 = nil
|
1643
1605
|
end
|
1606
|
+
s2 << r9
|
1644
1607
|
end
|
1645
1608
|
end
|
1646
1609
|
end
|
1647
1610
|
end
|
1648
1611
|
if s2.last
|
1649
|
-
r2 = instantiate_node(
|
1650
|
-
r2.extend(
|
1612
|
+
r2 = instantiate_node(SetExpr,input, i2...index, s2)
|
1613
|
+
r2.extend(SetExpr0)
|
1651
1614
|
else
|
1652
1615
|
@index = i2
|
1653
1616
|
r2 = nil
|
@@ -1655,60 +1618,8 @@ module Delorean
|
|
1655
1618
|
if r2
|
1656
1619
|
r0 = r2
|
1657
1620
|
else
|
1658
|
-
|
1659
|
-
|
1660
|
-
r26 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
1661
|
-
@index += 1
|
1662
|
-
else
|
1663
|
-
terminal_parse_failure('{')
|
1664
|
-
r26 = nil
|
1665
|
-
end
|
1666
|
-
s25 << r26
|
1667
|
-
if r26
|
1668
|
-
r28 = _nt_sp
|
1669
|
-
if r28
|
1670
|
-
r27 = r28
|
1671
|
-
else
|
1672
|
-
r27 = instantiate_node(SyntaxNode,input, index...index)
|
1673
|
-
end
|
1674
|
-
s25 << r27
|
1675
|
-
if r27
|
1676
|
-
r29 = _nt_fn_args
|
1677
|
-
s25 << r29
|
1678
|
-
if r29
|
1679
|
-
r31 = _nt_sp
|
1680
|
-
if r31
|
1681
|
-
r30 = r31
|
1682
|
-
else
|
1683
|
-
r30 = instantiate_node(SyntaxNode,input, index...index)
|
1684
|
-
end
|
1685
|
-
s25 << r30
|
1686
|
-
if r30
|
1687
|
-
if has_terminal?('}', false, index)
|
1688
|
-
r32 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
1689
|
-
@index += 1
|
1690
|
-
else
|
1691
|
-
terminal_parse_failure('}')
|
1692
|
-
r32 = nil
|
1693
|
-
end
|
1694
|
-
s25 << r32
|
1695
|
-
end
|
1696
|
-
end
|
1697
|
-
end
|
1698
|
-
end
|
1699
|
-
if s25.last
|
1700
|
-
r25 = instantiate_node(SetExpr,input, i25...index, s25)
|
1701
|
-
r25.extend(SetExpr2)
|
1702
|
-
else
|
1703
|
-
@index = i25
|
1704
|
-
r25 = nil
|
1705
|
-
end
|
1706
|
-
if r25
|
1707
|
-
r0 = r25
|
1708
|
-
else
|
1709
|
-
@index = i0
|
1710
|
-
r0 = nil
|
1711
|
-
end
|
1621
|
+
@index = i0
|
1622
|
+
r0 = nil
|
1712
1623
|
end
|
1713
1624
|
end
|
1714
1625
|
|
@@ -1745,7 +1656,7 @@ module Delorean
|
|
1745
1656
|
elements[9]
|
1746
1657
|
end
|
1747
1658
|
|
1748
|
-
def
|
1659
|
+
def args
|
1749
1660
|
elements[10]
|
1750
1661
|
end
|
1751
1662
|
|
@@ -1860,7 +1771,7 @@ module Delorean
|
|
1860
1771
|
r15 = _nt_sp
|
1861
1772
|
s2 << r15
|
1862
1773
|
if r15
|
1863
|
-
r16 =
|
1774
|
+
r16 = _nt_unpack_args
|
1864
1775
|
s2 << r16
|
1865
1776
|
if r16
|
1866
1777
|
r17 = _nt_sp
|
@@ -55,11 +55,16 @@ grammar Delorean
|
|
55
55
|
'.' sp? i:(identifier / integer) <GetAttr>
|
56
56
|
end
|
57
57
|
|
58
|
+
rule unpack_args
|
59
|
+
arg0:identifier args_rest:(sp? ',' sp? args:unpack_args?)? <UnpackArgs>
|
60
|
+
end
|
61
|
+
|
58
62
|
rule list_expr
|
59
63
|
'[]' <ListExpr>
|
60
64
|
/
|
61
65
|
'[' sp? e2:expression sp
|
62
|
-
'for' sp
|
66
|
+
'for' sp args:unpack_args sp
|
67
|
+
'in' sp e1:expression sp?
|
63
68
|
ifexp:('if' sp e3:expression sp?)?
|
64
69
|
']' <ListComprehension>
|
65
70
|
/
|
@@ -69,11 +74,6 @@ grammar Delorean
|
|
69
74
|
rule set_expr
|
70
75
|
'{-}' <SetExpr>
|
71
76
|
/
|
72
|
-
'{' sp? e2:expression sp
|
73
|
-
'for' sp i:identifier sp 'in' sp e1:expression sp?
|
74
|
-
ifexp:('if' sp e3:expression sp?)?
|
75
|
-
'}' <SetComprehension>
|
76
|
-
/
|
77
77
|
'{' sp? args:fn_args sp? '}' <SetExpr>
|
78
78
|
end
|
79
79
|
|
@@ -81,7 +81,8 @@ grammar Delorean
|
|
81
81
|
'{}' <HashExpr>
|
82
82
|
/
|
83
83
|
'{' sp? el:expression sp? ':' sp? er:expression sp
|
84
|
-
'for' sp
|
84
|
+
'for' sp args:unpack_args sp
|
85
|
+
'in' sp e1:expression sp?
|
85
86
|
ifexp:('if' sp ei:expression sp?)?
|
86
87
|
'}' <HashComprehension>
|
87
88
|
/
|
data/lib/delorean/nodes.rb
CHANGED
@@ -404,31 +404,51 @@ eos
|
|
404
404
|
end
|
405
405
|
end
|
406
406
|
|
407
|
-
class
|
407
|
+
class UnpackArgs < SNode
|
408
408
|
def check(context, *)
|
409
|
-
|
409
|
+
[arg0.text_value] +
|
410
|
+
(defined?(args_rest.args) && !args_rest.args.text_value.empty? ?
|
411
|
+
args_rest.args.check(context) : [])
|
412
|
+
end
|
410
413
|
|
414
|
+
def rewrite(context)
|
415
|
+
arg0.rewrite(context) +
|
416
|
+
(defined?(args_rest.args) && !args_rest.args.text_value.empty? ?
|
417
|
+
", " + args_rest.args.rewrite(context) : "")
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
class ListComprehension < SNode
|
422
|
+
def check(context, *)
|
423
|
+
unpack_vars = args.check(context)
|
411
424
|
e1c = e1.check(context)
|
412
|
-
context.parse_define_var(vname)
|
425
|
+
unpack_vars.each {|vname| context.parse_define_var(vname)}
|
426
|
+
|
413
427
|
# need to check e2/e3 in a context where the comprehension var
|
414
428
|
# is defined.
|
415
429
|
e2c = e2.check(context)
|
416
430
|
e3c = defined?(ifexp.e3) ? ifexp.e3.check(context) : []
|
417
431
|
|
418
|
-
|
419
|
-
|
420
|
-
|
432
|
+
unpack_vars.each {
|
433
|
+
|vname|
|
434
|
+
context.parse_undef_var(vname)
|
435
|
+
e2c.delete(vname)
|
436
|
+
e3c.delete(vname)
|
437
|
+
}
|
421
438
|
|
422
439
|
e1c + e2c + e3c
|
423
440
|
end
|
424
441
|
|
425
442
|
def rewrite(context)
|
426
443
|
res = "(#{e1.rewrite(context)})"
|
427
|
-
|
428
|
-
|
444
|
+
unpack_vars = args.check(context)
|
445
|
+
unpack_vars.each {|vname| context.parse_define_var(vname)}
|
446
|
+
args_str = args.rewrite(context)
|
447
|
+
|
448
|
+
res += ".select{|#{args_str}|(#{ifexp.e3.rewrite(context)})}" if
|
429
449
|
defined?(ifexp.e3)
|
430
|
-
res += ".map{|#{
|
431
|
-
context.parse_undef_var(
|
450
|
+
res += ".map{|#{args_str}| (#{e2.rewrite(context)}) }"
|
451
|
+
unpack_vars.each {|vname| context.parse_undef_var(vname)}
|
432
452
|
res
|
433
453
|
end
|
434
454
|
end
|
@@ -439,41 +459,45 @@ eos
|
|
439
459
|
end
|
440
460
|
end
|
441
461
|
|
442
|
-
class SetComprehension < ListComprehension
|
443
|
-
def rewrite(context)
|
444
|
-
"Set[*#{super}]"
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
462
|
class HashComprehension < SNode
|
449
|
-
|
450
|
-
|
463
|
+
# used in generating unique hash names
|
464
|
+
@@comp_count = 0
|
451
465
|
|
466
|
+
def check(context, *)
|
467
|
+
unpack_vars = args.check(context)
|
452
468
|
e1c = e1.check(context)
|
453
|
-
context.parse_define_var(vname)
|
469
|
+
unpack_vars.each {|vname| context.parse_define_var(vname)}
|
470
|
+
|
454
471
|
# need to check el/er/ei in a context where the comprehension var
|
455
472
|
# is defined.
|
456
473
|
elc = el.check(context)
|
457
474
|
erc = er.check(context)
|
458
475
|
eic = defined?(ifexp.ei) ? ifexp.ei.check(context) : []
|
459
476
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
477
|
+
unpack_vars.each {
|
478
|
+
|vname|
|
479
|
+
context.parse_undef_var(vname)
|
480
|
+
elc.delete(vname)
|
481
|
+
erc.delete(vname)
|
482
|
+
eic.delete(vname)
|
483
|
+
}
|
465
484
|
e1c + elc + erc + eic
|
466
485
|
end
|
467
486
|
|
468
487
|
def rewrite(context)
|
469
488
|
res = "(#{e1.rewrite(context)})"
|
470
|
-
|
471
|
-
|
472
|
-
|
489
|
+
unpack_vars = args.check(context)
|
490
|
+
unpack_vars.each {|vname| context.parse_define_var(vname)}
|
491
|
+
args_str = args.rewrite(context)
|
492
|
+
|
493
|
+
hid = @@comp_count += 1
|
494
|
+
|
495
|
+
res += ".select{|#{args_str}| (#{ifexp.ei.rewrite(context)}) }" if
|
473
496
|
defined?(ifexp.ei)
|
474
|
-
res += ".
|
475
|
-
"_h#{
|
476
|
-
|
497
|
+
res += ".each_with_object({}){|(#{args_str}), _h#{hid}| " +
|
498
|
+
"_h#{hid}[#{el.rewrite(context)}]=(#{er.rewrite(context)})}"
|
499
|
+
|
500
|
+
unpack_vars.each {|vname| context.parse_undef_var(vname)}
|
477
501
|
res
|
478
502
|
end
|
479
503
|
end
|
@@ -484,7 +508,7 @@ eos
|
|
484
508
|
end
|
485
509
|
|
486
510
|
def rewrite(context)
|
487
|
-
"{
|
511
|
+
"{#{args.rewrite(context) if defined?(args)}}"
|
488
512
|
end
|
489
513
|
end
|
490
514
|
|
data/lib/delorean/version.rb
CHANGED
data/spec/eval_spec.rb
CHANGED
@@ -534,14 +534,13 @@ eof
|
|
534
534
|
]
|
535
535
|
end
|
536
536
|
|
537
|
-
it "should eval sets
|
537
|
+
it "should eval sets" do
|
538
538
|
engine.parse defn("A:",
|
539
539
|
" a = {-}",
|
540
|
-
" b = {i*5 for i in {1,2,3}}",
|
541
540
|
" c = {1,2,3} | {4,5}",
|
542
541
|
)
|
543
|
-
engine.evaluate_attrs("A", ["a", "
|
544
|
-
[Set[], Set[
|
542
|
+
engine.evaluate_attrs("A", ["a", "c"]).should ==
|
543
|
+
[Set[], Set[1,2,3,4,5]]
|
545
544
|
end
|
546
545
|
|
547
546
|
it "should eval list comprehension" do
|
@@ -583,6 +582,13 @@ eof
|
|
583
582
|
engine.evaluate("A", "c").should == [0.5]
|
584
583
|
end
|
585
584
|
|
585
|
+
it "should handle list comprehension unpacking" do
|
586
|
+
engine.parse defn("A:",
|
587
|
+
" b = [a-b for a, b in [[1,2],[20,10]]]",
|
588
|
+
)
|
589
|
+
engine.evaluate("A", "b").should == [-1, 10]
|
590
|
+
end
|
591
|
+
|
586
592
|
it "should eval hashes" do
|
587
593
|
engine.parse defn("A:",
|
588
594
|
" b = {}",
|
@@ -638,6 +644,13 @@ eof
|
|
638
644
|
engine.evaluate_attrs("A", ["d", "f"]).should == [26, 2]
|
639
645
|
end
|
640
646
|
|
647
|
+
it "should eval multi-var hash comprehension" do
|
648
|
+
engine.parse defn("A:",
|
649
|
+
" b = {k*5 : v+1 for k, v in {1:2, 7:-30}}",
|
650
|
+
)
|
651
|
+
engine.evaluate("A", "b").should == {5=>3, 35=>-29}
|
652
|
+
end
|
653
|
+
|
641
654
|
it "should be able to amend node calls" do
|
642
655
|
engine.parse defn("A:",
|
643
656
|
" a =?",
|
data/spec/func_spec.rb
CHANGED
@@ -101,7 +101,9 @@ describe "Delorean" do
|
|
101
101
|
r.should == [p.year, p.day, p.month]
|
102
102
|
|
103
103
|
# Non date argument should raise an error
|
104
|
-
expect {
|
104
|
+
expect {
|
105
|
+
engine.evaluate_attrs("A", ["y", "d", "m"], {"p" => 123})
|
106
|
+
}.to raise_error
|
105
107
|
end
|
106
108
|
|
107
109
|
it "should handle FLATTEN" do
|
@@ -139,10 +141,11 @@ describe "Delorean" do
|
|
139
141
|
" dd = d.flatten()",
|
140
142
|
" e = dd.sort()",
|
141
143
|
" f = e.uniq()",
|
142
|
-
" g = e.length
|
144
|
+
" g = e.length",
|
143
145
|
" gg = a.length()",
|
144
146
|
" l = a.member(5)",
|
145
147
|
" m = [a.member(5), a.member(55)]",
|
148
|
+
" n = {'a':1, 'b':2, 'c':3}.length()",
|
146
149
|
)
|
147
150
|
|
148
151
|
engine.evaluate("A", "c").should == x.flatten(1)
|
@@ -153,6 +156,20 @@ describe "Delorean" do
|
|
153
156
|
engine.evaluate("A", "g").should == dd.length
|
154
157
|
engine.evaluate("A", "gg").should == x.length
|
155
158
|
engine.evaluate("A", "m").should == [x.member?(5), x.member?(55)]
|
159
|
+
engine.evaluate("A", "n").should == 3
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should be able to call function on hash" do
|
163
|
+
# FIXME: this is actually a Delorean design issue. How do
|
164
|
+
# whitelisted functions interact with attrs? In this case, we
|
165
|
+
# return nil since there is no Delorean 'length' attr in the hash.
|
166
|
+
|
167
|
+
engine.parse defn("A:",
|
168
|
+
" n = {}.length",
|
169
|
+
" m = {'length':100}.length",
|
170
|
+
)
|
171
|
+
engine.evaluate("A", "n").should == 0
|
172
|
+
engine.evaluate("A", "m").should == 100
|
156
173
|
end
|
157
174
|
|
158
175
|
it "should handle RUBY slice function" do
|
data/spec/parse_spec.rb
CHANGED
@@ -638,6 +638,12 @@ describe "Delorean" do
|
|
638
638
|
engine.reset
|
639
639
|
end
|
640
640
|
|
641
|
+
it "should accept hash comprehension 2-var unpacking" do
|
642
|
+
engine.parse defn("A:",
|
643
|
+
" b = [ a+b for a, b in [] ]",
|
644
|
+
)
|
645
|
+
end
|
646
|
+
|
641
647
|
it "should allow nodes as values" do
|
642
648
|
engine.parse defn("A:",
|
643
649
|
" a = 123",
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,69 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delorean_lang
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
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-
|
11
|
+
date: 2014-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: treetop
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.4.8
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.4.8
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: sqlite3
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
description: A "compiler" for the Delorean programming language
|
@@ -73,8 +73,8 @@ executables: []
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
-
- .gitignore
|
77
|
-
- .rspec
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
78
|
- Gemfile
|
79
79
|
- LICENSE
|
80
80
|
- README.md
|
@@ -105,17 +105,17 @@ require_paths:
|
|
105
105
|
- lib
|
106
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
112
|
requirements:
|
113
|
-
- -
|
113
|
+
- - ">="
|
114
114
|
- !ruby/object:Gem::Version
|
115
115
|
version: '0'
|
116
116
|
requirements: []
|
117
117
|
rubyforge_project:
|
118
|
-
rubygems_version: 2.
|
118
|
+
rubygems_version: 2.2.2
|
119
119
|
signing_key:
|
120
120
|
specification_version: 4
|
121
121
|
summary: Delorean compiler
|
@@ -125,4 +125,3 @@ test_files:
|
|
125
125
|
- spec/func_spec.rb
|
126
126
|
- spec/parse_spec.rb
|
127
127
|
- spec/spec_helper.rb
|
128
|
-
has_rdoc:
|