Innovations Anonymous
Innovations Anonymous

Reputation: 134

How to execute AST or code object in a separate process without exceeding max recursion depth

I am trying to write a metamorphic quine. Without the "spawn" context, the subprocesses seem to inherit the stack, and so I ultimately exceed the max recursion depth. With the "spawn context," the subprocess doesn't seem to recurse. How would I go about executing the modified AST?

def main():
    module  = sys.modules[__name__]
    source  = inspect.getsource(module)
    tree    = ast.parse(source)

    visitor = Visitor() # TODO mutate
    tree    = visitor.visit(tree)
    tree    = ast.fix_missing_locations(tree)

    ctx     = multiprocessing.get_context("spawn")
    process = ctx.Process(target=Y, args=(tree,))
    # Y() encapsulates these lines, since code objects can't be pickled
    #code    = compile(tree, filename="<ast>", mode='exec', optimize=2)
    #process = ctx.Process(target=exec, args=(code, globals())) # locals()

    process.daemon = True
    process.start()
    # TODO why do daemonized processes need to be joined in order to run?
    process.join()

    return 0

if __name__ == '__main__': exit(main())

Upvotes: 0

Views: 331

Answers (1)

Innovations Anonymous
Innovations Anonymous

Reputation: 134

It really is that easy. with daemon.DaemonContext(): foo() Based on comments by @user2357112 supports Monica.

@trace
def spawn_child(f:Callable):
    with daemon.DaemonContext(stdin=sys.stdin, stdout=sys.stdout): return f()

I = TypeVar('I')
def ai(f:Callable[[int,], I])->Callable[[int,], I]:
    def g(*args, **kwargs)->int:
        # assuming we have a higher-order function morph()
        # that has a concept of eta-equivalence
        # (e.g., a probabilistic notion),
        # then the recursive call should be "metamorphic"
        O = [morph(f), status, partial(spawn_child, f),]
        i = random.randrange(0, len(O)) # TODO something magickal
        return O[i]()
    return g

def main()->int: return Y(ai)()

if __name__ == '__main__': exit(main())

The next problem is compiling the source for a nested function definition, since f() is not a reference to ai() but to a function defined within Y().

Upvotes: 0

Related Questions