Moves the prelude to runtime

Previously, it was hardcoded at 'compile' time (in as much
Python has that). This would make it more difficult to add
stuff to it. Also, in a lot of places we made assumptions
about prelude instead of checking properly.
This commit is contained in:
Johan B.W. de Vries 2025-05-26 19:25:14 +02:00
parent d97be81828
commit b83772e178
14 changed files with 345 additions and 904 deletions

0
phasm/build/__init__.py Normal file
View File

211
phasm/build/base.py Normal file
View File

@ -0,0 +1,211 @@
"""
The base class for build environments.
Contains nothing but the explicit compiler builtins.
"""
from typing import Any, NamedTuple, Type
from ..type3.types import (
IntType3,
Type3,
TypeConstructor_Base,
TypeConstructor_DynamicArray,
TypeConstructor_StaticArray,
TypeConstructor_Struct,
TypeConstructor_Tuple,
)
from ..type3.typeclasses import Type3Class, Type3ClassMethod
from ..type3.routers import NoRouteForTypeException, TypeApplicationRouter
from ..wasm import WasmType, WasmTypeInt32
from . import builtins
TypeInfo = NamedTuple('TypeInfo', [
# Name of the type
('typ', str, ),
# What WebAssembly type to use when passing this value around
# For example in function arguments
('wasm_type', Type[WasmType]),
# What WebAssembly function to use when loading a value from memory
('wasm_load_func', str),
# What WebAssembly function to use when storing a value to memory
('wasm_store_func', str),
# When storing this value in memory, how many bytes do we use?
# Only valid for non-constructed types, see calculate_alloc_size
# Should match wasm_load_func / wasm_store_func
('alloc_size', int),
])
class BuildBase:
__slots__ = (
'dynamic_array',
'static_array',
'struct',
'tuple_',
'none_',
'type_info_map',
'type_info_constructed',
'types',
'type_class_instances',
'methods',
'operators',
'alloc_size_router',
)
dynamic_array: TypeConstructor_DynamicArray
"""
This is a dynamic length piece of memory.
It should be applied with two arguments. It has a runtime
determined length, and each argument is the same.
"""
static_array: TypeConstructor_StaticArray
"""
This is a fixed length piece of memory.
It should be applied with two arguments. It has a compile time
determined length, and each argument is the same.
"""
struct: TypeConstructor_Struct
"""
This is like a tuple, but each argument is named, so that developers
can get and set fields by name.
"""
tuple_: TypeConstructor_Tuple
"""
This is a fixed length piece of memory.
It should be applied with zero or more arguments. It has a compile time
determined length, and each argument can be different.
"""
none_: Type3
"""
The none type, for when functions simply don't return anything. e.g., IO().
"""
type_info_map: dict[str, TypeInfo]
"""
Map from type name to the info of that type
"""
type_info_constructed: TypeInfo
"""
By default, constructed types are passed as pointers
NOTE: ALLOC SIZE IN THIS STRUCT DOES NOT WORK FOR CONSTRUCTED TYPES
USE calculate_alloc_size FOR ACCURATE RESULTS
Functions count as constructed types - even though they are
not memory pointers but table addresses instead.
"""
types: dict[str, Type3]
"""
Types that are available without explicit import.
"""
type_class_instances: set[tuple[Type3Class, tuple[Type3 | TypeConstructor_Base[Any], ...]]]
"""
Type class instances that are available without explicit import.
"""
methods: dict[str, Type3ClassMethod]
"""
Methods that are available without explicit import.
"""
operators: dict[str, Type3ClassMethod]
"""
Operators that are available without explicit import.
"""
alloc_size_router: TypeApplicationRouter['BuildBase', int]
"""
Helper value for calculate_alloc_size.
"""
def __init__(self) -> None:
self.dynamic_array = builtins.dynamic_array
self.static_array = builtins.static_array
self.struct = builtins.struct
self.tuple_ = builtins.tuple_
self.none_ = builtins.none
self.type_info_map = {}
self.type_info_constructed = TypeInfo('t a', WasmTypeInt32, 'i32.load', 'i32.store', 4)
self.types = {
'None': self.none_,
}
self.type_class_instances = set()
self.methods = {}
self.operators = {}
self.alloc_size_router = TypeApplicationRouter['BuildBase', int]()
self.alloc_size_router.add(self.static_array, self.__class__.calculate_alloc_size_static_array)
self.alloc_size_router.add(self.struct, self.__class__.calculate_alloc_size_struct)
self.alloc_size_router.add(self.tuple_, self.__class__.calculate_alloc_size_tuple)
def calculate_alloc_size_static_array(self, args: tuple[Type3, IntType3]) -> int:
"""
Helper method for calculate_alloc_size - static_array
"""
sa_type, sa_len = args
return sa_len.value * self.calculate_alloc_size(sa_type, is_member=True)
def calculate_alloc_size_tuple(self, args: tuple[Type3, ...]) -> int:
"""
Helper method for calculate_alloc_size - tuple
"""
return sum(
self.calculate_alloc_size(x, is_member=True)
for x in args
)
def calculate_alloc_size_struct(self, args: tuple[tuple[str, Type3], ...]) -> int:
"""
Helper method for calculate_alloc_size - struct
"""
return sum(
self.calculate_alloc_size(x, is_member=True)
for _, x in args
)
def calculate_alloc_size(self, typ: Type3, is_member: bool = False) -> int:
"""
Calculates how much bytes you need to allocate when reserving memory for the given type.
"""
typ_info = self.type_info_map.get(typ.name)
if typ_info is not None:
return typ_info.alloc_size
if is_member:
return self.type_info_constructed.alloc_size
try:
return self.alloc_size_router(self, typ)
except NoRouteForTypeException:
raise NotImplementedError(typ)
def calculate_member_offset(self, st_name: str, st_args: tuple[tuple[str, Type3], ...], needle: str) -> int:
"""
Calculates the amount of bytes that should be skipped in memory befor reaching the struct's property with the given name.
"""
result = 0
for memnam, memtyp in st_args:
if needle == memnam:
return result
result += self.calculate_alloc_size(memtyp, is_member=True)
raise Exception(f'{needle} not in {st_name}')

22
phasm/build/builtins.py Normal file
View File

