def isDeepFrozen(obj): with Ejector() as ej: try: deepFrozenGuard.coerce(obj, ej) return True except Ejecting as ex: if ex.ejector is not ej: raise return False
def coerce(self, specimen, ej): for g in self.subguards: with Ejector() as cont: try: return g.call(u"coerce", [specimen, cont]) except Ejecting as e: if e.ejector is cont: continue throwStr(ej, u"No subguards matched")
def loop(iterable, consumer): """ Perform an iterative loop. """ # If the consumer is *not* a ScriptObject, then damn them to the slow # path. In order for the consumer to not be ScriptObject, though, the # compiler and optimizer must have decided that an object could be # directly passed to _loop(), which is currently impossible to do without # manual effort. It's really not a common pathway at all. if not isinstance(consumer, ScriptObject): return slowLoop(iterable, consumer) # Rarer path: If the consumer doesn't actually have RUN_2, then they're # not going to be JIT'd. Again, the compiler and optimizer won't ever do # this to us; it has to be intentional. code = consumer.codeScript.strategy.lookupMethod(RUN_2) if code is None: return slowLoop(iterable, consumer) iterator = iterable.call(u"_makeIterator", []) ej = Ejector() try: while True: # JIT merge point. loopDriver.jit_merge_point(code=code, consumer=consumer, ejector=ej, iterator=iterator) globals = promote(consumer.globals) if isinstance(consumer, BusyObject): machine = SmallCaps(code, consumer.closure, globals) else: machine = SmallCaps(code, None, globals) values = unwrapList(iterator.call(u"next", [ej])) # Push the arguments onto the stack, backwards. values.reverse() for arg in values: machine.push(arg) machine.push(NullObject) machine.push(EMPTY_MAP) machine.run() except Ejecting as e: if e.ejector is not ej: raise finally: ej.disable() return NullObject
def listFromIterable(obj): rv = [] iterator = obj.call(u"_makeIterator", []) ej = Ejector() while True: try: l = unwrapList(iterator.call(u"next", [ej])) if len(l) != 2: raise userError(u"makeList.fromIterable/1: Invalid iterator") rv.append(l[1]) except Ejecting as ex: if ex.ejector is ej: ej.disable() return rv raise
def slowLoop(iterable, consumer): iterator = iterable.call(u"_makeIterator", []) with Ejector() as ej: while True: try: values = iterator.call(u"next", [ej]) consumer.call(u"run", unwrapList(values)) except Ejecting as e: if e.ejector is ej: break else: raise return NullObject
def runMatchers(self, atom, args, namedArgs): message = ConstList([StrObject(atom.verb), ConstList(args), namedArgs]) for matcher in self.codeScript.strategy.getMatchers(): with Ejector() as ej: try: return self.runMatcher(matcher, message, ej) except Ejecting as e: if e.ejector is ej: # Looks like unification failed. On to the next # matcher! continue else: # It's not ours, cap'n. raise raise Refused(self, atom, args)
def testMakeIterator(self): """ Strings are iterable. """ s = StrObject(u"cs") iterator = s.call(u"_makeIterator", []) with Ejector() as ej: result = iterator.call(u"next", [ej]) objs = unwrapList(result) self.assertEqual(objs[0].getInt(), 0) self.assertEqual(objs[1]._c, u'c') result = iterator.call(u"next", [ej]) objs = unwrapList(result) self.assertEqual(objs[0].getInt(), 1) self.assertEqual(objs[1]._c, u's') self.assertRaises(Ejecting, iterator.call, u"next", [ej])
def loop(iterable, consumer): """ Perform an iterative loop. """ # If the consumer is *not* an InterpObject, then damn them to the slow # path. In order for the consumer to not be InterpObject, though, the # compiler and optimizer must have decided that an object could be # directly passed to _loop(), which is currently impossible to do without # manual effort. It's really not a common pathway at all. if not isinstance(consumer, InterpObject): return slowLoop(iterable, consumer) displayName = consumer.getDisplayName().encode("utf-8") # Rarer path: If the consumer doesn't actually have a method for run/2, # then they're not going to be JIT'd. Again, the compiler and optimizer # won't ever do this to us; it has to be intentional. method = consumer.getMethod(RUN_2) if method is None: return slowLoop(iterable, consumer) iterator = iterable.call(u"_makeIterator", []) # XXX We want to use a with-statement here, but we cannot because of # something weird about the merge point. ej = Ejector() try: while True: # JIT merge point. loopDriver.jit_merge_point(method=method, displayName=displayName, consumer=consumer, ejector=ej, iterator=iterator) values = unwrapList(iterator.call(u"next", [ej])) consumer.runMethod(method, values, EMPTY_MAP) except Ejecting as e: if e.ejector is not ej: raise finally: ej.disable() return NullObject
def recv(self, atom, args): if atom is COERCE_2: for g in self.subguards: with Ejector() as ej: try: return g.call(u"coerce", [args[0], ej]) except Ejecting as e: if e.ejector is ej: continue throw(args[1], StrObject(u"No subguards matched")) if atom is SUPERSETOF_1: for g in self.subguards: if not unwrapBool(g.call(u"supersetOf", [args[0]])): return wrapBool(False) return wrapBool(True) if atom is _UNCALL_0: from typhon.objects.collections.maps import EMPTY_MAP return ConstList([ anyGuard, StrObject(u"get"), ConstList(self.subguards), EMPTY_MAP ]) raise Refused(self, atom, args)
def runInstruction(self, instruction, pc): index = self.code.index(pc) # jit_debug(self.code.disAt(pc)) if instruction.asInt == ops.DUP.asInt: self.push(self.peek()) return pc + 1 elif instruction.asInt == ops.ROT.asInt: z = self.pop() y = self.pop() x = self.pop() self.push(y) self.push(z) self.push(x) return pc + 1 elif instruction.asInt == ops.POP.asInt: self.pop() return pc + 1 elif instruction.asInt == ops.SWAP.asInt: y = self.pop() x = self.pop() self.push(y) self.push(x) return pc + 1 elif instruction.asInt == ops.ASSIGN_GLOBAL.asInt: value = self.pop() self.env.putValueGlobal(index, value) return pc + 1 elif instruction.asInt == ops.ASSIGN_FRAME.asInt: value = self.pop() self.env.putValueFrame(index, value) return pc + 1 elif instruction.asInt == ops.ASSIGN_LOCAL.asInt: value = self.pop() self.env.putValueLocal(index, value) return pc + 1 elif instruction.asInt == ops.BIND.asInt: binding = self.pop() self.env.createBindingLocal(index, binding) return pc + 1 elif instruction.asInt == ops.BINDFINALSLOT.asInt: guard = self.pop() ej = self.pop() specimen = self.pop() val = guard.call(u"coerce", [specimen, ej]) self.env.createBindingLocal(index, finalBinding(val, guard)) return pc + 1 elif instruction.asInt == ops.BINDVARSLOT.asInt: guard = self.pop() ej = self.pop() specimen = self.pop() val = guard.call(u"coerce", [specimen, ej]) self.env.createBindingLocal(index, varBinding(val, guard)) return pc + 1 elif instruction.asInt == ops.SLOT_GLOBAL.asInt: self.push(self.env.getSlotGlobal(index)) return pc + 1 elif instruction.asInt == ops.SLOT_FRAME.asInt: self.push(self.env.getSlotFrame(index)) return pc + 1 elif instruction.asInt == ops.SLOT_LOCAL.asInt: self.push(self.env.getSlotLocal(index)) return pc + 1 elif instruction.asInt == ops.NOUN_GLOBAL.asInt: self.push(self.env.getValueGlobal(index)) return pc + 1 elif instruction.asInt == ops.NOUN_FRAME.asInt: self.push(self.env.getValueFrame(index)) return pc + 1 elif instruction.asInt == ops.NOUN_LOCAL.asInt: self.push(self.env.getValueLocal(index)) return pc + 1 elif instruction.asInt == ops.BINDING_GLOBAL.asInt: self.push(self.env.getBindingGlobal(index)) return pc + 1 elif instruction.asInt == ops.BINDING_FRAME.asInt: self.push(self.env.getBindingFrame(index)) return pc + 1 elif instruction.asInt == ops.BINDING_LOCAL.asInt: self.push(self.env.getBindingLocal(index)) return pc + 1 elif instruction.asInt == ops.LIST_PATT.asInt: self.listPattern(index) return pc + 1 elif instruction.asInt == ops.LITERAL.asInt: self.push(self.code.literal(index)) return pc + 1 elif instruction.asInt == ops.BINDOBJECT.asInt: self.bindObject(index) return pc + 1 elif instruction.asInt == ops.EJECTOR.asInt: # Look carefully at the order of operations. The handler captures # the depth of the stack, so it's important to create it *before* # pushing the ejector onto the stack. Otherwise, the handler # thinks that the stack started off with an extra level of depth. ej = Ejector() handler = Eject(self, ej, index) self.push(ej) self.env.pushHandler(handler) return pc + 1 elif instruction.asInt == ops.TRY.asInt: self.env.pushHandler(Catch(self, index)) return pc + 1 elif instruction.asInt == ops.UNWIND.asInt: self.env.pushHandler(Unwind(self, index)) return pc + 1 elif instruction.asInt == ops.END_HANDLER.asInt: handler = self.env.popHandler() return handler.drop(self, pc, index) elif instruction.asInt == ops.BRANCH.asInt: cond = unwrapBool(self.pop()) if cond: return pc + 1 else: return index elif instruction.asInt == ops.CALL.asInt: self.call(index, withMap=False) return pc + 1 elif instruction.asInt == ops.CALL_MAP.asInt: self.call(index, withMap=True) return pc + 1 elif instruction.asInt == ops.BUILD_MAP.asInt: self.buildMap(index) return pc + 1 elif instruction.asInt == ops.NAMEDARG_EXTRACT.asInt: k = self.pop() d = unwrapMap(self.pop()) if k not in d: raise userError(u"Named arg %s missing in call" % (k.toString(), )) self.push(d[k]) return pc + 1 elif instruction.asInt == ops.NAMEDARG_EXTRACT_OPTIONAL.asInt: k = self.pop() d = unwrapMap(self.pop()) if k not in d: self.push(NullObject) return pc + 1 self.push(d[k]) return index elif instruction.asInt == ops.JUMP.asInt: return index else: raise RuntimeError("Unknown instruction %s" % instruction.repr.encode("utf-8"))
def deepFrozenSupersetOf(guard): from typhon.objects.collections.helpers import monteMap from typhon.objects.collections.lists import unwrapList from typhon.objects.constants import wrapBool from typhon.objects.ejectors import Ejector from typhon.objects.refs import Promise from typhon.objects.guards import (AnyOfGuard, BoolGuard, BytesGuard, CharGuard, DoubleGuard, FinalSlotGuard, IntGuard, SameGuard, StrGuard, SubrangeGuard, VoidGuard) from typhon.prelude import getGlobalValue if guard is deepFrozenGuard: return True if guard is deepFrozenStamp: return True if isinstance(guard, Promise): guard = guard.resolution() if isinstance(guard, BoolGuard): return True if isinstance(guard, BytesGuard): return True if isinstance(guard, CharGuard): return True if isinstance(guard, DoubleGuard): return True if isinstance(guard, IntGuard): return True if isinstance(guard, StrGuard): return True if isinstance(guard, VoidGuard): return True if isinstance(guard, SameGuard): with Ejector() as ej: try: v = guard.value checkDeepFrozen(v, monteMap(), ej, v) return True except Ejecting: return False if isinstance(guard, FinalSlotGuard): return deepFrozenSupersetOf(guard.valueGuard) for superGuardName in [u"List", u"NullOk", u"Set"]: superGuard = getGlobalValue(superGuardName) if superGuard is None: continue with Ejector() as ej: try: subGuard = superGuard.call(u"extractGuard", [guard, ej]) return deepFrozenSupersetOf(subGuard) except Ejecting as e: # Just keep going. if e.ejector is not ej: raise for pairGuardName in [u"Map", u"Pair"]: pairGuard = getGlobalValue(pairGuardName) if pairGuard is None: continue with Ejector() as ej: try: guardPair = pairGuard.call(u"extractGuards", [guard, ej]) l = unwrapList(guardPair, ej) if len(l) == 2: return deepFrozenSupersetOf(l[0]) and deepFrozenSupersetOf( l[1]) except Ejecting as e: if e.ejector is not ej: raise if (SubrangeGuard(deepFrozenGuard).call(u"passes", [guard]) is wrapBool(True)): return True if isinstance(guard, AnyOfGuard): for g in guard.subguards: if not deepFrozenSupersetOf(g): return False return True return False
def deepFrozenSupersetOf(guard): from typhon.objects.collections.helpers import monteMap from typhon.objects.collections.lists import ConstList from typhon.objects.constants import wrapBool from typhon.objects.ejectors import Ejector from typhon.objects.refs import Promise from typhon.objects.guards import ( AnyOfGuard, BoolGuard, BytesGuard, CharGuard, DoubleGuard, FinalSlotGuard, IntGuard, SameGuard, StrGuard, SubrangeGuard, VoidGuard) from typhon.prelude import getGlobalValue if guard is deepFrozenGuard: return True if guard is deepFrozenStamp: return True if isinstance(guard, Promise): guard = guard.resolution() if isinstance(guard, BoolGuard): return True if isinstance(guard, BytesGuard): return True if isinstance(guard, CharGuard): return True if isinstance(guard, DoubleGuard): return True if isinstance(guard, IntGuard): return True if isinstance(guard, StrGuard): return True if isinstance(guard, VoidGuard): return True if isinstance(guard, SameGuard): ej = Ejector() try: v = guard.value checkDeepFrozen(v, monteMap(), ej, v) return True except Ejecting: return False if isinstance(guard, FinalSlotGuard): return deepFrozenSupersetOf(guard.valueGuard) for superGuardName in [u"List", u"NullOk", u"Set"]: superGuard = getGlobalValue(superGuardName) if superGuard is None: continue ej = Ejector() try: subGuard = superGuard.call(u"extractGuard", [guard, ej]) return deepFrozenSupersetOf(subGuard) except Ejecting: # XXX lets other ejectors get through pass for pairGuardName in [u"Map", u"Pair"]: pairGuard = getGlobalValue(pairGuardName) if pairGuard is None: continue ej = Ejector() try: guardPair = pairGuard.call(u"extractGuards", [guard, ej]) if isinstance(guardPair, ConstList) and guardPair.size() == 2: return ( (deepFrozenSupersetOf(guardPair.strategy.fetch( guardPair, 0))) and (deepFrozenSupersetOf(guardPair.strategy.fetch( guardPair, 1)))) except Ejecting: # XXX lets other ejectors get through pass if (SubrangeGuard(deepFrozenGuard).call(u"passes", [guard]) is wrapBool(True)): return True if isinstance(guard, AnyOfGuard): for g in guard.subguards: if not deepFrozenSupersetOf(g): return False return True return False
def testDisable(self): ej = Ejector() ej.disable() self.assertFalse(ej.active)