def fromMonte(target, verb, args, namedArgList): namedArgs = unwrapList(namedArgList) for na in namedArgs: if not isinstance(na, NamedArg): raise InvalidAST("named args must be NamedArg nodes") return Call(target, strToString(verb), unwrapList(args), namedArgs)
def fromPairs(wrappedPairs): from typhon.objects.collections.lists import unwrapList d = monteMap() for obj in unwrapList(wrappedPairs): pair = unwrapList(obj) assert len(pair) == 2, "Not a pair!" d[pair[0]] = pair[1] return ConstMap(d)
def fromMonte(doc, verb, params, namedParams, guard, block): if doc is NullObject: d = u"" else: d = unwrapStr(doc) return Method(d, unwrapStr(verb), unwrapList(params), unwrapList(namedParams), guard if guard is not NullObject else None, block)
def fromPairs(wrappedPairs): from typhon.objects.collections.lists import unwrapList d = monteMap() for obj in unwrapList(wrappedPairs): pair = unwrapList(obj) if len(pair) != 2: raise userError(u"fromPairs/1: Not a pair") d[pair[0]] = pair[1] return ConstMap(d)
def fromMonte(extends, methods, matchers): extends = nullToNone(extends) methods = unwrapList(methods) for meth in methods: if not isinstance(meth, Method): raise InvalidAST("Script method isn't a Method") matchers = unwrapList(matchers) for matcher in matchers: if not isinstance(matcher, Matcher): raise InvalidAST("Script matcher isn't a Matcher") return Script(extends, methods, matchers)
def checkDeepFrozen(specimen, seen, ej, root): from typhon.objects.collections.lists import unwrapList from typhon.objects.collections.maps import ConstMap from typhon.objects.ejectors import throwStr from typhon.objects.equality import TraversalKey from typhon.objects.refs import Promise, isBroken key = TraversalKey(specimen) if key in seen: return seen[key] = None if isinstance(specimen, Promise): specimen = specimen.resolution() if specimen.auditedBy(deepFrozenStamp): return elif isBroken(specimen): checkDeepFrozen(specimen.optProblem(), seen, ej, root) return elif (specimen.auditedBy(selfless) and (specimen.auditedBy(transparentStamp)) or specimen.auditedBy(semitransparentStamp)): portrayal = specimen.call(u"_uncall", []) if specimen.auditedBy(semitransparentStamp): if isinstance(portrayal, SealedPortrayal): portrayal = portrayal.portrayal else: throwStr(ej, u"Semitransparent portrayal was not sealed!") portrayalList = unwrapList(portrayal, ej) if len(portrayalList) != 4: throwStr(ej, u"Transparent object gave bad portrayal") return checkDeepFrozen(portrayalList[0], seen, ej, root) checkDeepFrozen(portrayalList[1], seen, ej, root) args = unwrapList(portrayalList[2], ej) for item in args: checkDeepFrozen(item, seen, ej, root) namedArgs = portrayalList[3] if not isinstance(namedArgs, ConstMap): throwStr(ej, u"Transparent object gave bad portrayal") return for k, v in namedArgs.iteritems(): checkDeepFrozen(k, seen, ej, root) checkDeepFrozen(v, seen, ej, root) else: if specimen is root: message = root.toQuote() + u" is not DeepFrozen" else: message = (root.toQuote() + u" is not DeepFrozen because " + specimen.toQuote() + u"is not") throwStr(ej, u"audit/1: " + message)
def connectStreamCB(connect, status): status = intmask(status) stream = connect.c_handle try: vat, resolvers = ruv.unstashStream(stream) sourceResolver, sinkResolver = unwrapList(resolvers) assert isinstance(sourceResolver, LocalResolver) assert isinstance(sinkResolver, LocalResolver) with scopedVat(vat): if status >= 0: debug_print("Made connection!") wrappedStream = ruv.wrapStream(stream, 2) sourceResolver.resolve(StreamSource(wrappedStream, vat)) sinkResolver.resolve(StreamSink(wrappedStream, vat)) else: error = "Connection failed: " + ruv.formatError(status) debug_print(error) sourceResolver.smash(StrObject(error.decode("utf-8"))) sinkResolver.smash(StrObject(error.decode("utf-8"))) # Done with stream. ruv.closeAndFree(stream) except: if not we_are_translated(): raise
def connectCB(connect, status): status = intmask(status) stream = connect.c_handle try: vat, resolvers = ruv.unstashStream(stream) fountResolver, drainResolver = unwrapList(resolvers) assert isinstance(fountResolver, LocalResolver) assert isinstance(drainResolver, LocalResolver) with scopedVat(vat): if status >= 0: debug_print("Made connection!") fountResolver.resolve(StreamFount(stream, vat)) drainResolver.resolve(StreamDrain(stream, vat)) else: error = "Connection failed: " + ruv.formatError(status) debug_print(error) fountResolver.smash(StrObject(error.decode("utf-8"))) drainResolver.smash(StrObject(error.decode("utf-8"))) # Done with stream. ruv.closeAndFree(stream) except: if not we_are_translated(): raise
def makeProcess(executable, args, environment): """ Create a subordinate process on the current node from the given executable, arguments, and environment. """ # Third incarnation: libuv-powered and requiring bytes. executable = unwrapBytes(executable) # This could be an LC, but doing it this way fixes the RPython annotation # for the list to be non-None. argv = [] for arg in unwrapList(args): s = unwrapBytes(arg) assert s is not None, "proven impossible by hand" argv.append(s) env = {} for (k, v) in unwrapMap(environment).items(): env[unwrapBytes(k)] = unwrapBytes(v) packedEnv = [k + '=' + v for (k, v) in env.items()] vat = currentVat.get() try: process = ruv.allocProcess() sub = SubProcess(vat, process, argv, env) ruv.spawn(vat.uv_loop, process, file=executable, args=argv, env=packedEnv) sub.retrievePID() return sub except ruv.UVError as uve: raise userError(u"makeProcess: Couldn't spawn process: %s" % uve.repr().decode("utf-8"))
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 fromMonte(patterns, tail): patterns = unwrapList(patterns) for p in patterns: if p is None: raise InvalidAST("List subpattern cannot be None") if tail is not None: raise InvalidAST("Kernel list patterns have no tail") return ListPattern(patterns, None)
def testSplit(self): """ Strings can be split. """ s = StrObject(u"first second") result = s.call(u"split", [StrObject(u" ")]) pieces = [obj._s for obj in unwrapList(result)] self.assertEqual(pieces, [u"first", u"second"])
def listPattern(self, size): ej = self.pop() xs = unwrapList(self.pop(), ej) if len(xs) != size: throw(ej, StrObject(u"Failed list pattern (needed %d, got %d)" % (size, len(xs)))) while size: size -= 1 self.push(xs[size]) self.push(ej)
def fromMonte(doc, name, asExpr, auditors, script): if not (isinstance(name, FinalPattern) or isinstance(name, IgnorePattern)): raise InvalidAST("Kernel object pattern must be FinalPattern or IgnorePattern") if not isinstance(script, Script): raise InvalidAST("Object's script isn't a Script") doc = doc._s if isinstance(doc, Str) else None return Obj(doc, name, nullToNone(asExpr), unwrapList(auditors), script)
def checkDeepFrozen(specimen, seen, ej, root): from typhon.objects.collections.lists import unwrapList from typhon.objects.collections.maps import ConstMap from typhon.objects.ejectors import throwStr from typhon.objects.equality import TraversalKey from typhon.objects.refs import Promise, isBroken key = TraversalKey(specimen) if key in seen: return seen[key] = None if isinstance(specimen, Promise): specimen = specimen.resolution() if specimen.auditedBy(deepFrozenStamp): return elif isBroken(specimen): checkDeepFrozen(specimen.optProblem(), seen, ej, root) return elif (specimen.auditedBy(selfless) and specimen.auditedBy(transparentStamp)): portrayal = specimen.call(u"_uncall", []) portrayalList = unwrapList(portrayal, ej) if len(portrayalList) != 4: throwStr(ej, u"Transparent object gave bad portrayal") return checkDeepFrozen(portrayalList[0], seen, ej, root) checkDeepFrozen(portrayalList[1], seen, ej, root) args = unwrapList(portrayalList[2], ej) for item in args: checkDeepFrozen(item, seen, ej, root) namedArgs = portrayalList[3] if not isinstance(namedArgs, ConstMap): throwStr(ej, u"Transparent object gave bad portrayal") return for k, v in namedArgs.iteritems(): checkDeepFrozen(k, seen, ej, root) checkDeepFrozen(v, seen, ej, root) else: if specimen is root: message = root.toQuote() + u" is not DeepFrozen" else: message = (root.toQuote() + u" is not DeepFrozen because " + specimen.toQuote() + u"is not") throwStr(ej, u"audit/1: " + message)
def recv(self, atom, args): if atom is FROMSTRING_1: return BytesObject("".join( [chr(ord(c)) for c in unwrapStr(args[0])])) if atom is FROMINTS_1: data = unwrapList(args[0]) return BytesObject("".join([chr(unwrapInt(i)) for i in data])) raise Refused(self, atom, args)
def recv(self, atom, args): if atom is FROMSTRING_1: return BytesObject("".join([chr(ord(c)) for c in unwrapStr(args[0])])) if atom is FROMINTS_1: data = unwrapList(args[0]) return BytesObject("".join([chr(unwrapInt(i)) for i in data])) raise Refused(self, atom, args)
def recv(self, atom, args): if atom is RUN_1: return DoubleObject(float(unwrapStr(args[0]).encode('utf-8'))) if atom is FROMBYTES_1: data = unwrapList(args[0]) x = unpack_float("".join([chr(unwrapInt(byte)) for byte in data]), True) return DoubleObject(x) raise Refused(self, atom, args)
def listFringe(o, fringe, path, sofar): result = True for i, x in enumerate(unwrapList(o)): if fringe is None: fr = None else: fr = FringePath(i, path) result &= samenessFringe(o, fr, fringe, sofar) if (not result) and fringe is None: # Unresolved promise found. return False return result
def fromMonte(doc, name, asExpr, auditors, script): if not (isinstance(name, FinalPattern) or isinstance(name, IgnorePattern)): raise InvalidAST( "Kernel object pattern must be FinalPattern or IgnorePattern") if not isinstance(script, Script): raise InvalidAST("Object's script isn't a Script") doc = doc._s if isinstance(doc, Str) else None return Obj(doc, name, nullToNone(asExpr), unwrapList(auditors), script)
def listPattern(self, size): ej = self.pop() xs = unwrapList(self.pop(), ej) if len(xs) != size: throw( ej, StrObject(u"Failed list pattern (needed %d, got %d)" % (size, len(xs)))) while size: size -= 1 self.push(xs[size]) self.push(ej)
def recv(self, atom, args): if atom is FROMSTRING_1: # XXX handle twineishness return args[0] if atom is FROMSTRING_2: # XXX handle twineishness return args[0] if atom is FROMCHARS_1: data = unwrapList(args[0]) return StrObject(u"".join([unwrapChar(c) for c in data])) raise Refused(self, atom, args)
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 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 callWithMessage(self, target, message): """ Pass a message of `[verb :Str, args :List, namedArgs :Map]` to an object. """ if len(message) != 3: raise userError( u"callWithPair/2 requires a [verb, args, namedArgs] triple") verb = unwrapStr(message[0]) args = unwrapList(message[1]) namedArgs = resolution(message[2]) if not isinstance(namedArgs, ConstMap): raise WrongType(u"namedArgs must be a ConstMap") return target.call(verb, args, namedArgs)
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 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", []) 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 recvNamed(self, atom, args, namedArgs): if atom is RUN_3: # Fourth incarnation: Now with stdio hookups. executable = unwrapBytes(args[0]) # This could be an LC, but doing it this way fixes the RPython annotation # for the list to be non-None. argv = [] for arg in unwrapList(args[1]): s = unwrapBytes(arg) assert s is not None, "proven impossible by hand" argv.append(s) env = {} for (k, v) in unwrapMap(args[2]).items(): env[unwrapBytes(k)] = unwrapBytes(v) packedEnv = [k + '=' + v for (k, v) in env.items()] vat = currentVat.get() # Set up the list of streams. Note that, due to (not incorrect) # libuv behavior, we must wait for the subprocess to be spawned # before we can interact with the pipes that we are creating; to # do this, we'll have a list of the (f, d) pairs that we need to # start, and we'll ensure that that doesn't happen until after the # process has spawned. streams = [] fount = namedArgs.extractStringKey(u"stdinFount", None) if fount is None: streams.append(nullptr(ruv.stream_t)) else: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) drain = StreamDrain(stream, vat) vat.sendOnly(fount, FLOWTO_1, [drain], EMPTY_MAP) for name in [u"stdoutDrain", u"stderrDrain"]: drain = namedArgs.extractStringKey(name, None) if drain is None: streams.append(nullptr(ruv.stream_t)) else: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) fount = StreamFount(stream, vat) vat.sendOnly(fount, FLOWTO_1, [drain], EMPTY_MAP) try: process = ruv.allocProcess() sub = SubProcess(vat, process, argv, env) ruv.spawn(vat.uv_loop, process, file=executable, args=argv, env=packedEnv, streams=streams) sub.retrievePID() return sub except ruv.UVError as uve: raise userError(u"makeProcess: Couldn't spawn process: %s" % uve.repr().decode("utf-8")) val = self.mirandaMethods(atom, args, namedArgs) if val is None: raise Refused(self, atom, args) else: return val
def fromMonte(l): return Sequence(unwrapList(l))
def recv(self, atom, args): if atom is CALLWITHPAIR_2 or atom is CALLWITHPAIR_3: target = args[0] pair = unwrapList(args[1]) if len(pair) not in (2, 3): raise userError(u"callWithPair/2 requires a pair!") if len(pair) == 3: namedArgs = pair[2] else: namedArgs = EMPTY_MAP sendVerb = unwrapStr(pair[0]) sendArgs = unwrapList(pair[1]) rv = target.call(sendVerb, sendArgs, namedArgs) if rv is None: print "callWithPair/2: Returned None:", \ target.__class__.__name__, sendVerb.encode("utf-8") raise RuntimeError("Implementation error") return rv if atom is CALL_3 or atom is CALL_4: target = args[0] sendVerb = unwrapStr(args[1]) sendArgs = unwrapList(args[2]) if len(args) == 3: namedArgs = EMPTY_MAP else: namedArgs = args[3] rv = target.call(sendVerb, sendArgs, namedArgs) if rv is None: print "call/3: Returned None:", target.__class__.__name__, \ sendVerb.encode("utf-8") raise RuntimeError("Implementation error") return rv if atom is SENDONLY_3: target = args[0] sendVerb = unwrapStr(args[1]) sendArgs = unwrapList(args[2]) # Signed, sealed, delivered, I'm yours. sendAtom = getAtom(sendVerb, len(sendArgs)) vat = currentVat.get() vat.sendOnly(target, sendAtom, sendArgs, EMPTY_MAP) return NullObject if atom is SEND_3: target = args[0] sendVerb = unwrapStr(args[1]) sendArgs = unwrapList(args[2]) # Signed, sealed, delivered, I'm yours. sendAtom = getAtom(sendVerb, len(sendArgs)) vat = currentVat.get() return vat.send(target, sendAtom, sendArgs, EMPTY_MAP) if atom is CALLWITHMESSAGE_2: target = args[0] msg = unwrapList(args[1]) if len(msg) != 3: raise userError( u"callWithPair/2 requires a [verb, args, namedArgs] triple") sendVerb = unwrapStr(msg[0]) sendArgs = unwrapList(msg[1]) sendNamedArgs = resolution(msg[2]) if not isinstance(sendNamedArgs, ConstMap): raise WrongType(u"namedArgs must be a ConstMap") rv = target.call(sendVerb, sendArgs, sendNamedArgs) if rv is None: print "callWithPair/2: Returned None:", \ target.__class__.__name__, sendVerb.encode("utf-8") raise RuntimeError("Implementation error") return rv if atom is CALL_4: target = args[0] sendVerb = unwrapStr(args[1]) sendArgs = unwrapList(args[2]) sendNamedArgs = resolution(args[3]) if not isinstance(sendNamedArgs, ConstMap): raise WrongType(u"namedArgs must be a ConstMap") rv = target.call(sendVerb, sendArgs, sendNamedArgs) if rv is None: print "call/3: Returned None:", target.__class__.__name__, \ sendVerb.encode("utf-8") raise RuntimeError("Implementation error") return rv if atom is SENDONLY_4: target = args[0] sendVerb = unwrapStr(args[1]) sendArgs = unwrapList(args[2]) sendNamedArgs = resolution(args[3]) if not isinstance(sendNamedArgs, ConstMap): raise WrongType(u"namedArgs must be a ConstMap") # Signed, sealed, delivered, I'm yours. sendAtom = getAtom(sendVerb, len(sendArgs)) vat = currentVat.get() return vat.sendOnly(target, sendAtom, sendArgs, sendNamedArgs) if atom is SEND_4: target = args[0] sendVerb = unwrapStr(args[1]) sendArgs = unwrapList(args[2]) sendNamedArgs = resolution(args[3]) if not isinstance(sendNamedArgs, ConstMap): raise WrongType(u"namedArgs must be a ConstMap") # Signed, sealed, delivered, I'm yours. sendAtom = getAtom(sendVerb, len(sendArgs)) vat = currentVat.get() return vat.send(target, sendAtom, sendArgs, sendNamedArgs) if atom is TOQUOTE_1: return StrObject(args[0].toQuote()) if atom is TOSTRING_1: return StrObject(toString(args[0])) raise Refused(self, atom, args)
def testUnwrapListPromise(self): with scopedVat(testingVat()): p = makeNear(wrapList([])) self.assertEqual(unwrapList(p), [])
def testSlice(self): l = ConstList(map(CharObject, "abcdefg")) result = l.call(u"slice", [IntObject(3), IntObject(6)]) chars = [char._c for char in unwrapList(result)] self.assertEqual(chars, list("def"))
def recv(self, atom, args): if atom is ADD_1: other = args[0] if isinstance(other, BytesObject): return BytesObject(self._bs + other._bs) if isinstance(other, IntObject): return BytesObject(self._bs + str(chr(other._i))) if atom is ASLIST_0: from typhon.objects.collections.lists import ConstList return ConstList(self.asList()) if atom is ASSET_0: from typhon.objects.collections.sets import ConstSet return ConstSet(self.asSet()) if atom is CONTAINS_1: needle = args[0] if isinstance(needle, IntObject): return wrapBool(chr(needle._i) in self._bs) if isinstance(needle, BytesObject): return wrapBool(needle._bs in self._bs) if atom is GET_1: index = unwrapInt(args[0]) if not 0 <= index < len(self._bs): raise userError(u"string.get/1: Index out of bounds: %d" % index) return IntObject(ord(self._bs[index])) if atom is INDEXOF_1: needle = unwrapBytes(args[0]) return IntObject(self._bs.find(needle)) if atom is INDEXOF_2: needle = unwrapBytes(args[0]) offset = unwrapInt(args[1]) if offset < 0: raise userError(u"indexOf/2: Negative offset %d not supported" % offset) return IntObject(self._bs.find(needle, offset)) if atom is JOIN_1: from typhon.objects.collections.lists import unwrapList return BytesObject(self.join(unwrapList(args[0]))) if atom is LASTINDEXOF_1: needle = unwrapBytes(args[0]) return IntObject(self._bs.rfind(needle)) if atom is MULTIPLY_1: amount = args[0] if isinstance(amount, IntObject): return BytesObject(self._bs * amount._i) if atom is OP__CMP_1: return polyCmp(self._bs, unwrapBytes(args[0])) if atom is REPLACE_2: return BytesObject(replace(self._bs, unwrapBytes(args[0]), unwrapBytes(args[1]))) if atom is SIZE_0: return IntObject(len(self._bs)) if atom is SLICE_1: start = unwrapInt(args[0]) if start < 0: raise userError(u"Slice start cannot be negative") return BytesObject(self._bs[start:]) if atom is SLICE_2: start = unwrapInt(args[0]) stop = unwrapInt(args[1]) if start < 0: raise userError(u"Slice start cannot be negative") if stop < 0: raise userError(u"Slice stop cannot be negative") return BytesObject(self._bs[start:stop]) if atom is SPLIT_1: from typhon.objects.collections.lists import ConstList return ConstList(self.split(unwrapBytes(args[0]))) if atom is SPLIT_2: from typhon.objects.collections.lists import ConstList return ConstList(self.split(unwrapBytes(args[0]), unwrapInt(args[1]))) if atom is TOLOWERCASE_0: return BytesObject(self.toLowerCase()) if atom is TOUPPERCASE_0: return BytesObject(self.toUpperCase()) if atom is TRIM_0: return BytesObject(self.trim()) if atom is WITH_1: return BytesObject(self._bs + chr(unwrapInt(args[0]))) if atom is _MAKEITERATOR_0: return bytesIterator(self._bs) raise Refused(self, atom, args)
def samenessHash(obj, depth, fringe, path=None): """ Generate a hash code for an object that may not be completely settled. If two objects are the same, then they will have identical hashes. The generated hash is valid until settledness of a component changes. """ if depth <= 0: # not gonna look any further for the purposes of hash computation, but # we do have to know about unsettled refs if samenessFringe(obj, path, fringe): # obj is settled. return -1 elif fringe is None: raise userError(u"Must be settled") else: # not settled. return -1 o = resolution(obj) # The constants have their own special hash values. if o is NullObject: return 0 if o is TrueObject: return 1 if o is FalseObject: return 2 # Objects that do their own hashing. if (isinstance(o, CharObject) or isinstance(o, DoubleObject) or isinstance(o, IntObject) or isinstance(o, BigInt) or isinstance(o, StrObject) or isinstance(o, BytesObject) or isinstance(o, TraversalKey)): return o.computeHash(depth) # Lists. if isinstance(o, ConstList): oList = unwrapList(o) result = len(oList) for i, x in enumerate(oList): if fringe is None: fr = None else: fr = FringePath(i, path) result ^= i ^ samenessHash(x, depth - 1, fringe, path=fr) return result # The empty map. (Uncalls contain maps, thus this base case.) if isinstance(o, ConstMap) and o.empty(): return 127 from typhon.objects.proxy import FarRef, DisconnectedRef if isinstance(o, FarRef) or isinstance(o, DisconnectedRef): return samenessHash(o.handler, depth, fringe, path=path) # Other objects compared by structure. if selfless in o.auditorStamps(): if transparentStamp in o.auditorStamps(): return samenessHash(o.call(u"_uncall", []), depth, fringe, path=path) if semitransparentStamp in o.auditorStamps(): p = o.call(u"_uncall", []) if not isinstance(p, SealedPortrayal): userError( u'Semitransparent portrayal was not a SealedPortrayal!') return samenessHash(p.portrayal, depth, fringe, path=path) # Objects compared by identity. if isResolved(o): return compute_identity_hash(o) elif fringe is None: raise userError(u"Must be settled") # Unresolved refs. fringe.append(FringeNode(o, path)) return -1
def optSame(first, second, cache=None): """ Determine whether two objects are equal, returning None if a decision cannot be reached. This is a complex topic; expect lots of comments. """ # We need to see whether our objects are settled. If not, then give up. if not isSettled(first) or not isSettled(second): # Well, actually, there's one chance that they could be equal, if # they're the same object. But if they aren't, then we can't tell # anything else about them, so we'll call it quits. return EQUAL if first is second else NOTYET # Our objects are settled. Thus, we should be able to ask for their # resolutions. first = resolution(first) second = resolution(second) # Two identical objects are equal. if first is second: return EQUAL # Are we structurally recursive? If so, return the already-calculated # value. if cache is not None and (first, second) in cache: return cache[first, second] if cache is not None and (second, first) in cache: return cache[second, first] # Null. if first is NullObject: return eq(second is NullObject) # Bools. This should probably be covered by the identity case already, # but it's included for completeness. if isinstance(first, BoolObject): return eq( isinstance(second, BoolObject) and first.isTrue() == second.isTrue()) # Chars. if isinstance(first, CharObject): return eq(isinstance(second, CharObject) and first._c == second._c) # Doubles. if isinstance(first, DoubleObject): if isinstance(second, DoubleObject): fd = first.getDouble() sd = second.getDouble() # NaN == NaN if math.isnan(fd) and math.isnan(sd): return eq(True) else: return eq(fd == sd) return INEQUAL # Ints. if isinstance(first, IntObject): if isinstance(second, IntObject): return eq(first.getInt() == second.getInt()) if isinstance(second, BigInt): return eq(second.bi.int_eq(first.getInt())) return INEQUAL if isinstance(first, BigInt): if isinstance(second, IntObject): return eq(first.bi.int_eq(second.getInt())) if isinstance(second, BigInt): return eq(first.bi.eq(second.bi)) return INEQUAL # Strings. if isinstance(first, StrObject): return eq(isinstance(second, StrObject) and first._s == second._s) # Bytestrings. if isinstance(first, BytesObject): return eq(isinstance(second, BytesObject) and first._bs == second._bs) # Lists. if isinstance(first, ConstList): if not isinstance(second, ConstList): return INEQUAL firstList = unwrapList(first) secondList = unwrapList(second) # No point wasting time if the lists are obviously different. if len(firstList) != len(secondList): return INEQUAL # Iterate and use a cache of already-seen objects to avoid recursive # problems. if cache is None: cache = {} cache[first, second] = EQUAL return listEq(firstList, secondList, cache) if isinstance(first, TraversalKey): if not isinstance(second, TraversalKey): return INEQUAL if first.snapHash != second.snapHash: return INEQUAL # are the values the same now? if optSame(first.ref, second.ref) is not EQUAL: return INEQUAL # OK but were they the same when the traversal keys were made? return eq(fringeEq(first.fringe, second.fringe)) # Proxies do their own sameness checking. from typhon.objects.proxy import DisconnectedRef, Proxy if isinstance(first, Proxy) or isinstance(first, DisconnectedRef): return eq(first.eq(second)) if isinstance(first, ConstMap): if not isinstance(second, ConstMap): return INEQUAL if len(first.objectMap) == 0 and len(second.objectMap) == 0: return EQUAL # Fall through to uncall-based comparison. # We've eliminated all objects that can be compared on first principles, now # we need the specimens to cooperate with further investigation. # First, see if either object wants to stop with just identity comparison. if selfless in first.auditorStamps(): if selfless not in second.auditorStamps(): return INEQUAL # Then see if both objects can be compared by contents. if (transparentStamp in first.auditorStamps() and transparentStamp in second.auditorStamps()): # This could recurse. if cache is None: cache = {} cache[first, second] = INEQUAL left = first.call(u"_uncall", []) right = second.call(u"_uncall", []) # Recurse, add the new value to the cache, and return. rv = optSame(left, right, cache) cache[first, second] = rv return rv # XXX Add support for Semitransparent, comparing objects for structural # equality even if they don't publicly reveal their contents. else: return NOTYET # By default, objects are not equal. return INEQUAL
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): 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]) l = unwrapList(guardPair, ej) if len(l) == 2: return deepFrozenSupersetOf(l[0]) and deepFrozenSupersetOf(l[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 testUnwrapListPromise(self): with scopedVat(testingVat()): p = makeNear(ConstList([])) self.assertEqual(unwrapList(p), [])
def samenessHash(obj, depth, path, fringe): """ Generate a hash code for an object that may not be completely settled. Equality of hash code implies sameness of objects. The generated hash is valid until settledness of a component changes. """ if depth <= 0: # not gonna look any further for the purposes of hash computation, but # we do have to know about unsettled refs if samenessFringe(obj, path, fringe): # obj is settled. return -1 elif fringe is None: raise userError(u"Must be settled") else: # not settled. return -1 o = resolution(obj) if o is NullObject: return 0 # Objects that do their own hashing. if ( isinstance(o, BoolObject) or isinstance(o, CharObject) or isinstance(o, DoubleObject) or isinstance(o, IntObject) or isinstance(o, BigInt) or isinstance(o, StrObject) or isinstance(o, BytesObject) or isinstance(o, TraversalKey) ): return o.hash() # Lists. if isinstance(o, ConstList): oList = unwrapList(o) result = len(oList) for i, x in enumerate(oList): if fringe is None: fr = None else: fr = FringePath(i, path) result ^= i ^ samenessHash(x, depth - 1, fr, fringe) return result # The empty map. (Uncalls contain maps, thus this base case.) if isinstance(o, ConstMap) and len(o.objectMap) == 0: return 127 from typhon.objects.proxy import FarRef, DisconnectedRef if isinstance(o, FarRef) or isinstance(o, DisconnectedRef): return samenessHash(o.handler, depth, path, fringe) # Other objects compared by structure. if selfless in o.auditorStamps(): if transparentStamp in o.auditorStamps(): return samenessHash(o.call(u"_uncall", []), depth, path, fringe) # XXX Semitransparent support goes here # Objects compared by identity. if isResolved(o): return compute_identity_hash(o) elif fringe is None: raise userError(u"Must be settled") # Unresolved refs. fringe.append(FringeNode(o, path)) return -1
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 optSame(first, second, cache=None): """ Determine whether two objects are equal, returning None if a decision cannot be reached. This is a complex topic; expect lots of comments. """ # We need to see whether our objects are settled. If not, then give up. if not isSettled(first) or not isSettled(second): # Well, actually, there's one chance that they could be equal, if # they're the same object. But if they aren't, then we can't tell # anything else about them, so we'll call it quits. return EQUAL if first is second else NOTYET # Our objects are settled. Thus, we should be able to ask for their # resolutions. first = resolution(first) second = resolution(second) # Two identical objects are equal. if first is second: return EQUAL # Are we structurally recursive? If so, return the already-calculated # value. if cache is not None and (first, second) in cache: return cache[first, second] if cache is not None and (second, first) in cache: return cache[second, first] # Null. if first is NullObject: return eq(second is NullObject) # Bools. This should probably be covered by the identity case already, # but it's included for completeness. if isinstance(first, BoolObject): return eq(isinstance(second, BoolObject) and first.isTrue() == second.isTrue()) # Chars. if isinstance(first, CharObject): return eq(isinstance(second, CharObject) and first._c == second._c) # Doubles. if isinstance(first, DoubleObject): if isinstance(second, DoubleObject): fd = first.getDouble() sd = second.getDouble() # NaN == NaN if math.isnan(fd) and math.isnan(sd): return eq(True) else: return eq(fd == sd) return INEQUAL # Ints. if isinstance(first, IntObject): if isinstance(second, IntObject): return eq(first.getInt() == second.getInt()) if isinstance(second, BigInt): return eq(second.bi.int_eq(first.getInt())) return INEQUAL if isinstance(first, BigInt): if isinstance(second, IntObject): return eq(first.bi.int_eq(second.getInt())) if isinstance(second, BigInt): return eq(first.bi.eq(second.bi)) return INEQUAL # Strings. if isinstance(first, StrObject): return eq(isinstance(second, StrObject) and first._s == second._s) # Bytestrings. if isinstance(first, BytesObject): return eq(isinstance(second, BytesObject) and first._bs == second._bs) # Lists. if isinstance(first, ConstList): if not isinstance(second, ConstList): return INEQUAL firstList = unwrapList(first) secondList = unwrapList(second) # No point wasting time if the lists are obviously different. if len(firstList) != len(secondList): return INEQUAL # Iterate and use a cache of already-seen objects to avoid recursive # problems. if cache is None: cache = {} cache[first, second] = EQUAL return listEq(firstList, secondList, cache) if isinstance(first, TraversalKey): if not isinstance(second, TraversalKey): return INEQUAL if first.snapHash != second.snapHash: return INEQUAL # are the values the same now? if optSame(first.ref, second.ref) is not EQUAL: return INEQUAL # OK but were they the same when the traversal keys were made? return eq(fringeEq(first.fringe, second.fringe)) # Proxies do their own sameness checking. from typhon.objects.proxy import DisconnectedRef, Proxy if isinstance(first, Proxy) or isinstance(first, DisconnectedRef): return eq(first.eq(second)) if isinstance(first, ConstMap): if not isinstance(second, ConstMap): return INEQUAL if len(first.objectMap) == 0 and len(second.objectMap) == 0: return EQUAL # Fall through to uncall-based comparison. # We've eliminated all objects that can be compared on first principles, now # we need the specimens to cooperate with further investigation. # First, see if either object wants to stop with just identity comparison. if selfless in first.auditorStamps(): if selfless not in second.auditorStamps(): return INEQUAL # Then see if both objects can be compared by contents. if transparentStamp in first.auditorStamps() and transparentStamp in second.auditorStamps(): # This could recurse. if cache is None: cache = {} cache[first, second] = INEQUAL left = first.call(u"_uncall", []) right = second.call(u"_uncall", []) # Recurse, add the new value to the cache, and return. rv = optSame(left, right, cache) cache[first, second] = rv return rv # XXX Add support for Semitransparent, comparing objects for structural # equality even if they don't publicly reveal their contents. else: return NOTYET # By default, objects are not equal. return INEQUAL
def optSame(first, second, cache=None): """ Determine whether two objects are equal, returning None if a decision cannot be reached. This is a complex topic; expect lots of comments. """ # Two identical objects are equal. We do this twice; this first time is # done prior to checking settledness, which takes time proportional to the # size of the object graphs. if first is second: return EQUAL # We need to see whether our objects are settled. If not, then give up. if not first.isSettled() or not second.isSettled(): # Well, actually, there's one chance that they could be equal, if # they're the same object. But they aren't, because of the early # identity check above. return NOTYET # Our objects are settled. Thus, we should be able to ask for their # resolutions. first = resolution(first) second = resolution(second) # Two identical objects are equal. Again. if first is second: return EQUAL # Are we structurally recursive? If so, return the already-calculated # value. if cache is not None and (first, second) in cache: return cache[first, second] if cache is not None and (second, first) in cache: return cache[second, first] # NB: null, true, and false are all singletons, prebuilt before # translation, and as such, their identities cannot possibly vary. Code # checking for their cases used to live here, but it has been removed for # speed. ~ C. # Chars. if isinstance(first, CharObject): return eq(isinstance(second, CharObject) and first._c == second._c) # Doubles. if isinstance(first, DoubleObject): if isinstance(second, DoubleObject): fd = first.getDouble() sd = second.getDouble() # NaN == NaN if math.isnan(fd) and math.isnan(sd): return eq(True) else: return eq(fd == sd) return INEQUAL # Ints. if isinstance(first, IntObject): if isinstance(second, IntObject): return eq(first.getInt() == second.getInt()) if isinstance(second, BigInt): return eq(second.bi.int_eq(first.getInt())) return INEQUAL if isinstance(first, BigInt): if isinstance(second, IntObject): return eq(first.bi.int_eq(second.getInt())) if isinstance(second, BigInt): return eq(first.bi.eq(second.bi)) return INEQUAL # Strings. if isinstance(first, StrObject): return eq(isinstance(second, StrObject) and first._s == second._s) # Bytestrings. if isinstance(first, BytesObject): return eq(isinstance(second, BytesObject) and first._bs == second._bs) # Lists. if isinstance(first, ConstList): if not isinstance(second, ConstList): return INEQUAL firstList = unwrapList(first) secondList = unwrapList(second) # No point wasting time if the lists are obviously different. if len(firstList) != len(secondList): return INEQUAL # Iterate and use a cache of already-seen objects to avoid recursive # problems. if cache is None: cache = {} cache[first, second] = EQUAL return listEq(firstList, secondList, cache) if isinstance(first, TraversalKey): if not isinstance(second, TraversalKey): return INEQUAL if first.snapHash != second.snapHash: return INEQUAL # are the values the same now? if optSame(first.ref, second.ref) is not EQUAL: return INEQUAL # OK but were they the same when the traversal keys were made? return eq(fringeEq(first.fringe, second.fringe)) # Proxies do their own sameness checking. from typhon.objects.proxy import DisconnectedRef, Proxy if isinstance(first, Proxy) or isinstance(first, DisconnectedRef): return eq(first.eq(second)) if isinstance(first, ConstMap): if not isinstance(second, ConstMap): return INEQUAL if first.empty() and second.empty(): return EQUAL # Fall through to uncall-based comparison. # We've eliminated all objects that can be compared on first principles, now # we need the specimens to cooperate with further investigation. # First, see if either object wants to stop with just identity comparison. if selfless in first.auditorStamps(): if selfless not in second.auditorStamps(): return INEQUAL # Then see if both objects can be compared by contents. isSemitransparent = (semitransparentStamp in first.auditorStamps() and semitransparentStamp in second.auditorStamps()) if ((transparentStamp in first.auditorStamps() and transparentStamp in second.auditorStamps()) or isSemitransparent): # This could recurse. if cache is None: cache = {} cache[first, second] = INEQUAL left = first.call(u"_uncall", []) right = second.call(u"_uncall", []) if isSemitransparent: if not isinstance(left, SealedPortrayal): userError( u'Left Semitransparent uncall in sameness comparison ' u'was not a SealedPortrayal!') left = left.portrayal if not isinstance(right, SealedPortrayal): userError( u'Right Semitransparent uncall in sameness comparison ' u'was not a SealedPortrayal!') right = right.portrayal # Recurse, add the new value to the cache, and return. rv = optSame(left, right, cache) cache[first, second] = rv return rv else: return NOTYET # By default, objects are not equal. return INEQUAL
def samenessHash(obj, depth, path, fringe): """ Generate a hash code for an object that may not be completely settled. Equality of hash code implies sameness of objects. The generated hash is valid until settledness of a component changes. """ if depth <= 0: # not gonna look any further for the purposes of hash computation, but # we do have to know about unsettled refs if samenessFringe(obj, path, fringe): # obj is settled. return -1 elif fringe is None: raise userError(u"Must be settled") else: # not settled. return -1 o = resolution(obj) if o is NullObject: return 0 # Objects that do their own hashing. if (isinstance(o, BoolObject) or isinstance(o, CharObject) or isinstance(o, DoubleObject) or isinstance(o, IntObject) or isinstance(o, BigInt) or isinstance(o, StrObject) or isinstance(o, BytesObject) or isinstance(o, TraversalKey)): return o.hash() # Lists. if isinstance(o, ConstList): oList = unwrapList(o) result = len(oList) for i, x in enumerate(oList): if fringe is None: fr = None else: fr = FringePath(i, path) result ^= i ^ samenessHash(x, depth - 1, fr, fringe) return result # The empty map. (Uncalls contain maps, thus this base case.) if isinstance(o, ConstMap) and len(o.objectMap) == 0: return 127 from typhon.objects.proxy import FarRef, DisconnectedRef if isinstance(o, FarRef) or isinstance(o, DisconnectedRef): return samenessHash(o.handler, depth, path, fringe) # Other objects compared by structure. if selfless in o.auditorStamps(): if transparentStamp in o.auditorStamps(): return samenessHash(o.call(u"_uncall", []), depth, path, fringe) # XXX Semitransparent support goes here # Objects compared by identity. if isResolved(o): return compute_identity_hash(o) elif fringe is None: raise userError(u"Must be settled") # Unresolved refs. fringe.append(FringeNode(o, path)) return -1