import continuation

_path = None

class Path:
    def __init__(self,choices):
        global _path
        self.cont = continuation.caller(2)
        self.choices = choices
        self._next = _path
        _path = self
    def next(self):
        if not self.choices:
            _path = self._next
            if not _path:
                raise AmbEvalError("no answers found")
            _path.next()
        val = self.choices[0]
        self.choices = self.choices[1:]
        self.cont(val)

class AmbEvalError(Exception):
    pass

def choose(choices):
    Path(choices).next()

def fail():
    _path.next()

def require(condition):
    if not condition:
        fail()

def amb_eval(func,*args):
    global _path
    _path = None
    try:
        return apply(func,args)
    finally:
        _path = None

def amb_getall(func,*args):
    global _path
    _path = None
    result = []
    try:
        result.append( apply(func,args) )
        while 1:
            result.append( fail() )
    except AmbEvalError:
        return result

if __name__=='__main__':
    def trick(n):
        x = choose(range(1,10))
        y = choose(range(1,10))
        require(x + y == n)
        return x,y
    import sys
    print amb_getall(trick,int(sys.argv[1]))
