예제 #1
0
    def run(self, unused):
        from typhon.objects.collections.maps import EMPTY_MAP
        if self.done:
            return

        if self._ref.isResolved():
            if isBroken(self._ref):
                f = self._eb
            else:
                f = self._cb
            try:
                outcome = f.call(u"run", [self._ref])
                if not isBroken(self._ref) and isBroken(outcome):
                    # success arm returned a broken promise
                    outcome = self._eb.call(u"run", [outcome])
                self._resolver.resolve(outcome)
            except UserException as ue:
                from typhon.objects.exceptions import sealException
                if not isBroken(self._ref):
                    # success arm threw
                    try:
                        self._resolver.resolve(self._eb.call(u"run", [UnconnectedRef(currentVat.get(), sealException(ue))]))
                    except UserException as ue2:
                        self._resolver.smash(sealException(ue2))
                else:
                    # failure arm threw
                    self._resolver.smash(sealException(ue))
            self.done = True
        else:
            self.vat.sendOnly(self._ref, _WHENMORERESOLVED_1, [self],
                              EMPTY_MAP)
예제 #2
0
    def takeTurn(self):
        from typhon.objects.exceptions import sealException
        from typhon.objects.refs import Promise, resolution

        with self._pendingLock:
            resolver, target, atom, args, namedArgs = self._pending.pop(0)

        # Set up our Miranda FAIL.
        if namedArgs.extractStringKey(u"FAIL", None) is None:
            if resolver is not None:
                FAIL = resolver.makeSmasher()
            else:
                from typhon.objects.ejectors import theThrower
                FAIL = theThrower
            namedArgs = namedArgs.withStringKey(u"FAIL", FAIL)

        # If the target is a promise, then we should send to it instead of
        # calling. Try to resolve it as much as possible first, though.
        target = resolution(target)

        # self.log(u"Taking turn: %s<-%s(%s) (resolver: %s)" %
        #          (target.toQuote(), atom.verb,
        #           u", ".join([arg.toQuote() for arg in args]),
        #           u"yes" if resolver is not None else u"no"))
        try:
            if isinstance(target, Promise):
                if resolver is None:
                    target.sendOnly(atom, args, namedArgs)
                else:
                    result = target.send(atom, args, namedArgs)
                    # The resolver may have already been invoked, so we'll use
                    # .resolveRace/1 instead of .resolve/1. ~ C.
                    resolver.resolveRace(result)
            else:
                result = target.callAtom(atom, args, namedArgs)
                if resolver is not None:
                    # Same logic as above.
                    resolver.resolveRace(result)
        except UserException as ue:
            if resolver is not None:
                resolver.smash(sealException(ue))
            else:
                self.log(u"Uncaught user exception while taking turn"
                         u" (and no resolver): %s" %
                         ue.formatError().decode("utf-8"),
                         tags=["serious"])
        except VatCheckpointed:
            self.log(u"Ran out of checkpoints while taking turn",
                     tags=["serious"])
            if resolver is not None:
                resolver.smash(
                    sealException(userError(u"Vat ran out of checkpoints")))
        except Ejecting:
            self.log(u"Ejector tried to escape vat turn boundary",
                     tags=["serious"])
            if resolver is not None:
                resolver.smash(
                    sealException(
                        userError(u"Ejector tried to escape from vat")))
예제 #3
0
    def takeTurn(self):
        from typhon.objects.exceptions import sealException
        from typhon.objects.refs import Promise, resolution

        with self._pendingLock:
            resolver, target, atom, args, namedArgs = self._pending.pop(0)

        # Set up our Miranda FAIL.
        if namedArgs.extractStringKey(u"FAIL", None) is None:
            if resolver is not None:
                FAIL = resolver.makeSmasher()
            else:
                from typhon.objects.ejectors import theThrower
                FAIL = theThrower
            namedArgs = namedArgs.withStringKey(u"FAIL", FAIL)

        # If the target is a promise, then we should send to it instead of
        # calling. Try to resolve it as much as possible first, though.
        target = resolution(target)

        # self.log(u"Taking turn: %s<-%s(%s) (resolver: %s)" %
        #          (target.toQuote(), atom.verb,
        #           u", ".join([arg.toQuote() for arg in args]),
        #           u"yes" if resolver is not None else u"no"))
        try:
            if isinstance(target, Promise):
                if resolver is None:
                    target.sendOnly(atom, args, namedArgs)
                else:
                    result = target.send(atom, args, namedArgs)
                    # The resolver may have already been invoked, so we'll use
                    # .resolveRace/1 instead of .resolve/1. ~ C.
                    resolver.resolveRace(result)
            else:
                result = target.callAtom(atom, args, namedArgs)
                if resolver is not None:
                    # Same logic as above.
                    resolver.resolveRace(result)
        except UserException as ue:
            if resolver is not None:
                resolver.smash(sealException(ue))
            else:
                self.log(u"Uncaught user exception while taking turn"
                         u" (and no resolver): %s" %
                         ue.formatError().decode("utf-8"),
                         tags=["serious"])
        except VatCheckpointed:
            self.log(u"Ran out of checkpoints while taking turn",
                     tags=["serious"])
            if resolver is not None:
                resolver.smash(sealException(userError(u"Vat ran out of checkpoints")))
        except Ejecting:
            self.log(u"Ejector tried to escape vat turn boundary",
                     tags=["serious"])
            if resolver is not None:
                resolver.smash(sealException(userError(u"Ejector tried to escape from vat")))
