// // INIT_WORD_INDEX_Debug: C // void INIT_WORD_INDEX_Debug(RELVAL *v, REBCNT i) { assert(ANY_WORD(v)); assert(GET_VAL_FLAG((v), WORD_FLAG_BOUND)); if (IS_RELATIVE(v)) assert( VAL_WORD_CANON(v) == VAL_PARAM_CANON(FUNC_PARAM(VAL_WORD_FUNC(v), i)) ); else assert( VAL_WORD_CANON(v) == CTX_KEY_CANON(VAL_WORD_CONTEXT(KNOWN(v)), i) ); v->payload.any_word.index = i; }
// // Make_Context_For_Action_Push_Partials: C // // This creates a FRAME! context with NULLED cells in the unspecialized slots // that are available to be filled. For partial refinement specializations // in the action, it will push the refinement to the stack. In this way it // retains the ordering information implicit in the partial refinements of an // action's existing specialization. // // It is able to take in more specialized refinements on the stack. These // will be ordered *after* partial specializations in the function already. // The caller passes in the stack pointer of the lowest priority refinement, // which goes up to DSP for the highest of those added specializations. // // Since this is walking the parameters to make the frame already--and since // we don't want to bind to anything specialized out (including the ad-hoc // refinements added on the stack) we go ahead and collect bindings from the // frame if needed. // REBCTX *Make_Context_For_Action_Push_Partials( const REBVAL *action, // need ->binding, so can't just be a REBACT* REBDSP lowest_ordered_dsp, // caller can add refinement specializations struct Reb_Binder *opt_binder, REBFLGS prep // cell formatting mask bits, result managed if non-stack ){ REBDSP highest_ordered_dsp = DSP; REBACT *act = VAL_ACTION(action); REBCNT num_slots = ACT_NUM_PARAMS(act) + 1; // +1 is for CTX_ARCHETYPE() REBARR *varlist = Make_Array_Core(num_slots, SERIES_MASK_VARLIST); REBVAL *rootvar = RESET_CELL( ARR_HEAD(varlist), REB_FRAME, CELL_MASK_CONTEXT ); INIT_VAL_CONTEXT_VARLIST(rootvar, varlist); INIT_VAL_CONTEXT_PHASE(rootvar, VAL_ACTION(action)); INIT_BINDING(rootvar, VAL_BINDING(action)); const REBVAL *param = ACT_PARAMS_HEAD(act); REBVAL *arg = rootvar + 1; const REBVAL *special = ACT_SPECIALTY_HEAD(act); // of exemplar/paramlist REBCNT index = 1; // used to bind REFINEMENT! values to parameter slots REBCTX *exemplar = ACT_EXEMPLAR(act); // may be null if (exemplar) assert(special == CTX_VARS_HEAD(exemplar)); else assert(special == ACT_PARAMS_HEAD(act)); for (; NOT_END(param); ++param, ++arg, ++special, ++index) { arg->header.bits = prep; if (Is_Param_Hidden(param)) { // specialized out assert(GET_CELL_FLAG(special, ARG_MARKED_CHECKED)); Move_Value(arg, special); // doesn't copy ARG_MARKED_CHECKED SET_CELL_FLAG(arg, ARG_MARKED_CHECKED); continue_specialized: assert(not IS_NULLED(arg)); assert(GET_CELL_FLAG(arg, ARG_MARKED_CHECKED)); continue; // Eval_Core() double-checks type in debug build } assert(NOT_CELL_FLAG(special, ARG_MARKED_CHECKED)); REBSTR *canon = VAL_PARAM_CANON(param); // for adding to binding if (not TYPE_CHECK(param, REB_TS_REFINEMENT)) { // nothing to push continue_unspecialized: assert(arg->header.bits == prep); Init_Nulled(arg); if (opt_binder) { if (not Is_Param_Unbindable(param)) Add_Binder_Index(opt_binder, canon, index); } continue; } // Unspecialized refinement slots may have an SYM-WORD! in them that // reflects a partial that needs to be pushed to the stack. (They // are in *reverse* order of use.) assert( (special == param and IS_PARAM(special)) or (IS_SYM_WORD(special) or IS_NULLED(special)) ); if (IS_SYM_WORD(special)) { REBCNT partial_index = VAL_WORD_INDEX(special); Init_Any_Word_Bound( // push a SYM-WORD! to data stack DS_PUSH(), REB_SYM_WORD, VAL_STORED_CANON(special), exemplar, partial_index ); } // Unspecialized or partially specialized refinement. Check the // passed-in refinements on the stack for usage. // REBDSP dsp = highest_ordered_dsp; for (; dsp != lowest_ordered_dsp; --dsp) { REBVAL *ordered = DS_AT(dsp); if (VAL_STORED_CANON(ordered) != canon) continue; // just continuing this loop assert(not IS_WORD_BOUND(ordered)); // we bind only one INIT_BINDING(ordered, varlist); INIT_WORD_INDEX_UNCHECKED(ordered, index); if (not Is_Typeset_Invisible(param)) // needs argument goto continue_unspecialized; // If refinement named on stack takes no arguments, then it can't // be partially specialized...only fully, and won't be bound: // // specialize 'append/only [only: false] ; only not bound // Init_Word(arg, VAL_STORED_CANON(ordered)); Refinify(arg); SET_CELL_FLAG(arg, ARG_MARKED_CHECKED); goto continue_specialized; } goto continue_unspecialized; } TERM_ARRAY_LEN(varlist, num_slots); MISC_META_NODE(varlist) = nullptr; // GC sees this, we must initialize // !!! Can't pass SERIES_FLAG_STACK_LIFETIME into Make_Array_Core(), // because TERM_ARRAY_LEN won't let it set stack array lengths. // if (prep & CELL_FLAG_STACK_LIFETIME) SET_SERIES_FLAG(varlist, STACK_LIFETIME); INIT_CTX_KEYLIST_SHARED(CTX(varlist), ACT_PARAMLIST(act)); return CTX(varlist); }