cpyte 4.2.2__tar.gz → 4.2.3__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.2/source/cpyte.egg-info → cpyte-4.2.3}/PKG-INFO +1 -1
- cpyte-4.2.3/source/cpyte/__init__.py +143 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/_bignum_bc.py +3 -2
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/_runtime_bc.py +3 -2
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/astparse.py +44 -1
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/bytecoding.py +260 -10
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/compiling.py +2 -2
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/formatter.py +4 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/lexar.py +1 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/linker.py +8 -3
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/mainpie.py +1 -1
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/optimizations.py +26 -59
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/semantic_analasis.py +395 -17
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/winjit_patch.py +25 -25
- {cpyte-4.2.2 → cpyte-4.2.3/source/cpyte.egg-info}/PKG-INFO +1 -1
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte.egg-info/SOURCES.txt +2 -1
- cpyte-4.2.3/test/test_fuzz_del_has.py +544 -0
- cpyte-4.2.2/source/cpyte/__init__.py +0 -1
- {cpyte-4.2.2 → cpyte-4.2.3}/MANIFEST.in +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/pyproject.toml +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/readme.md +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/setup.cfg +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/__main__.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/bignum.c +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/clib.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/extension_hooks.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/gc_runtime.c +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/generate_bc.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/lsp_server.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/package_manifest.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/runtime.c +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/runtime_scorpion.c +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/sef.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/ugc.h +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/ui.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/update_check.py +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte/winjit_stubs.c +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte.egg-info/dependency_links.txt +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte.egg-info/entry_points.txt +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte.egg-info/requires.txt +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/source/cpyte.egg-info/top_level.txt +0 -0
- {cpyte-4.2.2 → cpyte-4.2.3}/test/test_bignum_jit.py +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
__version__ = "4.2.3"
|
|
2
|
+
|
|
3
|
+
# ---------------------------------------------------------------------------
|
|
4
|
+
# Public library API.
|
|
5
|
+
#
|
|
6
|
+
# Consumers should import ONLY the ``cpyte`` package and use these entry
|
|
7
|
+
# points (``import cpyte; cpyte.parse_and_analyze(...)``) instead of reaching
|
|
8
|
+
# into ``cpyte.astparse`` / ``cpyte.lexar`` / ``cpyte.semantic_analasis`` /
|
|
9
|
+
# ``cpyte.bytecoding`` / ``cpyte.compiling`` internals. Everything here is an
|
|
10
|
+
# additive re-export or thin wrapper: compiler behavior is unchanged.
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
from . import astparse, bytecoding, compiling, lexar, mainpie, semantic_analasis, ui
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CpyteCompileError(Exception):
|
|
17
|
+
"""Raised by the high-level library entry points on parse / analyze /
|
|
18
|
+
codegen failure (library calls never ``sys.exit``)."""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def parse_and_analyze(
|
|
22
|
+
source,
|
|
23
|
+
*,
|
|
24
|
+
tab_size=4,
|
|
25
|
+
strict=False,
|
|
26
|
+
enable_extensions=True,
|
|
27
|
+
no_gc=False,
|
|
28
|
+
filepath=None,
|
|
29
|
+
workspace_root=None,
|
|
30
|
+
):
|
|
31
|
+
"""Lex + parse + semantically analyze ``source``.
|
|
32
|
+
|
|
33
|
+
Returns ``(parsed, generic_instantiations, warnings_txt)`` or raises
|
|
34
|
+
:class:`CpyteCompileError`. Loads workspace package manifests when
|
|
35
|
+
extensions are enabled (same behavior as ``cpy build``).
|
|
36
|
+
"""
|
|
37
|
+
if workspace_root is None:
|
|
38
|
+
workspace_root = mainpie._find_workspace_root(filepath)
|
|
39
|
+
if enable_extensions:
|
|
40
|
+
mainpie._load_package_manifests_from_source(workspace_root)
|
|
41
|
+
lex = lexar.Lexer(source, tab_size=tab_size, enable_extensions=enable_extensions)
|
|
42
|
+
tokens = lex.get_tokens()
|
|
43
|
+
try:
|
|
44
|
+
parsed, _ = astparse.parse_file(tokens, enable_extensions=enable_extensions)
|
|
45
|
+
except (lexar.LexerError, astparse.ParseError) as e:
|
|
46
|
+
raise CpyteCompileError(f"parse error: {e}") from e
|
|
47
|
+
result, warnings_txt, generic_instantiations = semantic_analasis.analyze(
|
|
48
|
+
source,
|
|
49
|
+
parsed,
|
|
50
|
+
strict=strict,
|
|
51
|
+
workspace_root=workspace_root,
|
|
52
|
+
filepath=filepath,
|
|
53
|
+
enable_extensions=enable_extensions,
|
|
54
|
+
no_gc=no_gc,
|
|
55
|
+
)
|
|
56
|
+
if result:
|
|
57
|
+
raise CpyteCompileError(str(result).rstrip())
|
|
58
|
+
return parsed, generic_instantiations, warnings_txt
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def emit_program(
|
|
62
|
+
parsed,
|
|
63
|
+
*,
|
|
64
|
+
generic_instantiations=None,
|
|
65
|
+
no_userspace=False,
|
|
66
|
+
enable_extensions=True,
|
|
67
|
+
no_gc=False,
|
|
68
|
+
use_native_eh=False,
|
|
69
|
+
debug_instrument=False,
|
|
70
|
+
debug_nids=None,
|
|
71
|
+
debug_step_ids=None,
|
|
72
|
+
):
|
|
73
|
+
"""Emit LLVM IR for a parsed module.
|
|
74
|
+
|
|
75
|
+
Returns ``(module, src_files, emitter)``; the emitter carries the
|
|
76
|
+
``_dbg_*`` debug metadata (tracer symbols, box slots/types) when
|
|
77
|
+
``debug_instrument`` is enabled. Raises :class:`CpyteCompileError` on
|
|
78
|
+
codegen failure.
|
|
79
|
+
"""
|
|
80
|
+
c = bytecoding.LLVM(
|
|
81
|
+
no_userspace=no_userspace,
|
|
82
|
+
enable_extensions=enable_extensions,
|
|
83
|
+
no_gc=no_gc,
|
|
84
|
+
use_native_eh=use_native_eh,
|
|
85
|
+
debug_instrument=debug_instrument,
|
|
86
|
+
debug_nids=debug_nids,
|
|
87
|
+
debug_step_ids=debug_step_ids,
|
|
88
|
+
)
|
|
89
|
+
c.generic_instantiations = generic_instantiations or {}
|
|
90
|
+
try:
|
|
91
|
+
prog, src_files = c.emit_program(parsed)
|
|
92
|
+
except Exception as e:
|
|
93
|
+
raise CpyteCompileError(f"codegen error: {type(e).__name__}: {e}") from e
|
|
94
|
+
return prog, src_files, c
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# -- low-level re-exports (the whole compiler usable from one package) ------
|
|
98
|
+
from .astparse import ( # noqa: F401
|
|
99
|
+
Assert,
|
|
100
|
+
Assign,
|
|
101
|
+
Break,
|
|
102
|
+
Call,
|
|
103
|
+
ClassDef,
|
|
104
|
+
Continue,
|
|
105
|
+
DeferStmt,
|
|
106
|
+
DelStmt,
|
|
107
|
+
EnumDef,
|
|
108
|
+
ExprStmt,
|
|
109
|
+
FuncDef,
|
|
110
|
+
If,
|
|
111
|
+
Import,
|
|
112
|
+
ParseError,
|
|
113
|
+
Print,
|
|
114
|
+
Raise,
|
|
115
|
+
Return,
|
|
116
|
+
StructDef,
|
|
117
|
+
Switch,
|
|
118
|
+
Try,
|
|
119
|
+
TypeAlias,
|
|
120
|
+
VarDecl,
|
|
121
|
+
While,
|
|
122
|
+
parse_file,
|
|
123
|
+
)
|
|
124
|
+
from .bytecoding import LLVM # noqa: F401
|
|
125
|
+
from .compiling import ( # noqa: F401
|
|
126
|
+
Linker,
|
|
127
|
+
LinkerNotFoundError,
|
|
128
|
+
host_target,
|
|
129
|
+
run_aot,
|
|
130
|
+
run_jit,
|
|
131
|
+
)
|
|
132
|
+
from .compiling import _host_default_pic as host_default_pic
|
|
133
|
+
from .lexar import Lexer, LexerError # noqa: F401
|
|
134
|
+
from .mainpie import ( # noqa: F401
|
|
135
|
+
_collect_frameworks as collect_frameworks,
|
|
136
|
+
)
|
|
137
|
+
from .mainpie import (
|
|
138
|
+
_detect_nogc as detect_nogc,
|
|
139
|
+
)
|
|
140
|
+
from .mainpie import (
|
|
141
|
+
_find_workspace_root as find_workspace_root,
|
|
142
|
+
)
|
|
143
|
+
from .semantic_analasis import analyze # noqa: F401
|
|
@@ -142,7 +142,14 @@ class ListLit(Node):
|
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
class Call(Node):
|
|
145
|
-
__slots__ = (
|
|
145
|
+
__slots__ = (
|
|
146
|
+
"_token",
|
|
147
|
+
"args",
|
|
148
|
+
"callee",
|
|
149
|
+
"inferred_type",
|
|
150
|
+
"param_types",
|
|
151
|
+
"meta",
|
|
152
|
+
)
|
|
146
153
|
|
|
147
154
|
def __init__(self, callee, args: list, token=None):
|
|
148
155
|
self.callee = callee
|
|
@@ -150,6 +157,7 @@ class Call(Node):
|
|
|
150
157
|
self._token = token
|
|
151
158
|
self.inferred_type = None
|
|
152
159
|
self.param_types = None
|
|
160
|
+
self.meta = None
|
|
153
161
|
|
|
154
162
|
def __repr__(self):
|
|
155
163
|
return f"Call({self.callee}, {self.args})"
|
|
@@ -1185,6 +1193,8 @@ def _parse_standard_statement(tokens: list[Token], pos: int):
|
|
|
1185
1193
|
node, pos = parse_break(tokens, pos)
|
|
1186
1194
|
elif tok.type == TokenType.KEYWORD and tok.value == "continue":
|
|
1187
1195
|
node, pos = parse_continue(tokens, pos)
|
|
1196
|
+
elif tok.type == TokenType.KEYWORD and tok.value == "del":
|
|
1197
|
+
node, pos = parse_del(tokens, pos)
|
|
1188
1198
|
elif tok.type == TokenType.KEYWORD and tok.value == "assert":
|
|
1189
1199
|
node, pos = parse_assert(tokens, pos)
|
|
1190
1200
|
elif tok.type == TokenType.KEYWORD and tok.value == "asm":
|
|
@@ -1987,6 +1997,26 @@ class DeferStmt(Node):
|
|
|
1987
1997
|
return f"DeferStmt({self.body!r})"
|
|
1988
1998
|
|
|
1989
1999
|
|
|
2000
|
+
class DelStmt(Node):
|
|
2001
|
+
"""`del <target>` — unbind a variable or clear a runtime slot.
|
|
2002
|
+
|
|
2003
|
+
Static locals are removed from the compiler scope (later uses become
|
|
2004
|
+
compile errors); dynamic/arena variables are marked deleted at runtime
|
|
2005
|
+
(kind DYN_NONE); heap pointers from `new`/`malloc` are freed; and
|
|
2006
|
+
`del obj.field` / `del arr[i]` / `del *p` clear the addressed slot.
|
|
2007
|
+
"""
|
|
2008
|
+
|
|
2009
|
+
__slots__ = ("_token", "target", "del_kind")
|
|
2010
|
+
|
|
2011
|
+
def __init__(self, target, token=None):
|
|
2012
|
+
self.target = target
|
|
2013
|
+
self._token = token
|
|
2014
|
+
self.del_kind = None # "static" | "dynamic" | "heap" | "slot", set by semantic
|
|
2015
|
+
|
|
2016
|
+
def __repr__(self):
|
|
2017
|
+
return f"DelStmt({self.target!r})"
|
|
2018
|
+
|
|
2019
|
+
|
|
1990
2020
|
class StructDef(Node):
|
|
1991
2021
|
__slots__ = ("_token", "fields", "generic_params", "name")
|
|
1992
2022
|
|
|
@@ -2502,12 +2532,25 @@ def parse_defer(tokens: list[Token], pos: int):
|
|
|
2502
2532
|
return DeferStmt(stmt, token=tok), pos
|
|
2503
2533
|
|
|
2504
2534
|
|
|
2535
|
+
def parse_del(tokens: list[Token], pos: int):
|
|
2536
|
+
tok = tokens[pos] # 'del'
|
|
2537
|
+
pos += 1
|
|
2538
|
+
if pos >= len(tokens):
|
|
2539
|
+
raise ParseError("Expected an expression after `del`", tok)
|
|
2540
|
+
target, pos = parse_expression(tokens, pos)
|
|
2541
|
+
_expect_newline(tokens, pos, tok)
|
|
2542
|
+
return DelStmt(target, token=tok), pos
|
|
2543
|
+
|
|
2544
|
+
|
|
2505
2545
|
def parse_statement(tokens: list[Token], pos: int):
|
|
2506
2546
|
if pos >= len(tokens):
|
|
2507
2547
|
return None, pos
|
|
2508
2548
|
|
|
2509
2549
|
tok = tokens[pos]
|
|
2510
2550
|
|
|
2551
|
+
if tok.type == TokenType.KEYWORD and tok.value == "del":
|
|
2552
|
+
return parse_del(tokens, pos)
|
|
2553
|
+
|
|
2511
2554
|
if tok.type == TokenType.KEYWORD and tok.value == "return":
|
|
2512
2555
|
return parse_return(tokens, pos)
|
|
2513
2556
|
|