Reworks function lookup

Before this commit, finding the implementation for a type
class method was done with a simple lookup table.

This commit adds a router based on function signature.
This also paves the way for adding type constructor
arguments in function signatures.

And it removes quite a few references to the prelude out
of the compiler.

Also adds a bunch of helper methods to render signatures
as strings.
This commit is contained in:
Johan B.W. de Vries 2025-05-09 17:53:04 +02:00
parent 78c98b1e61
commit 6c627bca01
9 changed files with 457 additions and 369 deletions

View File

@ -11,6 +11,7 @@ from .stdlib import types as stdlib_types
from .type3 import functions as type3functions from .type3 import functions as type3functions
from .type3 import typeclasses as type3classes from .type3 import typeclasses as type3classes
from .type3 import types as type3types from .type3 import types as type3types
from .type3.routers import NoRouteForTypeException, TypeApplicationRouter
from .wasmgenerator import Generator as WasmGenerator from .wasmgenerator import Generator as WasmGenerator
TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before your program can be compiled' TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before your program can be compiled'
@ -29,239 +30,6 @@ LOAD_STORE_TYPE_MAP = {
'bytes': 'i32', # Bytes are passed around as pointers 'bytes': 'i32', # Bytes are passed around as pointers
} }
# For now this is nice & clean, but this will get messy quick
# Especially once we get functions with polymorphying applied types
INSTANCES = {
prelude.Eq.operators['==']: {
'a=u8': stdlib_types.u8_eq_equals,
'a=u32': stdlib_types.u32_eq_equals,
'a=u64': stdlib_types.u64_eq_equals,
'a=i8': stdlib_types.i8_eq_equals,
'a=i32': stdlib_types.i32_eq_equals,
'a=i64': stdlib_types.i64_eq_equals,
'a=f32': stdlib_types.f32_eq_equals,
'a=f64': stdlib_types.f64_eq_equals,
},
prelude.Eq.operators['!=']: {
'a=u8': stdlib_types.u8_eq_not_equals,
'a=u32': stdlib_types.u32_eq_not_equals,
'a=u64': stdlib_types.u64_eq_not_equals,
'a=i8': stdlib_types.i8_eq_not_equals,
'a=i32': stdlib_types.i32_eq_not_equals,
'a=i64': stdlib_types.i64_eq_not_equals,
'a=f32': stdlib_types.f32_eq_not_equals,
'a=f64': stdlib_types.f64_eq_not_equals,
},
prelude.Ord.methods['min']: {
'a=u8': stdlib_types.u8_ord_min,
'a=u32': stdlib_types.u32_ord_min,
'a=u64': stdlib_types.u64_ord_min,
'a=i8': stdlib_types.i8_ord_min,
'a=i32': stdlib_types.i32_ord_min,
'a=i64': stdlib_types.i64_ord_min,
'a=f32': stdlib_types.f32_ord_min,
'a=f64': stdlib_types.f64_ord_min,
},
prelude.Ord.methods['max']: {
'a=u8': stdlib_types.u8_ord_max,
'a=u32': stdlib_types.u32_ord_max,
'a=u64': stdlib_types.u64_ord_max,
'a=i8': stdlib_types.i8_ord_max,
'a=i32': stdlib_types.i32_ord_max,
'a=i64': stdlib_types.i64_ord_max,
'a=f32': stdlib_types.f32_ord_max,
'a=f64': stdlib_types.f64_ord_max,
},
prelude.Ord.operators['<']: {
'a=u8': stdlib_types.u8_ord_less_than,
'a=u32': stdlib_types.u32_ord_less_than,
'a=u64': stdlib_types.u64_ord_less_than,
'a=i8': stdlib_types.i8_ord_less_than,
'a=i32': stdlib_types.i32_ord_less_than,
'a=i64': stdlib_types.i64_ord_less_than,
'a=f32': stdlib_types.f32_ord_less_than,
'a=f64': stdlib_types.f64_ord_less_than,
},
prelude.Ord.operators['<=']: {
'a=u8': stdlib_types.u8_ord_less_than_or_equal,
'a=u32': stdlib_types.u32_ord_less_than_or_equal,
'a=u64': stdlib_types.u64_ord_less_than_or_equal,
'a=i8': stdlib_types.i8_ord_less_than_or_equal,
'a=i32': stdlib_types.i32_ord_less_than_or_equal,
'a=i64': stdlib_types.i64_ord_less_than_or_equal,
'a=f32': stdlib_types.f32_ord_less_than_or_equal,
'a=f64': stdlib_types.f64_ord_less_than_or_equal,
},
prelude.Ord.operators['>']: {
'a=u8': stdlib_types.u8_ord_greater_than,
'a=u32': stdlib_types.u32_ord_greater_than,
'a=u64': stdlib_types.u64_ord_greater_than,
'a=i8': stdlib_types.i8_ord_greater_than,
'a=i32': stdlib_types.i32_ord_greater_than,
'a=i64': stdlib_types.i64_ord_greater_than,
'a=f32': stdlib_types.f32_ord_greater_than,
'a=f64': stdlib_types.f64_ord_greater_than,
},
prelude.Ord.operators['>=']: {
'a=u8': stdlib_types.u8_ord_greater_than_or_equal,
'a=u32': stdlib_types.u32_ord_greater_than_or_equal,
'a=u64': stdlib_types.u64_ord_greater_than_or_equal,
'a=i8': stdlib_types.i8_ord_greater_than_or_equal,
'a=i32': stdlib_types.i32_ord_greater_than_or_equal,
'a=i64': stdlib_types.i64_ord_greater_than_or_equal,
'a=f32': stdlib_types.f32_ord_greater_than_or_equal,
'a=f64': stdlib_types.f64_ord_greater_than_or_equal,
},
prelude.Bits.methods['shl']: {
'a=u8': stdlib_types.u8_bits_logical_shift_left,
'a=u32': stdlib_types.u32_bits_logical_shift_left,
'a=u64': stdlib_types.u64_bits_logical_shift_left,
},
prelude.Bits.methods['shr']: {
'a=u8': stdlib_types.u8_bits_logical_shift_right,
'a=u32': stdlib_types.u32_bits_logical_shift_right,
'a=u64': stdlib_types.u64_bits_logical_shift_right,
},
prelude.Bits.methods['rotl']: {
'a=u8': stdlib_types.u8_bits_rotate_left,
'a=u32': stdlib_types.u32_bits_rotate_left,
'a=u64': stdlib_types.u64_bits_rotate_left,
},
prelude.Bits.methods['rotr']: {
'a=u8': stdlib_types.u8_bits_rotate_right,
'a=u32': stdlib_types.u32_bits_rotate_right,
'a=u64': stdlib_types.u64_bits_rotate_right,
},
prelude.Bits.operators['&']: {
'a=u8': stdlib_types.u8_bits_bitwise_and,
'a=u32': stdlib_types.u32_bits_bitwise_and,
'a=u64': stdlib_types.u64_bits_bitwise_and,
},
prelude.Bits.operators['|']: {
'a=u8': stdlib_types.u8_bits_bitwise_or,
'a=u32': stdlib_types.u32_bits_bitwise_or,
'a=u64': stdlib_types.u64_bits_bitwise_or,
},
prelude.Bits.operators['^']: {
'a=u8': stdlib_types.u8_bits_bitwise_xor,
'a=u32': stdlib_types.u32_bits_bitwise_xor,
'a=u64': stdlib_types.u64_bits_bitwise_xor,
},
prelude.Floating.methods['sqrt']: {
'a=f32': stdlib_types.f32_floating_sqrt,
'a=f64': stdlib_types.f64_floating_sqrt,
},
prelude.Fractional.methods['ceil']: {
'a=f32': stdlib_types.f32_fractional_ceil,
'a=f64': stdlib_types.f64_fractional_ceil,
},
prelude.Fractional.methods['floor']: {
'a=f32': stdlib_types.f32_fractional_floor,
'a=f64': stdlib_types.f64_fractional_floor,
},
prelude.Fractional.methods['trunc']: {
'a=f32': stdlib_types.f32_fractional_trunc,
'a=f64': stdlib_types.f64_fractional_trunc,
},
prelude.Fractional.methods['nearest']: {
'a=f32': stdlib_types.f32_fractional_nearest,
'a=f64': stdlib_types.f64_fractional_nearest,
},
prelude.Fractional.operators['/']: {
'a=f32': stdlib_types.f32_fractional_div,
'a=f64': stdlib_types.f64_fractional_div,
},
prelude.Integral.operators['//']: {
'a=u32': stdlib_types.u32_integral_div,
'a=u64': stdlib_types.u64_integral_div,
'a=i32': stdlib_types.i32_integral_div,
'a=i64': stdlib_types.i64_integral_div,
},
prelude.Integral.operators['%']: {
'a=u32': stdlib_types.u32_integral_rem,
'a=u64': stdlib_types.u64_integral_rem,
'a=i32': stdlib_types.i32_integral_rem,
'a=i64': stdlib_types.i64_integral_rem,
},
prelude.IntNum.methods['abs']: {
'a=i32': stdlib_types.i32_intnum_abs,
'a=i64': stdlib_types.i64_intnum_abs,
'a=f32': stdlib_types.f32_intnum_abs,
'a=f64': stdlib_types.f64_intnum_abs,
},
prelude.IntNum.methods['neg']: {
'a=i32': stdlib_types.i32_intnum_neg,
'a=i64': stdlib_types.i64_intnum_neg,
'a=f32': stdlib_types.f32_intnum_neg,
'a=f64': stdlib_types.f64_intnum_neg,
},
prelude.NatNum.operators['+']: {
'a=u32': stdlib_types.u32_natnum_add,
'a=u64': stdlib_types.u64_natnum_add,
'a=i32': stdlib_types.i32_natnum_add,
'a=i64': stdlib_types.i64_natnum_add,
'a=f32': stdlib_types.f32_natnum_add,
'a=f64': stdlib_types.f64_natnum_add,
},
prelude.NatNum.operators['-']: {
'a=u32': stdlib_types.u32_natnum_sub,
'a=u64': stdlib_types.u64_natnum_sub,
'a=i32': stdlib_types.i32_natnum_sub,
'a=i64': stdlib_types.i64_natnum_sub,
'a=f32': stdlib_types.f32_natnum_sub,
'a=f64': stdlib_types.f64_natnum_sub,
},
prelude.NatNum.operators['*']: {
'a=u32': stdlib_types.u32_natnum_mul,
'a=u64': stdlib_types.u64_natnum_mul,
'a=i32': stdlib_types.i32_natnum_mul,
'a=i64': stdlib_types.i64_natnum_mul,
'a=f32': stdlib_types.f32_natnum_mul,
'a=f64': stdlib_types.f64_natnum_mul,
},
prelude.NatNum.operators['<<']: {
'a=u32': stdlib_types.u32_natnum_arithmic_shift_left,
'a=u64': stdlib_types.u64_natnum_arithmic_shift_left,
'a=i32': stdlib_types.i32_natnum_arithmic_shift_left,
'a=i64': stdlib_types.i64_natnum_arithmic_shift_left,
'a=f32': stdlib_types.f32_natnum_arithmic_shift_left,
'a=f64': stdlib_types.f64_natnum_arithmic_shift_left,
},
prelude.NatNum.operators['>>']: {
'a=u32': stdlib_types.u32_natnum_arithmic_shift_right,
'a=u64': stdlib_types.u64_natnum_arithmic_shift_right,
'a=i32': stdlib_types.i32_natnum_arithmic_shift_right,
'a=i64': stdlib_types.i64_natnum_arithmic_shift_right,
'a=f32': stdlib_types.f32_natnum_arithmic_shift_right,
'a=f64': stdlib_types.f64_natnum_arithmic_shift_right,
},
prelude.Sized_.methods['len']: {
'a=bytes': stdlib_types.bytes_sized_len,
},
prelude.Extendable.methods['extend']: {
'a=u8,b=u32': stdlib_types.u8_u32_extend,
'a=u8,b=u64': stdlib_types.u8_u64_extend,
'a=u32,b=u64': stdlib_types.u32_u64_extend,
'a=i8,b=i32': stdlib_types.i8_i32_extend,
'a=i8,b=i64': stdlib_types.i8_i64_extend,
'a=i32,b=i64': stdlib_types.i32_i64_extend,
},
prelude.Extendable.methods['wrap']: {
'a=u8,b=u32': stdlib_types.u8_u32_wrap,
'a=u8,b=u64': stdlib_types.u8_u64_wrap,
'a=u32,b=u64': stdlib_types.u32_u64_wrap,
'a=i8,b=i32': stdlib_types.i8_i32_wrap,
'a=i8,b=i64': stdlib_types.i8_i64_wrap,
'a=i32,b=i64': stdlib_types.i32_i64_wrap,
},
prelude.Promotable.methods['promote']: {
'a=f32,b=f64': stdlib_types.f32_f64_promote,
},
prelude.Promotable.methods['demote']: {
'a=f32,b=f64': stdlib_types.f32_f64_demote,
},
}
def phasm_compile(inp: ourlang.Module) -> wasm.Module: def phasm_compile(inp: ourlang.Module) -> wasm.Module:
""" """
Public method for compiling a parsed Phasm module into Public method for compiling a parsed Phasm module into
@ -450,7 +218,7 @@ def expression_subscript_tuple(
wgn.add_statement(f'{mtyp}.load', f'offset={offset}') wgn.add_statement(f'{mtyp}.load', f'offset={offset}')
SUBSCRIPT_ROUTER = type3types.TypeApplicationRouter[tuple[WasmGenerator, ourlang.Subscript], None]() SUBSCRIPT_ROUTER = TypeApplicationRouter[tuple[WasmGenerator, ourlang.Subscript], None]()
SUBSCRIPT_ROUTER.add_n(prelude.bytes_, expression_subscript_bytes) SUBSCRIPT_ROUTER.add_n(prelude.bytes_, expression_subscript_bytes)
SUBSCRIPT_ROUTER.add(prelude.static_array, expression_subscript_static_array) SUBSCRIPT_ROUTER.add(prelude.static_array, expression_subscript_static_array)
SUBSCRIPT_ROUTER.add(prelude.tuple_, expression_subscript_tuple) SUBSCRIPT_ROUTER.add(prelude.tuple_, expression_subscript_tuple)
@ -524,8 +292,6 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
expression(wgn, inp.left) expression(wgn, inp.left)
expression(wgn, inp.right) expression(wgn, inp.right)
assert inp.type3 is not None, TYPE3_ASSERTION_ERROR
type_var_map: Dict[type3functions.TypeVariable, type3types.Type3] = {} type_var_map: Dict[type3functions.TypeVariable, type3types.Type3] = {}
for type_var, arg_expr in zip(inp.operator.signature.args, [inp.left, inp.right, inp], strict=True): for type_var, arg_expr in zip(inp.operator.signature.args, [inp.left, inp.right, inp], strict=True):
@ -536,18 +302,10 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
assert arg_expr.type3 is not None, TYPE3_ASSERTION_ERROR assert arg_expr.type3 is not None, TYPE3_ASSERTION_ERROR
type_var_map[type_var] = arg_expr.type3 type_var_map[type_var] = arg_expr.type3
instance_key = ','.join( router = prelude.PRELUDE_TYPE_CLASS_INSTANCE_METHODS[inp.operator]
f'{k.letter}={v.name}' router(wgn, type_var_map)
for k, v in type_var_map.items()
)
instance = INSTANCES.get(inp.operator, {}).get(instance_key, None)
if instance is not None:
instance(wgn)
return return
raise NotImplementedError(inp.operator, instance_key)
if isinstance(inp, ourlang.FunctionCall): if isinstance(inp, ourlang.FunctionCall):
for arg in inp.arguments: for arg in inp.arguments:
expression(wgn, arg) expression(wgn, arg)
@ -564,18 +322,13 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
assert arg_expr.type3 is not None, TYPE3_ASSERTION_ERROR assert arg_expr.type3 is not None, TYPE3_ASSERTION_ERROR
type_var_map[type_var] = arg_expr.type3 type_var_map[type_var] = arg_expr.type3
instance_key = ','.join( router = prelude.PRELUDE_TYPE_CLASS_INSTANCE_METHODS[inp.function]
f'{k.letter}={v.name}' try:
for k, v in sorted(type_var_map.items(), key=lambda x: x[0].letter) router(wgn, type_var_map)
) except NoRouteForTypeException:
raise NotImplementedError(str(inp.function), type_var_map)
instance = INSTANCES.get(inp.function, {}).get(instance_key, None)
if instance is not None:
instance(wgn)
return return
raise NotImplementedError(inp.function, instance_key)
wgn.add_statement('call', '${}'.format(inp.function.name)) wgn.add_statement('call', '${}'.format(inp.function.name))
return return

View File

@ -1,10 +1,15 @@
""" """
The prelude are all the builtin types, type classes and methods The prelude are all the builtin types, type classes and methods
""" """
from ..type3.functions import ( from typing import Callable
TypeVariable, from warnings import warn
)
from ..type3.typeclasses import Type3Class from phasm.stdlib import types as stdtypes
from phasm.wasmgenerator import Generator
from ..type3.functions import TypeVariable
from ..type3.routers import FunctionSignatureRouter
from ..type3.typeclasses import Type3Class, Type3ClassMethod
from ..type3.types import ( from ..type3.types import (
IntType3, IntType3,
Type3, Type3,
@ -16,14 +21,61 @@ from ..type3.types import (
PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: set[tuple[Type3Class, tuple[Type3, ...]]] = set() PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: set[tuple[Type3Class, tuple[Type3, ...]]] = set()
PRELUDE_TYPE_CLASS_INSTANCE_METHODS: dict[Type3ClassMethod, FunctionSignatureRouter[Generator, None]] = {}
def instance_type_class(cls: Type3Class, *typ: Type3) -> None: class MissingImplementationException(Exception):
pass
class MissingImplementationWarning(Warning):
pass
def instance_type_class(
cls: Type3Class,
*typ: Type3,
methods: dict[str, Callable[[Generator], None]] = {},
operators: dict[str, Callable[[Generator], None]] = {},
) -> None:
global PRELUDE_TYPE_CLASS_INSTANCES_EXISTING global PRELUDE_TYPE_CLASS_INSTANCES_EXISTING
global PRELUDE_TYPE_CLASS_INSTANCE_METHODS
assert len(cls.args) == len(typ)
type_var_map = {}
for arg_tv, arg_tp in zip(cls.args, typ, strict=True):
type_var_map[arg_tv] = arg_tp
# TODO: Check for required existing instantiations # TODO: Check for required existing instantiations
PRELUDE_TYPE_CLASS_INSTANCES_EXISTING.add((cls, tuple(typ), )) 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 = FunctionSignatureRouter[Generator, None](method.signature)
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(type_var_map, generator)
for operator_name, operator in cls.operators.items():
router = PRELUDE_TYPE_CLASS_INSTANCE_METHODS.get(operator)
if router is None:
router = FunctionSignatureRouter[Generator, None](operator.signature)
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(type_var_map, generator)
none = Type3('none', TypeApplication_Nullary(None, None)) none = Type3('none', TypeApplication_Nullary(None, None))
""" """
The none type, for when functions simply don't return anything. e.g., IO(). The none type, for when functions simply don't return anything. e.g., IO().
@ -163,14 +215,38 @@ Eq = Type3Class('Eq', [a], methods={}, operators={
# FIXME: Do we want to expose 'eqz'? Or is that a compiler optimization? # FIXME: Do we want to expose 'eqz'? Or is that a compiler optimization?
}) })
instance_type_class(Eq, u8) instance_type_class(Eq, u8, operators={
instance_type_class(Eq, u32) '==': stdtypes.u8_eq_equals,
instance_type_class(Eq, u64) '!=': stdtypes.u8_eq_not_equals,
instance_type_class(Eq, i8) })
instance_type_class(Eq, i32) instance_type_class(Eq, u32, operators={
instance_type_class(Eq, i64) '==': stdtypes.u32_eq_equals,
instance_type_class(Eq, f32) '!=': stdtypes.u32_eq_not_equals,
instance_type_class(Eq, f64) })
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, 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={ Ord = Type3Class('Ord', [a], methods={
'min': [a, a, a], 'min': [a, a, a],
@ -182,14 +258,78 @@ Ord = Type3Class('Ord', [a], methods={
'>=': [a, a, bool_], '>=': [a, a, bool_],
}, inherited_classes=[Eq]) }, inherited_classes=[Eq])
instance_type_class(Ord, u8) instance_type_class(Ord, u8, methods={
instance_type_class(Ord, u32) 'min': stdtypes.u8_ord_min,
instance_type_class(Ord, u64) 'max': stdtypes.u8_ord_max,
instance_type_class(Ord, i8) }, operators={
instance_type_class(Ord, i32) '<': stdtypes.u8_ord_less_than,
instance_type_class(Ord, i64) '<=': stdtypes.u8_ord_less_than_or_equal,
instance_type_class(Ord, f32) '>': stdtypes.u8_ord_greater_than,
instance_type_class(Ord, f64) '>=': stdtypes.u8_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, 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={ Bits = Type3Class('Bits', [a], methods={
'shl': [a, u32, a], # Logical shift left 'shl': [a, u32, a], # Logical shift left
@ -203,9 +343,36 @@ Bits = Type3Class('Bits', [a], methods={
'^': [a, a, a], # Bit-wise xor '^': [a, a, a], # Bit-wise xor
}) })
instance_type_class(Bits, u8) instance_type_class(Bits, u8, methods={
instance_type_class(Bits, u32) 'shl': stdtypes.u8_bits_logical_shift_left,
instance_type_class(Bits, u64) '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, 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={ NatNum = Type3Class('NatNum', [a], methods={}, operators={
'+': [a, a, a], '+': [a, a, a],
@ -215,22 +382,70 @@ NatNum = Type3Class('NatNum', [a], methods={}, operators={
'>>': [a, u32, a], # Arithmic shift right '>>': [a, u32, a], # Arithmic shift right
}) })
instance_type_class(NatNum, u32) instance_type_class(NatNum, u32, operators={
instance_type_class(NatNum, u64) '+': stdtypes.u32_natnum_add,
instance_type_class(NatNum, i32) '-': stdtypes.u32_natnum_sub,
instance_type_class(NatNum, i64) '*': stdtypes.u32_natnum_mul,
instance_type_class(NatNum, f32) '<<': stdtypes.u32_natnum_arithmic_shift_left,
instance_type_class(NatNum, f64) '>>': 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={ IntNum = Type3Class('IntNum', [a], methods={
'abs': [a, a], 'abs': [a, a],
'neg': [a, a], 'neg': [a, a],
}, operators={}, inherited_classes=[NatNum]) }, operators={}, inherited_classes=[NatNum])
instance_type_class(IntNum, i32) instance_type_class(IntNum, i32, methods={
instance_type_class(IntNum, i64) 'abs': stdtypes.i32_intnum_abs,
instance_type_class(IntNum, f32) 'neg': stdtypes.i32_intnum_neg,
instance_type_class(IntNum, f64) })
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('Eq', [a], methods={ Integral = Type3Class('Eq', [a], methods={
}, operators={ }, operators={
@ -238,10 +453,22 @@ Integral = Type3Class('Eq', [a], methods={
'%': [a, a, a], '%': [a, a, a],
}, inherited_classes=[NatNum]) }, inherited_classes=[NatNum])
instance_type_class(Integral, u32) instance_type_class(Integral, u32, operators={
instance_type_class(Integral, u64) '//': stdtypes.u32_integral_div,
instance_type_class(Integral, i32) '%': stdtypes.u32_integral_rem,
instance_type_class(Integral, i64) })
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={ Fractional = Type3Class('Fractional', [a], methods={
'ceil': [a, a], 'ceil': [a, a],
@ -252,8 +479,22 @@ Fractional = Type3Class('Fractional', [a], methods={
'/': [a, a, a], '/': [a, a, a],
}, inherited_classes=[NatNum]) }, inherited_classes=[NatNum])
instance_type_class(Fractional, f32) instance_type_class(Fractional, f32, methods={
instance_type_class(Fractional, f64) '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={ Floating = Type3Class('Floating', [a], methods={
'sqrt': [a, a], 'sqrt': [a, a],
@ -261,33 +502,60 @@ Floating = Type3Class('Floating', [a], methods={
# FIXME: Do we want to expose copysign? # FIXME: Do we want to expose copysign?
instance_type_class(Floating, f32) instance_type_class(Floating, f32, methods={
instance_type_class(Floating, f64) 'sqrt': stdtypes.f32_floating_sqrt,
})
instance_type_class(Floating, f64, methods={
'sqrt': stdtypes.f64_floating_sqrt,
})
Sized_ = Type3Class('Sized', [a], methods={ Sized_ = Type3Class('Sized', [a], methods={
'len': [a, u32], 'len': [a, u32],
}, operators={}) # FIXME: Once we get type class families, add [] here }, operators={}) # FIXME: Once we get type class families, add [] here
instance_type_class(Sized_, bytes_) instance_type_class(Sized_, bytes_, methods={
'len': stdtypes.bytes_sized_len,
})
Extendable = Type3Class('Extendable', [a, b], methods={ Extendable = Type3Class('Extendable', [a, b], methods={
'extend': [a, b], 'extend': [a, b],
'wrap': [b, a], 'wrap': [b, a],
}, operators={}) }, operators={})
instance_type_class(Extendable, u8, u32) instance_type_class(Extendable, u8, u32, methods={
instance_type_class(Extendable, u8, u64) 'extend': stdtypes.u8_u32_extend,
instance_type_class(Extendable, u32, u64) 'wrap': stdtypes.u8_u32_wrap,
instance_type_class(Extendable, i8, i32) })
instance_type_class(Extendable, i8, i64) instance_type_class(Extendable, u8, u64, methods={
instance_type_class(Extendable, i32, i64) 'extend': stdtypes.u8_u64_extend,
'wrap': stdtypes.u8_u64_wrap,
})
instance_type_class(Extendable, u32, u64, methods={
'extend': stdtypes.u32_u64_extend,
'wrap': stdtypes.u32_u64_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, i32, i64, methods={
'extend': stdtypes.i32_i64_extend,
'wrap': stdtypes.i32_i64_wrap,
})
Promotable = Type3Class('Promotable', [a, b], methods={ Promotable = Type3Class('Promotable', [a, b], methods={
'promote': [a, b], 'promote': [a, b],
'demote': [b, a], 'demote': [b, a],
}, operators={}) }, operators={})
instance_type_class(Promotable, f32, f64) instance_type_class(Promotable, f32, f64, methods={
'promote': stdtypes.f32_f64_promote,
'demote': stdtypes.f32_f64_demote,
})
PRELUDE_TYPE_CLASSES = { PRELUDE_TYPE_CLASSES = {
'Eq': Eq, 'Eq': Eq,

View File

@ -1,5 +1,6 @@
from . import prelude from . import prelude
from .type3.types import IntType3, NoRouteForTypeException, Type3, TypeApplicationRouter 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: def calculate_alloc_size_static_array(is_member: bool, args: tuple[Type3, IntType3]) -> int:

View File

@ -8,6 +8,7 @@ from typing import Dict, Iterable, List, Optional, Tuple, Union
from .. import ourlang, prelude from .. import ourlang, prelude
from . import placeholders, typeclasses, types from . import placeholders, typeclasses, types
from .placeholders import PlaceholderForType from .placeholders import PlaceholderForType
from .routers import NoRouteForTypeException, TypeApplicationRouter
class Error: class Error:
@ -189,7 +190,7 @@ class TupleMatchConstraint(ConstraintBase):
for arg, oth_arg in zip(self.args, tp_args, strict=True) for arg, oth_arg in zip(self.args, tp_args, strict=True)
] ]
GENERATE_ROUTER = types.TypeApplicationRouter['TupleMatchConstraint', CheckResult]() GENERATE_ROUTER = TypeApplicationRouter['TupleMatchConstraint', CheckResult]()
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array) GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple) GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
@ -203,7 +204,7 @@ class TupleMatchConstraint(ConstraintBase):
try: try:
return self.__class__.GENERATE_ROUTER(self, exp_type) return self.__class__.GENERATE_ROUTER(self, exp_type)
except types.NoRouteForTypeException: except NoRouteForTypeException:
raise NotImplementedError(exp_type) raise NotImplementedError(exp_type)
class MustImplementTypeClassConstraint(ConstraintBase): class MustImplementTypeClassConstraint(ConstraintBase):
@ -363,7 +364,7 @@ class LiteralFitsConstraint(ConstraintBase):
return res return res
GENERATE_ROUTER = types.TypeApplicationRouter['LiteralFitsConstraint', CheckResult]() GENERATE_ROUTER = TypeApplicationRouter['LiteralFitsConstraint', CheckResult]()
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array) GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
GENERATE_ROUTER.add(prelude.struct, _generate_struct) GENERATE_ROUTER.add(prelude.struct, _generate_struct)
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple) GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
@ -422,7 +423,7 @@ class LiteralFitsConstraint(ConstraintBase):
try: try:
return self.__class__.GENERATE_ROUTER(self, exp_type) return self.__class__.GENERATE_ROUTER(self, exp_type)
except types.NoRouteForTypeException: except NoRouteForTypeException:
raise NotImplementedError(exp_type) raise NotImplementedError(exp_type)
def human_readable(self) -> HumanReadableRet: def human_readable(self) -> HumanReadableRet:
@ -502,7 +503,7 @@ class CanBeSubscriptedConstraint(ConstraintBase):
SameTypeConstraint(tp_args[self.index.value], self.ret_type3, comment=f'Tuple subscript index {self.index.value}'), SameTypeConstraint(tp_args[self.index.value], self.ret_type3, comment=f'Tuple subscript index {self.index.value}'),
] ]
GENERATE_ROUTER = types.TypeApplicationRouter['CanBeSubscriptedConstraint', CheckResult]() GENERATE_ROUTER = TypeApplicationRouter['CanBeSubscriptedConstraint', CheckResult]()
GENERATE_ROUTER.add_n(prelude.bytes_, _generate_bytes) GENERATE_ROUTER.add_n(prelude.bytes_, _generate_bytes)
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array) GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple) GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
@ -517,7 +518,7 @@ class CanBeSubscriptedConstraint(ConstraintBase):
try: try:
return self.__class__.GENERATE_ROUTER(self, exp_type) return self.__class__.GENERATE_ROUTER(self, exp_type)
except types.NoRouteForTypeException: except NoRouteForTypeException:
return Error(f'{exp_type.name} cannot be subscripted') return Error(f'{exp_type.name} cannot be subscripted')
def human_readable(self) -> HumanReadableRet: def human_readable(self) -> HumanReadableRet:

View File

@ -51,22 +51,34 @@ class Constraint_TypeClassInstanceExists(ConstraintBase):
# you can only add a constraint by supplying types for all variables # you can only add a constraint by supplying types for all variables
assert len(self.type_class3.args) == len(self.types) assert len(self.type_class3.args) == len(self.types)
class TypeVariableContext: def __str__(self) -> str:
__slots__ = ('variables', 'constraints', ) return self.type_class3.name + ' ' + ' '.join(x.letter for x in self.types)
def __repr__(self) -> str:
return f'Constraint_TypeClassInstanceExists({self.type_class3.name}, {self.types!r})'
class TypeVariableContext:
__slots__ = ('constraints', )
variables: set[TypeVariable]
constraints: list[ConstraintBase] constraints: list[ConstraintBase]
def __init__(self) -> None: def __init__(self) -> None:
self.variables = set()
self.constraints = [] self.constraints = []
def __copy__(self) -> 'TypeVariableContext': def __copy__(self) -> 'TypeVariableContext':
result = TypeVariableContext() result = TypeVariableContext()
result.variables.update(self.variables)
result.constraints.extend(self.constraints) result.constraints.extend(self.constraints)
return result return result
def __str__(self) -> str:
if not self.constraints:
return ''
return '(' + ', '.join(str(x) for x in self.constraints) + ') => '
def __repr__(self) -> str:
return f'TypeVariableContext({self.constraints!r})'
class FunctionSignature: class FunctionSignature:
__slots__ = ('context', 'args', ) __slots__ = ('context', 'args', )
@ -76,3 +88,9 @@ class FunctionSignature:
def __init__(self, context: TypeVariableContext, args: Iterable[Union['Type3', TypeVariable]]) -> None: def __init__(self, context: TypeVariableContext, args: Iterable[Union['Type3', TypeVariable]]) -> None:
self.context = context.__copy__() self.context = context.__copy__()
self.args = list(args) self.args = list(args)
def __str__(self) -> str:
return str(self.context) + ' -> '.join(x.letter if isinstance(x, TypeVariable) else x.name for x in self.args)
def __repr__(self) -> str:
return f'FunctionSignature({self.context!r}, {self.args!r})'

88
phasm/type3/routers.py Normal file
View File

@ -0,0 +1,88 @@
from typing import Any, Callable, TypeVar
from .functions import FunctionSignature, TypeVariable
from .types import Type3, TypeConstructor_Base
T = TypeVar('T')
class NoRouteForTypeException(Exception):
pass
class TypeApplicationRouter[S, R]:
"""
Helper class to find a method based on a constructed type
"""
__slots__ = ('by_constructor', 'by_type', )
by_constructor: dict[Any, Callable[[S, Any], R]]
"""
Contains all the added routing functions for constructed types
"""
by_type: dict[Type3, Callable[[S], R]]
"""
Contains all the added routing functions for constructed types
"""
def __init__(self) -> None:
self.by_constructor = {}
self.by_type = {}
def add_n(self, typ: Type3, helper: Callable[[S], R]) -> None:
"""
Lets you route to types that were not constructed
Also known types of kind *
"""
self.by_type[typ] = helper
def add(self, constructor: TypeConstructor_Base[T], helper: Callable[[S, T], R]) -> None:
self.by_constructor[constructor] = helper
def __call__(self, arg0: S, typ: Type3) -> R:
t_helper = self.by_type.get(typ)
if t_helper is not None:
return t_helper(arg0)
c_helper = self.by_constructor.get(typ.application.constructor)
if c_helper is not None:
return c_helper(arg0, typ.application.arguments)
raise NoRouteForTypeException(arg0, typ)
class FunctionSignatureRouter[S, R]:
"""
Helper class to find a method based on a function signature
"""
__slots__ = ('signature', 'data', )
signature: FunctionSignature
data: dict[tuple[Type3, ...], Callable[[S], R]]
def __init__(self, signature: FunctionSignature) -> None:
self.signature = signature
self.data = {}
def add(self, tv_map: dict[TypeVariable, Type3], helper: Callable[[S], R]) -> None:
key = tuple(
tv_map[x]
for x in self.signature.args
if isinstance(x, TypeVariable)
)
# assert len(key) == len(tv_map), (key, tv_map)
self.data[key] = helper
def __call__(self, arg0: S, tv_map: dict[TypeVariable, Type3]) -> R:
key = tuple(
tv_map[x]
for x in self.signature.args
if isinstance(x, TypeVariable)
)
t_helper = self.data.get(key)
if t_helper is not None:
return t_helper(arg0)
raise NoRouteForTypeException(arg0, tv_map)

View File

@ -19,6 +19,9 @@ class Type3ClassMethod:
self.name = name self.name = name
self.signature = signature self.signature = signature
def __str__(self) -> str:
return f'{self.name} :: {self.signature}'
def __repr__(self) -> str: def __repr__(self) -> str:
return f'Type3ClassMethod({repr(self.name)}, {repr(self.signature)})' return f'Type3ClassMethod({repr(self.name)}, {repr(self.signature)})'

View File

@ -248,48 +248,3 @@ class TypeConstructor_Struct(TypeConstructor_Base[tuple[tuple[str, Type3], ...]]
class TypeApplication_Struct(TypeApplication_Base[TypeConstructor_Struct, tuple[tuple[str, Type3], ...]]): class TypeApplication_Struct(TypeApplication_Base[TypeConstructor_Struct, tuple[tuple[str, Type3], ...]]):
pass pass
class NoRouteForTypeException(Exception):
pass
class TypeApplicationRouter[S, R]:
"""
Helper class to find a method based on a constructed type
"""
__slots__ = ('by_constructor', 'by_type', )
by_constructor: dict[Any, Callable[[S, Any], R]]
"""
Contains all the added routing functions for constructed types
"""
by_type: dict[Type3, Callable[[S], R]]
"""
Contains all the added routing functions for constructed types
"""
def __init__(self) -> None:
self.by_constructor = {}
self.by_type = {}
def add_n(self, typ: Type3, helper: Callable[[S], R]) -> None:
"""
Lets you route to types that were not constructed
Also known types of kind *
"""
self.by_type[typ] = helper
def add(self, constructor: TypeConstructor_Base[T], helper: Callable[[S, T], R]) -> None:
self.by_constructor[constructor] = helper
def __call__(self, arg0: S, typ: Type3) -> R:
t_helper = self.by_type.get(typ)
if t_helper is not None:
return t_helper(arg0)
c_helper = self.by_constructor.get(typ.application.constructor)
if c_helper is not None:
return c_helper(arg0, typ.application.arguments)
raise NoRouteForTypeException(arg0, typ)

View File

@ -11,6 +11,7 @@ from phasm.runtime import (
calculate_alloc_size_tuple, calculate_alloc_size_tuple,
) )
from phasm.type3 import types as type3types from phasm.type3 import types as type3types
from phasm.type3.routers import NoRouteForTypeException, TypeApplicationRouter
from . import runners from . import runners
@ -87,7 +88,7 @@ class Suite:
try: try:
adr = ALLOCATE_MEMORY_STORED_ROUTER((runner, arg), arg_typ) adr = ALLOCATE_MEMORY_STORED_ROUTER((runner, arg), arg_typ)
wasm_args.append(adr) wasm_args.append(adr)
except type3types.NoRouteForTypeException: except NoRouteForTypeException:
raise NotImplementedError(arg_typ, arg) raise NotImplementedError(arg_typ, arg)
write_header(sys.stderr, 'Memory (pre run)') write_header(sys.stderr, 'Memory (pre run)')
@ -131,7 +132,7 @@ def _write_memory_stored_value(
adr2 = ALLOCATE_MEMORY_STORED_ROUTER((runner, val), val_typ) adr2 = ALLOCATE_MEMORY_STORED_ROUTER((runner, val), val_typ)
runner.interpreter_write_memory(adr, compiler.module_data_u32(adr2)) runner.interpreter_write_memory(adr, compiler.module_data_u32(adr2))
return 4 return 4
except type3types.NoRouteForTypeException: except NoRouteForTypeException:
to_write = WRITE_LOOKUP_MAP[val_typ.name](val) to_write = WRITE_LOOKUP_MAP[val_typ.name](val)
runner.interpreter_write_memory(adr, to_write) runner.interpreter_write_memory(adr, to_write)
return len(to_write) return len(to_write)
@ -205,7 +206,7 @@ def _allocate_memory_stored_tuple(attrs: tuple[runners.RunnerBase, Any], tp_args
offset += _write_memory_stored_value(runner, offset, val_el_typ, val_el_val) offset += _write_memory_stored_value(runner, offset, val_el_typ, val_el_val)
return adr return adr
ALLOCATE_MEMORY_STORED_ROUTER = type3types.TypeApplicationRouter[tuple[runners.RunnerBase, Any], Any]() 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_n(prelude.bytes_, _allocate_memory_stored_bytes)
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.static_array, _allocate_memory_stored_static_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.struct, _allocate_memory_stored_struct)
@ -373,7 +374,7 @@ def _load_tuple_from_address(attrs: tuple[runners.RunnerBase, int], tp_args: tup
for arg_typ, arg_bytes in zip(tp_args, _split_read_bytes(read_bytes, arg_sizes), strict=True) for arg_typ, arg_bytes in zip(tp_args, _split_read_bytes(read_bytes, arg_sizes), strict=True)
) )
LOAD_FROM_ADDRESS_ROUTER = type3types.TypeApplicationRouter[tuple[runners.RunnerBase, int], Any]() 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_n(prelude.bytes_, _load_bytes_from_address)
LOAD_FROM_ADDRESS_ROUTER.add(prelude.static_array, _load_static_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.struct, _load_struct_from_address)