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:
|
||||
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()
|
||||
|
||||
def visit_binary_expr(self, expr: p.BinaryExpr) -> Type:
|
||||
|
||||
@@ -15,7 +15,11 @@ class Environment:
|
||||
def __init__(self, enclosing: Optional[Environment] = None) -> None:
|
||||
self.enclosing: Optional[Environment] = enclosing
|
||||
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:
|
||||
"""Define a variable in this environment
|
||||
@@ -129,3 +133,10 @@ class Environment:
|
||||
if self.enclosing is None:
|
||||
return 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 json
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
@@ -18,6 +19,7 @@ from midas.lexer.token import Token, TokenType
|
||||
from midas.parser.midas import MidasParser
|
||||
from midas.parser.python import PythonParser
|
||||
from midas.resolver.resolver import Resolver
|
||||
from midas.utils import UniversalJSONDumper
|
||||
|
||||
|
||||
@click.group()
|
||||
@@ -40,6 +42,15 @@ def compile(file: TextIO):
|
||||
for diagnostic in diagnostics:
|
||||
print(diagnostic)
|
||||
|
||||
print(
|
||||
json.dumps(
|
||||
UniversalJSONDumper.dump(
|
||||
checker.global_env, [("Environment", "_children")]
|
||||
),
|
||||
indent=4,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@midas.group()
|
||||
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