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; }
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); }
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; }
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); } }
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; }
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); } }
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); } }
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); } }
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())); }
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))); }
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; }