/** execute_statement Execute a Cx statement * * @param p_function_id : ptr to the routine symtab node */ void cx_executor::execute_statement(cx_symtab_node *p_function_id) { if (token != tc_left_bracket) { ++statement_count; trace_statement(); } switch (token) { case tc_identifier: { if (p_node->defn.how == dc_function) { execute_function_call(p_node); } else { cx_symtab_node *p_var = p_node; get_token(); if (token_in(token, tokenlist_assign_ops)) { execute_assignment(p_var); } else { execute_variable(p_var, false); pop(); } } } break; case tc_DO: execute_DO(p_function_id); break; case tc_WHILE: execute_WHILE(p_function_id); break; case tc_IF: execute_IF(p_function_id); break; case tc_FOR: execute_FOR(p_function_id); break; case tc_SWITCH: //parse_SWITCH(); break; case tc_CASE: case tc_DEFAULT://parse_case_label(); break; case tc_BREAK: get_token(); break_loop = true; break; case tc_left_bracket: execute_compound(p_function_id); break; case tc_RETURN: execute_RETURN(p_function_id); break; default: break; } }
/** execute_actual_parameters Execute the actual parameters of * a declared subroutine call. * * @param p_function_id : ptr to the subroutine name's symtab node */ void cx_executor::execute_actual_parameters (cx_symtab_node *p_function_id) { cx_symtab_node *p_formal_id; // ptr to formal parm's symtab node // Loop to execute each actual parameter. for (p_formal_id = p_function_id->defn.routine.locals.p_parms_ids; p_formal_id; p_formal_id = p_formal_id->next__) { cx_type *p_formal_type = p_formal_id->p_type; get_token(); /* Reference parameter: execute_variable will leave the actual * parameter's address on top of the stack. */ if (p_formal_id->defn.how == dc_reference) { const int size = p_node->p_type->size; p_formal_type->form = p_node->p_type->form; execute_variable(p_node, true); if (p_formal_type->form == fc_array) { p_formal_type->size = size; p_formal_type->array.element_count = size; p_formal_type->array.max_index = size; p_formal_id->runstack_item = top(); } else { p_formal_id->runstack_item = top(); } get_token(); }// value parameter else { cx_type *p_actual_type = execute_expression(); if ((p_formal_type == p_float_type) && (p_actual_type->base_type() == p_integer_type)) { // real formal := integer actual: // convert integer value to real. float ff = top()->basic_types.int__; pop(); push(ff); p_formal_id->runstack_item = top(); } else if (!p_formal_type->is_scalar_type()) { /* Formal parameter is an array or a record: * Make a copy of the actual parameter's value. */ const int size = p_actual_type->size; void *p_target_address = nullptr; const int num_of_elements = size / p_actual_type->base_type()->size; p_target_address = realloc(p_target_address, size); //memset(p_target_address, 0, size); if (p_target_address == nullptr) { perror("realloc"); exit(0); } void *p_source = top()->basic_types.addr__; memcpy(p_target_address, p_source, size); pop(); push(p_target_address); p_formal_type->array.element_count = num_of_elements; p_formal_type->array.max_index = num_of_elements; p_formal_type->size = size; p_formal_type->form = fc_array; p_formal_id->runstack_item = top(); } else { // Range check an integer or enumeration // formal parameter. range_check(p_formal_type, top()->basic_types.int__); p_formal_id->runstack_item = top(); } } } if (token == tc_left_paren) get_token(); }