phasm/phasm/ourlang.py
Johan B.W. de Vries 1d107d1baa Notes
2025-07-19 19:41:47 +02:00

418 lines
11 KiB
Python

"""
Contains the syntax tree for ourlang
"""
from typing import Dict, Iterable, List, Optional, Union
from .build.base import BuildBase
from .type3.functions import FunctionSignature, TypeVariableContext
from .type3.typeclasses import Type3ClassMethod
from .type3.types import Type3, TypeApplication_Struct
from .type5 import typeexpr as type5typeexpr
class Expression:
"""
An expression within a statement
"""
__slots__ = ('type3', 'type5', )
type3: Type3 | None
type5: type5typeexpr.TypeExpr | None
def __init__(self) -> None:
self.type3 = None
self.type5 = None
class Constant(Expression):
"""
An constant value expression within a statement
# FIXME: Rename to literal
"""
__slots__ = ()
class ConstantPrimitive(Constant):
"""
An primitive constant value expression within a statement
"""
__slots__ = ('value', )
value: Union[int, float]
def __init__(self, value: Union[int, float]) -> None:
super().__init__()
self.value = value
def __repr__(self) -> str:
return f'ConstantPrimitive({repr(self.value)})'
class ConstantMemoryStored(Constant):
"""
An constant value expression within a statement
# FIXME: Rename to literal
"""
__slots__ = ('data_block', )
data_block: 'ModuleDataBlock'
def __init__(self, data_block: 'ModuleDataBlock') -> None:
super().__init__()
self.data_block = data_block
class ConstantBytes(ConstantMemoryStored):
"""
A bytes constant value expression within a statement
"""
__slots__ = ('value', )
value: bytes
def __init__(self, value: bytes, data_block: 'ModuleDataBlock') -> None:
super().__init__(data_block)
self.value = value
def __repr__(self) -> str:
# Do not repr the whole ModuleDataBlock
# As this has a reference back to this constant for its data
# which it needs to compile the data into the program
return f'ConstantBytes({repr(self.value)}, @{repr(self.data_block.address)})'
class ConstantTuple(ConstantMemoryStored):
"""
A Tuple constant value expression within a statement
"""
__slots__ = ('value', )
value: List[Union[ConstantPrimitive, ConstantBytes, 'ConstantTuple', 'ConstantStruct']]
def __init__(self, value: List[Union[ConstantPrimitive, ConstantBytes, 'ConstantTuple', 'ConstantStruct']], data_block: 'ModuleDataBlock') -> None:
super().__init__(data_block)
self.value = value
def __repr__(self) -> str:
# Do not repr the whole ModuleDataBlock
# As this has a reference back to this constant for its data
# which it needs to compile the data into the program
return f'ConstantTuple({repr(self.value)}, @{repr(self.data_block.address)})'
class ConstantStruct(ConstantMemoryStored):
"""
A Struct constant value expression within a statement
"""
__slots__ = ('struct_type3', 'value', )
struct_type3: Type3
value: List[Union[ConstantPrimitive, ConstantBytes, ConstantTuple, 'ConstantStruct']]
def __init__(self, struct_type3: Type3, value: List[Union[ConstantPrimitive, ConstantBytes, ConstantTuple, 'ConstantStruct']], data_block: 'ModuleDataBlock') -> None:
super().__init__(data_block)
self.struct_type3 = struct_type3
self.value = value
def __repr__(self) -> str:
# Do not repr the whole ModuleDataBlock
# As this has a reference back to this constant for its data
# which it needs to compile the data into the program
return f'ConstantStruct({self.struct_type3!r}, {self.value!r}, @{self.data_block.address!r})'
class VariableReference(Expression):
"""
An variable reference expression within a statement
"""
__slots__ = ('variable', )
variable: Union['ModuleConstantDef', 'FunctionParam'] # also possibly local
def __init__(self, variable: Union['ModuleConstantDef', 'FunctionParam']) -> None:
super().__init__()
self.variable = variable
class BinaryOp(Expression):
"""
A binary operator expression within a statement
"""
__slots__ = ('operator', 'left', 'right', )
operator: Type3ClassMethod
left: Expression
right: Expression
def __init__(self, operator: Type3ClassMethod, left: Expression, right: Expression) -> None:
super().__init__()
self.operator = operator
self.left = left
self.right = right
def __repr__(self) -> str:
return f'BinaryOp({repr(self.operator)}, {repr(self.left)}, {repr(self.right)})'
class FunctionCall(Expression):
"""
A function call expression within a statement
"""
__slots__ = ('function', 'arguments', )
function: Union['Function', 'FunctionParam', Type3ClassMethod]
arguments: List[Expression]
def __init__(self, function: Union['Function', 'FunctionParam', Type3ClassMethod]) -> None:
super().__init__()
self.function = function
self.arguments = []
class FunctionReference(Expression):
"""
An function reference expression within a statement
"""
__slots__ = ('function', )
function: 'Function'
def __init__(self, function: 'Function') -> None:
super().__init__()
self.function = function
class TupleInstantiation(Expression):
"""
Instantiation a tuple
"""
__slots__ = ('elements', )
elements: List[Expression]
def __init__(self, elements: List[Expression]) -> None:
super().__init__()
self.elements = elements
class Subscript(Expression):
"""
A subscript, for example to refer to a static array or tuple
by index
"""
__slots__ = ('varref', 'index', )
varref: VariableReference
index: Expression
def __init__(self, varref: VariableReference, index: Expression) -> None:
super().__init__()
self.varref = varref
self.index = index
class AccessStructMember(Expression):
"""
Access a struct member for reading of writing
"""
__slots__ = ('varref', 'struct_type3', 'member', )
varref: VariableReference
struct_type3: Type3
member: str
def __init__(self, varref: VariableReference, struct_type3: Type3, member: str) -> None:
super().__init__()
self.varref = varref
self.struct_type3 = struct_type3
self.member = member
class Statement:
"""
A statement within a function
"""
__slots__ = ()
class StatementPass(Statement):
"""
A pass statement
"""
__slots__ = ()
class StatementReturn(Statement):
"""
A return statement within a function
"""
__slots__ = ('value', )
def __init__(self, value: Expression) -> None:
self.value = value
def __repr__(self) -> str:
return f'StatementReturn({repr(self.value)})'
class StatementIf(Statement):
"""
An if statement within a function
"""
__slots__ = ('test', 'statements', 'else_statements', )
test: Expression
statements: List[Statement]
else_statements: List[Statement]
def __init__(self, test: Expression) -> None:
self.test = test
self.statements = []
self.else_statements = []
class FunctionParam:
"""
A parameter for a Function
"""
__slots__ = ('name', 'type3', )
name: str
type3: Type3
def __init__(self, name: str, type3: Type3) -> None:
self.name = name
self.type3 = type3
def __repr__(self) -> str:
return f'FunctionParam({self.name!r}, {self.type3!r})'
class Function:
"""
A function processes input and produces output
"""
__slots__ = ('name', 'lineno', 'exported', 'imported', 'statements', 'signature', 'returns_type3', 'type5', 'posonlyargs', )
name: str
lineno: int
exported: bool
imported: Optional[str]
statements: List[Statement]
signature: FunctionSignature
returns_type3: Type3
type5: type5typeexpr.TypeExpr | None
posonlyargs: List[FunctionParam]
def __init__(self, name: str, lineno: int, returns_type3: Type3) -> None:
self.name = name
self.lineno = lineno
self.exported = False
self.imported = None
self.statements = []
self.signature = FunctionSignature(TypeVariableContext(), [])
self.returns_type3 = returns_type3
self.type5 = None
self.posonlyargs = []
class StructDefinition:
"""
The definition for a struct
"""
__slots__ = ('struct_type3', 'lineno', )
struct_type3: Type3
lineno: int
def __init__(self, struct_type3: Type3, lineno: int) -> None:
self.struct_type3 = struct_type3
self.lineno = lineno
class StructConstructor(Function):
"""
The constructor method for a struct
A function will generated to instantiate a struct. The arguments
will be the defaults
"""
__slots__ = ('struct_type3', )
struct_type3: Type3
def __init__(self, struct_type3: Type3) -> None:
super().__init__(f'@{struct_type3.name}@__init___@', -1, struct_type3)
assert isinstance(struct_type3.application, TypeApplication_Struct)
for mem, typ in struct_type3.application.arguments:
self.posonlyargs.append(FunctionParam(mem, typ, ))
self.signature.args.append(typ)
self.signature.args.append(struct_type3)
self.struct_type3 = struct_type3
class ModuleConstantDef:
"""
A constant definition within a module
"""
__slots__ = ('name', 'lineno', 'type3', 'type5', 'constant', )
name: str
lineno: int
type3: Type3
type5: type5typeexpr.TypeExpr
constant: Constant
def __init__(self, name: str, lineno: int, type3: Type3, type5: type5typeexpr.TypeExpr, constant: Constant) -> None:
self.name = name
self.lineno = lineno
self.type3 = type3
self.type5 = type5
self.constant = constant
class ModuleDataBlock:
"""
A single allocated block for module data
"""
__slots__ = ('data', 'address', )
data: List[Union[ConstantPrimitive, ConstantMemoryStored]]
address: Optional[int]
def __init__(self, data: Iterable[Union[ConstantPrimitive, ConstantMemoryStored]]) -> None:
self.data = [*data]
self.address = None
def __repr__(self) -> str:
return f'ModuleDataBlock({self.data!r}, {self.address!r})'
class ModuleData:
"""
The data for when a module is loaded into memory
"""
__slots__ = ('blocks', )
blocks: List[ModuleDataBlock]
def __init__(self) -> None:
self.blocks = []
class Module[G]:
"""
A module is a file and consists of functions
"""
__slots__ = ('build', 'data', 'types', 'type5s', 'struct_definitions', 'constant_defs', 'functions', 'methods', 'operators', 'functions_table', )
build: BuildBase[G]
data: ModuleData
types: dict[str, Type3]
type5s: dict[str, type5typeexpr.TypeExpr]
struct_definitions: Dict[str, StructDefinition]
constant_defs: Dict[str, ModuleConstantDef]
functions: Dict[str, Function]
methods: Dict[str, Type3ClassMethod]
operators: Dict[str, Type3ClassMethod]
functions_table: dict[Function, int]
def __init__(self, build: BuildBase[G]) -> None:
self.build = build
self.data = ModuleData()
self.types = {}
self.type5s = {}
self.struct_definitions = {}
self.constant_defs = {}
self.functions = {}
self.methods = {}
self.operators = {}
self.functions_table = {}