int igraph_i_eigen_matrix_lapack_cmp_sm(void *extra, const void *a, const void *b) { igraph_i_eml_cmp_t *myextra=(igraph_i_eml_cmp_t *) extra; int *aa=(int*) a, *bb=(int*) b; igraph_real_t a_m=VECTOR(*myextra->mag)[*aa]; igraph_real_t b_m=VECTOR(*myextra->mag)[*bb]; if (MORE(a_m, b_m)) { return 1; } else if (LESS(a_m, b_m)) { return -1; } else { igraph_real_t a_r=VECTOR(*myextra->real)[*aa]; igraph_real_t a_i=VECTOR(*myextra->imag)[*aa]; igraph_real_t b_r=VECTOR(*myextra->real)[*bb]; igraph_real_t b_i=VECTOR(*myextra->imag)[*bb]; if (NONZERO(a_i) && ZERO(b_i)) { return -1; } if (ZERO(a_i) && NONZERO(b_i)) { return 1; } if (LESS(a_r, b_r)) { return -1; } if (MORE(a_r, b_r)) { return 1; } if (LESS(a_i, b_i)) { return -1; } if (MORE(a_i, b_i)) { return 1; } } return 0; }
void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, Register recv, Register method_temp, Register temp2, bool for_compiler_entry) { BLOCK_COMMENT("jump_to_lambda_form {"); // This is the initial entry point of a lazy method handle. // After type checking, it picks up the invoker from the LambdaForm. assert_different_registers(recv, method_temp, temp2); assert(recv != noreg, "required register"); assert(method_temp == rmethod, "required register for loading method"); //NOT_PRODUCT({ FlagSetting fs(TraceMethodHandles, true); trace_method_handle(_masm, "LZMH"); }); // Load the invoker, as MH -> MH.form -> LF.vmentry __ verify_oop(recv); __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()))); __ verify_oop(method_temp); __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(method_temp); // the following assumes that a Method* is normally compressed in the vmtarget field: __ ldr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack __ ldr(temp2, Address(method_temp, Method::const_offset())); __ load_sized_value(temp2, Address(temp2, ConstMethod::size_of_parameters_offset()), sizeof(u2), /*is_signed*/ false); // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), ""); Label L; __ ldr(rscratch1, __ argument_address(temp2, -1)); __ cmp(recv, rscratch1); __ br(Assembler::EQ, L); __ ldr(r0, __ argument_address(temp2, -1)); __ hlt(0); __ BIND(L); } jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry); BLOCK_COMMENT("} jump_to_lambda_form"); }
void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, Register recv, Register method_temp, Register temp2, Register temp3, bool for_compiler_entry) { BLOCK_COMMENT("jump_to_lambda_form {"); // This is the initial entry point of a lazy method handle. // After type checking, it picks up the invoker from the LambdaForm. assert_different_registers(recv, method_temp, temp2); // temp3 is only passed on assert(method_temp == R19_method, "required register for loading method"); // Load the invoker, as MH -> MH.form -> LF.vmentry __ verify_oop(recv); __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv, temp2); __ verify_oop(method_temp); __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2); __ verify_oop(method_temp); // The following assumes that a Method* is normally compressed in the vmtarget field: __ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp); if (VerifyMethodHandles && !for_compiler_entry) { // Make sure recv is already on stack. __ ld(temp2, in_bytes(Method::const_offset()), method_temp); __ load_sized_value(temp2, in_bytes(ConstMethod::size_of_parameters_offset()), temp2, sizeof(u2), /*is_signed*/ false); // assert(sizeof(u2) == sizeof(ConstMethod::_size_of_parameters), ""); Label L; __ ld(temp2, __ argument_offset(temp2, temp2, 0), CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp)); __ cmpd(CCR1, temp2, recv); __ beq(CCR1, L); __ stop("receiver not on stack"); __ BIND(L); } jump_from_method_handle(_masm, method_temp, temp2, temp3, for_compiler_entry); BLOCK_COMMENT("} jump_to_lambda_form"); }
void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) { Label L; BLOCK_COMMENT("verify_ref_kind {"); __ movl(temp, Address(member_reg, NONZERO(java_lang_invoke_MemberName::flags_offset_in_bytes()))); __ shrl(temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT); __ andl(temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); __ cmpl(temp, ref_kind); __ jcc(Assembler::equal, L); { char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal); jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); if (ref_kind == JVM_REF_invokeVirtual || ref_kind == JVM_REF_invokeSpecial) // could do this for all ref_kinds, but would explode assembly code size trace_method_handle(_masm, buf); __ STOP(buf); } BLOCK_COMMENT("} verify_ref_kind"); __ bind(L); }
void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) { Label L; BLOCK_COMMENT("verify_ref_kind {"); __ load_sized_value(temp, NONZERO(java_lang_invoke_MemberName::flags_offset_in_bytes()), member_reg, sizeof(u4), /*is_signed*/ false); // assert(sizeof(u4) == sizeof(java.lang.invoke.MemberName.flags), ""); __ srwi( temp, temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT); __ andi(temp, temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); __ cmpwi(CCR1, temp, ref_kind); __ beq(CCR1, L); { char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal); jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); if (ref_kind == JVM_REF_invokeVirtual || ref_kind == JVM_REF_invokeSpecial) // could do this for all ref_kinds, but would explode assembly code size trace_method_handle(_masm, buf); __ stop(buf); } BLOCK_COMMENT("} verify_ref_kind"); __ BIND(L); }
void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, vmIntrinsics::ID iid, Register receiver_reg, Register member_reg, bool for_compiler_entry) { assert(is_signature_polymorphic(iid), "expected invoke iid"); Register temp1 = (for_compiler_entry ? R25_tmp5 : R7); Register temp2 = (for_compiler_entry ? R22_tmp2 : R8); Register temp3 = (for_compiler_entry ? R23_tmp3 : R9); Register temp4 = (for_compiler_entry ? R24_tmp4 : R10); if (receiver_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, receiver_reg); if (member_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, member_reg); if (iid == vmIntrinsics::_invokeBasic) { // indirect through MH.form.vmentry.vmtarget jump_to_lambda_form(_masm, receiver_reg, R19_method, temp1, temp2, for_compiler_entry); } else { // The method is a member invoker used by direct method handles. if (VerifyMethodHandles) { // make sure the trailing argument really is a MemberName (caller responsibility) verify_klass(_masm, member_reg, SystemDictionary::WK_KLASS_ENUM_NAME(MemberName_klass), temp1, temp2, "MemberName required for invokeVirtual etc."); } Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { __ verify_oop(receiver_reg); if (iid == vmIntrinsics::_linkToSpecial) { // Don't actually load the klass; just null-check the receiver. __ null_check_throw(receiver_reg, -1, temp1, EXCEPTION_ENTRY); } else { // load receiver klass itself __ null_check_throw(receiver_reg, oopDesc::klass_offset_in_bytes(), temp1, EXCEPTION_ENTRY); __ load_klass(temp1_recv_klass, receiver_reg); __ verify_klass_ptr(temp1_recv_klass); } BLOCK_COMMENT("check_receiver {"); // The receiver for the MemberName must be in receiver_reg. // Check the receiver against the MemberName.clazz if (VerifyMethodHandles && iid == vmIntrinsics::_linkToSpecial) { // Did not load it above... __ load_klass(temp1_recv_klass, receiver_reg); __ verify_klass_ptr(temp1_recv_klass); } if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) { Label L_ok; Register temp2_defc = temp2; __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3); load_klass_from_Class(_masm, temp2_defc, temp3, temp4); __ verify_klass_ptr(temp2_defc); __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok); // If we get here, the type check failed! __ stop("receiver class disagrees with MemberName.clazz"); __ BIND(L_ok); } BLOCK_COMMENT("} check_receiver"); } if (iid == vmIntrinsics::_linkToSpecial || iid == vmIntrinsics::_linkToStatic) { DEBUG_ONLY(temp1_recv_klass = noreg); // these guys didn't load the recv_klass } // Live registers at this point: // member_reg - MemberName that was the trailing argument // temp1_recv_klass - klass of stacked receiver, if needed // O5_savedSP - interpreter linkage (if interpreted) // O0..O5 - compiler arguments (if compiled) Label L_incompatible_class_change_error; switch (iid) { case vmIntrinsics::_linkToSpecial: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2); } __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2); } __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); break; case vmIntrinsics::_linkToVirtual: { // same as TemplateTable::invokevirtual, // minus the CP setup and profiling: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp2); } // pick out the vtable index from the MemberName, and then we can discard it: Register temp2_index = temp2; __ ld(temp2_index, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()), member_reg); if (VerifyMethodHandles) { Label L_index_ok; __ cmpdi(CCR1, temp2_index, 0); __ bge(CCR1, L_index_ok); __ stop("no virtual index"); __ BIND(L_index_ok); } // Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget // at this point. And VerifyMethodHandles has already checked clazz, if needed. // get target Method* & entry point __ lookup_virtual_method(temp1_recv_klass, temp2_index, R19_method); break; } case vmIntrinsics::_linkToInterface: { // same as TemplateTable::invokeinterface // (minus the CP setup and profiling, with different argument motion) if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp2); } Register temp2_intf = temp2; __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3); load_klass_from_Class(_masm, temp2_intf, temp3, temp4); __ verify_klass_ptr(temp2_intf); Register vtable_index = R19_method; __ ld(vtable_index, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()), member_reg); if (VerifyMethodHandles) { Label L_index_ok; __ cmpdi(CCR1, vtable_index, 0); __ bge(CCR1, L_index_ok); __ stop("invalid vtable index for MH.invokeInterface"); __ BIND(L_index_ok); } // given intf, index, and recv klass, dispatch to the implementation method __ lookup_interface_method(temp1_recv_klass, temp2_intf, // note: next two args must be the same: vtable_index, R19_method, temp3, temp4, L_incompatible_class_change_error); break; } default: fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid))); break; } // Live at this point: // R19_method // O5_savedSP (if interpreted) // After figuring out which concrete method to call, jump into it. // Note that this works in the interpreter with no data motion. // But the compiled version will require that rcx_recv be shifted out. __ verify_method_ptr(R19_method); jump_from_method_handle(_masm, R19_method, temp1, temp2, for_compiler_entry); if (iid == vmIntrinsics::_linkToInterface) { __ BIND(L_incompatible_class_change_error); __ load_const_optimized(temp1, StubRoutines::throw_IncompatibleClassChangeError_entry()); __ mtctr(temp1); __ bctr(); } } }
void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, vmIntrinsics::ID iid, Register receiver_reg, Register member_reg, bool for_compiler_entry) { assert(is_signature_polymorphic(iid), "expected invoke iid"); // temps used in this code are not used in *either* compiled or interpreted calling sequences Register temp1 = r10; Register temp2 = r11; Register temp3 = r14; // r13 is live by this point: it contains the sender SP if (for_compiler_entry) { assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0), "only valid assignment"); assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7); assert_different_registers(temp2, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7); assert_different_registers(temp3, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5, j_rarg6, j_rarg7); } assert_different_registers(temp1, temp2, temp3, receiver_reg); assert_different_registers(temp1, temp2, temp3, member_reg); if (iid == vmIntrinsics::_invokeBasic) { // indirect through MH.form.vmentry.vmtarget jump_to_lambda_form(_masm, receiver_reg, rmethod, temp1, for_compiler_entry); } else { // The method is a member invoker used by direct method handles. if (VerifyMethodHandles) { // make sure the trailing argument really is a MemberName (caller responsibility) verify_klass(_masm, member_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_invoke_MemberName), "MemberName required for invokeVirtual etc."); } Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { __ verify_oop(receiver_reg); if (iid == vmIntrinsics::_linkToSpecial) { // Don't actually load the klass; just null-check the receiver. __ null_check(receiver_reg); } else { // load receiver klass itself __ null_check(receiver_reg, oopDesc::klass_offset_in_bytes()); __ load_klass(temp1_recv_klass, receiver_reg); __ verify_klass_ptr(temp1_recv_klass); } BLOCK_COMMENT("check_receiver {"); // The receiver for the MemberName must be in receiver_reg. // Check the receiver against the MemberName.clazz if (VerifyMethodHandles && iid == vmIntrinsics::_linkToSpecial) { // Did not load it above... __ load_klass(temp1_recv_klass, receiver_reg); __ verify_klass_ptr(temp1_recv_klass); } if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) { Label L_ok; Register temp2_defc = temp2; __ load_heap_oop(temp2_defc, member_clazz); load_klass_from_Class(_masm, temp2_defc); __ verify_klass_ptr(temp2_defc); __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, L_ok); // If we get here, the type check failed! __ hlt(0); // __ STOP("receiver class disagrees with MemberName.clazz"); __ bind(L_ok); } BLOCK_COMMENT("} check_receiver"); } if (iid == vmIntrinsics::_linkToSpecial || iid == vmIntrinsics::_linkToStatic) { DEBUG_ONLY(temp1_recv_klass = noreg); // these guys didn't load the recv_klass } // Live registers at this point: // member_reg - MemberName that was the trailing argument // temp1_recv_klass - klass of stacked receiver, if needed // r13 - interpreter linkage (if interpreted) ??? FIXME // r1 ... r0 - compiler arguments (if compiled) Label L_incompatible_class_change_error; switch (iid) { case vmIntrinsics::_linkToSpecial: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } __ ldr(rmethod, member_vmtarget); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } __ ldr(rmethod, member_vmtarget); break; case vmIntrinsics::_linkToVirtual: { // same as TemplateTable::invokevirtual, // minus the CP setup and profiling: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp3); } // pick out the vtable index from the MemberName, and then we can discard it: Register temp2_index = temp2; __ ldr(temp2_index, member_vmindex); if (VerifyMethodHandles) { Label L_index_ok; __ cmpw(temp2_index, 0U); __ br(Assembler::GE, L_index_ok); __ hlt(0); __ BIND(L_index_ok); } // Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget // at this point. And VerifyMethodHandles has already checked clazz, if needed. // get target Method* & entry point __ lookup_virtual_method(temp1_recv_klass, temp2_index, rmethod); break; } case vmIntrinsics::_linkToInterface: { // same as TemplateTable::invokeinterface // (minus the CP setup and profiling, with different argument motion) if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp3); } Register temp3_intf = temp3; __ load_heap_oop(temp3_intf, member_clazz); load_klass_from_Class(_masm, temp3_intf); __ verify_klass_ptr(temp3_intf); Register rindex = rmethod; __ ldr(rindex, member_vmindex); if (VerifyMethodHandles) { Label L; __ cmpw(rindex, 0U); __ br(Assembler::GE, L); __ hlt(0); __ bind(L); } // given intf, index, and recv klass, dispatch to the implementation method __ lookup_interface_method(temp1_recv_klass, temp3_intf, // note: next two args must be the same: rindex, rmethod, temp2, L_incompatible_class_change_error); break; } default: fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)); break; } // live at this point: rmethod, r13 (if interpreted) // After figuring out which concrete method to call, jump into it. // Note that this works in the interpreter with no data motion. // But the compiled version will require that r2_recv be shifted out. __ verify_method_ptr(rmethod); jump_from_method_handle(_masm, rmethod, temp1, for_compiler_entry); if (iid == vmIntrinsics::_linkToInterface) { __ bind(L_incompatible_class_change_error); __ far_jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); } } }
/* The actual interpreter loop */ void interp(state_t *st) { while (1) { obj_t *x, *y, *z; char *p, c; int i; unsigned long u; /* fprintf(stderr, "Executing '%c'\n", *st->pc); */ switch (c = *st->pc++) { case '\0': return; case '\r': case '\n': case '\t': case ' ': /* nop */ break; case '!': /* call */ POP(x); if (x->type != function) { error("Not a function.\n"); } else { CALL(x); decref(x); } break; case '"': /* output string */ p = skip_string(st->pc); c = *p; /* Save old character */ *p = '\0'; /* Change it to NUL */ fputs(st->pc, stdout); /* Print the string */ *p = c; /* Replace original character */ st->pc = p + 1; /* Set the PC to one past the closing quote*/ break; case '#': /* over */ POP(y); POP(x); PUS(x); PUS(y); PUSH(x); break; case '$': /* dup */ POP(x); PUS(x); PUSH(x); break; case '%': /* mod */ BINOP(mpz_mod); break; case '&': /* && */ BINBOOL(NONZERO(x) && NONZERO(y)); break; case '\'': /* Set multi */ for (p = st->pc; *p && *p != '\''; p++); st->pc = p + 1; for (p--; *p != '\''; p--) { if (*p >= 'a' && *p <= 'z') { /* local */ POP(x); i = *p - 'a'; if ((y = st->frame->vars[i]) != NULL) decref(y); st->frame->vars[i] = x; } else if (*p >= 'A' && *p <= 'Z') { /* global */ POP(x); i = *p - 'A'; if ((y = st->vars[i]) != NULL) decref(y); st->vars[i] = x; } else if (*p != '\n' && *p != '\t' && *p != ' ') { error("Not a variable: '%c'", *p); } } break; case '(': /* Comment; can't be nested */ st->pc = skip_comment(st->pc); break; case '*': /* mul */ BINOP(mpz_mul); break; case '+': /* add */ BINOP(mpz_add); break; case ',': /* print character */ POP(x); u = to_ulong(x); putchar(u); decref(x); break; case '-': /* sub */ BINOP(mpz_sub); break; case '.': /* print */ POP(x); print_obj(stdout, x); decref(x); break; case '/': /* div */ BINOP(mpz_fdiv_q); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': p = st->pc; /* Skip to the first non-digit */ while ((c = *p) >= '0' && c <= '9') p++; *p = '\0'; /* Temporarily put a NUL there */ PUS(num_new_from_str(st->pc-1)); *p = c; /* Replace original character */ st->pc = p; break; case ':': /* Set variable */ POP(x); c = *st->pc++; if (c >= 'A' && c <= 'Z') { /* global */ i = c - 'A'; if ((y = st->vars[i]) != NULL) decref(y); st->vars[i] = x; } else if (c >= 'a' && c <= 'z') { /* local */ i = c - 'a'; if ((y = st->frame->vars[i]) != NULL) decref(y); st->frame->vars[i] = x; } else { error("Not a variable: '%c'\n", *st->pc); } break; /* case ';': */ /* break; */ case '<': /* less than */ BINBOOL(mpz_cmp(*to_mpz(x), *to_mpz(y)) < 0); break; case '=': /* equal to */ BINBOOL(mpz_cmp(*to_mpz(x), *to_mpz(y)) == 0); break; case '>': /* greater than */ BINBOOL(mpz_cmp(*to_mpz(x), *to_mpz(y)) > 0); break; case '?': /* if */ POP(z); POP(y); POP(x); if (x->type != number || y->type != function || z->type != function) error("Wrong argument type."); CALL(NONZERO(x) ? y : z); decref(z); decref(y); decref(x); break; case '@': /* rot */ POP(z); POP(y); POP(x); PUS(y); PUS(z); PUS(x); break; /* global variables */ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': /* global variables */ i = c - 'A'; if ((x = st->vars[i]) == NULL) { error("Uninitialized variable '%c'\n", c); } if (x->type == function) { CALL(x); } else { PUSH(x); } break; case '[': PUS(fun_new(st->pc)); i = 1; while (*st->pc) { switch (*st->pc++) { case '"': st->pc = skip_string(st->pc) + 1; break; case '(': st->pc = skip_comment(st->pc) + 1; break; case '[': i++; break; case ']': if (--i <= 0) goto done; break; } } done: break; case '\\': /* swap */ POP(y); POP(x); PUS(y); PUS(x); break; case ']': POPRET(); break; case '^': /* trace */ print_trace(st); break; /* case '^': /\* pow *\/ */ /* POP(y); POP(x); */ /* z = num_new(); */ /* mpz_pow_ui(z->data.mpz, *to_mpz(x), to_ulong(y)); */ /* PUSH(z); */ /* decref(y); decref(x); */ /* break; *\/ */ case '_': /* neg */ POP(x); mpz_neg(*to_mpz(x), x->data.mpz); PUS(x); break; case '`': /* drop */ POP(x); decref(x); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': /* local variables */ i = c - 'a'; if ((x = st->frame->vars[i]) == NULL) { error("Uninitialized variable '%c'\n", c); } if (x->type == function) { CALL(x); } else { PUSH(x); } break; /* case '{': */ /* break; */ case '|': /* or */ BINBOOL(NONZERO(x) || NONZERO(y)); break; /* case '}': */ /* break; */ case '~': /* not */ POP(x); PUSH(ZERO(x) ? one : zero); decref(x); break; default: error("Undefined token '%c'\n", c); } } }