/*add vars defined in a func param list into var table *return param numbers*/ int init_param_list(struct var_descriptor* param_list_head, struct tree_node* varlist_node){ assert(varlist_node -> unit_code == VarList); assert(param_list_head != NULL); int num = 0; struct var_descriptor* prev_var = param_list_head; while(true){ //treate all params as global vars struct tree_node* specifier_node = varlist_node -> child -> child; struct tree_node* vardec_node = specifier_node -> sibling; struct var_descriptor* new_var = create_variable(specifier_node, vardec_node, var_table_head, false); if(new_var != NULL){ //insert param into param list in order(not insert after head) num ++; struct var_descriptor* new_var_copy = create_var_descriptor(new_var -> var_name, new_var -> var_type, new_var -> var_array); prev_var -> next = new_var_copy; prev_var = new_var_copy; } if(varlist_node -> child -> sibling != NULL) varlist_node = varlist_node -> child -> sibling -> sibling; else break; } //print_var_table(param_list_head); return num; }
/*add vars defined in the deflist of a structure into the structure's member list *return member var number*/ int init_member_list(struct var_descriptor* member_list_head, struct tree_node* deflist_node){ assert(deflist_node -> unit_code == DefList); assert(member_list_head != NULL); int num = 0; while(deflist_node -> child != NULL){ struct tree_node* specifier_node = deflist_node -> child -> child; struct tree_node* declist_node = specifier_node -> sibling; while(true){ struct tree_node* vardec_node = declist_node -> child -> child; if(vardec_node -> sibling != NULL){ printf("Error type 15 at line %d: struct member initialized\n", vardec_node -> lineno); semantic_error_flag = true; } else{ if(create_variable(specifier_node, vardec_node, member_list_head, true) != NULL) num ++; } if(declist_node -> child -> sibling != NULL) declist_node = declist_node -> child -> sibling -> sibling; else break; } deflist_node = deflist_node -> child -> sibling; } return num; }
/*analyze an extdef node*/ void analyze_extdef_node(struct tree_node* extdef_node){ assert( extdef_node -> unit_code == ExtDef ); /*switch case fundef case global var def case struct def */ struct tree_node* specifier_node = extdef_node -> child; struct tree_node* second_child = extdef_node -> child -> sibling; switch(second_child -> unit_code){ case ExtDecList: { //ExtDef -> Specifier ExtDecList SEMI struct tree_node* extdeclist_node = second_child; while(true){ struct tree_node* vardec_node = extdeclist_node -> child; create_variable(specifier_node, vardec_node, var_table_head, false); if(extdeclist_node -> child -> sibling != NULL) extdeclist_node = extdeclist_node -> child -> sibling -> sibling; else break; } break; } case FunDec: { //ExtDef -> Specifier FunDec CompSt struct tree_node* fundec_node = second_child; struct tree_node* compst_node = fundec_node -> sibling; analyze_function_node(specifier_node, fundec_node, compst_node); break; } case SEMI : { //Extdef -> Specifier SEMI; if(specifier_node -> child -> unit_code == TYPE){ //Specifier -> TYPE printf("Error type 100 at line %d: Empty variable definition\n", specifier_node -> lineno); return; } //Specifier -> StructSpecifier struct tree_node* structspecifier_node = specifier_node -> child; if(structspecifier_node -> child -> sibling -> unit_code == Tag){ //StructSpecifier -> STRUCT Tag printf("Error type 100 at line %d: Empty structure definition\n", structspecifier_node -> lineno); return ; } if(structspecifier_node -> child -> sibling -> child == NULL){ //OptTag -> empty printf("Error type 100 at line %d: Anonymous structure definition without variables\n", structspecifier_node -> lineno); return ; } create_structure(structspecifier_node); break; } default: assert(0); } }
/** * Assign a value to a variable or delete the variable if no assignment is given. * List all variables if no arguments are given. */ void cmd_let(char *args) { unsigned char token; unsigned int var_name; unsigned char var_type; skip_whitespace(args); if (*args == '\0') { print_all_variables(); print_ready(); return; } if (args = parse_variable(args, &var_name, &var_type)) { if (next_token(args) == TOKEN_ASSIGN) { token = next_token(args); args = consume_token(args, token); switch (var_type) { case VAR_TYPE_INTEGER: { int value; if (parse_number_expression(args, &value)) { create_variable(var_name, var_type, &value); } break; } case VAR_TYPE_STRING: { char *value; if (parse_string_expression(args, &value)) { create_variable(var_name, var_type, value); } break; } } } else { if (*args == '\0') { delete_variable(var_name, var_type); } } } else { syntax_error(); } }
/** * Input a variable from the keyboard. * INPUT <variable> [ONERROR <command] */ void cmd_input(char *args) { unsigned int var_name; unsigned char var_type; args = parse_variable(args, &var_name, &var_type); if (args) { if (var_type == VAR_TYPE_STRING) { char *line = readline(INTERRUPTIBLE); create_variable(var_name, var_type, line); } else if (var_type == VAR_TYPE_INTEGER) { for (;;) { int value = 0; char *line = readline(INTERRUPTIBLE); if (is_interrupted()) { break; } if (parse_integer(line, &value)) { create_variable(var_name, var_type, &value); break; } else { if (next_token(args) == TOKEN_ONERROR) { args = consume_token(args, TOKEN_ONERROR); execute(args); break; } else { syntax_error_invalid_number(); lcd_puts("Enter again: "); } } } } else { syntax_error_invalid_argument(); } } else { syntax_error_invalid_argument(); } }
/******************** * initialize_variables ********************/ int initialize_variables(dres_t *dres) { dres_initializer_t *init; char name[128]; int status; for (init = dres->initializers; init != NULL; init = init->next) { dres_name(dres, init->variable, name, sizeof(name)); if ((status = create_variable(dres, name + 1, init->fields)) != 0) return status; } return 0; }
/** * Set the cursor to a specific screen position. * AT <x>,<y> */ void cmd_at(char *args) { int x; int y; unsigned char token; args = parse_number_expression(args, &x); if (!args || x < 0 || x > 39) { syntax_error_invalid_argument(); return; } args = consume_token(args, TOKEN_COMMA); if (! args) { return; } args = parse_number_expression(args, &y); if (!args || y < 0 || y > 3) { syntax_error_invalid_argument(); return; } if (next_token(args) == TOKEN_COMMA) { args = consume_token(args, TOKEN_COMMA); if ((token = next_token(args)) == TOKEN_VAR_STRING) { unsigned int var_name; unsigned char var_type; if (args = parse_variable(args, &var_name, &var_type)) { char c = lcd_getc(x, y); sprintf (print_buffer, "%c", c); create_variable(var_name, VAR_TYPE_STRING, print_buffer); } } else { syntax_error_invalid_token(token); } } else { lcd_goto(x, y); } }
/*analyze the func body*/ void analyze_compst_node(struct func_descriptor* belongs_func, struct tree_node* compst_node){ assert(compst_node -> unit_code == CompSt); struct tree_node* deflist_node = compst_node -> child -> sibling; struct tree_node* stmtlist_node = deflist_node -> sibling; //firstly, deal with local defs while(deflist_node -> child != NULL){ struct tree_node* specifier_node = deflist_node -> child -> child; struct tree_node* declist_node = specifier_node -> sibling; while(true){ struct tree_node* vardec_node = declist_node -> child -> child; struct var_descriptor* new_var = create_variable(specifier_node, vardec_node, var_table_head, false); if(vardec_node -> sibling != NULL){ struct var_descriptor* init_exp_var = check_exp_valid(vardec_node -> sibling -> sibling); if(new_var != NULL && init_exp_var != NULL) if(!var_type_equal(new_var , init_exp_var)){ printf("Error type 5 at line %d: Type mismatch between assignment operator\n", vardec_node -> lineno); semantic_error_flag = true; } } if(declist_node -> child -> sibling != NULL) declist_node = declist_node -> child -> sibling -> sibling; else break; } deflist_node = deflist_node -> child -> sibling; } //then stmts while(stmtlist_node -> child != NULL){ check_stmt_valid(belongs_func, stmtlist_node -> child); stmtlist_node = stmtlist_node -> child -> sibling; } }
int wam_run(wam_t *wam) { wam->failed = 1; wam->opcnt = 0; wam->bpcnt = 0; int time = 0; int halted; while (wam->pc >= 0) { halted = 0; time += 1; wam->failed = 0; stmt_t *stmt = wam->prog->stmts[wam->pc]; if (wam->opcnt > wam->maxopcnt) { printf("panic: maximum opcnt reached\n"); wam->failed = 1; break; } if (time > 10000) { printf("> 10000\n"); stmt->op = OP_HALT; wam->failed = 1; break; } switch (stmt->op) { case OP_ALLOC: allocate(wam); break; case OP_DEALLOC: deallocate(wam); break; case OP_CALL: wam_call(wam, stmt->jump); break; case OP_CREATE_VAR: create_variable(wam, stmt->args[0], stmt->args[1]); break; case OP_GET_CONST: get_constant(wam, stmt->args[0], stmt->args[1]); break; case OP_GET_VAL: get_value(wam, stmt->args[0], stmt->args[1]); break; case OP_GET_VAR: get_variable(wam, stmt->args[0], stmt->args[1]); break; case OP_PUT_VAL: put_value(wam, stmt->args[0], stmt->args[1]); break; case OP_PUT_VAR: put_variable(wam, stmt->args[0], stmt->args[1]); break; case OP_PUT_CONST: put_constant(wam, stmt->args[0], stmt->args[1]); break; case OP_HALT: halted = 1; case OP_NOOP: wam->pc += 1; break; case OP_PROCEED: proceed(wam); break; case OP_RTRY_ME_ELSE: case OP_TRY_ME_ELSE: try_me_else(wam, stmt->jump); break; case OP_TRUST_ME: wam->pc++; break; case OP_UNI_STRUC: unify_struc(wam, stmt->args[0], stmt->args[1], stmt->args[2]); break; case OP_UNI_VAR: unify_variable(wam, stmt->args[0], stmt->args[1]); break; case OP_UNI_LIST: unify_list(wam, stmt->args[0], stmt->args[1], stmt->args[2]); break; default: printf("unknown wam op in line %d!\n", wam->pc); wam_backtrack(wam); break; } if (halted) break; } if (halted) return 0; if (wam->failed) { while (wam->cp != NULL) wam_backtrack(wam); wam_backtrack(wam); } return 0; }