Esempio n. 1
0
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
Esempio n. 2
0
def emit(m: Module, g: Graph) -> Symbol:
    # TODO: name
    # TODO: import_
    i = 0
    variables: t.Dict[int, Symbol] = {}

    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:]],
        ]

        spec: Fnspec = metadata.get("fnspec")
        provider_callable: t.Optional[Symbol] = None
        if spec is not None:
            pkg_prefix = m.import_(metadata["component_type"].gopackage)
            provider_callable = m.symbol(f"{pkg_prefix}.{spec.name}")
        if provider_callable is None:
            provider_callable = m.symbol(spec.name if spec else 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
    return variables[node.uid]
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
def inject(
    m: Module,
    g: Graph,
    *,
    variables: t.Dict[int, Symbol],
    levels: t.Optional[t.Dict[int, int]] = None,
    nodes: t.Optional[t.List[Node]] = None,
    seen: t.Optional[t.Set[int]] = None,
    strict: bool = True,
) -> Symbol:
    # TODO: name
    i = len(variables)
    if levels is None:
        levels = defaultdict(int)
    if nodes:
        node = nodes[0]

    nodes = topological_sorted(g, seen=seen, nodes=nodes)
    for node in nodes:
        if node.is_primitive:
            if strict:
                assert node.uid in variables
            else:
                variables[node.uid] = m.symbol(node.name)
            continue

        metadata = t.cast(Metadata, node.metadata)
        return_type = metadata.get("return_type", "")

        # handling provider callable
        return_types = list(typing_get_args(return_type) or [return_type])
        var_names = [
            f"v{i}",
            *[getattr(typ, "name", typ.__name__) for typ in return_types[1:]],
        ]

        spec: t.Optional[Fnspec] = metadata.get("fnspec")
        provider_callable: t.Optional[Symbol] = None
        if spec is not None:
            provider = spec.name
            pkg = get_gopackage(metadata["fnspec"].body)
            if pkg is not None:
                pkg_prefix = m.import_(pkg)
                provider = f"{pkg_prefix}.{provider}"
            provider_callable = m.symbol(provider)
        if provider_callable is None:
            provider_callable = m.symbol(spec.name if spec else node.name)

        # handling arguments (pointer)
        if spec is None:
            args = [variables[dep.uid] for dep in node.depends]  # todo: remove
        else:
            args = []
            assert len(node.depends) == len(spec.arguments), (
                len(node.depends),
                len(spec.arguments),
            )
            for dep, (name, typ, _) in zip(node.depends,
                                           spec.arguments):  # parameters?
                sym = variables[dep.uid]

                current_level = levels[dep.uid]
                need_level = metadata["levels"].get(name, 0)  # more strict?
                level_diff = need_level - current_level

                if level_diff == 0:
                    pass
                elif level_diff > 0:
                    sym = Symbol("&" * level_diff + str(sym))
                else:
                    sym = Symbol("*" * -level_diff + str(sym))
                args.append(sym)
            levels[node.uid] = metadata["levels"]["return"]

        variables[node.uid], *extra_vars = m.letN(var_names,
                                                  provider_callable(*args))

        # handling error and cleanup:
        if extra_vars:
            for sym, typ in sorted(
                    zip(extra_vars, return_types[1:]),
                    key=lambda pair: getattr(  # type:ignore
                        pair[1], "priority", priority.NORMAL),
                    reverse=True,
            ):
                if hasattr(typ, "emit"):
                    typ.emit(m, sym)

        i += 1
    return variables[node.uid]