예제 #1
0
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;
}
예제 #2
0
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);
	}
}
예제 #3
0
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);
    }
}