def _to_num(json): assert json.is_object obj = json.value_object() if "real" in obj: r = obj["real"] return values.W_Flonum.make(r.value_float()) if "real-part" in obj: r = obj["real-part"] i = obj["imag-part"] return values.W_Complex.make(_to_num(r), _to_num(i)) if "numerator" in obj: n = obj["numerator"] d = obj["denominator"] return values.W_Rational.make(_to_num(n), _to_num(d)) if "extended-real" in obj: rs = obj["extended-real"].value_string() if rs == "+inf.0": return values.W_Flonum.INF if rs == "-inf.0": return values.W_Flonum.NEGINF if rs == "+nan.0": return values.W_Flonum.NAN if "integer" in obj: rs = obj["integer"].value_string() try: return values.W_Fixnum.make(string_to_int(rs)) except ParseStringOverflowError: val = rbigint.fromdecimalstr(rs) return values.W_Bignum(val) assert False
def read_number_or_id(f, init): sofar = StringBuilder(64) sofar.append(init) while True: c = f.peek() if c == "": break if idchar(c): v = f.read(1) assert v == c sofar.append(v) else: break got = sofar.build() try: val = string_to_int(got) return values.W_Fixnum.make_or_interned(val) except ParseStringOverflowError: val = rbigint.fromdecimalstr(got) return values.W_Bignum(val) except ParseStringError: try: return values.W_Flonum(float(got)) except: return values.W_Symbol.make(got)
def arith_sub_same(self, other): assert isinstance(other, values.W_Fixnum) try: res = rarithmetic.ovfcheck(self.value - other.value) except OverflowError: return values.W_Bignum(rbigint.fromint(self.value)).arith_sub(other) return values.W_Fixnum(res)
def integer_bytes_to_integer(bstr, signed, big_endian, w_start, w_end): bytes = bstr.as_bytes_list() start = w_start.value if w_end is None: end = len(bytes) else: end = w_end.value if not (0 <= start < len(bytes)): raise SchemeException( "integer-bytes->integer: start position not in byte string") if not (0 <= end <= len(bytes)): raise SchemeException( "integer-bytes->integer: end position not in byte string") if end < start: raise SchemeException( "integer-bytes->integer: end position less than start position") length = end - start if length not in (2, 4, 8): raise SchemeException( "integer-bytes->integer: byte string must have length 2, 4, or 8") if start != 0 or end != len(bytes): bytes = bytes[start:end] byteorder = "little" if big_endian is values.w_false else "big" is_signed = signed is not values.w_false big = rbigint.frombytes(bytes, byteorder, is_signed) try: result = values.W_Fixnum(big.toint()) except OverflowError: result = values.W_Bignum(big) return result
def arith_pow_same(self, other): assert isinstance(other, values.W_Fixnum) # XXX nonsense try: res = rarithmetic.ovfcheck_float_to_int(math.pow(self.value, other.value)) except OverflowError: return self.arith_pow(values.W_Bignum(rbigint.fromint(other.value))) return values.W_Fixnum(res)
def arith_mod_same(self, other): assert isinstance(other, values.W_Fixnum) if other.value == 0: raise Exception("zero_divisor") try: res = rarithmetic.ovfcheck(self.value % other.value) except OverflowError: return self.arith_mod(values.W_Bignum(rbigint.fromint(other.value))) return values.W_Fixnum(res)
def arith_mul_same(self, other): assert isinstance(other, values.W_Fixnum) if not self.value: return self if not other.value: return other try: res = rarithmetic.ovfcheck(self.value * other.value) except OverflowError: return self.arith_mul(values.W_Bignum(rbigint.fromint(other.value))) return values.W_Fixnum(res)
def arith_gcd_same(self, other): assert isinstance(other, values.W_Fixnum) if other.value: try: res = rarithmetic.ovfcheck(self.value % other.value) return other.arith_gcd(values.W_Fixnum(res)) except OverflowError: return values.W_Bignum(rbigint.fromint( self.value)).arith_gcd(other) else: return self
def _str2num(s, radix): from rpython.rlib import rarithmetic, rfloat, rbigint from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError from rpython.rlib.rsre import rsre_re as re import math try: if ((radix == 16 and re.match("^[0-9A-Fa-f]+$", s)) or (radix == 8 and re.match("^[0-7]+$", s)) or (radix == 10 and re.match("^[0-9]+$", s))): try: return values.W_Fixnum(rarithmetic.string_to_int(s, base=radix)) except ParseStringOverflowError: return values.W_Bignum(rbigint.rbigint.fromstr(s, base=radix)) if re.match("[+-]?([\d]+)?.?\d+[tT]\d", s): # it's an extflonum return values.W_ExtFlonum(s) if re.match("[+-]?([\d]+)?.?\d+[sf]\d", s): if "f" in s: f_parts = s.split("f") elif "s" in s: f_parts = s.split("s") else: raise ParseStringError("invalid floating point number : %s" % s) if len(f_parts) > 2: raise ParseStringError("invalid floating point number : %s" % s) try: numb = float(f_parts[0]) prec = int(f_parts[1]) p = math.pow(10, prec) except ValueError, e: return values.w_false return values.W_Flonum.make(numb * p, True) if re.match("[+-]?([\d]+)?.?\d+e\d", s): e_parts = s.split("e") if len(e_parts) > 2: raise ParseStringError("invalid floating point number : %s" % s) try: num = float(e_parts[0]) exp = int(e_parts[1]) p = math.pow(10, exp) except ValueError, e: return values.w_false return values.W_Flonum(num * p)
def arith_shl_same(self, other): assert isinstance(other, values.W_Fixnum) if other.value >= r_int.BITS: if not self.value: return values.W_Fixnum.ZERO val = rbigint.fromint(self.value).lshift(other.value) return values.W_Integer.frombigint(val) try: res = rarithmetic.ovfcheck(self.value << other.value) except OverflowError: return self.arith_shl(values.W_Bignum(rbigint.fromint(other.value))) return values.W_Fixnum(res)
def arith_quotient_same(self, other): assert isinstance(other, values.W_Fixnum) x = self.value y = other.value if y: try: res = int_floordiv_ovf(x, y) # misnomer, should be int_truncdiv or so except OverflowError: return self.arith_quotient(values.W_Bignum(rbigint.fromint(other.value))) else: raise SchemeException("zero_divisor") return values.W_Fixnum(res)
def arith_div_same(self, other): assert isinstance(other, values.W_Fixnum) if other.value == 0: raise SchemeException("zero_divisor") try: res = rarithmetic.ovfcheck(self.value / other.value) except OverflowError: return self.arith_div(values.W_Bignum(rbigint.fromint( other.value))) if res * other.value == self.value: return values.W_Fixnum(res) return values.W_Rational.fromint(self.value, other.value)
def file_size(obj): if not is_path_string(obj): raise SchemeException("file-size: expected path string") path = extract_path(obj) try: size = os.path.getsize(path) except OSError: raise SchemeException("file-size: file %s does not exists" % path) intsize = intmask(size) if intsize == size: return values.W_Fixnum(intsize) return values.W_Bignum(rbigint.fromrarith_int(size))
def str2num(w_s): from rpython.rlib import rarithmetic, rfloat, rbigint from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError s = w_s.as_str_utf8() try: if "." in s: return values.W_Flonum(rfloat.string_to_float(s)) else: try: return values.W_Fixnum(rarithmetic.string_to_int(s, base=10)) except ParseStringOverflowError: return values.W_Bignum(rbigint.rbigint.fromstr(s)) except ParseStringError as e: return values.w_false
def arith_remainder_same(self, other): assert isinstance(other, values.W_Fixnum) if other.value == 0: raise Exception("zero_divisor") a = abs(self.value) b = abs(other.value) try: res = rarithmetic.ovfcheck(a % b) if self.value < 0: res = rarithmetic.ovfcheck(-res) except OverflowError: res = a % b res1 = -res if self.value < 0 else res return self.arith_mod(values.W_Bignum(rbigint.fromint(res1))) return values.W_Fixnum(res)
def integer_bytes_to_integer(bstr, signed, big_endian): # XXX Currently does not make use of the signed or big endian parameter bytes = bstr.value if len(bytes) not in (2, 4, 8): raise SchemeException( "integer-bytes->integer: byte string must have length 2, 4, or 8") byteorder = "little" if big_endian is values.w_false else "big" is_signed = signed is not values.w_false big = rbigint.frombytes(bytes, byteorder, is_signed) try: result = values.W_Fixnum(big.toint()) except OverflowError: result = values.W_Bignum(big) return result
def read_number_or_id(f, init): sofar = [init] while True: c = f.peek() if c == "": break if idchar(c): v = f.read(1) assert v == c sofar.append(v) else: break got = "".join(sofar) try: return NumberToken(values.W_Fixnum.make(string_to_int(got))) except ParseStringOverflowError: val = rbigint.fromdecimalstr(got) return NumberToken(values.W_Bignum(val)) except ParseStringError: try: return NumberToken(values.W_Flonum.make(float(got))) except: return SymbolToken(values.W_Symbol.make(got))
def arith_unarysub(self): try: res = rarithmetic.ovfcheck(-self.value) except OverflowError: return values.W_Bignum(rbigint.fromint(self.value).neg()) return values.W_Fixnum(res)
def fasl_to_sexp_recursive(self, fasl_string, pos): from pycket import values as v from pycket.values_string import W_String from pycket.values_regex import W_Regexp, W_PRegexp, W_ByteRegexp, W_BytePRegexp from pycket.vector import W_Vector from pycket.values_struct import W_Struct from pycket.prims.general import srcloc from pycket.hash import simple as hash_simple from pycket.hash.equal import W_EqualHashTable from pycket.prims.numeric import float_bytes_to_real from pycket.prims.string import _str2num from rpython.rlib.rbigint import rbigint from pycket.prims.input_output import build_path, bytes_to_path_element from pycket.ast_vs_sexp import to_rpython_list from pycket.racket_entry import get_primitive typ, pos = self.read_byte_no_eof(fasl_string, pos) if typ == FASL_GRAPH_DEF_TYPE: position, pos = self.read_fasl_integer(fasl_string, pos) val, pos = self.fasl_to_sexp_recursive(fasl_string, pos) if position >= self.GLOBAL_SHARED_COUNT: raise Exception("fasl: bad graph index") self.SHARED[position] = val return val, pos elif typ == FASL_GRAPH_REF_TYPE: position, pos = self.read_fasl_integer(fasl_string, pos) if position >= self.GLOBAL_SHARED_COUNT: raise Exception("fasl: bad graph index") return self.SHARED[position], pos elif typ == FASL_FALSE_TYPE: return v.w_false, pos elif typ == FASL_TRUE_TYPE: return v.w_true, pos elif typ == FASL_NULL_TYPE: return v.w_null, pos elif typ == FASL_VOID_TYPE: return v.w_void, pos elif typ == FASL_EOF_TYPE: return v.eof_object, pos elif typ == FASL_INTEGER_TYPE: num, pos = self.read_fasl_integer(fasl_string, pos) if isinstance(num, rbigint): return v.W_Bignum(num), pos return v.W_Fixnum(num), pos elif typ == FASL_FLONUM_TYPE: num_str, pos = self.read_bytes_exactly(fasl_string, pos, 8) return float_bytes_to_real(list(num_str), v.w_false), pos elif typ == FASL_SINGLE_FLONUM_TYPE: num_str, pos = self.read_bytes_exactly(fasl_string, pos, 4) real = float_bytes_to_real(list(num_str), v.w_false) return real.arith_exact_inexact(), pos elif typ == FASL_EXTFLONUM_TYPE: bstr_len, pos = self.read_fasl_integer(fasl_string, pos) num_str, pos = self.read_bytes_exactly(fasl_string, pos, bstr_len) return _str2num(W_String.fromstr_utf8(num_str).as_str_utf8(), 10), pos elif typ == FASL_RATIONAL_TYPE: num, pos = self.fasl_to_sexp_recursive(fasl_string, pos) den, pos = self.fasl_to_sexp_recursive(fasl_string, pos) return v.W_Rational.make(num, den), pos elif typ == FASL_COMPLEX_TYPE: re, pos = self.fasl_to_sexp_recursive(fasl_string, pos) im, pos = self.fasl_to_sexp_recursive(fasl_string, pos) return v.W_Complex.from_real_pair(re, im), pos elif typ == FASL_CHAR_TYPE: _chr, pos = self.read_fasl_integer(fasl_string, pos) return v.W_Character(unichr(_chr)), pos elif typ == FASL_SYMBOL_TYPE: sym_str, pos = self.read_fasl_string(fasl_string, pos) return v.W_Symbol.make(sym_str), pos elif typ == FASL_UNREADABLE_SYMBOL_TYPE: sym_str, pos = self.read_fasl_string(fasl_string, pos) return v.W_Symbol.make_unreadable(sym_str), pos elif typ == FASL_UNINTERNED_SYMBOL_TYPE: sym_str, pos = self.read_fasl_string(fasl_string, pos) return v.W_Symbol(sym_str), pos elif typ == FASL_KEYWORD_TYPE: key_str, pos = self.read_fasl_string(fasl_string, pos) return v.W_Keyword.make(key_str), pos elif typ == FASL_STRING_TYPE: str_str, pos = self.read_fasl_string(fasl_string, pos) return W_String.make(str_str), pos elif typ == FASL_IMMUTABLE_STRING_TYPE: str_str, pos = self.read_fasl_string(fasl_string, pos) return W_String.make(str_str).make_immutable(), pos elif typ == FASL_BYTES_TYPE: byts, pos = self.read_fasl_bytes(fasl_string, pos) return v.W_Bytes.from_string(byts, immutable=False), pos elif typ == FASL_IMMUTABLE_BYTES_TYPE: byts, pos = self.read_fasl_bytes(fasl_string, pos) return v.W_Bytes.from_string(byts), pos elif typ == FASL_PATH_TYPE: byts, pos = self.read_fasl_bytes(fasl_string, pos) return v.W_Path(byts), pos elif typ == FASL_RELATIVE_PATH_TYPE: wrt_dir = self.current_relative_dir p_w_lst, pos = self.fasl_to_sexp_recursive(fasl_string, pos) p_r_lst, _ = to_rpython_list(p_w_lst) rel_elems = [ bytes_to_path_element(p) if isinstance(p, v.W_Bytes) else p for p in p_r_lst ] if wrt_dir: return build_path([wrt_dir] + rel_elems), pos elif rel_elems == []: return build_path([v.W_Symbol.make("same")]), pos else: return build_path(rel_elems), pos elif typ == FASL_PREGEXP_TYPE: str_str, pos = self.read_fasl_string(fasl_string, pos) reg_str = W_String.make(str_str) pregexp = get_primitive('pregexp') pregexp_obj = pregexp.call_interpret([reg_str]) return pregexp_obj, pos elif typ == FASL_REGEXP_TYPE: str_str, pos = self.read_fasl_string(fasl_string, pos) reg_str = W_String.make(str_str) regexp = get_primitive('regexp') regexp_obj = regexp.call_interpret([reg_str]) return regexp_obj, pos elif typ == FASL_BYTE_PREGEXP: str_str, pos = self.read_fasl_string(fasl_string, pos) reg_bytes = v.W_Bytes.from_string(str_str) byte_pregexp = get_primitive('byte-pregexp') byte_pregexp_obj = byte_pregexp.call_interpret([reg_bytes]) return byte_pregexp_obj, pos elif typ == FASL_BYTE_REGEXP_TYPE: str_str, pos = self.read_fasl_string(fasl_string, pos) reg_bytes = v.W_Bytes.from_string(str_str) byte_regexp = get_primitive('byte-regexp') byte_regexp_obj = byte_regexp.call_interpret([reg_bytes]) return byte_regexp_obj, pos elif typ == FASL_LIST_TYPE: list_len, pos = self.read_fasl_integer(fasl_string, pos) lst, pos = self.read_multi_into_rpython_list( fasl_string, pos, list_len) return v.to_list(lst), pos elif typ == FASL_PAIR_TYPE: car, pos = self.fasl_to_sexp_recursive(fasl_string, pos) cdr, pos = self.fasl_to_sexp_recursive(fasl_string, pos) return v.W_Cons.make(car, cdr), pos elif typ == FASL_LIST_STAR_TYPE: list_len, pos = self.read_fasl_integer(fasl_string, pos) # list_len is the length of the proper part lst, pos = self.read_multi_into_rpython_list( fasl_string, pos, list_len) # read the last element return_list, pos = self.fasl_to_sexp_recursive(fasl_string, pos) for i in range(list_len - 1, -1, -1): return_list = v.W_Cons.make(lst[i], return_list) return return_list, pos elif typ == FASL_VECTOR_TYPE or typ == FASL_IMMUTABLE_VECTOR_TYPE: vec_len, pos = self.read_fasl_integer(fasl_string, pos) storage, pos = self.read_multi_into_rpython_list( fasl_string, pos, vec_len) if typ == FASL_IMMUTABLE_VECTOR_TYPE: return W_Vector.fromelements(storage, immutable=True), pos return W_Vector.fromelements(storage), pos elif typ == FASL_BOX_TYPE: element, pos = self.fasl_to_sexp_recursive(fasl_string, pos) return v.W_MBox(element), pos elif typ == FASL_IMMUTABLE_BOX_TYPE: element, pos = self.fasl_to_sexp_recursive(fasl_string, pos) return v.W_IBox(element), pos elif typ == FASL_PREFAB_TYPE: key, pos = self.fasl_to_sexp_recursive(fasl_string, pos) length, pos = self.read_fasl_integer(fasl_string, pos) vals, pos = self.read_multi_into_rpython_list( fasl_string, pos, length) return W_Struct.make_prefab(key, vals), pos elif typ == FASL_HASH_TYPE: variant, pos = self.read_byte_no_eof(fasl_string, pos) length, pos = self.read_fasl_integer(fasl_string, pos) keys, vals, pos = self.read_multi_double_into_rpython_list( fasl_string, pos, length) if variant == FASL_HASH_EQ_VARIANT: return hash_simple.make_simple_mutable_table( hash_simple.W_EqMutableHashTable, keys, vals), pos elif variant == FASL_HASH_EQV_VARIANT: return hash_simple.make_simple_mutable_table( hash_simple.W_EqvMutableHashTable, keys, vals), pos else: # variant == FASL_HASH_EQUAL_VARIANT: return W_EqualHashTable(keys, vals, immutable=False), pos elif typ == FASL_IMMUTABLE_HASH_TYPE: variant, pos = self.read_byte_no_eof(fasl_string, pos) length, pos = self.read_fasl_integer(fasl_string, pos) keys, vals, pos = self.read_multi_double_into_rpython_list( fasl_string, pos, length) if variant == FASL_HASH_EQ_VARIANT: return hash_simple.make_simple_immutable_table( hash_simple.W_EqImmutableHashTable, keys, vals), pos elif variant == FASL_HASH_EQV_VARIANT: return hash_simple.make_simple_immutable_table( hash_simple.W_EqvImmutableHashTable, keys, vals), pos else: # variant == FASL_HASH_EQUAL_VARIANT: return W_EqualHashTable(keys, vals, immutable=True), pos elif typ == FASL_SRCLOC: # difficult to create an instance of srcloc struct so defer that to the runtime source, pos = self.fasl_to_sexp_recursive(fasl_string, pos) line, pos = self.fasl_to_sexp_recursive(fasl_string, pos) column, pos = self.fasl_to_sexp_recursive(fasl_string, pos) position, pos = self.fasl_to_sexp_recursive(fasl_string, pos) span, pos = self.fasl_to_sexp_recursive(fasl_string, pos) return W_Struct.make([source, line, column, position, span], srcloc), pos else: if typ >= FASL_SMALL_INTEGER_START: return v.W_Fixnum((typ - FASL_SMALL_INTEGER_START) + FASL_LOWEST_SMALL_INTEGER), pos else: raise Exception("unrecognized fasl tag : %s" % typ)
exp = int(e_parts[1]) p = math.pow(10, exp) except ValueError, e: return values.w_false return values.W_Flonum(num*p) if "." in s or re.match("[+-]?([\d]+)(\.[\d]+)?e[+-][\d]+$", s): if not radix == 10: # FIXME raise SchemeException("string->number : floats with base different than 10 are not supported yet : given number : %s - radix : %s" % (w_s.tostring(), str(radix))) return values.W_Flonum(rfloat.string_to_float(s)) else: try: return values.W_Fixnum(rarithmetic.string_to_int(s, base=radix)) except ParseStringOverflowError: return values.W_Bignum(rbigint.rbigint.fromstr(s, base=radix)) except ParseStringError as e: return values.w_false @expose("number->string", [values.W_Number, default(values.W_Fixnum, values.W_Fixnum.make(10))]) def num2str(a, radix): from rpython.rlib.rbigint import BASE8, BASE16 if radix.value == 10: return W_String.fromascii(a.tostring()) else: if isinstance(a, values.W_Fixnum): if radix.value == 16: res = hex(a.value) if a.value >= 0: res = res[2:]
def arith_unarysub(self): # XXX fix the sys.maxint + 1 case return values.W_Bignum(self.value.neg())
def same_numeric_class(self, other): if isinstance(other, values.W_Fixnum): return self, values.W_Bignum(rbigint.fromint(other.value)) if isinstance(other, values.W_Bignum): return self, other return other.same_numeric_class_reversed(self)
def str2num(w_s, radix, convert_mode, decimal_mode): from rpython.rlib import rarithmetic, rfloat, rbigint from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError from rpython.rlib.rsre import rsre_re as re import math s = w_s.as_str_utf8() try: if re.match("[+-]?([\d]+)?.?\d+[tT]\d", s): # it's an extflonum return values.W_ExtFlonum(s) if re.match("[+-]?([\d]+)?.?\d+[sf]\d", s): if "f" in s: f_parts = s.split("f") elif "s" in s: f_parts = s.split("s") else: raise ParseStringError("invalid floating point number : %s" % s) if len(f_parts) > 2: raise ParseStringError("invalid floating point number : %s" % s) try: numb = float(f_parts[0]) prec = int(f_parts[1]) p = math.pow(10, prec) except ValueError: return values.w_false return values.W_Flonum.make(numb * p, True) if re.match("[+-]?([\d]+)?.?\d+e\d", s): e_parts = s.split("e") if len(e_parts) > 2: raise ParseStringError("invalid floating point number : %s" % s) try: num = float(e_parts[0]) exp = int(e_parts[1]) p = math.pow(10, exp) except ValueError: return values.w_false return values.W_Flonum(num * p) if "." in s or re.match("[+-]?([\d]+)(\.[\d]+)?e[+-][\d]+$", s): if not radix.equal(values.W_Fixnum(10)): # FIXME raise SchemeException( "string->number : floats with base different than 10 are not supported yet : given number : %s - radix : %s" % (w_s.tostring(), radix.tostring())) return values.W_Flonum(rfloat.string_to_float(s)) else: try: return values.W_Fixnum( rarithmetic.string_to_int(s, base=radix.toint())) except ParseStringOverflowError: return values.W_Bignum(rbigint.rbigint.fromstr(s)) except ParseStringError as e: return values.w_false