188 lines
4.4 KiB
Python
188 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
import abc
|
|
from abc import abstractmethod
|
|
|
|
from .errors import OverrideMandatoryError
|
|
from .logger import Logger
|
|
from .source import SourceLocation
|
|
from .typechecking import typecheck
|
|
|
|
logger = Logger(__name__)
|
|
|
|
|
|
class IRItem:
|
|
def __init__(self, location: SourceLocation):
|
|
self.location = location
|
|
|
|
@abstractmethod
|
|
def codegen(self) -> str:
|
|
raise OverrideMandatoryError()
|
|
|
|
@abstractmethod
|
|
def destination(self) -> IRValue:
|
|
raise OverrideMandatoryError()
|
|
|
|
def __repr__(self):
|
|
return f"{self.codegen()}"
|
|
|
|
|
|
class IRAction(IRItem, abc.ABC):
|
|
pass
|
|
|
|
|
|
class IRNop(IRAction):
|
|
def __init__(self, location: SourceLocation):
|
|
super().__init__(location)
|
|
|
|
def codegen(self) -> str:
|
|
return "NOP"
|
|
|
|
def destination(self) -> IRValue:
|
|
return IRVoid(self.location)
|
|
|
|
|
|
class IRValue(IRItem, abc.ABC):
|
|
def destination(self) -> IRValue:
|
|
return self
|
|
|
|
|
|
class IRMove(IRAction):
|
|
|
|
@typecheck
|
|
def __init__(self, location: SourceLocation, dest: IRAssignable, source: IRValue):
|
|
super().__init__(location)
|
|
self.dest = dest
|
|
self.source = source
|
|
|
|
def destination(self) -> IRValue:
|
|
return self.dest
|
|
|
|
def codegen(self) -> str:
|
|
return f"MOVE {self.source} -> {self.dest}"
|
|
|
|
|
|
class IRCall(IRAction):
|
|
def __init__(self, location: SourceLocation, dest: IRAssignable, function: IRVariable, arguments: list[IRValue]):
|
|
super().__init__(location)
|
|
self.dest = dest
|
|
self.function = function
|
|
self.arguments = arguments
|
|
|
|
def codegen(self) -> str:
|
|
return f"CALL {self.function} -> {self.dest} : {', '.join(repr(arg) for arg in self.arguments)}"
|
|
|
|
def destination(self) -> IRValue:
|
|
return self.dest
|
|
|
|
|
|
class IRImmediate(IRValue):
|
|
@typecheck
|
|
def __init__(self, location: SourceLocation, value: int | float | str):
|
|
super().__init__(location)
|
|
self.value = value
|
|
|
|
def codegen(self):
|
|
return f"{self.value}"
|
|
|
|
|
|
class IRVoid(IRValue):
|
|
@typecheck
|
|
def __init__(self, location: SourceLocation):
|
|
super().__init__(location)
|
|
|
|
def codegen(self) -> str:
|
|
return "<VOID>"
|
|
|
|
|
|
class IRAssignable(IRValue, metaclass=abc.ABCMeta):
|
|
pass
|
|
|
|
|
|
class IRRegister(IRAssignable):
|
|
register_id = 0
|
|
|
|
def __init__(self, location: SourceLocation):
|
|
super().__init__(location)
|
|
self.id = IRRegister.register_id
|
|
IRRegister.register_id += 1
|
|
|
|
def codegen(self):
|
|
return f"%r{self.id}"
|
|
|
|
|
|
class IRVariable(IRAssignable):
|
|
def __init__(self, location: SourceLocation, fq_identifier: str):
|
|
super().__init__(location)
|
|
self.fq_identifier = fq_identifier
|
|
|
|
def codegen(self) -> str:
|
|
return f"@{self.fq_identifier}"
|
|
|
|
|
|
class IRAdd(IRAction):
|
|
|
|
@typecheck
|
|
def __init__(self, location: SourceLocation, dest: IRAssignable, *values: IRValue):
|
|
super().__init__(location)
|
|
assert all(isinstance(v, IRValue) for v in values)
|
|
|
|
self.values = values
|
|
self.dest = dest
|
|
|
|
def destination(self) -> IRValue:
|
|
return self.dest
|
|
|
|
def codegen(self) -> str:
|
|
values = [repr(value) for value in self.values]
|
|
return f"ADD {', '.join(values)} -> {self.dest}"
|
|
|
|
|
|
class IRMul(IRAction):
|
|
|
|
@typecheck
|
|
def __init__(self, location: SourceLocation, dest: IRAssignable, *values: IRValue):
|
|
super().__init__(location)
|
|
assert all(isinstance(v, IRValue) for v in values)
|
|
|
|
self.values = values
|
|
self.dest = dest
|
|
|
|
def destination(self) -> IRValue:
|
|
return self.dest
|
|
|
|
def codegen(self) -> str:
|
|
values = [repr(value) for value in self.values]
|
|
return f"MUL {', '.join(values)} -> {self.dest}"
|
|
|
|
|
|
class IRNegation(IRAction):
|
|
|
|
@typecheck
|
|
def __init__(self, location: SourceLocation, dest: IRAssignable, source: IRValue):
|
|
super().__init__(location)
|
|
|
|
self.source = source
|
|
self.dest = dest
|
|
|
|
def destination(self) -> IRValue:
|
|
return self.dest
|
|
|
|
def codegen(self) -> str:
|
|
return f"NEG {self.source} -> {self.dest}"
|
|
|
|
|
|
class IRInvert(IRAction):
|
|
|
|
@typecheck
|
|
def __init__(self, location: SourceLocation, dest: IRAssignable, source: IRValue):
|
|
super().__init__(location)
|
|
|
|
self.source = source
|
|
self.dest = dest
|
|
|
|
def destination(self) -> IRValue:
|
|
return self.dest
|
|
|
|
def codegen(self) -> str:
|
|
return f"INVERT {self.source} -> {self.dest}"
|