Ejemplo n.º 1
0
void for_loop_finish_iteration(Stack* context)
{
    Frame* frame = top_frame(context);
    Branch* contents = frame->branch;

    // Find list length
    caValue* listInput = get_frame_register(frame, 0);

    // Increment the loop index
    caValue* index = get_frame_register(frame, for_loop_find_index(contents)->index);
    set_int(index, as_int(index) + 1);

    // Check if we are finished
    if (as_int(index) >= list_length(listInput)) {
        frame->loop = false;
        finish_frame(context);
        return;
    }

    // If we're not finished yet, copy rebound outputs back to inputs.
    for (int i=1;; i++) {
        Term* input = get_input_placeholder(contents, i);
        if (input == NULL)
            break;
        Term* output = get_output_placeholder(contents, i);
        copy(get_frame_register(frame, output->index),
            get_frame_register(frame, input->index));
    }

    // Return to start of loop body
    frame->pc = 0;
    frame->nextPc = 0;
}
Ejemplo n.º 2
0
void for_loop_remake_zero_branch(Branch* forContents)
{
    Branch* zero = for_loop_get_zero_branch(forContents);
    clear_branch(zero);

    // Clone inputs
    for (int i=0;; i++) {
        Term* placeholder = get_input_placeholder(forContents, i);
        if (placeholder == NULL)
            break;
        Term* clone = append_input_placeholder(zero);
        rename(clone, placeholder->nameSymbol);
    }

    Term* loopOutput = create_list(zero);

    // Clone outputs
    for (int i=0;; i++) {
        Term* placeholder = get_output_placeholder(forContents, i);
        if (placeholder == NULL)
            break;

        // Find the appropriate connection
        Term* result = find_local_name(zero, placeholder->name.c_str());

        if (i == 0)
            result = loopOutput;

        Term* clone = append_output_placeholder(zero, result);
        rename(clone, placeholder->nameSymbol);
    }

    branch_finish_changes(zero);
}
Ejemplo n.º 3
0
Term* if_block_append_case(Term* ifBlock, Term* input)
{
    Branch* contents = nested_contents(ifBlock);
    int insertPos = 0;
    for (int i=0; i < contents->length(); i++) {
        Term* term = contents->get(i);

        if (term->function == FUNCS.input)
            insertPos = term->index + 1;

        // Insert position is right after the last non-default case.
        if (term->function == FUNCS.case_func && term->input(0) != NULL)
            insertPos = term->index + 1;
    }

    Term* newCase = apply(contents, FUNCS.case_func, TermList(input));
    contents->move(newCase, insertPos);

    // Add existing input placeholders to this case
    for (int i=0;; i++) {
        Term* placeholder = get_input_placeholder(contents, i);
        if (placeholder == NULL) break;
        Term* localPlaceholder = append_input_placeholder(nested_contents(newCase));
        change_declared_type(localPlaceholder, placeholder->type);
    }

    return newCase;
}
Ejemplo n.º 4
0
void if_block_fix_outer_pointers(Term* ifCall, Branch* caseContents)
{
    // disable this
    return;

    Branch* contents = nested_contents(ifCall);

    for (OuterInputIterator it(caseContents); it.unfinished(); ++it) {

        // Don't worry about outer pointers to values. (This should probably be
        // standard behavior)
        if (is_value(it.currentTerm()))
            continue;

        // Fetch values from OuterInputIterator, while it's safe. The iterator
        // may get confused soon, due to inserted terms.
        Term* currentTerm = it.currentTerm();
        Term* input = it.currentInput();
        int currentInputIndex = it.currentInputIndex();

        // Check if this pointer goes outside the if-block. If so, we'll have to
        // find the corresponding placeholder (or create a new one).
        if (input->owningBranch != contents) {

            Term* placeholder = NULL;

            int inputIndex = find_input_index_for_pointer(ifCall, input);
            if (inputIndex >= 0) {
                placeholder = get_input_placeholder(contents, inputIndex);
            } else {
                // Create a new placeholder
                // This call will result in an inserted term, which will confuse
                // our OuterInputIterator. So, don't use the iterator again until
                // the next iteration.
                placeholder = if_block_add_input(ifCall, input);
            }

            input = placeholder;
        }

        // Now 'input' points to an if-block placeholder, remap it to the case-local
        // placeholder.
        Term* caseLocal = get_input_placeholder(caseContents, input->index);
        ca_assert(caseLocal != NULL);
        set_input(currentTerm, currentInputIndex, caseLocal);
    }
}
Ejemplo n.º 5
0
Type* get_input_type(Block* block, int index)
{
    bool varArgs = has_variable_args(block);
    if (varArgs)
        index = 0;

    Term* placeholder = get_input_placeholder(block, index);
    if (placeholder == NULL)
        return NULL;

    return placeholder->type;
}
Ejemplo n.º 6
0
void Block__inputs(VM* vm)
{
    Block* block = as_block(vm->input(0));
    Value* output = vm->output();
    set_list(output, 0);
    for (int i=0;; i++) {
        Term* term = get_input_placeholder(block, i);
        if (term == NULL)
            break;
        set_term_ref(list_append(output), term);
    }
}
Ejemplo n.º 7
0
void Branch__inputs(caStack* stack)
{
    Branch* branch = as_branch(circa_input(stack, 0));
    caValue* output = circa_output(stack, 0);
    set_list(output, 0);
    for (int i=0;; i++) {
        Term* term = get_input_placeholder(branch, i);
        if (term == NULL)
            break;
        set_term_ref(list_append(output), term);
    }
}
Ejemplo n.º 8
0
void if_block_turn_outer_name_rebinds_into_outputs(Term* ifCall, Branch *caseBranch)
{
    Branch* mainBranch = nested_contents(ifCall);
    Branch* outerBranch = ifCall->owningBranch;

    for (int i=0; i < caseBranch->length(); i++) {
        Term* term = caseBranch->get(i);
        if (term->name == "")
            continue;

        const char* name = term->name.c_str();
        Term* outer = find_name(outerBranch, name);
        if (outer == NULL)
            continue;

        // This term rebinds an outer name.

        // First, bring in the outer name as an input to the branch.

        // Check if we already have an output for this name.
        Term* inputPlaceholder = find_input_placeholder_with_name(mainBranch, name);

        // Create it if necessary
        if (inputPlaceholder == NULL) {
            inputPlaceholder = if_block_add_input(ifCall, outer);
            rename(inputPlaceholder, name);

            // Fix the new input placeholders to have the correct name and input.
            for (CaseIterator it(mainBranch); it.unfinished(); it.advance()) {
                Branch* caseContents = nested_contents(it.current());
                Term* casePlaceholder = get_input_placeholder(caseContents,
                                        inputPlaceholder->index);
                ca_assert(casePlaceholder != NULL);
                rename(casePlaceholder, name);
            }
        }

        // Now make sure there is an output placeholder for this name.
        Term* outputPlaceholder = find_output_placeholder_with_name(mainBranch, name);

        if (outputPlaceholder == NULL)
            outputPlaceholder = if_block_add_output_for_name(ifCall, name);
    }
}
Ejemplo n.º 9
0
void Block__input(VM* vm)
{
    Block* block = as_block(vm->input(0));
    set_term_ref(vm->output(),
        get_input_placeholder(block, vm->input(1)->as_i()));
}
Ejemplo n.º 10
0
void Branch__input(caStack* stack)
{
    Branch* branch = as_branch(circa_input(stack, 0));
    set_term_ref(circa_output(stack, 0),
        get_input_placeholder(branch, circa_int_input(stack, 1)));
}
Ejemplo n.º 11
0
void for_loop_finish_iteration(Stack* stack, bool enableLoopOutput)
{
    INCREMENT_STAT(LoopFinishIteration);

    Frame* frame = top_frame(stack);
    Branch* contents = frame->branch;

    // Find list length
    caValue* listInput = get_frame_register(frame, 0);

    // Increment the loop index
    caValue* index = get_top_register(stack, for_loop_find_index(contents));
    set_int(index, as_int(index) + 1);

    // Preserve list output
    if (enableLoopOutput && frame->exitType != name_Discard) {
        caValue* outputIndex = get_frame_register(frame, for_loop_find_output_index(contents));

        Term* outputPlaceholder = get_output_placeholder(contents, 0);
        caValue* outputList = get_frame_register(frame, outputPlaceholder);
        caValue* outputValue = find_stack_value_for_term(stack, outputPlaceholder->input(0), 0);

        if (!is_list(outputList))
            set_list(outputList);
        list_touch(outputList);
        copy(outputValue, list_get(outputList, as_int(outputIndex)));

        INCREMENT_STAT(LoopWriteOutput);

        // Advance output index
        set_int(outputIndex, as_int(outputIndex) + 1);
    }

    // Check if we are finished
    if (as_int(index) >= list_length(listInput)
            || frame->exitType == name_Break
            || frame->exitType == name_Return) {

        // Possibly truncate output list, in case any elements were discarded.
        if (enableLoopOutput) {
            caValue* outputIndex = get_frame_register(frame, for_loop_find_output_index(contents));
            Term* outputPlaceholder = get_output_placeholder(contents, 0);
            caValue* outputList = get_frame_register(frame, outputPlaceholder);
            list_resize(outputList, as_int(outputIndex));
        } else {
            Term* outputPlaceholder = get_output_placeholder(contents, 0);
            caValue* outputList = get_frame_register(frame, outputPlaceholder);
            set_list(outputList, 0);
        }
        
        finish_frame(stack);
        return;
    }

    // If we're not finished yet, copy rebound outputs back to inputs.
    for (int i=1;; i++) {
        Term* input = get_input_placeholder(contents, i);
        if (input == NULL)
            break;
        Term* output = get_output_placeholder(contents, i);
        copy(get_frame_register(frame, output),
            get_frame_register(frame, input));

        INCREMENT_STAT(Copy_LoopCopyRebound);
    }

    // Return to start of loop body
    frame->pc = 0;
    frame->nextPc = 0;
    frame->exitType = name_None;
}