From 55a45ff17c3fffe9b2f9e31b2e18bf10ecb5d6ff Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Wed, 16 Nov 2022 13:50:03 +0100 Subject: [PATCH] Trying out some things regarding StaticArray --- phasm/typer.py | 1 + phasm/typing.py | 92 ++++++++++++++----- .../test_lang/test_static_array.py | 2 +- tests/integration/test_lang/test_struct.py | 3 + 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/phasm/typer.py b/phasm/typer.py index abfb370..78f6fce 100644 --- a/phasm/typer.py +++ b/phasm/typer.py @@ -175,6 +175,7 @@ def module_constant_def(ctx: Context, inp: ourlang.ModuleConstantDef) -> None: inp.type_var = from_str(ctx, inp.type_str) assert inp.constant.type_var is not None + # This doesn't work sufficiently with StaticArray ctx.unify(inp.type_var, inp.constant.type_var) def module(inp: ourlang.Module) -> None: diff --git a/phasm/typing.py b/phasm/typing.py index c9ab59a..0c80060 100644 --- a/phasm/typing.py +++ b/phasm/typing.py @@ -1,7 +1,7 @@ """ The phasm type system """ -from typing import Callable, Dict, Iterable, Optional, List, Set, Type +from typing import Any, Callable, Dict, Iterable, Optional, List, Set, Type, Union from typing import TypeVar as MyPyTypeVar import enum @@ -132,17 +132,55 @@ class TypeStruct(TypeBase): ASSERTION_ERROR = 'You must call phasm_type after calling phasm_parse before you can call any other method' class PhasmType: - __slots__ = ('name', ) - name: str + __slots__ = ('name', 'args', 'arg_count', ) - def __init__(self, name: str) -> None: + name: str + args: List[Union['PhasmType', 'TypeVar']] + arg_count: int + + def __init__(self, name: str, arg_count: int = 0) -> None: self.name = name + self.args = [] + self.arg_count = arg_count + + def __call__(self, type_arg: Union['PhasmType', 'TypeVar']) -> 'PhasmType': + assert 0 < self.arg_count + + result = PhasmType(self.name, self.arg_count - 1) + result.args = self.args + [type_arg] + + return result + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, PhasmType): + raise NotImplementedError + + return ( + self.name == other.name + and self.args == other.args + and self.arg_count == other.arg_count + ) + + def __ne__(self, other: Any) -> bool: + if not isinstance(other, PhasmType): + raise NotImplementedError + + return ( + self.name != other.name + or self.args != other.args + or self.arg_count != other.arg_count + ) def __repr__(self) -> str: - return 'PhasmType' + self.name + return ( + 'PhasmType' + self.name + ' ' + + ' '.join(map(repr, self.args)) + ' ' + + ' '.join(['?'] * self.arg_count) + ).strip() PhasmTypeInteger = PhasmType('Integer') PhasmTypeReal = PhasmType('Real') +PhasmTypeStaticArray = PhasmType('StaticArray', 1) class TypingNarrowProtoError(TypingError): """ @@ -331,6 +369,12 @@ class TypeVar: def add_location(self, ref: str) -> None: self.ctx.var_locations[self.ctx_id].add(ref) + def __eq__(self, other: Any) -> bool: + raise NotImplementedError + + def __ne__(self, other: Any) -> bool: + raise NotImplementedError + def __repr__(self) -> str: typ = self.ctx.var_types[self.ctx_id] @@ -396,8 +440,7 @@ class Context: if l_type is not None and r_type is not None and l_type != r_type: raise TypingNarrowError(l, r, 'Type does not match') - else: - self.var_types[n.ctx_id] = l_type + self.var_types[n.ctx_id] = l_type try: for const in self.var_constraints[l_ctx_id].values(): @@ -579,23 +622,22 @@ def from_str(ctx: Context, inp: str, location: Optional[str] = None) -> TypeVar: result.add_location(location) return result - # match = TYPE_MATCH_STATIC_ARRAY.fullmatch(inp) - # if match: - # result = ctx.new_var() - # - # result.add_constraint(TypeConstraintPrimitive(TypeConstraintPrimitive.Primitive.STATIC_ARRAY)) - # result.add_constraint(TypeConstraintSubscript(members=( - # # Make copies so they don't get entangled - # # with each other. - # from_str(ctx, match[1], match[1]) - # for _ in range(int(match[2])) - # ))) - # - # result.add_location(inp) - # - # if location is not None: - # result.add_location(location) - # - # return result + match = TYPE_MATCH_STATIC_ARRAY.fullmatch(inp) + if match: + result = ctx.new_var(PhasmTypeStaticArray) + + result.add_constraint(TypeConstraintSubscript(members=( + # Make copies so they don't get entangled + # with each other. + from_str(ctx, match[1], match[1]) + for _ in range(int(match[2])) + ))) + + result.add_location(inp) + + if location is not None: + result.add_location(location) + + return result raise NotImplementedError(from_str, inp) diff --git a/tests/integration/test_lang/test_static_array.py b/tests/integration/test_lang/test_static_array.py index 39fb1ae..912afd3 100644 --- a/tests/integration/test_lang/test_static_array.py +++ b/tests/integration/test_lang/test_static_array.py @@ -1,6 +1,6 @@ import pytest -from phasm.exceptions import StaticError, TypingError +from phasm.exceptions import TypingError from ..constants import ( ALL_FLOAT_TYPES, ALL_INT_TYPES, COMPLETE_INT_TYPES, COMPLETE_NUMERIC_TYPES, TYPE_MAP diff --git a/tests/integration/test_lang/test_struct.py b/tests/integration/test_lang/test_struct.py index 04846e7..a7218f9 100644 --- a/tests/integration/test_lang/test_struct.py +++ b/tests/integration/test_lang/test_struct.py @@ -1,5 +1,8 @@ import pytest +from phasm.exceptions import StaticError +from phasm.parser import phasm_parse + from ..helpers import Suite @pytest.mark.integration_test