Compare commits
9
Commits
0c851cbc9b
...
a9a3164c24
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9a3164c24
|
||
|
|
88ab9dc14d
|
||
|
|
f41dbb528c
|
||
|
|
44963db425
|
||
|
|
b67c940112
|
||
|
|
ad40db98d0
|
||
|
|
7a021b2450
|
||
|
|
a7b62e752b
|
||
|
|
44984af8a3
|
@@ -1,6 +1,9 @@
|
||||
from typing import final
|
||||
|
||||
import midas.ast.midas as m
|
||||
|
||||
|
||||
@final
|
||||
class MidasPrinter(
|
||||
m.Expr.Visitor[str],
|
||||
m.Stmt.Visitor[str],
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
from typing import final
|
||||
|
||||
import midas.ast.midas as m
|
||||
from midas.ast.printer.base import AstPrinter
|
||||
|
||||
|
||||
@final
|
||||
class MidasAstPrinter(
|
||||
AstPrinter,
|
||||
m.Expr.Visitor[None],
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import ast
|
||||
from typing import final
|
||||
|
||||
import midas.ast.python as p
|
||||
from midas.ast.printer.base import AstPrinter
|
||||
|
||||
|
||||
@final
|
||||
class PythonAstPrinter(
|
||||
AstPrinter,
|
||||
p.MidasType.Visitor[None],
|
||||
@@ -115,6 +117,24 @@ class PythonAstPrinter(
|
||||
stmt.iterator.accept(self)
|
||||
self._write_sequence("body", stmt.body, last=True)
|
||||
|
||||
def visit_import_stmt(self, stmt: p.ImportStmt) -> None:
|
||||
self._write_line("ImportStmt")
|
||||
with self._child_level(single=True):
|
||||
self._write_sequence("imports", stmt.imports, print_func=self._print_import)
|
||||
|
||||
def visit_from_import_stmt(self, stmt: p.FromImportStmt) -> None:
|
||||
self._write_line("FromImportStmt")
|
||||
with self._child_level():
|
||||
self._write_line(f'module: "{stmt.module}"')
|
||||
self._write_sequence("imports", stmt.imports, print_func=self._print_import)
|
||||
self._write_line(f"level: {stmt.level}", last=True)
|
||||
|
||||
def _print_import(self, import_: p.ImportAlias) -> None:
|
||||
self._write_line("ImportAlias")
|
||||
with self._child_level():
|
||||
self._write_line(f'name: "{import_.name}"')
|
||||
self._write_line(f'alias: "{import_.alias}"')
|
||||
|
||||
def visit_raw_stmt(self, stmt: p.RawStmt) -> None:
|
||||
self._write_line("RawStmt")
|
||||
with self._child_level(single=True):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Any, Callable, Optional, final
|
||||
|
||||
import midas.ast.midas as m
|
||||
from midas.ast.location import Location
|
||||
@@ -18,6 +18,7 @@ class PartialPredicate(Predicate):
|
||||
"""A dictionary of already applied parameters"""
|
||||
|
||||
|
||||
@final
|
||||
class Evaluator(m.Expr.Visitor[Any]):
|
||||
"""Helper class to evaluate an expression
|
||||
|
||||
|
||||
+14
-10
@@ -1,6 +1,6 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from typing import Optional, final
|
||||
|
||||
import midas.ast.midas as m
|
||||
from midas.ast.location import Location
|
||||
@@ -30,6 +30,7 @@ from midas.lexer.token import Token, TokenType
|
||||
from midas.parser.midas import MidasParser
|
||||
|
||||
|
||||
@final
|
||||
class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type]):
|
||||
"""A resolver which evaluates Midas type definitions and build a registry"""
|
||||
|
||||
@@ -110,7 +111,7 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
return self._local_variables[name]
|
||||
return self.types.get_type(name)
|
||||
|
||||
def get_variable(self, name: str) -> Type:
|
||||
def get_variable(self, location: Location, name: str) -> Type:
|
||||
"""Get the type of a variable
|
||||
|
||||
This function will first look into the current predicate's parameters if
|
||||
@@ -118,11 +119,9 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
The the variable is looked up in the preamble (i.e. global environment)
|
||||
|
||||
Args:
|
||||
location (Location): the location of the variable reference
|
||||
name (str): the name of the variable
|
||||
|
||||
Raises:
|
||||
NameError: if the variable cannot be found
|
||||
|
||||
Returns:
|
||||
Type: the type of the variable
|
||||
"""
|
||||
@@ -136,7 +135,8 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
if global_ is not None:
|
||||
return global_
|
||||
|
||||
raise NameError(f"Unknown variable '{name}'")
|
||||
self.reporter.error(location, f"Unknown variable '{name}'")
|
||||
return UnknownType()
|
||||
|
||||
def resolve(self, stmts: list[m.Stmt]):
|
||||
"""Process a sequence of statements
|
||||
@@ -293,6 +293,9 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
return result.result
|
||||
|
||||
def visit_unary_expr(self, expr: m.UnaryExpr) -> Type:
|
||||
# First evaluate operand to surface all errors
|
||||
operand: Type = self.type_of(expr.right)
|
||||
|
||||
# Special case because there is no __not__ dunder method
|
||||
match expr.operator:
|
||||
case Token(type=TokenType.BANG):
|
||||
@@ -306,7 +309,6 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
)
|
||||
return UnknownType()
|
||||
|
||||
operand: Type = self.type_of(expr.right)
|
||||
operation: Optional[Type] = self.types.lookup_member(operand, method)
|
||||
if operation is None:
|
||||
self.reporter.error(
|
||||
@@ -350,7 +352,7 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
return member
|
||||
|
||||
def visit_variable_expr(self, expr: m.VariableExpr) -> Type:
|
||||
return self.get_variable(expr.name.lexeme)
|
||||
return self.get_variable(expr.location, expr.name.lexeme)
|
||||
|
||||
def visit_grouping_expr(self, expr: m.GroupingExpr) -> Type:
|
||||
return expr.expr.accept(self)
|
||||
@@ -365,12 +367,14 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
return self.types.get_type("float")
|
||||
case str():
|
||||
return self.types.get_type("str")
|
||||
case None:
|
||||
return self.types.get_type("None")
|
||||
case _:
|
||||
self.reporter.warning(expr.location, f"Unknown literal {expr}")
|
||||
return UnknownType()
|
||||
|
||||
def visit_wildcard_expr(self, expr: m.WildcardExpr) -> Type:
|
||||
return self.get_variable("_")
|
||||
return self.get_variable(expr.location, "_")
|
||||
|
||||
def visit_named_type(self, type: m.NamedType) -> Type:
|
||||
name: str = type.name.lexeme
|
||||
@@ -409,7 +413,7 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
self._predicate_params = {}
|
||||
if not self.types.is_subtype(constraint_type, self._bool):
|
||||
self.reporter.error(
|
||||
type.location,
|
||||
type.constraint.location,
|
||||
f"Constraint must evaluate to a boolean, got {constraint_type}",
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ast
|
||||
import logging
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, final
|
||||
|
||||
import midas.ast.python as p
|
||||
from midas.ast.location import Location
|
||||
@@ -55,6 +55,7 @@ class UndefinedMethodException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@final
|
||||
class PythonTyper(
|
||||
p.Stmt.Visitor[None],
|
||||
p.Expr.Visitor[Type],
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import final
|
||||
|
||||
import midas.ast.python as p
|
||||
from midas.ast.location import Location
|
||||
from midas.checker.reporter import FileReporter
|
||||
@@ -6,6 +8,7 @@ from midas.checker.reporter import FileReporter
|
||||
class ResolverError(Exception): ...
|
||||
|
||||
|
||||
@final
|
||||
class Resolver(p.Stmt.Visitor[None], p.Expr.Visitor[None]):
|
||||
"""A variable assignment and reference resolver
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Generic, Optional, Protocol, TextIO, TypeVar
|
||||
from typing import Generic, Optional, Protocol, TextIO, TypeVar, final
|
||||
|
||||
import midas.ast.midas as m
|
||||
import midas.ast.python as p
|
||||
@@ -121,6 +121,7 @@ class Highlighter(ABC):
|
||||
self.openings.setdefault((l + 1, 0), []).append(opening)
|
||||
|
||||
|
||||
@final
|
||||
class PythonHighlighter(
|
||||
Highlighter,
|
||||
p.MidasType.Visitor[None],
|
||||
@@ -197,6 +198,10 @@ class PythonHighlighter(
|
||||
for body_stmt in stmt.body:
|
||||
body_stmt.accept(self)
|
||||
|
||||
def visit_import_stmt(self, stmt: p.ImportStmt) -> None: ...
|
||||
|
||||
def visit_from_import_stmt(self, stmt: p.FromImportStmt) -> None: ...
|
||||
|
||||
def visit_binary_expr(self, expr: p.BinaryExpr) -> None: ...
|
||||
|
||||
def visit_compare_expr(self, expr: p.CompareExpr) -> None: ...
|
||||
@@ -255,6 +260,7 @@ class PythonHighlighter(
|
||||
def visit_raw_stmt(self, stmt: p.RawStmt) -> None: ...
|
||||
|
||||
|
||||
@final
|
||||
class MidasHighlighter(
|
||||
Highlighter, m.Stmt.Visitor[None], m.Expr.Visitor[None], m.Type.Visitor[None]
|
||||
):
|
||||
@@ -263,6 +269,11 @@ class MidasHighlighter(
|
||||
def highlight(self, node: Highlightable[MidasHighlighter]):
|
||||
node.accept(self)
|
||||
|
||||
def visit_alias_stmt(self, stmt: m.AliasStmt) -> None:
|
||||
self.wrap(stmt, "alias-stmt")
|
||||
self.wrap(LocatableToken(stmt.name), "type-name")
|
||||
stmt.type.accept(self)
|
||||
|
||||
def visit_type_stmt(self, stmt: m.TypeStmt) -> None:
|
||||
self.wrap(stmt, "type-stmt")
|
||||
self.wrap(LocatableToken(stmt.name), "type-name")
|
||||
@@ -352,6 +363,7 @@ class MidasHighlighter(
|
||||
self.wrap(column, "column")
|
||||
|
||||
|
||||
@final
|
||||
class DiagnosticsHighlighter(Highlighter):
|
||||
EXTRA_CSS_PATH: Optional[Path] = Path(__file__).parent / "hl_diagnostic.css"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ast
|
||||
from typing import Optional
|
||||
from typing import Optional, final
|
||||
|
||||
import midas.ast.midas as m
|
||||
from midas.checker.registry import TypesRegistry
|
||||
@@ -39,6 +39,7 @@ COMPARISON_OPERATORS: dict[TokenType, type[ast.cmpop]] = {
|
||||
}
|
||||
|
||||
|
||||
@final
|
||||
class ConstraintGenerator(m.Expr.Visitor[ast.expr]):
|
||||
"""Class to generate Python code for constraint expressions"""
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import logging
|
||||
import shutil
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Optional, assert_never
|
||||
from typing import Optional, assert_never, final
|
||||
|
||||
import midas.ast.midas as m
|
||||
import midas.ast.python as p
|
||||
@@ -47,6 +47,7 @@ class Scope:
|
||||
"""A list of aliases defined in the scope, that can be discard afterwards"""
|
||||
|
||||
|
||||
@final
|
||||
class Generator(p.Stmt.Visitor[ast.stmt], p.Expr.Visitor[ast.expr]):
|
||||
"""
|
||||
A class to translate the custom Python AST back into raw `ast` nodes
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// Alias declaration
|
||||
alias A = object
|
||||
|
||||
// Type declaration
|
||||
type B = object
|
||||
|
||||
// Generic declaration
|
||||
type C[T] = object
|
||||
type D[T <: A] = object
|
||||
type E[T, U] = object
|
||||
|
||||
// Type expressions
|
||||
type F[T] = T
|
||||
type G = A where predicate(_)
|
||||
type H = A where _ > 0 & _.attr < 1.0 & +_ + 4.0 >= "string" & !(-_ - 4.0 <= 0 & _ == none & _ != false)
|
||||
type I = fn() -> Any
|
||||
type J = fn(a: int, /, b: float, *, c: bool) -> Any
|
||||
type K = fn(a: int, /, b: float, *, c: bool?) -> Any
|
||||
type L = fn(a: int, /, b: float?, *, c: bool?) -> Any
|
||||
type M = fn(a: int?, /, b: float?, *, c: bool?) -> Any
|
||||
|
||||
// Extend
|
||||
extend N {}
|
||||
extend O {
|
||||
prop a: int
|
||||
def b: fn(int, /) -> int
|
||||
def b: fn(float, /) -> float
|
||||
}
|
||||
|
||||
// Predicate
|
||||
predicate P = true
|
||||
predicate Q(v: float) = v > 0
|
||||
predicate R(a: float, b: float)(v: float) = a < v & v < b
|
||||
predicate S = R(0.0, 1.0)
|
||||
predicate T = R(a=0.0, b=1.0)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
# type: ignore
|
||||
# ruff: disable[F821]
|
||||
|
||||
import module1
|
||||
import module2 as alias2
|
||||
from module3 import submodule3
|
||||
from module4 import submodule4 as alias4
|
||||
|
||||
a: int
|
||||
b: Generic[int]
|
||||
c: Generic2[int, float]
|
||||
d: Frame[a:int, b:float]
|
||||
|
||||
e = 3
|
||||
f: int = 4
|
||||
g = []
|
||||
h = [1, 0.1, " ", None, False, True]
|
||||
i = {}
|
||||
j = {"a": 1, "b": 2}
|
||||
k = {"c": 3, **j}
|
||||
l = cast(int, a)
|
||||
m = unsafe_cast(int, a)
|
||||
|
||||
|
||||
def n(a: int, /, b: float, *, c: str) -> Any:
|
||||
return
|
||||
|
||||
|
||||
def o(a: int = 1, /, b: float = 2.0, *, c: str = "") -> Any:
|
||||
return 1
|
||||
|
||||
|
||||
for i in h:
|
||||
pass
|
||||
|
||||
if e == f:
|
||||
pass
|
||||
elif f == g:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
p = +a + -b - ~c * d / e**f
|
||||
q = not (a and b) or c
|
||||
r = a & b | c ^ d
|
||||
|
||||
s = a.b.c
|
||||
t = a[b][c, d][e:f]
|
||||
u = a(b)(c=d)
|
||||
@@ -0,0 +1,725 @@
|
||||
{
|
||||
"stmts": [
|
||||
{
|
||||
"_type": "ImportStmt",
|
||||
"imports": [
|
||||
{
|
||||
"_type": "ImportAlias",
|
||||
"name": "module1",
|
||||
"alias": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_type": "ImportStmt",
|
||||
"imports": [
|
||||
{
|
||||
"_type": "ImportAlias",
|
||||
"name": "module2",
|
||||
"alias": "alias2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_type": "FromImportStmt",
|
||||
"module": "module3",
|
||||
"imports": [
|
||||
{
|
||||
"_type": "ImportAlias",
|
||||
"name": "submodule3",
|
||||
"alias": null
|
||||
}
|
||||
],
|
||||
"level": 0
|
||||
},
|
||||
{
|
||||
"_type": "FromImportStmt",
|
||||
"module": "module4",
|
||||
"imports": [
|
||||
{
|
||||
"_type": "ImportAlias",
|
||||
"name": "submodule4",
|
||||
"alias": "alias4"
|
||||
}
|
||||
],
|
||||
"level": 0
|
||||
},
|
||||
{
|
||||
"_type": "TypeAssign",
|
||||
"name": "a",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "TypeAssign",
|
||||
"name": "b",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "Generic",
|
||||
"args": [
|
||||
{
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "TypeAssign",
|
||||
"name": "c",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "Generic2",
|
||||
"args": [
|
||||
{
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"_type": "BaseType",
|
||||
"base": "float",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "TypeAssign",
|
||||
"name": "d",
|
||||
"type": {
|
||||
"_type": "FrameType",
|
||||
"columns": [
|
||||
{
|
||||
"_type": "FrameColumn",
|
||||
"name": "a",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "FrameColumn",
|
||||
"name": "b",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "float",
|
||||
"args": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "e"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "LiteralExpr",
|
||||
"value": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "TypeAssign",
|
||||
"name": "f",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "f"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "LiteralExpr",
|
||||
"value": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "g"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "ListExpr",
|
||||
"items": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "h"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "ListExpr",
|
||||
"items": [
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": 0.1
|
||||
},
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": " "
|
||||
},
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "i"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "DictExpr",
|
||||
"keys": [],
|
||||
"values": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "j"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "DictExpr",
|
||||
"keys": [
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": "a"
|
||||
},
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": "b"
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "k"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "DictExpr",
|
||||
"keys": [
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": "c"
|
||||
},
|
||||
null
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"_type": "LiteralExpr",
|
||||
"value": 3
|
||||
},
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "j"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "l"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "CastExpr",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
},
|
||||
"expr": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
},
|
||||
"unsafe": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "m"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "CastExpr",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
},
|
||||
"expr": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
},
|
||||
"unsafe": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "Function",
|
||||
"name": "n",
|
||||
"params": {
|
||||
"_type": "ParamSpec",
|
||||
"pos": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
},
|
||||
"default": null
|
||||
}
|
||||
],
|
||||
"mixed": [
|
||||
{
|
||||
"name": "b",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "float",
|
||||
"args": []
|
||||
},
|
||||
"default": null
|
||||
}
|
||||
],
|
||||
"kw": [
|
||||
{
|
||||
"name": "c",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "str",
|
||||
"args": []
|
||||
},
|
||||
"default": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"returns": {
|
||||
"_type": "BaseType",
|
||||
"base": "Any",
|
||||
"args": []
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"_type": "ReturnStmt",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_type": "Function",
|
||||
"name": "o",
|
||||
"params": {
|
||||
"_type": "ParamSpec",
|
||||
"pos": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "int",
|
||||
"args": []
|
||||
},
|
||||
"default": {
|
||||
"_type": "LiteralExpr",
|
||||
"value": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"mixed": [
|
||||
{
|
||||
"name": "b",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "float",
|
||||
"args": []
|
||||
},
|
||||
"default": {
|
||||
"_type": "LiteralExpr",
|
||||
"value": 2.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"kw": [
|
||||
{
|
||||
"name": "c",
|
||||
"type": {
|
||||
"_type": "BaseType",
|
||||
"base": "str",
|
||||
"args": []
|
||||
},
|
||||
"default": {
|
||||
"_type": "LiteralExpr",
|
||||
"value": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"returns": {
|
||||
"_type": "BaseType",
|
||||
"base": "Any",
|
||||
"args": []
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"_type": "ReturnStmt",
|
||||
"value": {
|
||||
"_type": "LiteralExpr",
|
||||
"value": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_type": "ForStmt",
|
||||
"target": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "i"
|
||||
},
|
||||
"iterator": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "h"
|
||||
},
|
||||
"body": []
|
||||
},
|
||||
{
|
||||
"_type": "IfStmt",
|
||||
"test": {
|
||||
"_type": "CompareExpr",
|
||||
"left": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "e"
|
||||
},
|
||||
"operator": "==",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "f"
|
||||
}
|
||||
},
|
||||
"body": [],
|
||||
"orelse": [
|
||||
{
|
||||
"_type": "IfStmt",
|
||||
"test": {
|
||||
"_type": "CompareExpr",
|
||||
"left": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "f"
|
||||
},
|
||||
"operator": "==",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "g"
|
||||
}
|
||||
},
|
||||
"body": [],
|
||||
"orelse": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "p"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "UnaryExpr",
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
}
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"_type": "UnaryExpr",
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "b"
|
||||
}
|
||||
}
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "UnaryExpr",
|
||||
"operator": "~",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "c"
|
||||
}
|
||||
},
|
||||
"operator": "*",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "d"
|
||||
}
|
||||
},
|
||||
"operator": "/",
|
||||
"right": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "e"
|
||||
},
|
||||
"operator": "**",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "f"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "q"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "LogicalExpr",
|
||||
"left": {
|
||||
"_type": "UnaryExpr",
|
||||
"operator": "not",
|
||||
"right": {
|
||||
"_type": "LogicalExpr",
|
||||
"left": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
},
|
||||
"operator": "and",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "b"
|
||||
}
|
||||
}
|
||||
},
|
||||
"operator": "or",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "c"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "r"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
},
|
||||
"operator": "&",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "b"
|
||||
}
|
||||
},
|
||||
"operator": "|",
|
||||
"right": {
|
||||
"_type": "BinaryExpr",
|
||||
"left": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "c"
|
||||
},
|
||||
"operator": "^",
|
||||
"right": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "d"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "s"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "GetExpr",
|
||||
"object": {
|
||||
"_type": "GetExpr",
|
||||
"object": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
},
|
||||
"name": "b"
|
||||
},
|
||||
"name": "c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "t"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "SubscriptExpr",
|
||||
"object": {
|
||||
"_type": "SubscriptExpr",
|
||||
"object": {
|
||||
"_type": "SubscriptExpr",
|
||||
"object": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
},
|
||||
"index": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "b"
|
||||
}
|
||||
},
|
||||
"index": {
|
||||
"_type": "TupleExpr",
|
||||
"items": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "c"
|
||||
},
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "d"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"index": {
|
||||
"_type": "SliceExpr",
|
||||
"lower": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "e"
|
||||
},
|
||||
"upper": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "f"
|
||||
},
|
||||
"step": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_type": "AssignStmt",
|
||||
"targets": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "u"
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
"_type": "CallExpr",
|
||||
"callee": {
|
||||
"_type": "CallExpr",
|
||||
"callee": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "a"
|
||||
},
|
||||
"arguments": [
|
||||
{
|
||||
"_type": "VariableExpr",
|
||||
"name": "b"
|
||||
}
|
||||
],
|
||||
"keywords": {}
|
||||
},
|
||||
"arguments": [],
|
||||
"keywords": {
|
||||
"c": {
|
||||
"_type": "VariableExpr",
|
||||
"name": "d"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+12
-1
@@ -1,3 +1,4 @@
|
||||
import ast
|
||||
import json
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from pathlib import Path
|
||||
@@ -6,17 +7,27 @@ import midas.ast.python as p
|
||||
from midas.checker.checker import TypeChecker
|
||||
from midas.checker.diagnostic import Diagnostic
|
||||
from midas.checker.types import Type
|
||||
from midas.lexer.token import TokenType
|
||||
from tests.base import Tester
|
||||
from tests.serializer.python import PythonAstJsonSerializer
|
||||
|
||||
|
||||
class CustomEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
if isinstance(o, ast.AST):
|
||||
return ast.dump(o)
|
||||
if isinstance(o, TokenType):
|
||||
return o.name
|
||||
return super().default(o)
|
||||
|
||||
|
||||
@dataclass
|
||||
class CaseResult:
|
||||
diagnostics: list[dict] = field(default_factory=list)
|
||||
judgments: list = field(default_factory=list)
|
||||
|
||||
def dumps(self) -> str:
|
||||
return json.dumps(asdict(self), indent=2)
|
||||
return json.dumps(asdict(self), indent=2, cls=CustomEncoder)
|
||||
|
||||
|
||||
class CheckerTester(Tester):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Optional, Sequence
|
||||
from typing import Optional, Sequence, final
|
||||
|
||||
from midas.ast.midas import (
|
||||
AliasStmt,
|
||||
@@ -28,6 +28,7 @@ from midas.ast.midas import (
|
||||
)
|
||||
|
||||
|
||||
@final
|
||||
class MidasAstJsonSerializer(
|
||||
Stmt.Visitor[dict], Expr.Visitor[dict], Type.Visitor[dict]
|
||||
):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ast
|
||||
from typing import Optional, Sequence, Type
|
||||
from typing import Optional, Sequence, Type, final
|
||||
|
||||
from midas.ast.python import (
|
||||
AssignStmt,
|
||||
@@ -78,6 +78,7 @@ boolean_ops: dict[Type[ast.boolop], str] = {
|
||||
}
|
||||
|
||||
|
||||
@final
|
||||
class PythonAstJsonSerializer(
|
||||
Stmt.Visitor[dict], Expr.Visitor[dict], MidasType.Visitor[dict]
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user