Type Semantic::expType(Exp * e) { if (e->v == Exp::ICONST_T) { return Type(Type::INT_T); } else if (e->v == Exp::STRLIT_T) { return Type(Type::STRING_T); } else if (e->v == Exp::CHRLIT_T) { return Type(Type::CHAR_T); } else if (e->v == Exp::BOLLIT_T) { return Type(Type::BOOL_T); } else if (e->v == Exp::NULL_T) { //return NULL?? return Type(Type::VOID_T); } else if (e->v == Exp::ID_T) { return *getSym(e->id).type; } else if (e->v == Exp::UNOP_T) { if (e->id == "~" || e->id == "!") { return Type(Type::BOOL_T); } else if (e->id == "++" || e->id == "--") { return Type(Type::INT_T); } else if (e->id == "-") { return expType(e->l); //return *getSym(e->l->id).type; } } else if (e->v == Exp::BINOP_T) { if (e->id == "<" || e->id == ">" || e->id == "<=" || e->id == ">=" || e->id == "!=" || e->id == "==" || e->id == "&" || e->id == "^" || e->id == "|" || e->id == "&&" || e->id == "||") { return Type(Type::BOOL_T); } else if (e->id == "+" || e->id == "*" || e->id == "-" || e->id == "/" || e->id == "%") { return Type(Type::INT_T); } } else if (e->v == Exp::IFLINE_T) { return Type(Type::VOID_T); } else if (e->v == Exp::FCALL_T) { return Type(Type::INT_T); //return *getSym(e->id).type; } else if (e->v == Exp::ACC_T || e->v == Exp::DOT_T) { return *getSym(e->id).type; } else if (e->v == Exp::SUBSC_T) { return Type(Type::VECTOR_T); } else if (e->v == Exp::ALLOC_T || e->v == Exp::ALLOCARRAY_T) { return Type(Type::POINTER_T); } throw std::runtime_error("Expression is not of any desired type."); }
void adjustActArgType (COND_EXPR *exp, hlType forType, PPROC pproc) /* Checks to determine whether the expression (actual argument) has the * same type as the given type (from the procedure's formal list). If not, * the actual argument gets modified */ { hlType actType; Int offset, offL, size; if (exp == NULL) return; actType = expType (exp, pproc); if ((actType != forType) && (exp->type == IDENTIFIER)) { switch (forType) { case TYPE_UNKNOWN: case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: case TYPE_RECORD: break; case TYPE_PTR: case TYPE_CONST: break; case TYPE_STR: switch (actType) { case TYPE_CONST: /* It's an offset into image where a string is * found. Point to the string. */ offL = exp->expr.ident.idNode.kte.kte; if (prog.fCOM) offset = (pproc->state.r[rDS]<<4) + offL + 0x100; else offset = (pproc->state.r[rDS]<<4) + offL; exp->expr.ident.idNode.strIdx = offset; exp->expr.ident.idType = STRING; break; case TYPE_PTR: /* It's a pointer to a char rather than a pointer to * an integer */ /***HERE - modify the type ****/ break; case TYPE_WORD_SIGN: break; } /* eos */ break; } } }
void Semantic::traverse(Exp * cur) { if (cur->v == Exp::ICONST_T || cur->v == Exp::STRLIT_T || cur->v == Exp::CHRLIT_T || cur->v == Exp::BOLLIT_T || cur->v == Exp::NULL_T) { //we're dealing with a constant here, ensure int constant in 0 2^31 if (cur->v == Exp::ICONST_T) if (cur->id.length() == std::string("2147483647").length() && cur->id > "2147483647") error("integer literal constants must be < 2^31"); } else if (cur->v == Exp::ID_T) { //variable getSym(cur->id); } else if (cur->v == Exp::UNOP_T) { //ensure subexp type is char or int Type l = expType(cur->l); if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T)))) error("unop must be applied to expression of type int or char"); traverse(cur->l); } else if (cur->v == Exp::BINOP_T) { //if <=, <, >, >= ensure int or char //if != or == ensure int bool char t[] or t* Type l = expType(cur->l), r = expType(cur->r); if (cur->id == "==" || cur->id == "!="); if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T)))) error("binop must be applied to expression of type int or char or bool"); else if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T)))) error("binop must be applied to expression of type int or char or bool"); traverse(cur->l); traverse(cur->r); } else if (cur->v == Exp::IFLINE_T) { Type l = expType(cur->l); if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T)))) error("Condition must be of type bool"); traverse(cur->l); traverse(cur->m); traverse(cur->r); } else if (cur->v == Exp::FCALL_T) { if (cur->id == "print" || cur->id == "read_int") return; Symbol func = getSym(cur->id); if (func.decl == NULL && func.defn == NULL) { error("call to undeclared function " + cur->id); return; } ArgItem * ptr = (func.decl != NULL) ? func.decl->list : func.defn->args; ExpItem * old = cur->args; while (ptr != NULL) { if (old == NULL) { error("bad argument passed to function " + cur->id); break; } if (!sameType(*(ptr->arg->type), expType(old->exp))) { error("bad argument passed to function " + cur->id); break; } traverse(old->exp); ptr = ptr->next; old = old->next; } if (old != NULL) error("bad argument passed to function " + cur->id); } else if (cur->v == Exp::DOT_T) { //see if type has that field Type t = expType(cur->l); if (t.v != Type::STRUCT_T) error("accessing field in a non-struct type"); Symbol s = getFromMap(sid, t.str); bool hasField = false; ArgItem * ptr = s.defn->args; while (ptr != NULL) { if (ptr->arg->ID == cur->id) { hasField = true; break; } ptr = ptr->next; } if (!hasField) error("accessing non existing struct field " + cur->id); } else if (cur->v == Exp::ACC_T) { //see if type has that field Type t = expType(cur->l); if (t.v != Type::POINTER_T || t.type->v != Type::STRUCT_T) error("referencing field in a pointer to struct type"); Symbol s = getFromMap(sid, t.type->str); bool hasField = false; ArgItem * ptr = s.defn->args; while (ptr != NULL) { if (ptr->arg->ID == cur->id) { hasField = true; break; } ptr = ptr->next; } if (!hasField) error("referencing non existing struct field " + cur->id); } else if (cur->v == Exp::SUBSC_T) { //see if subst is char or int and other type is vector Type l = expType(cur->l); Type r = expType(cur->r); if (l.v != Type::VECTOR_T) error("accessing index in non-vector type"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T)))) error("index type must be int or char"); traverse(cur->l); traverse(cur->r); } else if (cur->v == Exp::ALLOC_T) { //return the little thing allocated in memory (heap?) if (cur->t->v != Type::STRUCT_T) error("cannot alloc non-struct type"); } else if (cur->v == Exp::ALLOCARRAY_T) { //return the little thing[] allocated in memory (heap?) Type r = expType(cur->l); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T)))) error("alloc_array size must be type int"); traverse(cur->l); } }
void Semantic::traverse(Stmt * cur) { if (cur->v == Stmt::LIST_T) { pushScope(); traverse(cur->list); popScope(); } else if (cur->v == Stmt::IF_T || cur->v == Stmt::WHILE_T) { if (cur->v == Stmt::WHILE_T) loops.push(cur); Type t = expType(cur->exp); traverse(cur->exp); if (t.v == Type::INT_T || t.v == Type::CHAR_T) { //warning pushScope(); traverse(cur->left); popScope(); } else if (t.v == Type::BOOL_T) { pushScope(); traverse(cur->left); popScope(); } else error("Condition must be of type bool"); if (cur->v == Stmt::WHILE_T) loops.pop(); } else if (cur->v == Stmt::FOR_T) { loops.push(cur); pushScope(); traverse(cur->left); Type t = expType(cur->exp); traverse(cur->exp); if (t.v == Type::INT_T || t.v == Type::CHAR_T) { //warning pushScope(); traverse(cur->stmt); popScope(); } else if (t.v == Type::BOOL_T) { pushScope(); traverse(cur->stmt); popScope(); } else error("Condition must be of type bool"); if (hasDecl(cur->right)) error("For loop-end statement must not include declarations"); traverse(cur->right); popScope(); loops.pop(); } else if (cur->v == Stmt::RETURN_T) { //check current function return type and compare it with this if (!sameType(expType(cur->exp), *getSym(curF).defn->type)) error("return expression type differs from function " + curF + " signature"); if (cur->exp != NULL) traverse(cur->exp); } else if (cur->v == Stmt::ASSERT_T) { //check argument type to be of bool if (!sameType(expType(cur->exp), Type(Type::BOOL_T))) error("assert expression type must be bool"); traverse(cur->exp); } else if (cur->v == Stmt::ERROR_T) { //call error function with argment string if (!sameType(expType(cur->exp), Type(Type::STRING_T))) error("error argument must be of type string"); traverse(cur->exp); } else if (cur->v == Stmt::ASSIGN_T) { //check if lhs and rhs same type, ensure rhs and lhs is not a struct Type l = lvalType(cur->lval), r = expType(cur->exp); traverse(cur->exp); if (cur->op == "=") { if (!sameType(l, r)) error("lval and expression have different types"); } else if (cur->op == ">>=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from right shift must be of type int or char"); if (!sameType(r, Type(Type::INT_T))) error("shift ammount must be of type int"); } else if (cur->op == "<<=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from left shift must be of type int or char"); if (!sameType(r, Type(Type::INT_T))) error("shift ammount must be of type int"); } else if (cur->op == "+=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from add assign must be of type int or char"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)))) error("expression from add assign must be of type int or char"); } else if (cur->op == "-=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from sub assign must be of type int or char"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)))) error("expression from sub assign must be of type int or char"); } else if (cur->op == "*=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from mul assign must be of type int or char"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)))) error("expression from mul assign must be of type int or char"); } else if (cur->op == "/=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from div assign must be of type int or char"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)))) error("expression from div assign must be of type int or char"); } else if (cur->op == "%=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from mod assign must be of type int or char"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)))) error("expression from mod assign must be of type int or char"); } else if (cur->op == "&=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T)))) error("lval from and assign must be of type int or char or bool"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T)))) error("expression from and assign must be of type int or char or bool"); } else if (cur->op == "^=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T)))) error("lval from xor assign must be of type int or char or bool"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T)))) error("expression from xor assign must be of type int or char or bool"); } else if (cur->op == "|=") { if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T)))) error("lval from or assign must be of type int or char or bool"); if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T)))) error("expression from or assign must be of type int or char or bool"); } } else if (cur->v == Stmt::INC_T) { //check if lhs is int or char Type l = lvalType(cur->lval); if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from increment must be of type int or char"); } else if (cur->v == Stmt::DEC_T) { //check if lhs is int or char Type l = lvalType(cur->lval); if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)))) error("lval from decrement must be of type int or char"); } else if (cur->v == Stmt::EXP_T) { traverse(cur->exp); } else if (cur->v == Stmt::DECL_T) { //declaring a variable newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type)); } else if (cur->v == Stmt::DECLI_T) { //declaring and assigning a variable newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type)); } else if (cur->v == Stmt::BREAK_T) { //check most recent loop if (loops.empty()) error("break statement does not have a loop"); } else if (cur->v == Stmt::CONT_T) { if (loops.empty()) error("continue statement does not have a loop"); } }