struct type *expr_typecheck(struct expr *e){ if (e == NULL) { return type_create(TYPE_VOID,0,0,0); } struct type *l = malloc(sizeof(struct type)); struct type *r = malloc(sizeof(struct type)); switch (e->kind){ case (EXPR_ADD): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot add "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_SUB): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot subtract "); type_print(l); literal_print(e->left); printf(" from "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_MUL): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot multiply "); type_print(l); literal_print(e->left); printf(" and "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_DIV): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot divide "); type_print(l); literal_print(e->left); printf(" by "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_INCREMENT): l = expr_typecheck(e->left); if (l->kind != TYPE_INTEGER){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot increment "); type_print(l); literal_print(e->left); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_DECREMENT): l = expr_typecheck(e->left); if (l->kind != TYPE_INTEGER){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot decrement "); type_print(l); literal_print(e->left); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_NOT): r = expr_typecheck(e->right); if (r->kind != TYPE_BOOLEAN){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot negate "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_POWER): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot raise "); type_print(l); literal_print(e->left); printf(" to power "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_MODULO): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot take modulus of "); type_print(l); literal_print(e->left); printf(" and "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_LESS_THAN): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_GREATER_THAN): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_LESS_THAN_OR_EQUAL): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_GREATER_THAN_OR_EQUAL): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_EQUIVALENCE_COMPARISON): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind == TYPE_FUNCTION) || (r->kind == TYPE_FUNCTION)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of functions\n"); e->type = 0; } else if ((l->kind == TYPE_ARRAY) || (r->kind == TYPE_ARRAY)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of arrays\n"); e->type = 0; } else if (l->kind != r->kind){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_NONEQUIVALENCE_COMPARISON): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind == TYPE_FUNCTION) || (r->kind == TYPE_FUNCTION)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of functions\n"); e->type = 0; } else if ((l->kind == TYPE_ARRAY) || (r->kind == TYPE_ARRAY)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of arrays\n"); e->type = 0; } else if (l->kind != r->kind){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_AND): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_BOOLEAN) || (r->kind != TYPE_BOOLEAN)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_OR): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_BOOLEAN) || (r->kind != TYPE_BOOLEAN)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_ASSIGNMENT): l = expr_typecheck(e->left); r = expr_typecheck(e->right); //if ((l->kind == TYPE_FUNCTION) || (r->kind == TYPE_FUNCTION)){ if (l->kind == TYPE_FUNCTION){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot assign a function\n"); e->type = 0; } else if (l->kind != r->kind) { error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot assign "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(l->kind,0,0,0); } break; case (EXPR_BOOLEAN_LITERAL): e->type = type_create(TYPE_BOOLEAN, 0, 0, 0); break; case (EXPR_INTEGER_LITERAL): e->type = type_create(TYPE_INTEGER, 0, 0, 0); break; case (EXPR_CHARACTER_LITERAL): e->type = type_create(TYPE_CHARACTER, 0, 0, 0); break; case (EXPR_STRING_LITERAL): e->type = type_create(TYPE_STRING, 0, 0, 0); break; case (EXPR_IDENTIFIER): e->type = e->symbol->type; break; case (EXPR_PARENTHESES): e->type = expr_typecheck(e->left); break; case (EXPR_FUNCTION_CALL): param_list_typecheck(); e->type = e->left->symbol->type->subtype; break; case (EXPR_ARRAY_INDEX): e->type = type_create(TYPE_ARRAY, 0, 0, 0); break; } return e->type; }
struct type * expr_typecheck( struct expr *e ) { if (!e) return type_create(TYPE_VOID, 0, 0); struct type *L; struct type *R; switch (e->kind) { case EXPR_INT_VAL: return type_create(TYPE_INTEGER, 0, 0); case EXPR_NAME: return type_copy(e->symbol->type); case EXPR_STRING_VAL: return type_create(TYPE_STRING, 0, 0); case EXPR_CHAR_VAL: return type_create(TYPE_CHARACTER, 0, 0); case EXPR_BOOLEAN_VAL: return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_ARRAY_VAL: { struct expr *vals = e->right; struct type *subtype = 0; int num_subtype = 0; while (vals) { struct type *cur_t = expr_typecheck(vals); if (!subtype) { subtype = cur_t; } if (!type_compare(subtype, cur_t)) { decl_has_error = 1; printf("type error: array of element type "); type_print(subtype); printf(" cannot have expression of type "); type_print(cur_t); printf("\n"); } num_subtype++; vals = vals->next; } struct type *t = type_create(TYPE_ARRAY, 0, subtype); t->num_subtype = expr_create_integer_literal(num_subtype); return t; } //return type_copy(e->symbol->type); case EXPR_ARRAY_SUB: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot use "); type_print(R); printf(" as index to an array\n"); } if (L->kind != TYPE_ARRAY) { decl_has_error = 1; printf("type error: access an "); type_print(R); printf(" as an array\n"); } return type_copy(L->subtype); case EXPR_FUNCTION_VAL: // need to check function params!!!!! param_list_typecheck(e->right, e->symbol->params, e->name); return type_copy(e->symbol->type->subtype); case EXPR_ADD: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot add "); type_print(L); printf(" to a "); type_print(R); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_SUB: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if ( !(L->kind == TYPE_INTEGER && L->kind == TYPE_INTEGER) || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot subtract "); type_print(L); printf(" to a "); type_print(R); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_MUL: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot multiply "); type_print(L); printf(" to a "); type_print(R); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_DIV: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot divide "); type_print(L); printf(" to a "); type_print(R); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_MODULO: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot module "); type_print(L); printf(" to a "); type_print(R); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_EXPO: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot expo "); type_print(L); printf(" to a "); type_print(R); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_POST_DECREASE: L = expr_typecheck(e->left); if (L->kind != TYPE_INTEGER ) { decl_has_error = 1; printf("type error: cannot decrease a "); type_print(L); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_POST_INCREASE: L = expr_typecheck(e->left); if (L->kind != TYPE_INTEGER ) { decl_has_error = 1; printf("type error: cannot add a "); type_print(L); printf("\n"); } return type_create(TYPE_INTEGER, 0, 0); case EXPR_GE: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot make greater equal than compare "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_LE: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot make less equal compare "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_GT: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot make greater than compare "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_LT: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) { decl_has_error = 1; printf("type error: cannot make less than compare "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_AND: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_BOOLEAN || R->kind != TYPE_BOOLEAN) { decl_has_error = 1; printf("type error: cannot and "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_NOT: R = expr_typecheck(e->right); if (R->kind != TYPE_BOOLEAN) { decl_has_error = 1; printf("type error: cannot not a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_OR: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind != TYPE_BOOLEAN || R->kind != TYPE_BOOLEAN) { decl_has_error = 1; printf("type error: cannot or "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_EQ: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind == TYPE_FUNCTION || R->kind == TYPE_FUNCTION || L->kind == TYPE_ARRAY || R->kind == TYPE_ARRAY) { decl_has_error = 1; printf("type error: cannot compare equality "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_NEQ: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind == TYPE_FUNCTION || R->kind == TYPE_FUNCTION || L->kind == TYPE_ARRAY || R->kind == TYPE_ARRAY) { decl_has_error = 1; printf("type error: cannot compare non equality "); type_print(L); printf(" with a "); type_print(R); printf("\n"); } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_ASSIGN: L = expr_typecheck(e->left); R = expr_typecheck(e->right); if (L->kind == TYPE_FUNCTION || R->kind == TYPE_FUNCTION) { decl_has_error = 1; printf("type error: cannot assign "); type_print(R); printf(" to a "); type_print(L); printf("\n"); } if (!type_compare(L, R)) { decl_has_error = 1; printf("type error: cannot assign "); type_print(R); printf(" to a "); type_print(L); printf("\n"); } return type_copy(R); } }
struct type * expr_typecheck(struct expr *e) { if (!e) return type_create(TYPE_VOID, 0, 0); struct type *l, *r; switch(e->kind) { case EXPR_INTEGER_LITERAL: return type_create(TYPE_INTEGER, 0, 0); case EXPR_BOOLEAN_LITERAL: return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_CHAR_LITERAL: return type_create(TYPE_CHARACTER, 0, 0); case EXPR_STRING_LITERAL: return type_create(TYPE_STRING, 0, 0); case EXPR_VARIABLE: return type_create(e->symbol->type->kind, 0, 0); case EXPR_FUNCTION_CALL: param_list_typecheck(e->symbol->type->params, e->right, 0); return type_create(e->symbol->type->subtype->kind, 0, 0); case EXPR_ADD: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: cannot add type ", e->line); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" to type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_UNARY: r = expr_typecheck(e->right); if (r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("unary operator (-) cannot be applied to type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_ASSIGN: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind == TYPE_FUNCTION || r->kind == TYPE_FUNCTION) { printf("type error: line %d: ", e->line); printf("= operator not compatible with functions\n"); error_count++; } else if (!(type_compare(l, r))) { printf("type error: line %d: cannot assign type ", e->line); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf(" to type "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf("\n"); error_count++; } return type_create(l->kind, 0, 0); case EXPR_LIST: l = expr_typecheck(e->left); expr_typecheck(e->right); return l; case EXPR_LIST_OUTER: r = expr_typecheck(e->right); return r;; case EXPR_SUB: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: cannot subtract type ", e->line); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" from type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_MUL: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: cannot multiply type ", e->line); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_DIV: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: cannot divide type ", e->line); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" by type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_MOD: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: cannot modulus type ", e->line); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" with type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_POW: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: cannot exponentiate type ", e->line); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" by type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_INCR: r = expr_typecheck(e->right); if (r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("++ operator not compatible with type "); type_print(e->symbol->type); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_DECR: r = expr_typecheck(e->right); if (r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("-- operator not compatible with type "); type_print(e->symbol->type); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_INTEGER, 0, 0); case EXPR_NOT: r = expr_typecheck(e->right); if (r->kind != TYPE_BOOLEAN) { printf("type error: line %d: ", e->line); printf("! operator requires boolean type boolean type operand (found "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf(" )\n" ); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_LT: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("< operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_LE: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("<= operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_GT: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("> operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_GE: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_INTEGER || r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf(">= operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_EQ: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind == TYPE_ARRAY || l->kind == TYPE_FUNCTION || r->kind == TYPE_ARRAY || r->kind == TYPE_FUNCTION) { printf("type error: line %d: ", e->line); printf("== operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } else if (!type_compare(l, r)) { printf("type error: line %d: ", e->line); printf("cannot use == operator on non-matching types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_NE: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind == TYPE_ARRAY || l->kind == TYPE_FUNCTION || r->kind == TYPE_ARRAY || r->kind == TYPE_FUNCTION) { printf("type error: line %d:", e->line); printf("!= operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } else if (!type_compare(l, r)) { printf("type error: line %d:", e->line); printf("cannot use != operator on non-matching types "); printf(" ("); expr_print(e->left); printf(")"); type_print(l); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_AND: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_BOOLEAN || r->kind != TYPE_BOOLEAN) { printf("type error: line %d: ", e->line); printf("&& operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->right); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_OR: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_BOOLEAN || r->kind != TYPE_BOOLEAN) { printf("type error: line %d: ", e->line); printf("|| operator not compatible with types "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf(" and "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } return type_create(TYPE_BOOLEAN, 0, 0); case EXPR_ARRAY_MEMBER: l = expr_typecheck(e->left); r = expr_typecheck(e->right); if (l->kind != TYPE_ARRAY && l->kind != TYPE_STRING) { printf("type error: line %d: ", e->line); printf("[] operator cannot follow a variable of type "); type_print(l); printf(" ("); expr_print(e->left); printf(")"); printf("\n"); error_count++; } return type_create(type_array_type(e), 0, 0); case EXPR_INDEX: if (e->left) { l = expr_typecheck(e->left->right); if (l->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("an array index cannot be type "); type_print(l); printf(" ("); expr_print(e->left->right); printf(")"); printf("\n"); error_count++; } expr_typecheck(e->right); } else { r = expr_typecheck(e->right); if (r->kind != TYPE_INTEGER) { printf("type error: line %d: ", e->line); printf("an array index cannot be type "); type_print(r); printf(" ("); expr_print(e->right); printf(")"); printf("\n"); error_count++; } } return type_create(TYPE_INTEGER, 0, 0); default: fprintf(stderr, "cminor: ERROR! Illegal expr type found!\n"); exit(1); } }