Compare commits
2 Commits
78eba39ae3
...
45f7d1be2b
| Author | SHA1 | Date | |
|---|---|---|---|
|
45f7d1be2b
|
|||
|
27f3fa7d1e
|
@@ -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:
|
||||
@@ -174,6 +174,10 @@ class SliceExpr:
|
||||
step: Optional[Expr]
|
||||
|
||||
|
||||
class TupleExpr:
|
||||
items: tuple[Expr, ...]
|
||||
|
||||
|
||||
class RawExpr:
|
||||
expr: ast.expr
|
||||
|
||||
|
||||
@@ -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")
|
||||
@@ -862,6 +868,17 @@ class PythonAstPrinter(
|
||||
self._write_optional_child("upper", expr.upper)
|
||||
self._write_optional_child("step", expr.step, last=True)
|
||||
|
||||
def visit_tuple_expr(self, expr: p.TupleExpr) -> None:
|
||||
self._write_line("TupleExpr")
|
||||
with self._child_level():
|
||||
self._write_line("items", last=True)
|
||||
with self._child_level():
|
||||
for i, item in enumerate(expr.items):
|
||||
self._idx = i
|
||||
if i == len(expr.items) - 1:
|
||||
self._mark_last()
|
||||
item.accept(self)
|
||||
|
||||
def visit_raw_expr(self, expr: p.RawExpr) -> None:
|
||||
self._write_line("RawExpr")
|
||||
with self._child_level(single=True):
|
||||
|
||||
@@ -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)
|
||||
@@ -268,6 +268,9 @@ class Expr(ABC):
|
||||
@abstractmethod
|
||||
def visit_slice_expr(self, expr: SliceExpr) -> T: ...
|
||||
|
||||
@abstractmethod
|
||||
def visit_tuple_expr(self, expr: TupleExpr) -> T: ...
|
||||
|
||||
@abstractmethod
|
||||
def visit_raw_expr(self, expr: RawExpr) -> T: ...
|
||||
|
||||
@@ -402,6 +405,14 @@ class SliceExpr(Expr):
|
||||
return visitor.visit_slice_expr(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TupleExpr(Expr):
|
||||
items: tuple[Expr, ...]
|
||||
|
||||
def accept(self, visitor: Expr.Visitor[T]) -> T:
|
||||
return visitor.visit_tuple_expr(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RawExpr(Expr):
|
||||
expr: ast.expr
|
||||
|
||||
@@ -750,6 +750,11 @@ class PythonTyper(
|
||||
def visit_slice_expr(self, expr: p.SliceExpr) -> Type:
|
||||
return self.types.get_type("slice")
|
||||
|
||||
def visit_tuple_expr(self, expr: p.TupleExpr) -> Type:
|
||||
return TupleType(
|
||||
items=tuple(self.type_of(item) for item in expr.items),
|
||||
)
|
||||
|
||||
def visit_raw_expr(self, expr: p.RawExpr) -> Type:
|
||||
return UnknownType()
|
||||
|
||||
@@ -761,9 +766,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:
|
||||
|
||||
@@ -236,5 +236,9 @@ class Resolver(p.Stmt.Visitor[None], p.Expr.Visitor[None]):
|
||||
if expr.step is not None:
|
||||
self.resolve(expr.step)
|
||||
|
||||
def visit_tuple_expr(self, expr: p.TupleExpr) -> None:
|
||||
for item in expr.items:
|
||||
self.resolve(item)
|
||||
|
||||
def visit_raw_expr(self, expr: p.RawExpr) -> None:
|
||||
pass
|
||||
|
||||
@@ -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")
|
||||
@@ -247,6 +247,10 @@ class PythonHighlighter(
|
||||
if expr.step is not None:
|
||||
expr.step.accept(self)
|
||||
|
||||
def visit_tuple_expr(self, expr: p.TupleExpr) -> None:
|
||||
for item in expr.items:
|
||||
item.accept(self)
|
||||
|
||||
def visit_raw_expr(self, expr: p.RawExpr) -> None: ...
|
||||
|
||||
def visit_raw_stmt(self, stmt: p.RawStmt) -> None: ...
|
||||
|
||||
@@ -3,7 +3,7 @@ span {
|
||||
--col: 108, 233, 108;
|
||||
}
|
||||
|
||||
&.param {
|
||||
&.arg {
|
||||
--col: 103, 192, 224;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ from midas.ast.python import (
|
||||
Stmt,
|
||||
SubscriptExpr,
|
||||
TernaryExpr,
|
||||
TupleExpr,
|
||||
TypeAssign,
|
||||
UnaryExpr,
|
||||
VariableExpr,
|
||||
@@ -300,26 +301,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 +348,7 @@ class PythonParser:
|
||||
return BaseType(
|
||||
location=loc,
|
||||
base="None",
|
||||
param=None,
|
||||
args=(),
|
||||
)
|
||||
|
||||
case _:
|
||||
@@ -477,6 +480,12 @@ class PythonParser:
|
||||
step=self.parse_expr(step) if step is not None else None,
|
||||
)
|
||||
|
||||
case ast.Tuple(elts=items):
|
||||
return TupleExpr(
|
||||
location=location,
|
||||
items=tuple(self.parse_expr(item) for item in items),
|
||||
)
|
||||
|
||||
case _:
|
||||
print(f"Unsupported expression: {ast.unparse(node)}")
|
||||
return RawExpr(location=location, expr=node)
|
||||
|
||||
@@ -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:
|
||||
@@ -302,6 +302,12 @@ class PythonAstJsonSerializer(
|
||||
"step": self._serialize_optional(expr.step),
|
||||
}
|
||||
|
||||
def visit_tuple_expr(self, expr: TupleExpr) -> dict:
|
||||
return {
|
||||
"_type": "TupleExpr",
|
||||
"items": [item.accept(self) for item in expr.items],
|
||||
}
|
||||
|
||||
def visit_raw_expr(self, expr: RawExpr) -> dict:
|
||||
return {
|
||||
"_type": "RawExpr",
|
||||
|
||||
Reference in New Issue
Block a user