extern data list_start( arg_s *parg, /* arg entry causing call */ callinfo_s *pinfo, /* info we need to pass around */ long *plength) /* for varying length fields */ { /* take a type number and a buffer, and push them on the field list stack, * emit field */ list_s *list; /* new list */ parg; plength; list = (list_s *)calloc(sizeof(list_s), 1); if (list == 0) { fatal("cannot allocate list structure\n"); } /* if */ list->type = type_create(); list->next = list_stack; list->psym = pinfo->psym; list_stack = list; if (proc_arg_count_ptr) { /* we had previously been asked to stuff an arg count in a * LF_PROCEDURE, now we bind that request to this list. */ list->pproccount = proc_arg_count_ptr; proc_arg_count_ptr = 0; } /* if */ return type_get_index(list->type); } /* list_start */
static Endpoint_t *create_builtin_reader (Domain_t *dp, Builtin_Type_t type, const char *topic_name, const char *type_name) { TopicType_t *typep; Topic_t *tp; Reader_t *rp; DDS_TopicQos qos_data; typep = type_create (dp, type_name, NULL); if (!typep) return (NULL); typep->flags = EF_LOCAL | EF_BUILTIN; typep->index = type; tp = topic_create (&dp->participant, NULL, topic_name, type_name, NULL); if (!tp) return (NULL); tp->entity.flags |= EF_ENABLED | EF_BUILTIN | EF_NOT_IGNORED; qos_data = qos_def_topic_qos; qos_data.durability.kind = DDS_TRANSIENT_LOCAL_DURABILITY_QOS; qos_data.reliability.kind = DDS_RELIABLE_RELIABILITY_QOS; tp->qos = qos_topic_new (&qos_data); if (!tp->qos) { topic_delete (&dp->participant, tp, NULL, NULL); return (NULL); } rp = DDS_Subscriber_create_datareader (dp->builtin_subscriber, (DDS_TopicDescription) tp, DDS_DATAREADER_QOS_USE_TOPIC_QOS, NULL, 0); if (!rp) { topic_delete (&dp->participant, tp, NULL, NULL); return (NULL); } dp->builtin_readers [type] = rp; #ifdef RTPS_USED if (rtps_used) disc_populate_builtin (dp, type); #endif return (&rp->r_ep); }
// recursively copy all the way down. struct type * type_copy(struct type *t){ if(!t) return NULL; struct type * temp = type_create(t->kind, param_list_copy(t->params), type_copy(t->subtype), expr_copy(t->opt_expr)); return temp; }
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); }
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); } }
DDS_ReturnCode_t DDS_DomainParticipant_register_type (DDS_DomainParticipant dp, DDS_TypeSupport ts, const char *type_name) { TopicType_t *typep; TypeSupport_t *pts; DDS_ReturnCode_t ret; #ifdef DDS_TYPECODE unsigned char *vtc; #endif ctrc_begind (DCPS_ID, DCPS_DP_R_TYPE, &dp, sizeof (dp)); ctrc_contd (&ts, sizeof (ts)); ctrc_contd (type_name, strlen (type_name)); ctrc_endd (); prof_start (dcps_reg_type); /* Validate some required arguments. */ if (!ts) return (DDS_RETCODE_BAD_PARAMETER); if (!domain_ptr (dp, 1, &ret)) return (ret); if (!type_name && (type_name = DDS_TypeSupport_get_type_name (ts)) == NULL) return (DDS_RETCODE_BAD_PARAMETER); /* Search type name in participant type list. */ typep = type_lookup (dp, type_name); if (typep) { if ((pts = typep->type_support) != NULL) { #ifdef DDS_TYPECODE /* Type already learned from remote peers? */ if (pts->ts_prefer >= MODE_V_TC) { vtc = (unsigned char *) pts->ts_vtc; if (!vtc_identical (ts, vtc)) { /* Oops: already present in domain but incompatible - notify later when a topic is created. */ typep->flags |= EF_INC_TYPE; type_promote_tc (dp, typep, ts, NULL); } else { typep->flags &= ~EF_INC_TYPE; type_promote_tc (dp, typep, ts, vtc); } /* Replace with real type support.*/ xfree (typep->type_support); typep->type_support = (TypeSupport_t *) ts; vtc_free (vtc); } else /* Already defined: check compatibility. */ if (ts->ts_prefer != pts->ts_prefer || ts->ts_keys != pts->ts_keys || ts->ts_fksize != pts->ts_fksize || ts->ts_length != pts->ts_length || ts->ts_mkeysize != pts->ts_mkeysize) return (DDS_RETCODE_PRECONDITION_NOT_MET); else if (ts->ts_prefer == MODE_CDR) { if (!xt_type_equal (ts->ts_cdr, pts->ts_cdr)) return (DDS_RETCODE_PRECONDITION_NOT_MET); } else if (ts->ts_prefer == MODE_PL_CDR) { if (pts->ts_pl->builtin || ts->ts_pl->builtin || !xt_type_equal (ts->ts_pl->xtype, pts->ts_pl->xtype)) return (DDS_RETCODE_PRECONDITION_NOT_MET); } else #else if (pts != ts) #endif return (DDS_RETCODE_PRECONDITION_NOT_MET); } else { typep->type_support = (TypeSupport_t *) ts; typep->type_support->ts_users++; } } else { /* Doesn't exist yet -- allocate new type context. */ typep = type_create (dp, type_name, NULL); if (!typep) { warn_printf ("create_topic_type (%s): out of memory for topic type!\r\n", type_name); lock_release (dp->lock); return (DDS_RETCODE_OUT_OF_RESOURCES); } typep->type_support = (TypeSupport_t *) ts; typep->type_support->ts_users++; } typep->flags |= EF_LOCAL; typep->nrefs++; typep->nlrefs++; lock_release (dp->lock); prof_stop (dcps_reg_type, 1); return (DDS_RETCODE_OK); }
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); }
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; } }
struct type *expr_typecheck(struct expr *e){ if (e == NULL) { return type_create(TYPE_VOID,0,0,0); } struct type *l = malloc(sizeof(struct type)); struct type *r = malloc(sizeof(struct type)); switch (e->kind){ case (EXPR_ADD): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot add "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_SUB): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot subtract "); type_print(l); literal_print(e->left); printf(" from "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_MUL): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot multiply "); type_print(l); literal_print(e->left); printf(" and "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_DIV): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot divide "); type_print(l); literal_print(e->left); printf(" by "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_INCREMENT): l = expr_typecheck(e->left); if (l->kind != TYPE_INTEGER){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot increment "); type_print(l); literal_print(e->left); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_DECREMENT): l = expr_typecheck(e->left); if (l->kind != TYPE_INTEGER){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot decrement "); type_print(l); literal_print(e->left); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_NOT): r = expr_typecheck(e->right); if (r->kind != TYPE_BOOLEAN){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot negate "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_POWER): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot raise "); type_print(l); literal_print(e->left); printf(" to power "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_MODULO): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot take modulus of "); type_print(l); literal_print(e->left); printf(" and "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_INTEGER,0,0,0); } break; case (EXPR_LESS_THAN): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_GREATER_THAN): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_LESS_THAN_OR_EQUAL): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_GREATER_THAN_OR_EQUAL): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_INTEGER) || (r->kind != TYPE_INTEGER)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_EQUIVALENCE_COMPARISON): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind == TYPE_FUNCTION) || (r->kind == TYPE_FUNCTION)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of functions\n"); e->type = 0; } else if ((l->kind == TYPE_ARRAY) || (r->kind == TYPE_ARRAY)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of arrays\n"); e->type = 0; } else if (l->kind != r->kind){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_NONEQUIVALENCE_COMPARISON): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind == TYPE_FUNCTION) || (r->kind == TYPE_FUNCTION)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of functions\n"); e->type = 0; } else if ((l->kind == TYPE_ARRAY) || (r->kind == TYPE_ARRAY)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of arrays\n"); e->type = 0; } else if (l->kind != r->kind){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare equivalence of "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_AND): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_BOOLEAN) || (r->kind != TYPE_BOOLEAN)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_OR): l = expr_typecheck(e->left); r = expr_typecheck(e->right); if ((l->kind != TYPE_BOOLEAN) || (r->kind != TYPE_BOOLEAN)){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot compare "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(TYPE_BOOLEAN,0,0,0); } break; case (EXPR_ASSIGNMENT): l = expr_typecheck(e->left); r = expr_typecheck(e->right); //if ((l->kind == TYPE_FUNCTION) || (r->kind == TYPE_FUNCTION)){ if (l->kind == TYPE_FUNCTION){ error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot assign a function\n"); e->type = 0; } else if (l->kind != r->kind) { error_counter += 1; printf("Error #%i ",error_counter); printf("type error: cannot assign "); type_print(l); literal_print(e->left); printf(" to "); type_print(r); literal_print(e->right); printf("\n"); e->type = 0; } else { e->type = type_create(l->kind,0,0,0); } break; case (EXPR_BOOLEAN_LITERAL): e->type = type_create(TYPE_BOOLEAN, 0, 0, 0); break; case (EXPR_INTEGER_LITERAL): e->type = type_create(TYPE_INTEGER, 0, 0, 0); break; case (EXPR_CHARACTER_LITERAL): e->type = type_create(TYPE_CHARACTER, 0, 0, 0); break; case (EXPR_STRING_LITERAL): e->type = type_create(TYPE_STRING, 0, 0, 0); break; case (EXPR_IDENTIFIER): e->type = e->symbol->type; break; case (EXPR_PARENTHESES): e->type = expr_typecheck(e->left); break; case (EXPR_FUNCTION_CALL): param_list_typecheck(); e->type = e->left->symbol->type->subtype; break; case (EXPR_ARRAY_INDEX): e->type = type_create(TYPE_ARRAY, 0, 0, 0); break; } return e->type; }
struct type * expr_typecheck(struct expr *e) { if (!e) return type_create(TYPE_VOID, 0, 0); struct type *l, *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); } }