예제 #4
0
 def unwind(self, machine, ex):
     machine.env.restoreDepth(self.savedDepth)
     # Push the caught value.
     machine.push(sealException(ex))
     # And the ejector.
     machine.push(NullObject)
     return self.index
예제 #5
0
    def _resolve(self, target, strict=True):
        if self._ref is None:
            if strict:
                raise userError(u"Already resolved")
            return False
        else:
            if self.guard is not None and not isinstance(target,
                    UnconnectedRef):
                # Coerce. If there's a problem, then smash the promise.
                with Ejector() as ej:
                    try:
                        target = self.guard.call(u"coerce", [target, ej])
                    except Ejecting as e:
                        if e.ejector is not ej:
                            raise
                        target = UnconnectedRef(self.vat, e.value)
                    except UserException as ue:
                        from typhon.objects.exceptions import sealException
                        target = UnconnectedRef(self.vat, sealException(ue))
            self._ref.setTarget(_toRef(target, self.vat))
            self._ref.commit()
            self._buf.deliverAll(target)

            self._ref = None
            self._buf = None
            return True
예제 #6
0
    def run(self, unused):
        from typhon.objects.collections.maps import EMPTY_MAP
        if self.done:
            return

        if self._ref.state() is NEAR:
            try:
                outcome = self._cb.call(u"run", [self._ref])
                if self._resolver is not None:
                    self._resolver.resolve(outcome)
            except UserException as ue:
                if self._resolver is None:
                    raise
                else:
                    from typhon.objects.exceptions import sealException
                    self._resolver.smash(sealException(ue))

            self.done = True
        elif self._ref.state() is BROKEN:
            if self._resolver is not None:
                self._resolver.resolve(self._ref)
            self.done = True
        else:
            self.vat.sendOnly(self._ref, _WHENMORERESOLVED_1, [self],
                              EMPTY_MAP)
예제 #7
0
 def unwind(self, machine, ex):
     machine.env.restoreDepth(self.savedDepth)
     # Push the caught value.
     machine.push(sealException(ex))
     # And the ejector.
     machine.push(NullObject)
     return self.index
예제 #8
0
파일: refs.py 프로젝트: dckc/typhon
    def run(self, unused):
        from typhon.objects.collections.maps import EMPTY_MAP
        if not isinstance(self._ref, Promise):
            # Near refs can't possibly be broken.
            return

        if self._ref.state() is EVENTUAL:
            self.vat.sendOnly(self._ref, _WHENMORERESOLVED_1, [self],
                              EMPTY_MAP)
        elif self._ref.state() is BROKEN:
            try:
                # Deliver the brokenness notification.
                outcome = self._cb.call(u"run", [self._ref])
                if self._resolver is not None:
                    # Success.
                    self._resolver.resolve(outcome)
            except UserException as ue:
                # Failure. Continue delivering failures.
                from typhon.objects.exceptions import sealException
                self._resolver.smash(sealException(ue))
