compiler/compiler/ir.py

141 lines
3.3 KiB
Python

from __future__ import annotations
import abc
from abc import abstractmethod
from beartype import beartype
from .logger import Logger
from .source import SourceLocation
logger = Logger(__name__)
class IRItem:
def __init__(self, location: SourceLocation):
self.location = location
@abstractmethod
def codegen(self) -> str:
raise NotImplementedError(f"Please override {self.__class__.__name__}.{__name__}")
@abstractmethod
def destination(self) -> IRValue:
raise NotImplementedError(f"Please override {self.__class__.__name__}.{__name__}")
def __repr__(self):
return f"{self.codegen()}"
class IRAction(IRItem, abc.ABC):
pass
class IRValue(IRItem, abc.ABC):
def destination(self) -> IRValue:
return self
class IRMove(IRAction):
@beartype
def __init__(self, location: SourceLocation, dest: IRRegister, 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 IRImmediate(IRValue):
@beartype
def __init__(self, location: SourceLocation, value: int | float | str):
super().__init__(location)
self.value = value
def codegen(self):
return f"{self.value}"
class IRRegister(IRValue):
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 IRAdd(IRAction):
@beartype
def __init__(self, location: SourceLocation, dest: IRRegister, *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):
@beartype
def __init__(self, location: SourceLocation, dest: IRRegister, *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):
@beartype
def __init__(self, location: SourceLocation, dest: IRRegister, 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):
@beartype
def __init__(self, location: SourceLocation, dest: IRRegister, 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}"