diff --git a/compiler/errors.py b/compiler/errors.py index 2ae3641..577ad07 100644 --- a/compiler/errors.py +++ b/compiler/errors.py @@ -1,5 +1,7 @@ from __future__ import annotations +import inspect + from . import source, tokenizer @@ -19,3 +21,18 @@ class UnexpectedTokenError(CompilationError): class SemanticAnalysisError(CompilationError): pass + + +class OverrideMandatoryError(NotImplementedError): + def __init__(self, klass: object = None, function_name: str = None): + if klass is None or function_name is None: + frame = inspect.currentframe() + assert frame is not None + prev_frame = frame.f_back + assert prev_frame is not None + if klass is None: + klass = prev_frame.f_locals.get("self", None) + if function_name is None: + function_name = prev_frame.f_code.co_name + + super().__init__(f"Please override {klass.__class__.__name__}.{function_name}") diff --git a/compiler/ir.py b/compiler/ir.py index 03d5a37..9041cc1 100644 --- a/compiler/ir.py +++ b/compiler/ir.py @@ -5,6 +5,7 @@ from abc import abstractmethod from beartype import beartype +from .errors import OverrideMandatoryError from .logger import Logger from .source import SourceLocation @@ -17,11 +18,11 @@ class IRItem: @abstractmethod def codegen(self) -> str: - raise NotImplementedError(f"Please override {self.__class__.__name__}.{__name__}") + raise OverrideMandatoryError() @abstractmethod def destination(self) -> IRValue: - raise NotImplementedError(f"Please override {self.__class__.__name__}.{__name__}") + raise OverrideMandatoryError() def __repr__(self): return f"{self.codegen()}" diff --git a/compiler/nodes.py b/compiler/nodes.py index f04b38c..6fb0be6 100644 --- a/compiler/nodes.py +++ b/compiler/nodes.py @@ -7,7 +7,7 @@ from typing import Any, Iterable from beartype import beartype from . import ir, semantic -from .errors import SemanticAnalysisError +from .errors import SemanticAnalysisError, OverrideMandatoryError from .logger import Logger from .source import SourceLocation @@ -21,7 +21,7 @@ class Node: @abstractmethod def _values(self) -> list[Node | Any]: - raise NotImplementedError(f"Please override {__name__}") + raise OverrideMandatoryError() @functools.cache def location(self) -> SourceLocation: @@ -66,7 +66,7 @@ class Node: @abstractmethod def intermediate_representation(self) -> list[ir.IRItem]: - raise NotImplementedError(f"Please implement {self.__class__.__name__}.{__name__}") + raise OverrideMandatoryError() def semantic_analysis(self, context: semantic.Context): logger.debug(f"Doing semantic analysis in {self}")