cpyte 4.2.7__tar.gz → 4.3.0__tar.gz
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.
- {cpyte-4.2.7/source/cpyte.egg-info → cpyte-4.3.0}/PKG-INFO +1 -1
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/__init__.py +1 -1
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/astparse.py +262 -23
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/bytecoding.py +272 -2
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/formatter.py +19 -1
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/lexar.py +2 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/semantic_analasis.py +474 -16
- {cpyte-4.2.7 → cpyte-4.3.0/source/cpyte.egg-info}/PKG-INFO +1 -1
- {cpyte-4.2.7 → cpyte-4.3.0}/MANIFEST.in +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/pyproject.toml +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/readme.md +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/setup.cfg +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/__main__.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/_bignum_bc.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/_runtime_bc.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/bignum.c +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/clib.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/compiling.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/extension_hooks.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/gc_runtime.c +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/generate_bc.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/linker.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/lsp_server.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/mainpie.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/optimizations.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/package_manifest.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/runtime.c +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/runtime_scorpion.c +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/sef.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/ugc.h +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/ui.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/update_check.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/winjit_patch.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte/winjit_stubs.c +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte.egg-info/SOURCES.txt +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte.egg-info/dependency_links.txt +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte.egg-info/entry_points.txt +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte.egg-info/requires.txt +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/source/cpyte.egg-info/top_level.txt +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/test/test_bignum_jit.py +0 -0
- {cpyte-4.2.7 → cpyte-4.3.0}/test/test_fuzz_del_has.py +0 -0
|
@@ -187,7 +187,14 @@ class Index(Node):
|
|
|
187
187
|
|
|
188
188
|
class Attr(Node):
|
|
189
189
|
inferred_type: str | None
|
|
190
|
-
__slots__ = (
|
|
190
|
+
__slots__ = (
|
|
191
|
+
"_enum_member_value",
|
|
192
|
+
"_token",
|
|
193
|
+
"inferred_type",
|
|
194
|
+
"meta",
|
|
195
|
+
"name",
|
|
196
|
+
"obj",
|
|
197
|
+
)
|
|
191
198
|
|
|
192
199
|
def __init__(self, obj, name: str, token=None):
|
|
193
200
|
self.obj = obj
|
|
@@ -195,6 +202,7 @@ class Attr(Node):
|
|
|
195
202
|
self._token = token
|
|
196
203
|
self._enum_member_value = None
|
|
197
204
|
self.inferred_type = None
|
|
205
|
+
self.meta = None
|
|
198
206
|
|
|
199
207
|
def __repr__(self):
|
|
200
208
|
return f"Attr({self.obj}, {self.name})"
|
|
@@ -828,13 +836,27 @@ def _parse_call_args(tokens: list[Token], pos: int, callee):
|
|
|
828
836
|
|
|
829
837
|
|
|
830
838
|
def _parse_postfix(tokens: list[Token], pos: int, node):
|
|
831
|
-
while pos < len(tokens) and
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
839
|
+
while pos < len(tokens) and (
|
|
840
|
+
tokens[pos].type in (
|
|
841
|
+
TokenType.LPAREN,
|
|
842
|
+
TokenType.LBRACKET,
|
|
843
|
+
TokenType.DOT,
|
|
844
|
+
)
|
|
845
|
+
or (tokens[pos].type == TokenType.KEYWORD and tokens[pos].value == "as")
|
|
835
846
|
):
|
|
836
847
|
tok = tokens[pos]
|
|
837
|
-
if tok.type == TokenType.
|
|
848
|
+
if tok.type == TokenType.KEYWORD and tok.value == "as":
|
|
849
|
+
pos += 1
|
|
850
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.IDENTIFIER:
|
|
851
|
+
raise ParseError(
|
|
852
|
+
"Expected a class name after 'as'",
|
|
853
|
+
tokens[pos] if pos < len(tokens) else None,
|
|
854
|
+
)
|
|
855
|
+
name = tokens[pos].value
|
|
856
|
+
assert name is not None
|
|
857
|
+
pos += 1
|
|
858
|
+
node = AsExpr(name, node, token=tok)
|
|
859
|
+
elif tok.type == TokenType.LPAREN:
|
|
838
860
|
node, pos = _parse_call_args(tokens, pos, node)
|
|
839
861
|
elif tok.type == TokenType.LBRACKET:
|
|
840
862
|
pos += 1
|
|
@@ -1039,13 +1061,27 @@ def _parse_expr_iterative(tokens: list[Token], pos: int, min_prec: int):
|
|
|
1039
1061
|
elif kind == "postfix":
|
|
1040
1062
|
prefixes = frame[1]
|
|
1041
1063
|
node = vals.pop()
|
|
1042
|
-
while pos < len(tokens) and
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1064
|
+
while pos < len(tokens) and (
|
|
1065
|
+
tokens[pos].type in (
|
|
1066
|
+
TokenType.LPAREN,
|
|
1067
|
+
TokenType.LBRACKET,
|
|
1068
|
+
TokenType.DOT,
|
|
1069
|
+
)
|
|
1070
|
+
or (tokens[pos].type == TokenType.KEYWORD and tokens[pos].value == "as")
|
|
1046
1071
|
):
|
|
1047
1072
|
ptok = tokens[pos]
|
|
1048
|
-
if ptok.type == TokenType.
|
|
1073
|
+
if ptok.type == TokenType.KEYWORD and ptok.value == "as":
|
|
1074
|
+
pos += 1
|
|
1075
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.IDENTIFIER:
|
|
1076
|
+
raise ParseError(
|
|
1077
|
+
"Expected a class name after 'as'",
|
|
1078
|
+
tokens[pos] if pos < len(tokens) else None,
|
|
1079
|
+
)
|
|
1080
|
+
name = tokens[pos].value
|
|
1081
|
+
assert name is not None
|
|
1082
|
+
pos += 1
|
|
1083
|
+
node = AsExpr(name, node, token=ptok)
|
|
1084
|
+
elif ptok.type == TokenType.LPAREN:
|
|
1049
1085
|
pos += 1
|
|
1050
1086
|
frames.append(("call_done", prefixes))
|
|
1051
1087
|
frames.append(("callargs", node, [], ptok))
|
|
@@ -1210,14 +1246,10 @@ def _parse_standard_statement(tokens: list[Token], pos: int):
|
|
|
1210
1246
|
node, pos = parse_decorated_def(tokens, pos)
|
|
1211
1247
|
elif tok.type == TokenType.KEYWORD and tok.value == "sealed":
|
|
1212
1248
|
# `sealed class X:` — a closed, monomorphic class (no vtable).
|
|
1213
|
-
pos
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
)
|
|
1217
|
-
raise ParseError(
|
|
1218
|
-
'Expected "class" after "sealed"', tokens[pos] if pos < len(tokens) else None
|
|
1219
|
-
)
|
|
1220
|
-
node, pos = parse_class(tokens, pos, sealed=True)
|
|
1249
|
+
node, pos = parse_sealed_class(tokens, pos)
|
|
1250
|
+
elif tok.type == TokenType.KEYWORD and tok.value == "dataclass":
|
|
1251
|
+
# `dataclass class X:` — auto-synthesized `__init__`/`__eq__`/`__str__`.
|
|
1252
|
+
node, pos = parse_dataclass_class(tokens, pos)
|
|
1221
1253
|
elif tok.type == TokenType.KEYWORD and tok.value == "class":
|
|
1222
1254
|
node, pos = parse_class(tokens, pos)
|
|
1223
1255
|
elif tok.type == TokenType.KEYWORD and tok.value == "struct":
|
|
@@ -1383,7 +1415,7 @@ def parse_decorated_def(tokens: list[Token], pos: int):
|
|
|
1383
1415
|
return _parse_func_with_visibility(tokens, pos, visibility, tok)
|
|
1384
1416
|
|
|
1385
1417
|
|
|
1386
|
-
def parse_class(tokens: list[Token], pos: int, sealed: bool = False):
|
|
1418
|
+
def parse_class(tokens: list[Token], pos: int, sealed: bool = False, dataclass: bool = False):
|
|
1387
1419
|
tok = tokens[pos]
|
|
1388
1420
|
pos += 1
|
|
1389
1421
|
if pos >= len(tokens) or tokens[pos].type != TokenType.IDENTIFIER:
|
|
@@ -1409,25 +1441,182 @@ def parse_class(tokens: list[Token], pos: int, sealed: bool = False):
|
|
|
1409
1441
|
tokens[pos] if pos < len(tokens) else None,
|
|
1410
1442
|
)
|
|
1411
1443
|
pos += 1
|
|
1412
|
-
body, pos =
|
|
1444
|
+
body, pos = parse_class_suite(tokens, pos)
|
|
1413
1445
|
fields = []
|
|
1414
1446
|
methods = []
|
|
1447
|
+
properties = []
|
|
1415
1448
|
for stmt in body:
|
|
1416
1449
|
if isinstance(stmt, FuncDef):
|
|
1417
1450
|
methods.append(stmt)
|
|
1418
1451
|
elif isinstance(stmt, VarDecl):
|
|
1419
1452
|
fields.append(Field(stmt.name, stmt.var_type, token=stmt._token))
|
|
1453
|
+
elif isinstance(stmt, PropertyDef):
|
|
1454
|
+
properties.append(stmt)
|
|
1420
1455
|
return ClassDef(
|
|
1421
1456
|
name,
|
|
1422
1457
|
base=base,
|
|
1423
1458
|
fields=fields,
|
|
1424
1459
|
methods=methods,
|
|
1460
|
+
properties=properties,
|
|
1425
1461
|
generic_params=generic_params,
|
|
1426
1462
|
sealed=sealed,
|
|
1463
|
+
dataclass=dataclass,
|
|
1427
1464
|
token=tok,
|
|
1428
1465
|
), pos
|
|
1429
1466
|
|
|
1430
1467
|
|
|
1468
|
+
def parse_class_suite(tokens: list[Token], pos: int):
|
|
1469
|
+
"""Parse a class body suite, intercepting `property name:` blocks."""
|
|
1470
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.COLON:
|
|
1471
|
+
raise ParseError('Expected ":"', tokens[pos] if pos < len(tokens) else None)
|
|
1472
|
+
pos += 1
|
|
1473
|
+
|
|
1474
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.NEWLINE:
|
|
1475
|
+
raise ParseError(
|
|
1476
|
+
'Expected newline after ":"', tokens[pos] if pos < len(tokens) else None
|
|
1477
|
+
)
|
|
1478
|
+
pos += 1
|
|
1479
|
+
|
|
1480
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.INDENT:
|
|
1481
|
+
raise ParseError(
|
|
1482
|
+
"Expected indented block", tokens[pos] if pos < len(tokens) else None
|
|
1483
|
+
)
|
|
1484
|
+
pos += 1
|
|
1485
|
+
|
|
1486
|
+
stmts = []
|
|
1487
|
+
while pos < len(tokens) and tokens[pos].type not in (
|
|
1488
|
+
TokenType.DEDENT,
|
|
1489
|
+
TokenType.EOF,
|
|
1490
|
+
):
|
|
1491
|
+
if (
|
|
1492
|
+
tokens[pos].type == TokenType.IDENTIFIER
|
|
1493
|
+
and tokens[pos].value == "property"
|
|
1494
|
+
):
|
|
1495
|
+
pnode, pos = parse_property(tokens, pos)
|
|
1496
|
+
stmts.append(pnode)
|
|
1497
|
+
while pos < len(tokens) and tokens[pos].type == TokenType.NEWLINE:
|
|
1498
|
+
pos += 1
|
|
1499
|
+
continue
|
|
1500
|
+
stmt, pos = parse_statement(tokens, pos)
|
|
1501
|
+
if stmt is not None:
|
|
1502
|
+
stmts.append(stmt)
|
|
1503
|
+
while pos < len(tokens) and tokens[pos].type == TokenType.NEWLINE:
|
|
1504
|
+
pos += 1
|
|
1505
|
+
if pos < len(tokens) and tokens[pos].type == TokenType.DEDENT:
|
|
1506
|
+
pos += 1
|
|
1507
|
+
return stmts, pos
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
def parse_sealed_class(tokens: list[Token], pos: int):
|
|
1511
|
+
"""Parse `sealed class X:` (or `sealed dataclass class X:`) — a closed,
|
|
1512
|
+
monomorphic class (no vtable)."""
|
|
1513
|
+
pos += 1
|
|
1514
|
+
dataclass = False
|
|
1515
|
+
if (
|
|
1516
|
+
pos < len(tokens)
|
|
1517
|
+
and tokens[pos].type == TokenType.KEYWORD
|
|
1518
|
+
and tokens[pos].value == "dataclass"
|
|
1519
|
+
):
|
|
1520
|
+
dataclass = True
|
|
1521
|
+
pos += 1
|
|
1522
|
+
if pos >= len(tokens) or (
|
|
1523
|
+
tokens[pos].type != TokenType.KEYWORD or tokens[pos].value != "class"
|
|
1524
|
+
):
|
|
1525
|
+
raise ParseError(
|
|
1526
|
+
'Expected "class" after "sealed"',
|
|
1527
|
+
tokens[pos] if pos < len(tokens) else None,
|
|
1528
|
+
)
|
|
1529
|
+
return parse_class(tokens, pos, sealed=True, dataclass=dataclass)
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
def parse_dataclass_class(tokens: list[Token], pos: int):
|
|
1533
|
+
"""Parse `dataclass class X:` (or `sealed dataclass class X:`) — a class
|
|
1534
|
+
that auto-synthesizes `__init__`/`__eq__`/`__str__` from its fields
|
|
1535
|
+
(Python-style dataclass)."""
|
|
1536
|
+
pos += 1
|
|
1537
|
+
sealed = False
|
|
1538
|
+
if (
|
|
1539
|
+
pos < len(tokens)
|
|
1540
|
+
and tokens[pos].type == TokenType.KEYWORD
|
|
1541
|
+
and tokens[pos].value == "sealed"
|
|
1542
|
+
):
|
|
1543
|
+
sealed = True
|
|
1544
|
+
pos += 1
|
|
1545
|
+
if pos >= len(tokens) or (
|
|
1546
|
+
tokens[pos].type != TokenType.KEYWORD or tokens[pos].value != "class"
|
|
1547
|
+
):
|
|
1548
|
+
raise ParseError(
|
|
1549
|
+
'Expected "class" after "dataclass"',
|
|
1550
|
+
tokens[pos] if pos < len(tokens) else None,
|
|
1551
|
+
)
|
|
1552
|
+
return parse_class(tokens, pos, sealed=sealed, dataclass=True)
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
def parse_property(tokens: list[Token], pos: int):
|
|
1556
|
+
"""Parse a `property name:` block with `get`/`set` accessor bodies."""
|
|
1557
|
+
tok = tokens[pos]
|
|
1558
|
+
pos += 1
|
|
1559
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.IDENTIFIER:
|
|
1560
|
+
raise ParseError(
|
|
1561
|
+
"Expected property name after `property`",
|
|
1562
|
+
tokens[pos] if pos < len(tokens) else None,
|
|
1563
|
+
)
|
|
1564
|
+
name = tokens[pos].value
|
|
1565
|
+
assert name is not None
|
|
1566
|
+
pos += 1
|
|
1567
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.COLON:
|
|
1568
|
+
raise ParseError(
|
|
1569
|
+
'Expected ":" after property name',
|
|
1570
|
+
tokens[pos] if pos < len(tokens) else None,
|
|
1571
|
+
)
|
|
1572
|
+
pos += 1
|
|
1573
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.NEWLINE:
|
|
1574
|
+
raise ParseError(
|
|
1575
|
+
'Expected newline after ":"', tokens[pos] if pos < len(tokens) else None
|
|
1576
|
+
)
|
|
1577
|
+
pos += 1
|
|
1578
|
+
if pos >= len(tokens) or tokens[pos].type != TokenType.INDENT:
|
|
1579
|
+
raise ParseError(
|
|
1580
|
+
"Expected indented block", tokens[pos] if pos < len(tokens) else None
|
|
1581
|
+
)
|
|
1582
|
+
pos += 1
|
|
1583
|
+
|
|
1584
|
+
get = None
|
|
1585
|
+
setm = None
|
|
1586
|
+
while pos < len(tokens) and tokens[pos].type not in (
|
|
1587
|
+
TokenType.DEDENT,
|
|
1588
|
+
TokenType.EOF,
|
|
1589
|
+
):
|
|
1590
|
+
if (
|
|
1591
|
+
tokens[pos].type == TokenType.IDENTIFIER
|
|
1592
|
+
and tokens[pos].value in ("get", "set")
|
|
1593
|
+
and pos + 1 < len(tokens)
|
|
1594
|
+
and tokens[pos + 1].type == TokenType.COLON
|
|
1595
|
+
):
|
|
1596
|
+
atok = tokens[pos]
|
|
1597
|
+
aname = tokens[pos].value
|
|
1598
|
+
abody, pos = parse_suite(tokens, pos + 1)
|
|
1599
|
+
accessor = FuncDef(aname, {}, abody, "auto", token=atok)
|
|
1600
|
+
if aname == "get":
|
|
1601
|
+
get = accessor
|
|
1602
|
+
else:
|
|
1603
|
+
setm = accessor
|
|
1604
|
+
else:
|
|
1605
|
+
stmt, pos = parse_statement(tokens, pos)
|
|
1606
|
+
if isinstance(stmt, FuncDef):
|
|
1607
|
+
if stmt.name == "get":
|
|
1608
|
+
get = stmt
|
|
1609
|
+
elif stmt.name == "set":
|
|
1610
|
+
setm = stmt
|
|
1611
|
+
while pos < len(tokens) and tokens[pos].type == TokenType.NEWLINE:
|
|
1612
|
+
pos += 1
|
|
1613
|
+
if pos < len(tokens) and tokens[pos].type == TokenType.DEDENT:
|
|
1614
|
+
pos += 1
|
|
1615
|
+
if get is None:
|
|
1616
|
+
raise ParseError("Expected a `get` accessor in property block", tok)
|
|
1617
|
+
return PropertyDef(name, get, setm, token=tok), pos
|
|
1618
|
+
|
|
1619
|
+
|
|
1431
1620
|
def parse_try(tokens: list[Token], pos: int):
|
|
1432
1621
|
tok = tokens[pos]
|
|
1433
1622
|
pos += 1
|
|
@@ -1706,6 +1895,7 @@ class FuncDef(Node):
|
|
|
1706
1895
|
"const_params",
|
|
1707
1896
|
"decorators",
|
|
1708
1897
|
"generic_params",
|
|
1898
|
+
"meta",
|
|
1709
1899
|
"name",
|
|
1710
1900
|
"params",
|
|
1711
1901
|
"rettype",
|
|
@@ -1732,6 +1922,7 @@ class FuncDef(Node):
|
|
|
1732
1922
|
self.generic_params = generic_params or []
|
|
1733
1923
|
self.const_params = const_params or []
|
|
1734
1924
|
self.decorators = decorators or []
|
|
1925
|
+
self.meta = None
|
|
1735
1926
|
self._token = token
|
|
1736
1927
|
|
|
1737
1928
|
def __repr__(self):
|
|
@@ -1928,7 +2119,7 @@ class Raise(Node):
|
|
|
1928
2119
|
|
|
1929
2120
|
|
|
1930
2121
|
class NewExpr(Node):
|
|
1931
|
-
__slots__ = ("_token", "size", "type_expr", "args")
|
|
2122
|
+
__slots__ = ("_token", "size", "type_expr", "args", "inferred_type")
|
|
1932
2123
|
|
|
1933
2124
|
def __init__(self, type_expr, size=None, token=None, args=None):
|
|
1934
2125
|
self.type_expr = type_expr
|
|
@@ -1993,6 +2184,27 @@ class CastExpr(Node):
|
|
|
1993
2184
|
return f"CastExpr({self.type_expr}, {self.expr})"
|
|
1994
2185
|
|
|
1995
2186
|
|
|
2187
|
+
class AsExpr(Node):
|
|
2188
|
+
"""`expr as T` — safe runtime downcast (C#/Kotlin style).
|
|
2189
|
+
|
|
2190
|
+
`x as T` returns `x` re-typed as `T*` when the runtime class of `x` is a
|
|
2191
|
+
descendant-or-equal of `T` (checked through the class-id RTTI ancestor
|
|
2192
|
+
grid), and `null` otherwise. Unlike a parenthesized `(T)x` hard cast, an
|
|
2193
|
+
`as` that fails yields null rather than silently re-typing the pointer.
|
|
2194
|
+
"""
|
|
2195
|
+
|
|
2196
|
+
__slots__ = ("_token", "inferred_type", "type_expr", "expr", "meta")
|
|
2197
|
+
|
|
2198
|
+
def __init__(self, type_expr: str, expr, token=None):
|
|
2199
|
+
self.type_expr = type_expr
|
|
2200
|
+
self.expr = expr
|
|
2201
|
+
self._token = token
|
|
2202
|
+
self.inferred_type = None
|
|
2203
|
+
|
|
2204
|
+
def __repr__(self):
|
|
2205
|
+
return f"AsExpr({self.expr} as {self.type_expr})"
|
|
2206
|
+
|
|
2207
|
+
|
|
1996
2208
|
class BorrowExpr(Node):
|
|
1997
2209
|
"""`borrow x` or `borrow mut x` — create a reference to x.
|
|
1998
2210
|
|
|
@@ -2123,10 +2335,12 @@ class ClassDef(Node):
|
|
|
2123
2335
|
__slots__ = (
|
|
2124
2336
|
"_token",
|
|
2125
2337
|
"base",
|
|
2338
|
+
"dataclass",
|
|
2126
2339
|
"fields",
|
|
2127
2340
|
"generic_params",
|
|
2128
2341
|
"methods",
|
|
2129
2342
|
"name",
|
|
2343
|
+
"properties",
|
|
2130
2344
|
"sealed",
|
|
2131
2345
|
)
|
|
2132
2346
|
|
|
@@ -2138,6 +2352,8 @@ class ClassDef(Node):
|
|
|
2138
2352
|
methods: list | None = None,
|
|
2139
2353
|
generic_params: list | None = None,
|
|
2140
2354
|
sealed: bool = False,
|
|
2355
|
+
dataclass: bool = False,
|
|
2356
|
+
properties: list | None = None,
|
|
2141
2357
|
token=None,
|
|
2142
2358
|
):
|
|
2143
2359
|
self.name = name
|
|
@@ -2146,11 +2362,30 @@ class ClassDef(Node):
|
|
|
2146
2362
|
self.methods = methods or []
|
|
2147
2363
|
self.generic_params = generic_params or []
|
|
2148
2364
|
self.sealed = sealed
|
|
2365
|
+
self.dataclass = dataclass
|
|
2366
|
+
self.properties = properties or []
|
|
2149
2367
|
self._token = token
|
|
2150
2368
|
|
|
2151
2369
|
def __repr__(self):
|
|
2152
2370
|
seal = "sealed " if self.sealed else ""
|
|
2153
|
-
|
|
2371
|
+
dc = "dataclass " if self.dataclass else ""
|
|
2372
|
+
return f"ClassDef({seal}{dc}{self.name}, base={self.base}, fields={self.fields}, properties={self.properties}, methods={self.methods})"
|
|
2373
|
+
|
|
2374
|
+
|
|
2375
|
+
class PropertyDef(Node):
|
|
2376
|
+
"""A `property name:` block holding paired `get`/`set` accessor bodies."""
|
|
2377
|
+
|
|
2378
|
+
__slots__ = ("_token", "name", "get", "set", "_ptype")
|
|
2379
|
+
|
|
2380
|
+
def __init__(self, name: str, get, set=None, token=None):
|
|
2381
|
+
self.name = name
|
|
2382
|
+
self.get = get
|
|
2383
|
+
self.set = set
|
|
2384
|
+
self._ptype = None
|
|
2385
|
+
self._token = token
|
|
2386
|
+
|
|
2387
|
+
def __repr__(self):
|
|
2388
|
+
return f"PropertyDef({self.name}, get={self.get and self.get.name}, set={self.set and self.set.name})"
|
|
2154
2389
|
|
|
2155
2390
|
|
|
2156
2391
|
def parse_ccode(tokens: list[Token], pos: int):
|
|
@@ -2649,6 +2884,8 @@ def parse_statement(tokens: list[Token], pos: int):
|
|
|
2649
2884
|
"import",
|
|
2650
2885
|
"enum",
|
|
2651
2886
|
"type",
|
|
2887
|
+
"sealed",
|
|
2888
|
+
"dataclass",
|
|
2652
2889
|
):
|
|
2653
2890
|
handler = {
|
|
2654
2891
|
"while": parse_while,
|
|
@@ -2658,6 +2895,8 @@ def parse_statement(tokens: list[Token], pos: int):
|
|
|
2658
2895
|
"import": parse_import,
|
|
2659
2896
|
"enum": parse_enum,
|
|
2660
2897
|
"type": parse_type_alias,
|
|
2898
|
+
"sealed": parse_sealed_class,
|
|
2899
|
+
"dataclass": parse_dataclass_class,
|
|
2661
2900
|
}[tok.value]
|
|
2662
2901
|
return handler(tokens, pos)
|
|
2663
2902
|
|