Block* find_block_that_exit_point_will_reach(Term* term) { ca_assert(is_exit_point(term)); Block* block = term->owningBlock; // 'return' exits to nearest major block. if (term->function == FUNCS.return_func) { while (is_minor_block(block)) { Block* parent = get_parent_block(block); if (parent == NULL) return block; block = parent; } return block; } // 'case_condition_bool' exits the current if-block. if (term->function == FUNCS.case_condition_bool) return get_parent_block(term->owningBlock); // Otherwise, exit to nearest for-loop. while (!is_for_loop(block) && !is_while_loop(block)) { Block* parent = get_parent_block(block); if (parent == NULL) return block; block = parent; } return block; }
Block* find_enclosing_loop(Block* block) { while (true) { if (block == NULL) return NULL; if (is_while_loop(block) || is_for_loop(block)) return block; if (is_major_block(block)) return NULL; block = get_parent_block(block); } return NULL; }
void start_for_loop(caStack* stack, bool enableLoopOutput) { Frame* frame = top_frame(stack); Branch* contents = frame->branch; // Check if top frame actually contains a for-loop (it might be using the #zero branch) if (!is_for_loop(contents)) return; // Initialize the loop index set_int(get_frame_register(frame, for_loop_find_index(contents)), 0); if (enableLoopOutput) { // Initialize output value set_int(get_frame_register(frame, for_loop_find_output_index(contents)), 0); caValue* listInput = circa_input(stack, 0); set_list(get_frame_register_from_end(frame, 0), list_length(listInput)); } // Interpreter will run the contents of the branch }
bool is_loop(Block* block) { return is_for_loop(block) || is_while_loop(block); }
void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt) { switch(ivl_statement_type(stmt)) { case IVL_ST_NOOP: /* If this is a statement termination then just finish the * statement, otherwise print an empty begin/end pair. */ if (single_indent) { single_indent = 0; fprintf(vlog_out, ";\n"); } else { fprintf(vlog_out, "%*cbegin\n", get_indent(), ' '); fprintf(vlog_out, "%*cend\n", get_indent(), ' '); } break; case IVL_ST_ALLOC: /* This statement is only used with an automatic task so we * can safely skip it. The automatic task definition will * generate an appropriate error message.*/ break; case IVL_ST_ASSIGN: emit_stmt_assign(scope, stmt); break; case IVL_ST_ASSIGN_NB: emit_stmt_assign_nb(scope, stmt); break; case IVL_ST_BLOCK: if (ivl_stmt_block_scope(stmt)) { emit_stmt_block_named(scope, stmt); } else { if (is_delayed_or_event_assign(scope, stmt)) break; if (is_for_loop(scope, stmt)) break; if (is_repeat_event_assign(scope, stmt)) break; if (is_wait(scope, stmt)) break; if (is_utask_call_with_args(scope, stmt)) break; emit_stmt_block(scope, stmt); } break; case IVL_ST_CASE: case IVL_ST_CASER: case IVL_ST_CASEX: case IVL_ST_CASEZ: emit_stmt_case(scope, stmt); break; case IVL_ST_CASSIGN: emit_stmt_cassign(scope, stmt); break; case IVL_ST_CONDIT: emit_stmt_condit(scope, stmt); break; case IVL_ST_DEASSIGN: emit_stmt_deassign(scope, stmt); break; case IVL_ST_DELAY: emit_stmt_delay(scope, stmt); break; case IVL_ST_DELAYX: emit_stmt_delayx(scope, stmt); break; case IVL_ST_DISABLE: emit_stmt_disable(scope, stmt); break; case IVL_ST_FORCE: emit_stmt_force(scope, stmt); break; case IVL_ST_FOREVER: emit_stmt_forever(scope, stmt); break; case IVL_ST_FORK: if (ivl_stmt_block_scope(stmt)) { emit_stmt_fork_named(scope, stmt); } else { emit_stmt_fork(scope, stmt); } break; case IVL_ST_FREE: /* This statement is only used with an automatic task so we * can safely skip it. The automatic task definition will * generate an appropriate error message.*/ break; case IVL_ST_RELEASE: emit_stmt_release(scope, stmt); break; case IVL_ST_REPEAT: emit_stmt_repeat(scope, stmt); break; case IVL_ST_STASK: emit_stmt_stask(scope, stmt); break; case IVL_ST_TRIGGER: emit_stmt_trigger(scope, stmt); break; case IVL_ST_UTASK: emit_stmt_utask(scope, stmt); break; case IVL_ST_WAIT: emit_stmt_wait(scope, stmt); break; case IVL_ST_WHILE: emit_stmt_while(scope, stmt); break; default: fprintf(vlog_out, "%*c<unknown>;\n", get_indent(), ' '); fprintf(stderr, "%s:%u: vlog95 error: Unknown statement " "type (%d).\n", ivl_stmt_file(stmt), ivl_stmt_lineno(stmt), (int)ivl_statement_type(stmt)); vlog_errors += 1; break; } }