diff --git a/compiler/nodes.py b/compiler/nodes.py index 9b8d6c5..4388a29 100644 --- a/compiler/nodes.py +++ b/compiler/nodes.py @@ -16,10 +16,20 @@ class Node: def _values(self) -> Any | list[Node]: raise NotImplementedError(f"Please override {__name__}") + @functools.cache + def location(self) -> SourceLocation: + locations = [v.location() for v in self._values()] + begin = min([loc.begin for loc in locations]) + end = max([loc.end for loc in locations]) + loc = SourceLocation(begin=begin, end=end) + return loc + def __repr__(self): vals = self._values() if type(vals) == list: vals = ", ".join(repr(val) for val in vals) + else: + vals = repr(vals) return f"{self.__class__.__name__}({vals})" def pprint(self, depth: int | None = None, indent: str = "\t"): @@ -48,9 +58,13 @@ class Node: return result -class Literal(Node): - def __init__(self, value: Any): +class Literal(Node, ABC): + def __init__(self, location: SourceLocation, value: Any): self.value = value + self.loc = location + + def location(self) -> SourceLocation: + return self.loc def _values(self) -> Any | list[Node]: return self.value @@ -96,14 +110,15 @@ BinaryOperation = Sum | Sub | Product | Division @beartype class Float(Literal): - def __init__(self, value: float): - super().__init__(value) + def __init__(self, location: SourceLocation, value: float): + super().__init__(location, value) @beartype class Integer(Literal): - def __init__(self, value: int): - super().__init__(value) + + def __init__(self, location: SourceLocation, value: int): + super().__init__(location, value) class Expression(Node): @@ -113,6 +128,26 @@ class Expression(Node): def _values(self) -> Any | list[Node]: return self.node + def location(self) -> SourceLocation: + return self.node.location() + + +class Identifier(Literal): + def __init__(self, name: str): + super().__init__(name) + + +class Assignment(Node): + def intermediate_representation(self, context: semantic.Context) -> list[ir.IRItem]: + return self.value.intermediate_representation(context) + + def __init__(self, identifier: Identifier, value: Value): + self.identifier = identifier + self.value = value + + def _values(self) -> Any | list[Node]: + return [self.identifier, self.value] + Number = Float | Integer Value = BinaryOperation | Number diff --git a/compiler/parser.py b/compiler/parser.py index 8228751..4db1c95 100644 --- a/compiler/parser.py +++ b/compiler/parser.py @@ -68,10 +68,10 @@ class Parser: def number(self, mandatory: bool = False): if tok := self.accept(Tokens.Float): logger.debug(f"Found float {tok}") - return Float(value=float(tok.value)) + return Float(location=tok.loc, value=float(tok.value)) elif tok := self.accept(Tokens.Integer): logger.debug(f"Found integer {tok}") - return Integer(value=int(tok.value)) + return Integer(location=tok.loc, value=int(tok.value)) elif mandatory: raise UnexpectedTokenError(self.token, "integer or float")