Пример #1
0
void expr_typecheck_array(struct type *array_type, struct expr *e_list)
{
    if (!e_list)
        return;

    struct type *t;

    if (e_list->kind == EXPR_LIST)
        t = expr_typecheck(e_list->left);
    else if (e_list->kind == EXPR_LIST_OUTER)
        t = expr_typecheck(e_list->right);

    if (!type_compare(t, array_type))
    {
        printf("type error: line %d: ", e_list->line);
        printf("expression type ");
        type_print(t);
        printf(" (");
        expr_print(e_list->right);
        printf(")");
        printf(" found in assignment to array of type ");
        type_print(array_type);
        printf("\n");
        error_count++;
    }

    expr_typecheck_array(array_type, e_list->right);
}
Пример #2
0
void decl_typecheck( struct decl *d ) {
	if (!d) return;
	if (d->value) {
		struct type *T = expr_typecheck( d-> value );
		if (!type_compare(d->type, T)) {
			printf("type error: cannot initialize variable (%s) of type ", d->name);
			type_print(d->type);
			printf(" and assign it a ");
			type_print( T );
			printf("\n");
		}
	}
	if (d->type->kind == TYPE_ARRAY) {
		// for array
		decl_array_typecheck(d->type, d->name);
	} else if (d->type->kind == TYPE_FUNCTION) {
		// for function return
		decl_array_typecheck(d->type->subtype, d->name);		
	}
	
	if (d->code) {
		decl_func_sym = scope_lookup(d->name);
		stmt_typecheck(d->code);
	}
	if (d->next)
		decl_typecheck(d->next);
}
Пример #3
0
// make sure declared array type has a correct size initialization
void decl_array_typecheck( struct type *t, char *name ) {
	if (!t ) return;
	if (t->kind == TYPE_ARRAY) {
		if (!t->num_subtype) {
			decl_has_error = 1;
			printf("type error: array(%s) declaration must have a size value\n", name);
		} else if (expr_typecheck(t->num_subtype)->kind != TYPE_INTEGER) {
			decl_has_error = 1;
			printf("type error: array(%s) size must have integer type\n", name );
		}
	}
	decl_array_typecheck(t->subtype, name);
}
Пример #4
0
//checks if a function call matches up to the function types
void function_typecheck(const char *function_name, struct expr *e, struct param_list *p, int param, int func_params) {
	if(!e && !p) return; //only for no parameters
	if(!e) {
		printf("type error: In call to function %s, expected %d parameters, but received %d\n", function_name, param, func_params);
		error_count++;
		return;
	} 
	if(!p) {
		struct expr *e1;
		if(e->kind == EXPR_COMMA) e1 = e->left;
		else e1 = e;
		struct type *t = expr_typecheck(e1);
		printf("type error: In call to function %s, expected %d parameters, but received %d\n", function_name, param, func_params);
		error_count++;
		return;
	}
	int last_expr = 0, last_param = 0;
	if(e->kind != EXPR_COMMA) last_expr = 1;
	if(!p->next) last_param = 1;

	struct type *t = expr_typecheck(e->left);
	if(e->kind == EXPR_COMMA){
		if(!type_compare(t, p->type)){
			printf("type error: In call to function %s, expected parameter %d to be of type ", function_name, param);
			type_print(p->type);
			printf(". Instead, expression ");
			expr_print(e->left);
			printf(" of type ");
			type_print(t);
			printf(" was passed to parameter %d\n", param);
			error_count++;
		}	
	}

	if(last_expr && last_param) return;
	function_typecheck(function_name, e->right, p->next, ++param, func_params);
}
Пример #5
0
void resolve_array_values(struct expr *e,struct type *t,const char *name)
{
	if(!e)return;
	if(e->kind == EXPR_EXPR_LIST || e->kind == EXPR_ARRAY_LIST ){resolve_array_values(e->left,t,name); resolve_array_values(e->right,t,name);}
	else{
		const_expr++;	
		struct type *aux2 = expr_typecheck(e);
		if(aux2->kind != t->kind){
			get_incrementError(2);
			printf("Passing wrong argument to array %s: Passing int the array expression list ",name);
			type_print(aux2);
			printf(" ");
			expr_print(e);
			printf("\n");
		}
	
	}
}
Пример #6
0
void param_list_typecheck( struct expr * e, struct param_list *params, char *func_name) {
	while (e && params) {
		struct type *T = expr_typecheck(e);
		if (!type_compare(T, params->type)) {
			decl_has_error = 1;
			printf("type error: cannot pass variable of type ");
			type_print(T);
			printf(" to function %s\n", func_name);

		} 
		e = e->next;
		params = params->next;
	}
	if (e) {
		decl_has_error = 1;
		printf("type error: pass more variables to functions call %s than needed\n", func_name);
	}
	if (params) {
		decl_has_error = 1;
		printf("type error: not enough variables to function call %s\n", func_name);
	}
}
Пример #7
0
void param_list_typecheck(struct param_list *p, struct expr *e, const char * const name) {
    // this is invoked for each function invocation
    // we compare each item in the param list with the given expression list

    struct param_list *p_ptr = p;
    struct expr *e_ptr = e;

    while (p_ptr && e_ptr) {
        // comparing each pair
        struct type *expected_type = p_ptr->type;
        struct type *received_type = expr_typecheck(e_ptr);
        if (!type_is_equal(expected_type, received_type)) {
            // error
            ++error_count_type;
            printf("type error: function `%s` parameter %d type mismatch; expected ",
                name,
                p_ptr->symbol->which);
            type_print(expected_type);
            printf(", received ");
            type_print(received_type);
            printf("\n");
        }
        TYPE_FREE(received_type);

        // move on
        p_ptr = p_ptr->next;
        e_ptr = e_ptr->next;
    }

    // ensure lengths are the same
    if (p_ptr != NULL || e_ptr != NULL) {
        ++error_count_type;
        printf("type error: function `%s` expected %u parameters, received %u arguments\n",
            name,
            param_list_length(p),
            expr_list_length(e));
    }
}
Пример #8
0
struct type *expr_typecheck(struct expr *e) {
	if(!e) return type_create(TYPE_VOID, 0, 0, 0);
	struct param_list *param_ptr;
	struct expr *expr_ptr;
	struct type *left;
	struct type *right;
	switch(e->kind) {
		case EXPR_LIST:
			left = expr_typecheck(e->left);
			right = expr_typecheck(e->right);
			return type_create(TYPE_VOID, 0, 0, 0);
			break;
		case EXPR_ASSIGNMENT:
			left = expr_typecheck(e->left);
			right = expr_typecheck(e->right);
			while(left->kind == TYPE_ARRAY) left = left->subtype; 
			while(right->kind == TYPE_ARRAY) left = left->subtype; 
			if(type_equal(left, right) && left->kind != TYPE_FUNCTION) {
				return type_copy(left);
			} else {
				printf("Cannot assign ");
				type_print(right);
				printf(" to ");
				type_print(left);
				if(e->left->name) {
					printf(" %s\n", e->left->name);
				} else {
					printf("\n");
				}
				type_check_errors++;
				return left;
			}
			break;
		case EXPR_NOT_EQUALS:
		case EXPR_EQUALS:
			left = expr_typecheck(e->left);
			right = expr_typecheck(e->right);
			if(type_equal(left, right) && left->kind != TYPE_FUNCTION && left->kind != TYPE_ARRAY) {
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			} else {
				printf("Cannot perform logical equals operation on ");
				type_print(left);
				printf(" and ");
				type_print(right);
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			}
			break;
		case EXPR_LT:
		case EXPR_GT:
		case EXPR_LE:
		case EXPR_GE:
			left = expr_typecheck(e->left);
			right = expr_typecheck(e->right);
			if(left->kind == TYPE_INTEGER && right->kind == TYPE_INTEGER) {
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			} else {
				printf("Cannot perform boolean operations on ");
				type_print(left);
				printf(" and ");
				type_print(right);
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			}
			break;
		case EXPR_ADD:
		case EXPR_MINUS:
		case EXPR_TIMES:
		case EXPR_DIVIDES:
		case EXPR_MOD:
		case EXPR_POWER:
			left = expr_typecheck(e->left);
			right = expr_typecheck(e->right);
			if(left->kind == TYPE_INTEGER && right->kind == TYPE_INTEGER) {
				return type_create(TYPE_INTEGER, 0, 0, 0);
			} else {
				printf("Cannot perform arithmetic operations on ");
				type_print(left);
				printf(" and ");
				type_print(right);
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_INTEGER, 0, 0, 0);
			}
			break;
		case EXPR_NEGATIVE:
			right = expr_typecheck(e->right);
			if(right->kind == TYPE_INTEGER) {
				return type_create(TYPE_INTEGER, 0, 0, 0);
			} else {
				printf("Cannot take the negative of ");
				type_print(right);	
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_INTEGER, 0, 0, 0);
			}
			break;
		case EXPR_OR:
		case EXPR_AND:
			left = expr_typecheck(e->left);
			right = expr_typecheck(e->right);
			if(left->kind == TYPE_BOOLEAN && right->kind == TYPE_BOOLEAN) {
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			} else {
				printf("Cannot perform logical operations on ");
				type_print(left);
				printf(" and ");
				type_print(right);
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			}
			break;
		case EXPR_NOT:
			right = expr_typecheck(e->right);
			if(right->kind == TYPE_BOOLEAN) {
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			} else {
				printf("Cannot perform a logical not on ");
				type_print(right);	
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_BOOLEAN, 0, 0, 0);
			}
			break;
		case EXPR_PRE_INCREMENT:
		case EXPR_PRE_DECREMENT:
			right = expr_typecheck(e->right);
			if(right->kind == TYPE_INTEGER) {
				return type_create(TYPE_INTEGER, 0, 0, 0);
			} else {
				printf("Cannot perform integer operations on ");
				type_print(right);	
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_INTEGER, 0, 0, 0);
			}
			break;
		case EXPR_POST_INCREMENT:
		case EXPR_POST_DECREMENT:
			left = expr_typecheck(e->left);
			if(left->kind == TYPE_INTEGER) {
				return type_create(TYPE_INTEGER, 0, 0, 0);
			} else {
				printf("Cannot perform integer operations on ");
				type_print(left);	
				printf("\n");
				type_check_errors++;
				return type_create(TYPE_INTEGER, 0, 0, 0);
			}
			break;
		case EXPR_FUNCTION:
			param_ptr = e->left->symbol->type->params;
			expr_ptr = e->right;
			while(param_ptr) {
				if(!expr_ptr) {
					printf("Not enough arguments given for function %s\n", e->left->name);
					type_check_errors++;
					break;
				}
				if(!type_equal(param_ptr->type, expr_typecheck(expr_ptr->left))) {
					printf("Function %s requires a paramater of type ", e->left->name);
					type_print(param_ptr->type);
					printf(" but ");
					expr_print(expr_ptr->left);
					printf(" is of type ");
					type_print(expr_typecheck(expr_ptr->left));
					printf("\n");
					type_check_errors++;
					break;
				}
				param_ptr = param_ptr->next;
				expr_ptr = expr_ptr->right;
			}
			if(expr_ptr) {
				printf("Too many arguments given for function %s\n", e->left->name);
				type_check_errors++;
			}
			return e->left->symbol->type->subtype;
			break;
		case EXPR_BOOLEAN:
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_INT:
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_CHAR:
			return type_create(TYPE_CHARACTER, 0, 0, 0);
			break;
		case EXPR_STRING:
			return type_create(TYPE_STRING, 0, 0, 0);
			break;
		case EXPR_NAME:
			if (e->symbol) return e->symbol->type;
			return type_create(TYPE_VOID, 0, 0, 0);
			break;
		case EXPR_ARRAY:
			left = expr_typecheck(e->left);
			right = expr_typecheck(e->right);
			if(right->kind == TYPE_INTEGER) {
				return type_create(left->subtype->kind, 0, 0, 0);
			} else {
				printf("Cannot use ");
				type_print(right);
				printf(" as an array index. Must use an integer\n");
				type_check_errors++;
				return type_create(left->subtype->kind, 0, 0, 0);
			}
			break;
		case EXPR_ARRAY_LITERAL:
			left = expr_typecheck(e->right->left);
			return type_create(TYPE_ARRAY, 0, 0, left->subtype);
			break;
	}
	return type_create(TYPE_VOID, 0, 0, 0);
}
Пример #9
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);
	}
}
Пример #10
0
void decl_typecheck(struct decl *d){
	if(!d)return;
	if(d->value){
		if(d->type->kind!=TYPE_ARRAY){
			struct type* t;
			t = expr_typecheck(d->value);
			if(d->type-> kind != t->kind){
				printf("Cannot assign ");
				expr_print(d->value);
				printf(" to ");
				type_print(d->type);
				printf("\n");
				get_incrementError(2);
			}
		}else
		{
			if(d->value->kind!=EXPR_ARRAY_LIST){
				printf("Cannot assign ");
				expr_print(d->value);
				printf(" to array %s\n",d->name);
				get_incrementError(2);
			}
			else{
				struct type* aux_type = d->type;
				int lenght = 1;
				if(aux_type->expression){
					while(aux_type->kind == TYPE_ARRAY){
				 		 if(aux_type->expression && aux_type->expression->kind!= EXPR_INTEGER_LITERAL){
						  printf("Array %s must have a literal value as index\n",d->name);
						  lenght = 99999;
						  break;	
						}
						else{
						  lenght*=aux_type->expression->literal_value;
						}
						aux_type = aux_type->subtype;
			     	
					}
				}
				else{
					lenght = 99999;
					while(aux_type->kind == TYPE_ARRAY)aux_type = aux_type->subtype;
			   	}


				resolve_array_values(d->value,aux_type,d->name);	
				if(const_expr > lenght){
					get_incrementError(2);
					printf("Too many arguments on inicialization of array %s\n",d->name);
				}
			}
		}
	}
	
	if(d->symbol->kind == SYMBOL_GLOBAL)
	{
		const_expr = 0;
		expr_constant(d->value);
		if(const_expr>0){
		  get_incrementError(1);
		  printf("Tried to assign not constant variable in the declaration of %s\n",d->name);
		}
				
	}
		
	if(d->code)stmt_typecheck(d->code,d->type->subtype);
	decl_typecheck(d->next);

}
Пример #11
0
void stmt_typecheck(struct stmt *s, struct type *ret, int *returned) {
  if(!s) return;
  switch(s -> kind) {
    struct type *expr;
    struct expr *curr;
    case STMT_DECL:
      decl_typecheck(s -> decl);
      break;
    case STMT_EXPR:
      // need to typecheck, but don't need type
      type_delete(expr_typecheck(s -> expr));
      break;
    case STMT_IF_ELSE:
      expr = expr_typecheck(s -> expr);
      if(expr -> kind != TYPE_BOOLEAN) {
        fprintf(stderr, "TYPE_ERROR: cannot use a(n) ");
        type_fprint(stderr, expr);
        fprintf(stderr, " as the if statement expression (currently ");
        expr_fprint(stderr, s -> expr);
        fprintf(stderr, ") requires a boolean\n");
        type_error_count++;
      }
      stmt_typecheck(s -> body, ret, returned);
      stmt_typecheck(s -> else_body, ret, returned);
      type_delete(expr);
      break;
    case STMT_FOR:
      type_delete(expr_typecheck(s -> init_expr));
      expr = expr_typecheck(s -> expr);
      // need to check that the middle
      // expression is actually there
      if(expr && expr -> kind != TYPE_BOOLEAN) {
        fprintf(stderr, "TYPE_ERROR: cannot use a ");
        type_fprint(stderr, expr);
        fprintf(stderr, " as the middle expression requires a boolean (or an empty expression)\n");
        type_error_count++;
      }
      type_delete(expr);
      type_delete(expr_typecheck(s -> next_expr));
      stmt_typecheck(s -> body, ret, returned);
      break;
    case STMT_WHILE:
      break;
    case STMT_PRINT:
      curr = s -> expr;
      while(curr) {
        expr = expr_typecheck(curr);
        // pass type through new symbol
        if(!type_is_atomic(expr)) {
          fprintf(stderr, "TYPE_ERROR: cannot print (print ");
          expr_fprint(stderr, s -> expr);
          fprintf(stderr, ") a non-atomic value (");
          type_fprint(stderr, expr);
          fprintf(stderr, ")\n");
          type_error_count++;
        }
        switch(expr -> kind) {
          case TYPE_BOOLEAN:
            curr -> print_type = 1;
            break;
          case TYPE_CHARACTER:
            curr -> print_type = 2;
            break;
          case TYPE_INTEGER:
            curr -> print_type = 3;
            break;
          case TYPE_STRING:
            curr -> print_type = 4;
            break;
          case TYPE_ARRAY:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
          case TYPE_ARRAY_DECL:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
          case TYPE_FUNCTION:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
          case TYPE_VOID:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
        }
        type_delete(expr);
        curr = curr -> next;
      }
      break;
    case STMT_RET:
      // always set to 1
      *returned = 1;
      expr = expr_typecheck(s -> expr);
      if(!s -> expr) {
        type_delete(expr);
        expr = type_create(TYPE_VOID, 0, 0, 0);
      }
      if(!type_compare(expr, ret)) {
        fprintf(stderr, "TYPE_ERROR: the return statement (return ");
        expr_fprint(stderr, s -> expr);
        fprintf(stderr, ") does not match the function return type (");
        type_fprint(stderr, ret);
        fprintf(stderr, ")\n");
        type_error_count++;
      }
      type_delete(expr);
      break;
    case STMT_BLOCK:
      stmt_typecheck(s -> body, ret, returned);
      break;
  }
  stmt_typecheck(s -> next, ret, returned);
}
Пример #12
0
void compare(struct expr *e, FILE *file) {
	expr_codegen(e->left, file);
	expr_codegen(e->right, file);
	e->reg = register_alloc();
	
	if(expr_typecheck(e->left)->kind==TYPE_STRING && expr_typecheck(e->right)->kind==TYPE_STRING){
		fprintf(file, "\n\t#String comparison\n");
		const char *left;
		const char *right;
		//get the correct string for left
		if(e->left->kind==EXPR_STRING_LITERAL) left = e->left->string_literal;
		else if(e->left->kind==EXPR_IDENT) left = e->left->symbol->string_literal;

		//get the correct string for right
		if(e->right->kind==EXPR_STRING_LITERAL) right = e->right->string_literal;
		else if(e->right->kind==EXPR_IDENT) right = e->right->symbol->string_literal;

		//compare the strings
		int result = strcmp(left, right);
		if(e->kind == EXPR_EQ){
			if(result){
				fprintf(file, "\tMOV $0, %s\n", register_name(e->reg));
			} else {
				fprintf(file, "\tMOV $1, %s\n", register_name(e->reg));
			}
		} else if(e->kind == EXPR_NE){
			if(result){
				fprintf(file, "\tMOV $1, %s\n", register_name(e->reg));
			} else {
				fprintf(file, "\tMOV $0, %s\n", register_name(e->reg));
			}
		}
	} else {
		fprintf(file, "\n\t#Comparison\n");
		fprintf(file, "\tCMP %s, %s\n", register_name(e->right->reg), register_name(e->left->reg));
		register_free(e->left->reg);
		register_free(e->right->reg);
		char *jump = malloc(4);
		switch(e->kind){
			case EXPR_GE:
				strcpy(jump, "JGE");
				break;
			case EXPR_LE:
				strcpy(jump, "JLE");
				break;
			case EXPR_GT:
				strcpy(jump, "JG");
				break;
			case EXPR_LT:
				strcpy(jump, "JL");
				break;
			case EXPR_EQ:
				strcpy(jump, "JE");
				break;
			case EXPR_NE:
				strcpy(jump, "JNE");
				break;
		}
		int label_true = label_count++;
		int label_false = label_count++;
		fprintf(file, "\t%s L%d\n", jump, label_true);
		fprintf(file, "\tMOV $0, %s\n", register_name(e->reg));
		fprintf(file, "\tJMP L%d\n", label_false);
		fprintf(file, "L%d:\n", label_true);
		fprintf(file, "\tMOV $1, %s\n", register_name(e->reg));
		fprintf(file, "L%d:\n", label_false);
		free(jump);
	}
}
Пример #13
0
struct type * expr_typecheck(struct expr *e) {
	if(!e) return type_create(TYPE_VOID, 0, 0, 0);
	struct type *L = expr_typecheck(e->left);
	struct type *R = expr_typecheck(e->right);
	switch(e->kind) {
		case EXPR_ASSIGNMENT:
			if(L->kind == TYPE_FUNCTION){
				printf("type error: cannot use assignment operator on function ");
				expr_print(e->left);
				error_count++;
			}
			if(R->kind == TYPE_FUNCTION){
				printf("type error: cannot use assignment operator on function ");
				expr_print(e->right);
				error_count++;
			}
			if(!type_compare(L, R)){
				printf("type error: cannot assign ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf(" to ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}
			return L;
			break;
		case EXPR_GE:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot use operator >= to compare ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf(". This operator can only be used on two integers.\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_LE:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot use operator <= to compare ");
				type_print(L);
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				expr_print(e->right);
				printf(". This operator can only be used on two integers.\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_GT:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot use operator > to compare ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf(". This operator can only be used on two integers.\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_LT:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot use operator < to compare ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf(". This operator can only be used on two integers.\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_EQ:
			if(L->kind == TYPE_ARRAY){
				printf("type error: cannot use operator == on array ");
				expr_print(e->left);
				printf("\n");
				error_count++;	
			} else if(L->kind == TYPE_FUNCTION){
				printf("type error: cannot use operator == on function ");
				expr_print(e->left);
				printf("\n");
				error_count++;	
			}
			if(R->kind == TYPE_ARRAY){
				printf("type error: cannot use operator == on array ");
				expr_print(e->right);
				printf("\n");
				error_count++;	
			} else if(R->kind == TYPE_FUNCTION){
				printf("type error: cannot use operator == on function ");
				expr_print(e->right);
				printf("\n");
				error_count++;	
			}
			if(L->kind != R->kind){
				printf("type error: cannot use operator == to compare ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_NE:
			if(L->kind == TYPE_ARRAY){
				printf("type error: cannot use operator != on array ");
				expr_print(e->left);
				printf("\n");
				error_count++;	
			} else if(L->kind == TYPE_FUNCTION){
				printf("type error: cannot use operator != on function ");
				expr_print(e->left);
				printf("\n");
				error_count++;	
			}
			if(R->kind == TYPE_ARRAY){
				printf("type error: cannot use operator != on array ");
				expr_print(e->right);
				printf("\n");
				error_count++;	
			} else if(R->kind == TYPE_FUNCTION){
				printf("type error: cannot use operator != on function ");
				expr_print(e->right);
				printf("\n");
				error_count++;	
			}
			if(L->kind != R->kind){
				printf("type error: cannot use operator != to compare ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_ADD:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot add ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" to ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_SUB:
				
			if((L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER) && L->kind != TYPE_VOID){
				printf("type error: cannot subtract ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf(" from ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_MUL:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot multiply ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" with ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_DIV:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot divide ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf(" from ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_MOD:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot perform modular division ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" mod ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_POW:
			if(L->kind != TYPE_INTEGER || R->kind != TYPE_INTEGER){
				printf("type error: cannot exponentiate ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" ^ ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_POSTFIX_PLUS:
			if(L->kind != TYPE_INTEGER){
				printf("type error: cannot increment ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			} 
			if(e->left->kind != EXPR_IDENT) {
				printf("type error: cannot increment non-variable ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}	
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_POSTFIX_MINUS:
			if(L->kind != TYPE_INTEGER){
				printf("type error: cannot decrement ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}
			if(e->left->kind != EXPR_IDENT) {
				printf("type error: cannot decrement non-variable ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}	
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_LOGICAL_NOT:
			if(R->kind != TYPE_BOOLEAN){
				printf("type error: cannot negate non-boolean ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_LOGICAL_AND:
			if(L->kind != TYPE_BOOLEAN || R->kind != TYPE_BOOLEAN){
				printf("type error: cannot use && to compare non-boolean ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_LOGICAL_OR:
			if(L->kind != TYPE_BOOLEAN || R->kind != TYPE_BOOLEAN){
				printf("type error: cannot use && to compare non-boolean ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_INTEGER_LITERAL:
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_STRING_LITERAL:
			return type_create(TYPE_STRING, 0, 0, 0);
			break;
		case EXPR_CHAR_LITERAL:
			return type_create(TYPE_CHARACTER, 0, 0, 0);
			break;
		case EXPR_TRUE:
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_FALSE:
			return type_create(TYPE_BOOLEAN, 0, 0, 0);
			break;
		case EXPR_IDENT:
			return e->symbol->type;
			break;
		case EXPR_FCALL:
			if(L->kind != TYPE_FUNCTION) {
				printf("type error: cannot execute function call to non-function ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}
			function_typecheck(e->left->name, e->right, e->left->symbol->type->params, 1, function_params(e)+1);
			return L->subtype;
			break;
		case EXPR_ARRCALL:
			if(L->kind != TYPE_ARRAY) {
				printf("type error: cannot index into non-array ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			} 
			//return the number of subtypes that the index requires
			int i;
			struct type *T = L;
			for(i = 0; i < array_call_subtypes(e->right); i++){
				T = T->subtype;
			}
			return T;
			break;
		case EXPR_ARRINDEX:
			if(L->kind != TYPE_INTEGER){
				printf("type error: cannot index an array using non-integer ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf("\n");
				error_count++;
			}
			return type_create(TYPE_INTEGER, 0, 0, 0);
			break;
		case EXPR_PARENS:
			return R;
			break;
		case EXPR_BLOCK:
			return type_create(TYPE_ARRAY, 0, R, exprs_in_block(e)-1);
			break;
		case EXPR_BLOCK_COMMA:
			if(L->kind != R->kind && R->kind != TYPE_VOID){
				printf("type error: cannot have ");
				type_print(L);
				printf(" ");
				expr_print(e->left);
				printf(" and ");
				type_print(R);
				printf(" ");
				expr_print(e->right);
				printf(" in the same expression list\n");
				error_count++;
				return type_create(TYPE_VOID,0,0,0);
			}
			return L;
			break;
		case EXPR_COMMA:
			return R;
			break;
	}
}
Пример #14
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;
}
Пример #15
0
void stmt_typecheck( struct stmt *s, struct decl * current_function ) {
	if (!s) { return; }
	struct type * T = expr_typecheck(s->expr);
	switch (s -> kind) {
		case STMT_IF_ELSE:				
			T = expr_typecheck(s->expr);
			if(T->kind != TYPE_BOOLEAN){
				printf("type error: if condition is of type ");
				type_print(T);
				printf(" (");
				expr_print(s->expr);
				printf("), where a boolean value is required\n");
				error_count++;
			}
			stmt_typecheck(s->body,current_function);
			stmt_typecheck(s->else_body,current_function);
			break;
		// decl can't be a function decl if outside of global scope
		case STMT_DECL: 
			if(s->decl->type->kind == TYPE_FUNCTION){
				printf("type error: cannot declare a function (%s) nested in another function (%s)\n",s->decl->name,current_function->name);
				error_count++;
			}
			decl_typecheck(s->decl);
			break;
		case STMT_EXPR:
			expr_typecheck(s->expr);
			break;
		case STMT_FOR:
			expr_typecheck(s->init_expr);
			T = expr_typecheck(s->expr);
			if(T->kind != TYPE_BOOLEAN && T->kind != TYPE_VOID){
				printf("type error: for loop conditional is of type ");
				type_print(T);
				printf(" (");
				expr_print(s->expr);
				printf("), where a boolean value is required\n");
				error_count++;
			}
			expr_typecheck(s->next_expr);
			stmt_typecheck(s->body,current_function);
			break;
		case STMT_PRINT:
			expr_typecheck(s->expr);
			break;
		// check that value being returned matches the subtype of the function it is called in (the return values must match)
		case STMT_RETURN:
			if(current_function->type->subtype->kind != expr_typecheck(s->expr)->kind){
				printf("type error: cannot return ");
				type_print(expr_typecheck(s->expr));
				printf(" in function (%s) that returns ",current_function->name);
				type_print(current_function->type->subtype);
				printf("\n");
				error_count++;
			}
			break;
		case STMT_BLOCK:
			stmt_typecheck(s->body,current_function);
			break;
		case STMT_EMPTY:
			// do nothing
			break;
	}
	stmt_typecheck(s->next,current_function);
}
Пример #16
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);
    }
}