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

View File

@ -97,6 +97,9 @@ class OurVisitor:
def visit_Module(self, node: ast.Module) -> Module: def visit_Module(self, node: ast.Module) -> Module:
module = Module() module = Module()
module.operators.update(PRELUDE_OPERATORS)
module.types.update(PRELUDE_TYPES)
_not_implemented(not node.type_ignores, 'Module.type_ignores') _not_implemented(not node.type_ignores, 'Module.type_ignores')
# Second pass for the types # Second pass for the types
@ -113,14 +116,15 @@ class OurVisitor:
module.constant_defs[res.name] = res module.constant_defs[res.name] = res
if isinstance(res, StructDefinition): if isinstance(res, StructDefinition):
if res.struct_type3.name in module.struct_definitions: if res.struct_type3.name in module.types:
raise StaticError( 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 module.struct_definitions[res.struct_type3.name] = res
constructor = StructConstructor(res.struct_type3)
module.functions[constructor.name] = constructor
if isinstance(res, Function): if isinstance(res, Function):
if res.name in module.functions: if res.name in module.functions:
@ -367,11 +371,11 @@ class OurVisitor:
else: else:
raise NotImplementedError(f'Operator {node.op}') raise NotImplementedError(f'Operator {node.op}')
if operator not in PRELUDE_OPERATORS: if operator not in module.operators:
raise NotImplementedError(f'Operator {operator}') raise NotImplementedError(f'Operator {operator}')
return BinaryOp( 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.left),
self.visit_Module_FunctionDef_expr(module, function, our_locals, node.right), self.visit_Module_FunctionDef_expr(module, function, our_locals, node.right),
) )
@ -408,11 +412,11 @@ class OurVisitor:
else: else:
raise NotImplementedError(f'Operator {node.ops}') raise NotImplementedError(f'Operator {node.ops}')
if operator not in PRELUDE_OPERATORS: if operator not in module.operators:
raise NotImplementedError(f'Operator {operator}') raise NotImplementedError(f'Operator {operator}')
return BinaryOp( 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.left),
self.visit_Module_FunctionDef_expr(module, function, our_locals, node.comparators[0]), 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: if node.func.id in PRELUDE_METHODS:
func = PRELUDE_METHODS[node.func.id] 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': elif node.func.id == 'u32':
if 1 != len(node.args): if 1 != len(node.args):
_raise_static_error(node, f'Function {node.func.id} requires 1 arguments but {len(node.args)} are given') _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): if not isinstance(node.ctx, ast.Load):
_raise_static_error(node, 'Must be load context') _raise_static_error(node, 'Must be load context')
if node.id in PRELUDE_TYPES: if node.id in module.types:
return PRELUDE_TYPES[node.id] return module.types[node.id]
if node.id in module.struct_definitions:
return module.struct_definitions[node.id].struct_type3
_raise_static_error(node, f'Unrecognized type {node.id}') _raise_static_error(node, f'Unrecognized type {node.id}')

View File

@ -1,5 +1,6 @@
import pytest import pytest
from phasm.exceptions import StaticError
from phasm.type3.entry import Type3Exception from phasm.type3.entry import Type3Exception
from ..helpers import Suite 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'): with pytest.raises(Type3Exception, match=type_ + r' must be \(i32, i32, \) instead'):
Suite(code_py).run_code() 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()