@ -0,0 +1,22 @@
"""
Type (constructors) that are used integral to the compiler.
These cannot be changed as there is compiler logic depending on them.
For mode documentation, see base.py.
"""
from ..type3.types import (
Type3,
TypeApplication_Nullary,
TypeConstructor_DynamicArray,
TypeConstructor_StaticArray,
TypeConstructor_Struct,
TypeConstructor_Tuple,
)
dynamic_array = TypeConstructor_DynamicArray('dynamic_array')
static_array = TypeConstructor_StaticArray('static_array')
struct = TypeConstructor_Struct('struct')
tuple_ = TypeConstructor_Tuple('tuple')
none = Type3('none', TypeApplication_Nullary(None, None))

57
phasm/build/default.py Normal file
View File

@ -0,0 +1,57 @@
"""
The default class for build environments.
Contains the compiler builtins as well as some sane defaults.
# Added types
f32: A 32-bits IEEE 754 float, of 32 bits width.
"""
from ..type3.functions import (
TypeVariable,
TypeVariableApplication_Nullary,
)
from ..type3.typeclasses import Type3Class
from ..type3.types import (
Type3,
TypeApplication_Nullary,
)
from ..wasm import (
WasmTypeFloat32,
WasmTypeInt32,
)
from .base import BuildBase, TypeInfo
class BuildDefault(BuildBase):
def __init__(self) -> None:
super().__init__()
u32 = Type3('f32', TypeApplication_Nullary(None, None))
self.type_info_map.update({
'u32': TypeInfo('u32', WasmTypeInt32, 'i32.load', 'i32.store', 4),
'f32': TypeInfo('f32', WasmTypeFloat32, 'f32.load', 'f32.store', 4),
})
self.types.update({
'u32': u32,
'f32': Type3('f32', TypeApplication_Nullary(None, None)),
})
a = TypeVariable('a', TypeVariableApplication_Nullary(None, None))
NatNum = Type3Class('NatNum', (a, ), methods={}, operators={
'+': [a, a, a],
'-': [a, a, a],
'*': [a, a, a],
'<<': [a, u32, a], # Arithmic shift left
'>>': [a, u32, a], # Arithmic shift right
})
self.methods.update({
**NatNum.methods,
})
self.operators.update({
**NatNum.operators,
})

View File

@ -5,7 +5,7 @@ It's intented to be a "any color, as long as it's black" kind of renderer
"""
from typing import Generator
from . import ourlang, prelude
from . import ourlang
from .type3.types import Type3, TypeApplication_Struct
@ -21,9 +21,6 @@ def type3(inp: Type3) -> str:
"""
Render: type's name
"""
if inp is prelude.none:
return 'None'
return inp.name
def struct_definition(inp: ourlang.StructDefinition) -> str:

View File

@ -5,7 +5,7 @@ import struct
from typing import List
from . import ourlang, prelude, wasm
from .runtime import calculate_alloc_size, calculate_member_offset
from .build import builtins
from .stdlib import alloc as stdlib_alloc
from .stdlib import types as stdlib_types
from .stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
@ -187,9 +187,9 @@ def expression_subscript_tuple(
wgn.add_statement(el_type_info.wasm_load_func, f'offset={offset}')
SUBSCRIPT_ROUTER = TypeApplicationRouter[tuple[WasmGenerator, ourlang.Module, ourlang.Subscript], None]()
SUBSCRIPT_ROUTER.add_n(prelude.bytes_, expression_subscript_bytes)
SUBSCRIPT_ROUTER.add(prelude.static_array, expression_subscript_static_array)
SUBSCRIPT_ROUTER.add(prelude.tuple_, expression_subscript_tuple)
# SUBSCRIPT_ROUTER.add(builtins.dynamic_array, expression_subscript_dynamic_array)
SUBSCRIPT_ROUTER.add(builtins.static_array, expression_subscript_static_array)
SUBSCRIPT_ROUTER.add(builtins.tuple_, expression_subscript_tuple)
def expression(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Expression) -> None:
"""

View File

@ -4,6 +4,7 @@ Contains the syntax tree for ourlang
from typing import Dict, Iterable, List, Optional, Union
from . import prelude
from .build.base import BuildBase
from .type3.functions import FunctionSignature, TypeVariableContext
from .type3.typeclasses import Type3ClassMethod
from .type3.types import Type3, TypeApplication_Struct
@ -288,14 +289,14 @@ class Function:
returns_type3: Type3
posonlyargs: List[FunctionParam]
def __init__(self, name: str, lineno: int) -> None:
def __init__(self, name: str, lineno: int, returns_type3: Type3) -> None:
self.name = name
self.lineno = lineno
self.exported = False
self.imported = None
self.statements = []
self.signature = FunctionSignature(TypeVariableContext(), [])
self.returns_type3 = prelude.none # FIXME: This could be a placeholder
self.returns_type3 = returns_type3
self.posonlyargs = []
class StructDefinition:
@ -381,21 +382,26 @@ class Module:
"""
A module is a file and consists of functions
"""
__slots__ = ('data', 'types', 'struct_definitions', 'constant_defs', 'functions', 'operators', 'functions_table', )
__slots__ = ('build', 'data', 'types', 'struct_definitions', 'constant_defs', 'functions', 'methods', 'operators', 'functions_table', )
build: BuildBase
data: ModuleData
types: dict[str, Type3]
struct_definitions: Dict[str, StructDefinition]
constant_defs: Dict[str, ModuleConstantDef]
functions: Dict[str, Function]
methods: Dict[str, Type3ClassMethod]
operators: Dict[str, Type3ClassMethod]
functions_table: dict[Function, int]
def __init__(self) -> None:
def __init__(self, build: BuildBase) -> None:
self.build = build
self.data = ModuleData()
self.types = {}
self.struct_definitions = {}
self.constant_defs = {}
self.functions = {}
self.methods = {}
self.operators = {}
self.functions_table = {}

View File

