diff options
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/mparser.py | 215 |
1 files changed, 161 insertions, 54 deletions
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index fb0ec95..15e62e0 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -12,12 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations - -from dataclasses import dataclass +from dataclasses import dataclass, field import re import codecs import os import typing as T + from .mesonlib import MesonException from . import mlog @@ -240,13 +240,13 @@ class Lexer: if not matched: raise ParseException('lexer', self.getline(line_start), lineno, col) -@dataclass(eq=False) +@dataclass class BaseNode: - lineno: int - colno: int - filename: str - end_lineno: T.Optional[int] = None - end_colno: T.Optional[int] = None + lineno: int = field(hash=False) + colno: int = field(hash=False) + filename: str = field(hash=False) + end_lineno: T.Optional[int] = field(default=None, hash=False) + end_colno: T.Optional[int] = field(default=None, hash=False) def __post_init__(self) -> None: if self.end_lineno is None: @@ -266,57 +266,63 @@ class BaseNode: if callable(func): func(self) +@dataclass(init=False, unsafe_hash=True) class ElementaryNode(T.Generic[TV_TokenTypes], BaseNode): + + value: TV_TokenTypes # type: ignore[misc] + bytespan: T.Tuple[int, int] = field(hash=False) # type: ignore[misc] + def __init__(self, token: Token[TV_TokenTypes]): super().__init__(token.lineno, token.colno, token.filename) - self.value = token.value # type: TV_TokenTypes - self.bytespan = token.bytespan # type: T.Tuple[int, int] + self.value = token.value + self.bytespan = token.bytespan +@dataclass(init=False, unsafe_hash=True) class BooleanNode(ElementaryNode[bool]): - def __init__(self, token: Token[bool]): - super().__init__(token) - assert isinstance(self.value, bool) + pass +@dataclass(init=False, unsafe_hash=True) class IdNode(ElementaryNode[str]): - def __init__(self, token: Token[str]): - super().__init__(token) - assert isinstance(self.value, str) def __str__(self) -> str: return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) +@dataclass(init=False, unsafe_hash=True) class NumberNode(ElementaryNode[int]): - def __init__(self, token: Token[int]): - super().__init__(token) - assert isinstance(self.value, int) + pass +@dataclass(init=False, unsafe_hash=True) class StringNode(ElementaryNode[str]): - def __init__(self, token: Token[str]): - super().__init__(token) - assert isinstance(self.value, str) def __str__(self) -> str: return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) +@dataclass(init=False, unsafe_hash=True) class FormatStringNode(ElementaryNode[str]): - def __init__(self, token: Token[str]): - super().__init__(token) - assert isinstance(self.value, str) def __str__(self) -> str: return f"Format string node: '{self.value}' ({self.lineno}, {self.colno})." +@dataclass(init=False, unsafe_hash=True) class MultilineFormatStringNode(FormatStringNode): def __str__(self) -> str: return f"Multiline Format string node: '{self.value}' ({self.lineno}, {self.colno})." +@dataclass(init=False, unsafe_hash=True) class ContinueNode(ElementaryNode): pass +@dataclass(init=False, unsafe_hash=True) class BreakNode(ElementaryNode): pass +@dataclass(init=False) class ArgumentNode(BaseNode): + + arguments: T.List[BaseNode] # type: ignore[misc] + commas: T.List[Token] # type: ignore[misc] + kwargs: T.Dict[BaseNode, BaseNode] # type: ignore[misc] + def __init__(self, token: Token[TV_TokenTypes]): super().__init__(token.lineno, token.colno, token.filename) self.arguments = [] # type: T.List[BaseNode] @@ -357,12 +363,20 @@ class ArgumentNode(BaseNode): def __len__(self) -> int: return self.num_args() # Fixme +@dataclass(init=False, unsafe_hash=True) class ArrayNode(BaseNode): + + args: ArgumentNode # type: ignore[misc] + def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int): super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) - self.args = args # type: ArgumentNode + self.args = args +@dataclass(init=False, unsafe_hash=True) class DictNode(BaseNode): + + args: ArgumentNode # type: ignore[misc] + def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int): super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) self.args = args @@ -372,95 +386,177 @@ class EmptyNode(BaseNode): super().__init__(lineno, colno, filename) self.value = None + def __eq__(self, other: object) -> bool: + return isinstance(other, EmptyNode) + +@dataclass(init=False, unsafe_hash=True) class OrNode(BaseNode): + + left: BaseNode # type: ignore[misc] + right: BaseNode # type: ignore[misc] + def __init__(self, left: BaseNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) - self.left = left # type: BaseNode - self.right = right # type: BaseNode + self.left = left + self.right = right +@dataclass(init=False, unsafe_hash=True) class AndNode(BaseNode): + + left: BaseNode # type: ignore[misc] + right: BaseNode # type: ignore[misc] + def __init__(self, left: BaseNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) - self.left = left # type: BaseNode - self.right = right # type: BaseNode + self.left = left + self.right = right +@dataclass(init=False, unsafe_hash=True) class ComparisonNode(BaseNode): + + left: BaseNode # type: ignore[misc] + right: BaseNode # type: ignore[misc] + ctype: COMPARISONS # type: ignore[misc] + def __init__(self, ctype: COMPARISONS, left: BaseNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) - self.left = left # type: BaseNode - self.right = right # type: BaseNode + self.left = left + self.right = right self.ctype = ctype +@dataclass(init=False, unsafe_hash=True) class ArithmeticNode(BaseNode): + + left: BaseNode # type: ignore[misc] + right: BaseNode # type: ignore[misc] + # TODO: use a Literal for operation + operation: str # type: ignore[misc] + def __init__(self, operation: str, left: BaseNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) - self.left = left # type: BaseNode - self.right = right # type: BaseNode - self.operation = operation # type: str + self.left = left + self.right = right + self.operation = operation + +@dataclass(init=False, unsafe_hash=True) class NotNode(BaseNode): + + value: BaseNode # type: ignore[misc] + def __init__(self, token: Token[TV_TokenTypes], value: BaseNode): super().__init__(token.lineno, token.colno, token.filename) - self.value = value # type: BaseNode + self.value = value +@dataclass(init=False, unsafe_hash=True) class CodeBlockNode(BaseNode): + + lines: T.List[BaseNode] # type: ignore[misc] + def __init__(self, token: Token[TV_TokenTypes]): super().__init__(token.lineno, token.colno, token.filename) - self.lines = [] # type: T.List[BaseNode] + self.lines = [] +@dataclass(init=False, unsafe_hash=True) class IndexNode(BaseNode): + + iobject: BaseNode # type: ignore[misc] + index: BaseNode # type: ignore[misc] + def __init__(self, iobject: BaseNode, index: BaseNode): super().__init__(iobject.lineno, iobject.colno, iobject.filename) - self.iobject = iobject # type: BaseNode - self.index = index # type: BaseNode + self.iobject = iobject + self.index = index +@dataclass(init=False, unsafe_hash=True) class MethodNode(BaseNode): + + source_object: BaseNode # type: ignore[misc] + name: str # type: ignore[misc] + args: ArgumentNode = field(hash=False) # type: ignore[misc] + def __init__(self, filename: str, lineno: int, colno: int, source_object: BaseNode, name: str, args: ArgumentNode): super().__init__(lineno, colno, filename) - self.source_object = source_object # type: BaseNode - self.name = name # type: str + self.source_object = source_object + self.name = name assert isinstance(self.name, str) - self.args = args # type: ArgumentNode + self.args = args +@dataclass(init=False, unsafe_hash=True) class FunctionNode(BaseNode): + + func_name: str # type: ignore[misc] + args: ArgumentNode = field(hash=False) # type: ignore[misc] + def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, func_name: str, args: ArgumentNode): super().__init__(lineno, colno, filename, end_lineno=end_lineno, end_colno=end_colno) - self.func_name = func_name # type: str + self.func_name = func_name assert isinstance(func_name, str) - self.args = args # type: ArgumentNode + self.args = args + +@dataclass(init=False, unsafe_hash=True) class AssignmentNode(BaseNode): + + var_name: str # type: ignore[misc] + value: BaseNode # type: ignore[misc] + def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode): super().__init__(lineno, colno, filename) - self.var_name = var_name # type: str + self.var_name = var_name assert isinstance(var_name, str) - self.value = value # type: BaseNode + self.value = value + +@dataclass(init=False, unsafe_hash=True) class PlusAssignmentNode(BaseNode): + + var_name: str # type: ignore[misc] + value: BaseNode # type: ignore[misc] + def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode): super().__init__(lineno, colno, filename) - self.var_name = var_name # type: str + self.var_name = var_name assert isinstance(var_name, str) - self.value = value # type: BaseNode + self.value = value + +@dataclass(init=False) class ForeachClauseNode(BaseNode): + + varnames: T.List[str] # type: ignore[misc] + items: BaseNode # type: ignore[misc] + block: CodeBlockNode # type: ignore[misc] + def __init__(self, token: Token, varnames: T.List[str], items: BaseNode, block: CodeBlockNode): super().__init__(token.lineno, token.colno, token.filename) - self.varnames = varnames # type: T.List[str] - self.items = items # type: BaseNode - self.block = block # type: CodeBlockNode + self.varnames = varnames + self.items = items + self.block = block + +@dataclass(init=False) class IfNode(BaseNode): + + condition: BaseNode # type: ignore[misc] + block: CodeBlockNode # type: ignore[misc] + def __init__(self, linenode: BaseNode, condition: BaseNode, block: CodeBlockNode): super().__init__(linenode.lineno, linenode.colno, linenode.filename) self.condition = condition # type: BaseNode self.block = block # type: CodeBlockNode + +@dataclass(init=False) class IfClauseNode(BaseNode): + + ifs: T.List[IfNode] # type: ignore[misc] + elseblock: T.Union[EmptyNode, CodeBlockNode] # type: ignore[misc] + def __init__(self, linenode: BaseNode): super().__init__(linenode.lineno, linenode.colno, linenode.filename) - self.ifs = [] # type: T.List[IfNode] - self.elseblock = None # type: T.Union[EmptyNode, CodeBlockNode] + self.ifs = [] + self.elseblock = None class TestCaseClauseNode(BaseNode): def __init__(self, condition: BaseNode, block: CodeBlockNode): @@ -468,12 +564,23 @@ class TestCaseClauseNode(BaseNode): self.condition = condition self.block = block +@dataclass(init=False) class UMinusNode(BaseNode): + + value: BaseNode # type: ignore[misc] + def __init__(self, current_location: Token, value: BaseNode): super().__init__(current_location.lineno, current_location.colno, current_location.filename) - self.value = value # type: BaseNode + self.value = value + +@dataclass(init=False) class TernaryNode(BaseNode): + + condition: BaseNode # type: ignore[misc] + trueblock: BaseNode # type: ignore[misc] + falseblock: BaseNode # type: ignore[misc] + def __init__(self, condition: BaseNode, trueblock: BaseNode, falseblock: BaseNode): super().__init__(condition.lineno, condition.colno, condition.filename) self.condition = condition # type: BaseNode |