diff --git a/gen/python.py b/gen/python.py index df83e6f..56a5f41 100644 --- a/gen/python.py +++ b/gen/python.py @@ -15,7 +15,7 @@ from midas.ast.location import Location ###> MidasType | Type annotations | node class BaseType: base: str - param: Optional[MidasType] + args: tuple[MidasType, ...] class ConstraintType: diff --git a/midas/ast/printer.py b/midas/ast/printer.py index c2c0704..28cf99f 100644 --- a/midas/ast/printer.py +++ b/midas/ast/printer.py @@ -549,7 +549,13 @@ class PythonAstPrinter( self._write_line("BaseType") with self._child_level(): self._write_line(f"base: {node.base}") - self._write_optional_child("param", node.param, last=True) + self._write_line("args:", last=True) + with self._child_level(): + for i, arg in enumerate(node.args): + self._idx = i + if i == len(node.args) - 1: + self._mark_last() + arg.accept(self) def visit_constraint_type(self, node: p.ConstraintType) -> None: self._write_line("ConstraintType") diff --git a/midas/ast/python.py b/midas/ast/python.py index 20d7279..b67a043 100644 --- a/midas/ast/python.py +++ b/midas/ast/python.py @@ -44,7 +44,7 @@ class MidasType(ABC): @dataclass(frozen=True) class BaseType(MidasType): base: str - param: Optional[MidasType] + args: tuple[MidasType, ...] def accept(self, visitor: MidasType.Visitor[T]) -> T: return visitor.visit_base_type(self) diff --git a/midas/checker/python.py b/midas/checker/python.py index 359b68b..10f82e3 100644 --- a/midas/checker/python.py +++ b/midas/checker/python.py @@ -761,9 +761,9 @@ class PythonTyper( self.reporter.warning(node.location, f"Unknown type '{node.base}'") return UnknownType() - if node.param is not None: - param: Type = self.resolve_type_expr(node.param) - return self.types.apply_generic(base, [param]) + if len(node.args) != 0: + args: list[Type] = [self.resolve_type_expr(arg) for arg in node.args] + return self.types.apply_generic(base, args) return base def visit_constraint_type(self, node: p.ConstraintType) -> Type: diff --git a/midas/cli/highlighter.py b/midas/cli/highlighter.py index c131143..bced867 100644 --- a/midas/cli/highlighter.py +++ b/midas/cli/highlighter.py @@ -134,9 +134,9 @@ class PythonHighlighter( def visit_base_type(self, node: p.BaseType) -> None: self.wrap(node, "base-type") - if node.param is not None: - self.wrap(node.param, "param") - node.param.accept(self) + for arg in node.args: + self.wrap(arg, "arg") + arg.accept(self) def visit_constraint_type(self, node: p.ConstraintType) -> None: self.wrap(node, "constraint-type") diff --git a/midas/cli/hl_python.css b/midas/cli/hl_python.css index e6dc43b..899c461 100644 --- a/midas/cli/hl_python.css +++ b/midas/cli/hl_python.css @@ -3,7 +3,7 @@ span { --col: 108, 233, 108; } - &.param { + &.arg { --col: 103, 192, 224; } diff --git a/midas/parser/python.py b/midas/parser/python.py index 7839f52..9868229 100644 --- a/midas/parser/python.py +++ b/midas/parser/python.py @@ -300,26 +300,28 @@ class PythonParser: case ast.Subscript(value=ast.Name(id="Frame"), slice=schema): return self._parse_frame_type(schema) - case ast.Subscript(value=ast.Name(id=name), slice=param): + case ast.Subscript(value=ast.Name(id=name), slice=arg): + args: tuple[MidasType, ...] = ( + tuple(self._parse_type(a) for a in arg.elts) + if isinstance(arg, ast.Tuple) + else (self._parse_type(arg),) + ) return BaseType( location=loc, base=name, - param=self._parse_type(param), + args=args, ) case ast.Name(id=name): return BaseType( location=loc, base=name, - param=None, + args=(), ) case ast.BinOp(left=left_expr, op=ast.Add(), right=right_expr): left = self._parse_type(left_expr) match left: - case None: - raise InvalidSyntaxError() - # If chained constraints, separate base type and rebuild constraint case ConstraintType(type=left_type, constraint=left_constraint): constraint = ast.BinOp( @@ -345,7 +347,7 @@ class PythonParser: return BaseType( location=loc, base="None", - param=None, + args=(), ) case _: diff --git a/tests/serializer/python.py b/tests/serializer/python.py index 3904739..57e47c9 100644 --- a/tests/serializer/python.py +++ b/tests/serializer/python.py @@ -98,7 +98,7 @@ class PythonAstJsonSerializer( return { "_type": "BaseType", "base": node.base, - "param": self._serialize_optional(node.param), + "args": self._serialize_list(node.args), } def visit_constraint_type(self, node: ConstraintType) -> dict: