def _find_lam(self, args): jit.promote(self.caselam) for i, lam in enumerate(self.caselam.lams): actuals = lam.match_args(args) if actuals is not None: frees = self._get_list(i) return actuals, frees, lam if len(self.caselam.lams) == 1: single_lambda = self.caselam.lams[0] single_lambda.raise_nice_error(args) raise SchemeException("No matching arity in case-lambda")
def string(args): if len(args) == 0: return W_String.fromascii("") assert len(args) > 0 builder = UnicodeBuilder() # XXX could do one less copy in the ascii case for char in args: if not isinstance(char, values.W_Character): raise SchemeException("string: expected a character") builder.append(char.value) return W_String.fromunicode(builder.build())
def random(args): if not args: # random flonum return values.W_Flonum(rng.random()) a1 = args[0] if isinstance(a1, values.W_Fixnum): upper = a1.value return values.W_Fixnum(int(rng.random() * upper)) if isinstance(a1, values.W_PseudoRandomGenerator): return values.W_Flonum(rng.random()) raise SchemeException("random: invalid arguments")
def bitwise_bit_setp(w_n, w_m): if w_m.arith_negativep() is values.w_true: raise SchemeException("bitwise-bit-set?: second argument must be non-negative") if not isinstance(w_m, values.W_Fixnum): # a bignum that has such a big bit set does not fit in memory return w_n.arith_negativep() v = w_n.arith_and(arith_shift(values.W_Fixnum.ONE, w_m)) if isinstance(v, values.W_Fixnum) and 0 == v.value: return values.w_false else: return values.w_true
def list_to_bytes(w_list): if not w_list.is_proper_list(): raise SchemeException("list->bytes: expected proper list, got %s" % w_list.tostring()) ll = [] while isinstance(w_list, values.W_UnwrappedFixnumConsProper): val = w_list._car if not (0 <= val < 256): break ll.append(chr(val)) w_list = w_list.cdr() else: if w_list is values.w_null: return values.W_MutableBytes(ll[:]) assert isinstance(w_list, values.W_Cons) raise SchemeException( "list->bytes: expected a number between 0 and 255, got %s" % w_list.car().tostring())
def initialize_prop(self, props, p, sub_prop=None): prop = p.car() prop_val = p.cdr() if sub_prop is None: if prop.isinstance(w_prop_procedure): if self.prop_procedure is not None and\ self.prop_procedure is not prop_val: raise SchemeException( "make-struct-type: duplicate property binding\nproperty: %s" % prop.tostring()) self.prop_procedure = prop_val self.procedure_source = self elif prop.isinstance(w_prop_checked_procedure): if self.total_field_cnt < 2: raise SchemeException( "need at least two fields in the structure type") props.append((prop, prop_val, sub_prop)) assert isinstance(prop, W_StructProperty) for super_p in prop.supers: self.initialize_prop(props, super_p, prop)
def hash_set(table, key, val, env, cont): from pycket.interpreter import return_value if not table.immutable(): raise SchemeException("hash-set: not given an immutable table") # Fast path if isinstance(table, W_ImmutableHashTable): new_table = table.assoc(key, val) return return_value(new_table, env, cont) return hash_copy(table, env, hash_set_cont(key, val, env, cont))
def instance_set_variable_value(instance, name, w_val, mode): var = instance.vars.get(name, None) if var: if var.constance is not w_false: raise SchemeException("Cannot mutate a constant : %s" % name.tostring()) else: var = W_LinkletVar(w_val, name, mode) instance.vars[name] = var var.val = w_val return w_void
def vector_copy(dest, _dest_start, src, _src_start, _src_end, env, cont): if dest.immutable(): raise SchemeException("vector-copy!: given an immutable destination") src_start = _src_start.value if _src_start is not None else 0 src_end = _src_end.value if _src_end is not None else src.length() dest_start = _dest_start.value src_range = src_end - src_start dest_range = dest.length() - dest_start if not (0 <= dest_start < dest.length()): raise SchemeException("vector-copy!: destination start out of bounds") if not (0 <= src_start <= src.length()) or not (0 <= src_start <= src.length()): raise SchemeException("vector-copy!: source start/end out of bounds") if dest_range < src_range: raise SchemeException("vector-copy!: not enough room in target vector") return vector_copy_loop(src, src_start, src_end, dest, dest_start, values.W_Fixnum(0), env, cont)
def make_immutable_hasheq(assocs): pairs = values.from_list(assocs) keys = [None] * len(pairs) vals = [None] * len(pairs) for i, pair in enumerate(pairs): if not isinstance(pair, values.W_Cons): raise SchemeException( "make-immutable-hasheq: expected list of pairs") keys[i] = pair.car() vals[i] = pair.cdr() return make_simple_table(W_EqHashTable, keys, vals, immutable=True)
def extract_path(obj): if isinstance(obj, values_string.W_String): result = obj.as_str_utf8() elif isinstance(obj, values.W_Path): result = obj.path elif isinstance(obj, values.W_Bytes): result = obj.as_str() else: raise SchemeException("expected path-like values but got %s" % obj.tostring()) return result if result is not None else "."
def bytes(args): if len(args) == 0: return values.W_MutableBytes([]) assert len(args) > 0 builder = StringBuilder() for char in args: if not (isinstance(char, values.W_Fixnum) and 0 <= char.value <= 255): raise SchemeException("string: expected a character int") builder.append(chr(char.value)) return values.W_Bytes.from_string(builder.build(), immutable=False)
def format(form, vals, name): fmt = form.as_str_utf8() # XXX for now i = 0 j = 0 result = [] len_fmt = len(fmt) while True: i0 = i while i < len_fmt: if fmt[i] == '~': break i += 1 else: # not left via break, so we're done result.append(fmt[i0:len_fmt]) break result.append(fmt[i0:i]) if i + 1 == len_fmt: raise SchemeException(name + ": bad format string") s = fmt[i + 1] if (s == 'a' or # turns into switch s == 'A' or s == 's' or s == 'S' or s == 'v' or s == 'V' or s == 'e' or s == 'E' or s == '.'): # print a value # FIXME: different format chars if j >= len(vals): raise SchemeException( name + ": not enough arguments for format string") result.append(vals[j].tostring()) j += 1 elif s == 'n' or s == '%': result.append("\n") # newline elif s == '~': result.append("~") else: raise SchemeException("%s: undexpected format character '%s'" % (name, s)) i += 2 if j != len(vals): raise SchemeException(name + ": not all values used") return "".join(result)
def substring(w_string, w_start, w_end): """ (substring str start [end]) -> string? str : string? start : exact-nonnegative-integer? end : exact-nonnegative-integer? = (string-length str) """ lenstring = w_string.length() start = w_start.value if start > lenstring or start < 0: raise SchemeException("substring: end index out of bounds") if w_end is not None: end = w_end.value if end > lenstring or end < 0: raise SchemeException("substring: end index out of bounds") else: end = lenstring if end < start: raise SchemeException( "substring: ending index is smaller than starting index") return w_string.getslice(start, end)
def subbytes(w_bytes, w_start, w_end): """ (subbytes bstr start [end]) → bytes? bstr : bytes? start : exact-nonnegative-integer? end : exact-nonnegative-integer? = (bytes-length str) """ bytes = w_bytes.value start = w_start.value if start > len(bytes) or start < 0: raise SchemeException("subbytes: end index out of bounds") if w_end is not None: end = w_end.value if end > len(bytes) or end < 0: raise SchemeException("subbytes: end index out of bounds") else: end = len(bytes) if end < start: raise SchemeException( "subbytes: ending index is smaller than starting index") return values.W_MutableBytes(bytes[start:end])
def integer_bytes_to_integer(bstr, signed): # XXX Currently does not make use of the signed parameter bytes = bstr.value if len(bytes) not in (4, 8): raise SchemeException( "floating-point-bytes->real: byte string must have length 2, 4, or 8") val = 0 for i, v in enumerate(bytes): val += ord(v) << (i * 8) return values.W_Flonum(longlong2float.longlong2float(val))
def integer_bytes_to_integer(bstr, signed): # XXX Currently does not make use of the signed 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") val = 0 for i, v in enumerate(bytes): val += ord(v) << (i * 8) return values.W_Fixnum(val)
def call_with_output_file(s, proc, mode, exists, env, cont): m = "" if exists is w_append_sym: m += "a" elif exists is w_truncate_sym or w_truncate_replace_sym: m += "w" else: raise SchemeException("mode not yet supported: %s" % exists.tostring()) if mode is not w_text_sym: m += "b" port = open_outfile(s, m) return proc.call([port], env, close_cont(port, env, cont))
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 hash_set(table, key, val, env, cont): from pycket.interpreter import return_value if not table.immutable(): raise SchemeException("hash-set: not given an immutable table") # Fast path if isinstance(table, W_SimpleHashTable): copy = table.make_copy() copy.data[key] = val return return_value(copy, env, cont) return hash_copy(table, env, hash_set_cont(key, val, env, cont))
def read_stream(stream): next_token = read_token(stream) if isinstance(next_token, SpecialToken): v = read_stream(stream) return next_token.finish(v) if isinstance(next_token, DelimToken): if not isinstance(next_token, LParenToken): raise SchemeException("read: unexpected %s"%next_token.str) v = read_list(stream, values.w_null, next_token.str) return v else: return next_token.val
def process_list(_lst): lst = _lst for letter in unrolled: if not isinstance(lst, values.W_Cons): raise SchemeException("%s: expected %s given %s" % (name, contract, _lst)) if letter == 'a': lst = lst.car() elif letter == 'd': lst = lst.cdr() else: assert False, "Bad list eater specification" return lst
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 map_loop(f, lists, env, cont): from pycket.interpreter import return_value lists_new = [] args = [] for l in lists: if not isinstance(l, values.W_Cons): if l is not values.w_null: raise SchemeException("map: not given a proper list") return return_value(values.w_null, env, cont) args.append(l.car()) lists_new.append(l.cdr()) return f.call(args, env, map_first_cont(f, lists_new, env, cont))
def _find_lam(self, args): jit.promote(self.caselam) for (i, lam) in enumerate(self.caselam.lams): try: actuals = lam.match_args(args) except SchemeException: if len(self.caselam.lams) == 1: lam.raise_nice_error(args) else: frees = self._get_list(i) return (actuals, frees, lam) raise SchemeException("No matching arity in case-lambda")
def do(args): if len(args) < 2: raise SchemeException("number of arguments to %s too small" % name) idx = 2 truth = True while idx <= len(args): start = idx - 2 assert start >= 0 w_a, w_b = args[start], args[start + 1] nan_a = not isinstance(w_a, values.W_Number) nan_b = not isinstance(w_b, values.W_Number) if nan_a or nan_b: pf = ["st", "nd", "rd"][idx - 1] if idx <= 3 else "th" w = w_a if nan_a else w_b raise SchemeException( "%s expected number as %s%s argument, got : %s" % (name, idx, pf, w.tostring())) idx += 1 truth = truth and getattr(w_a, "arith_" + op)(w_b) return con(truth)
def atan(y, x): if x is not None: # FIXME: signs determine the quadrant of the result # and care about NaNs and precision if x.arith_zerop() is values.w_false: z = y.arith_div(x) else: # we should raise exn_fail_contract_divide_by_zero raise SchemeException("zero_divisor") else: z = y return getattr(z, "arith_atan")()
def do_write_string(w_str, port, start_pos, end_pos, env, cont): from pycket.interpreter import return_value start = start_pos.value assert start >= 0 if end_pos: end_pos = end_pos.value if end_pos < 0 or end_pos > w_str.length(): raise SchemeException("write-string: ending index out of range") else: end_pos = w_str.length() cont = write_string_cont(w_str, start, end_pos, env, cont) return get_output_port(port, env, cont)
def real_floating_point_bytes(n, _size, big_endian): if isinstance(n, values.W_Flonum): v = n.value elif isinstance(n, values.W_Fixnum): v = float(n.value) elif isinstance(n, values.W_Bignum): v = rbigint.tofloat(n.value) else: raise SchemeException("real->floating-point-bytes: expected real") size = _size.value if size != 4 and size != 8: raise SchemeException("real->floating-point-bytes: size not 4 or 8") intval = longlong2float.float2longlong(v) if big_endian is not values.w_false: intval = rarithmetic.byteswap(intval) chars = [chr((intval >> (i * 8)) % 256) for i in range(size)] return values.W_Bytes.from_charlist(chars)
def call(self, args, env, cont): from pycket.interpreter import return_value if len(args) == 0: return self.parameter.call(args, env, call_cont(self.wrap, env, cont)) elif len(args) == 1: if self.guard: return self.guard.call(args, env, call_cont(self.parameter, env, cont)) return self.parameter.call(args, env, cont) else: raise SchemeException("wrong number of arguments to parameter")