예제 #9
0
파일: vats.py 프로젝트: washort/typhon
    def takeTurn(self):
        from typhon.objects.refs import Promise, resolution

        with self._pendingLock:
            resolver, target, atom, args, namedArgs = self._pending.pop(0)

        # If the target is a promise, then we should send to it instead of
        # calling. Try to resolve it as much as possible first, though.
        target = resolution(target)

        self.log(u"Taking turn: %s<-%s(%s) (resolver: %s)" %
                 (target.toQuote(), atom.verb,
                  u", ".join([arg.toQuote() for arg in args]),
                  u"yes" if resolver is not None else u"no"))
        if resolver is None:
            try:
                # callOnly/sendOnly.
                if isinstance(target, Promise):
                    target.sendOnly(atom, args, namedArgs)
                else:
                    # Oh, that's right; we don't do callOnly since it's silly.
                    target.callAtom(atom, args, namedArgs)
            except UserException as ue:
                self.log(u"Uncaught user exception while taking turn"
                         u" (and no resolver): %s" %
                         ue.formatError().decode("utf-8"),
                         tags=["serious"])
            except VatCheckpointed:
                self.log(u"Ran out of checkpoints while taking turn",
                         tags=["serious"])
            except Ejecting:
                self.log(u"Ejector tried to escape vat turn boundary",
                         tags=["serious"])

        else:
            from typhon.objects.collections.maps import ConstMap, monteMap
            from typhon.objects.exceptions import sealException
            from typhon.objects.refs import Smash
            # XXX monteMap()
            _d = monteMap()
            _d[StrObject(u"FAIL")] = Smash(resolver)
            MIRANDA_ARGS = ConstMap(_d)
            namedArgs = namedArgs._or(MIRANDA_ARGS)
            try:
                # call/send.
                if isinstance(target, Promise):
                    result = target.send(atom, args, namedArgs)
                else:
                    result = target.callAtom(atom, args, namedArgs)
                # Resolver may be invoked from the code in this turn, so
                # strict=False to skip this if already resolved.
                resolver.resolve(result, strict=False)
            except UserException as ue:
                resolver.smash(sealException(ue))
            except VatCheckpointed:
                self.log(u"Ran out of checkpoints while taking turn; breaking resolver",
                         tags=["serious"])
                resolver.smash(sealException(userError(u"Vat ran out of checkpoints")))
            except Ejecting:
                self.log(u"Ejector tried to escape vat turn boundary",
                         tags=["serious"])
                resolver.smash(sealException(userError(u"Ejector tried to escape from vat")))
예제 #10
0
    def takeTurn(self):
        from typhon.objects.refs import Promise, resolution

        with self._pendingLock:
            resolver, target, atom, args, namedArgs = self._pending.pop(0)

        # If the target is a promise, then we should send to it instead of
        # calling. Try to resolve it as much as possible first, though.
        target = resolution(target)

        self.log(
            u"Taking turn: %s<-%s(%s) (resolver: %s)" %
            (target.toQuote(), atom.verb, u", ".join(
                [arg.toQuote()
                 for arg in args]), u"yes" if resolver is not None else u"no"))
        if resolver is None:
            try:
                # callOnly/sendOnly.
                if isinstance(target, Promise):
                    target.sendOnly(atom, args, namedArgs)
                else:
                    # Oh, that's right; we don't do callOnly since it's silly.
                    target.callAtom(atom, args, namedArgs)
            except UserException as ue:
                self.log(u"Uncaught user exception while taking turn"
                         u" (and no resolver): %s" %
                         ue.formatError().decode("utf-8"),
                         tags=["serious"])
            except VatCheckpointed:
                self.log(u"Ran out of checkpoints while taking turn",
                         tags=["serious"])
            except Ejecting:
                self.log(u"Ejector tried to escape vat turn boundary",
                         tags=["serious"])

        else:
            from typhon.objects.collections.maps import ConstMap, monteMap
            from typhon.objects.exceptions import sealException
            from typhon.objects.refs import Smash
            # XXX monteMap()
            _d = monteMap()
            _d[StrObject(u"FAIL")] = Smash(resolver)
            MIRANDA_ARGS = ConstMap(_d)
            namedArgs = namedArgs._or(MIRANDA_ARGS)
            try:
                # call/send.
                if isinstance(target, Promise):
                    result = target.send(atom, args, namedArgs)
                else:
                    result = target.callAtom(atom, args, namedArgs)
                # Resolver may be invoked from the code in this turn, so
                # strict=False to skip this if already resolved.
                resolver.resolve(result, strict=False)
            except UserException as ue:
                resolver.smash(sealException(ue))
            except VatCheckpointed:
                self.log(
                    u"Ran out of checkpoints while taking turn; breaking resolver",
                    tags=["serious"])
                resolver.smash(
                    sealException(userError(u"Vat ran out of checkpoints")))
            except Ejecting:
                self.log(u"Ejector tried to escape vat turn boundary",
                         tags=["serious"])
                resolver.smash(
                    sealException(
                        userError(u"Ejector tried to escape from vat")))