delorean_lang 0.3.4 → 0.3.5
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 +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:
|