"""Intermediate representation of modules.""" from typing import List, Tuple, Dict from mypyc.common import JsonDict from mypyc.ir.ops import DeserMaps from mypyc.ir.rtypes import RType, deserialize_type from mypyc.ir.func_ir import FuncIR, FuncDecl from mypyc.ir.class_ir import ClassIR class ModuleIR: """Intermediate representation of a module.""" def __init__( self, fullname: str, imports: List[str], functions: List[FuncIR], classes: List[ClassIR], final_names: List[Tuple[str, RType]]) -> None: self.fullname = fullname self.imports = imports[:] self.functions = functions self.classes = classes self.final_names = final_names def serialize(self) -> JsonDict: return { 'fullname': self.fullname, 'imports': self.imports, 'functions': [f.serialize() for f in self.functions], 'classes': [c.serialize() for c in self.classes], 'final_names': [(k, t.serialize()) for k, t in self.final_names], } @classmethod def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'ModuleIR': return ModuleIR( data['fullname'], data['imports'], [ctx.functions[FuncDecl.get_id_from_json(f)] for f in data['functions']], [ClassIR.deserialize(c, ctx) for c in data['classes']], [(k, deserialize_type(t, ctx)) for k, t in data['final_names']], ) def deserialize_modules(data: Dict[str, JsonDict], ctx: DeserMaps) -> Dict[str, ModuleIR]: """Deserialize a collection of modules. The modules can contain dependencies on each other. Arguments: data: A dict containing the modules to deserialize. ctx: The deserialization maps to use and to populate. They are populated with information from the deserialized modules and as a precondition must have been populated by deserializing any dependencies of the modules being deserialized (outside of dependencies between the modules themselves). Returns a map containing the deserialized modules. """ for mod in data.values(): # First create ClassIRs for every class so that we can construct types and whatnot for cls in mod['classes']: ir = ClassIR(cls['name'], cls['module_name']) assert ir.fullname not in ctx.classes, "Class %s already in map" % ir.fullname ctx.classes[ir.fullname] = ir for mod in data.values(): # Then deserialize all of the functions so that methods are available # to the class deserialization. for method in mod['functions']: func = FuncIR.deserialize(method, ctx) assert func.decl.id not in ctx.functions, ( "Method %s already in map" % func.decl.fullname) ctx.functions[func.decl.id] = func return {k: ModuleIR.deserialize(v, ctx) for k, v in data.items()} # ModulesIRs should also always be an *OrderedDict*, but if we # declared it that way we would need to put it in quotes everywhere... ModuleIRs = Dict[str, ModuleIR]