Exemplo n.º 1
0
//
//  Reduce_Any_Array_Throws: C
//
// Reduce array from the index position specified in the value.
//
// If `into` then splice into the existing `out`.  Otherwise, overwrite the
// `out` with all values collected from the stack, into an array matching the
// type of the input.  So [1 + 1 2 + 2] => [3 4], and 1/+/1/2/+/2 => 3/4
//
REBOOL Reduce_Any_Array_Throws(
    REBVAL *out,
    REBVAL *any_array,
    REBOOL into
) {
    REBDSP dsp_orig = DSP;

    Reb_Enumerator e;
    PUSH_SAFE_ENUMERATOR(&e, any_array); // REDUCE-ing could disrupt any-array

    while (NOT_END(e.value)) {
        UPDATE_EXPRESSION_START(&e); // informs the error delivery better

        REBVAL reduced;
        DO_NEXT_REFETCH_MAY_THROW(&reduced, &e, DO_FLAG_NORMAL);
        if (THROWN(&reduced)) {
            *out = reduced;
            DS_DROP_TO(dsp_orig);
            DROP_SAFE_ENUMERATOR(&e);
            return TRUE;
        }

        if (IS_VOID(&reduced)) {
            //
            // !!! Review if there should be a form of reduce which allows
            // void expressions.  The general feeling is that it shouldn't
            // be allowed by default, since N expressions would not make N
            // results...and reduce is often used for positional purposes.
            // Substituting anything (like a NONE!, or anything else) would
            // perhaps be disingenuous.
            //
            fail (Error(RE_REDUCE_MADE_VOID));
        }

        DS_PUSH(&reduced);
    }

    if (into)
        Pop_Stack_Values_Into(out, dsp_orig);
    else
        Val_Init_Array(out, VAL_TYPE(any_array), Pop_Stack_Values(dsp_orig));

    DROP_SAFE_ENUMERATOR(&e);
    return FALSE;
}
Exemplo n.º 2
0
//
//  Compose_Any_Array_Throws: C
//
// Compose a block from a block of un-evaluated values and GROUP! arrays that
// are evaluated.  This calls into Do_Core, so if 'into' is provided, then its
// series must be protected from garbage collection.
//
//     deep - recurse into sub-blocks
//     only - parens that return blocks are kept as blocks
//
// Writes result value at address pointed to by out.
//
REBOOL Compose_Any_Array_Throws(
    REBVAL *out,
    const REBVAL *any_array,
    REBOOL deep,
    REBOOL only,
    REBOOL into
) {
    REBDSP dsp_orig = DSP;

    Reb_Enumerator e;
    PUSH_SAFE_ENUMERATOR(&e, any_array); // evaluating could disrupt any_array

    while (NOT_END(e.value)) {
        UPDATE_EXPRESSION_START(&e); // informs the error delivery better

        if (IS_GROUP(e.value)) {
            //
            // We evaluate here, but disable lookahead so it only evaluates
            // the GROUP! and doesn't trigger errors on what's after it.
            //
            REBVAL evaluated;
            DO_NEXT_REFETCH_MAY_THROW(&evaluated, &e, DO_FLAG_NO_LOOKAHEAD);
            if (THROWN(&evaluated)) {
                *out = evaluated;
                DS_DROP_TO(dsp_orig);
                DROP_SAFE_ENUMERATOR(&e);
                return TRUE;
            }

            if (IS_BLOCK(&evaluated) && !only) {
                //
                // compose [blocks ([a b c]) merge] => [blocks a b c merge]
                //
                RELVAL *push = VAL_ARRAY_AT(&evaluated);
                while (NOT_END(push)) {
                    //
                    // `evaluated` is known to be specific, but its specifier
                    // may be needed to derelativize its children.
                    //
                    DS_PUSH_RELVAL(push, VAL_SPECIFIER(&evaluated));
                    push++;
                }
            }
            else if (!IS_VOID(&evaluated)) {
                //
                // compose [(1 + 2) inserts as-is] => [3 inserts as-is]
                // compose/only [([a b c]) unmerged] => [[a b c] unmerged]
                //
                DS_PUSH(&evaluated);
            }
            else {
                //
                // compose [(print "Voids *vanish*!")] => []
                //
            }
        }
        else if (deep) {
            if (IS_BLOCK(e.value)) {
                //
                // compose/deep [does [(1 + 2)] nested] => [does [3] nested]

                REBVAL specific;
                COPY_VALUE(&specific, e.value, e.specifier);

                REBVAL composed;
                if (Compose_Any_Array_Throws(
                    &composed,
                    &specific,
                    TRUE,
                    only,
                    into
                )) {
                    *out = composed;
                    DS_DROP_TO(dsp_orig);
                    DROP_SAFE_ENUMERATOR(&e);
                    return TRUE;
                }

                DS_PUSH(&composed);
            }
            else {
                if (ANY_ARRAY(e.value)) {
                    //
                    // compose [copy/(orig) (copy)] => [copy/(orig) (copy)]
                    // !!! path and second group are copies, first group isn't
                    //
                    REBARR *copy = Copy_Array_Shallow(
                        VAL_ARRAY(e.value),
                        IS_RELATIVE(e.value)
                            ? e.specifier // use parent specifier if relative...
                            : VAL_SPECIFIER(const_KNOWN(e.value)) // else child's
                    );
                    DS_PUSH_TRASH;
                    Val_Init_Array_Index(
                        DS_TOP, VAL_TYPE(e.value), copy, VAL_INDEX(e.value)
                    ); // ...manages
                }
                else
                    DS_PUSH_RELVAL(e.value, e.specifier);
            }
            FETCH_NEXT_ONLY_MAYBE_END(&e);
        }
        else {
            //
            // compose [[(1 + 2)] (reverse "wollahs")] => [[(1 + 2)] "shallow"]
            //
            DS_PUSH_RELVAL(e.value, e.specifier);
            FETCH_NEXT_ONLY_MAYBE_END(&e);
        }
    }

    if (into)
        Pop_Stack_Values_Into(out, dsp_orig);
    else
        Val_Init_Array(out, VAL_TYPE(any_array), Pop_Stack_Values(dsp_orig));

    DROP_SAFE_ENUMERATOR(&e);
    return FALSE;
}
Exemplo n.º 3
0
    if (f->indexor != END_FLAG) {
        while (NOT_END(value = va_arg(*f->source.vaptr, const REBVAL*)))
            DS_PUSH(value);

        if (truncated)
            f->indexor = 1; // skip the --optimized-out--
        else
            f->indexor = 0; // position at the start of the extracted values
    }
    else {
        // Leave at the END_FLAG, but give back the array to serve as
        // notice of the truncation (if it was truncated)
    }

    if (DSP != dsp_orig) {
        f->source.array = Pop_Stack_Values(dsp_orig);
        MANAGE_ARRAY(f->source.array); // held alive while frame running
    }
    else
        f->source.array = EMPTY_ARRAY; // doesn't need to be unique

    // We clear the DO_FLAG_VALIST, assuming that the truncation marker is
    // enough information to record the fact that it was a va_list (revisit
    // if there's another reason to know what it was...)

    f->flags &= ~DO_FLAG_VALIST;
}


//
//  Do_Va_Core: C