struct symbolRecord* newClassSymbol ( struct symbolTableRecord* syms, struct symbolTableRecord* gsyms, char* name ) { // Make sure name is unique or forward referenced struct symbolRecord* s = lookupLocal(syms, name); struct typeRecord* t = 0; if (s == 0) // new name { s = newSymbolRecord(name, classDefSymbol); s->u.c.location = syms->size++; addNewSymbol(syms, s); t = newTypeRecord(classType); s->u.c.typ = t; } else // already defined { if (s->styp != classDefSymbol) { yyserror ( "non class name %s used to define class", s->name ); } t = s->u.c.typ; if (t == 0) { yyserror ( "compiler error, missing type in class %s", s->name ); } if (t->ttyp != classType) { yyserror("class %s has non class type field", s->name); } if (t->u.c.symbols) { yyserror("class %s multiply defined", s->name); } } struct symbolTableRecord* ns = newSymbolTable(classTable, syms); t->u.c.symbols = ns; ns->definingType = t; return s; }
void uniqueName(struct symbolTableRecord* syms, char* name) { if (lookupLocal(syms, name)) { yyserror("name must be unique within context: %s", name); } }
/* Make sure argument is OK */ static int check_arg(node_ptr arg, int wantbool) { if (!arg) { yyerror("Null node encountered"); return 0; } if (arg->type == N_VAR) { node_ptr qval = find_symbol(arg->sval); if (!qval) { yyserror("Variable '%s' not found", arg->sval); return 0; } if (wantbool != qval->isbool) { if (wantbool) yyserror("Variable '%s' not Boolean", arg->sval); else yyserror("Variable '%s' not integer", arg->sval); return 0; } return 1; } if (arg->type == N_NUM) { if (wantbool && strcmp(arg->sval,"0") != 0 && strcmp(arg->sval,"1") != 0) { yyserror("Value '%s' not Boolean", arg->sval); return 0; } return 1; } if (wantbool && !arg->isbool) yyserror("Non Boolean argument '%s'", show_expr(arg)); if (!wantbool && arg->isbool) yyserror("Non integer argument '%s'", show_expr(arg)); return (wantbool == arg->isbool); }
void check_ast_var(node_ptr vnode) { if (vnode->ntype == E_VAR) yyserror("Invalid variable '%s'", vnode->name); if (vnode->ntype == E_AREF) { check_ast_var(vnode->children[0]); return; } if (vnode->ntype != E_LVAR && vnode->ntype != E_AVAR && vnode->ntype != E_LAVAR) { fprintf(ERRFILE, "Error (check_ast_var). Expected variable. Got node of type %s\n", node_type_name(vnode->ntype)); exit(1); } }
static node_ptr find_symbol(char *name) { int i; for (i = 0; i < sym_count; i++) { if (strcmp(name, sym_tab[0][i]->sval) == 0) { node_ptr result = sym_tab[1][i]; sym_tab[0][i]->ref++; return result; } } yyserror("Symbol %s not found", name); return NULL; }
struct symbolRecord* lookupSymbol ( struct symbolTableRecord* syms, char* name ) { for (; syms; syms = syms->surroundingContext) { struct symbolRecord* s = lookupLocal(syms, name); if (s) return s; } yyserror("unknown identifier: %s", name); return 0; }
/* Look for self-reference in assignment to newly declared variable */ void self_check(node_ptr dnode, node_ptr enode) { int i; node_ptr vnode = dnode; if (!enode) return; /* First find variable node (in case of array) */ while (vnode && vnode->ntype != E_LVAR && vnode->ntype != E_LAVAR) vnode = vnode->children[0]; if (!vnode) { fprintf(ERRFILE, "Error (self_check). No declared variable found\n"); exit(1); } if ((enode->ntype == E_LVAR || enode->ntype == E_AVAR || enode->ntype == E_LAVAR) && !strcmp(enode->name, vnode->name)) yyserror("Invalid reference to newly-declared variable '%s'", vnode->name); for (i = 0; i < enode->degree; i++) self_check(vnode, enode->children[i]); }
node_ptr make_ast_num(char *sval) { node_ptr result = new_node0(E_CONST, IOP_NONE); data_t dtype = DATA_SIGNED; int long_cnt = 0; int pos = strlen(sval)-1; int wsize = ISIZE; int i; int isdecimal = 1; char *endptr; ullong val = 0; float fval = 0.0; /* Promotion rules for decimal integer constants */ promo_rec dec_int_promo[] = { { ISIZE-2, DATA_SIGNED, ISIZE }, /* int */ { LSIZE-2, DATA_SIGNED, LSIZE }, /* long int */ { LSIZE-1, DATA_UNSIGNED, LSIZE }, /* long unsigned */ { LLSIZE-2, DATA_SIGNED, LLSIZE }, /* long long int */ { LLSIZE-1, DATA_UNSIGNED, LLSIZE }, /* long long unsigned */ { 0, 0, 0 }}; /* Too big */ promo_ptr dec_long_promo = &dec_int_promo[1]; promo_ptr dec_llong_promo = &dec_int_promo[3]; /* Promotion rules for hex/octal integer constants */ promo_rec hex_int_promo[] = { { ISIZE-2, DATA_SIGNED, ISIZE }, /* int */ { ISIZE-1, DATA_UNSIGNED, ISIZE }, /* unsigned */ { LSIZE-2, DATA_SIGNED, LSIZE }, /* long int */ { LSIZE-1, DATA_UNSIGNED, LSIZE }, /* long unsigned */ { LLSIZE-2, DATA_SIGNED, LLSIZE }, /* long long int */ { LLSIZE-1, DATA_UNSIGNED, LLSIZE }, /* long long unsigned */ { 0, 0, 0 }}; /* Too big */ promo_ptr hex_long_promo = &hex_int_promo[2]; promo_ptr hex_llong_promo = &hex_int_promo[4]; /* Promotion rules for unsigned integer constants */ promo_rec unsigned_int_promo[] = { { ISIZE-1, DATA_UNSIGNED, ISIZE }, /* unsigned */ { LSIZE-1, DATA_UNSIGNED, LSIZE }, /* long unsigned */ { LLSIZE-1, DATA_UNSIGNED, LLSIZE }, /* long long unsigned */ { 0, 0, 0 }}; /* Too big */ promo_ptr unsigned_long_promo = &dec_int_promo[1]; promo_ptr unsigned_llong_promo = &dec_int_promo[2]; promo_ptr all_dec_promo[3] = { dec_int_promo, dec_long_promo, dec_llong_promo }; promo_ptr all_hex_promo[3] = { hex_int_promo, hex_long_promo, hex_llong_promo }; promo_ptr all_unsigned_promo[3] = { unsigned_int_promo, unsigned_long_promo, unsigned_llong_promo }; /* See if suffixed with u, U, l, or L */ int c = sval[pos]; while (!isxdigit(c)) { switch (c) { case 'u': case 'U': dtype = DATA_UNSIGNED; break; case 'l': case 'L': long_cnt++; break; default: yyserror("Invalid number: '%s'", sval); break; } sval[pos] = 0; c = sval[--pos]; } if (sval[0] == '0') isdecimal = 0; /* See if contains ., e, or E, but is not in hex */ for (i = 0; sval[i]; i++) { char c = sval[i]; if (c == 'x' || c == 'X') { break; /* hex */ } if (c == '.' || c == 'e' || c == 'E') { dtype = DATA_FLOAT; isdecimal = 0; break; } } if (dtype == DATA_FLOAT) { fval = strtof(sval, &endptr); wsize = FSIZE; } else { #if HAVE_LONGLONG val = strtoull(sval, &endptr, 0); #else val = strtoul(sval, &endptr, 0); #endif } if (*endptr) yyserror("Invalid number '%s'", sval); if (dtype != DATA_FLOAT) { ullong bits; /* Find the most significant 1 position */ int msone = -1; for (bits = val; bits; bits >>= 1) msone++; if (long_cnt > 2) yyserror("Invalid number: '%s'", sval); else { /* Apply rules for sizing/typing integer constants */ promo_ptr rules = dtype == DATA_UNSIGNED ? all_unsigned_promo[long_cnt] : isdecimal ? all_dec_promo[long_cnt] : all_hex_promo[long_cnt]; int ok = 0; for (i = 0; !ok && rules[i].maxpos != 0; i++) { if (msone <= rules[i].maxpos) { /* Debugging */ #ifdef DEBUG data_t old_dtype = dtype; int old_wsize = wsize; #endif /* Change to this data type */ dtype = rules[i].dtype; wsize = rules[i].wsize; #ifdef DEBUG if (old_dtype != dtype || old_wsize != wsize) { printf("Changing '%s' to data type %s, word size %d (msb at %d)\n", sval, dtype == DATA_UNSIGNED ? "unsigned" : "int", wsize, msone); } #endif ok = 1; } } if (!ok) { yyserror("Number too large for data type: '%s'", sval); } } }
/* Recursively generate code for function */ static void gen_expr(node_ptr expr) { node_ptr ele; switch(expr->type) { case N_QUOTE: yyserror("Unexpected quoted string", expr->sval); break; case N_VAR: { node_ptr qstring = find_symbol(expr->sval); if (qstring) #if defined(VLOG) || defined(UCLID) outgen_print("%s", expr->sval); #else outgen_print("(%s)", qstring->sval); #endif else yyserror("Invalid variable '%s'", expr->sval); #ifdef UCLID check_for_arg(expr->sval); #endif } break; case N_NUM: #ifdef UCLID { long long int val = atoll(expr->sval); if (val < -1) outgen_print("pred^%d(CZERO)", -val); else if (val == -1) outgen_print("pred(CZERO)"); else if (val == 0) outgen_print("CZERO"); else if (val == 1) outgen_print("succ(CZERO)"); else outgen_print("succ^%d(CZERO)", val); } #else /* !UCLID */ fputs(expr->sval, outfile); #endif /* UCLID */ break; case N_AND: outgen_print("("); outgen_upindent(); gen_expr(expr->arg1); outgen_print(" & "); gen_expr(expr->arg2); outgen_print(")"); outgen_downindent(); break; case N_OR: outgen_print("("); outgen_upindent(); gen_expr(expr->arg1); outgen_print(" | "); gen_expr(expr->arg2); outgen_print(")"); outgen_downindent(); break; case N_NOT: #if defined(VLOG) || defined(UCLID) outgen_print("~"); #else outgen_print("!"); #endif gen_expr(expr->arg1); break; case N_COMP: outgen_print("("); outgen_upindent(); gen_expr(expr->arg1); #ifdef UCLID { char *cval = expr->sval; if (strcmp(cval, "==") == 0) cval = "="; outgen_print(" %s ", cval); } #else /* !UCLID */ outgen_print(" %s ", expr->sval); #endif /* UCLID */ gen_expr(expr->arg2); outgen_print(")"); outgen_downindent(); break; case N_ELE: outgen_print("("); outgen_upindent(); for (ele = expr->arg2; ele; ele=ele->next) { gen_expr(expr->arg1); #ifdef UCLID outgen_print(" = "); #else outgen_print(" == "); #endif gen_expr(ele); if (ele->next) #if defined(VLOG) || defined(UCLID) outgen_print(" | "); #else outgen_print(" || "); #endif } outgen_print(")"); outgen_downindent(); break; case N_CASE: #ifdef UCLID outgen_print("case"); outgen_terminate(); { /* Use this to keep track of last case when no default is given */ node_ptr last_arg2 = NULL; for (ele = expr; ele; ele=ele->next) { outgen_print(" "); if (ele->arg1->type == N_NUM && atoll(ele->arg1->sval) == 1) { outgen_print("default"); last_arg2 = NULL; } else { gen_expr(ele->arg1); last_arg2 = ele->arg2; } outgen_print(" : "); gen_expr(ele->arg2); outgen_print(";"); outgen_terminate(); } if (last_arg2) { /* Use final case as default */ outgen_print(" default : "); gen_expr(last_arg2); outgen_print(";"); outgen_terminate(); } } outgen_print(" esac"); #else /* !UCLID */ outgen_print("("); outgen_upindent(); int done = 0; for (ele = expr; ele && !done; ele=ele->next) { if (ele->arg1->type == N_NUM && atoll(ele->arg1->sval) == 1) { gen_expr(ele->arg2); done = 1; } else { gen_expr(ele->arg1); outgen_print(" ? "); gen_expr(ele->arg2); outgen_print(" : "); } } if (!done) outgen_print("0"); outgen_print(")"); outgen_downindent(); #endif break; default: yyerror("Unknown node type"); break; }