Had to implement both functions as arguments and type place holders (variables) for type constructors. Had to implement functions as a type as well. Still have to figure out how to pass functions around.
402 lines
11 KiB
Python
402 lines
11 KiB
Python
"""
|
|
Contains the syntax tree for ourlang
|
|
"""
|
|
from typing import Dict, Iterable, List, Optional, Union
|
|
|
|
from . import prelude
|
|
from .type3.functions import FunctionSignature, TypeVariableContext
|
|
from .type3.typeclasses import Type3ClassMethod
|
|
from .type3.types import Type3, TypeApplication_Struct
|
|
|
|
|
|
class Expression:
|
|
"""
|
|
An expression within a statement
|
|
"""
|
|
__slots__ = ('type3', )
|
|
|
|
type3: Type3 | None
|
|
|
|
def __init__(self) -> None:
|
|
self.type3 = 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', 'posonlyargs', )
|
|
|
|
name: str
|
|
lineno: int
|
|
exported: bool
|
|
imported: Optional[str]
|
|
statements: List[Statement]
|
|
signature: FunctionSignature
|
|
returns_type3: Type3
|
|
posonlyargs: List[FunctionParam]
|
|
|
|
def __init__(self, name: str, lineno: int) -> None:
|
|
self.name = name
|
|
self.lineno = lineno
|
|
self.exported = False
|
|
self.imported = None
|
|
self.statements = []
|
|
self.signature = FunctionSignature(TypeVariableContext(), [])
|
|
self.returns_type3 = prelude.none # FIXME: This could be a placeholder
|
|
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)
|
|
|
|
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.returns_type3 = struct_type3
|
|
self.signature.args.append(struct_type3)
|
|
|
|
self.struct_type3 = struct_type3
|
|
|
|
class ModuleConstantDef:
|
|
"""
|
|
A constant definition within a module
|
|
"""
|
|
__slots__ = ('name', 'lineno', 'type3', 'constant', )
|
|
|
|
name: str
|
|
lineno: int
|
|
type3: Type3
|
|
constant: Constant
|
|
|
|
def __init__(self, name: str, lineno: int, type3: Type3, constant: Constant) -> None:
|
|
self.name = name
|
|
self.lineno = lineno
|
|
self.type3 = type3
|
|
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
|
|
|
|
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:
|
|
"""
|
|
A module is a file and consists of functions
|
|
"""
|
|
__slots__ = ('data', 'types', 'struct_definitions', 'constant_defs', 'functions', 'operators', 'functions_table', )
|
|
|
|
data: ModuleData
|
|
types: dict[str, Type3]
|
|
struct_definitions: Dict[str, StructDefinition]
|
|
constant_defs: Dict[str, ModuleConstantDef]
|
|
functions: Dict[str, Function]
|
|
operators: Dict[str, Type3ClassMethod]
|
|
functions_table: dict[Function, int]
|
|
|
|
def __init__(self) -> None:
|
|
self.data = ModuleData()
|
|
self.types = {}
|
|
self.struct_definitions = {}
|
|
self.constant_defs = {}
|
|
self.functions = {}
|
|
self.operators = {}
|
|
self.functions_table = {}
|