def emit(g: Graph) -> Module: i = 0 m = Module() variables: t.Dict[int, Symbol] = {} # TODO: with type # TODO: name original_args = [ f"{node.name} string" for node in g.nodes if node.is_primitive ] with m.func("run", *original_args, return_="error"): for node in topological_sorted(g): if node.is_primitive: variables[node.uid] = m.symbol(node.name) continue args = [] for dep in node.depends: args.append(variables[dep.uid]) m.letN return_type = node.metadata.get("return_type", "") if return_type == "": [variables[node.uid]] = m.letN([f"v{i}"], m.symbol(node.name)(*args)) elif return_type == "with-err": variables[node.uid], err = m.letN((f"v{i}", "err"), m.symbol(node.name)(*args)) with m.if_("err != nil"): m.return_("err") elif return_type == "with-cleanup": variables[node.uid], cleanup = m.letN( (f"v{i}", "cleanup"), m.symbol(node.name)(*args)) m.stmt("defer cleanup()") elif return_type == "with-cleanup-err": variables[node.uid], cleanup, err = m.letN( (f"v{i}", "cleanup", "err"), m.symbol(node.name)(*args)) with m.if_("err != nil"): m.return_("err") m.stmt("defer cleanup()") else: raise ValueError(f"unexpected return_type {return_type}") i += 1 m.return_("nil") return m
def gen(*, m: t.Optional[Module] = None, names: t.List[str]) -> Module: m = m or Module() m.stmt("package main") m.sep() m.toplevel = m.submodule() m.sep() m.stmt("func main() {") with m.scope(): m.stmt("if err := run(); err != nil {") with m.scope(): log = m.toplevel.import_("log") m.stmt(f'{log.Fatalf}("!!%+v", err)') m.stmt("}") m.stmt("}") m.sep() visit(m, names=names) return m
def emit(g: Graph) -> Module: # TODO: name # TODO: import_ i = 0 m = Module() variables: t.Dict[int, Symbol] = {} with m.func("run", *_get_args(g), return_="error"): for node in topological_sorted(g): if node.is_primitive: variables[node.uid] = m.symbol(node.name) continue metadata = t.cast(Metadata, node.metadata) return_type = metadata.get("return_type", "") return_types = list(t.get_args(return_type) or [return_type]) var_names = [ f"v{i}", *[ getattr(typ, "name", typ.__name__) for typ in return_types[1:] ], ] provider_callable = m.symbol(metadata.get("provider") or node.name) args = [variables[dep.uid] for dep in node.depends] variables[node.uid], *extra_vars = m.letN(var_names, provider_callable(*args)) if extra_vars: for sym, typ in sorted( zip(extra_vars, return_types[1:]), key=lambda pair: getattr(pair[1], "priority", 5), reverse=True, ): if hasattr(typ, "emit"): typ.emit(m, sym) i += 1 m.return_("nil") return m
def emit(g: Graph) -> Module: i = 0 m = Module() variables: t.Dict[int, Symbol] = {} # TODO: with type # TODO: name root_args = [ f"{node.name} string" for node in g.nodes if node.is_primitive ] with m.func("run", *root_args, return_="error"): for node in topological_sorted(g): if node.is_primitive: variables[node.uid] = m.symbol(node.name) continue metadata = t.cast(Metadata, node.metadata) return_type = metadata.get("return_type", "") return_types = list(t.get_args(return_type) or [return_type]) var_names = [ f"v{i}", *[ getattr(typ, "name", typ.__name__) for typ in return_types[1:] ], ] provider_callable = m.symbol(metadata.get("provider") or node.name) args = [variables[dep.uid] for dep in node.depends] variables[node.uid], *extra_vars = m.letN(var_names, provider_callable(*args)) if extra_vars: for sym, typ in zip(extra_vars, return_types[1:]): if hasattr(typ, "emit"): typ.emit(m, sym) i += 1 m.return_("nil") return m
def gen(*, m=None): m = m or Module() m.stmt("package main") m.sep() m.stmt("import (") with m.scope(): m.stmt('"fmt"') m.stmt('"log"') m.sep() m.stmt('"github.com/pkg/errors"') m.stmt(")") m.sep() m.stmt("func main() {") with m.scope(): m.stmt("if err := run(); err != nil {") with m.scope(): m.stmt('log.Fatalf("!!%+v", err)') m.stmt("}") m.stmt("}") m.sep() visit(m, names=["f", "g"]) return m
returns=return_type, ): emit_fn(m.symbol(self.receiver), *args) return m.symbol(methodname) def _literal(s: str) -> t.Any: import json from prestring.utils import UnRepr return UnRepr(json.dumps(s)) gomethod = staticmethod class Greeter: @gomethod def emitHello(self, message: str) -> str: global m fmt = m.import_("fmt") m.return_(fmt.Printf(_literal("Hello %s\n"), message)) m = Module() m.package("greeter") m.import_("") emitter = MethodEmitter(Greeter) emitter.emit(Greeter.emitHello) print(m)