From 4f7608a60106a96c9258ae5ac48721403e4548c4 Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Mon, 19 Sep 2022 12:29:48 +0200 Subject: [PATCH] Fix: ModuleConstantDef type annotation was ignored --- phasm/ourlang.py | 6 ++++-- phasm/parser.py | 2 ++ phasm/typer.py | 5 ++++- tests/integration/test_lang/test_primitives.py | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/phasm/ourlang.py b/phasm/ourlang.py index 9ffe2c4..733476f 100644 --- a/phasm/ourlang.py +++ b/phasm/ourlang.py @@ -296,17 +296,19 @@ class ModuleConstantDef: """ A constant definition within a module """ - __slots__ = ('name', 'lineno', 'type_var', 'constant', 'data_block', ) + __slots__ = ('name', 'lineno', 'type_str', 'type_var', 'constant', 'data_block', ) name: str lineno: int + type_str: str type_var: Optional[TypeVar] constant: Constant data_block: Optional['ModuleDataBlock'] - def __init__(self, name: str, lineno: int, constant: Constant, data_block: Optional['ModuleDataBlock']) -> None: + def __init__(self, name: str, lineno: int, type_str: str, constant: Constant, data_block: Optional['ModuleDataBlock']) -> None: self.name = name self.lineno = lineno + self.type_str = type_str self.type_var = None self.constant = constant self.data_block = data_block diff --git a/phasm/parser.py b/phasm/parser.py index 00c4c16..f6570d1 100644 --- a/phasm/parser.py +++ b/phasm/parser.py @@ -201,6 +201,7 @@ class OurVisitor: return ModuleConstantDef( node.target.id, node.lineno, + self.visit_type(module, node.annotation), self.visit_Module_Constant(module, node.value), None, ) @@ -222,6 +223,7 @@ class OurVisitor: return ModuleConstantDef( node.target.id, node.lineno, + self.visit_type(module, node.annotation), ConstantTuple(tuple_data), data_block, ) diff --git a/phasm/typer.py b/phasm/typer.py index e57e043..ee356eb 100644 --- a/phasm/typer.py +++ b/phasm/typer.py @@ -125,7 +125,10 @@ def function(ctx: Context, inp: ourlang.Function) -> None: def module_constant_def(ctx: Context, inp: ourlang.ModuleConstantDef) -> None: constant(ctx, inp.constant) - inp.type_var = ctx.new_var() + if inp.type_str is None: + inp.type_var = ctx.new_var() + else: + inp.type_var = from_str(ctx, inp.type_str, inp.type_str) assert inp.constant.type_var is not None ctx.unify(inp.type_var, inp.constant.type_var) diff --git a/tests/integration/test_lang/test_primitives.py b/tests/integration/test_lang/test_primitives.py index d63d4ac..441dcdb 100644 --- a/tests/integration/test_lang/test_primitives.py +++ b/tests/integration/test_lang/test_primitives.py @@ -1,5 +1,7 @@ import pytest +from phasm.exceptions import TypingError + from ..helpers import Suite from ..constants import ALL_INT_TYPES, ALL_FLOAT_TYPES, COMPLETE_INT_TYPES, TYPE_MAP @@ -61,6 +63,19 @@ def testEntry() -> {type_}: assert 32.125 == result.returned_value +@pytest.mark.integration_test +def test_module_constant_entanglement(): + code_py = """ +CONSTANT: u8 = 1000 + +@exported +def testEntry() -> u32: + return 14 +""" + + with pytest.raises(TypingError, match='u8.*1000'): + Suite(code_py).run_code() + @pytest.mark.integration_test @pytest.mark.parametrize('type_', ['u32', 'u64']) # FIXME: Support u8, requires an extra AND operation def test_logical_left_shift(type_):