@pineforge/codegen-pyodide 0.9.0 → 0.10.1
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.
- package/package.json +1 -1
- package/pineforge_codegen/__init__.py +3 -0
- package/pineforge_codegen/analyzer/base.py +3999 -140
- package/pineforge_codegen/analyzer/call_handlers.py +662 -48
- package/pineforge_codegen/analyzer/contracts.py +104 -7
- package/pineforge_codegen/analyzer/types.py +951 -14
- package/pineforge_codegen/codegen/base.py +2359 -249
- package/pineforge_codegen/codegen/drawing.py +94 -14
- package/pineforge_codegen/codegen/emit_top.py +732 -172
- package/pineforge_codegen/codegen/security.py +1456 -150
- package/pineforge_codegen/codegen/ta.py +435 -99
- package/pineforge_codegen/codegen/tables.py +224 -77
- package/pineforge_codegen/codegen/types.py +1196 -215
- package/pineforge_codegen/codegen/visit_call.py +1168 -99
- package/pineforge_codegen/codegen/visit_expr.py +354 -33
- package/pineforge_codegen/codegen/visit_stmt.py +1144 -200
- package/pineforge_codegen/finite_ta_length.py +798 -0
- package/pineforge_codegen/method_binding.py +163 -0
- package/pineforge_codegen/parser.py +48 -9
- package/pineforge_codegen/signatures.py +4 -4
- package/pineforge_codegen/support_checker.py +194 -19
- package/pineforge_codegen/symbols.py +65 -0
- package/pineforge_codegen-0.10.1.tar.gz +0 -0
- package/release.json +2 -2
- package/tables.json +9 -11
- package/pineforge_codegen-0.9.0.tar.gz +0 -0
|
@@ -24,7 +24,7 @@ from __future__ import annotations
|
|
|
24
24
|
from dataclasses import dataclass, field
|
|
25
25
|
from typing import Any
|
|
26
26
|
|
|
27
|
-
from ..symbols import TypeSpec
|
|
27
|
+
from ..symbols import PineType, TypeSpec
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@dataclass
|
|
@@ -88,11 +88,12 @@ class FuncInfo:
|
|
|
88
88
|
# ``pivot hi`` parameter emits as ``pivot hi`` (not ``double hi``) and an
|
|
89
89
|
# untyped ``s`` used as a string emits as ``std::string s``.
|
|
90
90
|
param_type_specs: list = field(default_factory=list)
|
|
91
|
-
# ``TypeSpec`` of the function's return value when
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
91
|
+
# Exact ``TypeSpec`` of the function's return value when downstream
|
|
92
|
+
# expression inference needs more than the coarse ``return_type`` slot.
|
|
93
|
+
# This primarily carries arrays/maps and also direct-terminal primitive
|
|
94
|
+
# array-element reads, whose cached spec prevents inference from re-visiting
|
|
95
|
+
# a stateful UDF call. UDT / drawing-handle returns use ``udt_return_type``;
|
|
96
|
+
# tuple returns use ``returns_tuple``.
|
|
96
97
|
return_type_spec: Any = None
|
|
97
98
|
|
|
98
99
|
|
|
@@ -137,6 +138,12 @@ class SecurityCallInfo:
|
|
|
137
138
|
expression: Any
|
|
138
139
|
returns_tuple: bool
|
|
139
140
|
tuple_size: int
|
|
141
|
+
# Exact helper/direct tuple element types. Empty for scalar calls and for
|
|
142
|
+
# legacy/TA tuple records whose runtime result struct already defines its
|
|
143
|
+
# field types. User-defined request.security helpers use this to select
|
|
144
|
+
# numeric-double versus homogeneous-bool aggregate storage without
|
|
145
|
+
# guessing in codegen.
|
|
146
|
+
tuple_element_types: tuple[PineType, ...] = ()
|
|
140
147
|
gaps: Any = None
|
|
141
148
|
lookahead: Any = None
|
|
142
149
|
ta_range: Any = None
|
|
@@ -181,6 +188,22 @@ class AnalyzerContext:
|
|
|
181
188
|
symbols: Any # SymbolTable
|
|
182
189
|
ta_call_sites: list = field(default_factory=list)
|
|
183
190
|
series_vars: set = field(default_factory=set)
|
|
191
|
+
# Exact emitted member identities for persistent ``var``/``varip``
|
|
192
|
+
# bindings that are history-referenced. Unlike ``series_vars`` this set
|
|
193
|
+
# preserves sibling-block renames such as ``x__blk1``.
|
|
194
|
+
series_var_members: set = field(default_factory=set)
|
|
195
|
+
# Exact VarDecl node ids whose binding is history-referenced. This lets
|
|
196
|
+
# codegen distinguish a scalar local shadow from a same-named global
|
|
197
|
+
# Series without relying on the raw-name union above.
|
|
198
|
+
series_decl_nodes: set = field(default_factory=set)
|
|
199
|
+
# Exact declaration binding keys ``(node_id, raw_name)``. TupleAssign has
|
|
200
|
+
# one AST node for several independently scoped names, so node identity
|
|
201
|
+
# alone cannot say which destructured element owns history storage.
|
|
202
|
+
series_decl_bindings: set = field(default_factory=set)
|
|
203
|
+
# Raw names of exact declaration-bound, non-persistent Series storage.
|
|
204
|
+
# This excludes history parameters and global reads observed from inside a
|
|
205
|
+
# callable, both of which also appear in legacy raw series inventories.
|
|
206
|
+
nonpersistent_series_decl_names: set = field(default_factory=set)
|
|
184
207
|
series_bar_fields: set = field(default_factory=set)
|
|
185
208
|
var_members: list = field(default_factory=list) # [(name, PineType, init_expr_str)]
|
|
186
209
|
func_infos: list = field(default_factory=list)
|
|
@@ -198,11 +221,43 @@ class AnalyzerContext:
|
|
|
198
221
|
filename: str = "<stdin>"
|
|
199
222
|
global_var_decls: list = field(default_factory=list) # [(name, PineType)] non-var global scope vars
|
|
200
223
|
global_expr_map: dict = field(default_factory=dict) # name -> defining AST expr (global, non-var)
|
|
224
|
+
# Exact lexical binding scope for each visited Identifier AST node. Raw
|
|
225
|
+
# name lookup is not enough once a UDF parameter, block local, or loop
|
|
226
|
+
# iterator shadows a same-spelled global binding.
|
|
227
|
+
identifier_binding_scopes: dict = field(default_factory=dict) # id(Identifier) -> scope name | None
|
|
201
228
|
var_member_init_exprs: dict = field(default_factory=dict) # var-member name -> init AST expr
|
|
229
|
+
# id(VarDecl) -> (node, emitted member name, PineType, rendered initializer,
|
|
230
|
+
# is function/method scoped)
|
|
231
|
+
var_member_metadata_by_node: dict = field(default_factory=dict)
|
|
232
|
+
# id(VarDecl) -> exact structured declaration type. Name-keyed type
|
|
233
|
+
# registries cannot distinguish sibling/callable persistent bindings.
|
|
234
|
+
var_member_type_specs_by_node: dict = field(default_factory=dict)
|
|
235
|
+
# id(VarDecl) -> owning callable key (``FuncInfo.name``), or None for
|
|
236
|
+
# top-level/on-bar persistent bindings.
|
|
237
|
+
var_member_owners_by_node: dict = field(default_factory=dict)
|
|
202
238
|
# Per-call-site TA member cloning for user functions:
|
|
203
239
|
func_ta_ranges: dict = field(default_factory=dict) # func_name -> (start_idx, end_idx)
|
|
240
|
+
# Exact TA indices belonging to each callable path. ``func_ta_ranges`` is
|
|
241
|
+
# retained as the legacy stateful-callable marker, but a widened min/max
|
|
242
|
+
# range can contain unrelated sites allocated between two borrowed sites.
|
|
243
|
+
func_ta_indices: dict = field(default_factory=dict) # func_name -> [site_idx, ...]
|
|
204
244
|
func_call_cs_map: dict = field(default_factory=dict) # call_node_id -> (func_name, call_site_index)
|
|
245
|
+
# Removed lexical nested-call mappings inherit their natural parent's
|
|
246
|
+
# active cs index. Fresh context-sensitive parents have no such index, so
|
|
247
|
+
# codegen uses this exact node -> callee identity to compose dispatch.
|
|
248
|
+
func_inherited_call_names: dict = field(default_factory=dict)
|
|
205
249
|
func_call_site_counts: dict = field(default_factory=dict) # func_name -> int
|
|
250
|
+
# Exact primitive parameter/return types for each emitted written-callsite
|
|
251
|
+
# variant. Untyped Pine parameters are independently specialized at every
|
|
252
|
+
# written call; collapsing these onto FuncInfo's first observed type makes
|
|
253
|
+
# generated semantics depend on source order (for example one ``src[1]``
|
|
254
|
+
# helper called with both ``bar_index`` and ``close``).
|
|
255
|
+
func_callsite_param_types: dict = field(default_factory=dict)
|
|
256
|
+
func_callsite_return_types: dict = field(default_factory=dict)
|
|
257
|
+
# Declaration-time parameter specs, before any call-site inference fills
|
|
258
|
+
# untyped slots on the legacy FuncInfo record. Codegen uses this to apply
|
|
259
|
+
# variant overrides only to genuinely untyped parameters.
|
|
260
|
+
func_declared_param_type_specs: dict = field(default_factory=dict)
|
|
206
261
|
# Functions that need per-call-site body cloning PURELY because they
|
|
207
262
|
# contain a request.security(...) whose timeframe is a UDF parameter
|
|
208
263
|
# called with >= 2 distinct literal timeframes (the security-tf-
|
|
@@ -225,15 +280,57 @@ class AnalyzerContext:
|
|
|
225
280
|
# request.security calls (see SecurityCallInfo):
|
|
226
281
|
security_calls: list = field(default_factory=list)
|
|
227
282
|
global_mutable_infos: dict = field(default_factory=dict) # name -> MutableGlobalInfo
|
|
283
|
+
# AST-authoritative top-level non-var binding names. Unlike
|
|
284
|
+
# ``global_var_decls``, this is not filtered through legacy raw Series
|
|
285
|
+
# tracking and therefore survives same-named callable history state.
|
|
286
|
+
ordinary_global_binding_names: set = field(default_factory=set)
|
|
287
|
+
# Exact subset whose own top-level declaration is history-bearing. A raw
|
|
288
|
+
# callable Series name does not promote a same-named scalar/map global.
|
|
289
|
+
ordinary_global_series_names: set = field(default_factory=set)
|
|
228
290
|
# Per-function var_members + series_vars (used when emitting per-function call-site variants):
|
|
229
291
|
func_var_members: dict = field(default_factory=dict)
|
|
292
|
+
# Ordinary FuncDef persistent locals keep their Pine spelling in
|
|
293
|
+
# ``func_var_members`` for lexical/type analysis. When its storage would
|
|
294
|
+
# collide with another persistent lexical declaration, this owner-scoped
|
|
295
|
+
# overlay carries the collision-safe class-member identity instead:
|
|
296
|
+
# ``func_name -> {raw_name: emitted_member_name}``.
|
|
297
|
+
#
|
|
298
|
+
# Keeping lexical and storage identity separate is important. Clone maps
|
|
299
|
+
# operate on emitted members, while a function body must not see the new
|
|
300
|
+
# member until its declaration has executed (so an earlier same-named
|
|
301
|
+
# global read remains lexical Pine, not the future local).
|
|
302
|
+
func_var_storage_names: dict = field(default_factory=dict)
|
|
230
303
|
func_series_vars: dict = field(default_factory=dict)
|
|
231
|
-
#
|
|
304
|
+
# FuncDef owner -> declaration-bound non-persistent history-local names.
|
|
305
|
+
# Parameters are deliberately excluded so a same-named qualified
|
|
306
|
+
# persistent member does not manufacture a bogus raw/clone Series.
|
|
307
|
+
func_nonpersistent_series_vars: dict = field(default_factory=dict)
|
|
308
|
+
# Per-function exact return TypeSpec (see FuncInfo.return_type_spec).
|
|
232
309
|
func_return_type_specs: dict = field(default_factory=dict)
|
|
233
310
|
# var_name -> UDT type name for variables instantiated via TypeName.new(...)
|
|
234
311
|
udt_var_types: dict[str, str] = field(default_factory=dict)
|
|
235
312
|
# var_name -> structured collection/UDT type metadata
|
|
236
313
|
collection_types: dict[str, TypeSpec] = field(default_factory=dict)
|
|
314
|
+
# Stable callable key -> raw local name -> collection TypeSpec. Function
|
|
315
|
+
# and method locals are lexical: two callables may both declare ``values``
|
|
316
|
+
# with unrelated collection kinds/element types, so they cannot share the
|
|
317
|
+
# top-level raw-name registry above.
|
|
318
|
+
func_collection_types: dict[str, dict[str, TypeSpec]] = field(default_factory=dict)
|
|
319
|
+
# id(immediate branch/loop owner) -> raw local name -> collection TypeSpec.
|
|
320
|
+
# Sibling lexical blocks may reuse one raw name with unrelated kinds, so
|
|
321
|
+
# their bindings cannot be collapsed into ``func_collection_types``.
|
|
322
|
+
block_collection_types: dict[int, dict[str, TypeSpec | None]] = field(default_factory=dict)
|
|
323
|
+
# Block id -> owning FuncInfo key. Used for dead-callable header filtering
|
|
324
|
+
# and exact persistent-member TypeSpec lookup outside callable emission.
|
|
325
|
+
block_collection_owners: dict[int, str] = field(default_factory=dict)
|
|
326
|
+
# id(callable-local VarDecl) -> exact collection TypeSpec, or None for a
|
|
327
|
+
# non-collection declaration that lexically tombstones an outer binding.
|
|
328
|
+
callable_collection_bindings: dict[int, TypeSpec | None] = field(default_factory=dict)
|
|
329
|
+
# Declaration node id -> owning callable key. Persistent-member emission
|
|
330
|
+
# happens outside the analyzer's lexical scope, so raw names alone cannot
|
|
331
|
+
# distinguish a real persistent collection from a same-named ordinary
|
|
332
|
+
# local in another callable.
|
|
333
|
+
callable_collection_binding_owners: dict[int, str] = field(default_factory=dict)
|
|
237
334
|
# UDT name -> field_name -> structured type metadata
|
|
238
335
|
udt_field_type_specs: dict[str, dict[str, TypeSpec]] = field(default_factory=dict)
|
|
239
336
|
# id(block_node) -> {raw_var_name: scope_unique_member_name} for block-scoped
|