Removes some hardcoded references to prelude

This commit is contained in:
Johan B.W. de Vries 2025-04-27 12:10:27 +02:00
parent faaf7912b1
commit 292c9548fb
3 changed files with 48 additions and 26 deletions

View File

@ -7,8 +7,8 @@ from typing import Dict, Iterable, List, Optional, Union
from typing_extensions import Final
from . import prelude
from .type3 import typeclasses as type3typeclasses
from .type3.placeholders import PlaceholderForType, Type3OrPlaceholder
from .type3.typeclasses import Type3ClassMethod
from .type3.types import Type3
WEBASSEMBLY_BUILTIN_BYTES_OPS: Final = ('len', )
@ -150,11 +150,11 @@ class BinaryOp(Expression):
"""
__slots__ = ('operator', 'left', 'right', )
operator: type3typeclasses.Type3ClassMethod
operator: Type3ClassMethod
left: Expression
right: Expression
def __init__(self, operator: type3typeclasses.Type3ClassMethod, left: Expression, right: Expression) -> None:
def __init__(self, operator: Type3ClassMethod, left: Expression, right: Expression) -> None:
super().__init__()
self.operator = operator
@ -170,10 +170,10 @@ class FunctionCall(Expression):
"""
__slots__ = ('function', 'arguments', )
function: Union['Function', type3typeclasses.Type3ClassMethod]
function: Union['Function', Type3ClassMethod]
arguments: List[Expression]
def __init__(self, function: Union['Function', type3typeclasses.Type3ClassMethod]) -> None:
def __init__(self, function: Union['Function', Type3ClassMethod]) -> None:
super().__init__()
self.function = function
@ -411,15 +411,19 @@ class Module:
"""
A module is a file and consists of functions
"""
__slots__ = ('data', 'types', 'struct_definitions', 'constant_defs', 'functions',)
__slots__ = ('data', 'types', 'struct_definitions', 'constant_defs', 'functions', 'operators', )
data: ModuleData
types: dict[str, Type3]
struct_definitions: Dict[str, StructDefinition]
constant_defs: Dict[str, ModuleConstantDef]
functions: Dict[str, Function]
operators: Dict[str, Type3ClassMethod]
def __init__(self) -> None:
self.data = ModuleData()
self.types = {}
self.struct_definitions = {}
self.constant_defs = {}
self.functions = {}
self.operators = {}

View File

@ -97,6 +97,9 @@ class OurVisitor:
def visit_Module(self, node: ast.Module) -> Module:
module = Module()
module.operators.update(PRELUDE_OPERATORS)
module.types.update(PRELUDE_TYPES)
_not_implemented(not node.type_ignores, 'Module.type_ignores')
# Second pass for the types
@ -113,14 +116,15 @@ class OurVisitor:
module.constant_defs[res.name] = res
if isinstance(res, StructDefinition):
if res.struct_type3.name in module.struct_definitions:
if res.struct_type3.name in module.types:
raise StaticError(
f'{res.struct_type3.name} already defined on line {module.struct_definitions[res.struct_type3.name].lineno}'
f'{res.struct_type3.name} already defined as type'
)
module.types[res.struct_type3.name] = res.struct_type3
module.functions[res.struct_type3.name] = StructConstructor(res.struct_type3)
# Store that the definition was done in this module for the formatter
module.struct_definitions[res.struct_type3.name] = res
constructor = StructConstructor(res.struct_type3)
module.functions[constructor.name] = constructor
if isinstance(res, Function):
if res.name in module.functions:
@ -367,11 +371,11 @@ class OurVisitor:
else:
raise NotImplementedError(f'Operator {node.op}')
if operator not in PRELUDE_OPERATORS:
if operator not in module.operators:
raise NotImplementedError(f'Operator {operator}')
return BinaryOp(
PRELUDE_OPERATORS[operator],
module.operators[operator],
self.visit_Module_FunctionDef_expr(module, function, our_locals, node.left),
self.visit_Module_FunctionDef_expr(module, function, our_locals, node.right),
)
@ -408,11 +412,11 @@ class OurVisitor:
else:
raise NotImplementedError(f'Operator {node.ops}')
if operator not in PRELUDE_OPERATORS:
if operator not in module.operators:
raise NotImplementedError(f'Operator {operator}')
return BinaryOp(
PRELUDE_OPERATORS[operator],
module.operators[operator],
self.visit_Module_FunctionDef_expr(module, function, our_locals, node.left),
self.visit_Module_FunctionDef_expr(module, function, our_locals, node.comparators[0]),
)
@ -476,13 +480,6 @@ class OurVisitor:
if node.func.id in PRELUDE_METHODS:
func = PRELUDE_METHODS[node.func.id]
elif node.func.id in module.struct_definitions:
struct_definition = module.struct_definitions[node.func.id]
struct_constructor = StructConstructor(struct_definition.struct_type3)
# FIXME: Defer struct de-allocation
func = module.functions[struct_constructor.name]
elif node.func.id == 'u32':
if 1 != len(node.args):
_raise_static_error(node, f'Function {node.func.id} requires 1 arguments but {len(node.args)} are given')
@ -654,11 +651,8 @@ class OurVisitor:
if not isinstance(node.ctx, ast.Load):
_raise_static_error(node, 'Must be load context')
if node.id in PRELUDE_TYPES:
return PRELUDE_TYPES[node.id]
if node.id in module.struct_definitions:
return module.struct_definitions[node.id].struct_type3
if node.id in module.types:
return module.types[node.id]
_raise_static_error(node, f'Unrecognized type {node.id}')

View File

@ -1,5 +1,6 @@
import pytest
from phasm.exceptions import StaticError
from phasm.type3.entry import Type3Exception
from ..helpers import Suite
@ -76,3 +77,26 @@ def testEntry(arg: Struct) -> (i32, i32, ):
with pytest.raises(Type3Exception, match=type_ + r' must be \(i32, i32, \) instead'):
Suite(code_py).run_code()
@pytest.mark.integration_test
def test_name_already_use_struct():
code_py = """
class Struct:
param: i32
class Struct:
param: i64
"""
with pytest.raises(StaticError, match='Struct already defined as type'):
Suite(code_py).run_code()
@pytest.mark.integration_test
def test_name_already_use_type():
code_py = """
class f32:
param: i32
"""
with pytest.raises(StaticError, match='f32 already defined as type'):
Suite(code_py).run_code()