feat(cli): dump environment after compile
This commit is contained in:
@@ -273,7 +273,7 @@ class Checker(
|
|||||||
|
|
||||||
def visit_return_stmt(self, stmt: p.ReturnStmt) -> None:
|
def visit_return_stmt(self, stmt: p.ReturnStmt) -> None:
|
||||||
type: Type = stmt.value.accept(self) if stmt.value is not None else UnitType()
|
type: Type = stmt.value.accept(self) if stmt.value is not None else UnitType()
|
||||||
self.env.return_types.add(type)
|
self.env.return_types.append(type)
|
||||||
raise ReturnException()
|
raise ReturnException()
|
||||||
|
|
||||||
def visit_binary_expr(self, expr: p.BinaryExpr) -> Type:
|
def visit_binary_expr(self, expr: p.BinaryExpr) -> Type:
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ class Environment:
|
|||||||
def __init__(self, enclosing: Optional[Environment] = None) -> None:
|
def __init__(self, enclosing: Optional[Environment] = None) -> None:
|
||||||
self.enclosing: Optional[Environment] = enclosing
|
self.enclosing: Optional[Environment] = enclosing
|
||||||
self.values: dict[str, Type] = {}
|
self.values: dict[str, Type] = {}
|
||||||
self.return_types: set[Type] = set()
|
self.return_types: list[Type] = []
|
||||||
|
|
||||||
|
self._children: list[Environment] = []
|
||||||
|
if enclosing is not None:
|
||||||
|
enclosing._children.append(self)
|
||||||
|
|
||||||
def define(self, name: str, value: Type) -> None:
|
def define(self, name: str, value: Type) -> None:
|
||||||
"""Define a variable in this environment
|
"""Define a variable in this environment
|
||||||
@@ -129,3 +133,10 @@ class Environment:
|
|||||||
if self.enclosing is None:
|
if self.enclosing is None:
|
||||||
return self.values
|
return self.values
|
||||||
return self.enclosing.flat_dict() | self.values
|
return self.enclosing.flat_dict() | self.values
|
||||||
|
|
||||||
|
def dump(self) -> dict:
|
||||||
|
return {
|
||||||
|
"values": self.values,
|
||||||
|
"return_types": self.return_types,
|
||||||
|
"children": [child.dump() for child in self._children],
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import ast
|
import ast
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -18,6 +19,7 @@ from midas.lexer.token import Token, TokenType
|
|||||||
from midas.parser.midas import MidasParser
|
from midas.parser.midas import MidasParser
|
||||||
from midas.parser.python import PythonParser
|
from midas.parser.python import PythonParser
|
||||||
from midas.resolver.resolver import Resolver
|
from midas.resolver.resolver import Resolver
|
||||||
|
from midas.utils import UniversalJSONDumper
|
||||||
|
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
@@ -40,6 +42,15 @@ def compile(file: TextIO):
|
|||||||
for diagnostic in diagnostics:
|
for diagnostic in diagnostics:
|
||||||
print(diagnostic)
|
print(diagnostic)
|
||||||
|
|
||||||
|
print(
|
||||||
|
json.dumps(
|
||||||
|
UniversalJSONDumper.dump(
|
||||||
|
checker.global_env, [("Environment", "_children")]
|
||||||
|
),
|
||||||
|
indent=4,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@midas.group()
|
@midas.group()
|
||||||
def utils():
|
def utils():
|
||||||
|
|||||||
40
midas/utils.py
Normal file
40
midas/utils.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class UniversalJSONDumper:
|
||||||
|
@classmethod
|
||||||
|
def dump(
|
||||||
|
cls, obj: Any, include_keys: Optional[list[str | tuple[str, str]]] = None
|
||||||
|
) -> Any:
|
||||||
|
if include_keys is None:
|
||||||
|
include_keys = []
|
||||||
|
return cls._dump(obj, include_keys, [])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _dump(
|
||||||
|
cls, obj: Any, include_keys: list[str | tuple[str, str]], visited: list[Any]
|
||||||
|
) -> Any:
|
||||||
|
if obj in visited:
|
||||||
|
return None
|
||||||
|
match obj:
|
||||||
|
case str() | int() | float() | None:
|
||||||
|
return obj
|
||||||
|
case list() | set() | tuple():
|
||||||
|
return [cls._dump(child, include_keys, visited) for child in obj]
|
||||||
|
case dict():
|
||||||
|
return {
|
||||||
|
str(k): cls._dump(v, include_keys, visited) for k, v in obj.items()
|
||||||
|
}
|
||||||
|
case object():
|
||||||
|
visited.append(obj)
|
||||||
|
return {
|
||||||
|
"_type": obj.__class__.__name__,
|
||||||
|
} | {
|
||||||
|
k: cls._dump(v, include_keys, visited)
|
||||||
|
for k, v in obj.__dict__.items()
|
||||||
|
if not k.startswith("_")
|
||||||
|
or k in include_keys
|
||||||
|
or (obj.__class__.__name__, k) in include_keys
|
||||||
|
}
|
||||||
|
case _:
|
||||||
|
raise ValueError(f"Unsupported value: {obj}")
|
||||||
Reference in New Issue
Block a user