def setitem(self, index, value): if not isinstance(index, Integer): raise space.unwind(space.LTypeError(u"index not an integer")) if not 0 <= index.value < len(self.contents): raise space.unwind(space.LKeyError(self, index)) self.contents[index.value] = value return value
def parse_float_(string): value = 0.0 inv_scale = 1 divider = 1 exponent = 0.0 exponent_sign = +1.0 mode = 0 for ch in string.string: if mode == 0: if u'0' <= ch and ch <= u'9': digit = ord(ch) - ord(u'0') value = value * 10.0 + digit inv_scale *= divider elif u'.' == ch: divider = 10 elif u'e' == ch or u'E' == ch: mode = 1 else: raise space.unwind(space.LError(u"invalid digit char: " + ch)) elif mode == 1: mode = 2 if u'+' == ch: exponent_sign = +1.0 continue if u'-' == ch: exponent_sign = -1.0 continue else: # mode == 2 if u'0' <= ch and ch <= u'9': digit = ord(ch) - ord(u'0') exponent = exponent * 10.0 + digit else: raise space.unwind(space.LError(u"invalid digit char: " + ch)) exponent = exponent_sign * exponent return (value / inv_scale) * math.pow(10.0, exponent)
def Integer_to_string(integer, base): base = 10 if base is None else base.value if base >= len(digits): raise space.unwind(space.LError(u"not enough digits to represent this base %d" % base)) if base < 0: raise space.unwind(space.LError(u"negative base not supported")) return space.String(integer_to_string(integer.value, base))
def call(self, argv): if self.instantiate is None: if self.name == u'null': raise space.unwind(space.LTypeError(u"cannot call null")) raise space.unwind( space.LTypeError(u"cannot instantiate " + self.name)) return self.instantiate(self, argv)
def to_error(result): for errno, Exc in errors: if errno == rffi.r_long(result): return space.unwind(Exc()) else: return space.unwind( space.LUVError( rffi.charp2str(uv.err_name(result)).decode('utf-8'), rffi.charp2str(uv.strerror(result)).decode('utf-8')))
def call(self, argv): if len(argv) != 1: raise space.unwind(space.LCallError(1, 1, False, len(argv))) module = argv[0] if not isinstance(module, space.Module): raise space.unwind( space.LError(u"Argument to program must be a module")) entry = self.unit.functions[0] frame = Frame(entry, module, None, entry.regc) #regv = new_register_array(entry.regc) return interpret(0, entry.block, frame)
def cast(x, cls, info=u"something"): if isinstance(x, cls): # This here means that cast won't change object return x # if it is already correct type. try: fn = cast_methods[cls] except KeyError as _: raise space.unwind(space.LTypeError(u"expected %s is %s, got %s" % ( info, cls.interface.name, x.repr()))) res = fn(x) if isinstance(res, cls): return res # TODO: Consider alternative ways to say it. :) raise space.unwind(space.LTypeError(u"implicit conversion of %s at %s into %s returned %s" % ( x.repr(), info, cls.interface.name, res.repr())))
def setitem(self, index, value): # TODO: Add slice support to this side. index = space.cast(index, Integer, u"index not an integer") if not 0 <= index.value < len(self.contents): raise space.unwind(space.LKeyError(self, index)) self.contents[index.value] = value return value
def parse_int_(string, base): base = 10 if base is None else base.value value = 0 for ch in string.string: if u'0' <= ch and ch <= u'9': digit = ord(ch) - ord('0') elif u'a' <= ch and ch <= u'z': digit = ord(ch) - ord('a') + 10 elif u'A' <= ch and ch <= u'Z': digit = ord(ch) - ord('A') + 10 else: raise space.unwind(space.LError(u"invalid digit char: " + ch)) if digit >= base: raise space.unwind(space.LError(u"invalid digit char: " + ch)) value = value * base + digit return value
def setitem(self, index, value): index = space.cast(index, numbers.Integer, u"index not an integer") if not 0 <= index.value < self.length: raise space.unwind(space.LKeyError(self, index)) value = space.cast(value, numbers.Integer, u"value not an integer") self.uint8data[index.value] = rffi.r_uchar(value.value) return value
def from_object(obj): if as_i(obj.getitem(space.String(u"version"))) != 0: raise space.unwind(space.LError(u"bytecode version=0 required")) sources = as_list(obj.getitem(space.String(u"sources"))) constants = as_list(obj.getitem(space.String(u"constants"))) functions = [] for function_list in as_list(obj.getitem(space.String(u"functions"))): flags = as_i( function_list.getitem(space.String(u"flags"))) regc = as_i( function_list.getitem(space.String(u"regc"))) argc = rffi.r_ulong(as_i( function_list.getitem(space.String(u"argc")))) topc = rffi.r_ulong(as_i( function_list.getitem(space.String(u"topc")))) localc = as_i( function_list.getitem(space.String(u"localc"))) block_list = as_u8a(function_list.getitem(space.String(u"code"))) sourcemap = function_list.getitem(space.String(u"sourcemap")) exc_table = as_list(function_list.getitem(space.String(u"exceptions"))) block = lltype.malloc(u16_array, block_list.length/2) for i in range(block_list.length/2): a = rffi.r_long(block_list.uint8data[i*2+0]) b = rffi.r_long(block_list.uint8data[i*2+1]) block[i] = rffi.r_ushort((a << 8) | b) excs = [] for n in exc_table: excs.append(Exc( rffi.r_ulong(as_i(n.getitem(space.Integer(0)))), rffi.r_ulong(as_i(n.getitem(space.Integer(1)))), rffi.r_ulong(as_i(n.getitem(space.Integer(2)))), rffi.r_ulong(as_i(n.getitem(space.Integer(3)))), )) functions.append(Function(flags, regc, argc, topc, localc, block, sourcemap, excs[:])) return Program(Unit(constants[:], functions[:], sources[:]))
def Uint8Data_memcpy(self, src, size): size = src.length if size is None else size.value if size > self.length or size > src.length: raise space.unwind(space.LError(u"memcpy range error")) rffi.c_memcpy(rffi.cast(rffi.VOIDP, self.uint8data), rffi.cast(rffi.VOIDP, src.uint8data), size) return space.null
def call(self, argv): varargs = self.function.flags & 1 == 1 argc = self.function.argc topc = self.function.topc L = len(argv) if L < argc: # The pc=0 refers to the function itself. This entry # is really helpful when trying to determine the origin of a CallError. head_entry = TraceEntry(rffi.r_long(0), self.function.unit.sources, self.function.sourcemap, self.function.unit.path) unwinder = space.unwind(space.LCallError(argc, topc, varargs, L)) unwinder.traceback.contents.append(head_entry) raise unwinder # We are using this trait. #if L > topc and not varargs: # raise space.Error(u"too many arguments [%d], from %d to %d arguments allowed" % (L, argc, topc)) frame = Frame(self.function, self.frame.module, self.frame) for i in range(min(topc, L)): frame.local[i] = argv[i] if varargs: frame.local[topc] = space.List(argv[min(topc, L):]) regv = new_register_array(self.function.regc) if self.function.flags & 2 != 0: return Generator(0, self.function.block, regv, frame) else: return interpret(0, self.function.block, regv, frame)
def from_object(obj): if as_i(obj.getitem(space.String(u"version"))) != 0: raise space.unwind(space.LError(u"bytecode version=0 required")) sources = as_list(obj.getitem(space.String(u"sources"))) constants = as_list(obj.getitem(space.String(u"constants"))) functions = [] for function_list in as_list(obj.getitem(space.String(u"functions"))): flags = as_i(function_list.getitem(space.String(u"flags"))) regc = as_i(function_list.getitem(space.String(u"regc"))) argc = rffi.r_ulong(as_i(function_list.getitem(space.String(u"argc")))) topc = rffi.r_ulong(as_i(function_list.getitem(space.String(u"topc")))) localc = as_i(function_list.getitem(space.String(u"localc"))) block_list = as_u8a(function_list.getitem(space.String(u"code"))) sourcemap = function_list.getitem(space.String(u"sourcemap")) exc_table = as_list(function_list.getitem(space.String(u"exceptions"))) block = lltype.malloc(u16_array, block_list.length / 2) for i in range(block_list.length / 2): a = rffi.r_long(block_list.uint8data[i * 2 + 0]) b = rffi.r_long(block_list.uint8data[i * 2 + 1]) block[i] = rffi.r_ushort((a << 8) | b) excs = [] for n in exc_table: excs.append( Exc( rffi.r_ulong(as_i(n.getitem(space.Integer(0)))), rffi.r_ulong(as_i(n.getitem(space.Integer(1)))), rffi.r_ulong(as_i(n.getitem(space.Integer(2)))), rffi.r_ulong(as_i(n.getitem(space.Integer(3)))), )) functions.append( Function(flags, regc, argc, topc, localc, block, sourcemap, excs[:])) return Program(Unit(constants[:], functions[:], sources[:]))
def load(self, offset, copy): for rtype in floating_types: if self.size == rffi.sizeof(rtype): return Float( rffi.cast(rffi.DOUBLE, rffi.cast(rffi.CArrayPtr(rtype), offset)[0])) else: raise unwind(LTypeError(u"undefined ffi type: %s" % self.repr()))
def List_pop(self, index): if index: index = index.value else: index = len(self.contents) - 1 if not 0 <= index < len(self.contents): raise space.unwind(space.LKeyError(self, space.Integer(index))) return self.contents.pop(index)
def load(self, offset, copy): for rtype in signed_types: if self.size == rffi.sizeof(rtype): return Integer( rffi.cast(rffi.LONG, rffi.cast(rffi.CArrayPtr(rtype), offset)[0])) else: raise unwind(LTypeError(u"undefined ffi type: %s" % self.repr()))
def sizeof_a(tp, n): assert isinstance(tp, Type) if tp.size == 0 or tp.align == 0: raise unwind(LTypeError(u"cannot determine size of opaque type")) if tp.parameter is not None: return tp.size + sizeof(tp.parameter)*n else: return tp.size * n
def cast(x, cls, info=u"something"): if isinstance(x, cls): # This here means that cast won't change object return x # if it is already correct type. try: fn = cast_methods[cls] except KeyError as _: raise space.unwind( space.LTypeError(u"expected %s is %s, got %s" % (info, cls.interface.name, x.repr()))) res = fn(x) if isinstance(res, cls): return res # TODO: Consider alternative ways to say it. :) raise space.unwind( space.LTypeError( u"implicit conversion of %s at %s into %s returned %s" % (x.repr(), info, cls.interface.name, res.repr())))
def utf8_decoder_operate(decoder, newdata, final): data = decoder.buffer + newdata try: string, pos = str_decode_utf_8(data, len(data), '', final=final) except UnicodeDecodeError as error: raise space.unwind(space.LError(u"unicode decode failed")) decoder.buffer = data[pos:] return string
def sizeof_a(tp, n): assert isinstance(tp, Type) if tp.size == 0 or tp.align == 0: raise unwind(LTypeError(u"cannot determine size of opaque type")) if tp.parameter is not None: return tp.size + sizeof(tp.parameter) * n else: return tp.size * n
def call(self, argv): if len(argv) != 1: raise space.unwind(space.LCallError(1, 1, False, len(argv))) module = argv[0] assert isinstance(module, space.Module) entry = self.unit.functions[0] frame = Frame(entry, module, None) regv = new_register_array(entry.regc) return interpret(0, entry.block, regv, frame)
def setattr(self, name, value): if self.frozen: raise space.unwind(space.LFrozenError(self)) try: cell = jit.promote(self.lookup(name, True)) cell.setval(value) except KeyError: self.cells[name] = MutableCell(value) return value
def store(self, pool, offset, value): for rtype in signed_types: if self.size == rffi.sizeof(rtype): pnt = rffi.cast(rffi.CArrayPtr(rtype), offset) pnt[0] = rffi.cast(rtype, to_int(value)) break else: raise unwind(LTypeError(u"undefined ffi type: %s" % self.repr())) return value
def String_count(self, ch): if len(ch.string) != 1: raise space.unwind(space.LError(u"str.count expected char")) count = 0 x = ch.string[0] for ch in self.string: if ch == x: count += 1 return Integer(count)
def max_default(argv): if len(argv) == 2 and argv[1] is null: return argv[0] if len(argv) == 2 and argv[0] is null: return argv[1] args = coerce.call(argv) if not isinstance(args, List): raise space.unwind(space.LError(u"coerce should return list")) return max_.call_suppressed(args.contents)
def store(self, pool, offset, value): number = to_float(value) for rtype in floating_types: if self.size == rffi.sizeof(rtype): pnt = rffi.cast(rffi.CArrayPtr(rtype), offset) pnt[0] = rffi.cast(rtype, number) break else: raise unwind(LTypeError(u"undefined ffi type: %s" % self.repr())) return value
def utf8_decoder_operate(decoder, newdata, final): data = decoder.buffer + newdata try: string, pos = str_decode_utf_8(data, len(data), '', final=final) except UnicodeDecodeError as error: raise space.unwind(space.LError(u"unicode decode failed")) assert 0 <= pos <= len(data) # Added to satisfy PyPy 5.7 # The implementation of str_decode_utf_8 perhaps changed? decoder.buffer = data[pos:] return string
def getitem(self, index): index = space.cast(index, space.List, u"Multimethod.getitem") try: vec = [cls.interface.weakref for cls in index.contents] item = self.multimethod_table[vec]() if item is not None: return item except KeyError as _: pass raise space.unwind(space.LKeyError(self, index))
def String_is_digit(string, base): base = 10 if base is None else base.value if not 0 <= base <= 36: raise space.unwind(space.LError(u"is_digit base not in range .:36")) for ch in string.string: if not 0 <= as_alphadigit_i(ord(ch)) < base: return space.false if len(string.string) == 0: return space.false return space.true
def getitem(self, index): if isinstance(index, space.Slice): start, stop, step = index.clamped(0, len(self.contents)) result = [] for i in range(start, stop, step): result.append(self.contents[i]) return List(result) index = space.cast(index, Integer, u"index not an integer") if not 0 <= index.value < len(self.contents): raise space.unwind(space.LKeyError(self, index)) return self.contents[index.value]
def getitem(self, index): if isinstance(index, space.Slice): start, stop, step = index.clamped(0, len(self.contents) - 1) result = [] for i in range(start, stop, step): result.append(self.contents[i]) return List(result) index = space.cast(index, Integer, u"index not an integer") if not 0 <= index.value < len(self.contents): raise space.unwind(space.LKeyError(self, index)) return self.contents[index.value]
def getitem(self, index): if isinstance(index, space.Slice): result = [] start, stop, step = index.clamped(0, len(self.string)-1) for i in range(start, stop, step): result.append(self.string[i]) return String(u"".join(result)) index = space.cast(index, Integer, u"index not an integer") if not 0 <= index.value < len(self.string): raise space.unwind(space.LKeyError(self, index)) return String(self.string[index.value])
def getitem(self, index): if isinstance(index, space.Slice): result = [] start, stop, step = index.clamped(0, len(self.string)) for i in range(start, stop, step): result.append(self.string[i]) return String(u"".join(result)) index = space.cast(index, numbers.Integer, u"index not an integer") if not 0 <= index.value < len(self.string): raise space.unwind(space.LKeyError(self, index)) return String(self.string[index.value])
def to_float(obj): if isinstance(obj, Float): return obj.number elif isinstance(obj, Integer): return float(obj.value) elif isinstance(obj, Boolean): if is_true(obj): return 1.0 else: return 0.0 else: raise space.unwind(space.LTypeError(u"expected float value"))
def to_int(obj): if isinstance(obj, Float): return int(obj.number) elif isinstance(obj, Integer): return obj.value elif isinstance(obj, Boolean): if is_true(obj): return 1 else: return 0 else: raise space.unwind(space.LTypeError(u"expected int value"))
def setattr_force(self, name, value): try: cell = jit.promote(self.lookup(name, assign=True)) if isinstance(cell, FrozenCell): raise space.unwind(space.LFrozenError(self)) elif isinstance(cell, MutableCell): cell.slot = value else: assert False except KeyError: if self.frozen: self.cells[name] = FrozenCell(value) else: self.cells[name] = MutableCell(value) return value
def call(self, argv): varargs = self.function.flags & 1 == 1 argc = self.function.argc topc = self.function.topc L = len(argv) if L < argc: raise space.unwind(space.LCallError(argc, topc, varargs, L)) # We are using this trait. #if L > topc and not varargs: # raise space.Error(u"too many arguments [%d], from %d to %d arguments allowed" % (L, argc, topc)) frame = Frame(self.function, self.frame.module, self.frame) for i in range(min(topc, L)): frame.local[i] = argv[i] if varargs: frame.local[topc] = space.List(argv[min(topc, L):]) regv = new_register_array(self.function.regc) return interpret(0, self.function.block, regv, frame)
def fancy_frame(argv): args = () L = len(argv) if L < argc or (L > topc and not variadic): raise space.unwind(space.LCallError(argc, topc, variadic, L)) for i in argi: arg = argv[i] if isinstance(arg, argtypes[i]): args += (arg,) else: args += (space.cast(arg, argtypes[i], u"arg:%d"%i),) for j in argj: if j < L: arg = argv[j] if arg is null: arg = None elif not isinstance(arg, argtypes[j]): arg = space.cast(arg, argtypes[j], u"arg:%d"%j) else: arg = None args += (arg,) if variadic: args += (argv[min(topc, L):],) return func(*args)
def fancy_frame(argv): args = () L = len(argv) if L < argc or (L > topc and not variadic): raise space.unwind(space.LCallError(argc, topc, variadic, L)) for i in argi: arg = argv[i] if isinstance(arg, argtypes[i]): args += (arg,) else: raise expectations_error(i, argtypes[i].interface.name) for j in argj: if j < L: arg = argv[j] if arg is null: arg = None elif not isinstance(arg, argtypes[j]): raise expectations_error(j, argtypes[j].interface.name) else: arg = None args += (arg,) if variadic: args += (argv[min(topc, L):],) return func(*args)
def expectations_error(index, name): raise space.unwind(space.LTypeError(u"expected arg:%d is %s" % (index, name)))
def List_remove(self, obj): for index, item in enumerate(self.contents): if item.eq(obj): self.contents.pop(index) return space.null raise space.unwind(space.LValueError(self, obj))
def List_index(self, obj): for index, item in enumerate(self.contents): if item.eq(obj): return Integer(index) raise space.unwind(space.LValueError(self, obj))
def List_insert(self, index, obj): val = index.value if not 0 <= val <= len(self.contents): raise space.unwind(space.LKeyError(self, index)) self.contents.insert(val, obj) return space.null
def getitem(self, index): try: return self.data[index] except KeyError as _: raise space.unwind(space.LKeyError(self, index))
def Dict_pop(self, key): try: return self.data.pop(key) except KeyError as error: raise space.unwind(space.LKeyError(self, key))
def interpret(pc, block, regv, frame): module = jit.promote(frame.module) unit = jit.promote(frame.unit) excs = jit.promote(frame.excs) try: while pc < len(block): try: jitdriver.jit_merge_point( pc=pc, block=block, module=module, unit=unit, excs=excs, regv=regv, frame=frame) opcode = rffi.r_ulong(block[pc])>>8 ix = pc+1 pc = ix+(rffi.r_ulong(block[pc])&255) #print optable.dec[opcode][0] if opcode == opcode_of('assert'): obj = regv.load(block[ix+0]) raise space.unwind(space.LAssertionError(obj)) elif opcode == opcode_of('raise'): obj = regv.load(block[ix+0]) traceback = obj.getattr(u"traceback") if traceback is space.null: traceback = space.List([]) obj.setattr(u"traceback", traceback) elif not isinstance(traceback, space.List): raise space.unwind(space.LError(u"Expected null or list as .traceback: %s" % obj.repr())) raise space.Unwinder(obj, traceback) elif opcode == opcode_of('constant'): regv.store(block[ix+0], unit.constants[block[ix+1]]) elif opcode == opcode_of('list'): contents = [] for i in range(ix+1, pc): contents.append(regv.load(block[i])) regv.store(block[ix], space.List(contents)) elif opcode == opcode_of('move'): regv.store(block[ix+0], regv.load(block[ix+1])) elif opcode == opcode_of('call'): op_call(regv, block, ix, pc) elif opcode == opcode_of('callv'): op_callv(regv, block, ix, pc) elif opcode == opcode_of('return'): return regv.load(block[ix+0]) elif opcode == opcode_of('jump'): pc = rffi.r_ulong(block[ix+0]) elif opcode == opcode_of('cond'): if space.is_false(regv.load(block[ix+0])): pc = rffi.r_ulong(block[ix+2]) else: pc = rffi.r_ulong(block[ix+1]) elif opcode == opcode_of('func'): regv.store(block[ix+0], Closure(frame, unit.functions[block[ix+1]])) elif opcode == opcode_of('iter'): regv.store(block[ix+0], regv.load(block[ix+1]).iter()) elif opcode == opcode_of('next'): try: regv.store(block[ix+0], regv.load(block[ix+1]).callattr(u'next', [])) except StopIteration as _: pc = rffi.r_ulong(block[ix+2]) # this is missing. #elif isinstance(op, Yield): # raise YieldIteration(op.block, loop_break, op.i, regv.load(op.value.i)) elif opcode == opcode_of('getattr'): name = get_string(unit, block, ix+2) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.getattr(name)) elif opcode == opcode_of('setattr'): value = regv.load(block[ix+3]) name = get_string(unit, block, ix+2) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.setattr(name, value)) elif opcode == opcode_of('getitem'): index = regv.load(block[ix+2]) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.getitem(index)) elif opcode == opcode_of('setitem'): item = regv.load(block[ix+3]) index = regv.load(block[ix+2]) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.setitem(index, item)) elif opcode == opcode_of('getloc'): regv.store(block[ix+0], frame.local[block[ix+1]]) elif opcode == opcode_of('setloc'): value = regv.load(block[ix+2]) frame.local[block[ix+1]] = value regv.store(block[ix+0], value) elif opcode == opcode_of('getupv'): value = get_upframe(frame, block[ix+1]).local[block[ix+2]] regv.store(block[ix+0], value) elif opcode == opcode_of('setupv'): value = regv.load(block[ix+3]) get_upframe(frame, block[ix+1]).local[block[ix+2]] = value regv.store(block[ix+0], value) elif opcode == opcode_of('getglob'): regv.store(block[ix+0], module.getattr(get_string(unit, block, ix+1))) elif opcode == opcode_of('setglob'): regv.store(block[ix+0], module.setattr( get_string(unit, block, ix+1), regv.load(block[ix+2]))) elif opcode == opcode_of('not'): if space.is_false(regv.load(block[ix+1])): regv.store(block[ix+0], space.true) else: regv.store(block[ix+0], space.false) elif opcode == opcode_of('contains'): v0 = regv.load(block[ix+1]) v1 = regv.load(block[ix+2]) if v0.contains(v1): regv.store(block[ix+0], space.true) else: regv.store(block[ix+0], space.false) else: raise space.unwind(space.LInstructionError( optable.names.get(opcode, str(opcode)).decode('utf-8'), opcode)) except space.Unwinder as unwinder: #print "exception detected, doing unwinds", pc, unwinder.exception.repr() for exc in excs: #print exc.start, exc.stop, exc.label, exc.reg if exc.start < pc <= exc.stop: regv.store(exc.reg, unwinder.exception) pc = exc.label #print "exception handler found" break else: raise except StopIteration as stop: unwinder = space.unwind(space.LUncatchedStopIteration()) unwinder.traceback.contents.append(TraceEntry(rffi.r_long(pc), unit.sources, frame.sourcemap)) raise unwinder except space.Unwinder as unwinder: unwinder.traceback.contents.append(TraceEntry(rffi.r_long(pc), unit.sources, frame.sourcemap)) raise return space.null
def as_list(obj): if not isinstance(obj, space.List): raise space.unwind(space.LTypeError(u"expected list")) return obj.contents
def as_u8a(obj): if not isinstance(obj, space.Uint8Array): raise space.unwind(space.LTypeError(u"expected uint8array")) return obj
def as_i(obj): if not isinstance(obj, space.Integer): raise space.unwind(space.LTypeError(u"expected integer")) return obj.value