def _instr_unpack_args(self, instr, cf): num_fargs, has_vargs = Target.unpack_unpack_args(instr) num_fargs = jit.promote(num_fargs) has_vargs = jit.promote(has_vargs) if not has_vargs: nargs = jit.promote(cf.nargs) else: nargs = cf.nargs if nargs > num_fargs and not has_vargs: msg = "Too many parameters (%d passed, but a maximum of %d allowed)." % \ (nargs, num_fargs) self.raise_helper("Parameters_Exception", [Builtins.Con_String(self, msg)]) if num_fargs > 0: arg_offset = cf.bc_off + Target.INTSIZE + num_fargs * Target.INTSIZE for i in range(num_fargs - 1, -1, -1): arg_offset -= Target.INTSIZE arg_info = Target.read_word(cf.pc.mod.bc, arg_offset) if i >= nargs: if not Target.unpack_unpack_args_is_mandatory(arg_info): msg = "No value passed for parameter %d." % (i + 1) self.raise_helper("Parameters_Exception", [Builtins.Con_String(self, msg)]) else: if nargs > num_fargs: o = cf.stack_pop_n(nargs - num_fargs) else: o = cf.stack_pop() assert isinstance(o, Builtins.Con_Object) cf.closure.vars[Target.unpack_unpack_args_arg_num( arg_info)] = o if has_vargs: arg_offset = cf.bc_off + Target.INTSIZE + num_fargs * Target.INTSIZE arg_info = Target.read_word(cf.pc.mod.bc, arg_offset) if nargs <= num_fargs: l = [] else: j = cf.stackpe i = j - (nargs - num_fargs) assert i >= 0 and j >= 0 l = cf.stack_get_slice(i, j) cf.stackpe = i + 1 cf.closure.vars[Target.unpack_unpack_args_arg_num( arg_info)] = Builtins.Con_List(self, l) cf.bc_off += Target.INTSIZE + (num_fargs + 1) * Target.INTSIZE else: cf.bc_off += Target.INTSIZE + num_fargs * Target.INTSIZE
def apply_closure(self, func, args=None, allow_fail=False): if not args: nargs = 0 else: nargs = len(args) if isinstance(func, Builtins.Con_Partial_Application): real_func = func.f cf, stack_count = self._add_continuation_frame( real_func, nargs + 1) cf.stack_extend(func.args) else: real_func = func cf, stack_count = self._add_continuation_frame(func, nargs) if args: cf.stack_extend(list(args)) assert isinstance(real_func, Builtins.Con_Func) if stack_count > 1 or real_func.has_loop: o = self.execute_proc_jit_hidden(cf) else: o = self.execute_proc(cf) self._remove_continuation_frame() if o is self.get_builtin(Builtins.BUILTIN_FAIL_OBJ): o = None if not allow_fail and o is None: self.raise_helper("VM_Exception", [Builtins.Con_String(self, \ "Function attempting to return fail, but caller can not handle failure.")]) return o, cf.closure
def import_stdlib_mod(self, ptl_mod_id): if not ptl_mod_id.startswith(os.sep): return self.get_mod(ptl_mod_id) for cnd_mod_id in self.mods.keys(): bt_cnd_mod_id = cnd_mod_id # XXX. The next two operations are pure evil and are basically a poor-man's # bootstrapping. They're intended to convert between module IDs across different # platforms. The potential problems with the below are fairly obvious, although # unlikely to actually manifest themselves in real life. if CASE_SENSITIVE_FILENAMES == 0: bt_cnd_mod_id = bt_cnd_mod_id.lower() if os.sep == "/": bt_cnd_mod_id = bt_cnd_mod_id.replace("\\", "/") elif os.sep == "\\": bt_cnd_mod_id = bt_cnd_mod_id.replace("/", "\\") else: self.raise_helper( "VM_Exception", [Con_String(vm, "Unknown separator %s." % os.sep)]) if bt_cnd_mod_id.endswith(ptl_mod_id): mod = self.get_mod(cnd_mod_id) mod.import_(self) return mod self.raise_helper("Import_Exception", [Builtins.Con_String(self, ptl_mod_id)])
def _instr_module_lookup(self, instr, cf): o = cf.stack_pop() nm_start, nm_size = Target.unpack_mod_lookup(instr) nm = Target.extract_str(cf.pc.mod.bc, cf.bc_off + nm_start, nm_size) if isinstance(o, Builtins.Con_Module): v = o.get_defn(self, nm) else: v = self.get_slot_apply(o, "get_defn", [Builtins.Con_String(self, nm)]) cf.stack_push(v) cf.bc_off += Target.align(nm_start + nm_size)
def mk_mod(vm, bc, mod_off): mod_size = read_word(bc, mod_off + BC_MOD_SIZE) assert mod_off >= 0 and mod_size >= 0 mod_bc = rffi.ptradd(bc, mod_off) name = _extract_sstr(mod_bc, BC_MOD_NAME, BC_MOD_NAME_SIZE) id_ = _extract_sstr(mod_bc, BC_MOD_ID, BC_MOD_ID_SIZE) src_path = _extract_sstr(mod_bc, BC_MOD_SRC_PATH, BC_MOD_SRC_PATH_SIZE) imps = [] j = read_word(mod_bc, BC_MOD_IMPORTS) for k in range(read_word(mod_bc, BC_MOD_NUM_IMPORTS)): assert j > 0 imp_size = read_word(mod_bc, j) assert imp_size > 0 j += INTSIZE imps.append(rffi.charpsize2str(rffi.ptradd(mod_bc, j), imp_size)) j += align(imp_size) j += INTSIZE + align(read_word(mod_bc, j)) num_vars = read_word(mod_bc, BC_MOD_NUM_TL_VARS_MAP) tlvars_map = {} j = read_word(mod_bc, BC_MOD_TL_VARS_MAP) for k in range(num_vars): assert j > 0 var_num = read_word(mod_bc, j) j += INTSIZE tlvar_size = read_word(mod_bc, j) assert tlvar_size > 0 j += INTSIZE n = rffi.charpsize2str(rffi.ptradd(mod_bc, j), tlvar_size) tlvars_map[n] = var_num j += align(tlvar_size) num_consts = read_word(mod_bc, BC_MOD_NUM_CONSTANTS) mod = Builtins.new_bc_con_module(vm, mod_bc, name, id_, src_path, imps, tlvars_map, num_consts) init_func_off = read_word(mod_bc, BC_MOD_INSTRUCTIONS) pc = BC_PC(mod, init_func_off) max_stack_size = 512 # XXX! mod.init_func = Builtins.Con_Func(vm, Builtins.Con_String(vm, "$$init$$"), False, pc, \ max_stack_size, 0, num_vars, mod, None) return mod
def decode_args(self, mand="", opt="", vargs=False, self_of=None): cf = self.cur_cf nargs = cf.nargs # Number of arguments passed mand = jit.promote_string(mand) opt = jit.promote_string(opt) self_of = jit.promote(self_of) if nargs < len(mand): if vargs: self.raise_helper("Parameters_Exception", [Builtins.Con_String(self, \ "Too few parameters (%d passed, but at least %d needed)." % (nargs, len(mand)))]) else: self.raise_helper("Parameters_Exception", [Builtins.Con_String(self, \ "Too few parameters (%d passed, but %d needed)." % (nargs, len(mand)))]) elif nargs > (len(mand) + len(opt)) and not vargs: raise Exception("XXX") if nargs == 0: if vargs: return (None, []) else: return (None, None) nrmp = [None] * (len(mand) + len(opt)) # Normal params i = 0 while i < (len(mand) + len(opt)): if i >= nargs: for j in range(i, nargs): nrmp[j] = None break if i < len(mand): t = mand[i] else: t = opt[i - len(mand)] o = cf.stack_get(cf.stackpe - nargs + i) if t == "!": assert self_of is not None if not isinstance(o, self_of): raise Exception("XXX") nrmp[i] = o i += 1 continue if t >= "a": if o is self.get_builtin(Builtins.BUILTIN_NULL_OBJ): nrmp[i] = None i += 1 continue t = chr(ord("A") + ord(t) - ord("a")) if t == "O": nrmp[i] = o else: if t == "C": Builtins.type_check_class(self, o) elif t == "D": Builtins.type_check_dict(self, o) elif t == "E": Builtins.type_check_exception(self, o) elif t == "F": Builtins.type_check_func(self, o) elif t == "I": Builtins.type_check_int(self, o) elif t == "L": Builtins.type_check_list(self, o) elif t == "M": Builtins.type_check_module(self, o) elif t == "N": Builtins.type_check_number(self, o) elif t == "S": Builtins.type_check_string(self, o) elif t == "W": Builtins.type_check_set(self, o) else: print t raise Exception("XXX") nrmp[i] = o i += 1 if vargs: vap = [None] * (nargs - i) for j in range(i, nargs): vap[j - i] = cf.stack_get(cf.stackpe - nargs + j) else: vap = None cf.stack_del_from(cf.stackpe - nargs) return (nrmp, vap)
def get_mod(self, mod_id): m = self.find_mod(mod_id) if m is None: self.raise_helper("Import_Exception", [Builtins.Con_String(self, mod_id)]) return m