diff --git a/.github/workflows/fuzzer.yml b/.github/workflows/fuzzer.yml
index 64d3bd0..67daabe 100644
--- a/.github/workflows/fuzzer.yml
+++ b/.github/workflows/fuzzer.yml
@@ -44,4 +44,4 @@ jobs:
run: pip install -r requirements-dev.txt
- name: Run fuzzer (${{ inputs.iterations }} iterations)
run: |
- python fuzz.py -n ${{ inputs.iterations }}
+ python -m scripts.fuzz -n ${{ inputs.iterations }}
diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index ced6e37..64a9880 100644
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -16,17 +16,24 @@ jobs:
- "3.10"
- "3.11"
- "3.12"
+ - "3.13"
+ - "3.14"
+ fail-fast: false
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v7
- name: Setup python ${{ matrix.py_version }}
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.py_version }}
+ - name: Setup pythonfuzz
+ run: pip install -r requirements-dev.txt
- name: Run tests
run: |
- chmod +x ./run_tests.sh
- ./run_tests.sh --verbose
+ ./scripts/run_tests.sh --verbose
- name: Run mini-benchmark
run: |
- python ./benchmark.py
+ python -m scripts.benchmark
+ # Just to detect ultra-obvious bugs that our tests missed
+ - name: Run quick fuzzing (20000 iterations)
+ run: python -m scripts.fuzz -n 20000
diff --git a/.idea/inspectionProfiles/project_inspections.xml b/.idea/inspectionProfiles/project_inspections.xml
index 47654a1..552c34f 100644
--- a/.idea/inspectionProfiles/project_inspections.xml
+++ b/.idea/inspectionProfiles/project_inspections.xml
@@ -15,6 +15,15 @@
+
+
+
+
@@ -22,7 +31,35 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1e0a65c..4dcf192 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/.idea/programming_lang_2.iml b/.idea/programming_lang_2.iml
index 9ece612..ef786b5 100644
--- a/.idea/programming_lang_2.iml
+++ b/.idea/programming_lang_2.iml
@@ -4,8 +4,9 @@
+
-
+
\ No newline at end of file
diff --git a/detect_unused.sh b/detect_unused.sh
deleted file mode 100644
index 93e1100..0000000
--- a/detect_unused.sh
+++ /dev/null
@@ -1 +0,0 @@
-vulture ./parser ./main.py ./fuzz.py ./test --ignore-decorators="@_register_autowalk_expr*" --exclude="parser/astgen/ast_print.py"
diff --git a/main_example_0.st b/examples/main_example_0.st
similarity index 100%
rename from main_example_0.st
rename to examples/main_example_0.st
diff --git a/main_example_1.st b/examples/main_example_1.st
similarity index 100%
rename from main_example_1.st
rename to examples/main_example_1.st
diff --git a/main_example_2.st b/examples/main_example_2.st
similarity index 100%
rename from main_example_2.st
rename to examples/main_example_2.st
diff --git a/examples/main_example_3.st b/examples/main_example_3.st
new file mode 100644
index 0000000..0a79358
--- /dev/null
+++ b/examples/main_example_3.st
@@ -0,0 +1,146 @@
+global false = 0;
+global true = 1; // temporary
+/*intrinsic*/def len(/*list*/val a) {}
+/*intrinsic*/def delitem(/*list*/val a, number idx) {}
+
+global[] psHeap = [];
+global[] _psHeap_freelist = [];
+
+def _PsHeap_FinalizeObj(number ptr) {
+ // Dispatch finalizer here, decref components, etc.
+}
+
+global __result__; // TODO: some syntax sugar for return?
+def PsHeap_AllocWord() {
+ _psHeap_freelist__len();
+ if __result__ > 0 {
+ __result__ = _psHeap_freelist[0];
+ _psHeap_freelist__delitem(0);
+ if COUNT_REFS != 0 {
+ refStack[__result__] = 1;
+ }
+ } else {
+ // TODO: figure out list syntax
+ psHeap__append('');
+ psHeap__len(); // sets __result__
+ if COUNT_REFS != 0 {
+ refStack__append(1);
+ }
+ }
+}
+/** Note: Doesn't finalize! */
+def PsHeap_FreeWord(number ptr) {
+ psHeap[ptr] = ''; // Next person can't read what was here
+ if COUNT_REFS != 0 {
+ refStack[ptr] = 0;
+ }
+ _psHeap_freelist__append(ptr);
+}
+def PsHeap_DeleteWord(number ptr) {
+ _PsHeap_FinalizeObj(ptr);
+ PsHeap_FreeWord(ptr);
+}
+
+global[] refStack = [];
+/*intrinsic method*/def refStack__append(val x) {}
+/*intrinsic method*/def stack__append(val x) {}
+/*intrinsic method*/def lenStack() {}
+/*intrinsic method*/def stackDelitem(val x) {}
+/*intrinsic method*/def psHeap__append(val x) {}
+/*intrinsic method*/def _psHeap_freelist__append(val x) {}
+/*intrinsic method*/def _psHeap_freelist__delitem(val x) {}
+/*intrinsic method*/def _psHeap_freelist__len() {}
+/*intrinsic method*/def psHeap__len() {}
+
+def decref(number ptr) {
+ if refStack[ptr] >= 0 { // negative refcount indicates immortal objects
+ refStack[ptr] = refStack[ptr] - 1;
+ if refStack[ptr] == 0 {
+ PsHeap_DeleteWord(ptr);
+ }
+ }
+}
+def incref(number ptr) {
+ if refStack[ptr] >= 0 { // negative refcount indicates immortal objects
+ refStack[ptr] = refStack[ptr] + 1; // TODO: support += on list accesses
+ }
+}
+// implement GC that can do cycles
+
+
+global[] stack = [];
+global COUNT_REFS = false;
+
+// opcodes from python version 3.8:
+
+// opcodes from: https://unpyc.sourceforge.net/Opcodes.html
+// and https://harrisonmorgan.dev/2020/04/13/learning-cpython-bytecode-instructions/
+// also https://docs.python.org/3.8/library/dis.html#opcode-NOP for description
+// and https://github.com/python/cpython/blob/3.8/Lib/opcode.py#L58 for numbers
+
+def NOP() {}
+
+def POP_TOP() {
+ lenStack(); // -> __result__
+ if COUNT_REFS == true {
+ decref(stack[__result__]);
+ }
+ stackDelitem(__result__);
+}
+
+def ROT_TWO() {
+ lenStack();
+ let tos_idx = __result__;
+ let tos0 = stack[tos_idx];
+ stack[tos_idx] = stack[tos_idx - 1];
+ stack[tos_idx - 1] = tos0;
+}
+
+def ROT_THREE() {
+ // top = top-1
+ // top-1 = top-2
+ // top-2 = top
+ // i.e. move 2nd and 3rd up and move top to 3rd
+ lenStack();
+ let tos_idx = __result__;
+ let tos0 = stack[tos_idx];
+ stack[tos_idx] = stack[tos_idx - 1];
+ stack[tos_idx - 1] = stack[tos_idx - 2];
+ stack[tos_idx - 2] = tos0;
+}
+
+def DUP_TOP() {
+ lenStack();
+ let value = stack[__result__];
+ stack__append(value);
+ if COUNT_REFS != false {
+ incref(value);
+ }
+}
+
+def DUP_TOP_TWO() {
+ lenStack();
+ let tos_idx = __result__;
+ let tos0 = stack[tos_idx];
+ let tos1 = stack[tos_idx - 1];
+ stack__append(tos1);
+ stack__append(tos0); // keep tos0 at top
+ if COUNT_REFS != 0 {
+ incref(tos0);
+ incref(tos1);
+ }
+}
+
+def ROT_FOUR() {
+ // tos3 = tos
+ // tos = tos1
+ // tos1 = tos2
+ // tos2 = tos3
+ lenStack();
+ let tos_idx = __result__;
+ let tos0 = stack[tos_idx];
+ stack[tos_idx] = stack[tos_idx - 1];
+ stack[tos_idx - 1] = stack[tos_idx - 2];
+ stack[tos_idx - 2] = stack[tos_idx - 3];
+ stack[tos_idx - 3] = tos0;
+}
diff --git a/fuzz.py b/fuzz.py
deleted file mode 100644
index 2893b82..0000000
--- a/fuzz.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import time
-
-from parser.astgen.astgen import AstGen
-from parser.lexer.tokenizer import Tokenizer
-from parser.cst.cstgen import CstGen
-from parser.common.error import BaseParseError
-
-from pythonfuzz.fuzzer import Fuzzer
-import pythonfuzz.fuzzer as fuzzer_ns # For patching pythonfuzz
-
-from parser.typecheck.typecheck import NameResolver
-
-
-class UsePerfCounterInsteadOfTime:
- """Hack to avoid overwriting everyone's time module so we only
- overwrite `pythonfuzz`'s time module and don't modify the module itself.
- This hack is necessary because time.time() is rather inaccurate so
- it is possible that between 2 iterations, the difference in time.time() is 0
- which results in DivisionByZeroError (when calculating iterations/sec).
- Therefore, we replace with the more accurate time.perf_counter(),
- just for `pythonfuzz`"""
- def __getattr__(self, item):
- if item == 'time': # time.time
- item = 'perf_counter'
- return getattr(time, item)
-
-
-fuzzer_ns.time = UsePerfCounterInsteadOfTime()
-
-
-def fuzz(buf):
- try:
- string = buf.decode("ascii")
- try:
- NameResolver(AstGen(CstGen(Tokenizer(string)))).run()
- except BaseParseError:
- pass
- except UnicodeDecodeError:
- pass
-
-
-if __name__ == '__main__':
- import argparse
- ap = argparse.ArgumentParser("fuzz.py", description="Runs a fuzzer for n iterations")
- # Use type=float as gh mobile cannot specify integers as workflow args
- ap.add_argument('-n', '--iterations', default=-1,
- type=float, help="Number of iterations to run pythonfuzz for")
- ap.add_argument('-i', '--infinite',
- action='store_const', const=-1, dest='iterations')
- args = ap.parse_args()
-
- fuzzer = Fuzzer(fuzz, dirs=['./pythonfuzz_corpus'], timeout=30, runs=int(args.iterations))
- fuzzer.start()
diff --git a/parser/astgen/ast_node.py b/parser/astgen/ast_node.py
index 5994210..9e433c3 100644
--- a/parser/astgen/ast_node.py
+++ b/parser/astgen/ast_node.py
@@ -1,20 +1,27 @@
from __future__ import annotations
-from dataclasses import dataclass
+import sys
+from collections.abc import Callable, Sequence
+from dataclasses import dataclass, field
from enum import Enum
-from typing import Callable, TypeAlias, Iterable, TypeVar
+from typing import TypeAlias, Iterable, TypeVar, TYPE_CHECKING, Generic
-from util import flatten_force
from ..common import HasRegion, StrRegion
-__all__ = [
- "AstNode", "AstProgramNode", "VarDeclScope", "VarDeclType", "AstDeclNode",
- "AstRepeat", "AstIf", "AstWhile", "AstAssign", "AstAugAssign", "AstDefine",
- "AstNumber", "AstString", "AstAnyName", "AstIdent", "AstAttrName",
- "AstListLiteral", "AstAttribute", "AstItem", "AstCall", "AstOp", "AstBinOp",
- "AstUnaryOp", 'walk_ast', 'WalkableT', 'WalkerFnT', 'WalkerCallType',
- "FilteredWalker"
-]
+__all__ = ['AstNode', 'walk_ast', 'WalkableT', 'WalkerFnT', 'WalkerCallType', 'MetadataT']
+
+
+# noinspection PyUnreachableCode
+# If we are a type checker or a new enough runtime, we want default
+if TYPE_CHECKING or sys.version_info >= (3, 13):
+ # If we are an old version, import it (for type checkers; unreachable at runtime)
+ if sys.version_info < (3, 13):
+ from typing_extensions import TypeVar
+ # Now we have a default-able TypeVar from somewhere so can use it
+ MetadataT = TypeVar('MetadataT', default=None)
+else:
+ # We are an old runtime version without default
+ MetadataT = TypeVar('MetadataT')
class WalkerCallType(Enum):
@@ -22,17 +29,12 @@ class WalkerCallType(Enum):
POST = 'post'
-WalkableL0: TypeAlias = 'AstNode | list[AstNode] | tuple[AstNode, ...] | None'
-WalkableT: TypeAlias = 'WalkableL0 | list[WalkableL0] | tuple[WalkableL0, ...]'
-WalkerFnT: TypeAlias = Callable[[WalkableT, WalkerCallType], bool | None]
-"""Returns True if skip"""
-
-
@dataclass
-class AstNode(HasRegion):
+class AstNode(HasRegion, Generic[MetadataT]):
region: StrRegion
name = None # type: str
del name # So we get better error msg if we forget to add it to a class
+ meta: MetadataT = field(kw_only=True, default=None)
def walk(self, fn: WalkerFnT):
if fn(self, WalkerCallType.PRE):
@@ -76,333 +78,9 @@ def walk_multiple_objects(cls, fn: WalkerFnT, objs: Iterable[WalkableT]):
walk_ast = AstNode.walk_obj
-# region
-WT = TypeVar('WT', bound=WalkableT)
-VT = TypeVar('VT')
-SpecificCbT = Callable[[WT], bool | None]
-SpecificCbsDict = dict[type[WT] | type, list[Callable[[WT], bool | None]]]
-BothCbT = Callable[[WT, WalkerCallType], bool | None]
-BothCbsDict = dict[type[WT] | type, list[Callable[[WT, WalkerCallType], bool | None]]]
-
-
-class WalkerFilterRegistry:
- def __init__(self, enter_cbs: SpecificCbsDict = (),
- exit_cbs: SpecificCbsDict = (),
- both_sbc: BothCbsDict = ()):
- self.enter_cbs: SpecificCbsDict = dict(enter_cbs) # Copy them,
- self.exit_cbs: SpecificCbsDict = dict(exit_cbs) # also converts default () -> {}
- self.both_cbs: BothCbsDict = dict(both_sbc)
-
- def copy(self):
- return WalkerFilterRegistry(self.enter_cbs, self.exit_cbs, self.both_cbs)
-
- def register_both(self, t: type[WT], fn: Callable[[WT, WalkerCallType], bool | None]):
- self.both_cbs.setdefault(t, []).append(fn)
- return self
-
- def register_enter(self, t: type[WT], fn: Callable[[WT], bool | None]):
- self.enter_cbs.setdefault(t, []).append(fn)
- return self
-
- def register_exit(self, t: type[WT], fn: Callable[[WT], bool | None]):
- self.exit_cbs.setdefault(t, []).append(fn)
- return self
-
- def __call__(self, *args, **kwargs):
- return self
-
- def on_enter(self, *tps: type[WT] | type):
- """Decorator version of register_enter."""
- def decor(fn: SpecificCbT):
- for t in tps:
- self.register_enter(t, fn)
- return fn
- return decor
-
- def on_exit(self, *tps: type[WT] | type):
- """Decorator version of register_exit."""
- def decor(fn: SpecificCbT):
- for t in tps:
- self.register_exit(t, fn)
- return fn
- return decor
-
- def on_both(self, *tps: type[WT] | type):
- """Decorator version of register_both."""
- def decor(fn: BothCbT):
- for t in tps:
- self.register_both(t, fn)
- return fn
- return decor
-
-
-class FilteredWalker(WalkerFilterRegistry):
- def __init__(self):
- cls_reg = self.class_registry()
- super().__init__(cls_reg.enter_cbs, cls_reg.exit_cbs, cls_reg.both_cbs)
-
- @classmethod
- def class_registry(cls) -> WalkerFilterRegistry:
- return WalkerFilterRegistry()
-
- @classmethod
- def create_cls_registry(cls, fn=None):
- """Create a class-level registry that can be added to using decorators.
-
- This can be used in two ways (at the top of your class)::
-
- # MUST be this name
- class_registry = FilteredWalker.create_cls_registry()
-
- or::
-
- @classmethod
- @FilteredWalker.create_cls_registry
- def class_registry(cls): # MUST be this name
- pass
-
- and when registering methods::
-
- @class_registry.on_enter(AstDefine)
- def enter_define(self, ...):
- ...
-
- The restrictions on name are because we have no other way of detecting
- it (without metaclass dark magic) as we can't refer to the class while
- its namespace is being evaluated
- """
- if fn is not None and (parent := fn(cls)) is not None:
- return WalkerFilterRegistry.copy(parent)
- return WalkerFilterRegistry()
-
- def __call__(self, o: WalkableT, call_type: WalkerCallType):
- result = None
- # Call more specific ones first
- specific_cbs = self.enter_cbs if call_type == WalkerCallType.PRE else self.exit_cbs
- for fn in self._get_funcs(specific_cbs, type(o)):
- result = fn(o) or result
- for fn in self._get_funcs(self.both_cbs, type(o)):
- result = fn(o, call_type) or result
- return result
-
- @classmethod
- def _get_funcs(cls, mapping: dict[type[WT] | type, list[VT]], tp: type[WT]) -> list[VT]:
- """Also looks at superclasses/MRO"""
- return flatten_force(mapping.get(sub, []) for sub in tp.mro())
-# endregion
-
-
-@dataclass
-class AstProgramNode(AstNode):
- name = 'program'
- statements: list[AstNode]
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.statements,))
-
-
-# region ---- ----
-class VarDeclScope(Enum):
- LET = 'let'
- GLOBAL = 'global'
-
-
-class VarDeclType(Enum):
- VARIABLE = 'variable'
- LIST = 'list'
-
-
-@dataclass
-class AstDeclNode(AstNode):
- name = 'var_decl'
- scope: VarDeclScope
- type: VarDeclType
- ident: AstIdent
- value: AstNode | None
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.ident, self.value))
-
-
-@dataclass
-class AstRepeat(AstNode):
- name = 'repeat'
- count: AstNode
- body: list[AstNode]
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.count, self.body))
-
-
-@dataclass
-class AstIf(AstNode):
- name = 'if'
- cond: AstNode
- if_body: list[AstNode]
- # elseif = else{if
- else_body: list[AstNode] | None = None
- # ^ Separate cases for no block and empty block (can be else {} to easily
- # add extra blocks in scratch interface)
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.cond, self.if_body, self.else_body))
-
-
-@dataclass
-class AstWhile(AstNode):
- name = 'while'
- cond: AstNode
- body: list[AstNode]
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.cond, self.body))
-
-
-@dataclass
-class AstAssign(AstNode):
- name = '='
- target: AstNode
- source: AstNode
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.target, self.source))
-
-
-@dataclass
-class AstAugAssign(AstNode):
- op: str # maybe attach a StrRegion to the location of the op??
- target: AstNode
- source: AstNode
-
- @property
- def name(self):
- return self.op
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.target, self.source))
-
-
-@dataclass
-class AstDefine(AstNode):
- name = 'def'
-
- ident: AstIdent
- params: list[tuple[AstIdent, AstIdent]] # type, ident
- body: list[AstNode]
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.ident, self.params, self.body))
-# endregion ---- ----
-
-
-# region ---- ----
-@dataclass
-class AstNumber(AstNode):
- # No real point in storing the string representation (could always StrRegion.resolve())
- value: float | int
-
-
-@dataclass
-class AstString(AstNode):
- value: str # Values with escapes, etc. resolved
-
-
-@dataclass
-class AstAnyName(AstNode):
- id: str
-
- def __post_init__(self):
- if type(self) == AstAnyName:
- raise TypeError("AstAnyName must not be instantiated directly.")
-
-
-@dataclass
-class AstIdent(AstAnyName):
- name = 'ident'
-
-
-@dataclass
-class AstAttrName(AstAnyName):
- name = 'attr'
-
-
-@dataclass
-class AstListLiteral(AstNode):
- name = 'list'
- items: list[AstNode]
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.items,))
-
-
-@dataclass
-class AstAttribute(AstNode):
- name = '.'
- obj: AstNode
- attr: AstAttrName
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.obj, self.attr))
-
-
-@dataclass
-class AstItem(AstNode):
- name = 'item'
- obj: AstNode
- index: AstNode
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.obj, self.index))
-
-
-@dataclass
-class AstCall(AstNode):
- name = 'call'
- obj: AstNode
- args: list[AstNode]
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.obj, self.args))
-
-
-@dataclass
-class AstOp(AstNode):
- op: str
-
-
-@dataclass
-class AstBinOp(AstOp):
- left: AstNode
- right: AstNode
-
- valid_ops = [*'+-*/%', '**', '..', '||', '&&', # ops
- '==', '!=', '<', '>', '<=', '>=' # comparisons
- ] # type: list[str]
-
- def __post_init__(self):
- assert self.op in self.valid_ops
-
- @property
- def name(self):
- return self.op
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.left, self.right))
-
-
-@dataclass
-class AstUnaryOp(AstOp):
- operand: AstNode
-
- valid_ops = ('+', '-', '!')
-
- def __post_init__(self):
- assert self.op in self.valid_ops
-
- @property
- def name(self):
- return self.op
-
- def _walk_members(self, fn: WalkerFnT):
- self.walk_multiple_objects(fn, (self.operand,))
-# endregion ---- ----
+# TODO: We are unable to parameterise these by MetadataT as Pycharm cannot
+# handle TypeVar with `default` set properly which is very sad.
+WalkableL0: TypeAlias = AstNode | Sequence[AstNode] | None
+WalkableT: TypeAlias = WalkableL0 | Sequence[WalkableL0]
+WalkerFnT: TypeAlias = Callable[[WalkableT, WalkerCallType], bool | None]
+"""Returns True if skip"""
diff --git a/parser/astgen/ast_nodes.py b/parser/astgen/ast_nodes.py
new file mode 100644
index 0000000..5906e64
--- /dev/null
+++ b/parser/astgen/ast_nodes.py
@@ -0,0 +1,231 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from enum import Enum
+
+from .ast_node import AstNode, WalkerFnT, MetadataT
+
+__all__ = [
+ "AstNode", "AstProgramNode", "VarDeclScope", "VarDeclType", "AstDeclNode",
+ "AstRepeat", "AstIf", "AstWhile", "AstAssign", "AstAugAssign", "AstDefine",
+ "AstNumber", "AstString", "AstAnyName", "AstIdent", "AstAttrName",
+ "AstListLiteral", "AstAttribute", "AstItem", "AstCall", "AstOp", "AstBinOp",
+ "AstUnaryOp",
+]
+
+
+@dataclass
+class AstProgramNode(AstNode[MetadataT]):
+ name = 'program'
+ statements: list[AstNode[MetadataT]]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.statements,))
+
+
+# region ---- ----
+class VarDeclScope(Enum):
+ LET = 'let'
+ GLOBAL = 'global'
+
+
+class VarDeclType(Enum):
+ VARIABLE = 'variable'
+ LIST = 'list'
+
+
+@dataclass
+class AstDeclNode(AstNode[MetadataT]):
+ name = 'var_decl'
+ scope: VarDeclScope
+ type: VarDeclType
+ ident: AstIdent[MetadataT]
+ value: AstNode[MetadataT] | None
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.ident, self.value))
+
+
+@dataclass
+class AstRepeat(AstNode[MetadataT]):
+ name = 'repeat'
+ count: AstNode[MetadataT]
+ body: list[AstNode[MetadataT]]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.count, self.body))
+
+
+@dataclass
+class AstIf(AstNode[MetadataT]):
+ name = 'if'
+ cond: AstNode[MetadataT]
+ if_body: list[AstNode[MetadataT]]
+ # elseif = else{if
+ else_body: list[AstNode[MetadataT]] | None = None
+ # ^ Separate cases for no block and empty block (can be else {} to easily
+ # add extra blocks in scratch interface)
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.cond, self.if_body, self.else_body))
+
+
+@dataclass
+class AstWhile(AstNode[MetadataT]):
+ name = 'while'
+ cond: AstNode[MetadataT]
+ body: list[AstNode[MetadataT]]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.cond, self.body))
+
+
+@dataclass
+class AstAssign(AstNode[MetadataT]):
+ name = '='
+ target: AstNode[MetadataT]
+ source: AstNode[MetadataT]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.target, self.source))
+
+
+@dataclass
+class AstAugAssign(AstNode[MetadataT]):
+ op: str # maybe attach a StrRegion to the location of the op??
+ target: AstNode[MetadataT]
+ source: AstNode[MetadataT]
+
+ @property
+ def name(self):
+ return self.op
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.target, self.source))
+
+
+@dataclass
+class AstDefine(AstNode[MetadataT]):
+ name = 'def'
+
+ ident: AstIdent[MetadataT]
+ # TODO: this should be list[AstDefineParam] where AstParam is an AstNode
+ params: list[tuple[AstIdent[MetadataT], AstIdent[MetadataT]]] # type, ident
+ body: list[AstNode[MetadataT]]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.ident, self.params, self.body))
+# endregion ---- ----
+
+
+# region ---- ----
+@dataclass
+class AstNumber(AstNode[MetadataT]):
+ # No real point in storing the string representation (could always StrRegion.resolve())
+ value: float | int
+
+
+@dataclass
+class AstString(AstNode[MetadataT]):
+ value: str # Values with escapes, etc. resolved
+
+
+@dataclass
+class AstAnyName(AstNode[MetadataT]):
+ id: str
+
+ def __post_init__(self):
+ if type(self) == AstAnyName:
+ raise TypeError("AstAnyName must not be instantiated directly.")
+
+
+@dataclass
+class AstIdent(AstAnyName[MetadataT]):
+ name = 'ident'
+
+
+@dataclass
+class AstAttrName(AstAnyName[MetadataT]):
+ name = 'attr'
+
+
+@dataclass
+class AstListLiteral(AstNode[MetadataT]):
+ name = 'list'
+ items: list[AstNode[MetadataT]]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.items,))
+
+
+@dataclass
+class AstAttribute(AstNode[MetadataT]):
+ name = '.'
+ obj: AstNode[MetadataT]
+ attr: AstAttrName[MetadataT]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.obj, self.attr))
+
+
+@dataclass
+class AstItem(AstNode[MetadataT]):
+ name = 'item'
+ obj: AstNode[MetadataT]
+ index: AstNode[MetadataT]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.obj, self.index))
+
+
+@dataclass
+class AstCall(AstNode[MetadataT]):
+ name = 'call'
+ obj: AstNode[MetadataT]
+ args: list[AstNode[MetadataT]]
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.obj, self.args))
+
+
+@dataclass
+class AstOp(AstNode[MetadataT]):
+ op: str
+
+
+@dataclass
+class AstBinOp(AstOp[MetadataT]):
+ left: AstNode[MetadataT]
+ right: AstNode[MetadataT]
+
+ valid_ops = [*'+-*/%', '**', '..', '||', '&&', # ops
+ '==', '!=', '<', '>', '<=', '>=' # comparisons
+ ] # type: list[str]
+
+ def __post_init__(self):
+ assert self.op in self.valid_ops
+
+ @property
+ def name(self):
+ return self.op
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.left, self.right))
+
+
+@dataclass
+class AstUnaryOp(AstOp[MetadataT]):
+ operand: AstNode[MetadataT]
+
+ valid_ops = ('+', '-', '!')
+
+ def __post_init__(self):
+ assert self.op in self.valid_ops
+
+ @property
+ def name(self):
+ return self.op
+
+ def _walk_members(self, fn: WalkerFnT):
+ self.walk_multiple_objects(fn, (self.operand,))
+# endregion ---- ----
diff --git a/parser/astgen/astgen.py b/parser/astgen/astgen.py
index 1d2f4fe..dbf959c 100644
--- a/parser/astgen/astgen.py
+++ b/parser/astgen/astgen.py
@@ -5,7 +5,7 @@
from typing import Callable, overload, TypeVar, TypeAlias
from util import flatten_force, is_strict_subclass
-from .ast_node import *
+from .ast_nodes import *
from .eval_literal import eval_number, eval_string
from .errors import LocatedAstError
from ..common import region_union, RegionUnionArgT, HasRegion, StrRegion
@@ -68,7 +68,7 @@ def _detect_autowalk_type_from_annot(fn):
bound = sig.bind(0, 1) # simulate call w/ 2 args
except TypeError as e: # pragma: no cover
raise TypeError("Unable to detect node_type (signature may be incompatible)") from e
- arg2_name: str = (*bound.arguments,)[1] # get name it's bound to
+ arg2_name: str = tuple(bound.arguments)[1] # get name it's bound to
param = sig.parameters[arg2_name] # lookup the param by name
if param.kind not in (param.POSITIONAL_ONLY,
param.POSITIONAL_OR_KEYWORD): # pragma: no cover
@@ -89,10 +89,11 @@ def __init__(self, cst: CstGen):
self.src = self.cst.src
self.result: AstProgramNode | None = None
- def parse(self):
- if not self.result:
- self.result = self._walk_program(self.cst.parse())
- return self.result
+ def parse(self) -> AstProgramNode:
+ if self.result:
+ return self.result
+ result = self.result = self._walk_program(self.cst.parse())
+ return result
def _walk_program(self, root: ProgramNode):
return AstProgramNode(root.region, self._walk_block(root.statements))
@@ -111,6 +112,7 @@ def _walk_smt(self, smt: AnyNode) -> list[AstNode]:
elif isinstance(smt, ConditionalBlock):
return self._walk_conditional(smt)
elif isinstance(smt, AssignNode): # Simple assignment
+ # TODO: maybe separate SetAttr, SetItem, SetVar nodes?
return [AstAssign(smt.region, self._walk_assign_left(smt.target),
self._walk_expr(smt.source))]
elif isinstance(smt, AssignOpNode): # Other (aug.) assignment
@@ -165,19 +167,19 @@ def _walk_assign_left(self, lhs: AnyNode) -> AstNode:
def _walk_conditional(self, smt: ConditionalBlock):
# Build up else/elseif parts inner-first
- node = (None if isinstance(smt.else_block, NullElseBlock)
- else self._walk_block(smt.else_block.block))
- for elseif in smt.elseif_blocks:
+ else_cst = smt.else_block # New var to workaround Pycharm narrowing bug
+ else_block = (None if isinstance(else_cst, NullElseBlock)
+ else self._walk_block(else_cst.block))
+ for elseif in reversed(smt.elseif_blocks): # Last = innermost
# region is current elseif to end
- node = AstIf(elseif.region | smt.else_block.region,
- self._walk_expr(elseif.cond),
- self._walk_block(elseif.block), node)
+ else_block = [AstIf(elseif.region | smt.else_block.region,
+ self._walk_expr(elseif.cond),
+ self._walk_block(elseif.block), else_block)]
return [AstIf(smt.region, self._walk_expr(smt.if_block.cond),
- self._walk_block(smt.if_block.block), node)]
+ self._walk_block(smt.if_block.block), else_block)]
def _walk_block(self, nodes: list[AnyNode] | BlockNode) -> list[AstNode]:
- if isinstance(nodes, BlockNode):
- nodes = nodes.statements
+ nodes = nodes.statements if isinstance(nodes, BlockNode) else nodes
return flatten_force(map(self._walk_smt, nodes))
def _walk_expr(self, expr: AnyNode) -> AstNode:
diff --git a/parser/astgen/filtered_walker.py b/parser/astgen/filtered_walker.py
new file mode 100644
index 0000000..63633a6
--- /dev/null
+++ b/parser/astgen/filtered_walker.py
@@ -0,0 +1,178 @@
+from __future__ import annotations
+
+import functools
+from collections.abc import Callable
+from typing import TypeVar, Generic
+
+from util import flatten_force
+from .ast_node import WalkerCallType, WalkableT, walk_ast
+
+try:
+ from typing import TypeVarTuple, Unpack, ParamSpec, Concatenate, Self
+except ImportError:
+ from typing_extensions import TypeVarTuple, Unpack, ParamSpec, Concatenate, Self
+
+
+__all__ = ['WalkerFilterRegistry', 'FilteredWalker', 'walk_ast']
+
+VT = TypeVar('VT')
+WT = TypeVar('WT', bound=WalkableT)
+WTT = TypeVar('WTT', bound=type)
+Ps = TypeVarTuple('Ps')
+Q = ParamSpec('Q')
+
+SpecificCbT = Callable[[Unpack[Ps], WT], bool | None]
+SpecificCbsDict = dict[type[WT], list[SpecificCbT[Unpack[Ps], WT]]]
+# Equivalent to the above but requires passing type[WT] to first type arg
+# This is done to workaround Pycharm bug PY-90860.
+SpecificCbsDict3 = dict[WTT, list[SpecificCbT[Unpack[Ps], WT]]]
+
+BothCbT = Callable[[Unpack[Ps], WT, WalkerCallType], bool | None]
+BothCbsDict = dict[type[WT], list[BothCbT[Unpack[Ps], WT]]]
+BothCbsDict3 = dict[WTT, list[BothCbT[Unpack[Ps], WT]]] # Workaround to PY-90860
+
+
+class WalkerFilterRegistry(Generic[Unpack[Ps], WT]):
+ """Contains walkers over node types ``WT`` taking param types ``*Ps``
+ followed by either ``(node: WT)`` for ``enter``/``exit`` or
+ ``(node: WT, call_type: WalkerCallType)`` for ``both``. No walking
+ functionality in and of itself due to the possibility of needing extra args"""
+ def __init__(self,
+ enter_cbs: SpecificCbsDict3[type[WT], Unpack[Ps], WT] | None = None,
+ exit_cbs: SpecificCbsDict3[type[WT], Unpack[Ps], WT] | None = None,
+ both_sbc: BothCbsDict3[type[WT], Unpack[Ps], WT] | None = None):
+ self.enter_cbs = dict(enter_cbs or {}) # Copy them
+ self.exit_cbs = dict(exit_cbs or {})
+ self.both_cbs = dict(both_sbc or {})
+
+ def copy(self):
+ return type(self)(self.enter_cbs, self.exit_cbs, self.both_cbs)
+
+ def instantiate(self, *args: Unpack[Ps]):
+ return BasicFilteredWalker[WT](
+ self._instantiate_dict(self.enter_cbs, args),
+ self._instantiate_dict(self.exit_cbs, args),
+ self._instantiate_dict(self.both_cbs, args),
+ )
+
+ @classmethod
+ def _instantiate_dict(
+ cls,
+ d: dict[WTT, list[Callable[Concatenate[Unpack[Ps], Q], bool | None]]],
+ args: tuple[Unpack[Ps]]
+ ) -> dict[WTT, list[Callable[Q, bool | None]]]:
+ return {k: [functools.partial(f, *args) for f in fs] for k, fs in d.items()}
+
+ def register_both(self, t: type[WT], fn: BothCbT[Unpack[Ps], WT]):
+ self.both_cbs.setdefault(t, []).append(fn)
+ return self
+
+ def register_enter(self, t: type[WT], fn: SpecificCbT[Unpack[Ps], WT]):
+ self.enter_cbs.setdefault(t, []).append(fn)
+ return self
+
+ def register_exit(self, t: type[WT], fn: SpecificCbT[Unpack[Ps], WT]):
+ self.exit_cbs.setdefault(t, []).append(fn)
+ return self
+
+ def on_enter(self, *tps: type[WT]):
+ """Decorator version of register_enter."""
+ def decor(fn: SpecificCbT[Unpack[Ps], WT]):
+ for t in tps:
+ self.register_enter(t, fn)
+ return fn
+ return decor
+
+ def on_exit(self, *tps: type[WT]):
+ """Decorator version of register_exit."""
+ def decor(fn: SpecificCbT[Unpack[Ps], WT]):
+ for t in tps:
+ self.register_exit(t, fn)
+ return fn
+ return decor
+
+ def on_both(self, *tps: type[WT]):
+ """Decorator version of register_both."""
+ def decor(fn: BothCbT[Unpack[Ps], WT]):
+ for t in tps:
+ self.register_both(t, fn)
+ return fn
+ return decor
+
+
+class BasicFilteredWalker(WalkerFilterRegistry[WT], Generic[WT]):
+ def instantiate(self, *args: Unpack[()]):
+ assert len(args) == 0, "Walker already instantiated"
+ return self.copy()
+
+ def walk(self, o: WalkableT):
+ return walk_ast(o, self)
+
+ def __call__(self, o: WalkableT, call_type: WalkerCallType):
+ result = None
+ # Call more specific ones first
+ specific_cbs = self.enter_cbs if call_type == WalkerCallType.PRE else self.exit_cbs
+ for fn in self._get_funcs(specific_cbs, type(o)):
+ if result := result or fn(o):
+ return result # Don't call later ones if already skipped
+ for fn in self._get_funcs(self.both_cbs, type(o)):
+ if result := result or fn(o, call_type):
+ return result
+ return result
+
+ @classmethod
+ def _get_funcs(cls, mapping: dict[type[WT] | type, list[VT]], tp: type[WT]) -> list[VT]:
+ """Also looks at superclasses/MRO"""
+ return flatten_force([mapping.get(sub, []) for sub in _get_mro(tp)])
+
+
+class FilteredWalker(BasicFilteredWalker[WT], Generic[WT]):
+ def __init__(self):
+ # Can then add studd to specific instances
+ from_cls = (
+ self.class_registry
+ if isinstance(self.class_registry, WalkerFilterRegistry)
+ else self.class_registry()
+ ).instantiate(self)
+ super().__init__(from_cls.enter_cbs, from_cls.exit_cbs, from_cls.both_cbs)
+
+ @classmethod
+ def class_registry(cls) -> WalkerFilterRegistry[Self, WT]:
+ return WalkerFilterRegistry()
+
+ @classmethod
+ def create_cls_registry(cls, fn=None) -> WalkerFilterRegistry[Self, WT]:
+ """Create a class-level registry that can be added to using decorators.
+
+ This can be used in two ways (at the top of your class)::
+
+ # MUST be this name # Value can also be any WalkerFilterRegistry
+ class_registry = FilteredWalker.create_cls_registry()
+
+ or::
+
+ @FilteredWalker.create_cls_registry
+ @classmethod
+ def class_registry(cls): # MUST be this name
+ pass # Can return a WalkerFilterRegistry here
+
+ and when registering methods::
+
+ @class_registry.on_enter(AstDefine)
+ def enter_define(self, ...):
+ ...
+
+ The restrictions on name are because we have no other way of detecting
+ it (without metaclass dark magic) as we can't refer to the class while
+ its namespace is being evaluated
+ """
+ if fn is None:
+ return WalkerFilterRegistry()
+ fn = fn.__func__ if isinstance(fn, classmethod) else fn
+ if (parent := fn(cls)) is None:
+ return WalkerFilterRegistry()
+ return WalkerFilterRegistry.copy(parent)
+
+
+def _get_mro(tp: type) -> tuple[type, ...]: # tp.__mro__ but with proper types
+ return tp.__mro__ # .mro() recalculates it every time, hence is slow
diff --git a/parser/common/common.py b/parser/common/common.py
index 21dff3f..49f69d2 100644
--- a/parser/common/common.py
+++ b/parser/common/common.py
@@ -1,15 +1,25 @@
-from typing import TypeAlias, Sequence
+from __future__ import annotations
+
+from typing import TypeAlias, Sequence, TYPE_CHECKING
from .str_region import StrRegion
+if TYPE_CHECKING:
+ from typing import TypeIs
+
__all__ = ['HasRegion', 'RegionUnionArgT', 'region_union']
class HasRegion:
region: StrRegion
+ @classmethod
+ def has_instance_duck(cls, inst: object) -> TypeIs[HasRegion]:
+ """Duck-typed version of the isinstance(inst, HasRegion) check"""
+ return getattr(inst, 'region', None) is not None
+
-RegionUnionFlatT: TypeAlias = HasRegion | StrRegion
+RegionUnionFlatT: TypeAlias = HasRegion | StrRegion | None
RegionUnionArgT: TypeAlias = RegionUnionFlatT | Sequence[RegionUnionFlatT]
@@ -18,7 +28,7 @@ def region_union(*args: RegionUnionArgT):
for loc in args:
if loc is None:
continue
- if getattr(loc, 'region', None) is not None: # Duck-type HasRegion
+ if HasRegion.has_instance_duck(loc):
loc = loc.region
if isinstance(loc, StrRegion):
regs.append(loc)
diff --git a/parser/common/error.py b/parser/common/error.py
index 847be70..5970bb3 100644
--- a/parser/common/error.py
+++ b/parser/common/error.py
@@ -1,10 +1,6 @@
from __future__ import annotations
-import bisect
-import itertools
import traceback
-from dataclasses import replace as d_replace
-from typing import Sequence
from .common import HasRegion
from .str_region import StrRegion
@@ -71,8 +67,6 @@ class BaseParseError(_PolyfillAddNoteMixin, Exception):
class BaseLocatedError(BaseParseError, HasRegion):
- __notes__: list[str] # but might not exist
-
def __init__(self, msg: str, region: StrRegion, src: str):
super().__init__(msg)
self.msg = msg
@@ -94,7 +88,7 @@ def compute_location(self):
return
# noinspection PyBroadException
try:
- self.add_note(self.display_region(self._src_text, self.region))
+ self.add_note(self.region.display(self._src_text))
except Exception:
short_loc = f'{self.region.start} to {self.region.end - 1}'
self.add_note(
@@ -105,75 +99,3 @@ def compute_location(self):
def __str__(self):
self.compute_location()
return super().__str__()
-
- @classmethod
- def display_region(cls, src: str, region: StrRegion) -> str:
- if region.end > len(src): # end excl so ok if 1 beyond string
- region = d_replace(region, end=len(src))
- if region.start >= len(src):
- region = d_replace(region, start=len(src) - 1)
- if region.is_epsilon():
- # length=0 but still try to do something
- region = d_replace(region, end=region.start + 1)
- lines = src.splitlines(keepends=True)
- cum_lengths = tuple(itertools.accumulate(tuple(map(len, lines))))
- start_idx = region.start
- end_idx = region.end - 1 # its inclusive below so convert excl -> incl
- start_line, start_col = cls.idx_to_coord(cum_lengths, start_idx)
- end_line, end_col = cls.idx_to_coord(cum_lengths, end_idx)
- if start_line == end_line:
- return cls._display_single_line(lines, start_line, start_col, end_col)
- assert start_line < end_line
- return cls._display_multi_line(lines, start_line, start_col, end_line, end_col)
-
- @classmethod
- def _display_multi_line(cls, lines: Sequence[str], start_line: int, start_col: int,
- end_line: int, end_col: int):
- if end_line - start_line + 1 > 5:
- # just print start and end lines
- lineno_w = len(str(end_line + 1)) # last will always be biggest
- start_repr = cls._display_single_line(
- lines, start_line, start_col, len(lines[start_line]) - 1, lineno_w)
- end_repr = cls._display_single_line(
- lines, end_line, 0, end_col, lineno_w)
- return (f'{start_repr}\n'
- f'...\n'
- f'{end_repr}')
- lines_repr = []
- lineno_w = len(str(end_line + 1))
- for line in range(start_line, end_line + 1):
- if line == start_line:
- start_col_inner = start_col
- else:
- start_col_inner = 0
- if line == end_line:
- end_col_inner = end_col
- else:
- end_col_inner = len(lines[line]) - 2 # another for the \n at end
- line_repr = cls._display_single_line(
- lines, line, start_col_inner, end_col_inner, lineno_w)
- lines_repr.append(f'{line_repr}')
- return '\n'.join(lines_repr)
-
- @classmethod
- def _display_single_line(cls, lines: Sequence[str], line: int, start_col: int,
- end_col: int, lineno_w: int = None):
- start_spaces = ' ' * start_col
- carets = '^' * (end_col - start_col + 1)
- end_spaces = ' ' * (len(lines[line]) - end_col)
- if lineno_w is None:
- lineno_w = len(str(line + 1))
- (line_str,) = lines[line].splitlines() # remove \n on end
- return (f'{line + 1:>{lineno_w}} | {line_str}\n'
- f'{"" :>{lineno_w}} | {start_spaces}{carets}{end_spaces}')
-
- @classmethod
- def idx_to_coord(cls, cum_lengths: Sequence[int], idx: int) -> tuple[int, int]:
- """Converts an index to a **0-based** (line, column) tuple"""
- line = bisect.bisect_right(cum_lengths, idx)
- if line == 0:
- return line, idx
- # -1 to convert to idx, +1 to for char after last char on prev line
- line_start_idx = cum_lengths[line - 1] # - 1 + 1
- col = idx - line_start_idx
- return line, col
diff --git a/parser/common/str_region.py b/parser/common/str_region.py
index 20ddd89..c514e6c 100644
--- a/parser/common/str_region.py
+++ b/parser/common/str_region.py
@@ -2,6 +2,11 @@
from dataclasses import dataclass
+import bisect
+import itertools
+from dataclasses import replace as d_replace
+from typing import Sequence
+
__all__ = ['StrRegion']
@@ -34,3 +39,81 @@ def __or__(self, other: StrRegion):
def is_epsilon(self):
"""Return true if the length of the region is 0"""
return self.end <= self.start
+
+ def display(self, src: str):
+ # Logic held in separate class as it is rather complex
+ return _RegionPrinter.display_region(src, self)
+
+
+class _RegionPrinter:
+ @classmethod
+ def display_region(cls, src: str, region: StrRegion) -> str:
+ if region.end > len(src): # end excl so ok if 1 beyond string
+ region = d_replace(region, end=len(src))
+ if region.start >= len(src):
+ region = d_replace(region, start=len(src) - 1)
+ if region.is_epsilon():
+ # length=0 but still try to do something
+ region = d_replace(region, end=region.start + 1)
+ lines = src.splitlines(keepends=True)
+ cum_lengths = tuple(itertools.accumulate(tuple(map(len, lines))))
+ start_idx = region.start
+ end_idx = region.end - 1 # its inclusive below so convert excl -> incl
+ start_line, start_col = cls._idx_to_coord(cum_lengths, start_idx)
+ end_line, end_col = cls._idx_to_coord(cum_lengths, end_idx)
+ if start_line == end_line:
+ return cls._display_single_line(lines, start_line, start_col, end_col)
+ assert start_line < end_line
+ return cls._display_multi_line(lines, start_line, start_col, end_line, end_col)
+
+ @classmethod
+ def _display_multi_line(cls, lines: Sequence[str], start_line: int, start_col: int,
+ end_line: int, end_col: int):
+ if end_line - start_line + 1 > 5:
+ # just print start and end lines
+ lineno_w = len(str(end_line + 1)) # last will always be biggest
+ start_repr = cls._display_single_line(
+ lines, start_line, start_col, len(lines[start_line]) - 1, lineno_w)
+ end_repr = cls._display_single_line(
+ lines, end_line, 0, end_col, lineno_w)
+ return (f'{start_repr}\n'
+ f'...\n'
+ f'{end_repr}')
+ lines_repr = []
+ lineno_w = len(str(end_line + 1))
+ for line in range(start_line, end_line + 1):
+ if line == start_line:
+ start_col_inner = start_col
+ else:
+ start_col_inner = 0
+ if line == end_line:
+ end_col_inner = end_col
+ else:
+ end_col_inner = len(lines[line]) - 2 # another for the \n at end
+ line_repr = cls._display_single_line(
+ lines, line, start_col_inner, end_col_inner, lineno_w)
+ lines_repr.append(f'{line_repr}')
+ return '\n'.join(lines_repr)
+
+ @classmethod
+ def _display_single_line(cls, lines: Sequence[str], line: int, start_col: int,
+ end_col: int, lineno_w: int = None):
+ start_spaces = ' ' * start_col
+ carets = '^' * (end_col - start_col + 1)
+ end_spaces = ' ' * (len(lines[line]) - end_col)
+ if lineno_w is None:
+ lineno_w = len(str(line + 1))
+ (line_str,) = lines[line].splitlines() # remove \n on end
+ return (f'{line + 1:>{lineno_w}} | {line_str}\n'
+ f'{"" :>{lineno_w}} | {start_spaces}{carets}{end_spaces}')
+
+ @classmethod
+ def _idx_to_coord(cls, cum_lengths: Sequence[int], idx: int) -> tuple[int, int]:
+ """Converts an index to a **0-based** (line, column) tuple"""
+ line = bisect.bisect_right(cum_lengths, idx)
+ if line == 0:
+ return line, idx
+ # -1 to convert to idx, +1 to for char after last char on prev line
+ line_start_idx = cum_lengths[line - 1] # - 1 + 1
+ col = idx - line_start_idx
+ return line, col
diff --git a/parser/common/tree_print.py b/parser/common/tree_print.py
index e4d3ce3..40b39c2 100644
--- a/parser/common/tree_print.py
+++ b/parser/common/tree_print.py
@@ -1,11 +1,14 @@
from __future__ import annotations
+import dataclasses
import dataclasses as dcls
import enum
import sys
+from collections import UserString
from io import StringIO
from typing import IO, Sequence
+from util import dcls_field_default
from ..astgen.ast_node import AstNode
from ..cst.base_node import Leaf, AnyNode, Node
from .str_region import StrRegion
@@ -15,6 +18,37 @@
]
+@dataclasses.dataclass
+class Concat:
+ args: tuple[object, ...]
+
+ def __init__(self, *args: object):
+ self.args = args
+
+
+class ConcatLiteral(UserString):
+ pass
+
+
+@dataclasses.dataclass
+class IndentInfo:
+ """Represents a first/current-line indentation and a possibly-different
+ indentation for the next line."""
+
+ level: int
+ start_level: int = dataclasses.field(default=-1)
+
+ def __post_init__(self):
+ if self.start_level == -1:
+ self.start_level = self.level
+
+ def subindent(self, n=1, indent_first_line=True):
+ return type(self)(self.level + n, -1 if indent_first_line else 0)
+
+ def get_indent(self, first_line: bool = False):
+ return self.start_level if first_line else self.level
+
+
class TreePrinter:
def __init__(self, stream: IO[str] = None, indent=2, verbose=False, append_lf=False):
self.indent = indent
@@ -25,7 +59,7 @@ def __init__(self, stream: IO[str] = None, indent=2, verbose=False, append_lf=Fa
self.stream = stream
def print(self, obj: object):
- self._write(obj, 0)
+ self._write(obj, IndentInfo(0))
if self.append_lf:
self.stream.write('\n')
@@ -38,61 +72,114 @@ def format(self, obj: object):
self.stream = orig_stream
return out.getvalue()
- def _write(self, obj: object, level: int):
- if isinstance(obj, StrRegion):
- self._indented_write(level, self._fmt_region(obj))
+ def _write(self, obj: object, indent: IndentInfo):
+ # TODO: general dataclass pretty-printing
+ if isinstance(obj, Concat):
+ self._write_concat(obj, indent)
+ elif isinstance(obj, StrRegion):
+ self._write_region(obj, indent)
elif isinstance(obj, Node):
- self._write_cst_node(obj, level)
+ self._write_cst_node(obj, indent)
elif isinstance(obj, Leaf):
- self._write_cst_leaf(obj, level)
+ self._write_cst_leaf(obj, indent)
elif isinstance(obj, AstNode):
- self._write_ast_node(obj, level)
+ self._write_ast_node(obj, indent)
elif isinstance(obj, list):
- self._write_seq(obj, level, '[', ']')
+ self._write_seq(obj, indent, '[', ']')
elif isinstance(obj, tuple):
- self._write_seq(obj, level, '(', ')', True)
+ self._write_seq(obj, indent, '(', ')', True)
elif isinstance(obj, enum.Enum):
- self._indented_write(level, f'{type(obj).__name__}.{obj.name}')
+ self._write_enum(obj, indent)
else:
- self._write_fallback(obj, level)
+ self._write_fallback(obj, indent)
+
+ def _write_region(self, obj: StrRegion, indent: IndentInfo):
+ self._indented_write(self._fmt_region(obj), indent, first_line=True)
+
+ def _write_enum(self, obj: enum.Enum, indent: IndentInfo):
+ self._indented_write(f'{type(obj).__name__}.{obj.name}', indent, first_line=True)
- def _write_seq(self, obj: Sequence, level: int, start: str,
+ def _write_concat(self, obj: Concat, indent: IndentInfo):
+ self._indented_write('', indent, first_line=True) # write start indent
+ for o in obj.args:
+ if isinstance(o, ConcatLiteral):
+ self._indented_write(str(o), 0)
+ else:
+ self._write(o, indent.subindent(0, indent_first_line=False))
+
+ def _write_seq(self, obj: Sequence[object], indent: IndentInfo, start: str,
end: str, require_trailing=False):
- self._indented_write(level, start)
+ self._indented_write(start, indent, first_line=True)
if len(obj) == 0:
self.stream.write(end)
return
self.stream.write('\n') # Start items on new line
for i, c in enumerate(obj):
- self._write(c, level + 1)
+ self._write(c, indent.subindent())
if i != len(obj) - 1:
self.stream.write(',\n')
elif require_trailing and len(obj) == 1:
self.stream.write(',')
self.stream.write('\n') # Put ']' on new line
- self._indented_write(level, end)
+ self._indented_write(end, indent)
- def _write_cst_node(self, obj: Node, level: int):
+ def _write_cst_node(self, obj: Node, indent: IndentInfo):
start = self._fmt_node_header(obj, has_more_args=True) + '['
- self._write_seq(obj.children, level, start, end='])')
+ self._write_seq(obj.children, indent, start, end='])')
- def _write_cst_leaf(self, obj: Leaf, level: int):
- self._indented_write(level, self._fmt_node_header(obj, has_more_args=False) + ')')
+ def _write_cst_leaf(self, obj: Leaf, indent: IndentInfo):
+ self._indented_write(self._fmt_node_header(obj, has_more_args=False) + ')', indent)
- def _write_ast_node(self, obj: AstNode, level: int):
+ def _write_ast_node(self, obj: AstNode, indent: IndentInfo):
# TODO Not the ideal formatting (but I don't know what is.
- values = [getattr(obj, f.name) for f in dcls.fields(obj)]
- if any(isinstance(v, (AnyNode, AstNode, list, tuple)) for v in values):
- assert len(values) > 1 # Otherwise wouldn't be complex
- start = f'{type(obj).__name__}({self._fmt_region(obj.region)},'
- return self._write_seq(values[1:], level, start, end=')')
- self._indented_write(level, f'{type(obj).__name__}(')
- for i, v in enumerate(values):
- self._write(v, 0)
- if i != len(values) - 1:
+ field_values = [(f, getattr(obj, f.name)) for f in dcls.fields(obj)]
+ pos_field_values = [(f, v) for f, v in field_values if not f.kw_only]
+ while (pos_field_values and
+ dcls_field_default(pos_field_values[-1][0])
+ == pos_field_values[-1][1]):
+ pos_field_values.pop(-1) # start from last, remove default ones
+ pos_values = [(None, v) for _f, v in pos_field_values]
+ kw_values = [(f.name, v) for f, v in field_values
+ if f.kw_only and v != dcls_field_default(f)]
+ values = pos_values + kw_values
+ # Put the named ones at end. NOTE: relies on sort stability
+ values.sort(key=lambda pair: pair[0] is not None)
+ if ('meta', None) in values: # special case: remove meta= if no metadata
+ values.remove(('meta', None))
+ assert values[0] == (None, obj.region) # sanity check (region is first arg)
+ args = [
+ v if k is None else Concat(ConcatLiteral(f'{k}='), v)
+ for k, v in values
+ ]
+ if self._is_complex(*args):
+ return self._write_complex_ast_node(obj, args, indent)
+ return self._write_simple_ast_node(obj, args, indent)
+
+ @classmethod
+ def _is_complex(cls, *args: object) -> bool:
+ if len(args) != 1:
+ return any(cls._is_complex(a) for a in args)
+ (a,) = args
+ if isinstance(a, Concat):
+ return cls._is_complex(*a.args)
+ return isinstance(a, (AnyNode, AstNode, list, tuple))
+
+ def _write_simple_ast_node(self, obj: AstNode, args: list[object],
+ indent: IndentInfo):
+ self._indented_write(f'{type(obj).__name__}(', indent, first_line=True)
+ for i, v in enumerate(args):
+ # The subindent is just in case one of them does contain a
+ self._write(v, indent.subindent(indent_first_line=False))
+ if i != len(args) - 1:
self.stream.write(', ')
self.stream.write(')')
+ def _write_complex_ast_node(self, obj: AstNode, args: list[object],
+ indent: IndentInfo):
+ start = f'{type(obj).__name__}({self._fmt_region(obj.region)},'
+ del args[0] # Remove the region argument
+ return self._write_seq(args, indent, start, end=')')
+
def _fmt_node_header(self, obj: AnyNode, has_more_args=True):
args: list[str] = []
if type(obj) == Leaf or type(obj) == Node:
@@ -103,10 +190,14 @@ def _fmt_node_header(self, obj: AnyNode, has_more_args=True):
args.append('') # Placeholder for next arg so ', ' gets added
return f'{type(obj).__name__}({", ".join(args)}'
- def _write_fallback(self, obj: object, level: int):
- self._indented_write(level, repr(obj))
+ def _write_fallback(self, obj: object, level: IndentInfo):
+ lines = repr(obj).splitlines()
+ for i, ln in enumerate(lines):
+ self._indented_write(ln, level, first_line=(i == 0))
- def _indented_write(self, level: int, s: str):
+ def _indented_write(self, s: str, level: IndentInfo | int, first_line: bool = False):
+ if isinstance(level, IndentInfo):
+ level = level.get_indent(first_line=first_line)
if level:
self.stream.write(' ' * level * self.indent)
self.stream.write(s)
diff --git a/parser/cst/base_node.py b/parser/cst/base_node.py
index 880e68a..8d46bfb 100644
--- a/parser/cst/base_node.py
+++ b/parser/cst/base_node.py
@@ -47,7 +47,7 @@ def add(self, *nodes: AnyNode, update_end=False):
raise TypeError("Cannot have `None` as child of AnyNode (for now??)")
end = max(end, n.region.end)
self.children.append(n)
- n.parent = n
+ n.parent = self
if update_end:
self.region.end = end
diff --git a/parser/cst/cstgen.py b/parser/cst/cstgen.py
index 146001c..10f371e 100644
--- a/parser/cst/cstgen.py
+++ b/parser/cst/cstgen.py
@@ -3,7 +3,7 @@
from typing import (TypeVar, cast, Sequence, overload, Iterable, Callable)
from .base_node import AnyNode, Node
-from .named_node import AnyNamedNode, node_from_token, node_cls_from_name
+from .named_node import AnyNamedNode, node_from_token, node_cls_from_name, NamedNodeCls
from .nodes import *
from .token_matcher import OpM, KwdM, Matcher, PatternT
from ..common import StrRegion, region_union, RegionUnionArgT
@@ -270,7 +270,7 @@ def _parse_block(self, start: int) -> tuple[AnyNode, int]:
idx += 1
return BlockNode(self.tok_region(start, idx), None, smts), idx
- def _parse_block_with_header(self, start: int, cls: type[AnyNamedNode],
+ def _parse_block_with_header(self, start: int, cls: type[NamedNodeCls],
name: str = None) -> tuple[AnyNode, int]:
name = name or cls.name
idx = start
@@ -530,7 +530,7 @@ def _parse_cat(self, idx: int) -> tuple[AnyNode, int]:
def _parse_comp(self, idx: int) -> tuple[AnyNode, int]:
first, idx = self._parse_cat(idx)
- parts = [first]
+ parts: list[AnyNode | OpToken] = [first]
while self.match_ops(idx, COMPARISONS):
op_tok = cast(OpToken, self[idx])
idx += 1
diff --git a/parser/cst/named_node.py b/parser/cst/named_node.py
index 81dd0cd..0306663 100644
--- a/parser/cst/named_node.py
+++ b/parser/cst/named_node.py
@@ -53,8 +53,7 @@ def of(cls, token: HasRegion, parent: Node | None = None):
return cls(token.region, parent)
-AnyNamedNode: type[_AnyNamedNodeT] | type[NamedLeafCls] = cast(
- type[_AnyNamedNodeT], NamedLeafCls)
+AnyNamedNode: type[_AnyNamedNodeT] | type[NamedLeafCls] = NamedLeafCls
@dataclass
@@ -128,7 +127,7 @@ def register_once(name: str, cls: type[AnyNamedNode]):
NAME_REGISTRY[name, cls.size] = cls
else:
# Cast required because Pycharm stupid
- NAME_REGISTRY[name, cast(int, arity)] = cls
+ NAME_REGISTRY[name, arity] = cls
def decor(cls: type[AnyNamedNode]):
for n in names:
@@ -166,5 +165,5 @@ def node_from_token(token: Token, children: Sequence[Node] = None,
parent: Node | None = None, arity: int = None):
cls = node_cls_from_name(token.name, children, arity)
if children:
- return cls(token.region, parent, children)
+ return cast(type[NamedNodeCls], cls)(token.region, parent, list(children))
return cls(token.region, parent)
diff --git a/parser/cst/token_matcher.py b/parser/cst/token_matcher.py
index 28f2eac..e5d32ac 100644
--- a/parser/cst/token_matcher.py
+++ b/parser/cst/token_matcher.py
@@ -125,7 +125,7 @@ def _issubclass(cls: object, cls_or_tuple: type | tuple[type, ...]):
class Matcher:
# start argument is to save memory as then the list slices
# don't have to be stored separately
- def __init__(self, pattern: Iterable | type[Token] | Token | BaseMatcher,
+ def __init__(self, pattern: Iterable[BaseMatcher] | type[Token] | Token | BaseMatcher,
tokens: list[Token], start: int, src: str):
self.src = src
self.pattern = pattern
@@ -161,13 +161,13 @@ def _match(self):
self.result = self.pattern.matches(self.tokens, self.start, self.src)
-def matches(pattern: Iterable | type[Token] | Token | BaseMatcher,
+def matches(pattern: Iterable[BaseMatcher] | type[Token] | Token | BaseMatcher,
tokens: list[Token], start: int, src: str,
want_complete: bool = False) -> bool:
return Matcher(pattern, tokens, start, src).match(want_complete).success
-def match(pattern: Iterable | type[Token] | Token | BaseMatcher,
+def match(pattern: Iterable[BaseMatcher] | type[Token] | Token | BaseMatcher,
tokens: list[Token], start: int, src: str,
want_complete: bool = False) -> MatchResult:
return Matcher(pattern, tokens, start, src).match(want_complete).result
diff --git a/parser/lexer/src_handler.py b/parser/lexer/src_handler.py
index 973ec70..31293d5 100644
--- a/parser/lexer/src_handler.py
+++ b/parser/lexer/src_handler.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from typing import Sequence
+from typing import Sequence, cast
from .errors import LocatedTokenizerError
from .tokens import Token
@@ -27,11 +27,12 @@ def get(self, idx: int, eof: str = '\0') -> str:
def err(self, msg: str,
loc: int | Token | StrRegion | Sequence[int | Token | StrRegion],
- tp: type[BaseLocatedError] = None):
+ tp: type[BaseLocatedError] | None = None):
try:
+ # noinspection PyTypeChecker
seq: tuple[int | Token | StrRegion, ...] = tuple(loc)
except TypeError:
- seq = (loc,)
+ seq = (cast(int | Token | StrRegion, loc),)
region = region_union([
StrRegion(o, o + 1) if isinstance(o, int) else o
for o in seq])
diff --git a/parser/typecheck/name_resolver.py b/parser/typecheck/name_resolver.py
new file mode 100644
index 0000000..e797e55
--- /dev/null
+++ b/parser/typecheck/name_resolver.py
@@ -0,0 +1,127 @@
+from __future__ import annotations
+
+from typing import ClassVar
+
+from util import assert_not_none
+from .scope import NameInfo, FuncInfo, ParamInfo, Scope
+from .types import ValType, ListType, BoolType, VoidType, PARAM_TYPES
+from ..astgen.ast_node import AstNode
+from ..astgen.ast_nodes import AstIdent, AstDeclNode, VarDeclScope, VarDeclType, AstDefine
+from ..astgen.astgen import AstGen
+from ..astgen.filtered_walker import FilteredWalker
+from ..common import BaseLocatedError, RegionUnionArgT, region_union
+
+
+class NameResolutionError(BaseLocatedError):
+ pass
+
+
+# Variables:
+# - We can prevent usages before the variable is declared in 2 ways:
+# - Based on time: very sensible, like JS, but requires too many runtime features
+# - Based on location: somewhat makes sense except for inner functions -
+# they may be called later so should be able to access any variables.
+# - Or we can just ignore it (e.g. `var` in JS) and pretend everything was
+# declared at the top (but not assigned to - i.e. hoist `var foo;` to top).
+# To minimise accidental errors, option 1.2 is best
+# (errors shouldn't pass silently, and that method requires no special runtime)
+class NameResolver:
+ top_scope: Scope = None
+
+ def __init__(self, astgen: AstGen):
+ self.astgen = astgen
+ self.src = self.astgen.src
+
+ def _init(self):
+ self.ast = self.astgen.parse()
+ return Scope()
+
+ def run(self) -> Scope:
+ if self.top_scope:
+ return self.top_scope
+ self.top_scope = self._init()
+ ScopeNameResolver.resolve(self, block=self.ast.statements,
+ curr_scope=self.top_scope, parent_scopes=[])
+ return self.top_scope
+
+ def err(self, msg: str, loc: RegionUnionArgT):
+ return NameResolutionError(msg, region_union(loc), self.src)
+
+
+class ScopeNameResolver(FilteredWalker):
+ @classmethod
+ def resolve(cls, resolver: NameResolver, block: list[AstNode],
+ curr_scope: Scope, parent_scopes: list[Scope]):
+ return cls(resolver, block, curr_scope, parent_scopes).run()
+
+ def __init__(self, resolver: NameResolver, block: list[AstNode],
+ curr_scope: Scope, parent_scopes: list[Scope]):
+ super().__init__()
+ self.resolver = resolver
+ self.block = block
+ self.scope_stack = parent_scopes
+ self.curr_scope = curr_scope
+ self.top_scope = assert_not_none(self.resolver.top_scope)
+ self.inner_funcs: list[tuple[FuncInfo, AstDefine]] = []
+
+ def run(self):
+ self.scope_stack.append(self.curr_scope) # And our new scope onto the stack
+ self.walk(self.block)
+ self.walk_collected_inner_funcs()
+ return self.scope_stack.pop() # Remove current scope from stack & return it
+
+ def walk_collected_inner_funcs(self):
+ for fn_info, fn_decl in self.inner_funcs:
+ fn_info.subscope = ScopeNameResolver.resolve(
+ self.resolver, fn_decl.body, fn_info.subscope, self.scope_stack)
+
+ class_registry = FilteredWalker.create_cls_registry() # type: ClassVar
+
+ @class_registry.on_enter(AstIdent)
+ def enter_ident(self, n: AstIdent):
+ for s in reversed(self.scope_stack):
+ if info := s.declared.get(n.id):
+ self.curr_scope.used[n.id] = info
+ return
+ raise self.err(f"Name '{n.id}' is not defined", n)
+
+ @class_registry.on_enter(AstDeclNode)
+ def enter_decl(self, n: AstDeclNode):
+ # Need semi-special logic here to prevent walking it walking
+ # the AstIdent that is currently being declared.
+ self.walk(n.value) # Don't walk `n.ident`
+ # Do this after walking (that is when the name is bound)
+ ident = n.ident.id
+ target_scope = self.curr_scope if n.scope == VarDeclScope.LET else self.top_scope
+ if ident in target_scope.declared:
+ raise self.err("Variable already declared", n.ident)
+ target_scope.declared[ident] = NameInfo(target_scope, ident, (
+ ValType() if n.type == VarDeclType.VARIABLE else ListType()))
+ return True
+
+ @class_registry.on_enter(AstDefine)
+ def enter_fn_decl(self, fn: AstDefine):
+ ident = fn.ident.id
+ if ident in self.curr_scope.declared:
+ raise self.err("Function already declared", fn.ident)
+ subscope = Scope()
+ params: list[ParamInfo] = []
+ for tp_node, name_node in fn.params:
+ if tp_node.id not in PARAM_TYPES:
+ raise self.err("Unknown parameter type", tp_node)
+ if (name := name_node.id) in subscope.declared:
+ raise self.err("There is already a parameter of this name", name_node)
+ tp = BoolType() if tp_node.id == 'bool' else ValType()
+ subscope.declared[name] = NameInfo(subscope, name, tp, is_param=True)
+ params.append(ParamInfo(name, tp))
+ self.curr_scope.declared[ident] = info = FuncInfo.from_param_info(
+ self.curr_scope, ident, params,
+ ret_type=VoidType(), subscope=subscope)
+ self.inner_funcs.append((info, fn)) # Store funcs for later walking
+ # Skip walking body, only walk inner after collecting all declared
+ # variables in outer scope so function can use all variables
+ # declared in outer scope - even the ones declared below it)
+ return True
+
+ def err(self, msg: str, loc: RegionUnionArgT):
+ return self.resolver.err(msg, loc)
diff --git a/parser/typecheck/scope.py b/parser/typecheck/scope.py
new file mode 100644
index 0000000..133d73d
--- /dev/null
+++ b/parser/typecheck/scope.py
@@ -0,0 +1,49 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+
+from util.recursive_eq import recursive_eq
+from .types import TypeInfo, FunctionType
+
+
+@dataclass
+class NameInfo:
+ decl_scope: Scope
+ ident: str
+ tp_info: TypeInfo
+ # node: AstNode # <-- Why do we need this?
+ is_param: bool = field(default=False, kw_only=True)
+
+
+@dataclass
+class FuncInfo(NameInfo):
+ tp_info: FunctionType # Overrides types (doesn't change order)
+ params_info: list[ParamInfo]
+ # Can't just pass default_factory=Scope as it is only defined below
+ subscope: Scope = field(default_factory=lambda: Scope())
+
+ @classmethod
+ def from_param_info(
+ cls, decl_scope: Scope, ident: str, params_info: list[ParamInfo],
+ ret_type: TypeInfo, subscope: Scope | None = None):
+ subscope = subscope or Scope()
+ tp_info = FunctionType([p.tp for p in params_info], ret_type)
+ return cls(decl_scope, ident, tp_info, params_info, subscope)
+
+
+@dataclass
+class ParamInfo:
+ name: str
+ tp: TypeInfo
+
+
+@dataclass
+class Scope:
+ declared: dict[str, NameInfo] = field(default_factory=dict)
+ used: dict[str, NameInfo] = field(default_factory=dict)
+ """Add references to outer scopes' variables that we use.
+ (so type codegen/type-checker knows what each AstIdent refers to)"""
+
+
+# Prevent declared -> scope cmp recursion error
+Scope.__eq__ = recursive_eq(Scope.__eq__)
diff --git a/parser/typecheck/typecheck.py b/parser/typecheck/typecheck.py
index e989aa1..c0806b4 100644
--- a/parser/typecheck/typecheck.py
+++ b/parser/typecheck/typecheck.py
@@ -1,220 +1,285 @@
from __future__ import annotations
-from dataclasses import dataclass, field
+import contextlib
+import functools
+from collections.abc import Callable
+from typing import TypeAlias, TypeVar, ParamSpec
-from util.recursive_eq import recursive_eq
-from ..astgen.ast_node import (
- AstNode, walk_ast, AstIdent, AstDeclNode, AstDefine, VarDeclType,
- VarDeclScope, FilteredWalker)
-from ..astgen.astgen import AstGen
-from ..common import BaseLocatedError, StrRegion
+from util import assert_not_none
+from .name_resolver import NameResolver
+from .scope import FuncInfo, Scope
+from .types import (TypeInfo, ValType, BoolType, ListType, VoidType,
+ FunctionType, TypeType, TypeMetadata)
+from ..astgen.ast_nodes import *
+from ..common import BaseLocatedError, region_union, RegionUnionArgT
+T = TypeVar('T')
+P = ParamSpec('P')
+NodeTypecheckFn: TypeAlias = 'Callable[[Typechecker, AstNode], TypeInfo | None]'
+NodeTypecheckFnStrict: TypeAlias = 'Callable[[Typechecker, AstNode], TypeInfo]'
-@dataclass
-class TypeInfo:
- def __post_init__(self):
- assert type(self) != TypeInfo, "Cannot instantiate TypeInfo directly,use a subclass"
+class TypecheckError(BaseLocatedError):
+ """Errors raised by the typechecker"""
-@dataclass
-class ValType(TypeInfo):
- pass
-
-@dataclass
-class BoolType(TypeInfo):
- pass
-
-
-@dataclass
-class ListType(TypeInfo):
- pass
-
-
-@dataclass
-class VoidType(TypeInfo):
- """The ``void`` type - represents 'there must not be a value here'.
-
- For example, this is the return type of function that don't return anything
- (e.g. all regular user-defined scratch functions).
- """
-
-
-@dataclass
-class FunctionType(TypeInfo):
- arg_types: list[TypeInfo]
- ret_type: TypeInfo
-
-
-@dataclass
-class NameInfo:
- decl_scope: Scope
- ident: str
- tp_info: TypeInfo
- # node: AstNode # <-- Why do we need this?
- is_param: bool = field(default=False, kw_only=True)
-
-
-@dataclass
-class FuncInfo(NameInfo):
- tp_info: FunctionType # Overrides types (doesn't change order)
- params_info: list[ParamInfo]
- # Can't just pass default_factory=Scope as it is only defined below
- subscope: Scope = field(default_factory=lambda: Scope())
+class _TypecheckerInitVars:
+ """Stores variables needed at time of initialising the Typechecker class
+ (yes the class itself you read that right ;-)"""
+ typecheck_dispatch: dict[type[AstNode], NodeTypecheckFnStrict] = {}
+ and_set_type_metadata: Callable[[NodeTypecheckFn], NodeTypecheckFnStrict]
@classmethod
- def from_param_info(
- cls, decl_scope: Scope, ident: str, params_info: list[ParamInfo],
- ret_type: TypeInfo, subscope: Scope = None):
- subscope = subscope or Scope()
- tp_info = FunctionType([p.tp for p in params_info], ret_type)
- return cls(decl_scope, ident, tp_info, params_info, subscope)
-
-
-@dataclass
-class ParamInfo:
- name: str
- tp: TypeInfo
-
-
-@dataclass
-class Scope:
- declared: dict[str, NameInfo] = field(default_factory=dict)
- used: dict[str, NameInfo] = field(default_factory=dict)
- """Add references to outer scopes' variables that we use.
- (so type codegen/type-checker knows what each AstIdent refers to)"""
-
-
-Scope.__eq__ = recursive_eq(Scope.__eq__)
-
-
-class NameResolutionError(BaseLocatedError):
- pass
-
-
-# The reason `let` isn't used is because we don't want to imply similarity
-# between parameters as local variables (where none exists in Scratch).
-# Also, we might want to use `let` later as a modifier to bind it to
-# an actual local var.
-# Don't need to `sys.intern` these manually as Python automatically does
-# this for literals.
-PARAM_TYPES = {'number', 'string', 'val', 'bool'}
-
-
-# Variables:
-# - We can prevent usages before the variable is declared in 2 ways:
-# - Based on time: very sensible, like JS, but requires too many runtime features
-# - Based on location: somewhat makes sense except for inner functions -
-# they may be called later so should be able to access any variables.
-# - Or we can just ignore it (e.g. `var` in JS) and pretend everything was
-# declared at the top (but not assigned to - i.e. hoist `var foo;` to top).
-# To minimise accidental errors, option 1.2 is best
-# (errors shouldn't pass silently, and that method requires no special runtime)
-class NameResolver:
- def __init__(self, astgen: AstGen):
- self.astgen = astgen
- self.src = self.astgen.src
- self.top_scope: Scope | None = None
-
- def _init(self):
- self.ast = self.astgen.parse()
- self.top_scope = Scope()
-
- def run(self):
- if self.top_scope:
- return self.top_scope
- self._init()
- self.run_on_new_scope(self.ast.statements, curr_scope=self.top_scope)
- return self.top_scope
-
- def run_on_new_scope(self, block: list[AstNode], parent_scopes: list[Scope] = None,
- curr_scope: Scope = None):
- def enter_ident(n: AstIdent):
- for s in scope_stack[::-1]: # Inefficient, creates a copy!
- if info := s.declared.get(n.id):
- curr_scope.used[n.id] = info
- return
- raise self.err(f"Name '{n.id}' is not defined", n.region)
-
- def enter_decl(n: AstDeclNode):
- # Need semi-special logic here to prevent walking it walking
- # the AstIdent that is currently being declared.
- AstNode.walk_obj(n.value, walker) # Don't walk `n.ident`
- # Do this after walking (that is when the name is bound)
- ident = n.ident.id
- target_scope = curr_scope if n.scope == VarDeclScope.LET else self.top_scope
- if ident in target_scope.declared:
- raise self.err("Variable already declared", n.region)
- target_scope.declared[ident] = NameInfo(target_scope, ident, (
- ValType() if n.type == VarDeclType.VARIABLE else ListType()))
- return True
-
- def enter_fn_decl(fn: AstDefine):
- ident = fn.ident.id
- if ident in curr_scope.declared:
- raise self.err("Function already declared", fn.ident.region)
- subscope = Scope()
- params: list[ParamInfo] = []
- for tp_node, name_node in fn.params:
- if tp_node.id not in PARAM_TYPES:
- raise self.err("Unknown parameter type", tp_node.region)
- if (name := name_node.id) in subscope.declared:
- raise self.err("There is already a parameter of this name",
- name_node.region)
- tp = BoolType() if tp_node.id == 'bool' else ValType()
- subscope.declared[name] = NameInfo(subscope, name, tp, is_param=True)
- params.append(ParamInfo(name, tp))
- curr_scope.declared[ident] = info = FuncInfo.from_param_info(
- curr_scope, ident, params,
- ret_type=VoidType(), subscope=subscope)
- inner_funcs.append((info, fn)) # Store funcs for later walking
- # Skip walking body, only walk inner after collecting all declared
- # variables in outer scope so function can use all variables
- # declared in outer scope - even the ones declared below it)
- return True
-
- curr_scope = curr_scope or Scope()
- scope_stack = parent_scopes or []
- scope_stack.append(curr_scope)
- inner_funcs: list[tuple[FuncInfo, AstDefine]] = []
- # Walk self
- walker = (FilteredWalker()
- .register_enter(AstIdent, enter_ident)
- .register_enter(AstDeclNode, enter_decl)
- .register_enter(AstDefine, enter_fn_decl))
- walk_ast(block, walker)
- # Walk sub-functions
- for fn_info, fn_decl in inner_funcs:
- fn_info.subscope = self.run_on_new_scope(
- fn_decl.body, scope_stack, fn_info.subscope)
- return scope_stack.pop() # Remove current scope from stack & return it
-
- def err(self, msg: str, region: StrRegion):
- return NameResolutionError(msg, region, self.src)
+ def method(cls, attr: str):
+ """To be used as decorator, like @_TypecheckerInitVars.method('attr')"""
+ def decor(f: T) -> T:
+ setattr(cls, attr, f)
+ return f
+ return decor
class Typechecker:
+ _curr_scope: Scope
+
def __init__(self, name_resolver: NameResolver):
self.resolver = name_resolver
self.src = self.resolver.src
self.is_ok: bool | None = None
+ self.typed_ast: AstProgramNode[TypeMetadata] | None = None
def _init(self):
- self.resolver.run()
- self.ast = self.resolver.ast
- self.top_scope = self.resolver.top_scope
-
- def run(self):
- if self.is_ok is None:
- return self.is_ok
- self._typecheck()
- self.is_ok = True
- return self.is_ok
-
- def _typecheck(self):
- walker = FilteredWalker()
-
- self.ast.walk(walker)
- ...
-
+ self.top_scope = self._curr_scope = self.resolver.run()
+ self.orig_ast = self.resolver.ast
+ def run(self) -> AstProgramNode[TypeMetadata]:
+ if self.typed_ast is not None:
+ return self.typed_ast
+ self._init()
+ self._typecheck(self.orig_ast)
+ self.typed_ast = self.orig_ast # should now have the types
+ return assert_not_none(self.typed_ast)
+
+ @_TypecheckerInitVars.method('and_set_type_metadata') # Such Java vibes
+ def _and_set_type_metadata(
+ self: Callable[[Typechecker, AstNode, P], TypeInfo | None],
+ fn: Callable[[Typechecker, AstNode, P], TypeInfo | None] | None = None
+ ) -> Callable[[Typechecker, AstNode, P], TypeInfo]:
+ if fn is None:
+ assert callable(self)
+ fn = self # Called as decor in this class
+
+ @functools.wraps(fn)
+ def new_fn(self_inner: Typechecker, n: AstNode, *args, **kwargs) -> TypeInfo:
+ n_type: TypeInfo = fn(self_inner, n, *args, **kwargs) or VoidType()
+ n.meta = TypeMetadata(n_type) # ^^ checker return None = void type
+ return n_type
+ return new_fn
+
+ def _node_typechecker(self: type[AstNode], tp: type[AstNode] | None = None):
+ if tp is None:
+ assert callable(self)
+ tp_ = self if tp is None else tp # Need new var coz Pycharm stupid
+
+ def decor(fn: NodeTypecheckFn):
+ new_fn = _TypecheckerInitVars.typecheck_dispatch[tp_] = (
+ _TypecheckerInitVars.and_set_type_metadata(fn))
+ return new_fn
+ return decor
+
+ def _typecheck(self, n: AstNode):
+ try:
+ fn = _TypecheckerInitVars.typecheck_dispatch[type(n)]
+ except KeyError:
+ fn = type(self)._typecheck_node_fallback
+ return fn(self, n)
+
+ def _typecheck_node_fallback(self, n: AstNode):
+ raise NotImplementedError(f"No typechecker function for node "
+ f"type {type(n).__name__}")
+
+ @_node_typechecker(AstProgramNode)
+ def _typecheck_program(self, n: AstProgramNode):
+ self._typecheck_block(n.statements)
+
+ def _typecheck_block(self, block: list[AstNode]):
+ for smt in block:
+ self.expect_type(self._typecheck(smt), VoidType(), smt)
+
+ @_node_typechecker(AstDeclNode)
+ def _typecheck_decl(self, n: AstDeclNode):
+ # Note: must come before 'if' so always set n.ident.meta.type
+ expect = self._typecheck_ident_declared(n.ident, decl=n)
+ if n.value:
+ self.expect_type(self._typecheck(n.value), expect, n)
+
+ @_and_set_type_metadata
+ def _typecheck_ident_declared(self, n: AstIdent, decl: AstDeclNode):
+ return self._resolve_scope(decl.scope).declared[n.id].tp_info
+
+ @_node_typechecker(AstRepeat)
+ def _typecheck_repeat(self, n: AstRepeat):
+ # For now, we don't differentiate between number/string (as sc doesn't)
+ self.expect_type(self._typecheck(n.count), ValType(), n.count)
+ self._typecheck_block(n.body)
+
+ @_node_typechecker(AstIf)
+ def _typecheck_if(self, n: AstIf):
+ self.expect_type(self._typecheck(n.cond), BoolType(), n.cond)
+ self._typecheck_block(n.if_body)
+ if n.else_body is not None:
+ self._typecheck_block(n.else_body)
+
+ @_node_typechecker(AstWhile)
+ def _typecheck_while(self, n: AstWhile):
+ self.expect_type(self._typecheck(n.cond), BoolType(), n.cond)
+ self._typecheck_block(n.body)
+
+ @_node_typechecker(AstAssign)
+ def _typecheck_assign(self, n: AstAssign): # super tempted to call this _typecheck_ass
+ if isinstance(n.target, AstIdent):
+ # Assignment-to also counts as a type of usage (also sets .meta)
+ target_tp = self._typecheck_ident_used(n.target)
+ elif isinstance(n.target, AstItem): # ls[i] = v
+ target_tp = self._typecheck(n.target) # Also checks that `ls` is a list
+ elif isinstance(n.target, AstAttribute):
+ raise self.err("Setting attributes is currently unsupported", n.target)
+ else:
+ assert 0, "Unknown simple-assignment type"
+ if target_tp != ValType(): # Not even bool
+ raise self.err(f"Cannot assign directly to {target_tp}", n.target)
+ self.expect_type(self._typecheck(n.source), target_tp, n.source)
+
+ @_node_typechecker(AstAugAssign)
+ def _typecheck_aug_assign(self, n: AstAugAssign):
+ # TODO: change this when desugaring is implemented
+ # (for now only +=, only on variables)
+ if n.op != '+=':
+ raise self.err(f"The '{n.op}' operator is not implemented", n)
+ if not isinstance(n.target, AstIdent):
+ raise self.err(f"The '+=' operator is only implemented for variables", n)
+ target_tp = self._typecheck_ident_used(n.target)
+ if target_tp != ValType():
+ raise self.err(f"Cannot apply += to {target_tp}", n)
+ self.expect_type(self._typecheck(n.source), ValType(), n.source)
+
+ @_node_typechecker(AstDefine)
+ def _typecheck_define(self, n: AstDefine):
+ func_info = self._curr_scope.declared[n.ident.id]
+ assert isinstance(func_info, FuncInfo)
+ f_type = func_info.tp_info
+ n.ident.meta = TypeMetadata(f_type)
+ # Could also use .param_info here - should be same either way
+ for (type_node, name_node), param_type in zip(n.params, f_type.arg_types):
+ name_node.meta = TypeMetadata(param_type)
+ type_node.meta = TypeMetadata(TypeType(param_type))
+ with self._enter_scope(func_info.subscope):
+ self._typecheck_block(n.body)
+
+ @contextlib.contextmanager
+ def _enter_scope(self, scope: Scope):
+ old_scope = self._curr_scope
+ self._curr_scope = scope
+ try:
+ yield scope
+ finally:
+ self._curr_scope = old_scope
+
+ @_node_typechecker(AstNumber)
+ def _typecheck_number(self, _n: AstNumber):
+ return ValType()
+
+ @_node_typechecker(AstString)
+ def _typecheck_string(self, _n: AstString):
+ return ValType()
+
+ @_node_typechecker(AstListLiteral)
+ def _typecheck_list(self, n: AstListLiteral):
+ for item in n.items:
+ if self._typecheck(item) != ValType():
+ raise self.err("Can only have ValType()s in list", item)
+ return ListType()
+
+ @_node_typechecker(AstIdent)
+ def _typecheck_ident_used(self, n: AstIdent):
+ return self._curr_scope.used[n.id].tp_info
+
+ @_node_typechecker(AstAttrName)
+ def _typecheck_attr_name(self, _n: AstAttrName):
+ assert 0, "AstAttrName has no type, cannot be checked on its own"
+
+ @_node_typechecker(AstAttribute)
+ def _typecheck_attribute(self, n: AstAttribute):
+ # TODO: implement this properly, with better types and stuff
+ raise self.err("Attributes are not implemented yet", n)
+
+ @_node_typechecker(AstItem)
+ def _typecheck_item(self, n: AstItem):
+ # TODO: this will require different intrinsics for string vs list getitem
+ container_tp = self._typecheck(n.obj)
+ if container_tp not in (ListType(), ValType()):
+ raise self.err(f"Cannot get item of {container_tp}", n)
+ self.expect_type(self._typecheck(n.index), ValType(), n.index)
+ return ValType() # no list-in-list
+
+ @_node_typechecker(AstCall)
+ def _typecheck_call(self, n: AstCall):
+ called_tp = self._typecheck(n.obj)
+ if not isinstance(called_tp, FunctionType):
+ raise self.err(f"Cannot call {called_tp}", n.obj)
+ if (n_expect := len(called_tp.arg_types)) != (n_given := len(n.args)):
+ if n.args and n_given > n_expect:
+ region = n.args[n_expect].region # First unexpected one
+ else:
+ region = n.region
+ raise self.err(f"Incorrect number of arguments, expected "
+ f"{len(called_tp.arg_types)}, got {len(n.args)}",
+ region)
+ return self._check_abstract_op_types_only(n.args, called_tp)
+
+ _BINARY_OP_TYPES = dict.fromkeys(
+ [*'+-*/%', '**', '..'],
+ FunctionType([ValType(), ValType()], ValType())
+ ) | dict.fromkeys(
+ ['==', '!=', '<', '>', '<=', '>='],
+ FunctionType([ValType(), ValType()], BoolType())
+ ) | dict.fromkeys(
+ ['&&', '||'],
+ FunctionType([BoolType(), BoolType()], BoolType())
+ )
+
+ _UNARY_OP_TYPES = dict.fromkeys(
+ [*'+-'],
+ FunctionType([ValType()], ValType())
+ ) | dict.fromkeys(
+ ['!'],
+ FunctionType([BoolType()], BoolType())
+ )
+
+ def _check_abstract_op_types_only(
+ self, arg_types: list[AstNode], op_type: FunctionType):
+ """Arity should be checked before invoking as that allow better error highlighting"""
+ assert len(op_type.arg_types) == len(arg_types)
+ for decl_t, arg_node in zip(op_type.arg_types, arg_types):
+ self.expect_type(self._typecheck(arg_node), decl_t, arg_node)
+ return op_type.ret_type
+
+ # TODO: allow casting bool to val? - auto-cast or explicit?
+ @_node_typechecker(AstBinOp)
+ def _typecheck_bin_op(self, n: AstBinOp):
+ return self._check_abstract_op_types_only(
+ [n.left, n.right], self._BINARY_OP_TYPES[n.op])
+
+ @_node_typechecker(AstUnaryOp)
+ def _typecheck_unary_op(self, n: AstUnaryOp):
+ return self._check_abstract_op_types_only(
+ [n.operand], self._UNARY_OP_TYPES[n.op])
+
+ def _resolve_scope(self, scope_tp: VarDeclScope):
+ return self.top_scope if scope_tp == VarDeclScope.GLOBAL else self._curr_scope
+
+ def err(self, msg: str, loc: RegionUnionArgT):
+ return TypecheckError(msg, region_union(loc), self.src)
+
+ def expect_type(self, actual: TypeInfo, exp: TypeInfo, loc: RegionUnionArgT):
+ if exp != actual:
+ raise self.err(f"Expected type {exp}, got type {actual}", loc)
diff --git a/parser/typecheck/types.py b/parser/typecheck/types.py
new file mode 100644
index 0000000..be35440
--- /dev/null
+++ b/parser/typecheck/types.py
@@ -0,0 +1,73 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+
+
+@dataclass
+class TypeMetadata:
+ type: TypeInfo
+
+
+@dataclass
+class TypeInfo:
+ def __post_init__(self):
+ assert type(self) != TypeInfo, "Cannot instantiate TypeInfo directly, use a subclass"
+
+
+@dataclass
+class ValType(TypeInfo):
+ def __str__(self):
+ return 'val'
+
+
+@dataclass
+class BoolType(TypeInfo):
+ def __str__(self):
+ return 'bool'
+
+
+@dataclass
+class ListType(TypeInfo):
+ def __str__(self):
+ return 'list'
+
+
+@dataclass
+class VoidType(TypeInfo):
+ """The ``void`` type - represents 'there must not be a value here'.
+
+ For example, this is the return type of function that don't return anything
+ (e.g. all regular user-defined scratch functions).
+ """
+
+ def __str__(self):
+ return 'void'
+
+
+@dataclass
+class TypeType(TypeInfo):
+ """The equivalent of Java's Class or Python's type[T]"""
+ tp: TypeInfo
+
+ def __str__(self):
+ # Now we come to the decision: how to display this: OCaml, Java/C++, or
+ # Python style? I'll just go with the standard angle brackets for now
+ return f'type<{self.tp}>'
+
+
+@dataclass
+class FunctionType(TypeInfo):
+ arg_types: list[TypeInfo]
+ ret_type: TypeInfo
+
+ def __str__(self):
+ return f'({", ".join(map(str, self.arg_types))}) -> {self.ret_type}'
+
+
+# The reason `let` isn't used is because we don't want to imply similarity
+# between parameters as local variables (where none exists in Scratch).
+# Also, we might want to use `let` later as a modifier to bind it to
+# an actual local var.
+# Don't need to `sys.intern` these manually as Python automatically does
+# this for literals.
+PARAM_TYPES = {'number', 'string', 'val', 'bool'}
diff --git a/pythonfuzz_corpus/0246c2db3d3bf7f14c4fa5653ce8fcf1507ee7346176f1383efdf9e1181fc13e b/pythonfuzz_corpus/0246c2db3d3bf7f14c4fa5653ce8fcf1507ee7346176f1383efdf9e1181fc13e
new file mode 100644
index 0000000..5698a1e
Binary files /dev/null and b/pythonfuzz_corpus/0246c2db3d3bf7f14c4fa5653ce8fcf1507ee7346176f1383efdf9e1181fc13e differ
diff --git a/pythonfuzz_corpus/02b9da05e5c5f947e8ae343838a1242a7121eefc41a76c61744292296d2b7861 b/pythonfuzz_corpus/02b9da05e5c5f947e8ae343838a1242a7121eefc41a76c61744292296d2b7861
new file mode 100644
index 0000000..a4a2be5
Binary files /dev/null and b/pythonfuzz_corpus/02b9da05e5c5f947e8ae343838a1242a7121eefc41a76c61744292296d2b7861 differ
diff --git a/pythonfuzz_corpus/02cca8d59e735b3f1d523b3f774dd37d6a600d125558198013a1c93c2b8cc833 b/pythonfuzz_corpus/02cca8d59e735b3f1d523b3f774dd37d6a600d125558198013a1c93c2b8cc833
new file mode 100644
index 0000000..b95d2e6
Binary files /dev/null and b/pythonfuzz_corpus/02cca8d59e735b3f1d523b3f774dd37d6a600d125558198013a1c93c2b8cc833 differ
diff --git a/pythonfuzz_corpus/04ceb7b27f23aac869a97db5a8e9f0554f14da01823a9b5bc6057c2e3b0374b7 b/pythonfuzz_corpus/04ceb7b27f23aac869a97db5a8e9f0554f14da01823a9b5bc6057c2e3b0374b7
new file mode 100644
index 0000000..36a418b
Binary files /dev/null and b/pythonfuzz_corpus/04ceb7b27f23aac869a97db5a8e9f0554f14da01823a9b5bc6057c2e3b0374b7 differ
diff --git a/pythonfuzz_corpus/09f34627e1cee3156250c7856a425a327702463d97bbf216753bfd6d219638ff b/pythonfuzz_corpus/09f34627e1cee3156250c7856a425a327702463d97bbf216753bfd6d219638ff
new file mode 100644
index 0000000..be75b2e
--- /dev/null
+++ b/pythonfuzz_corpus/09f34627e1cee3156250c7856a425a327702463d97bbf216753bfd6d219638ff
@@ -0,0 +1 @@
+s=s+Íë+s.99.99;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/0b6d723db6acd1b91d7dcc14bbde368aee29af06c58b3f8f326c33339b2a922b b/pythonfuzz_corpus/0b6d723db6acd1b91d7dcc14bbde368aee29af06c58b3f8f326c33339b2a922b
new file mode 100644
index 0000000..ffdf74a
Binary files /dev/null and b/pythonfuzz_corpus/0b6d723db6acd1b91d7dcc14bbde368aee29af06c58b3f8f326c33339b2a922b differ
diff --git a/pythonfuzz_corpus/14859c9d0ebc311e45b30e9e30227199c0f80a3c3570f8a2f7590b9a151750e9 b/pythonfuzz_corpus/14859c9d0ebc311e45b30e9e30227199c0f80a3c3570f8a2f7590b9a151750e9
new file mode 100644
index 0000000..2a5e80a
--- /dev/null
+++ b/pythonfuzz_corpus/14859c9d0ebc311e45b30e9e30227199c0f80a3c3570f8a2f7590b9a151750e9
@@ -0,0 +1 @@
+s='\b9';
\ No newline at end of file
diff --git a/pythonfuzz_corpus/190063cf7caf4bb09a70d77e085c638b88ec56c53a53bd295c38ad2d305af3c7 b/pythonfuzz_corpus/190063cf7caf4bb09a70d77e085c638b88ec56c53a53bd295c38ad2d305af3c7
new file mode 100644
index 0000000..25ce481
Binary files /dev/null and b/pythonfuzz_corpus/190063cf7caf4bb09a70d77e085c638b88ec56c53a53bd295c38ad2d305af3c7 differ
diff --git a/pythonfuzz_corpus/1a6e0a4cf877bbce59e9d249121e5adb191c93145c85d33506e42e9ef0f05334 b/pythonfuzz_corpus/1a6e0a4cf877bbce59e9d249121e5adb191c93145c85d33506e42e9ef0f05334
new file mode 100644
index 0000000..e591c0a
--- /dev/null
+++ b/pythonfuzz_corpus/1a6e0a4cf877bbce59e9d249121e5adb191c93145c85d33506e42e9ef0f05334
@@ -0,0 +1 @@
+ÿÿ{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/1db410e4cfabad914e7791dad7bacb567e7ea90d31188e5bdbb50dc9f21e9bb4 b/pythonfuzz_corpus/1db410e4cfabad914e7791dad7bacb567e7ea90d31188e5bdbb50dc9f21e9bb4
new file mode 100644
index 0000000..e510ea3
Binary files /dev/null and b/pythonfuzz_corpus/1db410e4cfabad914e7791dad7bacb567e7ea90d31188e5bdbb50dc9f21e9bb4 differ
diff --git a/pythonfuzz_corpus/1f14378f71ad23f335645f03424d2fd4431d6fe8730d55a2b457637653f2e868 b/pythonfuzz_corpus/1f14378f71ad23f335645f03424d2fd4431d6fe8730d55a2b457637653f2e868
new file mode 100644
index 0000000..0fc7452
Binary files /dev/null and b/pythonfuzz_corpus/1f14378f71ad23f335645f03424d2fd4431d6fe8730d55a2b457637653f2e868 differ
diff --git a/pythonfuzz_corpus/223af19029a4fbb20e07d5048dac593a52e3b26fb3b16c17b6b587eb0978739b b/pythonfuzz_corpus/223af19029a4fbb20e07d5048dac593a52e3b26fb3b16c17b6b587eb0978739b
new file mode 100644
index 0000000..fc95c9a
--- /dev/null
+++ b/pythonfuzz_corpus/223af19029a4fbb20e07d5048dac593a52e3b26fb3b16c17b6b587eb0978739b
@@ -0,0 +1 @@
+7:’È)()();
\ No newline at end of file
diff --git a/pythonfuzz_corpus/24a5b86c9ab7c697a058e10c8152c1a7191ddde8ff14770f88318041798bfc54 b/pythonfuzz_corpus/24a5b86c9ab7c697a058e10c8152c1a7191ddde8ff14770f88318041798bfc54
new file mode 100644
index 0000000..6aed4d8
--- /dev/null
+++ b/pythonfuzz_corpus/24a5b86c9ab7c697a058e10c8152c1a7191ddde8ff14770f88318041798bfc54
@@ -0,0 +1,2 @@
+9ý
+),&
\ No newline at end of file
diff --git a/pythonfuzz_corpus/2617872c441d7d17737b8f66c1984461e74d149b1cb8456c1256d14ea29e9efb b/pythonfuzz_corpus/2617872c441d7d17737b8f66c1984461e74d149b1cb8456c1256d14ea29e9efb
new file mode 100644
index 0000000..69411d9
--- /dev/null
+++ b/pythonfuzz_corpus/2617872c441d7d17737b8f66c1984461e74d149b1cb8456c1256d14ea29e9efb
@@ -0,0 +1 @@
+6Ûà
\ No newline at end of file
diff --git a/pythonfuzz_corpus/2d850f9ecede02b524d029ca238e283bf15082990ca00b153893d29f7ddc2e0b b/pythonfuzz_corpus/2d850f9ecede02b524d029ca238e283bf15082990ca00b153893d29f7ddc2e0b
new file mode 100644
index 0000000..14557cf
Binary files /dev/null and b/pythonfuzz_corpus/2d850f9ecede02b524d029ca238e283bf15082990ca00b153893d29f7ddc2e0b differ
diff --git a/pythonfuzz_corpus/2fd6749e21905444150cd7133acc5e93f5557eba8c268ca2290dbbe40ec4ad04 b/pythonfuzz_corpus/2fd6749e21905444150cd7133acc5e93f5557eba8c268ca2290dbbe40ec4ad04
new file mode 100644
index 0000000..74877c6
--- /dev/null
+++ b/pythonfuzz_corpus/2fd6749e21905444150cd7133acc5e93f5557eba8c268ca2290dbbe40ec4ad04
@@ -0,0 +1 @@
+X.P.PøT
\ No newline at end of file
diff --git a/pythonfuzz_corpus/317310faf64795d07411a956a1174e1be09db5c2a5b1af012b1da18b5716df59 b/pythonfuzz_corpus/317310faf64795d07411a956a1174e1be09db5c2a5b1af012b1da18b5716df59
new file mode 100644
index 0000000..67c62f0
--- /dev/null
+++ b/pythonfuzz_corpus/317310faf64795d07411a956a1174e1be09db5c2a5b1af012b1da18b5716df59
@@ -0,0 +1 @@
+if++7{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/3244d329e454e10743f260d8125c1e507ad34a80a5044a299fa10475514fb4a5 b/pythonfuzz_corpus/3244d329e454e10743f260d8125c1e507ad34a80a5044a299fa10475514fb4a5
new file mode 100644
index 0000000..5f03e51
--- /dev/null
+++ b/pythonfuzz_corpus/3244d329e454e10743f260d8125c1e507ad34a80a5044a299fa10475514fb4a5
@@ -0,0 +1 @@
+if 7+7{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/33771b111b151c572fae44a4c96799dcf3814f1edc9b190b51bfa29096295282 b/pythonfuzz_corpus/33771b111b151c572fae44a4c96799dcf3814f1edc9b190b51bfa29096295282
new file mode 100644
index 0000000..b104fc8
--- /dev/null
+++ b/pythonfuzz_corpus/33771b111b151c572fae44a4c96799dcf3814f1edc9b190b51bfa29096295282
@@ -0,0 +1 @@
+f**fã*_
\ No newline at end of file
diff --git a/pythonfuzz_corpus/354dc5510bff7e22ddca9998c5369eb2aa4de28cea6cc758f140fa5a64cf56dd b/pythonfuzz_corpus/354dc5510bff7e22ddca9998c5369eb2aa4de28cea6cc758f140fa5a64cf56dd
new file mode 100644
index 0000000..0a8715e
--- /dev/null
+++ b/pythonfuzz_corpus/354dc5510bff7e22ddca9998c5369eb2aa4de28cea6cc758f140fa5a64cf56dd
@@ -0,0 +1 @@
+if+7{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/37bb7d2670f70faddb55def9fe2e206092c4bb1ba011f9d5b8815da841c3e9b1 b/pythonfuzz_corpus/37bb7d2670f70faddb55def9fe2e206092c4bb1ba011f9d5b8815da841c3e9b1
new file mode 100644
index 0000000..5d8c418
--- /dev/null
+++ b/pythonfuzz_corpus/37bb7d2670f70faddb55def9fe2e206092c4bb1ba011f9d5b8815da841c3e9b1
@@ -0,0 +1 @@
+/»r
\ No newline at end of file
diff --git a/pythonfuzz_corpus/39089896ccf0e398e93762261a2f67be3ce4171eaa08aa5ad6a8fb5683011d36 b/pythonfuzz_corpus/39089896ccf0e398e93762261a2f67be3ce4171eaa08aa5ad6a8fb5683011d36
new file mode 100644
index 0000000..e0fb20e
--- /dev/null
+++ b/pythonfuzz_corpus/39089896ccf0e398e93762261a2f67be3ce4171eaa08aa5ad6a8fb5683011d36
@@ -0,0 +1 @@
+' 7s9'.e/=' 7+6'.e/
\ No newline at end of file
diff --git a/pythonfuzz_corpus/3b1d23b2b400420d8fd298dc2c504837130a18ebe49dcaa95fb37e0c8ad64f5f b/pythonfuzz_corpus/3b1d23b2b400420d8fd298dc2c504837130a18ebe49dcaa95fb37e0c8ad64f5f
new file mode 100644
index 0000000..be00bbc
--- /dev/null
+++ b/pythonfuzz_corpus/3b1d23b2b400420d8fd298dc2c504837130a18ebe49dcaa95fb37e0c8ad64f5f
@@ -0,0 +1 @@
+(!(G+l))()();
\ No newline at end of file
diff --git a/pythonfuzz_corpus/3d7413ac5655eff0838b221dd2471cdf293eee48d22ebd6a318dd638212cb8f3 b/pythonfuzz_corpus/3d7413ac5655eff0838b221dd2471cdf293eee48d22ebd6a318dd638212cb8f3
new file mode 100644
index 0000000..b0b97a5
Binary files /dev/null and b/pythonfuzz_corpus/3d7413ac5655eff0838b221dd2471cdf293eee48d22ebd6a318dd638212cb8f3 differ
diff --git a/pythonfuzz_corpus/3ebd90fb3ff79d0668f038fed8e2a296c51e928e070f70b9a8013e24e522c032 b/pythonfuzz_corpus/3ebd90fb3ff79d0668f038fed8e2a296c51e928e070f70b9a8013e24e522c032
new file mode 100644
index 0000000..3392d42
Binary files /dev/null and b/pythonfuzz_corpus/3ebd90fb3ff79d0668f038fed8e2a296c51e928e070f70b9a8013e24e522c032 differ
diff --git a/pythonfuzz_corpus/4203e71fc7a66231df1e4bc3a623c0b413548834a9b6684e4c1c79f0c173ae2a b/pythonfuzz_corpus/4203e71fc7a66231df1e4bc3a623c0b413548834a9b6684e4c1c79f0c173ae2a
new file mode 100644
index 0000000..594376e
--- /dev/null
+++ b/pythonfuzz_corpus/4203e71fc7a66231df1e4bc3a623c0b413548834a9b6684e4c1c79f0c173ae2a
@@ -0,0 +1 @@
+s='d9's
\ No newline at end of file
diff --git a/pythonfuzz_corpus/42c1627332dc8dd001716c61e9398bbbdc4ff67b14215eafd4199785f1bb313a b/pythonfuzz_corpus/42c1627332dc8dd001716c61e9398bbbdc4ff67b14215eafd4199785f1bb313a
new file mode 100644
index 0000000..f4bf409
--- /dev/null
+++ b/pythonfuzz_corpus/42c1627332dc8dd001716c61e9398bbbdc4ff67b14215eafd4199785f1bb313a
@@ -0,0 +1 @@
+if+7+7{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/49faa6d40415ac33f0decbe972b297bd7fa54a97fb4f704ab121201454bb9e95 b/pythonfuzz_corpus/49faa6d40415ac33f0decbe972b297bd7fa54a97fb4f704ab121201454bb9e95
new file mode 100644
index 0000000..990b3cf
Binary files /dev/null and b/pythonfuzz_corpus/49faa6d40415ac33f0decbe972b297bd7fa54a97fb4f704ab121201454bb9e95 differ
diff --git a/pythonfuzz_corpus/518d46904a458139d18683ea4c5ab8b82e7dadde0794a178393968a6940dfe93 b/pythonfuzz_corpus/518d46904a458139d18683ea4c5ab8b82e7dadde0794a178393968a6940dfe93
new file mode 100644
index 0000000..7ff5acb
--- /dev/null
+++ b/pythonfuzz_corpus/518d46904a458139d18683ea4c5ab8b82e7dadde0794a178393968a6940dfe93
@@ -0,0 +1 @@
+s=+Ë9;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/564e6580e0dabd52b18147402390f79c019005ecbca0fff4150066a4c96ed9f5 b/pythonfuzz_corpus/564e6580e0dabd52b18147402390f79c019005ecbca0fff4150066a4c96ed9f5
new file mode 100644
index 0000000..cdc2d90
Binary files /dev/null and b/pythonfuzz_corpus/564e6580e0dabd52b18147402390f79c019005ecbca0fff4150066a4c96ed9f5 differ
diff --git a/pythonfuzz_corpus/5653ff00e40ddd638f4f03358a984622e1e04fc33ca00ec79aeccfcb2097537a b/pythonfuzz_corpus/5653ff00e40ddd638f4f03358a984622e1e04fc33ca00ec79aeccfcb2097537a
new file mode 100644
index 0000000..ef21854
--- /dev/null
+++ b/pythonfuzz_corpus/5653ff00e40ddd638f4f03358a984622e1e04fc33ca00ec79aeccfcb2097537a
@@ -0,0 +1 @@
+zƒ/è*..
\ No newline at end of file
diff --git a/pythonfuzz_corpus/567d92192436cfcaa2917f878286e07f7e24621154f2500f23460b24d342d575 b/pythonfuzz_corpus/567d92192436cfcaa2917f878286e07f7e24621154f2500f23460b24d342d575
new file mode 100644
index 0000000..9f4b10b
Binary files /dev/null and b/pythonfuzz_corpus/567d92192436cfcaa2917f878286e07f7e24621154f2500f23460b24d342d575 differ
diff --git a/pythonfuzz_corpus/56c134f8f2ee27c9838ba124993364d34717ab36e634088210934c2c1f2fba8f b/pythonfuzz_corpus/56c134f8f2ee27c9838ba124993364d34717ab36e634088210934c2c1f2fba8f
new file mode 100644
index 0000000..6c127d8
--- /dev/null
+++ b/pythonfuzz_corpus/56c134f8f2ee27c9838ba124993364d34717ab36e634088210934c2c1f2fba8f
@@ -0,0 +1 @@
+ifEifE{{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/589d53eb11ffc7d7e20157186b58a6e70004c85ee40baeb575aadf9e4b192eb0 b/pythonfuzz_corpus/589d53eb11ffc7d7e20157186b58a6e70004c85ee40baeb575aadf9e4b192eb0
new file mode 100644
index 0000000..edceb47
Binary files /dev/null and b/pythonfuzz_corpus/589d53eb11ffc7d7e20157186b58a6e70004c85ee40baeb575aadf9e4b192eb0 differ
diff --git a/pythonfuzz_corpus/5bb39a21b0ea22b2aded892209460ec332fdc5f5148ad61fda55131862e9fad4 b/pythonfuzz_corpus/5bb39a21b0ea22b2aded892209460ec332fdc5f5148ad61fda55131862e9fad4
new file mode 100644
index 0000000..42b60a5
--- /dev/null
+++ b/pythonfuzz_corpus/5bb39a21b0ea22b2aded892209460ec332fdc5f5148ad61fda55131862e9fad4
@@ -0,0 +1 @@
+è"{„Ëä
\ No newline at end of file
diff --git a/pythonfuzz_corpus/5f36da35e21cf0d3438628d1795f9039409c099181e553e5b7640446d0c8e9cb b/pythonfuzz_corpus/5f36da35e21cf0d3438628d1795f9039409c099181e553e5b7640446d0c8e9cb
new file mode 100644
index 0000000..1084d1b
--- /dev/null
+++ b/pythonfuzz_corpus/5f36da35e21cf0d3438628d1795f9039409c099181e553e5b7640446d0c8e9cb
@@ -0,0 +1 @@
+‹='\+9ê#
\ No newline at end of file
diff --git a/pythonfuzz_corpus/617886cd689f4db27cd6d6ea060c5d36af9013d7e7d4526c1ad16204100081e2 b/pythonfuzz_corpus/617886cd689f4db27cd6d6ea060c5d36af9013d7e7d4526c1ad16204100081e2
new file mode 100644
index 0000000..8a18913
--- /dev/null
+++ b/pythonfuzz_corpus/617886cd689f4db27cd6d6ea060c5d36af9013d7e7d4526c1ad16204100081e2
@@ -0,0 +1 @@
+-bÿÿ-
\ No newline at end of file
diff --git a/pythonfuzz_corpus/6cfb531030d981a2d37ba5c407b95d57463b31b692f718e576ac4297a6a93941 b/pythonfuzz_corpus/6cfb531030d981a2d37ba5c407b95d57463b31b692f718e576ac4297a6a93941
new file mode 100644
index 0000000..f02c86f
Binary files /dev/null and b/pythonfuzz_corpus/6cfb531030d981a2d37ba5c407b95d57463b31b692f718e576ac4297a6a93941 differ
diff --git a/pythonfuzz_corpus/6f473c7d142523c557135748c6fa2fd9470b744b76b28713b8ff5169a4871d00 b/pythonfuzz_corpus/6f473c7d142523c557135748c6fa2fd9470b744b76b28713b8ff5169a4871d00
new file mode 100644
index 0000000..450a6f5
Binary files /dev/null and b/pythonfuzz_corpus/6f473c7d142523c557135748c6fa2fd9470b744b76b28713b8ff5169a4871d00 differ
diff --git a/pythonfuzz_corpus/70321dacff04bb342a9c3827833ccb9733befa062d8c385af88ad82155d65001 b/pythonfuzz_corpus/70321dacff04bb342a9c3827833ccb9733befa062d8c385af88ad82155d65001
new file mode 100644
index 0000000..2031ec7
--- /dev/null
+++ b/pythonfuzz_corpus/70321dacff04bb342a9c3827833ccb9733befa062d8c385af88ad82155d65001
@@ -0,0 +1 @@
+s='\U9';
\ No newline at end of file
diff --git a/pythonfuzz_corpus/772d440d09b6b8cabb43545ab1526b1d6606e0a4a8c023034179b99a4d16e8f4 b/pythonfuzz_corpus/772d440d09b6b8cabb43545ab1526b1d6606e0a4a8c023034179b99a4d16e8f4
new file mode 100644
index 0000000..a339f29
--- /dev/null
+++ b/pythonfuzz_corpus/772d440d09b6b8cabb43545ab1526b1d6606e0a4a8c023034179b99a4d16e8f4
@@ -0,0 +1 @@
+8=ç«
\ No newline at end of file
diff --git a/pythonfuzz_corpus/780e95d86a10a2839bf405fdc0f907f09412fa0955dbefef93f8970191aee98f b/pythonfuzz_corpus/780e95d86a10a2839bf405fdc0f907f09412fa0955dbefef93f8970191aee98f
new file mode 100644
index 0000000..f56145f
--- /dev/null
+++ b/pythonfuzz_corpus/780e95d86a10a2839bf405fdc0f907f09412fa0955dbefef93f8970191aee98f
@@ -0,0 +1 @@
+'=7s9'.e+ ' 7+9'.e;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/782c8edef27e6f3c29e566760e8fa74c86e595fb4177dfed07ad8de8f25766df b/pythonfuzz_corpus/782c8edef27e6f3c29e566760e8fa74c86e595fb4177dfed07ad8de8f25766df
new file mode 100644
index 0000000..17d6eae
--- /dev/null
+++ b/pythonfuzz_corpus/782c8edef27e6f3c29e566760e8fa74c86e595fb4177dfed07ad8de8f25766df
@@ -0,0 +1 @@
+if"{"{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/786b6ce06e463b7ad348e9bb1adc4c0602f23ebf37f76db946b5637c791d968f b/pythonfuzz_corpus/786b6ce06e463b7ad348e9bb1adc4c0602f23ebf37f76db946b5637c791d968f
new file mode 100644
index 0000000..19700fc
Binary files /dev/null and b/pythonfuzz_corpus/786b6ce06e463b7ad348e9bb1adc4c0602f23ebf37f76db946b5637c791d968f differ
diff --git a/pythonfuzz_corpus/78738a134136e9732da155d88915bdd127fd0789096dd60de109e4e0e617a7ea b/pythonfuzz_corpus/78738a134136e9732da155d88915bdd127fd0789096dd60de109e4e0e617a7ea
new file mode 100644
index 0000000..b1234d2
Binary files /dev/null and b/pythonfuzz_corpus/78738a134136e9732da155d88915bdd127fd0789096dd60de109e4e0e617a7ea differ
diff --git a/pythonfuzz_corpus/79763cdd61f488d90b6573d4856c6eb17a74abda6e8670ed2a8257c356b62b00 b/pythonfuzz_corpus/79763cdd61f488d90b6573d4856c6eb17a74abda6e8670ed2a8257c356b62b00
new file mode 100644
index 0000000..c750b16
--- /dev/null
+++ b/pythonfuzz_corpus/79763cdd61f488d90b6573d4856c6eb17a74abda6e8670ed2a8257c356b62b00
@@ -0,0 +1 @@
+s=s22;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/7a622ba5fc130b4f9336f0ca36cd881156441fc68c9854718dbc32a0b6fa2022 b/pythonfuzz_corpus/7a622ba5fc130b4f9336f0ca36cd881156441fc68c9854718dbc32a0b6fa2022
new file mode 100644
index 0000000..bf16e15
--- /dev/null
+++ b/pythonfuzz_corpus/7a622ba5fc130b4f9336f0ca36cd881156441fc68c9854718dbc32a0b6fa2022
@@ -0,0 +1 @@
+s=+sè
\ No newline at end of file
diff --git a/pythonfuzz_corpus/81357d3c3feb4212baecfd78c4ecc0d972165dc848117286a783930305199092 b/pythonfuzz_corpus/81357d3c3feb4212baecfd78c4ecc0d972165dc848117286a783930305199092
new file mode 100644
index 0000000..bcda068
--- /dev/null
+++ b/pythonfuzz_corpus/81357d3c3feb4212baecfd78c4ecc0d972165dc848117286a783930305199092
@@ -0,0 +1 @@
+' 7s9'.e+=' 7+9'.e;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/822a9b1a511012385d2cce061ee6aba9fc124bc5d622e09bdfc414f1801d17f8 b/pythonfuzz_corpus/822a9b1a511012385d2cce061ee6aba9fc124bc5d622e09bdfc414f1801d17f8
new file mode 100644
index 0000000..be28ff0
Binary files /dev/null and b/pythonfuzz_corpus/822a9b1a511012385d2cce061ee6aba9fc124bc5d622e09bdfc414f1801d17f8 differ
diff --git a/pythonfuzz_corpus/868560ef019a87dfc8a9fe9944bd0ba03e85bf869855c8894878f28936b72f2f b/pythonfuzz_corpus/868560ef019a87dfc8a9fe9944bd0ba03e85bf869855c8894878f28936b72f2f
new file mode 100644
index 0000000..9fc66ad
--- /dev/null
+++ b/pythonfuzz_corpus/868560ef019a87dfc8a9fe9944bd0ba03e85bf869855c8894878f28936b72f2f
@@ -0,0 +1 @@
+¥òk¨“s;_s;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/8b7292d2bafc5e307d280b575a7b1a6947350c94960c7640ef14b297cfddd18f b/pythonfuzz_corpus/8b7292d2bafc5e307d280b575a7b1a6947350c94960c7640ef14b297cfddd18f
new file mode 100644
index 0000000..56157fc
--- /dev/null
+++ b/pythonfuzz_corpus/8b7292d2bafc5e307d280b575a7b1a6947350c94960c7640ef14b297cfddd18f
@@ -0,0 +1 @@
+c=+´s999=
\ No newline at end of file
diff --git a/pythonfuzz_corpus/8fbce986c5bd36862d25461d1a9f7f05fa04a6670ce31fb4c8fb63ed4bb3a314 b/pythonfuzz_corpus/8fbce986c5bd36862d25461d1a9f7f05fa04a6670ce31fb4c8fb63ed4bb3a314
new file mode 100644
index 0000000..afedd13
Binary files /dev/null and b/pythonfuzz_corpus/8fbce986c5bd36862d25461d1a9f7f05fa04a6670ce31fb4c8fb63ed4bb3a314 differ
diff --git a/pythonfuzz_corpus/903c00ec6b29cb82a5516f06f4e331c301e1bcdef49495b0b6d849b328a1902f b/pythonfuzz_corpus/903c00ec6b29cb82a5516f06f4e331c301e1bcdef49495b0b6d849b328a1902f
new file mode 100644
index 0000000..8867d69
--- /dev/null
+++ b/pythonfuzz_corpus/903c00ec6b29cb82a5516f06f4e331c301e1bcdef49495b0b6d849b328a1902f
@@ -0,0 +1 @@
+s=s+s99;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/906e4633e27c13bba3a718bd268c8fa3d67a5ee4e1d6131c87431c73872bc7c6 b/pythonfuzz_corpus/906e4633e27c13bba3a718bd268c8fa3d67a5ee4e1d6131c87431c73872bc7c6
new file mode 100644
index 0000000..e7c9368
Binary files /dev/null and b/pythonfuzz_corpus/906e4633e27c13bba3a718bd268c8fa3d67a5ee4e1d6131c87431c73872bc7c6 differ
diff --git a/pythonfuzz_corpus/95a2a980176e3c64f2b48716dae1370ef5020a0b40a1469b7a1151ac62f90e5c b/pythonfuzz_corpus/95a2a980176e3c64f2b48716dae1370ef5020a0b40a1469b7a1151ac62f90e5c
new file mode 100644
index 0000000..86a814d
--- /dev/null
+++ b/pythonfuzz_corpus/95a2a980176e3c64f2b48716dae1370ef5020a0b40a1469b7a1151ac62f90e5c
@@ -0,0 +1 @@
+è"{È×{
\ No newline at end of file
diff --git a/pythonfuzz_corpus/985eb10ba65c148f9b6d9a76c18bc03b5604dc94b303e1ba6017e7619e31f923 b/pythonfuzz_corpus/985eb10ba65c148f9b6d9a76c18bc03b5604dc94b303e1ba6017e7619e31f923
new file mode 100644
index 0000000..ed12a12
Binary files /dev/null and b/pythonfuzz_corpus/985eb10ba65c148f9b6d9a76c18bc03b5604dc94b303e1ba6017e7619e31f923 differ
diff --git a/pythonfuzz_corpus/9ae834f8673d039566070231bd208fe9050c9f5c0e47294fa8066fdae4ea015c b/pythonfuzz_corpus/9ae834f8673d039566070231bd208fe9050c9f5c0e47294fa8066fdae4ea015c
new file mode 100644
index 0000000..9588bd9
Binary files /dev/null and b/pythonfuzz_corpus/9ae834f8673d039566070231bd208fe9050c9f5c0e47294fa8066fdae4ea015c differ
diff --git a/pythonfuzz_corpus/9d097ce487c91f8e8f74a987950c4aac5f4bffa25212deb54b1c9c354b2f6a33 b/pythonfuzz_corpus/9d097ce487c91f8e8f74a987950c4aac5f4bffa25212deb54b1c9c354b2f6a33
new file mode 100644
index 0000000..2be77a4
Binary files /dev/null and b/pythonfuzz_corpus/9d097ce487c91f8e8f74a987950c4aac5f4bffa25212deb54b1c9c354b2f6a33 differ
diff --git a/pythonfuzz_corpus/9d465d4d13c80997d5a44c880278fdfaae25f36eb0fcb925b277984d1f1fb62c b/pythonfuzz_corpus/9d465d4d13c80997d5a44c880278fdfaae25f36eb0fcb925b277984d1f1fb62c
new file mode 100644
index 0000000..caaf9c5
--- /dev/null
+++ b/pythonfuzz_corpus/9d465d4d13c80997d5a44c880278fdfaae25f36eb0fcb925b277984d1f1fb62c
@@ -0,0 +1 @@
+if{E;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/9e47ec4fcb9c52b29c52cd74ecbe5e52fc4b8214abe0726999499ee4077f1f88 b/pythonfuzz_corpus/9e47ec4fcb9c52b29c52cd74ecbe5e52fc4b8214abe0726999499ee4077f1f88
new file mode 100644
index 0000000..76e6fef
--- /dev/null
+++ b/pythonfuzz_corpus/9e47ec4fcb9c52b29c52cd74ecbe5e52fc4b8214abe0726999499ee4077f1f88
@@ -0,0 +1 @@
+s.sswÿÿ=j2ýœ,¶ÕÔC99;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/a03f0b3afa4de56b52f38e95e1e6803da114c260dda011c6ea3ac5c0ef32dc80 b/pythonfuzz_corpus/a03f0b3afa4de56b52f38e95e1e6803da114c260dda011c6ea3ac5c0ef32dc80
new file mode 100644
index 0000000..097d3e2
Binary files /dev/null and b/pythonfuzz_corpus/a03f0b3afa4de56b52f38e95e1e6803da114c260dda011c6ea3ac5c0ef32dc80 differ
diff --git a/pythonfuzz_corpus/a663b9c619dde700de95276254b0c8f16e97e10f7fe0816a519ea782db184bf6 b/pythonfuzz_corpus/a663b9c619dde700de95276254b0c8f16e97e10f7fe0816a519ea782db184bf6
new file mode 100644
index 0000000..b10d392
--- /dev/null
+++ b/pythonfuzz_corpus/a663b9c619dde700de95276254b0c8f16e97e10f7fe0816a519ea782db184bf6
@@ -0,0 +1 @@
+' 7s9'.e/=' 7+6'.e;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/a75d509353e96672050108a3e95fae72ec279b7df7718ecb7ca8b0f73832c358 b/pythonfuzz_corpus/a75d509353e96672050108a3e95fae72ec279b7df7718ecb7ca8b0f73832c358
new file mode 100644
index 0000000..b3a8892
--- /dev/null
+++ b/pythonfuzz_corpus/a75d509353e96672050108a3e95fae72ec279b7df7718ecb7ca8b0f73832c358
@@ -0,0 +1 @@
+s=s+2;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/ad319997db794dcaad196e2389986b2e212a3f0c054167d7c151eb174e253f71 b/pythonfuzz_corpus/ad319997db794dcaad196e2389986b2e212a3f0c054167d7c151eb174e253f71
new file mode 100644
index 0000000..a1b3a9f
Binary files /dev/null and b/pythonfuzz_corpus/ad319997db794dcaad196e2389986b2e212a3f0c054167d7c151eb174e253f71 differ
diff --git a/pythonfuzz_corpus/ad528fc01081dcba7934b9b0fe56ea8ba681c0b9d30082ccd3050595b3abe393 b/pythonfuzz_corpus/ad528fc01081dcba7934b9b0fe56ea8ba681c0b9d30082ccd3050595b3abe393
new file mode 100644
index 0000000..58cd3d6
--- /dev/null
+++ b/pythonfuzz_corpus/ad528fc01081dcba7934b9b0fe56ea8ba681c0b9d30082ccd3050595b3abe393
@@ -0,0 +1 @@
+if+7ÿÿ
\ No newline at end of file
diff --git a/pythonfuzz_corpus/af77aedd08e748a4ff1be82b172ace743aaf367501dd47ec0d458013f8613a5a b/pythonfuzz_corpus/af77aedd08e748a4ff1be82b172ace743aaf367501dd47ec0d458013f8613a5a
new file mode 100644
index 0000000..20011f1
--- /dev/null
+++ b/pythonfuzz_corpus/af77aedd08e748a4ff1be82b172ace743aaf367501dd47ec0d458013f8613a5a
@@ -0,0 +1 @@
+Uý7&s.99;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/b012b869b6cb37904a1d2b1f4a109593c43631407206e885a453093cca279637 b/pythonfuzz_corpus/b012b869b6cb37904a1d2b1f4a109593c43631407206e885a453093cca279637
new file mode 100644
index 0000000..0717004
--- /dev/null
+++ b/pythonfuzz_corpus/b012b869b6cb37904a1d2b1f4a109593c43631407206e885a453093cca279637
@@ -0,0 +1 @@
+Û´Ü_
\ No newline at end of file
diff --git a/pythonfuzz_corpus/b5c2f3ae67451e238f049371c7504fb0e485265f869b6975d08042ff7c82801f b/pythonfuzz_corpus/b5c2f3ae67451e238f049371c7504fb0e485265f869b6975d08042ff7c82801f
new file mode 100644
index 0000000..db6de50
--- /dev/null
+++ b/pythonfuzz_corpus/b5c2f3ae67451e238f049371c7504fb0e485265f869b6975d08042ff7c82801f
@@ -0,0 +1 @@
+ss+=s+92;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/b5da8b675da89172837134ee8565ba818fb6a37744be63419e9ad46a79b2d0fd b/pythonfuzz_corpus/b5da8b675da89172837134ee8565ba818fb6a37744be63419e9ad46a79b2d0fd
new file mode 100644
index 0000000..2ec48dc
Binary files /dev/null and b/pythonfuzz_corpus/b5da8b675da89172837134ee8565ba818fb6a37744be63419e9ad46a79b2d0fd differ
diff --git a/pythonfuzz_corpus/b5dae346eba2b3034d5439e6f971545a066b418c5715cad155d4db93d6a60337 b/pythonfuzz_corpus/b5dae346eba2b3034d5439e6f971545a066b418c5715cad155d4db93d6a60337
new file mode 100644
index 0000000..9374c9f
Binary files /dev/null and b/pythonfuzz_corpus/b5dae346eba2b3034d5439e6f971545a066b418c5715cad155d4db93d6a60337 differ
diff --git a/pythonfuzz_corpus/b6d3123c31ba37d30bec59ddb22d73b12568f23580deae15797d21c330eba26e b/pythonfuzz_corpus/b6d3123c31ba37d30bec59ddb22d73b12568f23580deae15797d21c330eba26e
new file mode 100644
index 0000000..fdd7f81
--- /dev/null
+++ b/pythonfuzz_corpus/b6d3123c31ba37d30bec59ddb22d73b12568f23580deae15797d21c330eba26e
@@ -0,0 +1 @@
+ifÍó+›{}
\ No newline at end of file
diff --git a/pythonfuzz_corpus/be8c64be404507b0cd644ccb63c64b764943c1e7d377594dd280357dd4f677cc b/pythonfuzz_corpus/be8c64be404507b0cd644ccb63c64b764943c1e7d377594dd280357dd4f677cc
new file mode 100644
index 0000000..2dc52a5
--- /dev/null
+++ b/pythonfuzz_corpus/be8c64be404507b0cd644ccb63c64b764943c1e7d377594dd280357dd4f677cc
@@ -0,0 +1 @@
+[b-K,]-
\ No newline at end of file
diff --git a/pythonfuzz_corpus/c0cfa5d71c611dcbabbde3a67e12e2b9796406466b75fa5c8657de31ac7833b4 b/pythonfuzz_corpus/c0cfa5d71c611dcbabbde3a67e12e2b9796406466b75fa5c8657de31ac7833b4
new file mode 100644
index 0000000..9be4387
Binary files /dev/null and b/pythonfuzz_corpus/c0cfa5d71c611dcbabbde3a67e12e2b9796406466b75fa5c8657de31ac7833b4 differ
diff --git a/pythonfuzz_corpus/c1dab8c713ae68fff4d88d6d3b25a5138a8bdc66f8141b6687c10835a0f632e8 b/pythonfuzz_corpus/c1dab8c713ae68fff4d88d6d3b25a5138a8bdc66f8141b6687c10835a0f632e8
new file mode 100644
index 0000000..77b5136
Binary files /dev/null and b/pythonfuzz_corpus/c1dab8c713ae68fff4d88d6d3b25a5138a8bdc66f8141b6687c10835a0f632e8 differ
diff --git a/pythonfuzz_corpus/c2b0036c7463bd3ccae33eb520827dae0fbae737f30f1d14fe2e4102052a8dbc b/pythonfuzz_corpus/c2b0036c7463bd3ccae33eb520827dae0fbae737f30f1d14fe2e4102052a8dbc
new file mode 100644
index 0000000..934c23f
Binary files /dev/null and b/pythonfuzz_corpus/c2b0036c7463bd3ccae33eb520827dae0fbae737f30f1d14fe2e4102052a8dbc differ
diff --git a/pythonfuzz_corpus/c332cb8fc69acb70e1c25b4b024ac6917053b865a19e9e0b42f59dbcafe2d0d5 b/pythonfuzz_corpus/c332cb8fc69acb70e1c25b4b024ac6917053b865a19e9e0b42f59dbcafe2d0d5
new file mode 100644
index 0000000..aa60571
--- /dev/null
+++ b/pythonfuzz_corpus/c332cb8fc69acb70e1c25b4b024ac6917053b865a19e9e0b42f59dbcafe2d0d5
@@ -0,0 +1 @@
+s=' 7+9'.e;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/c6c2d61998d552d8b532092205466a53dfac1bad2d57e93c98966480fe4de7e3 b/pythonfuzz_corpus/c6c2d61998d552d8b532092205466a53dfac1bad2d57e93c98966480fe4de7e3
new file mode 100644
index 0000000..ee70b40
--- /dev/null
+++ b/pythonfuzz_corpus/c6c2d61998d552d8b532092205466a53dfac1bad2d57e93c98966480fe4de7e3
@@ -0,0 +1 @@
+f**fb*_
\ No newline at end of file
diff --git a/pythonfuzz_corpus/cb1ad5651d22e4ead37b8a1610536515847481d752d8330c2dfb447f60579eef b/pythonfuzz_corpus/cb1ad5651d22e4ead37b8a1610536515847481d752d8330c2dfb447f60579eef
new file mode 100644
index 0000000..9fa64c5
--- /dev/null
+++ b/pythonfuzz_corpus/cb1ad5651d22e4ead37b8a1610536515847481d752d8330c2dfb447f60579eef
@@ -0,0 +1 @@
+-8K[
\ No newline at end of file
diff --git a/pythonfuzz_corpus/cc43ed131cbd2dc1aa1a9c3d501efdcbb3837fd28805b39c33858379d11cf515 b/pythonfuzz_corpus/cc43ed131cbd2dc1aa1a9c3d501efdcbb3837fd28805b39c33858379d11cf515
new file mode 100644
index 0000000..194b960
Binary files /dev/null and b/pythonfuzz_corpus/cc43ed131cbd2dc1aa1a9c3d501efdcbb3837fd28805b39c33858379d11cf515 differ
diff --git a/pythonfuzz_corpus/cc568b2c439d164eba26f0657ee0ae3e35de3b95f0fd69716a800dfb1043d5a6 b/pythonfuzz_corpus/cc568b2c439d164eba26f0657ee0ae3e35de3b95f0fd69716a800dfb1043d5a6
new file mode 100644
index 0000000..a28564f
--- /dev/null
+++ b/pythonfuzz_corpus/cc568b2c439d164eba26f0657ee0ae3e35de3b95f0fd69716a800dfb1043d5a6
@@ -0,0 +1 @@
+(l=ÿ();
\ No newline at end of file
diff --git a/pythonfuzz_corpus/cf5b2953b0d4f2d71c56535ca1fc3653449f4780bf06a2ef36f9817267faf6a7 b/pythonfuzz_corpus/cf5b2953b0d4f2d71c56535ca1fc3653449f4780bf06a2ef36f9817267faf6a7
new file mode 100644
index 0000000..6d7d10a
--- /dev/null
+++ b/pythonfuzz_corpus/cf5b2953b0d4f2d71c56535ca1fc3653449f4780bf06a2ef36f9817267faf6a7
@@ -0,0 +1 @@
+s=sS++29;
\ No newline at end of file
diff --git a/pythonfuzz_corpus/d2b0bae5672ed2d7fbddb50db6b8e1c1cb3dff18bcd8da557b2f82b989c26246 b/pythonfuzz_corpus/d2b0bae5672ed2d7fbddb50db6b8e1c1cb3dff18bcd8da557b2f82b989c26246
new file mode 100644
index 0000000..946e7a6
Binary files /dev/null and b/pythonfuzz_corpus/d2b0bae5672ed2d7fbddb50db6b8e1c1cb3dff18bcd8da557b2f82b989c26246 differ
diff --git a/pythonfuzz_corpus/d2d45c96b7dbee464caf75e8276078f2ee9090452343d3621c5f5b3c915ecbb4 b/pythonfuzz_corpus/d2d45c96b7dbee464caf75e8276078f2ee9090452343d3621c5f5b3c915ecbb4
new file mode 100644
index 0000000..5e825d4
Binary files /dev/null and b/pythonfuzz_corpus/d2d45c96b7dbee464caf75e8276078f2ee9090452343d3621c5f5b3c915ecbb4 differ
diff --git a/pythonfuzz_corpus/d328184f5203d8ca87fd33a0dd3d48ff7afec357d5eaf36377e74a68bf3cb342 b/pythonfuzz_corpus/d328184f5203d8ca87fd33a0dd3d48ff7afec357d5eaf36377e74a68bf3cb342
new file mode 100644
index 0000000..a653313
--- /dev/null
+++ b/pythonfuzz_corpus/d328184f5203d8ca87fd33a0dd3d48ff7afec357d5eaf36377e74a68bf3cb342
@@ -0,0 +1 @@
+sŒžGžG
\ No newline at end of file
diff --git a/pythonfuzz_corpus/d35899fceef0e659ce23019b3db6bed25c793dbb086e9a3b9ec92298be497648 b/pythonfuzz_corpus/d35899fceef0e659ce23019b3db6bed25c793dbb086e9a3b9ec92298be497648
new file mode 100644
index 0000000..664c1c7
--- /dev/null
+++ b/pythonfuzz_corpus/d35899fceef0e659ce23019b3db6bed25c793dbb086e9a3b9ec92298be497648
@@ -0,0 +1 @@
+s=' +9'' +9';
\ No newline at end of file
diff --git a/pythonfuzz_corpus/d442ba3019d57c79ab251cfa74d1fa854874dcd380330cca2d276a1421fc319d b/pythonfuzz_corpus/d442ba3019d57c79ab251cfa74d1fa854874dcd380330cca2d276a1421fc319d
new file mode 100644
index 0000000..793cd32
--- /dev/null
+++ b/pythonfuzz_corpus/d442ba3019d57c79ab251cfa74d1fa854874dcd380330cca2d276a1421fc319d
@@ -0,0 +1 @@
+ssP>T¤áj
\ No newline at end of file
diff --git a/pythonfuzz_corpus/fd6653958e4bdaf4342259781114dbb76695990ee393d4ed52e0a67d25d4ff6c b/pythonfuzz_corpus/fd6653958e4bdaf4342259781114dbb76695990ee393d4ed52e0a67d25d4ff6c
new file mode 100644
index 0000000..81a65d9
Binary files /dev/null and b/pythonfuzz_corpus/fd6653958e4bdaf4342259781114dbb76695990ee393d4ed52e0a67d25d4ff6c differ
diff --git a/pythonfuzz_corpus/ff389c78072966b338cd686ad27dab02007c09d83cd855296f3879c3f4ae8f7d b/pythonfuzz_corpus/ff389c78072966b338cd686ad27dab02007c09d83cd855296f3879c3f4ae8f7d
new file mode 100644
index 0000000..4299535
Binary files /dev/null and b/pythonfuzz_corpus/ff389c78072966b338cd686ad27dab02007c09d83cd855296f3879c3f4ae8f7d differ
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 9190a83..896f217 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,2 +1,7 @@
+-r requirements.txt
+
+# For `if TYPE_CHECKING` stuff
+typing-extensions~=4.4; python_version < "3.13"
+
--extra-index-url https://gitlab.com/api/v4/projects/19904939/packages/pypi/simple
pythonfuzz>=1.0.11
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..4ae5e3a
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+typing-extensions~=4.1; python_version < "3.11"
diff --git a/benchmark.py b/scripts/benchmark.py
similarity index 87%
rename from benchmark.py
rename to scripts/benchmark.py
index 460c717..2c8fa8a 100644
--- a/benchmark.py
+++ b/scripts/benchmark.py
@@ -2,17 +2,18 @@
import contextlib
import time
-from parser.astgen.ast_node import AstProgramNode
+from parser.astgen.ast_nodes import AstProgramNode
from parser.astgen.astgen import AstGen
from parser.common.tree_print import tformat
from parser.cst.nodes import ProgramNode
from parser.cst.cstgen import CstGen
from parser.lexer import Tokenizer, format_tokens
-from parser.typecheck.typecheck import NameResolver, Scope
+from parser.typecheck.name_resolver import NameResolver
+from parser.typecheck.scope import Scope
from util import readfile
from util.pformat import pformat
-PROFILER = True
+PROFILER = False
class _Timer:
@@ -69,7 +70,7 @@ def run(self):
self.do_name_resolve()
self.do_name_resolve_fmt()
if p:
- p.dump_stats(f'perf_dump_{self.idx}.prof')
+ p.dump_stats(f'./_exclude/prof/perf_dump_{self.idx}.prof')
print(f'Perf for idx={self.idx} ({PROFILER=}):')
for _k, s in sorted(self.lines):
print(f' {s}')
@@ -132,20 +133,20 @@ def bench_full(n=200):
for _ in range(n):
t0 = time.perf_counter()
_sc = NameResolver(AstGen(CstGen(Tokenizer(
- readfile('main_example_2.st'))))).run()
+ readfile('./examples/main_example_2.st'))))).run()
t1 = time.perf_counter()
times.append(t1 - t0)
if p:
- p.dump_stats('./long_perf.prof')
+ p.dump_stats('./_exclude/prof/bench_full.prof')
print(f'Bench main_example_2.st, {n} iterations, ({PROFILER=}):')
print(f' Min: {min(times)*1000:.2f}ms')
print(f' Avg: {sum(times)/n*1000:.2f}ms')
def main():
- benchmark(readfile('main_example_0.st'), 0, do_ast=False)
- benchmark(readfile('main_example_1.st'), 1, do_name_resolve=False)
- benchmark(readfile('main_example_2.st'), 2)
+ benchmark(readfile('./examples/main_example_0.st'), 0, do_ast=False)
+ benchmark(readfile('./examples/main_example_1.st'), 1, do_name_resolve=False)
+ benchmark(readfile('./examples/main_example_2.st'), 2)
bench_full(200)
diff --git a/scripts/detect_unused.sh b/scripts/detect_unused.sh
new file mode 100755
index 0000000..749b750
--- /dev/null
+++ b/scripts/detect_unused.sh
@@ -0,0 +1 @@
+vulture ./parser ./scripts/fuzz.py ./scripts/benchmark.py ./test --ignore-decorators="@_register_autowalk_expr*" --exclude="parser/astgen/ast_print.py"
diff --git a/scripts/fuzz.py b/scripts/fuzz.py
new file mode 100644
index 0000000..342cebe
--- /dev/null
+++ b/scripts/fuzz.py
@@ -0,0 +1,101 @@
+import random
+import string
+import time
+
+from parser.astgen.ast_node import AstNode
+from parser.astgen.astgen import AstGen
+from parser.astgen.filtered_walker import FilteredWalker
+from parser.lexer.tokenizer import Tokenizer
+from parser.cst.cstgen import CstGen
+from parser.common.error import BaseParseError
+from parser.typecheck.typecheck import Typechecker
+from parser.typecheck.name_resolver import NameResolver
+from parser.typecheck.types import TypeMetadata
+
+from pythonfuzz.fuzzer import Fuzzer
+import pythonfuzz.fuzzer as fuzzer_ns # For patching pythonfuzz
+
+VERSION = 2
+
+
+class UsePerfCounterInsteadOfTime:
+ """Hack to avoid overwriting everyone's time module so we only
+ overwrite `pythonfuzz`'s time module and don't modify the module itself.
+ This hack is necessary because time.time() is rather inaccurate so
+ it is possible that between 2 iterations, the difference in time.time() is 0
+ which results in DivisionByZeroError (when calculating iterations/sec).
+ Therefore, we replace with the more accurate time.perf_counter(),
+ just for `pythonfuzz`"""
+ def __getattr__(self, item):
+ if item == 'time': # time.time
+ item = 'perf_counter'
+ return getattr(time, item)
+
+
+fuzzer_ns.time = UsePerfCounterInsteadOfTime()
+
+
+def assert_all_metadata(n: AstNode):
+ def on_exit_node(nd: AstNode):
+ assert isinstance(nd.meta, TypeMetadata)
+
+ # Report error with deepest one so on_exit
+ FilteredWalker().register_exit(AstNode, on_exit_node).walk(n)
+ return n
+
+
+def fuzz_advanced(buf: bytes):
+ # TODO There are massive biases due to Pythonfuzz's compulsion to give us
+ # specific byte values a lot more (stuff like FF, 00, 7F, 80)
+ important = [
+ 'let', 'for', 'while', 'if', 'else', 'global', *'+-*/%=<>!&|', 'def',
+ 'repeat', ';', 'val', 'number', 'string', 'bool', *'[](){}', "'", '"',
+ '\\', '.', *(' ' * 30) # same weight of spaces as other stuff approx
+ ]
+ other = [*string.printable]
+ sample_from = important * 5 + other
+ parts = []
+ rng = random.Random()
+ for i, byte in enumerate(buf):
+ rng.seed(buf + b'\0' + bytes(byte) + b'\0'
+ + i.to_bytes(length=i.bit_count() // 8 + 1, byteorder='big'))
+ parts.append(rng.choice(sample_from))
+ s = ''.join(parts)
+ target(s)
+
+
+def fuzz(buf: bytes):
+ if VERSION == 2:
+ if not buf:
+ return
+ flag, *buf = buf
+ if flag.bit_count(): # Parity rather than MSB check for less bias?
+ return fuzz_advanced(bytes(buf))
+ buf = bytes(map(0x7F.__and__, buf)) # wdym you don't understand
+ try:
+ s = buf.decode("ascii")
+ except UnicodeDecodeError:
+ return # Shouldn't happen though will catch anyway
+ target(s)
+
+
+def target(s: str):
+ try:
+ n = Typechecker(NameResolver(AstGen(CstGen(Tokenizer(s))))).run()
+ except BaseParseError:
+ return
+ assert_all_metadata(n)
+
+
+if __name__ == '__main__':
+ import argparse
+ ap = argparse.ArgumentParser("fuzz.py", description="Runs a fuzzer for n iterations")
+ # Use type=float as gh mobile cannot specify integers as workflow args
+ ap.add_argument('-n', '--iterations', default=-1,
+ type=float, help="Number of iterations to run pythonfuzz for")
+ ap.add_argument('-i', '--infinite',
+ action='store_const', const=-1, dest='iterations')
+ args = ap.parse_args()
+
+ fuzzer = Fuzzer(fuzz, dirs=['./pythonfuzz_corpus'], timeout=30, runs=int(args.iterations))
+ fuzzer.start()
diff --git a/run_tests.sh b/scripts/run_tests.sh
old mode 100644
new mode 100755
similarity index 100%
rename from run_tests.sh
rename to scripts/run_tests.sh
diff --git a/run_tests_coverage.sh b/scripts/run_tests_coverage.sh
old mode 100644
new mode 100755
similarity index 100%
rename from run_tests_coverage.sh
rename to scripts/run_tests_coverage.sh
diff --git a/run_tests_update.sh b/scripts/run_tests_update.sh
old mode 100644
new mode 100755
similarity index 100%
rename from run_tests_update.sh
rename to scripts/run_tests_update.sh
diff --git a/test/common/common.py b/test/common/common.py
index 57bcd05..e165f99 100644
--- a/test/common/common.py
+++ b/test/common/common.py
@@ -2,22 +2,29 @@
used in all projects should go in utils.py"""
from __future__ import annotations
+import contextlib
from enum import IntFlag, Enum
-from typing import Sequence, TypeVar
+from typing import Sequence, TypeVar, Any
from parser.astgen.ast_node import AstNode
from parser.astgen.astgen import AstGen
from parser.astgen.errors import LocatedAstError
+from parser.astgen.filtered_walker import FilteredWalker
+from parser.common import BaseLocatedError
from parser.common.error import BaseParseError
+from parser.common.str_region import StrRegion
from parser.common.tree_print import tformat
from parser.cst.base_node import Leaf, AnyNode, Node
from parser.cst.cstgen import CstGen, LocatedCstError
from parser.lexer import Tokenizer
from parser.lexer.tokens import Token, OpToken
-from parser.typecheck.typecheck import Scope, NameResolver, NameResolutionError
-from test.common.snapshottest import SnapshotTestCase
-from test.common.utils import TestCaseUtils
+from parser.typecheck.name_resolver import NameResolutionError, NameResolver
+from parser.typecheck.scope import Scope
+from parser.typecheck.typecheck import Typechecker, TypecheckError
+from parser.typecheck.types import TypeInfo, TypeMetadata
from util.pformat import pformat
+from .snapshottest import SnapshotTestCase
+from .utils import TestCaseUtils
def _strict_boundary_kwargs():
@@ -34,6 +41,7 @@ class TokenStreamFlag(IntFlag, **_strict_boundary_kwargs()):
BOTH = CONTENT | FULL
+T = TypeVar('T')
EnumTV = TypeVar('EnumTV', bound=Enum)
@@ -62,7 +70,7 @@ def setUpClass(cls) -> None:
def _token_as_tuple_no_region(cls, t: Token):
if isinstance(t, OpToken):
return t.name, t.op_str
- return (t.name, )
+ return (t.name,)
def assertTokenStreamEquals(
self, actual: Sequence[Token], expected: Sequence[Token],
@@ -101,6 +109,16 @@ def assertNotInternalErrorCST(self, src: str):
self.assertTrue(True)
self.assertTrue(True)
+ @classmethod
+ @contextlib.contextmanager
+ def raiseInternalErrorsOnly(cls):
+ try:
+ yield
+ except BaseParseError:
+ pass
+ except Exception:
+ raise
+
@classmethod
def raiseInternalErrorsOnlyCST(cls, src: str):
try:
@@ -129,11 +147,66 @@ def assertFailsGracefullyAST(self, src: str):
return ctx.exception
# noinspection PyMethodMayBeStatic
+ def getAstGen(self, src: str):
+ return AstGen(CstGen(Tokenizer(src)))
+
def getNameResolver(self, src: str):
- return NameResolver(AstGen(CstGen(Tokenizer(src))))
+ return NameResolver(self.getAstGen(src))
def assertNameResolveError(self, src: str):
nr = self.getNameResolver(src)
with self.assertRaises(NameResolutionError) as ctx:
nr.run()
return ctx.exception
+
+ def getTypechecker(self, src: str):
+ return Typechecker(self.getNameResolver(src))
+
+ def assertTypecheckedTo(self, node: AstNode[TypeMetadata] | None, expected: TypeInfo):
+ node = self.assertAsNotNone(node, "Expected a node with metadata, got None")
+ self.assertIsNotNone(node.meta, "Expected type metadata")
+ self.assertEqual(expected, node.meta.type)
+
+ def assertTypecheckError(self, src: str):
+ tc = self.getTypechecker(src)
+ with self.assertRaises(TypecheckError) as ctx:
+ tc.run()
+ return ctx.exception
+
+ @contextlib.contextmanager
+ def assertDoesntCrash(self):
+ try:
+ yield
+ except BaseParseError:
+ self.assertTrue(True)
+ except Exception:
+ raise # Let's be explicit
+ self.assertTrue(True)
+
+ def assertAllMetadata(self, n: AstNode[Any], expected_type: type[T]) -> AstNode[T]:
+ def on_exit_node(nd: AstNode[Any]):
+ if isinstance(nd, expected_type):
+ return
+ msg_extra = f"root={tformat(n)}\nnode={tformat(nd)}"
+ self.assertIsNotNone(
+ nd.meta, f"Expected node to have metadata:\n{msg_extra}")
+ self.assertIsInstance(
+ nd.meta, expected_type,
+ f"Bad metadata type for node:\n{msg_extra}")
+
+ # Report error with deepest one so on_exit
+ FilteredWalker().register_exit(AstNode, on_exit_node).walk(n)
+ return n
+
+ def assertRegionEquals(self, expected: StrRegion, actual: StrRegion, src: str | None):
+ if expected == actual:
+ return
+ # Newlines added so that != output by unittest looks reasonable
+ self.assertEqual(f'\n{expected.display(src)}\n',
+ f'\n{actual.display(src)}\n ',
+ "Expected regions to be equal (showing displayed)")
+ self.assertEqual(expected, actual, # Fallback in case display equal
+ "Expected regions to be equal (displayed as same)")
+
+ def assertErrorRegion(self, expected: StrRegion, err: BaseLocatedError):
+ self.assertRegionEquals(expected, err.region, err._src_text)
diff --git a/test/common/snapshottest.py b/test/common/snapshottest.py
index 5f66703..23be6ba 100644
--- a/test/common/snapshottest.py
+++ b/test/common/snapshottest.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import contextlib
import csv
import inspect
@@ -7,17 +9,28 @@
import unittest
from dataclasses import dataclass
from pathlib import Path
-from typing import IO
+from typing import IO, Literal, NewType, TYPE_CHECKING, cast
+
+if TYPE_CHECKING:
+ from typing import TypeIs
+
+
+class SnapshottestError(RuntimeError):
+ pass
# NOTE: This is copied from and should be kept up-to-date with
# https://github.com/MarcellPerger1/mini-snapshot/blob/main/mini_snapshot.py
-class SnapshotsNotFound(RuntimeError):
- ...
+class SnapshotsNotFound(SnapshottestError):
+ pass
+
+class CantUpdateSnapshots(SnapshottestError):
+ pass
-class CantUpdateSnapshots(RuntimeError):
- ...
+
+class UnusedSnapshot(SnapshottestError):
+ pass
def _string_is_number(s: str):
@@ -42,6 +55,10 @@ def _open_or_create_rw(path: str):
return open(path, 'w+', encoding='utf8') # Try to create if not exists
+def _environ_get_bool(name: str, default: bool):
+ return os.getenv(name, str(default)).lower() in ('1', 'true', 'yes')
+
+
_SNAPS_NOT_FOUND_MSG = (
'Snapshots not found, execute this with PY_SNAPSHOTTEST_UPDATE=1 to write \n'
'the following as the snapshot for {full_name}:\n'
@@ -52,17 +69,27 @@ def _open_or_create_rw(path: str):
'{value}'
)
+_SentinelT = NewType('_SentinelT', object)
+_DELETE_SENTINEL = _SentinelT(object())
+
+
+def _is_sentinel(o: object) -> TypeIs[_SentinelT]:
+ return o is _DELETE_SENTINEL
+
+# TODO: new unused detection needs testing!
class SnapshotTestCase(unittest.TestCase):
- snap_filename: str | None = None
- snaps_dir: Path | None = None
- snap_file: str | None = None
- cls_name: str | None = None
+ snap_filename: str = None
+ snaps_dir: Path = None
+ snap_file: str = None
+ cls_name: str = None
- update_snapshots: bool | None = None
+ update_snapshots: bool = None
+ unused_handling: Literal['ignore', 'error', 'print', 'prune'] | None = None
_files_cache: dict[str, dict[str, str]]
- _queued_changes: dict[str, dict[str, str]]
+ _queued_changes: dict[str, dict[str, str | _SentinelT]]
+ _referenced_snaps: dict[str, set[str]]
_subtest = None
format_dispatch = {}
@@ -100,12 +127,19 @@ def setUpClass(cls) -> None:
cls.cls_name = cls.cls_name or _safe_cls_name(cls)
cls._files_cache = {}
if cls.update_snapshots is None:
- cls.update_snapshots = os.environ.get(
- 'PY_SNAPSHOTTEST_UPDATE', '0').lower() in ('1', 'true', 'yes')
+ cls.update_snapshots = _environ_get_bool('PY_SNAPSHOTTEST_UPDATE', False)
+ if cls.unused_handling is None:
+ unused = os.getenv('PY_SNAPSHOTTEST_UNUSED', 'ignore').lower().strip()
+ if unused not in ('ignore', 'error', 'print', 'prune'):
+ print('WARN: unknown PY_SNAPSHOTTEST_UNUSED, assuming ignore',
+ file=sys.stderr)
+ unused: Literal['ignore'] = 'ignore'
+ cls.unused_handling = unused
# Store changes, not entire file. This reduces (but doesn't eliminate)
# chance of race conditions when using threading.
# Additionally, reduces memory load during the main bit of the tests.
cls._queued_changes = {}
+ cls._referenced_snaps = {}
super().setUpClass()
@classmethod
@@ -137,7 +171,7 @@ def _read_snapshot_file(cls):
except SnapshotsNotFound:
if not cls.update_snapshots:
raise
- snap_data = {} # need to have something
+ snap_data: dict[str, str] = {} # need to have something
cls._files_cache[file] = snap_data
return snap_data
@@ -159,7 +193,7 @@ def get_self_name(self):
subt = getattr(subt, '_parent_', None) # We override self.subTest
return '+'.join(parts)
- def _allocate_sub_name(self, name: str):
+ def _allocate_sub_name(self, name: str | None):
if name is None:
v = self.next_idx
self.next_idx += 1
@@ -172,6 +206,7 @@ def queue_write_snapshot(self, full_name: str, new_value: str):
self._queued_changes.setdefault(self.snap_file, {})[full_name] = new_value
def lookup_snapshot(self, full_name: str):
+ self._referenced_snaps.setdefault(self.snap_file, set()).add(full_name)
try:
return self._read_snapshot_file()[full_name]
except KeyError:
@@ -190,11 +225,37 @@ def subTest(self, msg: str = unittest.case._subtest_msg_sentinel, **params):
self.next_idx = old_idx
@classmethod
- def tearDownClass(cls) -> None:
+ def tearDownClass(cls):
+ cls._check_unused_snaps()
cls._files_cache.clear() # Free that huge data structure ASAP (not used in write)
- if cls.update_snapshots:
+ if cls.update_snapshots or cls.unused_handling == 'prune':
cls.write_queued_snapshots()
+ @classmethod
+ def _check_unused_snaps(cls):
+ try:
+ all_snap_keys = set(cls._read_snapshot_file().keys())
+ except SnapshotsNotFound:
+ return # No snapshots anyway
+ # Important: only look at the snapshot keys for our class
+ # TODO: not perfect, doesn't detect if entire class is gone (needs custom runtime)
+ our_snap_keys = {k for k in all_snap_keys if k.startswith(f'{cls.cls_name}::')}
+ referenced_keys = cls._referenced_snaps.get(cls.snap_file, set())
+ unreferenced_keys = our_snap_keys - referenced_keys
+ if len(unreferenced_keys) == 0:
+ return # Ok, all referenced
+ if cls.unused_handling == 'ignore':
+ return
+ if cls.unused_handling == 'prune':
+ cls._queued_changes.setdefault(cls.snap_file, {}).update(
+ dict.fromkeys(unreferenced_keys, _DELETE_SENTINEL))
+ return
+ msg = f'Unused snapshot keys: {", ".join(unreferenced_keys)}'
+ if cls.unused_handling == 'print':
+ return print(msg, file=sys.stderr)
+ assert cls.unused_handling == 'error'
+ raise UnusedSnapshot(msg)
+
@classmethod
def _make_snaps_dir(cls):
try:
@@ -208,6 +269,8 @@ def _make_snaps_dir(cls):
def write_queued_snapshots(cls):
if not cls._queued_changes:
return
+ if not cls.update_snapshots:
+ cls._check_only_prune_changes()
cls._make_snaps_dir()
for path, changes in cls._queued_changes.items():
if not changes:
@@ -222,8 +285,20 @@ def write_queued_snapshots(cls):
f.truncate()
@classmethod
- def _apply_file_changes(cls, orig: dict[str, str], new: dict[str, str]):
- return orig | new
+ def _check_only_prune_changes(cls):
+ for changes in cls._queued_changes.values():
+ for k, v in changes.items():
+ if v and not _is_sentinel(v):
+ # Check unconditionally as no update should guarantee only
+ # 'prune' changes even if our internal methods used.
+ raise AssertionError("Cannot write non-prune changes for"
+ f"snapshot {k} in non-update mode")
+
+ @classmethod
+ def _apply_file_changes(cls, orig: dict[str, str], changes: dict[str, str | _SentinelT]):
+ new = {k: v for k, v in orig.items() if not _is_sentinel(changes.get(k))}
+ changes = {k: v for k, v in changes.items() if not _is_sentinel(v)}
+ return new | cast(dict[str, str], changes)
@dataclass
@@ -280,7 +355,7 @@ def parse_snap(text: str): # This is a bit overcomplicated - need a better form
zip(lines_idx, names, strict=True))
except ValueError:
raise SnapshotsNotFound("Can't read snapshot file (invalid format)")
- name_to_src = {}
+ name_to_src: dict[str, str] = {}
for i, (line_idx, name) in enumerate(line_name_tup):
start = line_idx
if i == len(line_name_tup) - 1:
diff --git a/test/common/utils.py b/test/common/utils.py
index aed26fd..5b3b7ca 100644
--- a/test/common/utils.py
+++ b/test/common/utils.py
@@ -4,6 +4,7 @@
import os
import unittest
+from collections.abc import Sized
from pathlib import Path
from typing import overload, TYPE_CHECKING, TypeVar, Protocol, Iterable, Container, Any
@@ -13,6 +14,7 @@
T_contra = TypeVar('T_contra', contravariant=True)
U = TypeVar('U')
U_contra = TypeVar('U_contra', contravariant=True)
+SizedT = TypeVar('SizedT', bound=Sized)
if TYPE_CHECKING:
from _typeshed import SupportsDunderLE, SupportsDunderGE
@@ -75,3 +77,36 @@ def setProperCwd(self):
def resetCwd(self):
os.chdir(self._old_cwd)
+
+ def assertHasSingleItem(self, container: Iterable[T]) -> T:
+ # Overcomplicated for better error messages and generality
+ it = iter(container)
+ try:
+ v = next(it)
+ except StopIteration:
+ self.fail(f"Expected iterable to contain one item, was empty: {safe_repr(it)}")
+ try:
+ v2 = next(it)
+ except StopIteration:
+ return v # ok, ran out of items so list is singleton
+ try:
+ # noinspection PyTypeChecker
+ length = len(it)
+ except (TypeError, NotImplementedError):
+ self.fail(f"Expected iterable to contain one item, got at least "
+ f"one extra (iterable: {container}, extra: {v2})")
+ self.fail(f"Expected iterable to contain one item, got {length} items"
+ f"(iterable: {container})")
+
+ def assertAsNotNone(self, x: T | None, msg: str | None = None) -> T:
+ self.assertIsNotNone(x, msg)
+ return x
+
+ def assertHasLength(self, sized: SizedT | None, n: int) -> SizedT:
+ sized = self.assertAsNotNone(sized)
+ self.assertEqual(n, len(sized), f"Expected {sized} to have size {n}")
+ return sized
+
+ def assertAsInstance(self, o: object, cls: type[T], msg: str | None = None) -> T:
+ self.assertIsInstance(o, cls, msg)
+ return o
diff --git a/test/test_astgen/.snapshots/test_astgen.txt b/test/test_astgen/.snapshots/test_astgen.txt
index c5bf00c..9640acb 100644
--- a/test/test_astgen/.snapshots/test_astgen.txt
+++ b/test/test_astgen/.snapshots/test_astgen.txt
@@ -1,5 +1,5 @@
-"2","14","45","93","122","184","192","204","254","313","358"
-"TestAstGen::test_op_node:0","TestAstGen::test_nop_node:0","TestAstGen::test_aug_assign:0","TestAstGen::test_getattr:0","TestAstGen::test_while_block:0","TestAstGen::test_autocat:0","TestAstGen::test_string_basic:0","TestAstGen::test_unaries:0","TestAstGen::test_decl:0","TestAstGen::test_list_literal_decl:0","TestAstGen::test_list_literal_decl_paren:0"
+"2","14","47","95","124","186","194","206","256","315","360","374"
+"TestAstGen::test_op_node:0","TestAstGen::test_nop_node:0","TestAstGen::test_aug_assign:0","TestAstGen::test_getattr:0","TestAstGen::test_while_block:0","TestAstGen::test_autocat:0","TestAstGen::test_string_basic:0","TestAstGen::test_unaries:0","TestAstGen::test_decl:0","TestAstGen::test_list_literal_decl:0","TestAstGen::test_list_literal_decl_paren:0","TestAstGen::test_elif_chain:0"
AstProgramNode(StrRegion(0, 6),
[
AstAssign(StrRegion(0, 5),
@@ -17,20 +17,22 @@ AstProgramNode(StrRegion(0, 66),
AstIf(StrRegion(0, 38),
AstNumber(StrRegion(3, 4), 2),
[],
- AstIf(StrRegion(8, 38),
- AstBinOp(StrRegion(17, 21),
- '==',
- AstNumber(StrRegion(17, 18), 1),
- AstNumber(StrRegion(20, 21), 2)
- ),
- [
- AstCall(StrRegion(24, 27),
- AstIdent(StrRegion(24, 25), 'a'),
- []
- )
- ],
- []
- )
+ [
+ AstIf(StrRegion(8, 38),
+ AstBinOp(StrRegion(17, 21),
+ '==',
+ AstNumber(StrRegion(17, 18), 1),
+ AstNumber(StrRegion(20, 21), 2)
+ ),
+ [
+ AstCall(StrRegion(24, 27),
+ AstIdent(StrRegion(24, 25), 'a'),
+ []
+ )
+ ],
+ []
+ )
+ ]
),
AstRepeat(StrRegion(41, 53),
AstIdent(StrRegion(48, 49), 'a'),
@@ -369,4 +371,25 @@ AstProgramNode(StrRegion(0, 16),
)
)
]
+)
+AstProgramNode(StrRegion(0, 37),
+ [
+ AstIf(StrRegion(0, 37),
+ AstNumber(StrRegion(3, 4), 1),
+ [],
+ [
+ AstIf(StrRegion(7, 37),
+ AstNumber(StrRegion(15, 16), 6),
+ [],
+ [
+ AstIf(StrRegion(19, 37),
+ AstNumber(StrRegion(27, 28), 7),
+ [],
+ []
+ )
+ ]
+ )
+ ]
+ )
+ ]
)
\ No newline at end of file
diff --git a/test/test_astgen/test_astgen.py b/test/test_astgen/test_astgen.py
index a376d3f..b330da7 100644
--- a/test/test_astgen/test_astgen.py
+++ b/test/test_astgen/test_astgen.py
@@ -1,3 +1,4 @@
+from parser.astgen.ast_nodes import AstProgramNode, AstIf, AstNumber
from parser.common import StrRegion
from test.common import CommonTestCase
@@ -61,3 +62,24 @@ def test_list_literal_decl_paren(self):
self.assertAstMatchesSnapshot('let[] a = ([1]);')
# We only test for lists in variable decls (as them being allowed
# elsewhere is UB for now).
+
+ def test_elif_chain(self):
+ src = "if 1{} else if 6{} else if 7{} else{}"
+ a = self.assertAsInstance(self.getAstGen(src).parse(), AstProgramNode)
+ if_0 = self.assertAsInstance(self.assertHasSingleItem(a.statements), AstIf)
+ self.assertEqual(AstNumber(StrRegion(3, 4), 1), if_0.cond)
+ self.assertEqual(if_0.if_body, [])
+ self.assertIsInstance(if_0.else_body, list)
+ elif_1 = self.assertAsInstance(
+ self.assertHasSingleItem(self.assertAsNotNone(if_0.else_body)),
+ AstIf)
+ self.assertEqual(AstNumber(StrRegion(15, 16), 6), elif_1.cond)
+ self.assertEqual(elif_1.if_body, [])
+ self.assertIsInstance(elif_1.else_body, list)
+ elif_2 = self.assertAsInstance(
+ self.assertHasSingleItem(self.assertAsNotNone(elif_1.else_body)),
+ AstIf)
+ self.assertEqual(AstNumber(StrRegion(27, 28), 7), elif_2.cond)
+ self.assertEqual(elif_2.if_body, [])
+ self.assertEqual(elif_2.else_body, [])
+ self.assertMatchesSnapshot(a) # In case I missed any checks
diff --git a/test/test_astgen/test_eval_literal.py b/test/test_astgen/test_eval_literal.py
index 5ff0d25..f66ea44 100644
--- a/test/test_astgen/test_eval_literal.py
+++ b/test/test_astgen/test_eval_literal.py
@@ -79,7 +79,7 @@ def test_bad_hex_escape_2(self):
def test_py_consistency(self):
base = r'a\\\a\b\v\f\0\n\rq\t' '\\"' "\\'"
for x in (*range(0, 34, 3), *range(34, 256, 9), 255):
- for u in range(0, 65000, 1387):
+ for u in (*range(0, 1999, 217), *range(2000, 5719, 65000)):
for big_u in range(0, 0x110000, 0xE4C1):
v2 = (base + f'\\x{x:0>2x}1\\u{u:0>4x}e\\U{big_u:0>8x}'
'\\N{COPYRIGHT SIGN}\\N{EM DASH}')
diff --git a/test/test_common/__init__.py b/test/test_common/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/test/test_common/test_tree_print.py b/test/test_common/test_tree_print.py
new file mode 100644
index 0000000..2486a6c
--- /dev/null
+++ b/test/test_common/test_tree_print.py
@@ -0,0 +1,135 @@
+import enum
+from unittest import TestCase
+
+from parser.common import StrRegion
+from parser.common.tree_print import tformat
+from parser.cst import nodes as cst_nodes
+from parser.astgen import ast_nodes
+from parser.typecheck.types import ValType, ListType, VoidType, FunctionType
+
+
+class _DummyEnum(enum.Enum):
+ A = 1
+ B = 2
+
+
+class TestTreePrinter(TestCase):
+ def assertFormatsTo(self, obj: object, expect: str):
+ actual = tformat(obj, indent=2, verbose=True, append_lf=False)
+ self.assertEqual(expect, actual)
+
+ def test_elemental(self):
+ self.assertFormatsTo(123, '123')
+ self.assertFormatsTo(_DummyEnum.A, '_DummyEnum.A')
+ self.assertFormatsTo(StrRegion(3, 5), 'StrRegion(3, 5)')
+
+ def test_empty_collections(self):
+ self.assertFormatsTo([], '[]')
+ self.assertFormatsTo((), '()')
+
+ def test_flat_element_collections(self):
+ self.assertFormatsTo([2], '[\n 2\n]')
+ self.assertFormatsTo((2,), '(\n 2,\n)')
+ self.assertFormatsTo([2, "aa", StrRegion(3, 5)],
+ "[\n 2,\n 'aa',\n StrRegion(3, 5)\n]")
+
+ def test_cst_nodes(self):
+ ae = cst_nodes.AddEqNode(StrRegion(0, 10), None, [
+ cst_nodes.IdentNode(StrRegion(0, 2)),
+ cst_nodes.SubNode(StrRegion(4, 10), None, [
+ cst_nodes.IdentNode(StrRegion(4, 5)),
+ cst_nodes.UMinusNode(StrRegion(6, 10), None, [
+ cst_nodes.NumberNode(StrRegion(7, 10))
+ ])
+ ])
+ ])
+ self.assertFormatsTo(
+ ae, dedent('''\
+ AddEqNode(StrRegion(0, 10), [
+ IdentNode(StrRegion(0, 2)),
+ SubNode(StrRegion(4, 10), [
+ IdentNode(StrRegion(4, 5)),
+ UMinusNode(StrRegion(6, 10), [
+ NumberNode(StrRegion(7, 10))
+ ])
+ ])
+ ])'''))
+
+ def test_ast_nodes(self):
+ self.assertFormatsTo(ast_nodes.AstIdent(StrRegion(0, 2), 'ab'),
+ "AstIdent(StrRegion(0, 2), 'ab')")
+ n = ast_nodes.AstAssign(
+ StrRegion(0, 10),
+ ast_nodes.AstIdent(StrRegion(0, 2), 'ab'),
+ ast_nodes.AstBinOp(
+ StrRegion(3, 10),
+ '+',
+ ast_nodes.AstIdent(StrRegion(3, 4), 'c'),
+ ast_nodes.AstUnaryOp(
+ StrRegion(5, 10),
+ '-',
+ ast_nodes.AstNumber(StrRegion(6, 10), 1000)
+ )
+ )
+ )
+ self.assertFormatsTo(n, dedent('''\
+ AstAssign(StrRegion(0, 10),
+ AstIdent(StrRegion(0, 2), 'ab'),
+ AstBinOp(StrRegion(3, 10),
+ '+',
+ AstIdent(StrRegion(3, 4), 'c'),
+ AstUnaryOp(StrRegion(5, 10),
+ '-',
+ AstNumber(StrRegion(6, 10), 1000)
+ )
+ )
+ )'''))
+
+ def test_typed_ast_nodes(self):
+ self.assertFormatsTo(ast_nodes.AstIdent(StrRegion(0, 2), 'ab', meta=ValType()),
+ "AstIdent(StrRegion(0, 2), 'ab', meta=ValType())")
+ n = ast_nodes.AstAssign(
+ StrRegion(0, 10),
+ ast_nodes.AstIdent(StrRegion(0, 2), 'ab'),
+ ast_nodes.AstBinOp(
+ StrRegion(3, 10),
+ '+',
+ ast_nodes.AstIdent(StrRegion(3, 4), 'c'),
+ ast_nodes.AstUnaryOp(
+ StrRegion(5, 10),
+ '-',
+ ast_nodes.AstNumber(StrRegion(6, 10), 1000),
+ meta=FunctionType([ListType(), ValType()], VoidType())
+ )
+ ),
+ meta=ValType()
+ )
+ self.assertFormatsTo(n, dedent('''\
+ AstAssign(StrRegion(0, 10),
+ AstIdent(StrRegion(0, 2), 'ab'),
+ AstBinOp(StrRegion(3, 10),
+ '+',
+ AstIdent(StrRegion(3, 4), 'c'),
+ AstUnaryOp(StrRegion(5, 10),
+ '-',
+ AstNumber(StrRegion(6, 10), 1000),
+ meta=FunctionType(arg_types=[ListType(), ValType()], ret_type=VoidType())
+ )
+ ),
+ meta=ValType()
+ )'''))
+
+
+def _indent_size(line: str):
+ return len(line) - len(line.lstrip())
+
+
+def dedent(s: str):
+ s = s.removeprefix('\n') # if ''' and forgotten \ after the '''
+ content_lines = filter(None, map(str.rstrip, s.splitlines()))
+ amount = min(map(_indent_size, content_lines))
+ result_lines = []
+ for line in s.split('\n'): # not splitlines to preserve possible newline at EOF
+ num_ws = len(line) - len(line.lstrip())
+ result_lines.append(line[min(amount, num_ws):]) # don't strip more WS than there is
+ return '\n'.join(result_lines)
diff --git a/test/test_e2e/.snapshots/test_main_examples.txt b/test/test_e2e/.snapshots/test_main_examples.txt
index e028cb1..cccd645 100644
--- a/test/test_e2e/.snapshots/test_main_examples.txt
+++ b/test/test_e2e/.snapshots/test_main_examples.txt
@@ -1,5 +1,5 @@
-"2","90","188","680","1101","1485","2373","3125","3813"
-"TestMain::test_example_0:tokens","TestMain::test_example_0:cst","TestMain::test_example_1:tokens","TestMain::test_example_1:cst","TestMain::test_example_1:ast","TestMain::test_example_2:tokens","TestMain::test_example_2:cst","TestMain::test_example_2:ast","TestMain::test_example_2:name_resolve"
+"2","90","188","680","1101","1482","2370","3122","3801","5188","6216","7036","7789","9522"
+"TestMain::test_example_0:tokens","TestMain::test_example_0:cst","TestMain::test_example_1:tokens","TestMain::test_example_1:cst","TestMain::test_example_1:ast","TestMain::test_example_2:tokens","TestMain::test_example_2:cst","TestMain::test_example_2:ast","TestMain::test_example_2:name_resolve","TestMain::test_example_3:tokens","TestMain::test_example_3:cst","TestMain::test_example_3:ast","TestMain::test_example_3:name_resolve","TestMain::test_example_3:typecheck"
[IdentNameToken(region=StrRegion(start=0, end=3)),
WhitespaceToken(region=StrRegion(start=3, end=4)),
IdentNameToken(region=StrRegion(start=4, end=5)),
@@ -1136,8 +1136,7 @@ AstProgramNode(StrRegion(0, 1683),
)
]
)
- ],
- None
+ ]
),
AstCall(StrRegion(477, 503),
AstIdent(StrRegion(477, 484), 'delitem'),
@@ -1309,8 +1308,7 @@ AstProgramNode(StrRegion(0, 1683),
AstIdent(StrRegion(1083, 1088), 'value')
]
)
- ],
- None
+ ]
)
]
),
@@ -1384,8 +1382,7 @@ AstProgramNode(StrRegion(0, 1683),
AstIdent(StrRegion(1342, 1346), 'tos1')
]
)
- ],
- None
+ ]
)
]
),
@@ -3233,8 +3230,7 @@ AstProgramNode(StrRegion(0, 3169),
),
AstNumber(StrRegion(554, 555), 1)
)
- ],
- None
+ ]
)
],
[
@@ -3268,8 +3264,7 @@ AstProgramNode(StrRegion(0, 3169),
AstNumber(StrRegion(733, 734), 1)
]
)
- ],
- None
+ ]
)
]
)
@@ -3301,8 +3296,7 @@ AstProgramNode(StrRegion(0, 3169),
),
AstNumber(StrRegion(927, 928), 0)
)
- ],
- None
+ ]
),
AstCall(StrRegion(940, 968),
AstAttribute(StrRegion(940, 963),
@@ -3389,11 +3383,9 @@ AstProgramNode(StrRegion(0, 3169),
AstIdent(StrRegion(1283, 1286), 'ptr')
]
)
- ],
- None
+ ]
)
- ],
- None
+ ]
)
]
),
@@ -3424,8 +3416,7 @@ AstProgramNode(StrRegion(0, 3169),
),
AstNumber(StrRegion(1434, 1435), 1)
)
- ],
- None
+ ]
)
]
),
@@ -3469,8 +3460,7 @@ AstProgramNode(StrRegion(0, 3169),
)
]
)
- ],
- None
+ ]
),
AstCall(StrRegion(1973, 1999),
AstIdent(StrRegion(1973, 1980), 'delitem'),
@@ -3642,8 +3632,7 @@ AstProgramNode(StrRegion(0, 3169),
AstIdent(StrRegion(2579, 2584), 'value')
]
)
- ],
- None
+ ]
)
]
),
@@ -3717,8 +3706,7 @@ AstProgramNode(StrRegion(0, 3169),
AstIdent(StrRegion(2838, 2842), 'tos1')
]
)
- ],
- None
+ ]
)
]
),
@@ -5197,4 +5185,5244 @@ Scope(
is_param=False
)
}
+)
+[IdentNameToken(region=StrRegion(start=0, end=6)),
+ WhitespaceToken(region=StrRegion(start=6, end=7)),
+ IdentNameToken(region=StrRegion(start=7, end=12)),
+ WhitespaceToken(region=StrRegion(start=12, end=13)),
+ OpToken(region=StrRegion(start=13, end=14), op_str='='),
+ WhitespaceToken(region=StrRegion(start=14, end=15)),
+ NumberToken(region=StrRegion(start=15, end=16)),
+ SemicolonToken(region=StrRegion(start=16, end=17)),
+ WhitespaceToken(region=StrRegion(start=17, end=18)),
+ IdentNameToken(region=StrRegion(start=18, end=24)),
+ WhitespaceToken(region=StrRegion(start=24, end=25)),
+ IdentNameToken(region=StrRegion(start=25, end=29)),
+ WhitespaceToken(region=StrRegion(start=29, end=30)),
+ OpToken(region=StrRegion(start=30, end=31), op_str='='),
+ WhitespaceToken(region=StrRegion(start=31, end=32)),
+ NumberToken(region=StrRegion(start=32, end=33)),
+ SemicolonToken(region=StrRegion(start=33, end=34)),
+ WhitespaceToken(region=StrRegion(start=34, end=36)),
+ LineCommentToken(region=StrRegion(start=36, end=48)),
+ WhitespaceToken(region=StrRegion(start=48, end=49)),
+ BlockCommentToken(region=StrRegion(start=49, end=62)),
+ IdentNameToken(region=StrRegion(start=62, end=65)),
+ WhitespaceToken(region=StrRegion(start=65, end=66)),
+ IdentNameToken(region=StrRegion(start=66, end=69)),
+ LParToken(region=StrRegion(start=69, end=70)),
+ BlockCommentToken(region=StrRegion(start=70, end=78)),
+ IdentNameToken(region=StrRegion(start=78, end=81)),
+ WhitespaceToken(region=StrRegion(start=81, end=82)),
+ IdentNameToken(region=StrRegion(start=82, end=83)),
+ RParToken(region=StrRegion(start=83, end=84)),
+ WhitespaceToken(region=StrRegion(start=84, end=85)),
+ LBrace(region=StrRegion(start=85, end=86)),
+ RBrace(region=StrRegion(start=86, end=87)),
+ WhitespaceToken(region=StrRegion(start=87, end=88)),
+ BlockCommentToken(region=StrRegion(start=88, end=101)),
+ IdentNameToken(region=StrRegion(start=101, end=104)),
+ WhitespaceToken(region=StrRegion(start=104, end=105)),
+ IdentNameToken(region=StrRegion(start=105, end=112)),
+ LParToken(region=StrRegion(start=112, end=113)),
+ BlockCommentToken(region=StrRegion(start=113, end=121)),
+ IdentNameToken(region=StrRegion(start=121, end=124)),
+ WhitespaceToken(region=StrRegion(start=124, end=125)),
+ IdentNameToken(region=StrRegion(start=125, end=126)),
+ CommaToken(region=StrRegion(start=126, end=127)),
+ WhitespaceToken(region=StrRegion(start=127, end=128)),
+ IdentNameToken(region=StrRegion(start=128, end=134)),
+ WhitespaceToken(region=StrRegion(start=134, end=135)),
+ IdentNameToken(region=StrRegion(start=135, end=138)),
+ RParToken(region=StrRegion(start=138, end=139)),
+ WhitespaceToken(region=StrRegion(start=139, end=140)),
+ LBrace(region=StrRegion(start=140, end=141)),
+ RBrace(region=StrRegion(start=141, end=142)),
+ WhitespaceToken(region=StrRegion(start=142, end=144)),
+ IdentNameToken(region=StrRegion(start=144, end=150)),
+ LSqBracket(region=StrRegion(start=150, end=151)),
+ RSqBracket(region=StrRegion(start=151, end=152)),
+ WhitespaceToken(region=StrRegion(start=152, end=153)),
+ IdentNameToken(region=StrRegion(start=153, end=159)),
+ WhitespaceToken(region=StrRegion(start=159, end=160)),
+ OpToken(region=StrRegion(start=160, end=161), op_str='='),
+ WhitespaceToken(region=StrRegion(start=161, end=162)),
+ LSqBracket(region=StrRegion(start=162, end=163)),
+ RSqBracket(region=StrRegion(start=163, end=164)),
+ SemicolonToken(region=StrRegion(start=164, end=165)),
+ WhitespaceToken(region=StrRegion(start=165, end=166)),
+ IdentNameToken(region=StrRegion(start=166, end=172)),
+ LSqBracket(region=StrRegion(start=172, end=173)),
+ RSqBracket(region=StrRegion(start=173, end=174)),
+ WhitespaceToken(region=StrRegion(start=174, end=175)),
+ IdentNameToken(region=StrRegion(start=175, end=191)),
+ WhitespaceToken(region=StrRegion(start=191, end=192)),
+ OpToken(region=StrRegion(start=192, end=193), op_str='='),
+ WhitespaceToken(region=StrRegion(start=193, end=194)),
+ LSqBracket(region=StrRegion(start=194, end=195)),
+ RSqBracket(region=StrRegion(start=195, end=196)),
+ SemicolonToken(region=StrRegion(start=196, end=197)),
+ WhitespaceToken(region=StrRegion(start=197, end=199)),
+ IdentNameToken(region=StrRegion(start=199, end=202)),
+ WhitespaceToken(region=StrRegion(start=202, end=203)),
+ IdentNameToken(region=StrRegion(start=203, end=222)),
+ LParToken(region=StrRegion(start=222, end=223)),
+ IdentNameToken(region=StrRegion(start=223, end=229)),
+ WhitespaceToken(region=StrRegion(start=229, end=230)),
+ IdentNameToken(region=StrRegion(start=230, end=233)),
+ RParToken(region=StrRegion(start=233, end=234)),
+ WhitespaceToken(region=StrRegion(start=234, end=235)),
+ LBrace(region=StrRegion(start=235, end=236)),
+ WhitespaceToken(region=StrRegion(start=236, end=241)),
+ LineCommentToken(region=StrRegion(start=241, end=292)),
+ WhitespaceToken(region=StrRegion(start=292, end=293)),
+ RBrace(region=StrRegion(start=293, end=294)),
+ WhitespaceToken(region=StrRegion(start=294, end=296)),
+ IdentNameToken(region=StrRegion(start=296, end=302)),
+ WhitespaceToken(region=StrRegion(start=302, end=303)),
+ IdentNameToken(region=StrRegion(start=303, end=313)),
+ SemicolonToken(region=StrRegion(start=313, end=314)),
+ WhitespaceToken(region=StrRegion(start=314, end=316)),
+ LineCommentToken(region=StrRegion(start=316, end=354)),
+ WhitespaceToken(region=StrRegion(start=354, end=355)),
+ IdentNameToken(region=StrRegion(start=355, end=358)),
+ WhitespaceToken(region=StrRegion(start=358, end=359)),
+ IdentNameToken(region=StrRegion(start=359, end=375)),
+ LParToken(region=StrRegion(start=375, end=376)),
+ RParToken(region=StrRegion(start=376, end=377)),
+ WhitespaceToken(region=StrRegion(start=377, end=378)),
+ LBrace(region=StrRegion(start=378, end=379)),
+ WhitespaceToken(region=StrRegion(start=379, end=384)),
+ IdentNameToken(region=StrRegion(start=384, end=405)),
+ LParToken(region=StrRegion(start=405, end=406)),
+ RParToken(region=StrRegion(start=406, end=407)),
+ SemicolonToken(region=StrRegion(start=407, end=408)),
+ WhitespaceToken(region=StrRegion(start=408, end=413)),
+ IdentNameToken(region=StrRegion(start=413, end=415)),
+ WhitespaceToken(region=StrRegion(start=415, end=416)),
+ IdentNameToken(region=StrRegion(start=416, end=426)),
+ WhitespaceToken(region=StrRegion(start=426, end=427)),
+ OpToken(region=StrRegion(start=427, end=428), op_str='>'),
+ WhitespaceToken(region=StrRegion(start=428, end=429)),
+ NumberToken(region=StrRegion(start=429, end=430)),
+ WhitespaceToken(region=StrRegion(start=430, end=431)),
+ LBrace(region=StrRegion(start=431, end=432)),
+ WhitespaceToken(region=StrRegion(start=432, end=441)),
+ IdentNameToken(region=StrRegion(start=441, end=451)),
+ WhitespaceToken(region=StrRegion(start=451, end=452)),
+ OpToken(region=StrRegion(start=452, end=453), op_str='='),
+ WhitespaceToken(region=StrRegion(start=453, end=454)),
+ IdentNameToken(region=StrRegion(start=454, end=470)),
+ LSqBracket(region=StrRegion(start=470, end=471)),
+ NumberToken(region=StrRegion(start=471, end=472)),
+ RSqBracket(region=StrRegion(start=472, end=473)),
+ SemicolonToken(region=StrRegion(start=473, end=474)),
+ WhitespaceToken(region=StrRegion(start=474, end=483)),
+ IdentNameToken(region=StrRegion(start=483, end=508)),
+ LParToken(region=StrRegion(start=508, end=509)),
+ NumberToken(region=StrRegion(start=509, end=510)),
+ RParToken(region=StrRegion(start=510, end=511)),
+ SemicolonToken(region=StrRegion(start=511, end=512)),
+ WhitespaceToken(region=StrRegion(start=512, end=521)),
+ IdentNameToken(region=StrRegion(start=521, end=523)),
+ WhitespaceToken(region=StrRegion(start=523, end=524)),
+ IdentNameToken(region=StrRegion(start=524, end=534)),
+ WhitespaceToken(region=StrRegion(start=534, end=535)),
+ OpToken(region=StrRegion(start=535, end=537), op_str='!='),
+ WhitespaceToken(region=StrRegion(start=537, end=538)),
+ NumberToken(region=StrRegion(start=538, end=539)),
+ WhitespaceToken(region=StrRegion(start=539, end=540)),
+ LBrace(region=StrRegion(start=540, end=541)),
+ WhitespaceToken(region=StrRegion(start=541, end=554)),
+ IdentNameToken(region=StrRegion(start=554, end=562)),
+ LSqBracket(region=StrRegion(start=562, end=563)),
+ IdentNameToken(region=StrRegion(start=563, end=573)),
+ RSqBracket(region=StrRegion(start=573, end=574)),
+ WhitespaceToken(region=StrRegion(start=574, end=575)),
+ OpToken(region=StrRegion(start=575, end=576), op_str='='),
+ WhitespaceToken(region=StrRegion(start=576, end=577)),
+ NumberToken(region=StrRegion(start=577, end=578)),
+ SemicolonToken(region=StrRegion(start=578, end=579)),
+ WhitespaceToken(region=StrRegion(start=579, end=588)),
+ RBrace(region=StrRegion(start=588, end=589)),
+ WhitespaceToken(region=StrRegion(start=589, end=594)),
+ RBrace(region=StrRegion(start=594, end=595)),
+ WhitespaceToken(region=StrRegion(start=595, end=596)),
+ IdentNameToken(region=StrRegion(start=596, end=600)),
+ WhitespaceToken(region=StrRegion(start=600, end=601)),
+ LBrace(region=StrRegion(start=601, end=602)),
+ WhitespaceToken(region=StrRegion(start=602, end=611)),
+ LineCommentToken(region=StrRegion(start=611, end=642)),
+ WhitespaceToken(region=StrRegion(start=642, end=651)),
+ IdentNameToken(region=StrRegion(start=651, end=665)),
+ LParToken(region=StrRegion(start=665, end=666)),
+ StringToken(region=StrRegion(start=666, end=668)),
+ RParToken(region=StrRegion(start=668, end=669)),
+ SemicolonToken(region=StrRegion(start=669, end=670)),
+ WhitespaceToken(region=StrRegion(start=670, end=679)),
+ IdentNameToken(region=StrRegion(start=679, end=690)),
+ LParToken(region=StrRegion(start=690, end=691)),
+ RParToken(region=StrRegion(start=691, end=692)),
+ SemicolonToken(region=StrRegion(start=692, end=693)),
+ WhitespaceToken(region=StrRegion(start=693, end=695)),
+ LineCommentToken(region=StrRegion(start=695, end=713)),
+ WhitespaceToken(region=StrRegion(start=713, end=722)),
+ IdentNameToken(region=StrRegion(start=722, end=724)),
+ WhitespaceToken(region=StrRegion(start=724, end=725)),
+ IdentNameToken(region=StrRegion(start=725, end=735)),
+ WhitespaceToken(region=StrRegion(start=735, end=736)),
+ OpToken(region=StrRegion(start=736, end=738), op_str='!='),
+ WhitespaceToken(region=StrRegion(start=738, end=739)),
+ NumberToken(region=StrRegion(start=739, end=740)),
+ WhitespaceToken(region=StrRegion(start=740, end=741)),
+ LBrace(region=StrRegion(start=741, end=742)),
+ WhitespaceToken(region=StrRegion(start=742, end=755)),
+ IdentNameToken(region=StrRegion(start=755, end=771)),
+ LParToken(region=StrRegion(start=771, end=772)),
+ NumberToken(region=StrRegion(start=772, end=773)),
+ RParToken(region=StrRegion(start=773, end=774)),
+ SemicolonToken(region=StrRegion(start=774, end=775)),
+ WhitespaceToken(region=StrRegion(start=775, end=784)),
+ RBrace(region=StrRegion(start=784, end=785)),
+ WhitespaceToken(region=StrRegion(start=785, end=790)),
+ RBrace(region=StrRegion(start=790, end=791)),
+ WhitespaceToken(region=StrRegion(start=791, end=792)),
+ RBrace(region=StrRegion(start=792, end=793)),
+ WhitespaceToken(region=StrRegion(start=793, end=794)),
+ BlockCommentToken(region=StrRegion(start=794, end=824)),
+ WhitespaceToken(region=StrRegion(start=824, end=825)),
+ IdentNameToken(region=StrRegion(start=825, end=828)),
+ WhitespaceToken(region=StrRegion(start=828, end=829)),
+ IdentNameToken(region=StrRegion(start=829, end=844)),
+ LParToken(region=StrRegion(start=844, end=845)),
+ IdentNameToken(region=StrRegion(start=845, end=851)),
+ WhitespaceToken(region=StrRegion(start=851, end=852)),
+ IdentNameToken(region=StrRegion(start=852, end=855)),
+ RParToken(region=StrRegion(start=855, end=856)),
+ WhitespaceToken(region=StrRegion(start=856, end=857)),
+ LBrace(region=StrRegion(start=857, end=858)),
+ WhitespaceToken(region=StrRegion(start=858, end=863)),
+ IdentNameToken(region=StrRegion(start=863, end=869)),
+ LSqBracket(region=StrRegion(start=869, end=870)),
+ IdentNameToken(region=StrRegion(start=870, end=873)),
+ RSqBracket(region=StrRegion(start=873, end=874)),
+ WhitespaceToken(region=StrRegion(start=874, end=875)),
+ OpToken(region=StrRegion(start=875, end=876), op_str='='),
+ WhitespaceToken(region=StrRegion(start=876, end=877)),
+ StringToken(region=StrRegion(start=877, end=879)),
+ SemicolonToken(region=StrRegion(start=879, end=880)),
+ WhitespaceToken(region=StrRegion(start=880, end=882)),
+ LineCommentToken(region=StrRegion(start=882, end=921)),
+ WhitespaceToken(region=StrRegion(start=921, end=926)),
+ IdentNameToken(region=StrRegion(start=926, end=928)),
+ WhitespaceToken(region=StrRegion(start=928, end=929)),
+ IdentNameToken(region=StrRegion(start=929, end=939)),
+ WhitespaceToken(region=StrRegion(start=939, end=940)),
+ OpToken(region=StrRegion(start=940, end=942), op_str='!='),
+ WhitespaceToken(region=StrRegion(start=942, end=943)),
+ NumberToken(region=StrRegion(start=943, end=944)),
+ WhitespaceToken(region=StrRegion(start=944, end=945)),
+ LBrace(region=StrRegion(start=945, end=946)),
+ WhitespaceToken(region=StrRegion(start=946, end=955)),
+ IdentNameToken(region=StrRegion(start=955, end=963)),
+ LSqBracket(region=StrRegion(start=963, end=964)),
+ IdentNameToken(region=StrRegion(start=964, end=967)),
+ RSqBracket(region=StrRegion(start=967, end=968)),
+ WhitespaceToken(region=StrRegion(start=968, end=969)),
+ OpToken(region=StrRegion(start=969, end=970), op_str='='),
+ WhitespaceToken(region=StrRegion(start=970, end=971)),
+ NumberToken(region=StrRegion(start=971, end=972)),
+ SemicolonToken(region=StrRegion(start=972, end=973)),
+ WhitespaceToken(region=StrRegion(start=973, end=978)),
+ RBrace(region=StrRegion(start=978, end=979)),
+ WhitespaceToken(region=StrRegion(start=979, end=984)),
+ IdentNameToken(region=StrRegion(start=984, end=1008)),
+ LParToken(region=StrRegion(start=1008, end=1009)),
+ IdentNameToken(region=StrRegion(start=1009, end=1012)),
+ RParToken(region=StrRegion(start=1012, end=1013)),
+ SemicolonToken(region=StrRegion(start=1013, end=1014)),
+ WhitespaceToken(region=StrRegion(start=1014, end=1015)),
+ RBrace(region=StrRegion(start=1015, end=1016)),
+ WhitespaceToken(region=StrRegion(start=1016, end=1017)),
+ IdentNameToken(region=StrRegion(start=1017, end=1020)),
+ WhitespaceToken(region=StrRegion(start=1020, end=1021)),
+ IdentNameToken(region=StrRegion(start=1021, end=1038)),
+ LParToken(region=StrRegion(start=1038, end=1039)),
+ IdentNameToken(region=StrRegion(start=1039, end=1045)),
+ WhitespaceToken(region=StrRegion(start=1045, end=1046)),
+ IdentNameToken(region=StrRegion(start=1046, end=1049)),
+ RParToken(region=StrRegion(start=1049, end=1050)),
+ WhitespaceToken(region=StrRegion(start=1050, end=1051)),
+ LBrace(region=StrRegion(start=1051, end=1052)),
+ WhitespaceToken(region=StrRegion(start=1052, end=1057)),
+ IdentNameToken(region=StrRegion(start=1057, end=1076)),
+ LParToken(region=StrRegion(start=1076, end=1077)),
+ IdentNameToken(region=StrRegion(start=1077, end=1080)),
+ RParToken(region=StrRegion(start=1080, end=1081)),
+ SemicolonToken(region=StrRegion(start=1081, end=1082)),
+ WhitespaceToken(region=StrRegion(start=1082, end=1087)),
+ IdentNameToken(region=StrRegion(start=1087, end=1102)),
+ LParToken(region=StrRegion(start=1102, end=1103)),
+ IdentNameToken(region=StrRegion(start=1103, end=1106)),
+ RParToken(region=StrRegion(start=1106, end=1107)),
+ SemicolonToken(region=StrRegion(start=1107, end=1108)),
+ WhitespaceToken(region=StrRegion(start=1108, end=1109)),
+ RBrace(region=StrRegion(start=1109, end=1110)),
+ WhitespaceToken(region=StrRegion(start=1110, end=1112)),
+ IdentNameToken(region=StrRegion(start=1112, end=1118)),
+ LSqBracket(region=StrRegion(start=1118, end=1119)),
+ RSqBracket(region=StrRegion(start=1119, end=1120)),
+ WhitespaceToken(region=StrRegion(start=1120, end=1121)),
+ IdentNameToken(region=StrRegion(start=1121, end=1129)),
+ WhitespaceToken(region=StrRegion(start=1129, end=1130)),
+ OpToken(region=StrRegion(start=1130, end=1131), op_str='='),
+ WhitespaceToken(region=StrRegion(start=1131, end=1132)),
+ LSqBracket(region=StrRegion(start=1132, end=1133)),
+ RSqBracket(region=StrRegion(start=1133, end=1134)),
+ SemicolonToken(region=StrRegion(start=1134, end=1135)),
+ WhitespaceToken(region=StrRegion(start=1135, end=1136)),
+ BlockCommentToken(region=StrRegion(start=1136, end=1156)),
+ IdentNameToken(region=StrRegion(start=1156, end=1159)),
+ WhitespaceToken(region=StrRegion(start=1159, end=1160)),
+ IdentNameToken(region=StrRegion(start=1160, end=1176)),
+ LParToken(region=StrRegion(start=1176, end=1177)),
+ IdentNameToken(region=StrRegion(start=1177, end=1180)),
+ WhitespaceToken(region=StrRegion(start=1180, end=1181)),
+ IdentNameToken(region=StrRegion(start=1181, end=1182)),
+ RParToken(region=StrRegion(start=1182, end=1183)),
+ WhitespaceToken(region=StrRegion(start=1183, end=1184)),
+ LBrace(region=StrRegion(start=1184, end=1185)),
+ RBrace(region=StrRegion(start=1185, end=1186)),
+ WhitespaceToken(region=StrRegion(start=1186, end=1187)),
+ BlockCommentToken(region=StrRegion(start=1187, end=1207)),
+ IdentNameToken(region=StrRegion(start=1207, end=1210)),
+ WhitespaceToken(region=StrRegion(start=1210, end=1211)),
+ IdentNameToken(region=StrRegion(start=1211, end=1224)),
+ LParToken(region=StrRegion(start=1224, end=1225)),
+ IdentNameToken(region=StrRegion(start=1225, end=1228)),
+ WhitespaceToken(region=StrRegion(start=1228, end=1229)),
+ IdentNameToken(region=StrRegion(start=1229, end=1230)),
+ RParToken(region=StrRegion(start=1230, end=1231)),
+ WhitespaceToken(region=StrRegion(start=1231, end=1232)),
+ LBrace(region=StrRegion(start=1232, end=1233)),
+ RBrace(region=StrRegion(start=1233, end=1234)),
+ WhitespaceToken(region=StrRegion(start=1234, end=1235)),
+ BlockCommentToken(region=StrRegion(start=1235, end=1255)),
+ IdentNameToken(region=StrRegion(start=1255, end=1258)),
+ WhitespaceToken(region=StrRegion(start=1258, end=1259)),
+ IdentNameToken(region=StrRegion(start=1259, end=1267)),
+ LParToken(region=StrRegion(start=1267, end=1268)),
+ RParToken(region=StrRegion(start=1268, end=1269)),
+ WhitespaceToken(region=StrRegion(start=1269, end=1270)),
+ LBrace(region=StrRegion(start=1270, end=1271)),
+ RBrace(region=StrRegion(start=1271, end=1272)),
+ WhitespaceToken(region=StrRegion(start=1272, end=1273)),
+ BlockCommentToken(region=StrRegion(start=1273, end=1293)),
+ IdentNameToken(region=StrRegion(start=1293, end=1296)),
+ WhitespaceToken(region=StrRegion(start=1296, end=1297)),
+ IdentNameToken(region=StrRegion(start=1297, end=1309)),
+ LParToken(region=StrRegion(start=1309, end=1310)),
+ IdentNameToken(region=StrRegion(start=1310, end=1313)),
+ WhitespaceToken(region=StrRegion(start=1313, end=1314)),
+ IdentNameToken(region=StrRegion(start=1314, end=1315)),
+ RParToken(region=StrRegion(start=1315, end=1316)),
+ WhitespaceToken(region=StrRegion(start=1316, end=1317)),
+ LBrace(region=StrRegion(start=1317, end=1318)),
+ RBrace(region=StrRegion(start=1318, end=1319)),
+ WhitespaceToken(region=StrRegion(start=1319, end=1320)),
+ BlockCommentToken(region=StrRegion(start=1320, end=1340)),
+ IdentNameToken(region=StrRegion(start=1340, end=1343)),
+ WhitespaceToken(region=StrRegion(start=1343, end=1344)),
+ IdentNameToken(region=StrRegion(start=1344, end=1358)),
+ LParToken(region=StrRegion(start=1358, end=1359)),
+ IdentNameToken(region=StrRegion(start=1359, end=1362)),
+ WhitespaceToken(region=StrRegion(start=1362, end=1363)),
+ IdentNameToken(region=StrRegion(start=1363, end=1364)),
+ RParToken(region=StrRegion(start=1364, end=1365)),
+ WhitespaceToken(region=StrRegion(start=1365, end=1366)),
+ LBrace(region=StrRegion(start=1366, end=1367)),
+ RBrace(region=StrRegion(start=1367, end=1368)),
+ WhitespaceToken(region=StrRegion(start=1368, end=1369)),
+ BlockCommentToken(region=StrRegion(start=1369, end=1389)),
+ IdentNameToken(region=StrRegion(start=1389, end=1392)),
+ WhitespaceToken(region=StrRegion(start=1392, end=1393)),
+ IdentNameToken(region=StrRegion(start=1393, end=1417)),
+ LParToken(region=StrRegion(start=1417, end=1418)),
+ IdentNameToken(region=StrRegion(start=1418, end=1421)),
+ WhitespaceToken(region=StrRegion(start=1421, end=1422)),
+ IdentNameToken(region=StrRegion(start=1422, end=1423)),
+ RParToken(region=StrRegion(start=1423, end=1424)),
+ WhitespaceToken(region=StrRegion(start=1424, end=1425)),
+ LBrace(region=StrRegion(start=1425, end=1426)),
+ RBrace(region=StrRegion(start=1426, end=1427)),
+ WhitespaceToken(region=StrRegion(start=1427, end=1428)),
+ BlockCommentToken(region=StrRegion(start=1428, end=1448)),
+ IdentNameToken(region=StrRegion(start=1448, end=1451)),
+ WhitespaceToken(region=StrRegion(start=1451, end=1452)),
+ IdentNameToken(region=StrRegion(start=1452, end=1477)),
+ LParToken(region=StrRegion(start=1477, end=1478)),
+ IdentNameToken(region=StrRegion(start=1478, end=1481)),
+ WhitespaceToken(region=StrRegion(start=1481, end=1482)),
+ IdentNameToken(region=StrRegion(start=1482, end=1483)),
+ RParToken(region=StrRegion(start=1483, end=1484)),
+ WhitespaceToken(region=StrRegion(start=1484, end=1485)),
+ LBrace(region=StrRegion(start=1485, end=1486)),
+ RBrace(region=StrRegion(start=1486, end=1487)),
+ WhitespaceToken(region=StrRegion(start=1487, end=1488)),
+ BlockCommentToken(region=StrRegion(start=1488, end=1508)),
+ IdentNameToken(region=StrRegion(start=1508, end=1511)),
+ WhitespaceToken(region=StrRegion(start=1511, end=1512)),
+ IdentNameToken(region=StrRegion(start=1512, end=1533)),
+ LParToken(region=StrRegion(start=1533, end=1534)),
+ RParToken(region=StrRegion(start=1534, end=1535)),
+ WhitespaceToken(region=StrRegion(start=1535, end=1536)),
+ LBrace(region=StrRegion(start=1536, end=1537)),
+ RBrace(region=StrRegion(start=1537, end=1538)),
+ WhitespaceToken(region=StrRegion(start=1538, end=1539)),
+ BlockCommentToken(region=StrRegion(start=1539, end=1559)),
+ IdentNameToken(region=StrRegion(start=1559, end=1562)),
+ WhitespaceToken(region=StrRegion(start=1562, end=1563)),
+ IdentNameToken(region=StrRegion(start=1563, end=1574)),
+ LParToken(region=StrRegion(start=1574, end=1575)),
+ RParToken(region=StrRegion(start=1575, end=1576)),
+ WhitespaceToken(region=StrRegion(start=1576, end=1577)),
+ LBrace(region=StrRegion(start=1577, end=1578)),
+ RBrace(region=StrRegion(start=1578, end=1579)),
+ WhitespaceToken(region=StrRegion(start=1579, end=1581)),
+ IdentNameToken(region=StrRegion(start=1581, end=1584)),
+ WhitespaceToken(region=StrRegion(start=1584, end=1585)),
+ IdentNameToken(region=StrRegion(start=1585, end=1591)),
+ LParToken(region=StrRegion(start=1591, end=1592)),
+ IdentNameToken(region=StrRegion(start=1592, end=1598)),
+ WhitespaceToken(region=StrRegion(start=1598, end=1599)),
+ IdentNameToken(region=StrRegion(start=1599, end=1602)),
+ RParToken(region=StrRegion(start=1602, end=1603)),
+ WhitespaceToken(region=StrRegion(start=1603, end=1604)),
+ LBrace(region=StrRegion(start=1604, end=1605)),
+ WhitespaceToken(region=StrRegion(start=1605, end=1610)),
+ IdentNameToken(region=StrRegion(start=1610, end=1612)),
+ WhitespaceToken(region=StrRegion(start=1612, end=1613)),
+ IdentNameToken(region=StrRegion(start=1613, end=1621)),
+ LSqBracket(region=StrRegion(start=1621, end=1622)),
+ IdentNameToken(region=StrRegion(start=1622, end=1625)),
+ RSqBracket(region=StrRegion(start=1625, end=1626)),
+ WhitespaceToken(region=StrRegion(start=1626, end=1627)),
+ OpToken(region=StrRegion(start=1627, end=1629), op_str='>='),
+ WhitespaceToken(region=StrRegion(start=1629, end=1630)),
+ NumberToken(region=StrRegion(start=1630, end=1631)),
+ WhitespaceToken(region=StrRegion(start=1631, end=1632)),
+ LBrace(region=StrRegion(start=1632, end=1633)),
+ WhitespaceToken(region=StrRegion(start=1633, end=1635)),
+ LineCommentToken(region=StrRegion(start=1635, end=1682)),
+ WhitespaceToken(region=StrRegion(start=1682, end=1691)),
+ IdentNameToken(region=StrRegion(start=1691, end=1699)),
+ LSqBracket(region=StrRegion(start=1699, end=1700)),
+ IdentNameToken(region=StrRegion(start=1700, end=1703)),
+ RSqBracket(region=StrRegion(start=1703, end=1704)),
+ WhitespaceToken(region=StrRegion(start=1704, end=1705)),
+ OpToken(region=StrRegion(start=1705, end=1706), op_str='='),
+ WhitespaceToken(region=StrRegion(start=1706, end=1707)),
+ IdentNameToken(region=StrRegion(start=1707, end=1715)),
+ LSqBracket(region=StrRegion(start=1715, end=1716)),
+ IdentNameToken(region=StrRegion(start=1716, end=1719)),
+ RSqBracket(region=StrRegion(start=1719, end=1720)),
+ WhitespaceToken(region=StrRegion(start=1720, end=1721)),
+ OpToken(region=StrRegion(start=1721, end=1722), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=1722, end=1723)),
+ NumberToken(region=StrRegion(start=1723, end=1724)),
+ SemicolonToken(region=StrRegion(start=1724, end=1725)),
+ WhitespaceToken(region=StrRegion(start=1725, end=1734)),
+ IdentNameToken(region=StrRegion(start=1734, end=1736)),
+ WhitespaceToken(region=StrRegion(start=1736, end=1737)),
+ IdentNameToken(region=StrRegion(start=1737, end=1745)),
+ LSqBracket(region=StrRegion(start=1745, end=1746)),
+ IdentNameToken(region=StrRegion(start=1746, end=1749)),
+ RSqBracket(region=StrRegion(start=1749, end=1750)),
+ WhitespaceToken(region=StrRegion(start=1750, end=1751)),
+ OpToken(region=StrRegion(start=1751, end=1753), op_str='=='),
+ WhitespaceToken(region=StrRegion(start=1753, end=1754)),
+ NumberToken(region=StrRegion(start=1754, end=1755)),
+ WhitespaceToken(region=StrRegion(start=1755, end=1756)),
+ LBrace(region=StrRegion(start=1756, end=1757)),
+ WhitespaceToken(region=StrRegion(start=1757, end=1770)),
+ IdentNameToken(region=StrRegion(start=1770, end=1787)),
+ LParToken(region=StrRegion(start=1787, end=1788)),
+ IdentNameToken(region=StrRegion(start=1788, end=1791)),
+ RParToken(region=StrRegion(start=1791, end=1792)),
+ SemicolonToken(region=StrRegion(start=1792, end=1793)),
+ WhitespaceToken(region=StrRegion(start=1793, end=1802)),
+ RBrace(region=StrRegion(start=1802, end=1803)),
+ WhitespaceToken(region=StrRegion(start=1803, end=1808)),
+ RBrace(region=StrRegion(start=1808, end=1809)),
+ WhitespaceToken(region=StrRegion(start=1809, end=1810)),
+ RBrace(region=StrRegion(start=1810, end=1811)),
+ WhitespaceToken(region=StrRegion(start=1811, end=1812)),
+ IdentNameToken(region=StrRegion(start=1812, end=1815)),
+ WhitespaceToken(region=StrRegion(start=1815, end=1816)),
+ IdentNameToken(region=StrRegion(start=1816, end=1822)),
+ LParToken(region=StrRegion(start=1822, end=1823)),
+ IdentNameToken(region=StrRegion(start=1823, end=1829)),
+ WhitespaceToken(region=StrRegion(start=1829, end=1830)),
+ IdentNameToken(region=StrRegion(start=1830, end=1833)),
+ RParToken(region=StrRegion(start=1833, end=1834)),
+ WhitespaceToken(region=StrRegion(start=1834, end=1835)),
+ LBrace(region=StrRegion(start=1835, end=1836)),
+ WhitespaceToken(region=StrRegion(start=1836, end=1841)),
+ IdentNameToken(region=StrRegion(start=1841, end=1843)),
+ WhitespaceToken(region=StrRegion(start=1843, end=1844)),
+ IdentNameToken(region=StrRegion(start=1844, end=1852)),
+ LSqBracket(region=StrRegion(start=1852, end=1853)),
+ IdentNameToken(region=StrRegion(start=1853, end=1856)),
+ RSqBracket(region=StrRegion(start=1856, end=1857)),
+ WhitespaceToken(region=StrRegion(start=1857, end=1858)),
+ OpToken(region=StrRegion(start=1858, end=1860), op_str='>='),
+ WhitespaceToken(region=StrRegion(start=1860, end=1861)),
+ NumberToken(region=StrRegion(start=1861, end=1862)),
+ WhitespaceToken(region=StrRegion(start=1862, end=1863)),
+ LBrace(region=StrRegion(start=1863, end=1864)),
+ WhitespaceToken(region=StrRegion(start=1864, end=1866)),
+ LineCommentToken(region=StrRegion(start=1866, end=1913)),
+ WhitespaceToken(region=StrRegion(start=1913, end=1922)),
+ IdentNameToken(region=StrRegion(start=1922, end=1930)),
+ LSqBracket(region=StrRegion(start=1930, end=1931)),
+ IdentNameToken(region=StrRegion(start=1931, end=1934)),
+ RSqBracket(region=StrRegion(start=1934, end=1935)),
+ WhitespaceToken(region=StrRegion(start=1935, end=1936)),
+ OpToken(region=StrRegion(start=1936, end=1937), op_str='='),
+ WhitespaceToken(region=StrRegion(start=1937, end=1938)),
+ IdentNameToken(region=StrRegion(start=1938, end=1946)),
+ LSqBracket(region=StrRegion(start=1946, end=1947)),
+ IdentNameToken(region=StrRegion(start=1947, end=1950)),
+ RSqBracket(region=StrRegion(start=1950, end=1951)),
+ WhitespaceToken(region=StrRegion(start=1951, end=1952)),
+ OpToken(region=StrRegion(start=1952, end=1953), op_str='+'),
+ WhitespaceToken(region=StrRegion(start=1953, end=1954)),
+ NumberToken(region=StrRegion(start=1954, end=1955)),
+ SemicolonToken(region=StrRegion(start=1955, end=1956)),
+ WhitespaceToken(region=StrRegion(start=1956, end=1958)),
+ LineCommentToken(region=StrRegion(start=1958, end=1994)),
+ WhitespaceToken(region=StrRegion(start=1994, end=1999)),
+ RBrace(region=StrRegion(start=1999, end=2000)),
+ WhitespaceToken(region=StrRegion(start=2000, end=2001)),
+ RBrace(region=StrRegion(start=2001, end=2002)),
+ WhitespaceToken(region=StrRegion(start=2002, end=2003)),
+ LineCommentToken(region=StrRegion(start=2003, end=2037)),
+ WhitespaceToken(region=StrRegion(start=2037, end=2040)),
+ IdentNameToken(region=StrRegion(start=2040, end=2046)),
+ LSqBracket(region=StrRegion(start=2046, end=2047)),
+ RSqBracket(region=StrRegion(start=2047, end=2048)),
+ WhitespaceToken(region=StrRegion(start=2048, end=2049)),
+ IdentNameToken(region=StrRegion(start=2049, end=2054)),
+ WhitespaceToken(region=StrRegion(start=2054, end=2055)),
+ OpToken(region=StrRegion(start=2055, end=2056), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2056, end=2057)),
+ LSqBracket(region=StrRegion(start=2057, end=2058)),
+ RSqBracket(region=StrRegion(start=2058, end=2059)),
+ SemicolonToken(region=StrRegion(start=2059, end=2060)),
+ WhitespaceToken(region=StrRegion(start=2060, end=2061)),
+ IdentNameToken(region=StrRegion(start=2061, end=2067)),
+ WhitespaceToken(region=StrRegion(start=2067, end=2068)),
+ IdentNameToken(region=StrRegion(start=2068, end=2078)),
+ WhitespaceToken(region=StrRegion(start=2078, end=2079)),
+ OpToken(region=StrRegion(start=2079, end=2080), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2080, end=2081)),
+ IdentNameToken(region=StrRegion(start=2081, end=2086)),
+ SemicolonToken(region=StrRegion(start=2086, end=2087)),
+ WhitespaceToken(region=StrRegion(start=2087, end=2089)),
+ LineCommentToken(region=StrRegion(start=2089, end=2124)),
+ WhitespaceToken(region=StrRegion(start=2124, end=2126)),
+ LineCommentToken(region=StrRegion(start=2126, end=2185)),
+ WhitespaceToken(region=StrRegion(start=2185, end=2186)),
+ LineCommentToken(region=StrRegion(start=2186, end=2270)),
+ WhitespaceToken(region=StrRegion(start=2270, end=2271)),
+ LineCommentToken(region=StrRegion(start=2271, end=2354)),
+ WhitespaceToken(region=StrRegion(start=2354, end=2355)),
+ LineCommentToken(region=StrRegion(start=2355, end=2434)),
+ WhitespaceToken(region=StrRegion(start=2434, end=2436)),
+ IdentNameToken(region=StrRegion(start=2436, end=2439)),
+ WhitespaceToken(region=StrRegion(start=2439, end=2440)),
+ IdentNameToken(region=StrRegion(start=2440, end=2443)),
+ LParToken(region=StrRegion(start=2443, end=2444)),
+ RParToken(region=StrRegion(start=2444, end=2445)),
+ WhitespaceToken(region=StrRegion(start=2445, end=2446)),
+ LBrace(region=StrRegion(start=2446, end=2447)),
+ RBrace(region=StrRegion(start=2447, end=2448)),
+ WhitespaceToken(region=StrRegion(start=2448, end=2450)),
+ IdentNameToken(region=StrRegion(start=2450, end=2453)),
+ WhitespaceToken(region=StrRegion(start=2453, end=2454)),
+ IdentNameToken(region=StrRegion(start=2454, end=2461)),
+ LParToken(region=StrRegion(start=2461, end=2462)),
+ RParToken(region=StrRegion(start=2462, end=2463)),
+ WhitespaceToken(region=StrRegion(start=2463, end=2464)),
+ LBrace(region=StrRegion(start=2464, end=2465)),
+ WhitespaceToken(region=StrRegion(start=2465, end=2470)),
+ IdentNameToken(region=StrRegion(start=2470, end=2478)),
+ LParToken(region=StrRegion(start=2478, end=2479)),
+ RParToken(region=StrRegion(start=2479, end=2480)),
+ SemicolonToken(region=StrRegion(start=2480, end=2481)),
+ WhitespaceToken(region=StrRegion(start=2481, end=2483)),
+ LineCommentToken(region=StrRegion(start=2483, end=2499)),
+ WhitespaceToken(region=StrRegion(start=2499, end=2504)),
+ IdentNameToken(region=StrRegion(start=2504, end=2506)),
+ WhitespaceToken(region=StrRegion(start=2506, end=2507)),
+ IdentNameToken(region=StrRegion(start=2507, end=2517)),
+ WhitespaceToken(region=StrRegion(start=2517, end=2518)),
+ OpToken(region=StrRegion(start=2518, end=2520), op_str='=='),
+ WhitespaceToken(region=StrRegion(start=2520, end=2521)),
+ IdentNameToken(region=StrRegion(start=2521, end=2525)),
+ WhitespaceToken(region=StrRegion(start=2525, end=2526)),
+ LBrace(region=StrRegion(start=2526, end=2527)),
+ WhitespaceToken(region=StrRegion(start=2527, end=2536)),
+ IdentNameToken(region=StrRegion(start=2536, end=2542)),
+ LParToken(region=StrRegion(start=2542, end=2543)),
+ IdentNameToken(region=StrRegion(start=2543, end=2548)),
+ LSqBracket(region=StrRegion(start=2548, end=2549)),
+ IdentNameToken(region=StrRegion(start=2549, end=2559)),
+ RSqBracket(region=StrRegion(start=2559, end=2560)),
+ RParToken(region=StrRegion(start=2560, end=2561)),
+ SemicolonToken(region=StrRegion(start=2561, end=2562)),
+ WhitespaceToken(region=StrRegion(start=2562, end=2567)),
+ RBrace(region=StrRegion(start=2567, end=2568)),
+ WhitespaceToken(region=StrRegion(start=2568, end=2573)),
+ IdentNameToken(region=StrRegion(start=2573, end=2585)),
+ LParToken(region=StrRegion(start=2585, end=2586)),
+ IdentNameToken(region=StrRegion(start=2586, end=2596)),
+ RParToken(region=StrRegion(start=2596, end=2597)),
+ SemicolonToken(region=StrRegion(start=2597, end=2598)),
+ WhitespaceToken(region=StrRegion(start=2598, end=2599)),
+ RBrace(region=StrRegion(start=2599, end=2600)),
+ WhitespaceToken(region=StrRegion(start=2600, end=2602)),
+ IdentNameToken(region=StrRegion(start=2602, end=2605)),
+ WhitespaceToken(region=StrRegion(start=2605, end=2606)),
+ IdentNameToken(region=StrRegion(start=2606, end=2613)),
+ LParToken(region=StrRegion(start=2613, end=2614)),
+ RParToken(region=StrRegion(start=2614, end=2615)),
+ WhitespaceToken(region=StrRegion(start=2615, end=2616)),
+ LBrace(region=StrRegion(start=2616, end=2617)),
+ WhitespaceToken(region=StrRegion(start=2617, end=2622)),
+ IdentNameToken(region=StrRegion(start=2622, end=2630)),
+ LParToken(region=StrRegion(start=2630, end=2631)),
+ RParToken(region=StrRegion(start=2631, end=2632)),
+ SemicolonToken(region=StrRegion(start=2632, end=2633)),
+ WhitespaceToken(region=StrRegion(start=2633, end=2638)),
+ IdentNameToken(region=StrRegion(start=2638, end=2641)),
+ WhitespaceToken(region=StrRegion(start=2641, end=2642)),
+ IdentNameToken(region=StrRegion(start=2642, end=2649)),
+ WhitespaceToken(region=StrRegion(start=2649, end=2650)),
+ OpToken(region=StrRegion(start=2650, end=2651), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2651, end=2652)),
+ IdentNameToken(region=StrRegion(start=2652, end=2662)),
+ SemicolonToken(region=StrRegion(start=2662, end=2663)),
+ WhitespaceToken(region=StrRegion(start=2663, end=2668)),
+ IdentNameToken(region=StrRegion(start=2668, end=2671)),
+ WhitespaceToken(region=StrRegion(start=2671, end=2672)),
+ IdentNameToken(region=StrRegion(start=2672, end=2676)),
+ WhitespaceToken(region=StrRegion(start=2676, end=2677)),
+ OpToken(region=StrRegion(start=2677, end=2678), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2678, end=2679)),
+ IdentNameToken(region=StrRegion(start=2679, end=2684)),
+ LSqBracket(region=StrRegion(start=2684, end=2685)),
+ IdentNameToken(region=StrRegion(start=2685, end=2692)),
+ RSqBracket(region=StrRegion(start=2692, end=2693)),
+ SemicolonToken(region=StrRegion(start=2693, end=2694)),
+ WhitespaceToken(region=StrRegion(start=2694, end=2699)),
+ IdentNameToken(region=StrRegion(start=2699, end=2704)),
+ LSqBracket(region=StrRegion(start=2704, end=2705)),
+ IdentNameToken(region=StrRegion(start=2705, end=2712)),
+ RSqBracket(region=StrRegion(start=2712, end=2713)),
+ WhitespaceToken(region=StrRegion(start=2713, end=2714)),
+ OpToken(region=StrRegion(start=2714, end=2715), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2715, end=2716)),
+ IdentNameToken(region=StrRegion(start=2716, end=2721)),
+ LSqBracket(region=StrRegion(start=2721, end=2722)),
+ IdentNameToken(region=StrRegion(start=2722, end=2729)),
+ WhitespaceToken(region=StrRegion(start=2729, end=2730)),
+ OpToken(region=StrRegion(start=2730, end=2731), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=2731, end=2732)),
+ NumberToken(region=StrRegion(start=2732, end=2733)),
+ RSqBracket(region=StrRegion(start=2733, end=2734)),
+ SemicolonToken(region=StrRegion(start=2734, end=2735)),
+ WhitespaceToken(region=StrRegion(start=2735, end=2740)),
+ IdentNameToken(region=StrRegion(start=2740, end=2745)),
+ LSqBracket(region=StrRegion(start=2745, end=2746)),
+ IdentNameToken(region=StrRegion(start=2746, end=2753)),
+ WhitespaceToken(region=StrRegion(start=2753, end=2754)),
+ OpToken(region=StrRegion(start=2754, end=2755), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=2755, end=2756)),
+ NumberToken(region=StrRegion(start=2756, end=2757)),
+ RSqBracket(region=StrRegion(start=2757, end=2758)),
+ WhitespaceToken(region=StrRegion(start=2758, end=2759)),
+ OpToken(region=StrRegion(start=2759, end=2760), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2760, end=2761)),
+ IdentNameToken(region=StrRegion(start=2761, end=2765)),
+ SemicolonToken(region=StrRegion(start=2765, end=2766)),
+ WhitespaceToken(region=StrRegion(start=2766, end=2767)),
+ RBrace(region=StrRegion(start=2767, end=2768)),
+ WhitespaceToken(region=StrRegion(start=2768, end=2770)),
+ IdentNameToken(region=StrRegion(start=2770, end=2773)),
+ WhitespaceToken(region=StrRegion(start=2773, end=2774)),
+ IdentNameToken(region=StrRegion(start=2774, end=2783)),
+ LParToken(region=StrRegion(start=2783, end=2784)),
+ RParToken(region=StrRegion(start=2784, end=2785)),
+ WhitespaceToken(region=StrRegion(start=2785, end=2786)),
+ LBrace(region=StrRegion(start=2786, end=2787)),
+ WhitespaceToken(region=StrRegion(start=2787, end=2792)),
+ LineCommentToken(region=StrRegion(start=2792, end=2808)),
+ WhitespaceToken(region=StrRegion(start=2808, end=2813)),
+ LineCommentToken(region=StrRegion(start=2813, end=2829)),
+ WhitespaceToken(region=StrRegion(start=2829, end=2834)),
+ LineCommentToken(region=StrRegion(start=2834, end=2848)),
+ WhitespaceToken(region=StrRegion(start=2848, end=2853)),
+ LineCommentToken(region=StrRegion(start=2853, end=2900)),
+ WhitespaceToken(region=StrRegion(start=2900, end=2905)),
+ IdentNameToken(region=StrRegion(start=2905, end=2913)),
+ LParToken(region=StrRegion(start=2913, end=2914)),
+ RParToken(region=StrRegion(start=2914, end=2915)),
+ SemicolonToken(region=StrRegion(start=2915, end=2916)),
+ WhitespaceToken(region=StrRegion(start=2916, end=2921)),
+ IdentNameToken(region=StrRegion(start=2921, end=2924)),
+ WhitespaceToken(region=StrRegion(start=2924, end=2925)),
+ IdentNameToken(region=StrRegion(start=2925, end=2932)),
+ WhitespaceToken(region=StrRegion(start=2932, end=2933)),
+ OpToken(region=StrRegion(start=2933, end=2934), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2934, end=2935)),
+ IdentNameToken(region=StrRegion(start=2935, end=2945)),
+ SemicolonToken(region=StrRegion(start=2945, end=2946)),
+ WhitespaceToken(region=StrRegion(start=2946, end=2951)),
+ IdentNameToken(region=StrRegion(start=2951, end=2954)),
+ WhitespaceToken(region=StrRegion(start=2954, end=2955)),
+ IdentNameToken(region=StrRegion(start=2955, end=2959)),
+ WhitespaceToken(region=StrRegion(start=2959, end=2960)),
+ OpToken(region=StrRegion(start=2960, end=2961), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2961, end=2962)),
+ IdentNameToken(region=StrRegion(start=2962, end=2967)),
+ LSqBracket(region=StrRegion(start=2967, end=2968)),
+ IdentNameToken(region=StrRegion(start=2968, end=2975)),
+ RSqBracket(region=StrRegion(start=2975, end=2976)),
+ SemicolonToken(region=StrRegion(start=2976, end=2977)),
+ WhitespaceToken(region=StrRegion(start=2977, end=2982)),
+ IdentNameToken(region=StrRegion(start=2982, end=2987)),
+ LSqBracket(region=StrRegion(start=2987, end=2988)),
+ IdentNameToken(region=StrRegion(start=2988, end=2995)),
+ RSqBracket(region=StrRegion(start=2995, end=2996)),
+ WhitespaceToken(region=StrRegion(start=2996, end=2997)),
+ OpToken(region=StrRegion(start=2997, end=2998), op_str='='),
+ WhitespaceToken(region=StrRegion(start=2998, end=2999)),
+ IdentNameToken(region=StrRegion(start=2999, end=3004)),
+ LSqBracket(region=StrRegion(start=3004, end=3005)),
+ IdentNameToken(region=StrRegion(start=3005, end=3012)),
+ WhitespaceToken(region=StrRegion(start=3012, end=3013)),
+ OpToken(region=StrRegion(start=3013, end=3014), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3014, end=3015)),
+ NumberToken(region=StrRegion(start=3015, end=3016)),
+ RSqBracket(region=StrRegion(start=3016, end=3017)),
+ SemicolonToken(region=StrRegion(start=3017, end=3018)),
+ WhitespaceToken(region=StrRegion(start=3018, end=3023)),
+ IdentNameToken(region=StrRegion(start=3023, end=3028)),
+ LSqBracket(region=StrRegion(start=3028, end=3029)),
+ IdentNameToken(region=StrRegion(start=3029, end=3036)),
+ WhitespaceToken(region=StrRegion(start=3036, end=3037)),
+ OpToken(region=StrRegion(start=3037, end=3038), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3038, end=3039)),
+ NumberToken(region=StrRegion(start=3039, end=3040)),
+ RSqBracket(region=StrRegion(start=3040, end=3041)),
+ WhitespaceToken(region=StrRegion(start=3041, end=3042)),
+ OpToken(region=StrRegion(start=3042, end=3043), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3043, end=3044)),
+ IdentNameToken(region=StrRegion(start=3044, end=3049)),
+ LSqBracket(region=StrRegion(start=3049, end=3050)),
+ IdentNameToken(region=StrRegion(start=3050, end=3057)),
+ WhitespaceToken(region=StrRegion(start=3057, end=3058)),
+ OpToken(region=StrRegion(start=3058, end=3059), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3059, end=3060)),
+ NumberToken(region=StrRegion(start=3060, end=3061)),
+ RSqBracket(region=StrRegion(start=3061, end=3062)),
+ SemicolonToken(region=StrRegion(start=3062, end=3063)),
+ WhitespaceToken(region=StrRegion(start=3063, end=3068)),
+ IdentNameToken(region=StrRegion(start=3068, end=3073)),
+ LSqBracket(region=StrRegion(start=3073, end=3074)),
+ IdentNameToken(region=StrRegion(start=3074, end=3081)),
+ WhitespaceToken(region=StrRegion(start=3081, end=3082)),
+ OpToken(region=StrRegion(start=3082, end=3083), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3083, end=3084)),
+ NumberToken(region=StrRegion(start=3084, end=3085)),
+ RSqBracket(region=StrRegion(start=3085, end=3086)),
+ WhitespaceToken(region=StrRegion(start=3086, end=3087)),
+ OpToken(region=StrRegion(start=3087, end=3088), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3088, end=3089)),
+ IdentNameToken(region=StrRegion(start=3089, end=3093)),
+ SemicolonToken(region=StrRegion(start=3093, end=3094)),
+ WhitespaceToken(region=StrRegion(start=3094, end=3095)),
+ RBrace(region=StrRegion(start=3095, end=3096)),
+ WhitespaceToken(region=StrRegion(start=3096, end=3098)),
+ IdentNameToken(region=StrRegion(start=3098, end=3101)),
+ WhitespaceToken(region=StrRegion(start=3101, end=3102)),
+ IdentNameToken(region=StrRegion(start=3102, end=3109)),
+ LParToken(region=StrRegion(start=3109, end=3110)),
+ RParToken(region=StrRegion(start=3110, end=3111)),
+ WhitespaceToken(region=StrRegion(start=3111, end=3112)),
+ LBrace(region=StrRegion(start=3112, end=3113)),
+ WhitespaceToken(region=StrRegion(start=3113, end=3118)),
+ IdentNameToken(region=StrRegion(start=3118, end=3126)),
+ LParToken(region=StrRegion(start=3126, end=3127)),
+ RParToken(region=StrRegion(start=3127, end=3128)),
+ SemicolonToken(region=StrRegion(start=3128, end=3129)),
+ WhitespaceToken(region=StrRegion(start=3129, end=3134)),
+ IdentNameToken(region=StrRegion(start=3134, end=3137)),
+ WhitespaceToken(region=StrRegion(start=3137, end=3138)),
+ IdentNameToken(region=StrRegion(start=3138, end=3143)),
+ WhitespaceToken(region=StrRegion(start=3143, end=3144)),
+ OpToken(region=StrRegion(start=3144, end=3145), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3145, end=3146)),
+ IdentNameToken(region=StrRegion(start=3146, end=3151)),
+ LSqBracket(region=StrRegion(start=3151, end=3152)),
+ IdentNameToken(region=StrRegion(start=3152, end=3162)),
+ RSqBracket(region=StrRegion(start=3162, end=3163)),
+ SemicolonToken(region=StrRegion(start=3163, end=3164)),
+ WhitespaceToken(region=StrRegion(start=3164, end=3169)),
+ IdentNameToken(region=StrRegion(start=3169, end=3182)),
+ LParToken(region=StrRegion(start=3182, end=3183)),
+ IdentNameToken(region=StrRegion(start=3183, end=3188)),
+ RParToken(region=StrRegion(start=3188, end=3189)),
+ SemicolonToken(region=StrRegion(start=3189, end=3190)),
+ WhitespaceToken(region=StrRegion(start=3190, end=3195)),
+ IdentNameToken(region=StrRegion(start=3195, end=3197)),
+ WhitespaceToken(region=StrRegion(start=3197, end=3198)),
+ IdentNameToken(region=StrRegion(start=3198, end=3208)),
+ WhitespaceToken(region=StrRegion(start=3208, end=3209)),
+ OpToken(region=StrRegion(start=3209, end=3211), op_str='!='),
+ WhitespaceToken(region=StrRegion(start=3211, end=3212)),
+ IdentNameToken(region=StrRegion(start=3212, end=3217)),
+ WhitespaceToken(region=StrRegion(start=3217, end=3218)),
+ LBrace(region=StrRegion(start=3218, end=3219)),
+ WhitespaceToken(region=StrRegion(start=3219, end=3228)),
+ IdentNameToken(region=StrRegion(start=3228, end=3234)),
+ LParToken(region=StrRegion(start=3234, end=3235)),
+ IdentNameToken(region=StrRegion(start=3235, end=3240)),
+ RParToken(region=StrRegion(start=3240, end=3241)),
+ SemicolonToken(region=StrRegion(start=3241, end=3242)),
+ WhitespaceToken(region=StrRegion(start=3242, end=3247)),
+ RBrace(region=StrRegion(start=3247, end=3248)),
+ WhitespaceToken(region=StrRegion(start=3248, end=3249)),
+ RBrace(region=StrRegion(start=3249, end=3250)),
+ WhitespaceToken(region=StrRegion(start=3250, end=3252)),
+ IdentNameToken(region=StrRegion(start=3252, end=3255)),
+ WhitespaceToken(region=StrRegion(start=3255, end=3256)),
+ IdentNameToken(region=StrRegion(start=3256, end=3267)),
+ LParToken(region=StrRegion(start=3267, end=3268)),
+ RParToken(region=StrRegion(start=3268, end=3269)),
+ WhitespaceToken(region=StrRegion(start=3269, end=3270)),
+ LBrace(region=StrRegion(start=3270, end=3271)),
+ WhitespaceToken(region=StrRegion(start=3271, end=3276)),
+ IdentNameToken(region=StrRegion(start=3276, end=3284)),
+ LParToken(region=StrRegion(start=3284, end=3285)),
+ RParToken(region=StrRegion(start=3285, end=3286)),
+ SemicolonToken(region=StrRegion(start=3286, end=3287)),
+ WhitespaceToken(region=StrRegion(start=3287, end=3292)),
+ IdentNameToken(region=StrRegion(start=3292, end=3295)),
+ WhitespaceToken(region=StrRegion(start=3295, end=3296)),
+ IdentNameToken(region=StrRegion(start=3296, end=3303)),
+ WhitespaceToken(region=StrRegion(start=3303, end=3304)),
+ OpToken(region=StrRegion(start=3304, end=3305), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3305, end=3306)),
+ IdentNameToken(region=StrRegion(start=3306, end=3316)),
+ SemicolonToken(region=StrRegion(start=3316, end=3317)),
+ WhitespaceToken(region=StrRegion(start=3317, end=3322)),
+ IdentNameToken(region=StrRegion(start=3322, end=3325)),
+ WhitespaceToken(region=StrRegion(start=3325, end=3326)),
+ IdentNameToken(region=StrRegion(start=3326, end=3330)),
+ WhitespaceToken(region=StrRegion(start=3330, end=3331)),
+ OpToken(region=StrRegion(start=3331, end=3332), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3332, end=3333)),
+ IdentNameToken(region=StrRegion(start=3333, end=3338)),
+ LSqBracket(region=StrRegion(start=3338, end=3339)),
+ IdentNameToken(region=StrRegion(start=3339, end=3346)),
+ RSqBracket(region=StrRegion(start=3346, end=3347)),
+ SemicolonToken(region=StrRegion(start=3347, end=3348)),
+ WhitespaceToken(region=StrRegion(start=3348, end=3353)),
+ IdentNameToken(region=StrRegion(start=3353, end=3356)),
+ WhitespaceToken(region=StrRegion(start=3356, end=3357)),
+ IdentNameToken(region=StrRegion(start=3357, end=3361)),
+ WhitespaceToken(region=StrRegion(start=3361, end=3362)),
+ OpToken(region=StrRegion(start=3362, end=3363), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3363, end=3364)),
+ IdentNameToken(region=StrRegion(start=3364, end=3369)),
+ LSqBracket(region=StrRegion(start=3369, end=3370)),
+ IdentNameToken(region=StrRegion(start=3370, end=3377)),
+ WhitespaceToken(region=StrRegion(start=3377, end=3378)),
+ OpToken(region=StrRegion(start=3378, end=3379), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3379, end=3380)),
+ NumberToken(region=StrRegion(start=3380, end=3381)),
+ RSqBracket(region=StrRegion(start=3381, end=3382)),
+ SemicolonToken(region=StrRegion(start=3382, end=3383)),
+ WhitespaceToken(region=StrRegion(start=3383, end=3388)),
+ IdentNameToken(region=StrRegion(start=3388, end=3401)),
+ LParToken(region=StrRegion(start=3401, end=3402)),
+ IdentNameToken(region=StrRegion(start=3402, end=3406)),
+ RParToken(region=StrRegion(start=3406, end=3407)),
+ SemicolonToken(region=StrRegion(start=3407, end=3408)),
+ WhitespaceToken(region=StrRegion(start=3408, end=3413)),
+ IdentNameToken(region=StrRegion(start=3413, end=3426)),
+ LParToken(region=StrRegion(start=3426, end=3427)),
+ IdentNameToken(region=StrRegion(start=3427, end=3431)),
+ RParToken(region=StrRegion(start=3431, end=3432)),
+ SemicolonToken(region=StrRegion(start=3432, end=3433)),
+ WhitespaceToken(region=StrRegion(start=3433, end=3435)),
+ LineCommentToken(region=StrRegion(start=3435, end=3454)),
+ WhitespaceToken(region=StrRegion(start=3454, end=3459)),
+ IdentNameToken(region=StrRegion(start=3459, end=3461)),
+ WhitespaceToken(region=StrRegion(start=3461, end=3462)),
+ IdentNameToken(region=StrRegion(start=3462, end=3472)),
+ WhitespaceToken(region=StrRegion(start=3472, end=3473)),
+ OpToken(region=StrRegion(start=3473, end=3475), op_str='!='),
+ WhitespaceToken(region=StrRegion(start=3475, end=3476)),
+ NumberToken(region=StrRegion(start=3476, end=3477)),
+ WhitespaceToken(region=StrRegion(start=3477, end=3478)),
+ LBrace(region=StrRegion(start=3478, end=3479)),
+ WhitespaceToken(region=StrRegion(start=3479, end=3488)),
+ IdentNameToken(region=StrRegion(start=3488, end=3494)),
+ LParToken(region=StrRegion(start=3494, end=3495)),
+ IdentNameToken(region=StrRegion(start=3495, end=3499)),
+ RParToken(region=StrRegion(start=3499, end=3500)),
+ SemicolonToken(region=StrRegion(start=3500, end=3501)),
+ WhitespaceToken(region=StrRegion(start=3501, end=3510)),
+ IdentNameToken(region=StrRegion(start=3510, end=3516)),
+ LParToken(region=StrRegion(start=3516, end=3517)),
+ IdentNameToken(region=StrRegion(start=3517, end=3521)),
+ RParToken(region=StrRegion(start=3521, end=3522)),
+ SemicolonToken(region=StrRegion(start=3522, end=3523)),
+ WhitespaceToken(region=StrRegion(start=3523, end=3528)),
+ RBrace(region=StrRegion(start=3528, end=3529)),
+ WhitespaceToken(region=StrRegion(start=3529, end=3530)),
+ RBrace(region=StrRegion(start=3530, end=3531)),
+ WhitespaceToken(region=StrRegion(start=3531, end=3533)),
+ IdentNameToken(region=StrRegion(start=3533, end=3536)),
+ WhitespaceToken(region=StrRegion(start=3536, end=3537)),
+ IdentNameToken(region=StrRegion(start=3537, end=3545)),
+ LParToken(region=StrRegion(start=3545, end=3546)),
+ RParToken(region=StrRegion(start=3546, end=3547)),
+ WhitespaceToken(region=StrRegion(start=3547, end=3548)),
+ LBrace(region=StrRegion(start=3548, end=3549)),
+ WhitespaceToken(region=StrRegion(start=3549, end=3554)),
+ LineCommentToken(region=StrRegion(start=3554, end=3567)),
+ WhitespaceToken(region=StrRegion(start=3567, end=3572)),
+ LineCommentToken(region=StrRegion(start=3572, end=3585)),
+ WhitespaceToken(region=StrRegion(start=3585, end=3590)),
+ LineCommentToken(region=StrRegion(start=3590, end=3604)),
+ WhitespaceToken(region=StrRegion(start=3604, end=3609)),
+ LineCommentToken(region=StrRegion(start=3609, end=3623)),
+ WhitespaceToken(region=StrRegion(start=3623, end=3628)),
+ IdentNameToken(region=StrRegion(start=3628, end=3636)),
+ LParToken(region=StrRegion(start=3636, end=3637)),
+ RParToken(region=StrRegion(start=3637, end=3638)),
+ SemicolonToken(region=StrRegion(start=3638, end=3639)),
+ WhitespaceToken(region=StrRegion(start=3639, end=3644)),
+ IdentNameToken(region=StrRegion(start=3644, end=3647)),
+ WhitespaceToken(region=StrRegion(start=3647, end=3648)),
+ IdentNameToken(region=StrRegion(start=3648, end=3655)),
+ WhitespaceToken(region=StrRegion(start=3655, end=3656)),
+ OpToken(region=StrRegion(start=3656, end=3657), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3657, end=3658)),
+ IdentNameToken(region=StrRegion(start=3658, end=3668)),
+ SemicolonToken(region=StrRegion(start=3668, end=3669)),
+ WhitespaceToken(region=StrRegion(start=3669, end=3674)),
+ IdentNameToken(region=StrRegion(start=3674, end=3677)),
+ WhitespaceToken(region=StrRegion(start=3677, end=3678)),
+ IdentNameToken(region=StrRegion(start=3678, end=3682)),
+ WhitespaceToken(region=StrRegion(start=3682, end=3683)),
+ OpToken(region=StrRegion(start=3683, end=3684), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3684, end=3685)),
+ IdentNameToken(region=StrRegion(start=3685, end=3690)),
+ LSqBracket(region=StrRegion(start=3690, end=3691)),
+ IdentNameToken(region=StrRegion(start=3691, end=3698)),
+ RSqBracket(region=StrRegion(start=3698, end=3699)),
+ SemicolonToken(region=StrRegion(start=3699, end=3700)),
+ WhitespaceToken(region=StrRegion(start=3700, end=3705)),
+ IdentNameToken(region=StrRegion(start=3705, end=3710)),
+ LSqBracket(region=StrRegion(start=3710, end=3711)),
+ IdentNameToken(region=StrRegion(start=3711, end=3718)),
+ RSqBracket(region=StrRegion(start=3718, end=3719)),
+ WhitespaceToken(region=StrRegion(start=3719, end=3720)),
+ OpToken(region=StrRegion(start=3720, end=3721), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3721, end=3722)),
+ IdentNameToken(region=StrRegion(start=3722, end=3727)),
+ LSqBracket(region=StrRegion(start=3727, end=3728)),
+ IdentNameToken(region=StrRegion(start=3728, end=3735)),
+ WhitespaceToken(region=StrRegion(start=3735, end=3736)),
+ OpToken(region=StrRegion(start=3736, end=3737), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3737, end=3738)),
+ NumberToken(region=StrRegion(start=3738, end=3739)),
+ RSqBracket(region=StrRegion(start=3739, end=3740)),
+ SemicolonToken(region=StrRegion(start=3740, end=3741)),
+ WhitespaceToken(region=StrRegion(start=3741, end=3746)),
+ IdentNameToken(region=StrRegion(start=3746, end=3751)),
+ LSqBracket(region=StrRegion(start=3751, end=3752)),
+ IdentNameToken(region=StrRegion(start=3752, end=3759)),
+ WhitespaceToken(region=StrRegion(start=3759, end=3760)),
+ OpToken(region=StrRegion(start=3760, end=3761), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3761, end=3762)),
+ NumberToken(region=StrRegion(start=3762, end=3763)),
+ RSqBracket(region=StrRegion(start=3763, end=3764)),
+ WhitespaceToken(region=StrRegion(start=3764, end=3765)),
+ OpToken(region=StrRegion(start=3765, end=3766), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3766, end=3767)),
+ IdentNameToken(region=StrRegion(start=3767, end=3772)),
+ LSqBracket(region=StrRegion(start=3772, end=3773)),
+ IdentNameToken(region=StrRegion(start=3773, end=3780)),
+ WhitespaceToken(region=StrRegion(start=3780, end=3781)),
+ OpToken(region=StrRegion(start=3781, end=3782), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3782, end=3783)),
+ NumberToken(region=StrRegion(start=3783, end=3784)),
+ RSqBracket(region=StrRegion(start=3784, end=3785)),
+ SemicolonToken(region=StrRegion(start=3785, end=3786)),
+ WhitespaceToken(region=StrRegion(start=3786, end=3791)),
+ IdentNameToken(region=StrRegion(start=3791, end=3796)),
+ LSqBracket(region=StrRegion(start=3796, end=3797)),
+ IdentNameToken(region=StrRegion(start=3797, end=3804)),
+ WhitespaceToken(region=StrRegion(start=3804, end=3805)),
+ OpToken(region=StrRegion(start=3805, end=3806), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3806, end=3807)),
+ NumberToken(region=StrRegion(start=3807, end=3808)),
+ RSqBracket(region=StrRegion(start=3808, end=3809)),
+ WhitespaceToken(region=StrRegion(start=3809, end=3810)),
+ OpToken(region=StrRegion(start=3810, end=3811), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3811, end=3812)),
+ IdentNameToken(region=StrRegion(start=3812, end=3817)),
+ LSqBracket(region=StrRegion(start=3817, end=3818)),
+ IdentNameToken(region=StrRegion(start=3818, end=3825)),
+ WhitespaceToken(region=StrRegion(start=3825, end=3826)),
+ OpToken(region=StrRegion(start=3826, end=3827), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3827, end=3828)),
+ NumberToken(region=StrRegion(start=3828, end=3829)),
+ RSqBracket(region=StrRegion(start=3829, end=3830)),
+ SemicolonToken(region=StrRegion(start=3830, end=3831)),
+ WhitespaceToken(region=StrRegion(start=3831, end=3836)),
+ IdentNameToken(region=StrRegion(start=3836, end=3841)),
+ LSqBracket(region=StrRegion(start=3841, end=3842)),
+ IdentNameToken(region=StrRegion(start=3842, end=3849)),
+ WhitespaceToken(region=StrRegion(start=3849, end=3850)),
+ OpToken(region=StrRegion(start=3850, end=3851), op_str='-'),
+ WhitespaceToken(region=StrRegion(start=3851, end=3852)),
+ NumberToken(region=StrRegion(start=3852, end=3853)),
+ RSqBracket(region=StrRegion(start=3853, end=3854)),
+ WhitespaceToken(region=StrRegion(start=3854, end=3855)),
+ OpToken(region=StrRegion(start=3855, end=3856), op_str='='),
+ WhitespaceToken(region=StrRegion(start=3856, end=3857)),
+ IdentNameToken(region=StrRegion(start=3857, end=3861)),
+ SemicolonToken(region=StrRegion(start=3861, end=3862)),
+ WhitespaceToken(region=StrRegion(start=3862, end=3863)),
+ RBrace(region=StrRegion(start=3863, end=3864)),
+ WhitespaceToken(region=StrRegion(start=3864, end=3865)),
+ EofToken(region=StrRegion(start=3865, end=3865))]
+ProgramNode(StrRegion(0, 3864), [
+ DeclNode(StrRegion(0, 16), [
+ DeclScope_Global(StrRegion(0, 6)),
+ DeclType_Variable(StrRegion(6, 6)),
+ DeclItemsList(StrRegion(7, 16), [
+ DeclItemNode(StrRegion(7, 16), [
+ IdentNode(StrRegion(7, 12)),
+ NumberNode(StrRegion(15, 16))
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(18, 33), [
+ DeclScope_Global(StrRegion(18, 24)),
+ DeclType_Variable(StrRegion(24, 24)),
+ DeclItemsList(StrRegion(25, 33), [
+ DeclItemNode(StrRegion(25, 33), [
+ IdentNode(StrRegion(25, 29)),
+ NumberNode(StrRegion(32, 33))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(62, 87), [
+ IdentNode(StrRegion(66, 69)),
+ ArgsDeclNode(StrRegion(69, 84), [
+ ArgDeclNode(StrRegion(78, 83), [
+ IdentNode(StrRegion(78, 81)),
+ IdentNode(StrRegion(82, 83))
+ ])
+ ]),
+ BlockNode(StrRegion(85, 87), [])
+ ]),
+ DefineNode(StrRegion(101, 142), [
+ IdentNode(StrRegion(105, 112)),
+ ArgsDeclNode(StrRegion(112, 139), [
+ ArgDeclNode(StrRegion(121, 126), [
+ IdentNode(StrRegion(121, 124)),
+ IdentNode(StrRegion(125, 126))
+ ]),
+ ArgDeclNode(StrRegion(128, 138), [
+ IdentNode(StrRegion(128, 134)),
+ IdentNode(StrRegion(135, 138))
+ ])
+ ]),
+ BlockNode(StrRegion(140, 142), [])
+ ]),
+ DeclNode(StrRegion(144, 164), [
+ DeclScope_Global(StrRegion(144, 150)),
+ DeclType_List(StrRegion(150, 152)),
+ DeclItemsList(StrRegion(153, 164), [
+ DeclItemNode(StrRegion(153, 164), [
+ IdentNode(StrRegion(153, 159)),
+ ListNode(StrRegion(162, 164), [])
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(166, 196), [
+ DeclScope_Global(StrRegion(166, 172)),
+ DeclType_List(StrRegion(172, 174)),
+ DeclItemsList(StrRegion(175, 196), [
+ DeclItemNode(StrRegion(175, 196), [
+ IdentNode(StrRegion(175, 191)),
+ ListNode(StrRegion(194, 196), [])
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(199, 294), [
+ IdentNode(StrRegion(203, 222)),
+ ArgsDeclNode(StrRegion(222, 234), [
+ ArgDeclNode(StrRegion(223, 233), [
+ IdentNode(StrRegion(223, 229)),
+ IdentNode(StrRegion(230, 233))
+ ])
+ ]),
+ BlockNode(StrRegion(235, 294), [])
+ ]),
+ DeclNode(StrRegion(296, 313), [
+ DeclScope_Global(StrRegion(296, 302)),
+ DeclType_Variable(StrRegion(302, 302)),
+ DeclItemsList(StrRegion(303, 313), [
+ DeclItemNode(StrRegion(303, 313), [
+ IdentNode(StrRegion(303, 313))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(355, 793), [
+ IdentNode(StrRegion(359, 375)),
+ ArgsDeclNode(StrRegion(375, 377), []),
+ BlockNode(StrRegion(378, 793), [
+ CallNode(StrRegion(384, 407), [
+ IdentNode(StrRegion(384, 405)),
+ CallArgs(StrRegion(405, 407), [])
+ ]),
+ ConditionalBlock(StrRegion(413, 791), [
+ IfBlock(StrRegion(413, 595), [
+ GtNode(StrRegion(416, 430), [
+ IdentNode(StrRegion(416, 426)),
+ NumberNode(StrRegion(429, 430))
+ ]),
+ BlockNode(StrRegion(431, 595), [
+ AssignNode(StrRegion(441, 473), [
+ IdentNode(StrRegion(441, 451)),
+ GetitemNode(StrRegion(454, 473), [
+ IdentNode(StrRegion(454, 470)),
+ NumberNode(StrRegion(471, 472))
+ ])
+ ]),
+ CallNode(StrRegion(483, 511), [
+ IdentNode(StrRegion(483, 508)),
+ CallArgs(StrRegion(508, 511), [
+ NumberNode(StrRegion(509, 510))
+ ])
+ ]),
+ ConditionalBlock(StrRegion(521, 589), [
+ IfBlock(StrRegion(521, 589), [
+ NeqNode(StrRegion(524, 539), [
+ IdentNode(StrRegion(524, 534)),
+ NumberNode(StrRegion(538, 539))
+ ]),
+ BlockNode(StrRegion(540, 589), [
+ AssignNode(StrRegion(554, 578), [
+ GetitemNode(StrRegion(554, 574), [
+ IdentNode(StrRegion(554, 562)),
+ IdentNode(StrRegion(563, 573))
+ ]),
+ NumberNode(StrRegion(577, 578))
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(588, 589))
+ ])
+ ])
+ ]),
+ ElseBlock(StrRegion(596, 791), [
+ BlockNode(StrRegion(601, 791), [
+ CallNode(StrRegion(651, 669), [
+ IdentNode(StrRegion(651, 665)),
+ CallArgs(StrRegion(665, 669), [
+ StringNode(StrRegion(666, 668))
+ ])
+ ]),
+ CallNode(StrRegion(679, 692), [
+ IdentNode(StrRegion(679, 690)),
+ CallArgs(StrRegion(690, 692), [])
+ ]),
+ ConditionalBlock(StrRegion(722, 785), [
+ IfBlock(StrRegion(722, 785), [
+ NeqNode(StrRegion(725, 740), [
+ IdentNode(StrRegion(725, 735)),
+ NumberNode(StrRegion(739, 740))
+ ]),
+ BlockNode(StrRegion(741, 785), [
+ CallNode(StrRegion(755, 774), [
+ IdentNode(StrRegion(755, 771)),
+ CallArgs(StrRegion(771, 774), [
+ NumberNode(StrRegion(772, 773))
+ ])
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(784, 785))
+ ])
+ ])
+ ])
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(825, 1016), [
+ IdentNode(StrRegion(829, 844)),
+ ArgsDeclNode(StrRegion(844, 856), [
+ ArgDeclNode(StrRegion(845, 855), [
+ IdentNode(StrRegion(845, 851)),
+ IdentNode(StrRegion(852, 855))
+ ])
+ ]),
+ BlockNode(StrRegion(857, 1016), [
+ AssignNode(StrRegion(863, 879), [
+ GetitemNode(StrRegion(863, 874), [
+ IdentNode(StrRegion(863, 869)),
+ IdentNode(StrRegion(870, 873))
+ ]),
+ StringNode(StrRegion(877, 879))
+ ]),
+ ConditionalBlock(StrRegion(926, 979), [
+ IfBlock(StrRegion(926, 979), [
+ NeqNode(StrRegion(929, 944), [
+ IdentNode(StrRegion(929, 939)),
+ NumberNode(StrRegion(943, 944))
+ ]),
+ BlockNode(StrRegion(945, 979), [
+ AssignNode(StrRegion(955, 972), [
+ GetitemNode(StrRegion(955, 968), [
+ IdentNode(StrRegion(955, 963)),
+ IdentNode(StrRegion(964, 967))
+ ]),
+ NumberNode(StrRegion(971, 972))
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(978, 979))
+ ]),
+ CallNode(StrRegion(984, 1013), [
+ IdentNode(StrRegion(984, 1008)),
+ CallArgs(StrRegion(1008, 1013), [
+ IdentNode(StrRegion(1009, 1012))
+ ])
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(1017, 1110), [
+ IdentNode(StrRegion(1021, 1038)),
+ ArgsDeclNode(StrRegion(1038, 1050), [
+ ArgDeclNode(StrRegion(1039, 1049), [
+ IdentNode(StrRegion(1039, 1045)),
+ IdentNode(StrRegion(1046, 1049))
+ ])
+ ]),
+ BlockNode(StrRegion(1051, 1110), [
+ CallNode(StrRegion(1057, 1081), [
+ IdentNode(StrRegion(1057, 1076)),
+ CallArgs(StrRegion(1076, 1081), [
+ IdentNode(StrRegion(1077, 1080))
+ ])
+ ]),
+ CallNode(StrRegion(1087, 1107), [
+ IdentNode(StrRegion(1087, 1102)),
+ CallArgs(StrRegion(1102, 1107), [
+ IdentNode(StrRegion(1103, 1106))
+ ])
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(1112, 1134), [
+ DeclScope_Global(StrRegion(1112, 1118)),
+ DeclType_List(StrRegion(1118, 1120)),
+ DeclItemsList(StrRegion(1121, 1134), [
+ DeclItemNode(StrRegion(1121, 1134), [
+ IdentNode(StrRegion(1121, 1129)),
+ ListNode(StrRegion(1132, 1134), [])
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(1156, 1186), [
+ IdentNode(StrRegion(1160, 1176)),
+ ArgsDeclNode(StrRegion(1176, 1183), [
+ ArgDeclNode(StrRegion(1177, 1182), [
+ IdentNode(StrRegion(1177, 1180)),
+ IdentNode(StrRegion(1181, 1182))
+ ])
+ ]),
+ BlockNode(StrRegion(1184, 1186), [])
+ ]),
+ DefineNode(StrRegion(1207, 1234), [
+ IdentNode(StrRegion(1211, 1224)),
+ ArgsDeclNode(StrRegion(1224, 1231), [
+ ArgDeclNode(StrRegion(1225, 1230), [
+ IdentNode(StrRegion(1225, 1228)),
+ IdentNode(StrRegion(1229, 1230))
+ ])
+ ]),
+ BlockNode(StrRegion(1232, 1234), [])
+ ]),
+ DefineNode(StrRegion(1255, 1272), [
+ IdentNode(StrRegion(1259, 1267)),
+ ArgsDeclNode(StrRegion(1267, 1269), []),
+ BlockNode(StrRegion(1270, 1272), [])
+ ]),
+ DefineNode(StrRegion(1293, 1319), [
+ IdentNode(StrRegion(1297, 1309)),
+ ArgsDeclNode(StrRegion(1309, 1316), [
+ ArgDeclNode(StrRegion(1310, 1315), [
+ IdentNode(StrRegion(1310, 1313)),
+ IdentNode(StrRegion(1314, 1315))
+ ])
+ ]),
+ BlockNode(StrRegion(1317, 1319), [])
+ ]),
+ DefineNode(StrRegion(1340, 1368), [
+ IdentNode(StrRegion(1344, 1358)),
+ ArgsDeclNode(StrRegion(1358, 1365), [
+ ArgDeclNode(StrRegion(1359, 1364), [
+ IdentNode(StrRegion(1359, 1362)),
+ IdentNode(StrRegion(1363, 1364))
+ ])
+ ]),
+ BlockNode(StrRegion(1366, 1368), [])
+ ]),
+ DefineNode(StrRegion(1389, 1427), [
+ IdentNode(StrRegion(1393, 1417)),
+ ArgsDeclNode(StrRegion(1417, 1424), [
+ ArgDeclNode(StrRegion(1418, 1423), [
+ IdentNode(StrRegion(1418, 1421)),
+ IdentNode(StrRegion(1422, 1423))
+ ])
+ ]),
+ BlockNode(StrRegion(1425, 1427), [])
+ ]),
+ DefineNode(StrRegion(1448, 1487), [
+ IdentNode(StrRegion(1452, 1477)),
+ ArgsDeclNode(StrRegion(1477, 1484), [
+ ArgDeclNode(StrRegion(1478, 1483), [
+ IdentNode(StrRegion(1478, 1481)),
+ IdentNode(StrRegion(1482, 1483))
+ ])
+ ]),
+ BlockNode(StrRegion(1485, 1487), [])
+ ]),
+ DefineNode(StrRegion(1508, 1538), [
+ IdentNode(StrRegion(1512, 1533)),
+ ArgsDeclNode(StrRegion(1533, 1535), []),
+ BlockNode(StrRegion(1536, 1538), [])
+ ]),
+ DefineNode(StrRegion(1559, 1579), [
+ IdentNode(StrRegion(1563, 1574)),
+ ArgsDeclNode(StrRegion(1574, 1576), []),
+ BlockNode(StrRegion(1577, 1579), [])
+ ]),
+ DefineNode(StrRegion(1581, 1811), [
+ IdentNode(StrRegion(1585, 1591)),
+ ArgsDeclNode(StrRegion(1591, 1603), [
+ ArgDeclNode(StrRegion(1592, 1602), [
+ IdentNode(StrRegion(1592, 1598)),
+ IdentNode(StrRegion(1599, 1602))
+ ])
+ ]),
+ BlockNode(StrRegion(1604, 1811), [
+ ConditionalBlock(StrRegion(1610, 1809), [
+ IfBlock(StrRegion(1610, 1809), [
+ GeNode(StrRegion(1613, 1631), [
+ GetitemNode(StrRegion(1613, 1626), [
+ IdentNode(StrRegion(1613, 1621)),
+ IdentNode(StrRegion(1622, 1625))
+ ]),
+ NumberNode(StrRegion(1630, 1631))
+ ]),
+ BlockNode(StrRegion(1632, 1809), [
+ AssignNode(StrRegion(1691, 1724), [
+ GetitemNode(StrRegion(1691, 1704), [
+ IdentNode(StrRegion(1691, 1699)),
+ IdentNode(StrRegion(1700, 1703))
+ ]),
+ SubNode(StrRegion(1707, 1724), [
+ GetitemNode(StrRegion(1707, 1720), [
+ IdentNode(StrRegion(1707, 1715)),
+ IdentNode(StrRegion(1716, 1719))
+ ]),
+ NumberNode(StrRegion(1723, 1724))
+ ])
+ ]),
+ ConditionalBlock(StrRegion(1734, 1803), [
+ IfBlock(StrRegion(1734, 1803), [
+ EqNode(StrRegion(1737, 1755), [
+ GetitemNode(StrRegion(1737, 1750), [
+ IdentNode(StrRegion(1737, 1745)),
+ IdentNode(StrRegion(1746, 1749))
+ ]),
+ NumberNode(StrRegion(1754, 1755))
+ ]),
+ BlockNode(StrRegion(1756, 1803), [
+ CallNode(StrRegion(1770, 1792), [
+ IdentNode(StrRegion(1770, 1787)),
+ CallArgs(StrRegion(1787, 1792), [
+ IdentNode(StrRegion(1788, 1791))
+ ])
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(1802, 1803))
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(1808, 1809))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(1812, 2002), [
+ IdentNode(StrRegion(1816, 1822)),
+ ArgsDeclNode(StrRegion(1822, 1834), [
+ ArgDeclNode(StrRegion(1823, 1833), [
+ IdentNode(StrRegion(1823, 1829)),
+ IdentNode(StrRegion(1830, 1833))
+ ])
+ ]),
+ BlockNode(StrRegion(1835, 2002), [
+ ConditionalBlock(StrRegion(1841, 2000), [
+ IfBlock(StrRegion(1841, 2000), [
+ GeNode(StrRegion(1844, 1862), [
+ GetitemNode(StrRegion(1844, 1857), [
+ IdentNode(StrRegion(1844, 1852)),
+ IdentNode(StrRegion(1853, 1856))
+ ]),
+ NumberNode(StrRegion(1861, 1862))
+ ]),
+ BlockNode(StrRegion(1863, 2000), [
+ AssignNode(StrRegion(1922, 1955), [
+ GetitemNode(StrRegion(1922, 1935), [
+ IdentNode(StrRegion(1922, 1930)),
+ IdentNode(StrRegion(1931, 1934))
+ ]),
+ AddNode(StrRegion(1938, 1955), [
+ GetitemNode(StrRegion(1938, 1951), [
+ IdentNode(StrRegion(1938, 1946)),
+ IdentNode(StrRegion(1947, 1950))
+ ]),
+ NumberNode(StrRegion(1954, 1955))
+ ])
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(1999, 2000))
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(2040, 2059), [
+ DeclScope_Global(StrRegion(2040, 2046)),
+ DeclType_List(StrRegion(2046, 2048)),
+ DeclItemsList(StrRegion(2049, 2059), [
+ DeclItemNode(StrRegion(2049, 2059), [
+ IdentNode(StrRegion(2049, 2054)),
+ ListNode(StrRegion(2057, 2059), [])
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(2061, 2086), [
+ DeclScope_Global(StrRegion(2061, 2067)),
+ DeclType_Variable(StrRegion(2067, 2067)),
+ DeclItemsList(StrRegion(2068, 2086), [
+ DeclItemNode(StrRegion(2068, 2086), [
+ IdentNode(StrRegion(2068, 2078)),
+ IdentNode(StrRegion(2081, 2086))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(2436, 2448), [
+ IdentNode(StrRegion(2440, 2443)),
+ ArgsDeclNode(StrRegion(2443, 2445), []),
+ BlockNode(StrRegion(2446, 2448), [])
+ ]),
+ DefineNode(StrRegion(2450, 2600), [
+ IdentNode(StrRegion(2454, 2461)),
+ ArgsDeclNode(StrRegion(2461, 2463), []),
+ BlockNode(StrRegion(2464, 2600), [
+ CallNode(StrRegion(2470, 2480), [
+ IdentNode(StrRegion(2470, 2478)),
+ CallArgs(StrRegion(2478, 2480), [])
+ ]),
+ ConditionalBlock(StrRegion(2504, 2568), [
+ IfBlock(StrRegion(2504, 2568), [
+ EqNode(StrRegion(2507, 2525), [
+ IdentNode(StrRegion(2507, 2517)),
+ IdentNode(StrRegion(2521, 2525))
+ ]),
+ BlockNode(StrRegion(2526, 2568), [
+ CallNode(StrRegion(2536, 2561), [
+ IdentNode(StrRegion(2536, 2542)),
+ CallArgs(StrRegion(2542, 2561), [
+ GetitemNode(StrRegion(2543, 2560), [
+ IdentNode(StrRegion(2543, 2548)),
+ IdentNode(StrRegion(2549, 2559))
+ ])
+ ])
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(2567, 2568))
+ ]),
+ CallNode(StrRegion(2573, 2597), [
+ IdentNode(StrRegion(2573, 2585)),
+ CallArgs(StrRegion(2585, 2597), [
+ IdentNode(StrRegion(2586, 2596))
+ ])
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(2602, 2768), [
+ IdentNode(StrRegion(2606, 2613)),
+ ArgsDeclNode(StrRegion(2613, 2615), []),
+ BlockNode(StrRegion(2616, 2768), [
+ CallNode(StrRegion(2622, 2632), [
+ IdentNode(StrRegion(2622, 2630)),
+ CallArgs(StrRegion(2630, 2632), [])
+ ]),
+ DeclNode(StrRegion(2638, 2662), [
+ DeclScope_Let(StrRegion(2638, 2641)),
+ DeclType_Variable(StrRegion(2641, 2641)),
+ DeclItemsList(StrRegion(2642, 2662), [
+ DeclItemNode(StrRegion(2642, 2662), [
+ IdentNode(StrRegion(2642, 2649)),
+ IdentNode(StrRegion(2652, 2662))
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(2668, 2693), [
+ DeclScope_Let(StrRegion(2668, 2671)),
+ DeclType_Variable(StrRegion(2671, 2671)),
+ DeclItemsList(StrRegion(2672, 2693), [
+ DeclItemNode(StrRegion(2672, 2693), [
+ IdentNode(StrRegion(2672, 2676)),
+ GetitemNode(StrRegion(2679, 2693), [
+ IdentNode(StrRegion(2679, 2684)),
+ IdentNode(StrRegion(2685, 2692))
+ ])
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(2699, 2734), [
+ GetitemNode(StrRegion(2699, 2713), [
+ IdentNode(StrRegion(2699, 2704)),
+ IdentNode(StrRegion(2705, 2712))
+ ]),
+ GetitemNode(StrRegion(2716, 2734), [
+ IdentNode(StrRegion(2716, 2721)),
+ SubNode(StrRegion(2722, 2733), [
+ IdentNode(StrRegion(2722, 2729)),
+ NumberNode(StrRegion(2732, 2733))
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(2740, 2765), [
+ GetitemNode(StrRegion(2740, 2758), [
+ IdentNode(StrRegion(2740, 2745)),
+ SubNode(StrRegion(2746, 2757), [
+ IdentNode(StrRegion(2746, 2753)),
+ NumberNode(StrRegion(2756, 2757))
+ ])
+ ]),
+ IdentNode(StrRegion(2761, 2765))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(2770, 3096), [
+ IdentNode(StrRegion(2774, 2783)),
+ ArgsDeclNode(StrRegion(2783, 2785), []),
+ BlockNode(StrRegion(2786, 3096), [
+ CallNode(StrRegion(2905, 2915), [
+ IdentNode(StrRegion(2905, 2913)),
+ CallArgs(StrRegion(2913, 2915), [])
+ ]),
+ DeclNode(StrRegion(2921, 2945), [
+ DeclScope_Let(StrRegion(2921, 2924)),
+ DeclType_Variable(StrRegion(2924, 2924)),
+ DeclItemsList(StrRegion(2925, 2945), [
+ DeclItemNode(StrRegion(2925, 2945), [
+ IdentNode(StrRegion(2925, 2932)),
+ IdentNode(StrRegion(2935, 2945))
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(2951, 2976), [
+ DeclScope_Let(StrRegion(2951, 2954)),
+ DeclType_Variable(StrRegion(2954, 2954)),
+ DeclItemsList(StrRegion(2955, 2976), [
+ DeclItemNode(StrRegion(2955, 2976), [
+ IdentNode(StrRegion(2955, 2959)),
+ GetitemNode(StrRegion(2962, 2976), [
+ IdentNode(StrRegion(2962, 2967)),
+ IdentNode(StrRegion(2968, 2975))
+ ])
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(2982, 3017), [
+ GetitemNode(StrRegion(2982, 2996), [
+ IdentNode(StrRegion(2982, 2987)),
+ IdentNode(StrRegion(2988, 2995))
+ ]),
+ GetitemNode(StrRegion(2999, 3017), [
+ IdentNode(StrRegion(2999, 3004)),
+ SubNode(StrRegion(3005, 3016), [
+ IdentNode(StrRegion(3005, 3012)),
+ NumberNode(StrRegion(3015, 3016))
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(3023, 3062), [
+ GetitemNode(StrRegion(3023, 3041), [
+ IdentNode(StrRegion(3023, 3028)),
+ SubNode(StrRegion(3029, 3040), [
+ IdentNode(StrRegion(3029, 3036)),
+ NumberNode(StrRegion(3039, 3040))
+ ])
+ ]),
+ GetitemNode(StrRegion(3044, 3062), [
+ IdentNode(StrRegion(3044, 3049)),
+ SubNode(StrRegion(3050, 3061), [
+ IdentNode(StrRegion(3050, 3057)),
+ NumberNode(StrRegion(3060, 3061))
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(3068, 3093), [
+ GetitemNode(StrRegion(3068, 3086), [
+ IdentNode(StrRegion(3068, 3073)),
+ SubNode(StrRegion(3074, 3085), [
+ IdentNode(StrRegion(3074, 3081)),
+ NumberNode(StrRegion(3084, 3085))
+ ])
+ ]),
+ IdentNode(StrRegion(3089, 3093))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(3098, 3250), [
+ IdentNode(StrRegion(3102, 3109)),
+ ArgsDeclNode(StrRegion(3109, 3111), []),
+ BlockNode(StrRegion(3112, 3250), [
+ CallNode(StrRegion(3118, 3128), [
+ IdentNode(StrRegion(3118, 3126)),
+ CallArgs(StrRegion(3126, 3128), [])
+ ]),
+ DeclNode(StrRegion(3134, 3163), [
+ DeclScope_Let(StrRegion(3134, 3137)),
+ DeclType_Variable(StrRegion(3137, 3137)),
+ DeclItemsList(StrRegion(3138, 3163), [
+ DeclItemNode(StrRegion(3138, 3163), [
+ IdentNode(StrRegion(3138, 3143)),
+ GetitemNode(StrRegion(3146, 3163), [
+ IdentNode(StrRegion(3146, 3151)),
+ IdentNode(StrRegion(3152, 3162))
+ ])
+ ])
+ ])
+ ]),
+ CallNode(StrRegion(3169, 3189), [
+ IdentNode(StrRegion(3169, 3182)),
+ CallArgs(StrRegion(3182, 3189), [
+ IdentNode(StrRegion(3183, 3188))
+ ])
+ ]),
+ ConditionalBlock(StrRegion(3195, 3248), [
+ IfBlock(StrRegion(3195, 3248), [
+ NeqNode(StrRegion(3198, 3217), [
+ IdentNode(StrRegion(3198, 3208)),
+ IdentNode(StrRegion(3212, 3217))
+ ]),
+ BlockNode(StrRegion(3218, 3248), [
+ CallNode(StrRegion(3228, 3241), [
+ IdentNode(StrRegion(3228, 3234)),
+ CallArgs(StrRegion(3234, 3241), [
+ IdentNode(StrRegion(3235, 3240))
+ ])
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(3247, 3248))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(3252, 3531), [
+ IdentNode(StrRegion(3256, 3267)),
+ ArgsDeclNode(StrRegion(3267, 3269), []),
+ BlockNode(StrRegion(3270, 3531), [
+ CallNode(StrRegion(3276, 3286), [
+ IdentNode(StrRegion(3276, 3284)),
+ CallArgs(StrRegion(3284, 3286), [])
+ ]),
+ DeclNode(StrRegion(3292, 3316), [
+ DeclScope_Let(StrRegion(3292, 3295)),
+ DeclType_Variable(StrRegion(3295, 3295)),
+ DeclItemsList(StrRegion(3296, 3316), [
+ DeclItemNode(StrRegion(3296, 3316), [
+ IdentNode(StrRegion(3296, 3303)),
+ IdentNode(StrRegion(3306, 3316))
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(3322, 3347), [
+ DeclScope_Let(StrRegion(3322, 3325)),
+ DeclType_Variable(StrRegion(3325, 3325)),
+ DeclItemsList(StrRegion(3326, 3347), [
+ DeclItemNode(StrRegion(3326, 3347), [
+ IdentNode(StrRegion(3326, 3330)),
+ GetitemNode(StrRegion(3333, 3347), [
+ IdentNode(StrRegion(3333, 3338)),
+ IdentNode(StrRegion(3339, 3346))
+ ])
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(3353, 3382), [
+ DeclScope_Let(StrRegion(3353, 3356)),
+ DeclType_Variable(StrRegion(3356, 3356)),
+ DeclItemsList(StrRegion(3357, 3382), [
+ DeclItemNode(StrRegion(3357, 3382), [
+ IdentNode(StrRegion(3357, 3361)),
+ GetitemNode(StrRegion(3364, 3382), [
+ IdentNode(StrRegion(3364, 3369)),
+ SubNode(StrRegion(3370, 3381), [
+ IdentNode(StrRegion(3370, 3377)),
+ NumberNode(StrRegion(3380, 3381))
+ ])
+ ])
+ ])
+ ])
+ ]),
+ CallNode(StrRegion(3388, 3407), [
+ IdentNode(StrRegion(3388, 3401)),
+ CallArgs(StrRegion(3401, 3407), [
+ IdentNode(StrRegion(3402, 3406))
+ ])
+ ]),
+ CallNode(StrRegion(3413, 3432), [
+ IdentNode(StrRegion(3413, 3426)),
+ CallArgs(StrRegion(3426, 3432), [
+ IdentNode(StrRegion(3427, 3431))
+ ])
+ ]),
+ ConditionalBlock(StrRegion(3459, 3529), [
+ IfBlock(StrRegion(3459, 3529), [
+ NeqNode(StrRegion(3462, 3477), [
+ IdentNode(StrRegion(3462, 3472)),
+ NumberNode(StrRegion(3476, 3477))
+ ]),
+ BlockNode(StrRegion(3478, 3529), [
+ CallNode(StrRegion(3488, 3500), [
+ IdentNode(StrRegion(3488, 3494)),
+ CallArgs(StrRegion(3494, 3500), [
+ IdentNode(StrRegion(3495, 3499))
+ ])
+ ]),
+ CallNode(StrRegion(3510, 3522), [
+ IdentNode(StrRegion(3510, 3516)),
+ CallArgs(StrRegion(3516, 3522), [
+ IdentNode(StrRegion(3517, 3521))
+ ])
+ ])
+ ])
+ ]),
+ NullElseBlock(StrRegion(3528, 3529))
+ ])
+ ])
+ ]),
+ DefineNode(StrRegion(3533, 3864), [
+ IdentNode(StrRegion(3537, 3545)),
+ ArgsDeclNode(StrRegion(3545, 3547), []),
+ BlockNode(StrRegion(3548, 3864), [
+ CallNode(StrRegion(3628, 3638), [
+ IdentNode(StrRegion(3628, 3636)),
+ CallArgs(StrRegion(3636, 3638), [])
+ ]),
+ DeclNode(StrRegion(3644, 3668), [
+ DeclScope_Let(StrRegion(3644, 3647)),
+ DeclType_Variable(StrRegion(3647, 3647)),
+ DeclItemsList(StrRegion(3648, 3668), [
+ DeclItemNode(StrRegion(3648, 3668), [
+ IdentNode(StrRegion(3648, 3655)),
+ IdentNode(StrRegion(3658, 3668))
+ ])
+ ])
+ ]),
+ DeclNode(StrRegion(3674, 3699), [
+ DeclScope_Let(StrRegion(3674, 3677)),
+ DeclType_Variable(StrRegion(3677, 3677)),
+ DeclItemsList(StrRegion(3678, 3699), [
+ DeclItemNode(StrRegion(3678, 3699), [
+ IdentNode(StrRegion(3678, 3682)),
+ GetitemNode(StrRegion(3685, 3699), [
+ IdentNode(StrRegion(3685, 3690)),
+ IdentNode(StrRegion(3691, 3698))
+ ])
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(3705, 3740), [
+ GetitemNode(StrRegion(3705, 3719), [
+ IdentNode(StrRegion(3705, 3710)),
+ IdentNode(StrRegion(3711, 3718))
+ ]),
+ GetitemNode(StrRegion(3722, 3740), [
+ IdentNode(StrRegion(3722, 3727)),
+ SubNode(StrRegion(3728, 3739), [
+ IdentNode(StrRegion(3728, 3735)),
+ NumberNode(StrRegion(3738, 3739))
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(3746, 3785), [
+ GetitemNode(StrRegion(3746, 3764), [
+ IdentNode(StrRegion(3746, 3751)),
+ SubNode(StrRegion(3752, 3763), [
+ IdentNode(StrRegion(3752, 3759)),
+ NumberNode(StrRegion(3762, 3763))
+ ])
+ ]),
+ GetitemNode(StrRegion(3767, 3785), [
+ IdentNode(StrRegion(3767, 3772)),
+ SubNode(StrRegion(3773, 3784), [
+ IdentNode(StrRegion(3773, 3780)),
+ NumberNode(StrRegion(3783, 3784))
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(3791, 3830), [
+ GetitemNode(StrRegion(3791, 3809), [
+ IdentNode(StrRegion(3791, 3796)),
+ SubNode(StrRegion(3797, 3808), [
+ IdentNode(StrRegion(3797, 3804)),
+ NumberNode(StrRegion(3807, 3808))
+ ])
+ ]),
+ GetitemNode(StrRegion(3812, 3830), [
+ IdentNode(StrRegion(3812, 3817)),
+ SubNode(StrRegion(3818, 3829), [
+ IdentNode(StrRegion(3818, 3825)),
+ NumberNode(StrRegion(3828, 3829))
+ ])
+ ])
+ ]),
+ AssignNode(StrRegion(3836, 3861), [
+ GetitemNode(StrRegion(3836, 3854), [
+ IdentNode(StrRegion(3836, 3841)),
+ SubNode(StrRegion(3842, 3853), [
+ IdentNode(StrRegion(3842, 3849)),
+ NumberNode(StrRegion(3852, 3853))
+ ])
+ ]),
+ IdentNode(StrRegion(3857, 3861))
+ ])
+ ])
+ ])
+])
+AstProgramNode(StrRegion(0, 3864),
+ [
+ AstDeclNode(StrRegion(0, 16),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(7, 12), 'false'),
+ AstNumber(StrRegion(15, 16), 0)
+ ),
+ AstDeclNode(StrRegion(18, 33),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(25, 29), 'true'),
+ AstNumber(StrRegion(32, 33), 1)
+ ),
+ AstDefine(StrRegion(62, 87),
+ AstIdent(StrRegion(66, 69), 'len'),
+ [
+ (
+ AstIdent(StrRegion(78, 81), 'val'),
+ AstIdent(StrRegion(82, 83), 'a')
+ )
+ ],
+ []
+ ),
+ AstDefine(StrRegion(101, 142),
+ AstIdent(StrRegion(105, 112), 'delitem'),
+ [
+ (
+ AstIdent(StrRegion(121, 124), 'val'),
+ AstIdent(StrRegion(125, 126), 'a')
+ ),
+ (
+ AstIdent(StrRegion(128, 134), 'number'),
+ AstIdent(StrRegion(135, 138), 'idx')
+ )
+ ],
+ []
+ ),
+ AstDeclNode(StrRegion(144, 164),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(153, 159), 'psHeap'),
+ AstListLiteral(StrRegion(162, 164),
+ []
+ )
+ ),
+ AstDeclNode(StrRegion(166, 196),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(175, 191), '_psHeap_freelist'),
+ AstListLiteral(StrRegion(194, 196),
+ []
+ )
+ ),
+ AstDefine(StrRegion(199, 294),
+ AstIdent(StrRegion(203, 222), '_PsHeap_FinalizeObj'),
+ [
+ (
+ AstIdent(StrRegion(223, 229), 'number'),
+ AstIdent(StrRegion(230, 233), 'ptr')
+ )
+ ],
+ []
+ ),
+ AstDeclNode(StrRegion(296, 313),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(303, 313), '__result__'),
+ None
+ ),
+ AstDefine(StrRegion(355, 793),
+ AstIdent(StrRegion(359, 375), 'PsHeap_AllocWord'),
+ [],
+ [
+ AstCall(StrRegion(384, 407),
+ AstIdent(StrRegion(384, 405), '_psHeap_freelist__len'),
+ []
+ ),
+ AstIf(StrRegion(413, 791),
+ AstBinOp(StrRegion(416, 430),
+ '>',
+ AstIdent(StrRegion(416, 426), '__result__'),
+ AstNumber(StrRegion(429, 430), 0)
+ ),
+ [
+ AstAssign(StrRegion(441, 473),
+ AstIdent(StrRegion(441, 451), '__result__'),
+ AstItem(StrRegion(454, 473),
+ AstIdent(StrRegion(454, 470), '_psHeap_freelist'),
+ AstNumber(StrRegion(471, 472), 0)
+ )
+ ),
+ AstCall(StrRegion(483, 511),
+ AstIdent(StrRegion(483, 508), '_psHeap_freelist__delitem'),
+ [
+ AstNumber(StrRegion(509, 510), 0)
+ ]
+ ),
+ AstIf(StrRegion(521, 589),
+ AstBinOp(StrRegion(524, 539),
+ '!=',
+ AstIdent(StrRegion(524, 534), 'COUNT_REFS'),
+ AstNumber(StrRegion(538, 539), 0)
+ ),
+ [
+ AstAssign(StrRegion(554, 578),
+ AstItem(StrRegion(554, 574),
+ AstIdent(StrRegion(554, 562), 'refStack'),
+ AstIdent(StrRegion(563, 573), '__result__')
+ ),
+ AstNumber(StrRegion(577, 578), 1)
+ )
+ ]
+ )
+ ],
+ [
+ AstCall(StrRegion(651, 669),
+ AstIdent(StrRegion(651, 665), 'psHeap__append'),
+ [
+ AstString(StrRegion(666, 668), '')
+ ]
+ ),
+ AstCall(StrRegion(679, 692),
+ AstIdent(StrRegion(679, 690), 'psHeap__len'),
+ []
+ ),
+ AstIf(StrRegion(722, 785),
+ AstBinOp(StrRegion(725, 740),
+ '!=',
+ AstIdent(StrRegion(725, 735), 'COUNT_REFS'),
+ AstNumber(StrRegion(739, 740), 0)
+ ),
+ [
+ AstCall(StrRegion(755, 774),
+ AstIdent(StrRegion(755, 771), 'refStack__append'),
+ [
+ AstNumber(StrRegion(772, 773), 1)
+ ]
+ )
+ ]
+ )
+ ]
+ )
+ ]
+ ),
+ AstDefine(StrRegion(825, 1016),
+ AstIdent(StrRegion(829, 844), 'PsHeap_FreeWord'),
+ [
+ (
+ AstIdent(StrRegion(845, 851), 'number'),
+ AstIdent(StrRegion(852, 855), 'ptr')
+ )
+ ],
+ [
+ AstAssign(StrRegion(863, 879),
+ AstItem(StrRegion(863, 874),
+ AstIdent(StrRegion(863, 869), 'psHeap'),
+ AstIdent(StrRegion(870, 873), 'ptr')
+ ),
+ AstString(StrRegion(877, 879), '')
+ ),
+ AstIf(StrRegion(926, 979),
+ AstBinOp(StrRegion(929, 944),
+ '!=',
+ AstIdent(StrRegion(929, 939), 'COUNT_REFS'),
+ AstNumber(StrRegion(943, 944), 0)
+ ),
+ [
+ AstAssign(StrRegion(955, 972),
+ AstItem(StrRegion(955, 968),
+ AstIdent(StrRegion(955, 963), 'refStack'),
+ AstIdent(StrRegion(964, 967), 'ptr')
+ ),
+ AstNumber(StrRegion(971, 972), 0)
+ )
+ ]
+ ),
+ AstCall(StrRegion(984, 1013),
+ AstIdent(StrRegion(984, 1008), '_psHeap_freelist__append'),
+ [
+ AstIdent(StrRegion(1009, 1012), 'ptr')
+ ]
+ )
+ ]
+ ),
+ AstDefine(StrRegion(1017, 1110),
+ AstIdent(StrRegion(1021, 1038), 'PsHeap_DeleteWord'),
+ [
+ (
+ AstIdent(StrRegion(1039, 1045), 'number'),
+ AstIdent(StrRegion(1046, 1049), 'ptr')
+ )
+ ],
+ [
+ AstCall(StrRegion(1057, 1081),
+ AstIdent(StrRegion(1057, 1076), '_PsHeap_FinalizeObj'),
+ [
+ AstIdent(StrRegion(1077, 1080), 'ptr')
+ ]
+ ),
+ AstCall(StrRegion(1087, 1107),
+ AstIdent(StrRegion(1087, 1102), 'PsHeap_FreeWord'),
+ [
+ AstIdent(StrRegion(1103, 1106), 'ptr')
+ ]
+ )
+ ]
+ ),
+ AstDeclNode(StrRegion(1112, 1134),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(1121, 1129), 'refStack'),
+ AstListLiteral(StrRegion(1132, 1134),
+ []
+ )
+ ),
+ AstDefine(StrRegion(1156, 1186),
+ AstIdent(StrRegion(1160, 1176), 'refStack__append'),
+ [
+ (
+ AstIdent(StrRegion(1177, 1180), 'val'),
+ AstIdent(StrRegion(1181, 1182), 'x')
+ )
+ ],
+ []
+ ),
+ AstDefine(StrRegion(1207, 1234),
+ AstIdent(StrRegion(1211, 1224), 'stack__append'),
+ [
+ (
+ AstIdent(StrRegion(1225, 1228), 'val'),
+ AstIdent(StrRegion(1229, 1230), 'x')
+ )
+ ],
+ []
+ ),
+ AstDefine(StrRegion(1255, 1272),
+ AstIdent(StrRegion(1259, 1267), 'lenStack'),
+ [],
+ []
+ ),
+ AstDefine(StrRegion(1293, 1319),
+ AstIdent(StrRegion(1297, 1309), 'stackDelitem'),
+ [
+ (
+ AstIdent(StrRegion(1310, 1313), 'val'),
+ AstIdent(StrRegion(1314, 1315), 'x')
+ )
+ ],
+ []
+ ),
+ AstDefine(StrRegion(1340, 1368),
+ AstIdent(StrRegion(1344, 1358), 'psHeap__append'),
+ [
+ (
+ AstIdent(StrRegion(1359, 1362), 'val'),
+ AstIdent(StrRegion(1363, 1364), 'x')
+ )
+ ],
+ []
+ ),
+ AstDefine(StrRegion(1389, 1427),
+ AstIdent(StrRegion(1393, 1417), '_psHeap_freelist__append'),
+ [
+ (
+ AstIdent(StrRegion(1418, 1421), 'val'),
+ AstIdent(StrRegion(1422, 1423), 'x')
+ )
+ ],
+ []
+ ),
+ AstDefine(StrRegion(1448, 1487),
+ AstIdent(StrRegion(1452, 1477), '_psHeap_freelist__delitem'),
+ [
+ (
+ AstIdent(StrRegion(1478, 1481), 'val'),
+ AstIdent(StrRegion(1482, 1483), 'x')
+ )
+ ],
+ []
+ ),
+ AstDefine(StrRegion(1508, 1538),
+ AstIdent(StrRegion(1512, 1533), '_psHeap_freelist__len'),
+ [],
+ []
+ ),
+ AstDefine(StrRegion(1559, 1579),
+ AstIdent(StrRegion(1563, 1574), 'psHeap__len'),
+ [],
+ []
+ ),
+ AstDefine(StrRegion(1581, 1811),
+ AstIdent(StrRegion(1585, 1591), 'decref'),
+ [
+ (
+ AstIdent(StrRegion(1592, 1598), 'number'),
+ AstIdent(StrRegion(1599, 1602), 'ptr')
+ )
+ ],
+ [
+ AstIf(StrRegion(1610, 1809),
+ AstBinOp(StrRegion(1613, 1631),
+ '>=',
+ AstItem(StrRegion(1613, 1626),
+ AstIdent(StrRegion(1613, 1621), 'refStack'),
+ AstIdent(StrRegion(1622, 1625), 'ptr')
+ ),
+ AstNumber(StrRegion(1630, 1631), 0)
+ ),
+ [
+ AstAssign(StrRegion(1691, 1724),
+ AstItem(StrRegion(1691, 1704),
+ AstIdent(StrRegion(1691, 1699), 'refStack'),
+ AstIdent(StrRegion(1700, 1703), 'ptr')
+ ),
+ AstBinOp(StrRegion(1707, 1724),
+ '-',
+ AstItem(StrRegion(1707, 1720),
+ AstIdent(StrRegion(1707, 1715), 'refStack'),
+ AstIdent(StrRegion(1716, 1719), 'ptr')
+ ),
+ AstNumber(StrRegion(1723, 1724), 1)
+ )
+ ),
+ AstIf(StrRegion(1734, 1803),
+ AstBinOp(StrRegion(1737, 1755),
+ '==',
+ AstItem(StrRegion(1737, 1750),
+ AstIdent(StrRegion(1737, 1745), 'refStack'),
+ AstIdent(StrRegion(1746, 1749), 'ptr')
+ ),
+ AstNumber(StrRegion(1754, 1755), 0)
+ ),
+ [
+ AstCall(StrRegion(1770, 1792),
+ AstIdent(StrRegion(1770, 1787), 'PsHeap_DeleteWord'),
+ [
+ AstIdent(StrRegion(1788, 1791), 'ptr')
+ ]
+ )
+ ]
+ )
+ ]
+ )
+ ]
+ ),
+ AstDefine(StrRegion(1812, 2002),
+ AstIdent(StrRegion(1816, 1822), 'incref'),
+ [
+ (
+ AstIdent(StrRegion(1823, 1829), 'number'),
+ AstIdent(StrRegion(1830, 1833), 'ptr')
+ )
+ ],
+ [
+ AstIf(StrRegion(1841, 2000),
+ AstBinOp(StrRegion(1844, 1862),
+ '>=',
+ AstItem(StrRegion(1844, 1857),
+ AstIdent(StrRegion(1844, 1852), 'refStack'),
+ AstIdent(StrRegion(1853, 1856), 'ptr')
+ ),
+ AstNumber(StrRegion(1861, 1862), 0)
+ ),
+ [
+ AstAssign(StrRegion(1922, 1955),
+ AstItem(StrRegion(1922, 1935),
+ AstIdent(StrRegion(1922, 1930), 'refStack'),
+ AstIdent(StrRegion(1931, 1934), 'ptr')
+ ),
+ AstBinOp(StrRegion(1938, 1955),
+ '+',
+ AstItem(StrRegion(1938, 1951),
+ AstIdent(StrRegion(1938, 1946), 'refStack'),
+ AstIdent(StrRegion(1947, 1950), 'ptr')
+ ),
+ AstNumber(StrRegion(1954, 1955), 1)
+ )
+ )
+ ]
+ )
+ ]
+ ),
+ AstDeclNode(StrRegion(2040, 2059),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(2049, 2054), 'stack'),
+ AstListLiteral(StrRegion(2057, 2059),
+ []
+ )
+ ),
+ AstDeclNode(StrRegion(2061, 2086),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2068, 2078), 'COUNT_REFS'),
+ AstIdent(StrRegion(2081, 2086), 'false')
+ ),
+ AstDefine(StrRegion(2436, 2448),
+ AstIdent(StrRegion(2440, 2443), 'NOP'),
+ [],
+ []
+ ),
+ AstDefine(StrRegion(2450, 2600),
+ AstIdent(StrRegion(2454, 2461), 'POP_TOP'),
+ [],
+ [
+ AstCall(StrRegion(2470, 2480),
+ AstIdent(StrRegion(2470, 2478), 'lenStack'),
+ []
+ ),
+ AstIf(StrRegion(2504, 2568),
+ AstBinOp(StrRegion(2507, 2525),
+ '==',
+ AstIdent(StrRegion(2507, 2517), 'COUNT_REFS'),
+ AstIdent(StrRegion(2521, 2525), 'true')
+ ),
+ [
+ AstCall(StrRegion(2536, 2561),
+ AstIdent(StrRegion(2536, 2542), 'decref'),
+ [
+ AstItem(StrRegion(2543, 2560),
+ AstIdent(StrRegion(2543, 2548), 'stack'),
+ AstIdent(StrRegion(2549, 2559), '__result__')
+ )
+ ]
+ )
+ ]
+ ),
+ AstCall(StrRegion(2573, 2597),
+ AstIdent(StrRegion(2573, 2585), 'stackDelitem'),
+ [
+ AstIdent(StrRegion(2586, 2596), '__result__')
+ ]
+ )
+ ]
+ ),
+ AstDefine(StrRegion(2602, 2768),
+ AstIdent(StrRegion(2606, 2613), 'ROT_TWO'),
+ [],
+ [
+ AstCall(StrRegion(2622, 2632),
+ AstIdent(StrRegion(2622, 2630), 'lenStack'),
+ []
+ ),
+ AstDeclNode(StrRegion(2638, 2662),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2642, 2649), 'tos_idx'),
+ AstIdent(StrRegion(2652, 2662), '__result__')
+ ),
+ AstDeclNode(StrRegion(2668, 2693),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2672, 2676), 'tos0'),
+ AstItem(StrRegion(2679, 2693),
+ AstIdent(StrRegion(2679, 2684), 'stack'),
+ AstIdent(StrRegion(2685, 2692), 'tos_idx')
+ )
+ ),
+ AstAssign(StrRegion(2699, 2734),
+ AstItem(StrRegion(2699, 2713),
+ AstIdent(StrRegion(2699, 2704), 'stack'),
+ AstIdent(StrRegion(2705, 2712), 'tos_idx')
+ ),
+ AstItem(StrRegion(2716, 2734),
+ AstIdent(StrRegion(2716, 2721), 'stack'),
+ AstBinOp(StrRegion(2722, 2733),
+ '-',
+ AstIdent(StrRegion(2722, 2729), 'tos_idx'),
+ AstNumber(StrRegion(2732, 2733), 1)
+ )
+ )
+ ),
+ AstAssign(StrRegion(2740, 2765),
+ AstItem(StrRegion(2740, 2758),
+ AstIdent(StrRegion(2740, 2745), 'stack'),
+ AstBinOp(StrRegion(2746, 2757),
+ '-',
+ AstIdent(StrRegion(2746, 2753), 'tos_idx'),
+ AstNumber(StrRegion(2756, 2757), 1)
+ )
+ ),
+ AstIdent(StrRegion(2761, 2765), 'tos0')
+ )
+ ]
+ ),
+ AstDefine(StrRegion(2770, 3096),
+ AstIdent(StrRegion(2774, 2783), 'ROT_THREE'),
+ [],
+ [
+ AstCall(StrRegion(2905, 2915),
+ AstIdent(StrRegion(2905, 2913), 'lenStack'),
+ []
+ ),
+ AstDeclNode(StrRegion(2921, 2945),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2925, 2932), 'tos_idx'),
+ AstIdent(StrRegion(2935, 2945), '__result__')
+ ),
+ AstDeclNode(StrRegion(2951, 2976),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2955, 2959), 'tos0'),
+ AstItem(StrRegion(2962, 2976),
+ AstIdent(StrRegion(2962, 2967), 'stack'),
+ AstIdent(StrRegion(2968, 2975), 'tos_idx')
+ )
+ ),
+ AstAssign(StrRegion(2982, 3017),
+ AstItem(StrRegion(2982, 2996),
+ AstIdent(StrRegion(2982, 2987), 'stack'),
+ AstIdent(StrRegion(2988, 2995), 'tos_idx')
+ ),
+ AstItem(StrRegion(2999, 3017),
+ AstIdent(StrRegion(2999, 3004), 'stack'),
+ AstBinOp(StrRegion(3005, 3016),
+ '-',
+ AstIdent(StrRegion(3005, 3012), 'tos_idx'),
+ AstNumber(StrRegion(3015, 3016), 1)
+ )
+ )
+ ),
+ AstAssign(StrRegion(3023, 3062),
+ AstItem(StrRegion(3023, 3041),
+ AstIdent(StrRegion(3023, 3028), 'stack'),
+ AstBinOp(StrRegion(3029, 3040),
+ '-',
+ AstIdent(StrRegion(3029, 3036), 'tos_idx'),
+ AstNumber(StrRegion(3039, 3040), 1)
+ )
+ ),
+ AstItem(StrRegion(3044, 3062),
+ AstIdent(StrRegion(3044, 3049), 'stack'),
+ AstBinOp(StrRegion(3050, 3061),
+ '-',
+ AstIdent(StrRegion(3050, 3057), 'tos_idx'),
+ AstNumber(StrRegion(3060, 3061), 2)
+ )
+ )
+ ),
+ AstAssign(StrRegion(3068, 3093),
+ AstItem(StrRegion(3068, 3086),
+ AstIdent(StrRegion(3068, 3073), 'stack'),
+ AstBinOp(StrRegion(3074, 3085),
+ '-',
+ AstIdent(StrRegion(3074, 3081), 'tos_idx'),
+ AstNumber(StrRegion(3084, 3085), 2)
+ )
+ ),
+ AstIdent(StrRegion(3089, 3093), 'tos0')
+ )
+ ]
+ ),
+ AstDefine(StrRegion(3098, 3250),
+ AstIdent(StrRegion(3102, 3109), 'DUP_TOP'),
+ [],
+ [
+ AstCall(StrRegion(3118, 3128),
+ AstIdent(StrRegion(3118, 3126), 'lenStack'),
+ []
+ ),
+ AstDeclNode(StrRegion(3134, 3163),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3138, 3143), 'value'),
+ AstItem(StrRegion(3146, 3163),
+ AstIdent(StrRegion(3146, 3151), 'stack'),
+ AstIdent(StrRegion(3152, 3162), '__result__')
+ )
+ ),
+ AstCall(StrRegion(3169, 3189),
+ AstIdent(StrRegion(3169, 3182), 'stack__append'),
+ [
+ AstIdent(StrRegion(3183, 3188), 'value')
+ ]
+ ),
+ AstIf(StrRegion(3195, 3248),
+ AstBinOp(StrRegion(3198, 3217),
+ '!=',
+ AstIdent(StrRegion(3198, 3208), 'COUNT_REFS'),
+ AstIdent(StrRegion(3212, 3217), 'false')
+ ),
+ [
+ AstCall(StrRegion(3228, 3241),
+ AstIdent(StrRegion(3228, 3234), 'incref'),
+ [
+ AstIdent(StrRegion(3235, 3240), 'value')
+ ]
+ )
+ ]
+ )
+ ]
+ ),
+ AstDefine(StrRegion(3252, 3531),
+ AstIdent(StrRegion(3256, 3267), 'DUP_TOP_TWO'),
+ [],
+ [
+ AstCall(StrRegion(3276, 3286),
+ AstIdent(StrRegion(3276, 3284), 'lenStack'),
+ []
+ ),
+ AstDeclNode(StrRegion(3292, 3316),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3296, 3303), 'tos_idx'),
+ AstIdent(StrRegion(3306, 3316), '__result__')
+ ),
+ AstDeclNode(StrRegion(3322, 3347),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3326, 3330), 'tos0'),
+ AstItem(StrRegion(3333, 3347),
+ AstIdent(StrRegion(3333, 3338), 'stack'),
+ AstIdent(StrRegion(3339, 3346), 'tos_idx')
+ )
+ ),
+ AstDeclNode(StrRegion(3353, 3382),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3357, 3361), 'tos1'),
+ AstItem(StrRegion(3364, 3382),
+ AstIdent(StrRegion(3364, 3369), 'stack'),
+ AstBinOp(StrRegion(3370, 3381),
+ '-',
+ AstIdent(StrRegion(3370, 3377), 'tos_idx'),
+ AstNumber(StrRegion(3380, 3381), 1)
+ )
+ )
+ ),
+ AstCall(StrRegion(3388, 3407),
+ AstIdent(StrRegion(3388, 3401), 'stack__append'),
+ [
+ AstIdent(StrRegion(3402, 3406), 'tos1')
+ ]
+ ),
+ AstCall(StrRegion(3413, 3432),
+ AstIdent(StrRegion(3413, 3426), 'stack__append'),
+ [
+ AstIdent(StrRegion(3427, 3431), 'tos0')
+ ]
+ ),
+ AstIf(StrRegion(3459, 3529),
+ AstBinOp(StrRegion(3462, 3477),
+ '!=',
+ AstIdent(StrRegion(3462, 3472), 'COUNT_REFS'),
+ AstNumber(StrRegion(3476, 3477), 0)
+ ),
+ [
+ AstCall(StrRegion(3488, 3500),
+ AstIdent(StrRegion(3488, 3494), 'incref'),
+ [
+ AstIdent(StrRegion(3495, 3499), 'tos0')
+ ]
+ ),
+ AstCall(StrRegion(3510, 3522),
+ AstIdent(StrRegion(3510, 3516), 'incref'),
+ [
+ AstIdent(StrRegion(3517, 3521), 'tos1')
+ ]
+ )
+ ]
+ )
+ ]
+ ),
+ AstDefine(StrRegion(3533, 3864),
+ AstIdent(StrRegion(3537, 3545), 'ROT_FOUR'),
+ [],
+ [
+ AstCall(StrRegion(3628, 3638),
+ AstIdent(StrRegion(3628, 3636), 'lenStack'),
+ []
+ ),
+ AstDeclNode(StrRegion(3644, 3668),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3648, 3655), 'tos_idx'),
+ AstIdent(StrRegion(3658, 3668), '__result__')
+ ),
+ AstDeclNode(StrRegion(3674, 3699),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3678, 3682), 'tos0'),
+ AstItem(StrRegion(3685, 3699),
+ AstIdent(StrRegion(3685, 3690), 'stack'),
+ AstIdent(StrRegion(3691, 3698), 'tos_idx')
+ )
+ ),
+ AstAssign(StrRegion(3705, 3740),
+ AstItem(StrRegion(3705, 3719),
+ AstIdent(StrRegion(3705, 3710), 'stack'),
+ AstIdent(StrRegion(3711, 3718), 'tos_idx')
+ ),
+ AstItem(StrRegion(3722, 3740),
+ AstIdent(StrRegion(3722, 3727), 'stack'),
+ AstBinOp(StrRegion(3728, 3739),
+ '-',
+ AstIdent(StrRegion(3728, 3735), 'tos_idx'),
+ AstNumber(StrRegion(3738, 3739), 1)
+ )
+ )
+ ),
+ AstAssign(StrRegion(3746, 3785),
+ AstItem(StrRegion(3746, 3764),
+ AstIdent(StrRegion(3746, 3751), 'stack'),
+ AstBinOp(StrRegion(3752, 3763),
+ '-',
+ AstIdent(StrRegion(3752, 3759), 'tos_idx'),
+ AstNumber(StrRegion(3762, 3763), 1)
+ )
+ ),
+ AstItem(StrRegion(3767, 3785),
+ AstIdent(StrRegion(3767, 3772), 'stack'),
+ AstBinOp(StrRegion(3773, 3784),
+ '-',
+ AstIdent(StrRegion(3773, 3780), 'tos_idx'),
+ AstNumber(StrRegion(3783, 3784), 2)
+ )
+ )
+ ),
+ AstAssign(StrRegion(3791, 3830),
+ AstItem(StrRegion(3791, 3809),
+ AstIdent(StrRegion(3791, 3796), 'stack'),
+ AstBinOp(StrRegion(3797, 3808),
+ '-',
+ AstIdent(StrRegion(3797, 3804), 'tos_idx'),
+ AstNumber(StrRegion(3807, 3808), 2)
+ )
+ ),
+ AstItem(StrRegion(3812, 3830),
+ AstIdent(StrRegion(3812, 3817), 'stack'),
+ AstBinOp(StrRegion(3818, 3829),
+ '-',
+ AstIdent(StrRegion(3818, 3825), 'tos_idx'),
+ AstNumber(StrRegion(3828, 3829), 3)
+ )
+ )
+ ),
+ AstAssign(StrRegion(3836, 3861),
+ AstItem(StrRegion(3836, 3854),
+ AstIdent(StrRegion(3836, 3841), 'stack'),
+ AstBinOp(StrRegion(3842, 3853),
+ '-',
+ AstIdent(StrRegion(3842, 3849), 'tos_idx'),
+ AstNumber(StrRegion(3852, 3853), 3)
+ )
+ ),
+ AstIdent(StrRegion(3857, 3861), 'tos0')
+ )
+ ]
+ )
+ ]
+)
+Scope(
+ declared={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'DUP_TOP': FuncInfo(
+ decl_scope=,
+ ident='DUP_TOP',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={
+ 'value': NameInfo(
+ decl_scope=,
+ ident='value',
+ tp_info=ValType(),
+ is_param=False
+ )
+ },
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'false': NameInfo(
+ decl_scope=,
+ ident='false',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'incref': FuncInfo(
+ decl_scope=,
+ ident='incref',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'lenStack': FuncInfo(
+ decl_scope=,
+ ident='lenStack',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'stack': NameInfo(
+ decl_scope=,
+ ident='stack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'stack__append': FuncInfo(
+ decl_scope=,
+ ident='stack__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'value': NameInfo(
+ decl_scope=,
+ ident='value',
+ tp_info=ValType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'DUP_TOP_TWO': FuncInfo(
+ decl_scope=,
+ ident='DUP_TOP_TWO',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos1': NameInfo(
+ decl_scope=,
+ ident='tos1',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ },
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'incref': FuncInfo(
+ decl_scope=,
+ ident='incref',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'lenStack': FuncInfo(
+ decl_scope=,
+ ident='lenStack',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'stack': NameInfo(
+ decl_scope=,
+ ident='stack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'stack__append': FuncInfo(
+ decl_scope=,
+ ident='stack__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos1': NameInfo(
+ decl_scope=,
+ ident='tos1',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'NOP': FuncInfo(
+ decl_scope=,
+ ident='NOP',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'POP_TOP': FuncInfo(
+ decl_scope=,
+ ident='POP_TOP',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'decref': FuncInfo(
+ decl_scope=,
+ ident='decref',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'PsHeap_DeleteWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_DeleteWord',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'PsHeap_FreeWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_FreeWord',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '_psHeap_freelist__append': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'psHeap': NameInfo(
+ decl_scope=,
+ ident='psHeap',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ '_PsHeap_FinalizeObj': FuncInfo(
+ decl_scope=,
+ ident='_PsHeap_FinalizeObj',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ }
+ )
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'lenStack': FuncInfo(
+ decl_scope=,
+ ident='lenStack',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'stack': NameInfo(
+ decl_scope=,
+ ident='stack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'stackDelitem': FuncInfo(
+ decl_scope=,
+ ident='stackDelitem',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'true': NameInfo(
+ decl_scope=,
+ ident='true',
+ tp_info=ValType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'PsHeap_AllocWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_AllocWord',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '_psHeap_freelist': NameInfo(
+ decl_scope=,
+ ident='_psHeap_freelist',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ '_psHeap_freelist__delitem': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__delitem',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ '_psHeap_freelist__len': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__len',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'psHeap__append': FuncInfo(
+ decl_scope=,
+ ident='psHeap__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'psHeap__len': FuncInfo(
+ decl_scope=,
+ ident='psHeap__len',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'refStack__append': FuncInfo(
+ decl_scope=,
+ ident='refStack__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ )
+ }
+ )
+ ),
+ 'PsHeap_DeleteWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_DeleteWord',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'PsHeap_FreeWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_FreeWord',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '_psHeap_freelist__append': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'psHeap': NameInfo(
+ decl_scope=,
+ ident='psHeap',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ '_PsHeap_FinalizeObj': FuncInfo(
+ decl_scope=,
+ ident='_PsHeap_FinalizeObj',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ }
+ )
+ ),
+ 'PsHeap_FreeWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_FreeWord',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '_psHeap_freelist__append': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'psHeap': NameInfo(
+ decl_scope=,
+ ident='psHeap',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'ROT_FOUR': FuncInfo(
+ decl_scope=,
+ ident='ROT_FOUR',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ },
+ used={
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'lenStack': FuncInfo(
+ decl_scope=,
+ ident='lenStack',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'stack': NameInfo(
+ decl_scope=,
+ ident='stack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'ROT_THREE': FuncInfo(
+ decl_scope=,
+ ident='ROT_THREE',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ },
+ used={
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'lenStack': FuncInfo(
+ decl_scope=,
+ ident='lenStack',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'stack': NameInfo(
+ decl_scope=,
+ ident='stack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'ROT_TWO': FuncInfo(
+ decl_scope=,
+ ident='ROT_TWO',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ },
+ used={
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'lenStack': FuncInfo(
+ decl_scope=,
+ ident='lenStack',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'stack': NameInfo(
+ decl_scope=,
+ ident='stack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'tos0': NameInfo(
+ decl_scope=,
+ ident='tos0',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'tos_idx': NameInfo(
+ decl_scope=,
+ ident='tos_idx',
+ tp_info=ValType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ '_PsHeap_FinalizeObj': FuncInfo(
+ decl_scope=,
+ ident='_PsHeap_FinalizeObj',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ '__result__': NameInfo(
+ decl_scope=,
+ ident='__result__',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '_psHeap_freelist': NameInfo(
+ decl_scope=,
+ ident='_psHeap_freelist',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ '_psHeap_freelist__append': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ '_psHeap_freelist__delitem': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__delitem',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ '_psHeap_freelist__len': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__len',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'decref': FuncInfo(
+ decl_scope=,
+ ident='decref',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'PsHeap_DeleteWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_DeleteWord',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'PsHeap_FreeWord': FuncInfo(
+ decl_scope=,
+ ident='PsHeap_FreeWord',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'COUNT_REFS': NameInfo(
+ decl_scope=,
+ ident='COUNT_REFS',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ '_psHeap_freelist__append': FuncInfo(
+ decl_scope=,
+ ident='_psHeap_freelist__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'psHeap': NameInfo(
+ decl_scope=,
+ ident='psHeap',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ '_PsHeap_FinalizeObj': FuncInfo(
+ decl_scope=,
+ ident='_PsHeap_FinalizeObj',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ }
+ )
+ ),
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'delitem': FuncInfo(
+ decl_scope=,
+ ident='delitem',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType(),
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='a',
+ tp=ValType()
+ ),
+ ParamInfo(
+ name='idx',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'a': NameInfo(
+ decl_scope=,
+ ident='a',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'idx': NameInfo(
+ decl_scope=,
+ ident='idx',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'false': NameInfo(
+ decl_scope=,
+ ident='false',
+ tp_info=ValType(),
+ is_param=False
+ ),
+ 'incref': FuncInfo(
+ decl_scope=,
+ ident='incref',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='ptr',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={
+ 'ptr': NameInfo(
+ decl_scope=,
+ ident='ptr',
+ tp_info=ValType(),
+ is_param=True
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ )
+ }
+ )
+ ),
+ 'len': FuncInfo(
+ decl_scope=,
+ ident='len',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='a',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'a': NameInfo(
+ decl_scope=,
+ ident='a',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'lenStack': FuncInfo(
+ decl_scope=,
+ ident='lenStack',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'psHeap': NameInfo(
+ decl_scope=,
+ ident='psHeap',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'psHeap__append': FuncInfo(
+ decl_scope=,
+ ident='psHeap__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'psHeap__len': FuncInfo(
+ decl_scope=,
+ ident='psHeap__len',
+ tp_info=FunctionType(
+ arg_types=[],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[],
+ subscope=Scope(
+ declared={},
+ used={}
+ )
+ ),
+ 'refStack': NameInfo(
+ decl_scope=,
+ ident='refStack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'refStack__append': FuncInfo(
+ decl_scope=,
+ ident='refStack__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'stack': NameInfo(
+ decl_scope=,
+ ident='stack',
+ tp_info=ListType(),
+ is_param=False
+ ),
+ 'stackDelitem': FuncInfo(
+ decl_scope=,
+ ident='stackDelitem',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'stack__append': FuncInfo(
+ decl_scope=,
+ ident='stack__append',
+ tp_info=FunctionType(
+ arg_types=[
+ ValType()
+ ],
+ ret_type=VoidType()
+ ),
+ is_param=False,
+ params_info=[
+ ParamInfo(
+ name='x',
+ tp=ValType()
+ )
+ ],
+ subscope=Scope(
+ declared={
+ 'x': NameInfo(
+ decl_scope=,
+ ident='x',
+ tp_info=ValType(),
+ is_param=True
+ )
+ },
+ used={}
+ )
+ ),
+ 'true': NameInfo(
+ decl_scope=,
+ ident='true',
+ tp_info=ValType(),
+ is_param=False
+ )
+ },
+ used={
+ 'false': NameInfo(
+ decl_scope=,
+ ident='false',
+ tp_info=ValType(),
+ is_param=False
+ )
+ }
+)
+AstProgramNode(StrRegion(0, 3864),
+ [
+ AstDeclNode(StrRegion(0, 16),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(7, 12), 'false', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(15, 16), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(18, 33),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(25, 29), 'true', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(32, 33), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(62, 87),
+ AstIdent(StrRegion(66, 69), 'len', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(78, 81), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(82, 83), 'a', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(101, 142),
+ AstIdent(StrRegion(105, 112), 'delitem', meta=TypeMetadata(type=FunctionType(arg_types=[ValType(), ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(121, 124), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(125, 126), 'a', meta=TypeMetadata(type=ValType()))
+ ),
+ (
+ AstIdent(StrRegion(128, 134), 'number', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(135, 138), 'idx', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(144, 164),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(153, 159), 'psHeap', meta=TypeMetadata(type=ListType())),
+ AstListLiteral(StrRegion(162, 164),
+ [],
+ meta=TypeMetadata(type=ListType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(166, 196),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(175, 191), '_psHeap_freelist', meta=TypeMetadata(type=ListType())),
+ AstListLiteral(StrRegion(194, 196),
+ [],
+ meta=TypeMetadata(type=ListType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(199, 294),
+ AstIdent(StrRegion(203, 222), '_PsHeap_FinalizeObj', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(223, 229), 'number', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(230, 233), 'ptr', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(296, 313),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(303, 313), '__result__', meta=TypeMetadata(type=ValType())),
+ None,
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(355, 793),
+ AstIdent(StrRegion(359, 375), 'PsHeap_AllocWord', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [
+ AstCall(StrRegion(384, 407),
+ AstIdent(StrRegion(384, 405), '_psHeap_freelist__len', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(413, 791),
+ AstBinOp(StrRegion(416, 430),
+ '>',
+ AstIdent(StrRegion(416, 426), '__result__', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(429, 430), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstAssign(StrRegion(441, 473),
+ AstIdent(StrRegion(441, 451), '__result__', meta=TypeMetadata(type=ValType())),
+ AstItem(StrRegion(454, 473),
+ AstIdent(StrRegion(454, 470), '_psHeap_freelist', meta=TypeMetadata(type=ListType())),
+ AstNumber(StrRegion(471, 472), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(483, 511),
+ AstIdent(StrRegion(483, 508), '_psHeap_freelist__delitem', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstNumber(StrRegion(509, 510), 0, meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(521, 589),
+ AstBinOp(StrRegion(524, 539),
+ '!=',
+ AstIdent(StrRegion(524, 534), 'COUNT_REFS', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(538, 539), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstAssign(StrRegion(554, 578),
+ AstItem(StrRegion(554, 574),
+ AstIdent(StrRegion(554, 562), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(563, 573), '__result__', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstNumber(StrRegion(577, 578), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ [
+ AstCall(StrRegion(651, 669),
+ AstIdent(StrRegion(651, 665), 'psHeap__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstString(StrRegion(666, 668), '', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(679, 692),
+ AstIdent(StrRegion(679, 690), 'psHeap__len', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(722, 785),
+ AstBinOp(StrRegion(725, 740),
+ '!=',
+ AstIdent(StrRegion(725, 735), 'COUNT_REFS', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(739, 740), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstCall(StrRegion(755, 774),
+ AstIdent(StrRegion(755, 771), 'refStack__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstNumber(StrRegion(772, 773), 1, meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(825, 1016),
+ AstIdent(StrRegion(829, 844), 'PsHeap_FreeWord', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(845, 851), 'number', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(852, 855), 'ptr', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [
+ AstAssign(StrRegion(863, 879),
+ AstItem(StrRegion(863, 874),
+ AstIdent(StrRegion(863, 869), 'psHeap', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(870, 873), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstString(StrRegion(877, 879), '', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(926, 979),
+ AstBinOp(StrRegion(929, 944),
+ '!=',
+ AstIdent(StrRegion(929, 939), 'COUNT_REFS', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(943, 944), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstAssign(StrRegion(955, 972),
+ AstItem(StrRegion(955, 968),
+ AstIdent(StrRegion(955, 963), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(964, 967), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstNumber(StrRegion(971, 972), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(984, 1013),
+ AstIdent(StrRegion(984, 1008), '_psHeap_freelist__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(1009, 1012), 'ptr', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1017, 1110),
+ AstIdent(StrRegion(1021, 1038), 'PsHeap_DeleteWord', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1039, 1045), 'number', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1046, 1049), 'ptr', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [
+ AstCall(StrRegion(1057, 1081),
+ AstIdent(StrRegion(1057, 1076), '_PsHeap_FinalizeObj', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(1077, 1080), 'ptr', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(1087, 1107),
+ AstIdent(StrRegion(1087, 1102), 'PsHeap_FreeWord', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(1103, 1106), 'ptr', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(1112, 1134),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(1121, 1129), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstListLiteral(StrRegion(1132, 1134),
+ [],
+ meta=TypeMetadata(type=ListType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1156, 1186),
+ AstIdent(StrRegion(1160, 1176), 'refStack__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1177, 1180), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1181, 1182), 'x', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1207, 1234),
+ AstIdent(StrRegion(1211, 1224), 'stack__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1225, 1228), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1229, 1230), 'x', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1255, 1272),
+ AstIdent(StrRegion(1259, 1267), 'lenStack', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1293, 1319),
+ AstIdent(StrRegion(1297, 1309), 'stackDelitem', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1310, 1313), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1314, 1315), 'x', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1340, 1368),
+ AstIdent(StrRegion(1344, 1358), 'psHeap__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1359, 1362), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1363, 1364), 'x', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1389, 1427),
+ AstIdent(StrRegion(1393, 1417), '_psHeap_freelist__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1418, 1421), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1422, 1423), 'x', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1448, 1487),
+ AstIdent(StrRegion(1452, 1477), '_psHeap_freelist__delitem', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1478, 1481), 'val', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1482, 1483), 'x', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1508, 1538),
+ AstIdent(StrRegion(1512, 1533), '_psHeap_freelist__len', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1559, 1579),
+ AstIdent(StrRegion(1563, 1574), 'psHeap__len', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1581, 1811),
+ AstIdent(StrRegion(1585, 1591), 'decref', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1592, 1598), 'number', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1599, 1602), 'ptr', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [
+ AstIf(StrRegion(1610, 1809),
+ AstBinOp(StrRegion(1613, 1631),
+ '>=',
+ AstItem(StrRegion(1613, 1626),
+ AstIdent(StrRegion(1613, 1621), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(1622, 1625), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstNumber(StrRegion(1630, 1631), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstAssign(StrRegion(1691, 1724),
+ AstItem(StrRegion(1691, 1704),
+ AstIdent(StrRegion(1691, 1699), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(1700, 1703), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstBinOp(StrRegion(1707, 1724),
+ '-',
+ AstItem(StrRegion(1707, 1720),
+ AstIdent(StrRegion(1707, 1715), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(1716, 1719), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstNumber(StrRegion(1723, 1724), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(1734, 1803),
+ AstBinOp(StrRegion(1737, 1755),
+ '==',
+ AstItem(StrRegion(1737, 1750),
+ AstIdent(StrRegion(1737, 1745), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(1746, 1749), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstNumber(StrRegion(1754, 1755), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstCall(StrRegion(1770, 1792),
+ AstIdent(StrRegion(1770, 1787), 'PsHeap_DeleteWord', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(1788, 1791), 'ptr', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(1812, 2002),
+ AstIdent(StrRegion(1816, 1822), 'incref', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ (
+ AstIdent(StrRegion(1823, 1829), 'number', meta=TypeMetadata(type=TypeType(tp=ValType()))),
+ AstIdent(StrRegion(1830, 1833), 'ptr', meta=TypeMetadata(type=ValType()))
+ )
+ ],
+ [
+ AstIf(StrRegion(1841, 2000),
+ AstBinOp(StrRegion(1844, 1862),
+ '>=',
+ AstItem(StrRegion(1844, 1857),
+ AstIdent(StrRegion(1844, 1852), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(1853, 1856), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstNumber(StrRegion(1861, 1862), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstAssign(StrRegion(1922, 1955),
+ AstItem(StrRegion(1922, 1935),
+ AstIdent(StrRegion(1922, 1930), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(1931, 1934), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstBinOp(StrRegion(1938, 1955),
+ '+',
+ AstItem(StrRegion(1938, 1951),
+ AstIdent(StrRegion(1938, 1946), 'refStack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(1947, 1950), 'ptr', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstNumber(StrRegion(1954, 1955), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(2040, 2059),
+ VarDeclScope.GLOBAL,
+ VarDeclType.LIST,
+ AstIdent(StrRegion(2049, 2054), 'stack', meta=TypeMetadata(type=ListType())),
+ AstListLiteral(StrRegion(2057, 2059),
+ [],
+ meta=TypeMetadata(type=ListType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(2061, 2086),
+ VarDeclScope.GLOBAL,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2068, 2078), 'COUNT_REFS', meta=TypeMetadata(type=ValType())),
+ AstIdent(StrRegion(2081, 2086), 'false', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(2436, 2448),
+ AstIdent(StrRegion(2440, 2443), 'NOP', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(2450, 2600),
+ AstIdent(StrRegion(2454, 2461), 'POP_TOP', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [
+ AstCall(StrRegion(2470, 2480),
+ AstIdent(StrRegion(2470, 2478), 'lenStack', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(2504, 2568),
+ AstBinOp(StrRegion(2507, 2525),
+ '==',
+ AstIdent(StrRegion(2507, 2517), 'COUNT_REFS', meta=TypeMetadata(type=ValType())),
+ AstIdent(StrRegion(2521, 2525), 'true', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstCall(StrRegion(2536, 2561),
+ AstIdent(StrRegion(2536, 2542), 'decref', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstItem(StrRegion(2543, 2560),
+ AstIdent(StrRegion(2543, 2548), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(2549, 2559), '__result__', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(2573, 2597),
+ AstIdent(StrRegion(2573, 2585), 'stackDelitem', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(2586, 2596), '__result__', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(2602, 2768),
+ AstIdent(StrRegion(2606, 2613), 'ROT_TWO', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [
+ AstCall(StrRegion(2622, 2632),
+ AstIdent(StrRegion(2622, 2630), 'lenStack', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(2638, 2662),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2642, 2649), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstIdent(StrRegion(2652, 2662), '__result__', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(2668, 2693),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2672, 2676), 'tos0', meta=TypeMetadata(type=ValType())),
+ AstItem(StrRegion(2679, 2693),
+ AstIdent(StrRegion(2679, 2684), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(2685, 2692), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(2699, 2734),
+ AstItem(StrRegion(2699, 2713),
+ AstIdent(StrRegion(2699, 2704), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(2705, 2712), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstItem(StrRegion(2716, 2734),
+ AstIdent(StrRegion(2716, 2721), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(2722, 2733),
+ '-',
+ AstIdent(StrRegion(2722, 2729), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(2732, 2733), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(2740, 2765),
+ AstItem(StrRegion(2740, 2758),
+ AstIdent(StrRegion(2740, 2745), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(2746, 2757),
+ '-',
+ AstIdent(StrRegion(2746, 2753), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(2756, 2757), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstIdent(StrRegion(2761, 2765), 'tos0', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(2770, 3096),
+ AstIdent(StrRegion(2774, 2783), 'ROT_THREE', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [
+ AstCall(StrRegion(2905, 2915),
+ AstIdent(StrRegion(2905, 2913), 'lenStack', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(2921, 2945),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2925, 2932), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstIdent(StrRegion(2935, 2945), '__result__', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(2951, 2976),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(2955, 2959), 'tos0', meta=TypeMetadata(type=ValType())),
+ AstItem(StrRegion(2962, 2976),
+ AstIdent(StrRegion(2962, 2967), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(2968, 2975), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(2982, 3017),
+ AstItem(StrRegion(2982, 2996),
+ AstIdent(StrRegion(2982, 2987), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(2988, 2995), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstItem(StrRegion(2999, 3017),
+ AstIdent(StrRegion(2999, 3004), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3005, 3016),
+ '-',
+ AstIdent(StrRegion(3005, 3012), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3015, 3016), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(3023, 3062),
+ AstItem(StrRegion(3023, 3041),
+ AstIdent(StrRegion(3023, 3028), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3029, 3040),
+ '-',
+ AstIdent(StrRegion(3029, 3036), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3039, 3040), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstItem(StrRegion(3044, 3062),
+ AstIdent(StrRegion(3044, 3049), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3050, 3061),
+ '-',
+ AstIdent(StrRegion(3050, 3057), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3060, 3061), 2, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(3068, 3093),
+ AstItem(StrRegion(3068, 3086),
+ AstIdent(StrRegion(3068, 3073), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3074, 3085),
+ '-',
+ AstIdent(StrRegion(3074, 3081), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3084, 3085), 2, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstIdent(StrRegion(3089, 3093), 'tos0', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(3098, 3250),
+ AstIdent(StrRegion(3102, 3109), 'DUP_TOP', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [
+ AstCall(StrRegion(3118, 3128),
+ AstIdent(StrRegion(3118, 3126), 'lenStack', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(3134, 3163),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3138, 3143), 'value', meta=TypeMetadata(type=ValType())),
+ AstItem(StrRegion(3146, 3163),
+ AstIdent(StrRegion(3146, 3151), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(3152, 3162), '__result__', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(3169, 3189),
+ AstIdent(StrRegion(3169, 3182), 'stack__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(3183, 3188), 'value', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(3195, 3248),
+ AstBinOp(StrRegion(3198, 3217),
+ '!=',
+ AstIdent(StrRegion(3198, 3208), 'COUNT_REFS', meta=TypeMetadata(type=ValType())),
+ AstIdent(StrRegion(3212, 3217), 'false', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstCall(StrRegion(3228, 3241),
+ AstIdent(StrRegion(3228, 3234), 'incref', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(3235, 3240), 'value', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(3252, 3531),
+ AstIdent(StrRegion(3256, 3267), 'DUP_TOP_TWO', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [
+ AstCall(StrRegion(3276, 3286),
+ AstIdent(StrRegion(3276, 3284), 'lenStack', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(3292, 3316),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3296, 3303), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstIdent(StrRegion(3306, 3316), '__result__', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(3322, 3347),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3326, 3330), 'tos0', meta=TypeMetadata(type=ValType())),
+ AstItem(StrRegion(3333, 3347),
+ AstIdent(StrRegion(3333, 3338), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(3339, 3346), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(3353, 3382),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3357, 3361), 'tos1', meta=TypeMetadata(type=ValType())),
+ AstItem(StrRegion(3364, 3382),
+ AstIdent(StrRegion(3364, 3369), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3370, 3381),
+ '-',
+ AstIdent(StrRegion(3370, 3377), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3380, 3381), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(3388, 3407),
+ AstIdent(StrRegion(3388, 3401), 'stack__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(3402, 3406), 'tos1', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(3413, 3432),
+ AstIdent(StrRegion(3413, 3426), 'stack__append', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(3427, 3431), 'tos0', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstIf(StrRegion(3459, 3529),
+ AstBinOp(StrRegion(3462, 3477),
+ '!=',
+ AstIdent(StrRegion(3462, 3472), 'COUNT_REFS', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3476, 3477), 0, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=BoolType())
+ ),
+ [
+ AstCall(StrRegion(3488, 3500),
+ AstIdent(StrRegion(3488, 3494), 'incref', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(3495, 3499), 'tos0', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstCall(StrRegion(3510, 3522),
+ AstIdent(StrRegion(3510, 3516), 'incref', meta=TypeMetadata(type=FunctionType(arg_types=[ValType()], ret_type=VoidType()))),
+ [
+ AstIdent(StrRegion(3517, 3521), 'tos1', meta=TypeMetadata(type=ValType()))
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDefine(StrRegion(3533, 3864),
+ AstIdent(StrRegion(3537, 3545), 'ROT_FOUR', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ [
+ AstCall(StrRegion(3628, 3638),
+ AstIdent(StrRegion(3628, 3636), 'lenStack', meta=TypeMetadata(type=FunctionType(arg_types=[], ret_type=VoidType()))),
+ [],
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(3644, 3668),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3648, 3655), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstIdent(StrRegion(3658, 3668), '__result__', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstDeclNode(StrRegion(3674, 3699),
+ VarDeclScope.LET,
+ VarDeclType.VARIABLE,
+ AstIdent(StrRegion(3678, 3682), 'tos0', meta=TypeMetadata(type=ValType())),
+ AstItem(StrRegion(3685, 3699),
+ AstIdent(StrRegion(3685, 3690), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(3691, 3698), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(3705, 3740),
+ AstItem(StrRegion(3705, 3719),
+ AstIdent(StrRegion(3705, 3710), 'stack', meta=TypeMetadata(type=ListType())),
+ AstIdent(StrRegion(3711, 3718), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstItem(StrRegion(3722, 3740),
+ AstIdent(StrRegion(3722, 3727), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3728, 3739),
+ '-',
+ AstIdent(StrRegion(3728, 3735), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3738, 3739), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(3746, 3785),
+ AstItem(StrRegion(3746, 3764),
+ AstIdent(StrRegion(3746, 3751), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3752, 3763),
+ '-',
+ AstIdent(StrRegion(3752, 3759), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3762, 3763), 1, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstItem(StrRegion(3767, 3785),
+ AstIdent(StrRegion(3767, 3772), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3773, 3784),
+ '-',
+ AstIdent(StrRegion(3773, 3780), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3783, 3784), 2, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(3791, 3830),
+ AstItem(StrRegion(3791, 3809),
+ AstIdent(StrRegion(3791, 3796), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3797, 3808),
+ '-',
+ AstIdent(StrRegion(3797, 3804), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3807, 3808), 2, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstItem(StrRegion(3812, 3830),
+ AstIdent(StrRegion(3812, 3817), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3818, 3829),
+ '-',
+ AstIdent(StrRegion(3818, 3825), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3828, 3829), 3, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=VoidType())
+ ),
+ AstAssign(StrRegion(3836, 3861),
+ AstItem(StrRegion(3836, 3854),
+ AstIdent(StrRegion(3836, 3841), 'stack', meta=TypeMetadata(type=ListType())),
+ AstBinOp(StrRegion(3842, 3853),
+ '-',
+ AstIdent(StrRegion(3842, 3849), 'tos_idx', meta=TypeMetadata(type=ValType())),
+ AstNumber(StrRegion(3852, 3853), 3, meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=ValType())
+ ),
+ meta=TypeMetadata(type=ValType())
+ ),
+ AstIdent(StrRegion(3857, 3861), 'tos0', meta=TypeMetadata(type=ValType())),
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
+ )
+ ],
+ meta=TypeMetadata(type=VoidType())
)
\ No newline at end of file
diff --git a/test/test_e2e/test_from_fuzzer.py b/test/test_e2e/test_from_fuzzer.py
index a5d6dd3..17e1801 100644
--- a/test/test_e2e/test_from_fuzzer.py
+++ b/test/test_e2e/test_from_fuzzer.py
@@ -4,6 +4,7 @@
from parser.cst.cstgen import CstGen
from parser.lexer.tokenizer import Tokenizer
+from scripts.fuzz import fuzz
from test.common import CommonTestCase, TestCaseUtils
from util import timeout_decor, timeout_decor_async
@@ -17,15 +18,16 @@ def setUp(self):
# TestCase object isn't passed to the other process as the self value
@staticmethod
@timeout_decor_async(5, debug=0, pool=True)
- def _inner_once(src: str):
- return CommonTestCase.raiseInternalErrorsOnlyCST(src)
+ def _inner_once(src_bytes: bytes):
+ with CommonTestCase.raiseInternalErrorsOnly():
+ fuzz(src_bytes)
async def _test_once(self, p: Path):
with self.subTest(corp=p.name):
- with open(p, encoding='cp1252') as f:
- src = f.read()
+ with open(p, 'rb') as f:
+ src_bytes = f.read()
# noinspection PyUnresolvedReferences
- await self._inner_once(src) # Pycharm doesn't understand decorators
+ await self._inner_once(src_bytes) # Pycharm doesn't understand decorators
async def test(self):
await asyncio.gather(*[
diff --git a/test/test_e2e/test_main_examples.py b/test/test_e2e/test_main_examples.py
index ada0350..d7b2e07 100644
--- a/test/test_e2e/test_main_examples.py
+++ b/test/test_e2e/test_main_examples.py
@@ -3,7 +3,8 @@
from parser.astgen.astgen import AstGen
from parser.cst.cstgen import CstGen
from parser.lexer import Tokenizer
-from parser.typecheck.typecheck import NameResolver
+from parser.typecheck.name_resolver import NameResolver
+from parser.typecheck.typecheck import Typechecker
from test.common import CommonTestCase
from util import readfile
@@ -13,8 +14,11 @@ def setUp(self):
self.setProperCwd()
super().setUp()
- def _test_main_example_n(self, n: int, do_ast=True, do_name_resolve=True):
- src = readfile(f'./main_example_{n}.st')
+ def _test_main_example_n(
+ self, n: int, do_ast=True, do_name_resolve=True,
+ do_typecheck=True
+ ):
+ src = readfile(f'./examples/main_example_{n}.st')
tk = Tokenizer(src).tokenize()
self.assertMatchesSnapshot(tk.tokens, 'tokens')
t = CstGen(tk)
@@ -27,6 +31,10 @@ def _test_main_example_n(self, n: int, do_ast=True, do_name_resolve=True):
return
nr = NameResolver(a)
self.assertMatchesSnapshot(nr.run(), 'name_resolve')
+ if not do_typecheck:
+ return
+ tc = Typechecker(nr)
+ self.assertMatchesSnapshot(tc.run(), 'typecheck')
def test_example_0(self):
self._test_main_example_n(0, do_ast=False)
@@ -35,7 +43,10 @@ def test_example_1(self):
self._test_main_example_n(1, do_name_resolve=False)
def test_example_2(self):
- self._test_main_example_n(2)
+ self._test_main_example_n(2, do_typecheck=False)
+
+ def test_example_3(self):
+ self._test_main_example_n(3)
if __name__ == '__main__':
diff --git a/test/test_error.py b/test/test_error.py
index b157e11..6d780b8 100644
--- a/test/test_error.py
+++ b/test/test_error.py
@@ -1,13 +1,28 @@
import unittest
-from unittest.mock import patch
+from unittest.mock import patch, MagicMock
from parser.common import StrRegion
from parser.common.error import BaseLocatedError
+class _PatchRegionDisplay:
+ def __init__(self):
+ def _mocked_display(*args, **kwargs):
+ return self._mock(*args, **kwargs)
+ self._mock = MagicMock()
+ self._inner = patch.object(StrRegion, 'display', _mocked_display)
+
+ def __enter__(self):
+ self._inner.__enter__()
+ return self._mock
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return self._inner.__exit__(exc_type, exc_val, exc_tb)
+
+
class TestLocatedError(unittest.TestCase):
def test_adds_note_once(self):
- with patch.object(BaseLocatedError, 'display_region') as mock_display:
+ with _PatchRegionDisplay() as mock_display:
mock_display.return_value = 'mock_return_value'
err = BaseLocatedError("a_message", StrRegion(0, 2), 'src_str')
str(err)
@@ -16,15 +31,15 @@ def test_adds_note_once(self):
self.assertEqual(len(err.get_notes()), 1)
def test_uses_display_return_value(self):
- with patch.object(BaseLocatedError, 'display_region') as mock_display:
+ with _PatchRegionDisplay() as mock_display:
mock_display.return_value = 'mock_return_value'
err = BaseLocatedError("a_message", StrRegion(0, 2), 'src_str')
str(err)
- mock_display.assert_called_once_with('src_str', StrRegion(0, 2))
+ mock_display.assert_called_once_with(StrRegion(0, 2), 'src_str')
self.assertEqual(err.get_notes(), ['mock_return_value'])
def test_only_calls_display_when_needed(self):
- with patch.object(BaseLocatedError, 'display_region') as mock_display:
+ with _PatchRegionDisplay() as mock_display:
mock_display.return_value = 'mock_return_value'
err = BaseLocatedError("a_message", StrRegion(0, 2), 'src_str')
mock_display.assert_not_called()
diff --git a/test/test_typecheck/test_name_resolve.py b/test/test_typecheck/test_name_resolve.py
index 980e7a0..ac878dd 100644
--- a/test/test_typecheck/test_name_resolve.py
+++ b/test/test_typecheck/test_name_resolve.py
@@ -1,9 +1,9 @@
from unittest.mock import Mock, patch
from parser.common import StrRegion
-from parser.typecheck.typecheck import (
- NameResolver, Scope, NameInfo, BoolType, ValType, VoidType,
- FuncInfo, ParamInfo)
+from parser.typecheck.name_resolver import NameResolver
+from parser.typecheck.scope import NameInfo, FuncInfo, ParamInfo, Scope
+from parser.typecheck.types import ValType, BoolType, VoidType
from test.common import CommonTestCase
@@ -79,24 +79,54 @@ class TestNameResolveErrors(CommonTestCase):
def test_undefined_var(self):
err = self.assertNameResolveError('foo = 9;')
self.assertContains(err.msg, "Name 'foo' is not defined")
- self.assertEqual(StrRegion(0, 3), err.region)
+ self.assertErrorRegion(StrRegion(0, 3), err)
- def test_var_already_declared(self):
+ def test_var_already_declared_once(self):
err = self.assertNameResolveError('let foo = 9; let foo;')
self.assertContains(err.msg, "Variable already declared")
- self.assertEqual(StrRegion(13, 20), err.region)
+ self.assertErrorRegion(StrRegion(17, 20), err)
+
+ def test_var_already_declared_once_with_value(self):
+ err = self.assertNameResolveError('let foo = 9; let foo = 55;')
+ self.assertContains(err.msg, "Variable already declared")
+ self.assertErrorRegion(StrRegion(17, 20), err)
+
+ def test_var_already_declared_many_first(self):
+ err = self.assertNameResolveError('let foo = 9; let foo, bar;')
+ self.assertContains(err.msg, "Variable already declared")
+ self.assertErrorRegion(StrRegion(17, 20), err)
+
+ def test_var_already_declared_many_mid(self):
+ err = self.assertNameResolveError('let bar = 9; let foo, bar, baz;')
+ self.assertContains(err.msg, "Variable already declared")
+ self.assertErrorRegion(StrRegion(22, 25), err)
+
+ def test_var_already_declared_many_last(self):
+ err = self.assertNameResolveError('let baz = 9; let foo, bar, baz;')
+ self.assertContains(err.msg, "Variable already declared")
+ self.assertErrorRegion(StrRegion(27, 30), err)
def test_fn_already_declared(self):
err = self.assertNameResolveError('def foo(){}; def foo(){}')
self.assertContains(err.msg, "Function already declared")
- self.assertEqual(StrRegion(17, 20), err.region)
+ self.assertErrorRegion(StrRegion(17, 20), err)
def test_unknown_param_type(self):
err = self.assertNameResolveError('def foo(not_a_type name){};')
self.assertContains(err.msg, "Unknown parameter type")
- self.assertEqual(StrRegion(8, 18), err.region)
+ self.assertErrorRegion(StrRegion(8, 18), err)
def test_duplicate_param_name(self):
err = self.assertNameResolveError('def foo(bool a, val a){};')
self.assertContains(err.msg, "There is already a parameter of this name")
- self.assertEqual(StrRegion(20, 21), err.region)
+ self.assertErrorRegion(StrRegion(20, 21), err)
+
+ def test_fn_resued_as_var(self):
+ err = self.assertNameResolveError('def foo(){}; let foo;')
+ self.assertContains(err.msg, "Variable already declared")
+ self.assertErrorRegion(StrRegion(17, 20), err)
+
+ def test_var_resued_as_fn(self):
+ err = self.assertNameResolveError('let foo = 9; def foo(){/*hi*/}')
+ self.assertContains(err.msg, "Function already declared")
+ self.assertErrorRegion(StrRegion(17, 20), err)
diff --git a/test/test_typecheck/test_typecheck.py b/test/test_typecheck/test_typecheck.py
new file mode 100644
index 0000000..cb67b01
--- /dev/null
+++ b/test/test_typecheck/test_typecheck.py
@@ -0,0 +1,178 @@
+from parser.astgen.ast_node import AstNode
+from parser.astgen.ast_nodes import AstDeclNode, AstDefine, AstAugAssign, AstWhile, \
+ VarDeclType, VarDeclScope, AstRepeat, AstItem
+from parser.common import StrRegion
+from parser.typecheck.types import ValType, VoidType, BoolType, TypeType, TypeMetadata, \
+ ListType
+from test.common import CommonTestCase
+
+
+class TestGivenTypes(CommonTestCase):
+ def test_var_decl_assign(self):
+ prog = self.getTypechecker("let a = 9;").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+ self.assertTypecheckedTo(prog, VoidType())
+ decl = self.assertHasSingleItem(prog.statements)
+ self.assertTypecheckedTo(decl, VoidType())
+ self.assertIsInstance(decl, AstDeclNode)
+ decl: AstDeclNode[TypeMetadata]
+ self.assertTypecheckedTo(decl.value, ValType())
+ self.assertTypecheckedTo(decl.ident, ValType())
+ # self.assertMatchesSnapshot(prog)
+
+ def test_function(self):
+ prog = self.getTypechecker("def f(val a, bool b, number c, string d){}").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+ f = self.assertAsInstance(self.assertHasSingleItem(prog.statements), AstDefine)
+ expected_types = [ValType(), BoolType(), ValType(), ValType()]
+ self.assertEqual(len(expected_types), len(f.params))
+ for expect_t, (type_ident, name_ident) in zip(expected_types, f.params):
+ self.assertTypecheckedTo(name_ident, expect_t)
+ self.assertTypecheckedTo(type_ident, TypeType(expect_t))
+ # self.assertMatchesSnapshot(prog)
+
+ def test_operators(self):
+ prog = self.getTypechecker("let a = (1 + 1) * 2.2;").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+
+ def test_bools(self):
+ prog = self.getTypechecker("if(!(6==7) && (8==9 || 7<2) || 4>=2){}").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+
+ def test_assign_list_getitem(self):
+ prog = self.getTypechecker("global AA = 9; let[] bb = [7]; AA = bb[1];").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+
+ def test_aug_assign(self):
+ prog = self.getTypechecker("let v=8; v+=5;").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+ decl, aug = self.assertHasLength(prog.statements, 2)
+ self.assertTypecheckedTo(decl, VoidType())
+ self.assertTypecheckedTo(aug, VoidType())
+ self._check_decl_val(decl)
+ aug = self.assertAsInstance(aug, AstAugAssign)
+ self.assertTypecheckedTo(aug.target, ValType())
+ self.assertTypecheckedTo(aug.source, ValType())
+
+ def test_while(self):
+ prog = self.getTypechecker("while(1==1){let[] b;}").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+ while_ = self.assertAsInstance(self.assertHasSingleItem(prog.statements), AstWhile)
+ self.assertTypecheckedTo(while_, VoidType())
+ self.assertTypecheckedTo(while_.cond, BoolType())
+ let = self.assertAsInstance(self.assertHasSingleItem(while_.body), AstDeclNode)
+ self.assertTypecheckedTo(let, VoidType())
+ self.assertTypecheckedTo(let.ident, ListType())
+ self.assertIsNone(let.value)
+ self.assertEqual(VarDeclType.LIST, let.type)
+ self.assertEqual(VarDeclScope.LET, let.scope)
+
+ def test_repeat(self):
+ prog = self.getTypechecker("repeat 42 {}").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+ repeat = self.assertAsInstance(self.assertHasSingleItem(prog.statements), AstRepeat)
+ self.assertTypecheckedTo(repeat, VoidType())
+ self.assertTypecheckedTo(repeat.count, ValType())
+ self.assertHasLength(repeat.body, 0)
+
+ def test_string_getitem(self):
+ prog = self.getTypechecker("let a='hello'; let b=a[4];").run()
+ self.assertAllMetadata(prog, TypeMetadata)
+ a, b = self.assertHasLength(prog.statements, 2)
+ self.assertTypecheckedTo(a, VoidType())
+ self.assertTypecheckedTo(b, VoidType())
+ self._check_decl_val(a)
+ b = self._check_decl_val(b)
+ getitem = self.assertAsInstance(b.value, AstItem)
+ self.assertTypecheckedTo(getitem, ValType())
+ self.assertTypecheckedTo(getitem.obj, ValType())
+ self.assertTypecheckedTo(getitem.index, ValType())
+
+ def _check_decl_val(self, a: AstNode):
+ a = self.assertAsInstance(a, AstDeclNode)
+ self.assertTypecheckedTo(a.ident, ValType())
+ self.assertTypecheckedTo(a.value, ValType())
+ return a
+
+
+class TestErrors(CommonTestCase):
+ def test_cant_pass_list_to_val_param(self):
+ exc = self.assertTypecheckError("def f(val v){}\nglobal[] L=[];\nf(L);")
+ self.assertEqual(exc.msg, "Expected type val, got type list")
+ self.assertErrorRegion(StrRegion(32, 33), exc)
+ exc = self.assertTypecheckError("def f(val v){}\nglobal[] L=[];\ndef g(){f(L);}")
+ self.assertEqual(exc.msg, "Expected type val, got type list")
+ self.assertErrorRegion(StrRegion(40, 41), exc)
+
+ def test_assignment_error(self):
+ exc = self.assertTypecheckError("let a; a = (1 < 2);")
+ self.assertEqual(exc.msg, "Expected type val, got type bool")
+ # BEHAV: Or 11->18 (either including or excluding parens? - which one?)
+ self.assertErrorRegion(StrRegion(12, 17), exc)
+
+ def test_bool_only_in_condition(self):
+ exc = self.assertTypecheckError("let a=8;\nif a {}")
+ self.assertEqual(exc.msg, "Expected type bool, got type val")
+ self.assertErrorRegion(StrRegion(12, 13), exc)
+
+ def test_assign_func(self):
+ exc = self.assertTypecheckError("def f(){}\nf = 8;")
+ self.assertErrorRegion(StrRegion(10, 11), exc)
+ self.assertEqual(exc.msg, "Cannot assign directly to () -> void")
+
+ def test_call_extra_arg_single(self):
+ exc = self.assertTypecheckError("def f(){}; f(6769);")
+ self.assertErrorRegion(StrRegion(13, 17), exc)
+ self.assertEqual("Incorrect number of arguments, expected 0, got 1", exc.msg)
+
+ def test_call_error_one_extra_arg(self):
+ exc = self.assertTypecheckError("def f(val a){}; f(67, 69);")
+ self.assertErrorRegion(StrRegion(22, 24), exc)
+ self.assertEqual("Incorrect number of arguments, expected 1, got 2", exc.msg)
+
+ def test_call_error_many_extra_arg(self):
+ # BEHAV: should we do last or first extraneous one? Do first for
+ # now as last might imply that it's the only extraneous arg. Or all??
+ exc = self.assertTypecheckError("def f(){}; f(67, 69);")
+ self.assertErrorRegion(StrRegion(13, 15), exc)
+ self.assertEqual("Incorrect number of arguments, expected 0, got 2", exc.msg)
+
+ def test_call_not_enough_arg(self):
+ # BEHAV: Should we really highlight entire call? Fine I guess for now
+ exc = self.assertTypecheckError("def f(val s, val r){}; f(67);")
+ self.assertErrorRegion(StrRegion(23, 28), exc)
+ self.assertEqual("Incorrect number of arguments, expected 2, got 1", exc.msg)
+
+ def test_call_not_enough_arg_given_zero(self):
+ exc = self.assertTypecheckError("def f(val s, val r){}; f();")
+ self.assertErrorRegion(StrRegion(23, 26), exc)
+ self.assertEqual("Incorrect number of arguments, expected 2, got 0", exc.msg)
+
+ def test_call_list(self):
+ exc = self.assertTypecheckError("let[] a=[6]; a();")
+ self.assertEqual("Cannot call list", exc.msg)
+ self.assertErrorRegion(StrRegion(13, 14), exc)
+
+ def test_call_val(self):
+ exc = self.assertTypecheckError("let a=8; a();")
+ self.assertEqual("Cannot call val", exc.msg)
+ self.assertErrorRegion(StrRegion(9, 10), exc)
+
+ def test_item_of_func(self):
+ exc = self.assertTypecheckError("def f(val x){}; let a=f[9];")
+ self.assertEqual("Cannot get item of (val) -> void", exc.msg)
+ self.assertErrorRegion(StrRegion(22, 26), exc)
+
+ def test_attr_doesnt_crash(self):
+ with self.assertDoesntCrash():
+ self.getTypechecker("let a; a.b=9;").run()
+ with self.assertDoesntCrash():
+ self.getTypechecker("let a; let c = a.b;").run()
+
+ def test_unsupported_aug_assign_doesnt_crash(self):
+ with self.assertDoesntCrash():
+ self.getTypechecker("let a; a-=7;").run()
+ with self.assertDoesntCrash():
+ self.getTypechecker("let a; a**=7;").run()
+ with self.assertDoesntCrash():
+ self.getTypechecker("let[] a; a[6] += 7;").run()
diff --git a/util/__init__.py b/util/__init__.py
index 2faf3ce..380d2e5 100644
--- a/util/__init__.py
+++ b/util/__init__.py
@@ -1,7 +1,8 @@
from __future__ import annotations
+import dataclasses
from os import PathLike
-from typing import TypeVar, Any, overload, Iterable
+from typing import TypeVar, Any, overload, Iterable, Literal, TypeAlias
from .recursive_eq import recursive_eq
from .simple_process_pool import *
@@ -39,3 +40,21 @@ def is_strict_subclass(o: object, type_or_types: tuple[type, ...]):
except TypeError:
types = (type_or_types,)
return isinstance(o, type) and issubclass(o, types) and o not in types
+
+
+DataclassesMissingT: TypeAlias = 'Literal[dataclasses._MISSING_TYPE.MISSING]'
+
+
+# (Note: dataclasses._MISSING_TYPE isn't actually a runtime thing, it's just
+# for type checkers to recognise dataclasses.MISSING)
+def dcls_field_default(f: dataclasses.Field[T]) -> T | DataclassesMissingT:
+ if f.default is not dataclasses.MISSING:
+ return f.default
+ if (factory := f.default_factory) is not dataclasses.MISSING:
+ return factory()
+ return dataclasses.MISSING
+
+
+def assert_not_none(x: T | None) -> T:
+ assert x is not None, "Expected non-None value, got None"
+ return x
diff --git a/util/recursive_eq.py b/util/recursive_eq.py
index 2f86c02..3b33320 100644
--- a/util/recursive_eq.py
+++ b/util/recursive_eq.py
@@ -3,7 +3,12 @@
def recursive_eq(fn):
- """Must be used as decorator, like reprlib.recursive_repr.
+ """Allows safe recursive equality comparisons also cnosidering reference
+ identity (like if I modify a will b change?). Must be used as decorator,
+ like reprlib.recursive_repr. Note: may break with multi-threading or
+ super-weird reentrancy (comparing unrelated objects still of the same
+ type in the __eq__ where it has no relation to the current comparison).
+
Works by hypothesising that 2 ids are equal. Then, it tries to compare
them. If it encounters one of them again, it checks that the corresponding
value is the hypothesised value. If so, they're equal. If not, they're
@@ -12,6 +17,8 @@ def recursive_eq(fn):
@functools.wraps(fn)
def eq(a, b):
+ if a is b:
+ return True # Prevents nasty stuff like deleting same key twice
if (bid_exp := hypotheses.get(id(a))) is not None:
return bid_exp == id(b)
if (aid_exp := hypotheses.get(id(b))) is not None: