Esempio n. 1
0
void module_always_has_primary_output()
{
    test_write_fake_file("module.ca", 1, "1");

    Block block;
    load_script(&block, "module.ca");

    test_assert(get_output_placeholder(&block, 0) != NULL);
    test_assert(get_output_placeholder(&block, 0)->input(0) == NULL);
}
Esempio 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);
}
Esempio n. 3
0
void load_script(Block* block, const char* filename)
{
    // Store the filename
    set_string(block_insert_property(block, s_filename), filename);

    // Read the text file
    circa::Value contents;
    circa_read_file(block->world, filename, &contents);

    if (is_null(&contents)) {
        Value msg;
        set_string(&msg, "File not found: ");
        string_append(&msg, filename);
        Term* term = create_string(block, as_cstring(&msg));
        apply(block, FUNCS.error, TermList(term));
        return;
    }

    parse(block, parse_statement_list, &contents);

    // Make sure the block has a primary output.
    if (get_output_placeholder(block, 0) == NULL)
        append_output_placeholder(block, NULL);

    update_static_error_list(block);

    return;
}
Esempio n. 4
0
void finish_if_block(Term* ifBlock)
{
    Branch* contents = nested_contents(ifBlock);

    // Make sure there is a primary output
    if (get_output_placeholder(contents, 0) == NULL)
        if_block_prepend_primary_output(ifBlock);

    if_block_normalize_state_inputs(ifBlock);

    int caseIndex = 0;
    for (CaseIterator it(contents); it.unfinished(); it.advance()) {
        Term* term = it.current();
        if_block_turn_outer_name_rebinds_into_outputs(ifBlock, nested_contents(term));
        if_block_fix_outer_pointers(ifBlock, nested_contents(term));
        modify_branch_so_that_state_access_is_indexed(nested_contents(term), caseIndex);
        caseIndex++;
    }

    if_block_turn_common_rebinds_into_outputs(ifBlock);

    if_block_update_output_placeholder_types_from_cases(ifBlock);
    check_to_insert_implicit_inputs(ifBlock);
    update_extra_outputs(ifBlock);
}
Esempio n. 5
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;
}
Esempio n. 6
0
void loop_update_continue_inputs(Branch* branch, Term* continueTerm)
{
    for (int i=0;; i++) {
        Term* output = get_output_placeholder(branch, i);
        if (output == NULL)
            break;
        set_input(continueTerm, i,
            find_intermediate_result_for_output(continueTerm, output));
    }
}
Esempio n. 7
0
void load_script_from_text(Block* block, const char* text)
{
    parse(block, parse_statement_list, text);

    // Make sure the block has a primary output.
    if (get_output_placeholder(block, 0) == NULL)
        append_output_placeholder(block, NULL);

    update_static_error_list(block);
}
Esempio n. 8
0
void Block__outputs(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_output_placeholder(block, i);
        if (term == NULL)
            break;
        set_term_ref(list_append(output), term);
    }
}
Esempio n. 9
0
void Branch__outputs(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_output_placeholder(branch, i);
        if (term == NULL)
            break;
        set_term_ref(list_append(output), term);
    }
}
Esempio n. 10
0
Type* get_output_type(Block* block, int index)
{
    if (block == NULL)
        return TYPES.any;

    // If there's no output_placeholder, then we are probably still building this
    // function.
    Term* placeholder = get_output_placeholder(block, index);
    if (placeholder == NULL)
        return TYPES.any;

    return placeholder->type;
}
Esempio n. 11
0
void if_block_update_output_placeholder_types_from_cases(Term* ifBlock)
{
    Branch* masterContents = nested_contents(ifBlock);

    for (int outputIndex=0;; outputIndex++) {
        Term* masterPlaceholder = get_output_placeholder(masterContents, outputIndex);
        if (masterPlaceholder == NULL)
            return;

        List types;

        // Iterate through each case, and collect the output types
        for (int i=0; i < masterContents->length(); i++) {
            Term* term = masterContents->get(i);
            if (term->function != FUNCS.case_func)
                continue;
            Term* placeholder = get_output_placeholder(nested_contents(term), outputIndex);
            set_type(types.append(), placeholder->type);
        }

        change_declared_type(masterPlaceholder, find_common_type(&types));
    }
}
Esempio n. 12
0
Term* if_block_add_output_for_name(Term* ifCall, const char* name)
{
    // Fix the new output placeholders to have the correct name and input.
    Branch* mainBranch = nested_contents(ifCall);
    int outputCount = count_output_placeholders(mainBranch);
    Term* outputPlaceholder = if_block_append_output(ifCall);
    rename(outputPlaceholder, name);

    for (CaseIterator it(mainBranch); it.unfinished(); it.advance()) {
        Branch* caseContents = nested_contents(it.current());
        Term* casePlaceholder = get_output_placeholder(caseContents, outputCount);
        ca_assert(casePlaceholder != NULL);
        ca_assert(casePlaceholder->name == "");
        rename(casePlaceholder, name);
        set_input(casePlaceholder, 0, find_name_at(casePlaceholder, name));
        respecialize_type(casePlaceholder);
    }
    return outputPlaceholder;
}
Esempio n. 13
0
void update_derived_inputs_for_exit_point(Term* term)
{
    // Make sure that this exit point includes every block output as an input.
    // The intermediate value might be different at this location.

    Block* block = find_block_that_exit_point_will_reach(term);
    
    for (int i=0;; i++) {
        Term* inputResult = get_output_placeholder(block, i);
        if (inputResult == NULL)
            break;

        // Don't touch input if it's explicit.
        if (i < term->numInputs() && !is_input_implicit(term, i))
            continue;

        Term* intermediateValue = find_intermediate_result_for_output(term, inputResult);

        set_input(term, i, intermediateValue);
        set_input_implicit(term, i, true);
        set_input_hidden(term, i, true);
    }
}
Esempio n. 14
0
void if_block_post_setup(Term* ifCall)
{
    Branch* contents = nested_contents(ifCall);
    if (get_output_placeholder(contents, 0) == NULL)
        apply(contents, FUNCS.output, TermList(NULL));
}
Esempio n. 15
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;
}
Esempio n. 16
0
void Branch__output(caStack* stack)
{
    Branch* branch = as_branch(circa_input(stack, 0));
    set_term_ref(circa_output(stack, 0),
        get_output_placeholder(branch, circa_int_input(stack, 1)));
}
Esempio n. 17
0
void Block__output_placeholder(VM* vm)
{
    Block* block = as_block(vm->input(0));
    Term* placeholder = get_output_placeholder(block, vm->input(1)->as_i());
    set_term_ref(vm->output(), placeholder);
}