@ -5,6 +5,8 @@ import ast
from typing import Any, Dict, NoReturn, Union
from . import prelude
from .build.base import BuildBase
from .build.default import BuildDefault
from .exceptions import StaticError
from .ourlang import (
AccessStructMember,
@ -31,7 +33,6 @@ from .ourlang import (
TupleInstantiation,
VariableReference,
)
from .prelude import PRELUDE_METHODS, PRELUDE_OPERATORS, PRELUDE_TYPES
from .type3.typeclasses import Type3ClassMethod
from .type3.types import IntType3, Type3
@ -44,7 +45,8 @@ def phasm_parse(source: str) -> Module:
res = OptimizerTransformer().visit(res)
our_visitor = OurVisitor()
build = BuildDefault()
our_visitor = OurVisitor(build)
return our_visitor.visit_Module(res)
OurLocals = Dict[str, Union[FunctionParam]] # FIXME: Does it become easier if we add ModuleConstantDef to this dict?
@ -90,14 +92,14 @@ class OurVisitor:
# pylint: disable=C0103,C0116,C0301,R0201,R0912
def __init__(self) -> None:
pass
def __init__(self, build: BuildBase) -> None:
self.build = build
def visit_Module(self, node: ast.Module) -> Module:
module = Module()
module = Module(self.build)
module.operators.update(PRELUDE_OPERATORS)
module.types.update(PRELUDE_TYPES)
module.operators.update(self.build.operators)
module.types.update(self.build.types)
_not_implemented(not node.type_ignores, 'Module.type_ignores')
@ -153,7 +155,7 @@ class OurVisitor:
raise NotImplementedError(f'{node} on Module')
def pre_visit_Module_FunctionDef(self, module: Module, node: ast.FunctionDef) -> Function:
function = Function(node.name, node.lineno)
function = Function(node.name, node.lineno, self.build.none_)
_not_implemented(not node.args.posonlyargs, 'FunctionDef.args.posonlyargs')
@ -477,8 +479,8 @@ class OurVisitor:
func: Union[Function, FunctionParam, Type3ClassMethod]
if node.func.id in PRELUDE_METHODS:
func = PRELUDE_METHODS[node.func.id]
if node.func.id in module.methods:
func = module.methods[node.func.id]
elif node.func.id in our_locals:
func = our_locals[node.func.id]
else:

View File

@ -1,772 +0,0 @@
"""
The prelude are all the builtin types, type classes and methods
"""
from typing import Any, Callable
from warnings import warn
from phasm.stdlib import types as stdtypes
from phasm.wasmgenerator import Generator
from ..type3.functions import (
Constraint_TypeClassInstanceExists,
TypeConstructorVariable,
TypeVariable,
TypeVariableApplication_Nullary,
)
from ..type3.routers import TypeClassArgsRouter, TypeVariableLookup
from ..type3.typeclasses import Type3Class, Type3ClassMethod
from ..type3.types import (
Type3,
TypeApplication_Nullary,
TypeConstructor_Base,
TypeConstructor_DynamicArray,
TypeConstructor_Function,
TypeConstructor_StaticArray,
TypeConstructor_Struct,
TypeConstructor_Tuple,
)
PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: set[tuple[Type3Class, tuple[Type3 | TypeConstructor_Base[Any], ...]]] = set()
PRELUDE_TYPE_CLASS_INSTANCE_METHODS: dict[Type3ClassMethod, TypeClassArgsRouter[Generator, None]] = {}
class MissingImplementationException(Exception):
pass
class MissingImplementationWarning(Warning):
pass
def instance_type_class(
cls: Type3Class,
*typ: Type3 | TypeConstructor_Base[Any],
methods: dict[str, Callable[[Generator, TypeVariableLookup], None]] = {},
operators: dict[str, Callable[[Generator, TypeVariableLookup], None]] = {},
) -> None:
global PRELUDE_TYPE_CLASS_INSTANCES_EXISTING
global PRELUDE_TYPE_CLASS_INSTANCE_METHODS
assert len(cls.args) == len(typ)
tv_map: dict[TypeVariable, Type3] = {}
tc_map: dict[TypeConstructorVariable, TypeConstructor_Base[Any]] = {}
for arg_tv, arg_tp in zip(cls.args, typ, strict=True):
if isinstance(arg_tv, TypeVariable):
assert isinstance(arg_tp, Type3)
tv_map[arg_tv] = arg_tp
elif isinstance(arg_tv, TypeConstructorVariable):
assert isinstance(arg_tp, TypeConstructor_Base)
tc_map[arg_tv] = arg_tp
else:
raise NotImplementedError(arg_tv, arg_tp)
# TODO: Check for required existing instantiations
PRELUDE_TYPE_CLASS_INSTANCES_EXISTING.add((cls, tuple(typ), ))
for method_name, method in cls.methods.items():
router = PRELUDE_TYPE_CLASS_INSTANCE_METHODS.get(method)
if router is None:
router = TypeClassArgsRouter[Generator, None](cls.args)
PRELUDE_TYPE_CLASS_INSTANCE_METHODS[method] = router
try:
generator = methods[method_name]
except KeyError:
warn(MissingImplementationWarning(str(method), cls.name + ' ' + ' '.join(x.name for x in typ)))
continue
router.add(tv_map, tc_map, generator)
for operator_name, operator in cls.operators.items():
router = PRELUDE_TYPE_CLASS_INSTANCE_METHODS.get(operator)
if router is None:
router = TypeClassArgsRouter[Generator, None](cls.args)
PRELUDE_TYPE_CLASS_INSTANCE_METHODS[operator] = router
try:
generator = operators[operator_name]
except KeyError:
warn(MissingImplementationWarning(str(operator), cls.name + ' ' + ' '.join(x.name for x in typ)))
continue
router.add(tv_map, tc_map, generator)
none = Type3('none', TypeApplication_Nullary(None, None))
"""
The none type, for when functions simply don't return anything. e.g., IO().
"""
bool_ = Type3('bool', TypeApplication_Nullary(None, None))
"""
The bool type, either True or False
Suffixes with an underscores, as it's a Python builtin
"""
u8 = Type3('u8', TypeApplication_Nullary(None, None))
"""
The unsigned 8-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^8.
"""
u16 = Type3('u16', TypeApplication_Nullary(None, None))
"""
The unsigned 16-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^16.
"""
u32 = Type3('u32', TypeApplication_Nullary(None, None))
"""
The unsigned 32-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^32.
"""
u64 = Type3('u64', TypeApplication_Nullary(None, None))
"""
The unsigned 64-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^64.
"""
i8 = Type3('i8', TypeApplication_Nullary(None, None))
"""
The signed 8-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^8, but
with the middel point being 0.
"""
i16 = Type3('i16', TypeApplication_Nullary(None, None))
"""
The signed 16-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^16, but
with the middel point being 0.
"""
i32 = Type3('i32', TypeApplication_Nullary(None, None))
"""
The unsigned 32-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^32, but
with the middel point being 0.
"""
i64 = Type3('i64', TypeApplication_Nullary(None, None))
"""
The unsigned 64-bit integer type.
Operations on variables employ modular arithmetic, with modulus 2^64, but
with the middel point being 0.
"""
f32 = Type3('f32', TypeApplication_Nullary(None, None))
"""
A 32-bits IEEE 754 float, of 32 bits width.
"""
f64 = Type3('f64', TypeApplication_Nullary(None, None))
"""
A 32-bits IEEE 754 float, of 64 bits width.
"""
dynamic_array = TypeConstructor_DynamicArray('dynamic_array')
"""
This is a dynamic length piece of memory.
It should be applied with two arguments. It has a runtime
determined length, and each argument is the same.
"""
static_array = TypeConstructor_StaticArray('static_array')
"""
This is a fixed length piece of memory.
It should be applied with two arguments. It has a compile time
determined length, and each argument is the same.
"""
tuple_ = TypeConstructor_Tuple('tuple')
"""
This is a fixed length piece of memory.
It should be applied with zero or more arguments. It has a compile time
determined length, and each argument can be different.
"""
function = TypeConstructor_Function('function')
"""
This is a function.
It should be applied with one or more arguments. The last argument is the 'return' type.
"""
struct = TypeConstructor_Struct('struct')
"""
This is like a tuple, but each argument is named, so that developers
can get and set fields by name.
"""
a = TypeVariable('a', TypeVariableApplication_Nullary(None, None))
b = TypeVariable('b', TypeVariableApplication_Nullary(None, None))
t = TypeConstructorVariable('t')
Eq = Type3Class('Eq', (a, ), methods={}, operators={
'==': [a, a, bool_],
'!=': [a, a, bool_],
# FIXME: Do we want to expose 'eqz'? Or is that a compiler optimization?
})
instance_type_class(Eq, u8, operators={
'==': stdtypes.u8_eq_equals,
'!=': stdtypes.u8_eq_not_equals,
})
instance_type_class(Eq, u16, operators={
'==': stdtypes.u16_eq_equals,
'!=': stdtypes.u16_eq_not_equals,
})
instance_type_class(Eq, u32, operators={
'==': stdtypes.u32_eq_equals,
'!=': stdtypes.u32_eq_not_equals,
})
instance_type_class(Eq, u64, operators={
'==': stdtypes.u64_eq_equals,
'!=': stdtypes.u64_eq_not_equals,
})
instance_type_class(Eq, i8, operators={
'==': stdtypes.i8_eq_equals,
'!=': stdtypes.i8_eq_not_equals,
})
instance_type_class(Eq, i16, operators={
'==': stdtypes.i16_eq_equals,
'!=': stdtypes.i16_eq_not_equals,
})
instance_type_class(Eq, i32, operators={
'==': stdtypes.i32_eq_equals,
'!=': stdtypes.i32_eq_not_equals,
})
instance_type_class(Eq, i64, operators={
'==': stdtypes.i64_eq_equals,
'!=': stdtypes.i64_eq_not_equals,
})
instance_type_class(Eq, f32, operators={
'==': stdtypes.f32_eq_equals,
'!=': stdtypes.f32_eq_not_equals,
})
instance_type_class(Eq, f64, operators={
'==': stdtypes.f64_eq_equals,
'!=': stdtypes.f64_eq_not_equals,
})
Ord = Type3Class('Ord', (a, ), methods={
'min': [a, a, a],
'max': [a, a, a],
}, operators={
'<': [a, a, bool_],
'<=': [a, a, bool_],
'>': [a, a, bool_],
'>=': [a, a, bool_],
}, inherited_classes=[Eq])
instance_type_class(Ord, u8, methods={
'min': stdtypes.u8_ord_min,
'max': stdtypes.u8_ord_max,
}, operators={
'<': stdtypes.u8_ord_less_than,
'<=': stdtypes.u8_ord_less_than_or_equal,
'>': stdtypes.u8_ord_greater_than,
'>=': stdtypes.u8_ord_greater_than_or_equal,
})
instance_type_class(Ord, u16, methods={
'min': stdtypes.u16_ord_min,
'max': stdtypes.u16_ord_max,
}, operators={
'<': stdtypes.u16_ord_less_than,
'<=': stdtypes.u16_ord_less_than_or_equal,
'>': stdtypes.u16_ord_greater_than,
'>=': stdtypes.u16_ord_greater_than_or_equal,
})
instance_type_class(Ord, u32, methods={
'min': stdtypes.u32_ord_min,
'max': stdtypes.u32_ord_max,
}, operators={
'<': stdtypes.u32_ord_less_than,
'<=': stdtypes.u32_ord_less_than_or_equal,
'>': stdtypes.u32_ord_greater_than,
'>=': stdtypes.u32_ord_greater_than_or_equal,
})
instance_type_class(Ord, u64, methods={
'min': stdtypes.u64_ord_min,
'max': stdtypes.u64_ord_max,
}, operators={
'<': stdtypes.u64_ord_less_than,
'<=': stdtypes.u64_ord_less_than_or_equal,
'>': stdtypes.u64_ord_greater_than,
'>=': stdtypes.u64_ord_greater_than_or_equal,
})
instance_type_class(Ord, i8, methods={
'min': stdtypes.i8_ord_min,
'max': stdtypes.i8_ord_max,
}, operators={
'<': stdtypes.i8_ord_less_than,
'<=': stdtypes.i8_ord_less_than_or_equal,
'>': stdtypes.i8_ord_greater_than,
'>=': stdtypes.i8_ord_greater_than_or_equal,
})
instance_type_class(Ord, i16, methods={
'min': stdtypes.i16_ord_min,
'max': stdtypes.i16_ord_max,
}, operators={
'<': stdtypes.i16_ord_less_than,
'<=': stdtypes.i16_ord_less_than_or_equal,
'>': stdtypes.i16_ord_greater_than,
'>=': stdtypes.i16_ord_greater_than_or_equal,
})
instance_type_class(Ord, i32, methods={
'min': stdtypes.i32_ord_min,
'max': stdtypes.i32_ord_max,
}, operators={
'<': stdtypes.i32_ord_less_than,
'<=': stdtypes.i32_ord_less_than_or_equal,
'>': stdtypes.i32_ord_greater_than,
'>=': stdtypes.i32_ord_greater_than_or_equal,
})
instance_type_class(Ord, i64, methods={
'min': stdtypes.i64_ord_min,
'max': stdtypes.i64_ord_max,
}, operators={
'<': stdtypes.i64_ord_less_than,
'<=': stdtypes.i64_ord_less_than_or_equal,
'>': stdtypes.i64_ord_greater_than,
'>=': stdtypes.i64_ord_greater_than_or_equal,
})
instance_type_class(Ord, f32, methods={
'min': stdtypes.f32_ord_min,
'max': stdtypes.f32_ord_max,
}, operators={
'<': stdtypes.f32_ord_less_than,
'<=': stdtypes.f32_ord_less_than_or_equal,
'>': stdtypes.f32_ord_greater_than,
'>=': stdtypes.f32_ord_greater_than_or_equal,
})
instance_type_class(Ord, f64, methods={
'min': stdtypes.f64_ord_min,
'max': stdtypes.f64_ord_max,
}, operators={
'<': stdtypes.f64_ord_less_than,
'<=': stdtypes.f64_ord_less_than_or_equal,
'>': stdtypes.f64_ord_greater_than,
'>=': stdtypes.f64_ord_greater_than_or_equal,
})
Bits = Type3Class('Bits', (a, ), methods={
'shl': [a, u32, a], # Logical shift left
'shr': [a, u32, a], # Logical shift right
'rotl': [a, u32, a], # Rotate bits left
'rotr': [a, u32, a], # Rotate bits right
# FIXME: Do we want to expose clz, ctz, popcnt?
}, operators={
'&': [a, a, a], # Bit-wise and
'|': [a, a, a], # Bit-wise or
'^': [a, a, a], # Bit-wise xor
})
instance_type_class(Bits, u8, methods={
'shl': stdtypes.u8_bits_logical_shift_left,
'shr': stdtypes.u8_bits_logical_shift_right,
'rotl': stdtypes.u8_bits_rotate_left,
'rotr': stdtypes.u8_bits_rotate_right,
}, operators={
'&': stdtypes.u8_bits_bitwise_and,
'|': stdtypes.u8_bits_bitwise_or,
'^': stdtypes.u8_bits_bitwise_xor,
})
instance_type_class(Bits, u16, methods={
'shl': stdtypes.u16_bits_logical_shift_left,
'shr': stdtypes.u16_bits_logical_shift_right,
'rotl': stdtypes.u16_bits_rotate_left,
'rotr': stdtypes.u16_bits_rotate_right,
}, operators={
'&': stdtypes.u16_bits_bitwise_and,
'|': stdtypes.u16_bits_bitwise_or,
'^': stdtypes.u16_bits_bitwise_xor,
})
instance_type_class(Bits, u32, methods={
'shl': stdtypes.u32_bits_logical_shift_left,
'shr': stdtypes.u32_bits_logical_shift_right,
'rotl': stdtypes.u32_bits_rotate_left,
'rotr': stdtypes.u32_bits_rotate_right,
}, operators={
'&': stdtypes.u32_bits_bitwise_and,
'|': stdtypes.u32_bits_bitwise_or,
'^': stdtypes.u32_bits_bitwise_xor,
})
instance_type_class(Bits, u64, methods={
'shl': stdtypes.u64_bits_logical_shift_left,
'shr': stdtypes.u64_bits_logical_shift_right,
'rotl': stdtypes.u64_bits_rotate_left,
'rotr': stdtypes.u64_bits_rotate_right,
}, operators={
'&': stdtypes.u64_bits_bitwise_and,
'|': stdtypes.u64_bits_bitwise_or,
'^': stdtypes.u64_bits_bitwise_xor,
})
NatNum = Type3Class('NatNum', (a, ), methods={}, operators={
'+': [a, a, a],
'-': [a, a, a],
'*': [a, a, a],
'<<': [a, u32, a], # Arithmic shift left
'>>': [a, u32, a], # Arithmic shift right
})
instance_type_class(NatNum, u32, operators={
'+': stdtypes.u32_natnum_add,
'-': stdtypes.u32_natnum_sub,
'*': stdtypes.u32_natnum_mul,
'<<': stdtypes.u32_natnum_arithmic_shift_left,
'>>': stdtypes.u32_natnum_arithmic_shift_right,
})
instance_type_class(NatNum, u64, operators={
'+': stdtypes.u64_natnum_add,
'-': stdtypes.u64_natnum_sub,
'*': stdtypes.u64_natnum_mul,
'<<': stdtypes.u64_natnum_arithmic_shift_left,
'>>': stdtypes.u64_natnum_arithmic_shift_right,
})
instance_type_class(NatNum, i32, operators={
'+': stdtypes.i32_natnum_add,
'-': stdtypes.i32_natnum_sub,
'*': stdtypes.i32_natnum_mul,
'<<': stdtypes.i32_natnum_arithmic_shift_left,
'>>': stdtypes.i32_natnum_arithmic_shift_right,
})
instance_type_class(NatNum, i64, operators={
'+': stdtypes.i64_natnum_add,
'-': stdtypes.i64_natnum_sub,
'*': stdtypes.i64_natnum_mul,
'<<': stdtypes.i64_natnum_arithmic_shift_left,
'>>': stdtypes.i64_natnum_arithmic_shift_right,
})
instance_type_class(NatNum, f32, operators={
'+': stdtypes.f32_natnum_add,
'-': stdtypes.f32_natnum_sub,
'*': stdtypes.f32_natnum_mul,
'<<': stdtypes.f32_natnum_arithmic_shift_left,
'>>': stdtypes.f32_natnum_arithmic_shift_right,
})
instance_type_class(NatNum, f64, operators={
'+': stdtypes.f64_natnum_add,
'-': stdtypes.f64_natnum_sub,
'*': stdtypes.f64_natnum_mul,
'<<': stdtypes.f64_natnum_arithmic_shift_left,
'>>': stdtypes.f64_natnum_arithmic_shift_right,
})
IntNum = Type3Class('IntNum', (a, ), methods={
'abs': [a, a],
'neg': [a, a],
}, operators={}, inherited_classes=[NatNum])
instance_type_class(IntNum, i32, methods={
'abs': stdtypes.i32_intnum_abs,
'neg': stdtypes.i32_intnum_neg,
})
instance_type_class(IntNum, i64, methods={
'abs': stdtypes.i64_intnum_abs,
'neg': stdtypes.i64_intnum_neg,
})
instance_type_class(IntNum, f32, methods={
'abs': stdtypes.f32_intnum_abs,
'neg': stdtypes.f32_intnum_neg,
})
instance_type_class(IntNum, f64, methods={
'abs': stdtypes.f64_intnum_abs,
'neg': stdtypes.f64_intnum_neg,
})
Integral = Type3Class('Integral', (a, ), methods={
}, operators={
'//': [a, a, a],
'%': [a, a, a],
}, inherited_classes=[NatNum])
instance_type_class(Integral, u32, operators={
'//': stdtypes.u32_integral_div,
'%': stdtypes.u32_integral_rem,
})
instance_type_class(Integral, u64, operators={
'//': stdtypes.u64_integral_div,
'%': stdtypes.u64_integral_rem,
})
instance_type_class(Integral, i32, operators={
'//': stdtypes.i32_integral_div,
'%': stdtypes.i32_integral_rem,
})
instance_type_class(Integral, i64, operators={
'//': stdtypes.i64_integral_div,
'%': stdtypes.i64_integral_rem,
})
Fractional = Type3Class('Fractional', (a, ), methods={
'ceil': [a, a],
'floor': [a, a],
'trunc': [a, a],
'nearest': [a, a],
}, operators={
'/': [a, a, a],
}, inherited_classes=[NatNum])
instance_type_class(Fractional, f32, methods={
'ceil': stdtypes.f32_fractional_ceil,
'floor': stdtypes.f32_fractional_floor,
'trunc': stdtypes.f32_fractional_trunc,
'nearest': stdtypes.f32_fractional_nearest,
}, operators={
'/': stdtypes.f32_fractional_div,
})
instance_type_class(Fractional, f64, methods={
'ceil': stdtypes.f64_fractional_ceil,
'floor': stdtypes.f64_fractional_floor,
'trunc': stdtypes.f64_fractional_trunc,
'nearest': stdtypes.f64_fractional_nearest,
}, operators={
'/': stdtypes.f64_fractional_div,
})
Floating = Type3Class('Floating', (a, ), methods={
'sqrt': [a, a],
}, operators={}, inherited_classes=[Fractional])
# FIXME: Do we want to expose copysign?
instance_type_class(Floating, f32, methods={
'sqrt': stdtypes.f32_floating_sqrt,
})
instance_type_class(Floating, f64, methods={
'sqrt': stdtypes.f64_floating_sqrt,
})
Sized_ = Type3Class('Sized', (t, ), methods={
'len': [t(a), u32],
}, operators={}) # FIXME: Once we get type class families, add [] here
instance_type_class(Sized_, dynamic_array, methods={
'len': stdtypes.dynamic_array_sized_len,
})
instance_type_class(Sized_, static_array, methods={
'len': stdtypes.static_array_sized_len,
})
Extendable = Type3Class('Extendable', (a, b, ), methods={
'extend': [a, b],
'wrap': [b, a],
}, operators={})
instance_type_class(Extendable, u8, u16, methods={
'extend': stdtypes.u8_u16_extend,
'wrap': stdtypes.u8_u16_wrap,
})
instance_type_class(Extendable, u8, u32, methods={
'extend': stdtypes.u8_u32_extend,
'wrap': stdtypes.u8_u32_wrap,
})
instance_type_class(Extendable, u8, u64, methods={
'extend': stdtypes.u8_u64_extend,
'wrap': stdtypes.u8_u64_wrap,
})
instance_type_class(Extendable, u16, u32, methods={
'extend': stdtypes.u16_u32_extend,
'wrap': stdtypes.u16_u32_wrap,
})
instance_type_class(Extendable, u16, u64, methods={
'extend': stdtypes.u16_u64_extend,
'wrap': stdtypes.u16_u64_wrap,
})
instance_type_class(Extendable, u32, u64, methods={
'extend': stdtypes.u32_u64_extend,
'wrap': stdtypes.u32_u64_wrap,
})
instance_type_class(Extendable, i8, i16, methods={
'extend': stdtypes.i8_i16_extend,
'wrap': stdtypes.i8_i16_wrap,
})
instance_type_class(Extendable, i8, i32, methods={
'extend': stdtypes.i8_i32_extend,
'wrap': stdtypes.i8_i32_wrap,
})
instance_type_class(Extendable, i8, i64, methods={
'extend': stdtypes.i8_i64_extend,
'wrap': stdtypes.i8_i64_wrap,
})
instance_type_class(Extendable, i16, i32, methods={
'extend': stdtypes.i16_i32_extend,
'wrap': stdtypes.i16_i32_wrap,
})
instance_type_class(Extendable, i16, i64, methods={
'extend': stdtypes.i16_i64_extend,
'wrap': stdtypes.i16_i64_wrap,
})
instance_type_class(Extendable, i32, i64, methods={
'extend': stdtypes.i32_i64_extend,
'wrap': stdtypes.i32_i64_wrap,
})
Promotable = Type3Class('Promotable', (a, b, ), methods={
'promote': [a, b],
'demote': [b, a],
}, operators={})
instance_type_class(Promotable, f32, f64, methods={
'promote': stdtypes.f32_f64_promote,
'demote': stdtypes.f32_f64_demote,
})
Reinterpretable = Type3Class('Reinterpretable', (a, b, ), methods={
'reinterpret': [a, b]
}, operators={})
instance_type_class(Reinterpretable, u32, f32, methods={
'reinterpret': stdtypes.u32_f32_reinterpret,
})
instance_type_class(Reinterpretable, u64, f64, methods={
'reinterpret': stdtypes.u64_f64_reinterpret,
})
instance_type_class(Reinterpretable, i32, f32, methods={
'reinterpret': stdtypes.i32_f32_reinterpret,
})
instance_type_class(Reinterpretable, i64, f64, methods={
'reinterpret': stdtypes.i64_f64_reinterpret,
})
instance_type_class(Reinterpretable, f32, u32, methods={
'reinterpret': stdtypes.f32_u32_reinterpret,
})
instance_type_class(Reinterpretable, f64, u64, methods={
'reinterpret': stdtypes.f64_u64_reinterpret,
})
instance_type_class(Reinterpretable, f32, i32, methods={
'reinterpret': stdtypes.f32_i32_reinterpret,
})
instance_type_class(Reinterpretable, f64, i64, methods={
'reinterpret': stdtypes.f64_i64_reinterpret,
})
Convertable = Type3Class('Convertable', (a, b, ), methods={
'convert': [a, b],
'truncate': [b, a], # To prevent name clas with Fractional
}, operators={})
instance_type_class(Convertable, u32, f32, methods={
'convert': stdtypes.u32_f32_convert,
'truncate': stdtypes.u32_f32_truncate,
})
instance_type_class(Convertable, u32, f64, methods={
'convert': stdtypes.u32_f64_convert,
'truncate': stdtypes.u32_f64_truncate,
})
instance_type_class(Convertable, u64, f32, methods={
'convert': stdtypes.u64_f32_convert,
'truncate': stdtypes.u64_f32_truncate,
})
instance_type_class(Convertable, u64, f64, methods={
'convert': stdtypes.u64_f64_convert,
'truncate': stdtypes.u64_f64_truncate,
})
instance_type_class(Convertable, i32, f32, methods={
'convert': stdtypes.i32_f32_convert,
'truncate': stdtypes.i32_f32_truncate,
})
instance_type_class(Convertable, i32, f64, methods={
'convert': stdtypes.i32_f64_convert,
'truncate': stdtypes.i32_f64_truncate,
})
instance_type_class(Convertable, i64, f32, methods={
'convert': stdtypes.i64_f32_convert,
'truncate': stdtypes.i64_f32_truncate,
})
instance_type_class(Convertable, i64, f64, methods={
'convert': stdtypes.i64_f64_convert,
'truncate': stdtypes.i64_f64_truncate,
})
Foldable = Type3Class('Foldable', (t, ), methods={
'sum': [t(a), a],
'foldl': [[b, a, b], b, t(a), b],
'foldr': [[a, b, b], b, t(a), b],
}, operators={}, additional_context={
'sum': [Constraint_TypeClassInstanceExists(NatNum, (a, ))],
})
instance_type_class(Foldable, dynamic_array, methods={
'sum': stdtypes.dynamic_array_sum,
'foldl': stdtypes.dynamic_array_foldl,
'foldr': stdtypes.dynamic_array_foldr,
})
instance_type_class(Foldable, static_array, methods={
'sum': stdtypes.static_array_sum,
'foldl': stdtypes.static_array_foldl,
'foldr': stdtypes.static_array_foldr,
})
bytes_ = dynamic_array(u8)
PRELUDE_TYPES: dict[str, Type3] = {
'none': none,
'bool': bool_,
'u8': u8,
'u16': u16,
'u32': u32,
'u64': u64,
'i8': i8,
'i16': i16,
'i32': i32,
'i64': i64,
'f32': f32,
'f64': f64,
'bytes': bytes_,
}
PRELUDE_TYPE_CLASSES = {
'Eq': Eq,
'Ord': Ord,
'Bits': Bits,
'NatNum': NatNum,
'IntNum': IntNum,
'Integral': Integral,
'Fractional': Fractional,
'Floating': Floating,
'Extendable': Extendable,
'Promotable': Promotable,
}
PRELUDE_OPERATORS = {
**Bits.operators,
**Eq.operators,
**Ord.operators,
**Fractional.operators,
**Integral.operators,
**IntNum.operators,
**NatNum.operators,
}
PRELUDE_METHODS = {
**Bits.methods,
**Eq.methods,
**Ord.methods,
**Floating.methods,
**Fractional.methods,
**Integral.methods,
**IntNum.methods,
**NatNum.methods,
**Sized_.methods,
**Extendable.methods,
**Promotable.methods,
**Reinterpretable.methods,
**Convertable.methods,
**Foldable.methods,
}

View File

@ -1,62 +0,0 @@
from . import prelude
from .stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
from .type3.routers import NoRouteForTypeException, TypeApplicationRouter
from .type3.types import IntType3, Type3
def calculate_alloc_size_static_array(is_member: bool, args: tuple[Type3, IntType3]) -> int:
if is_member:
return TYPE_INFO_CONSTRUCTED.alloc_size
sa_type, sa_len = args
return sa_len.value * calculate_alloc_size(sa_type, is_member=True)
def calculate_alloc_size_tuple(is_member: bool, args: tuple[Type3, ...]) -> int:
if is_member:
return TYPE_INFO_CONSTRUCTED.alloc_size
return sum(
calculate_alloc_size(x, is_member=True)
for x in args
)
def calculate_alloc_size_struct(is_member: bool, args: tuple[tuple[str, Type3], ...]) -> int:
if is_member:
return TYPE_INFO_CONSTRUCTED.alloc_size
return sum(
calculate_alloc_size(x, is_member=True)
for _, x in args
)
ALLOC_SIZE_ROUTER = TypeApplicationRouter[bool, int]()
ALLOC_SIZE_ROUTER.add(prelude.static_array, calculate_alloc_size_static_array)
ALLOC_SIZE_ROUTER.add(prelude.struct, calculate_alloc_size_struct)
ALLOC_SIZE_ROUTER.add(prelude.tuple_, calculate_alloc_size_tuple)
def calculate_alloc_size(typ: Type3, is_member: bool = False) -> int:
typ_info = TYPE_INFO_MAP.get(typ.name)
if typ_info is not None:
return typ_info.alloc_size
try:
return ALLOC_SIZE_ROUTER(is_member, typ)
except NoRouteForTypeException:
if is_member:
# By default, 'boxed' or 'constructed' types are
# stored as pointers when a member of a struct or tuple
return TYPE_INFO_CONSTRUCTED.alloc_size
raise NotImplementedError(typ)
def calculate_member_offset(st_name: str, st_args: tuple[tuple[str, Type3], ...], needle: str) -> int:
result = 0
for memnam, memtyp in st_args:
if needle == memnam:
return result
result += calculate_alloc_size(memtyp, is_member=True)
raise Exception(f'{needle} not in {st_name}')

View File

@ -1,13 +1,13 @@
"""
stdlib: Standard types that are not wasm primitives
"""
from typing import Mapping, NamedTuple, Type
from typing import Mapping
from phasm.build.base import TypeInfo
from phasm.stdlib import alloc
from phasm.type3.routers import TypeVariableLookup
from phasm.type3.types import IntType3, Type3
from phasm.wasm import (
WasmType,
WasmTypeFloat32,
WasmTypeFloat64,
WasmTypeInt32,
@ -18,22 +18,6 @@ from phasm.wasmgenerator import Generator, func_wrapper
from phasm.wasmgenerator import VarType_i32 as i32
from phasm.wasmgenerator import VarType_i64 as i64
TypeInfo = NamedTuple('TypeInfo', [
# Name of the type
('typ', str, ),
# What WebAssembly type to use when passing this value around
# For example in function arguments
('wasm_type', Type[WasmType]),
# What WebAssembly function to use when loading a value from memory
('wasm_load_func', str),
# What WebAssembly function to use when storing a value to memory
('wasm_store_func', str),
# When storing this value in memory, how many bytes do we use?
# Only valid for non-constructed types, see calculate_alloc_size
# Should match wasm_load_func / wasm_store_func
('alloc_size', int),
])
TYPE_INFO_MAP: Mapping[str, TypeInfo] = {
'none': TypeInfo('none', WasmTypeNone, 'nop', 'nop', 0),
'bool': TypeInfo('bool', WasmTypeInt32, 'i32.load8_u', 'i32.store8', 1),

View File

@ -5,7 +5,8 @@ These need to be resolved before the program can be compiled.
"""
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
from .. import ourlang, prelude
from .. import ourlang
from ..build import builtins
from .functions import FunctionArgument, TypeVariable
from .placeholders import PlaceholderForType, Type3OrPlaceholder
from .routers import NoRouteForTypeException, TypeApplicationRouter
@ -271,7 +272,7 @@ class SameFunctionArgumentConstraint(ConstraintBase):
return [
SameTypeConstraint(
typ,
prelude.function(*exp_type_arg_list),
builtins.function(*exp_type_arg_list),
comment=self.comment,
)
]
@ -326,9 +327,9 @@ class TupleMatchConstraint(ConstraintBase):
]
GENERATE_ROUTER = TypeApplicationRouter['TupleMatchConstraint', CheckResult]()
GENERATE_ROUTER.add(prelude.dynamic_array, _generate_dynamic_array)
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
GENERATE_ROUTER.add(builtins.dynamic_array, _generate_dynamic_array)
GENERATE_ROUTER.add(builtins.static_array, _generate_static_array)
GENERATE_ROUTER.add(builtins.tuple_, _generate_tuple)
def check(self) -> CheckResult:
exp_type = self.exp_type
@ -530,10 +531,10 @@ class LiteralFitsConstraint(ConstraintBase):
return res
GENERATE_ROUTER = TypeApplicationRouter['LiteralFitsConstraint', CheckResult]()
GENERATE_ROUTER.add(prelude.dynamic_array, _generate_dynamic_array)
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
GENERATE_ROUTER.add(prelude.struct, _generate_struct)
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
GENERATE_ROUTER.add(builtins.dynamic_array, _generate_dynamic_array)
GENERATE_ROUTER.add(builtins.static_array, _generate_static_array)
GENERATE_ROUTER.add(builtins.struct, _generate_struct)
GENERATE_ROUTER.add(builtins.tuple_, _generate_tuple)
def check(self) -> CheckResult:
int_table: Dict[str, Tuple[int, bool]] = {
@ -581,7 +582,7 @@ class LiteralFitsConstraint(ConstraintBase):
return Error('Must be real', comment=self.comment) # FIXME: Add line information
if self.type3 is prelude.bytes_:
if self.type3 is builtins.bytes_:
if isinstance(self.literal.value, bytes):
return None
@ -666,9 +667,9 @@ class CanBeSubscriptedConstraint(ConstraintBase):
]
GENERATE_ROUTER = TypeApplicationRouter['CanBeSubscriptedConstraint', CheckResult]()
GENERATE_ROUTER.add_n(prelude.bytes_, _generate_bytes)
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
# GENERATE_ROUTER.add_n(builtins.bytes_, _generate_bytes)
GENERATE_ROUTER.add(builtins.static_array, _generate_static_array)
GENERATE_ROUTER.add(builtins.tuple_, _generate_tuple)
def check(self) -> CheckResult:
if self.type3.resolve_as is None:

View File

@ -32,7 +32,7 @@ ConstraintGenerator = Generator[ConstraintBase, None, None]
def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase]:
ctx = Context()
ctx.type_class_instances_existing.update(prelude.PRELUDE_TYPE_CLASS_INSTANCES_EXISTING)
ctx.type_class_instances_existing.update(inp.build.type_class_instances)
return [*module(ctx, inp)]

View File

@ -4,13 +4,8 @@ import sys
from typing import Any, Callable, Generator, Iterable, List, TextIO, Union
from phasm import compiler, prelude
from phasm.build import builtins
from phasm.codestyle import phasm_render
from phasm.runtime import (
calculate_alloc_size,
calculate_alloc_size_static_array,
calculate_alloc_size_struct,
calculate_alloc_size_tuple,
)
from phasm.stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
from phasm.type3 import types as type3types
from phasm.type3.routers import NoRouteForTypeException, TypeApplicationRouter
@ -285,11 +280,11 @@ def _allocate_memory_stored_tuple(attrs: tuple[runners.RunnerBase, Any], tp_args
return adr
ALLOCATE_MEMORY_STORED_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, Any], Any]()
ALLOCATE_MEMORY_STORED_ROUTER.add_n(prelude.bytes_, _allocate_memory_stored_bytes)
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.dynamic_array, _allocate_memory_stored_dynamic_array)
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.static_array, _allocate_memory_stored_static_array)
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.struct, _allocate_memory_stored_struct)
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.tuple_, _allocate_memory_stored_tuple)
# ALLOCATE_MEMORY_STORED_ROUTER.add_n(prelude.bytes_, _allocate_memory_stored_bytes)
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.dynamic_array, _allocate_memory_stored_dynamic_array)
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.static_array, _allocate_memory_stored_static_array)
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.struct, _allocate_memory_stored_struct)
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.tuple_, _allocate_memory_stored_tuple)
def _load_memory_stored_returned_value(
runner: runners.RunnerBase,
@ -479,8 +474,8 @@ def _load_tuple_from_address(attrs: tuple[runners.RunnerBase, int], tp_args: tup
)
LOAD_FROM_ADDRESS_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, int], Any]()
LOAD_FROM_ADDRESS_ROUTER.add_n(prelude.bytes_, _load_bytes_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(prelude.dynamic_array, _load_dynamic_array_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(prelude.static_array, _load_static_array_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(prelude.struct, _load_struct_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(prelude.tuple_, _load_tuple_from_address)
# LOAD_FROM_ADDRESS_ROUTER.add_n(prelude.bytes_, _load_bytes_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(builtins.dynamic_array, _load_dynamic_array_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(builtins.static_array, _load_static_array_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(builtins.struct, _load_struct_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(builtins.tuple_, _load_tuple_from_address)