feat(checker): remove custom midas import
remove custom import statement (`midas.using`) in favor of passing type definition files as arguments to the checker
This commit is contained in:
@@ -2,10 +2,6 @@
|
|||||||
# ruff: disable[F821]
|
# ruff: disable[F821]
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
# Prototype of custom type import to use valid Python syntax
|
|
||||||
import midas
|
|
||||||
midas.using("02_custom_types.midas")
|
|
||||||
|
|
||||||
# A data-frame using a custom type
|
# A data-frame using a custom type
|
||||||
df: Frame[
|
df: Frame[
|
||||||
location: GeoLocation
|
location: GeoLocation
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
# type: ignore
|
# type: ignore
|
||||||
# ruff: disable [F821]
|
# ruff: disable [F821]
|
||||||
|
|
||||||
midas.using("02_simple_types.midas")
|
|
||||||
|
|
||||||
distance: Meter = cast(Meter, 123.45)
|
distance: Meter = cast(Meter, 123.45)
|
||||||
time: Second = cast(Second, 6.7)
|
time: Second = cast(Second, 6.7)
|
||||||
speed = distance / time
|
speed = distance / time
|
||||||
|
|||||||
@@ -34,9 +34,15 @@ class Checker(
|
|||||||
):
|
):
|
||||||
"""A type checker which can use custom type definitions"""
|
"""A type checker which can use custom type definitions"""
|
||||||
|
|
||||||
def __init__(self, locals: dict[p.Expr, int], file_path: Path):
|
def __init__(
|
||||||
|
self,
|
||||||
|
locals: dict[p.Expr, int],
|
||||||
|
source_path: Path,
|
||||||
|
types_paths: list[Path],
|
||||||
|
):
|
||||||
self.logger: logging.Logger = logging.getLogger("Checker")
|
self.logger: logging.Logger = logging.getLogger("Checker")
|
||||||
self.file_path: Path = file_path
|
self.source_path: Path = source_path
|
||||||
|
self.types_paths: list[Path] = types_paths
|
||||||
self.ctx: MidasResolver = MidasResolver()
|
self.ctx: MidasResolver = MidasResolver()
|
||||||
self.global_env: Environment = Environment()
|
self.global_env: Environment = Environment()
|
||||||
self.env: Environment = self.global_env
|
self.env: Environment = self.global_env
|
||||||
@@ -46,7 +52,7 @@ class Checker(
|
|||||||
def diagnostic(self, type: DiagnosticType, location: Location, message: str):
|
def diagnostic(self, type: DiagnosticType, location: Location, message: str):
|
||||||
self.diagnostics.append(
|
self.diagnostics.append(
|
||||||
Diagnostic(
|
Diagnostic(
|
||||||
file_path=self.file_path,
|
file_path=self.source_path,
|
||||||
location=location,
|
location=location,
|
||||||
type=type,
|
type=type,
|
||||||
message=message,
|
message=message,
|
||||||
@@ -119,6 +125,12 @@ class Checker(
|
|||||||
list[Diagnostic]: the list of diagnostics (errors, warning, etc.)
|
list[Diagnostic]: the list of diagnostics (errors, warning, etc.)
|
||||||
"""
|
"""
|
||||||
self.diagnostics = []
|
self.diagnostics = []
|
||||||
|
|
||||||
|
for path in self.types_paths:
|
||||||
|
self.import_midas(path)
|
||||||
|
self.logger.debug(f"Midas types: {self.ctx._types}")
|
||||||
|
self.logger.debug(f"Midas operations: {self.ctx._operations}")
|
||||||
|
|
||||||
for stmt in statements:
|
for stmt in statements:
|
||||||
stmt.accept(self)
|
stmt.accept(self)
|
||||||
|
|
||||||
@@ -140,30 +152,6 @@ class Checker(
|
|||||||
return self.env.get_at(distance, name)
|
return self.env.get_at(distance, name)
|
||||||
return self.global_env.get(name)
|
return self.global_env.get(name)
|
||||||
|
|
||||||
def parse_midas_import(self, expr: p.CallExpr) -> Optional[Path]:
|
|
||||||
"""Parse a Midas import statement
|
|
||||||
|
|
||||||
The statement should be written as `midas.using("path/to/types.midas")`
|
|
||||||
|
|
||||||
Args:
|
|
||||||
expr (p.CallExpr): the import call expression
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Optional[Path]: the path to the imported file, or None if the expression is malformed
|
|
||||||
"""
|
|
||||||
match expr:
|
|
||||||
case p.CallExpr(
|
|
||||||
callee=p.GetExpr(
|
|
||||||
object=p.VariableExpr(name="midas"),
|
|
||||||
name="using",
|
|
||||||
),
|
|
||||||
arguments=[
|
|
||||||
p.LiteralExpr(value=path),
|
|
||||||
],
|
|
||||||
):
|
|
||||||
return Path(path)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def import_midas(self, path: Path) -> None:
|
def import_midas(self, path: Path) -> None:
|
||||||
"""Import Midas definitions from a path
|
"""Import Midas definitions from a path
|
||||||
|
|
||||||
@@ -171,14 +159,11 @@ class Checker(
|
|||||||
path (Path): the import path
|
path (Path): the import path
|
||||||
"""
|
"""
|
||||||
self.logger.debug(f"Importing type definitions from {path}")
|
self.logger.debug(f"Importing type definitions from {path}")
|
||||||
path = (self.file_path.parent / path).resolve()
|
|
||||||
lexer: MidasLexer = MidasLexer(path.read_text())
|
lexer: MidasLexer = MidasLexer(path.read_text())
|
||||||
tokens: list[Token] = lexer.process()
|
tokens: list[Token] = lexer.process()
|
||||||
parser: MidasParser = MidasParser(tokens)
|
parser: MidasParser = MidasParser(tokens)
|
||||||
stmts: list[m.Stmt] = parser.parse()
|
stmts: list[m.Stmt] = parser.parse()
|
||||||
self.ctx.resolve(stmts)
|
self.ctx.resolve(stmts)
|
||||||
self.logger.debug(f"Midas types: {self.ctx._types}")
|
|
||||||
self.logger.debug(f"Midas operations: {self.ctx._operations}")
|
|
||||||
|
|
||||||
def visit_expression_stmt(self, stmt: p.ExpressionStmt) -> None:
|
def visit_expression_stmt(self, stmt: p.ExpressionStmt) -> None:
|
||||||
self.type_of(stmt.expr)
|
self.type_of(stmt.expr)
|
||||||
@@ -362,9 +347,6 @@ class Checker(
|
|||||||
def visit_unary_expr(self, expr: p.UnaryExpr) -> Type: ...
|
def visit_unary_expr(self, expr: p.UnaryExpr) -> Type: ...
|
||||||
|
|
||||||
def visit_call_expr(self, expr: p.CallExpr) -> Type:
|
def visit_call_expr(self, expr: p.CallExpr) -> Type:
|
||||||
if path := self.parse_midas_import(expr):
|
|
||||||
self.import_midas(path)
|
|
||||||
return UnknownType()
|
|
||||||
callee: Type = self.type_of(expr.callee)
|
callee: Type = self.type_of(expr.callee)
|
||||||
if not isinstance(callee, Function):
|
if not isinstance(callee, Function):
|
||||||
self.error(expr.callee.location, "Callee is not a function")
|
self.error(expr.callee.location, "Callee is not a function")
|
||||||
|
|||||||
Reference in New Issue
Block a user