def make_adts(self, typedefs): adts = CodeSection("algebraic data types") adt_names = set() for typedef in typedefs: adt = typedef.typ adt_names.add(adt.type_name) # If true, this ADT contains a function type somewhere, and # therefore cannot derive Show or Eq. has_function = False ind = 0 for i, constructor in enumerate(adt.constructors): params = [] for p in constructor.parameters: pstring = self.funky_type_to_haskell(p, adt_names) if "->" in pstring: has_function = True params.append(pstring) params = " ".join(params) if i == 0: definition = "data {}{}".format(self.ADT_PREFIX, adt.type_name) ind = len(definition) + 1 line = "{} = {}{} {}".format(definition, self.ADT_PREFIX, constructor.identifier, params) adts.emit(line) else: line = "| {}{} {}".format(self.ADT_PREFIX, constructor.identifier, params) adts.emit(line, d=ind) self.constructor_names.add(constructor.identifier) if not has_function: adts.emit("deriving (Show, Eq)", d=ind) adts.newline() return adts
def make_core_section(self, core_tree): core_section = CodeSection("core section") for bind in core_tree.binds: compiled_bind = self.hs_compile(bind) core_section.emit(compiled_bind) core_section.newline() return core_section
def do_generate_code(self, core_tree, typedefs): """Generates Python code from the core tree and type definitions. :param core_tree: the type-checked core tree from the desugarer :param typedefs: the typedefs from the desugarer :return: the generated Python code as a string :rtype: str """ super().do_generate_code(core_tree, typedefs) log.info("Generating {} code...".format(self.lang_name)) self.program.reset() self.runtime.reset() header_section = self.code_header() base_runtime_section = self.make_base_runtime() log.info("Creating user-defined data structres...") adts_section = self.make_adts(typedefs) log.info("Done.") log.info("Compiling core tree...") core_section = CodeSection("core code") main = self.py_compile(core_tree, core_section, 0) log.info("Done.") log.info("Creating main method...") main_section = self.make_main(main) log.info("Done.") log.info("Creating used runtime section...") used_runtime_section = self.make_used_runtime() log.info("Done.") for i, section in enumerate([header_section, base_runtime_section, used_runtime_section, adts_section, core_section, main_section]): self.program.add_section(section, i) log.info("Done generating {} code.".format(self.lang_name)) return self.program.get_code()
def get_runtime(self): runtime_section = CodeSection("runtime") for method_code in self.used_runtime_methods: runtime_section.emit(method_code) runtime_section.newline() return runtime_section
def make_main_section(self, expr): main_section = CodeSection("main") main_section.emit("main = do") main_section.emit(" print ({})".format(self.hs_compile(expr))) return main_section
def make_base_runtime(self): runtime_section = CodeSection("base runtime") runtime_section.emit(base_runtime) runtime_section.newline() return runtime_section
def make_main(self, main): main_section = CodeSection("main method") main_section.emit("def result():") main_section.emit("return {}".format(main), d=4) main_section.emit("") main_section.emit("def main():") # are we in the REPL? if so, we want to show the representation of an # object. this has the nice benefit of wrapping it in quotes, etc, if # need be if funky.globals.CURRENT_MODE == funky.globals.Mode.REPL: main_section.emit("print(repr(result()))", d=4) else: main_section.emit("print(result())", d=4) main_section.newline() main_section.emit("if __name__ == \"__main__\":") main_section.emit(" main()") return main_section
def make_adts(self, typedefs): adts = CodeSection("algebraic data types") for typedef in typedefs: adt = typedef.typ superclass_name = "ADT{}".format(adt.type_name) adts.emit("class {}(ADT):".format(superclass_name)) adts.emit(" pass") adts.newline() for constructor in adt.constructors: constructor_name = "ADT{}".format(constructor.identifier) adts.emit("class {}({}):".format(constructor_name, superclass_name)) varnames = ["v{}".format(i) for i, _ in enumerate(constructor.parameters)] adts.newline() if varnames: adts.emit(" def __init__(self, {}):".format(", ".join(varnames))) adts.emit(" super().__init__([{}])".format(", ".join(v for v in varnames))) else: adts.emit(" def __init__(self):".format(", ".join(varnames))) adts.emit(" super().__init__([])") adts.newline() s = "" for var in varnames: s += "lambda {}: ".format(var) if constructor.identifier in kwlist: py_name = "__{}".format(constructor.identifier) else: py_name = constructor.identifier adts.emit("{} = {}{}({})".format(py_name, s, constructor_name, ", ".join(varnames))) adts.newline() return adts