diff --git a/phasm/codestyle.py b/phasm/codestyle.py index d36d60f..1ab8430 100644 --- a/phasm/codestyle.py +++ b/phasm/codestyle.py @@ -6,7 +6,6 @@ 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 .type3.placeholders import TYPE3_ASSERTION_ERROR, Type3OrPlaceholder from .type3.types import Type3 @@ -18,12 +17,10 @@ def phasm_render(inp: ourlang.Module) -> str: Statements = Generator[str, None, None] -def type3(inp: Type3OrPlaceholder) -> str: +def type3(inp: Type3) -> str: """ Render: type's name """ - assert isinstance(inp, Type3), TYPE3_ASSERTION_ERROR - if inp is prelude.none: return 'None' diff --git a/phasm/compiler.py b/phasm/compiler.py index 9903011..66409b2 100644 --- a/phasm/compiler.py +++ b/phasm/compiler.py @@ -9,11 +9,12 @@ from .runtime import calculate_alloc_size, calculate_member_offset from .stdlib import alloc as stdlib_alloc from .stdlib import types as stdlib_types from .type3 import functions as type3functions -from .type3 import placeholders as type3placeholders from .type3 import typeclasses as type3classes from .type3 import types as type3types from .wasmgenerator import Generator as WasmGenerator +TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before your program can be compiled' + LOAD_STORE_TYPE_MAP = { 'i8': 'i32', # Have to use an u32, since there is no native i8 type 'u8': 'i32', # Have to use an u32, since there is no native u8 type @@ -268,14 +269,14 @@ def phasm_compile(inp: ourlang.Module) -> wasm.Module: """ return module(inp) -def type3(inp: type3placeholders.Type3OrPlaceholder) -> wasm.WasmType: +def type3(inp: type3types.Type3) -> wasm.WasmType: """ Compile: type Types are used for example in WebAssembly function parameters and return types. """ - assert isinstance(inp, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert inp is not None, TYPE3_ASSERTION_ERROR if inp == prelude.none: return wasm.WasmTypeNone() @@ -327,7 +328,7 @@ def tuple_instantiation(wgn: WasmGenerator, inp: ourlang.TupleInstantiation) -> """ Compile: Instantiation (allocation) of a tuple """ - assert isinstance(inp.type3, type3types.Type3) + assert inp.type3 is not None, TYPE3_ASSERTION_ERROR args: list[type3types.Type3] = [] @@ -345,7 +346,7 @@ def tuple_instantiation(wgn: WasmGenerator, inp: ourlang.TupleInstantiation) -> comment_elements = '' for element in inp.elements: - assert isinstance(element.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert element.type3 is not None, TYPE3_ASSERTION_ERROR comment_elements += f'{element.type3.name}, ' tmp_var = wgn.temp_var_i32('tuple_adr') @@ -359,17 +360,11 @@ def tuple_instantiation(wgn: WasmGenerator, inp: ourlang.TupleInstantiation) -> # Store each element individually offset = 0 for element, exp_type3 in zip(inp.elements, args, strict=True): - if isinstance(exp_type3, type3placeholders.PlaceholderForType): - assert exp_type3.resolve_as is not None - assert isinstance(exp_type3.resolve_as, type3types.Type3) - exp_type3 = exp_type3.resolve_as - assert element.type3 == exp_type3 if (prelude.InternalPassAsPointer, (exp_type3, )) in prelude.PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: mtyp = 'i32' else: - assert isinstance(exp_type3, type3types.Type3), NotImplementedError('Tuple of applied types / structs') mtyp = LOAD_STORE_TYPE_MAP[exp_type3.name] wgn.add_statement('nop', comment='PRE') @@ -392,7 +387,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: raise Exception if isinstance(inp, ourlang.ConstantPrimitive): - assert isinstance(inp.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert inp.type3 is not None, TYPE3_ASSERTION_ERROR if inp.type3 in (prelude.i8, prelude.u8, ): # No native u8 type - treat as i32, with caution @@ -433,7 +428,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: return if isinstance(inp.variable, ourlang.ModuleConstantDef): - assert isinstance(inp.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert inp.type3 is not None, TYPE3_ASSERTION_ERROR if (prelude.InternalPassAsPointer, (inp.type3, )) in prelude.PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: assert isinstance(inp.variable.constant, (ourlang.ConstantBytes, ourlang.ConstantStruct, ourlang.ConstantTuple, )) @@ -443,11 +438,8 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: wgn.i32.const(address) return - if isinstance(inp.type3, type3types.Type3): - expression(wgn, inp.variable.constant) - return - - raise NotImplementedError(expression, inp) + expression(wgn, inp.variable.constant) + return raise NotImplementedError(expression, inp.variable) @@ -455,7 +447,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: expression(wgn, inp.left) expression(wgn, inp.right) - assert isinstance(inp.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert inp.type3 is not None, TYPE3_ASSERTION_ERROR type_var_map: Dict[type3functions.TypeVariable, type3types.Type3] = {} @@ -464,7 +456,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: # Fixed type, not part of the lookup requirements continue - assert isinstance(arg_expr.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert arg_expr.type3 is not None, TYPE3_ASSERTION_ERROR type_var_map[type_var] = arg_expr.type3 instance_key = ','.join( @@ -492,7 +484,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: # Fixed type, not part of the lookup requirements continue - assert isinstance(arg_expr.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert arg_expr.type3 is not None, TYPE3_ASSERTION_ERROR type_var_map[type_var] = arg_expr.type3 instance_key = ','.join( @@ -515,7 +507,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: return if isinstance(inp, ourlang.Subscript): - assert isinstance(inp.varref.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert inp.varref.type3 is not None, TYPE3_ASSERTION_ERROR if inp.varref.type3 is prelude.bytes_: expression(wgn, inp.varref) @@ -523,7 +515,7 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: wgn.call(stdlib_types.__subscript_bytes__) return - assert isinstance(inp.varref.type3, type3types.Type3) + assert inp.varref.type3 is not None, TYPE3_ASSERTION_ERROR sa_args = prelude.static_array.did_construct(inp.varref.type3) if sa_args is not None: @@ -549,7 +541,6 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: wgn.i32.mul() wgn.i32.add() - assert isinstance(el_type, type3types.Type3), NotImplementedError('Tuple of applied types / structs') mtyp = LOAD_STORE_TYPE_MAP[el_type.name] wgn.add_statement(f'{mtyp}.load') @@ -562,18 +553,17 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: offset = 0 for el_type in tp_args[0:inp.index.value]: - assert isinstance(el_type, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert el_type is not None, TYPE3_ASSERTION_ERROR offset += calculate_alloc_size(el_type) el_type = tp_args[inp.index.value] - assert isinstance(el_type, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert el_type is not None, TYPE3_ASSERTION_ERROR expression(wgn, inp.varref) if (prelude.InternalPassAsPointer, (el_type, )) in prelude.PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: mtyp = 'i32' else: - assert isinstance(el_type, type3types.Type3), NotImplementedError('Tuple of applied types / structs') mtyp = LOAD_STORE_TYPE_MAP[el_type.name] wgn.add_statement(f'{mtyp}.load', f'offset={offset}') @@ -582,14 +572,13 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: raise NotImplementedError(expression, inp, inp.varref.type3) if isinstance(inp, ourlang.AccessStructMember): - assert isinstance(inp.struct_type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert inp.struct_type3 is not None, TYPE3_ASSERTION_ERROR st_args = prelude.struct.did_construct(inp.struct_type3) assert st_args is not None member_type = st_args[inp.member] - assert isinstance(member_type, type3types.Type3), NotImplementedError('Tuple of applied types / structs') mtyp = LOAD_STORE_TYPE_MAP[member_type.name] expression(wgn, inp.varref) @@ -608,7 +597,7 @@ def expression_fold(wgn: WasmGenerator, inp: ourlang.Fold) -> None: """ Compile: Fold expression """ - assert isinstance(inp.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR + assert inp.type3 is not None, TYPE3_ASSERTION_ERROR if inp.iter.type3 is not prelude.bytes_: raise NotImplementedError(expression_fold, inp, inp.iter.type3) @@ -839,7 +828,7 @@ def module_data(inp: ourlang.ModuleData) -> bytes: data_list: List[bytes] = [] for constant in block.data: - assert isinstance(constant.type3, type3types.Type3), (id(constant), type3placeholders.TYPE3_ASSERTION_ERROR) + assert constant.type3 is not None, TYPE3_ASSERTION_ERROR if isinstance(constant, ourlang.ConstantMemoryStored) and block is not constant.data_block: # It's stored in a different block diff --git a/phasm/parser.py b/phasm/parser.py index 06a0b6f..5440eba 100644 --- a/phasm/parser.py +++ b/phasm/parser.py @@ -163,8 +163,8 @@ class OurVisitor: arg_type = self.visit_type(module, arg.annotation) - # if isisntance(arg_type, TypeVariable): - # arg_type = PlaceHolderForType() + # FIXME: Allow TypeVariable in the function signature + # This would also require FunctionParam to accept a placeholder function.signature.args.append(arg_type) function.posonlyargs.append(FunctionParam( diff --git a/phasm/type3/placeholders.py b/phasm/type3/placeholders.py index a6b6c99..58f8467 100644 --- a/phasm/type3/placeholders.py +++ b/phasm/type3/placeholders.py @@ -7,7 +7,6 @@ from typing import Any, Iterable, List, Optional, Protocol, Union from .types import Type3 -TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before you can call any other method' class ExpressionProtocol(Protocol): """ diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 26d17ae..3f6b8f0 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -5,7 +5,6 @@ from typing import Any, Generator, Iterable, List, TextIO, Union from phasm import compiler, prelude from phasm.codestyle import phasm_render from phasm.runtime import calculate_alloc_size -from phasm.type3 import placeholders as type3placeholders from phasm.type3 import types as type3types from . import runners @@ -65,9 +64,6 @@ class Suite: runner.interpreter_dump_memory(sys.stderr) for arg, arg_typ in zip(args, func_args, strict=True): - assert not isinstance(arg_typ, type3placeholders.PlaceholderForType), \ - 'Cannot call polymorphic function from outside' - if arg_typ in (prelude.u8, prelude.u32, prelude.u64, ): assert isinstance(arg, int) wasm_args.append(arg) @@ -88,7 +84,6 @@ class Suite: wasm_args.append(adr) continue - assert isinstance(arg_typ, type3types.Type3) sa_args = prelude.static_array.did_construct(arg_typ) if sa_args is not None: adr = _allocate_memory_stored_value(runner, arg_typ, arg) @@ -222,8 +217,6 @@ def _allocate_memory_stored_value( offset = adr for val_el_val, val_el_typ in zip(val, tp_args, strict=True): - assert not isinstance(val_el_typ, type3placeholders.PlaceholderForType) - offset += _write_memory_stored_value(runner, offset, val_el_typ, val_el_val) return adr @@ -240,8 +233,6 @@ def _allocate_memory_stored_value( offset = adr for val_el_name, val_el_typ in st_args.items(): - assert not isinstance(val_el_typ, type3placeholders.PlaceholderForType) - val_el_val = val[val_el_name] offset += _write_memory_stored_value(runner, offset, val_el_typ, val_el_val) return adr @@ -299,8 +290,6 @@ def _load_memory_stored_returned_value( return _load_bytes_from_address(runner, ret_type3, wasm_value) - assert isinstance(ret_type3, type3types.Type3) # Type hint - sa_args = prelude.static_array.did_construct(ret_type3) if sa_args is not None: assert isinstance(wasm_value, int), wasm_value @@ -366,8 +355,6 @@ def _unpack(runner: runners.RunnerBase, typ: type3types.Type3, inp: bytes) -> An assert len(inp) == 4 adr = struct.unpack(' Generator def _load_static_array_from_address(runner: runners.RunnerBase, sub_typ: type3types.Type3, len_typ: type3types.IntType3, adr: int) -> Any: sys.stderr.write(f'Reading 0x{adr:08x} {sub_typ:s} {len_typ:s}\n') - assert not isinstance(sub_typ, type3placeholders.PlaceholderForType) - assert isinstance(len_typ, type3types.IntType3) - sa_len = len_typ.value arg_size_1 = calculate_alloc_size(sub_typ, is_member=True)