void Semantic::traverse(Decl * cur) { if (cur->v == Decl::STRUCT_T) { newSym(sid, Symbol(cur->ID, cur)); //declared but not defined pre = false; } else if (cur->v == Decl::FUNC_T) { newSym(vid.back(), Symbol(cur->ID, cur)); //declared but not defined pre = false; } else if (cur->v == Decl::USE_LIT_T) { if (!pre) error("#use directives must all be on the top"); //check if cur->ID file exists, parse it, cur parent gets this progitem appended } else if (cur->v == Decl::USE_LIB_T) { if (!pre) error("#use directives must all be on the top"); //check if cur->ID file exists whithin include path, parse it, cur parent gets this progitem appended } }
void Semantic::traverse(Defn * cur) { if (cur->v == Defn::STRUCT_T) { newSym(sid, Symbol(cur->id, cur)); //check struct types and names pairwise to be distinct ArgItem * ptr = cur->args; std::set<std::string> ids; while (ptr != NULL) { valSctType(ptr->arg->type); if (ids.find(ptr->arg->ID) != ids.end()) error("struct field names must be pairwise distinct"); ptr = ptr->next; } } else if (cur->v == Defn::FUNC_T) { //check ret type valRetType(cur->type); newSym(vid.back(), Symbol(cur->id, cur)); curF = cur->id; pushScope(); //check args types and names ArgItem * ptr = cur->args; std::set<std::string> ids; while (ptr != NULL) { valArgType(ptr->arg->type); newSym(vid.back(), Symbol(ptr->arg->ID, cur->type)); if (ids.find(ptr->arg->ID) != ids.end()) error("argument names must be pairwise distinct"); ptr = ptr->next; } pushScope(); traverse(cur->stmts); popScope(); popScope(); curF = ""; } else if (cur->v == Defn::TYPEDEF_T) { valArgType(cur->type); newSym(aid, Symbol(cur->id, cur)); } }
Table *check(Absyn * program, boolean showSymbolTables) { Table *globalTable; Entry *e; globalTable = newTable(NULL); if (showSymbolTables) { local_debug = TRUE; } /* generate built-in types */ builtinType_int = newPrimitiveType("int", INT_BYTE_SIZE); builtinType_bool = newPrimitiveType("bool", BOOL_BYTE_SIZE); Entry *builtinProc_exit = newProcEntry(emptyParamTypes(), newTable(globalTable), NULL); Entry *builtinProc_time = newProcEntry(newParamTypes (builtinType_int, TRUE, emptyParamTypes()), newTable(globalTable), NULL); Entry *builtinProc_readi = newProcEntry(newParamTypes (builtinType_int, TRUE, emptyParamTypes()), newTable(globalTable), NULL); Entry *builtinProc_readc = newProcEntry(newParamTypes (builtinType_int, TRUE, emptyParamTypes()), newTable(globalTable), NULL); Entry *builtinProc_printi = newProcEntry(newParamTypes (builtinType_int, FALSE, emptyParamTypes()), newTable(globalTable), NULL); Entry *builtinProc_printc = newProcEntry(newParamTypes (builtinType_int, FALSE, emptyParamTypes()), newTable(globalTable), NULL); Entry *builtinProc_clearAll = newProcEntry(newParamTypes (builtinType_int, FALSE, emptyParamTypes()), newTable(globalTable), NULL); Entry *builtinProc_setPixel = newProcEntry(newParamTypes(builtinType_int, FALSE, newParamTypes(builtinType_int, FALSE, newParamTypes (builtinType_int, FALSE, emptyParamTypes()))), newTable(globalTable), NULL); Entry *builtinProc_drawCircle = newProcEntry(newParamTypes(builtinType_int, FALSE, newParamTypes(builtinType_int, FALSE, newParamTypes (builtinType_int, FALSE, newParamTypes (builtinType_int, FALSE, emptyParamTypes())))), newTable(globalTable), NULL); Entry *builtinProc_drawLine = newProcEntry(newParamTypes(builtinType_int, FALSE, newParamTypes(builtinType_int, FALSE, newParamTypes (builtinType_int, FALSE, newParamTypes (builtinType_int, FALSE, newParamTypes (builtinType_int, FALSE, emptyParamTypes()))))), newTable(globalTable), NULL); /* setup global symbol table */ enter(globalTable, newSym("int"), newTypeEntry(builtinType_int)); enter(globalTable, newSym("exit"), builtinProc_exit); enter(globalTable, newSym("time"), builtinProc_time); enter(globalTable, newSym("readi"), builtinProc_readi); enter(globalTable, newSym("readc"), builtinProc_readc); enter(globalTable, newSym("printi"), builtinProc_printi); enter(globalTable, newSym("printc"), builtinProc_printc); enter(globalTable, newSym("clearAll"), builtinProc_clearAll); enter(globalTable, newSym("setPixel"), builtinProc_setPixel); enter(globalTable, newSym("drawCircle"), builtinProc_drawCircle); enter(globalTable, newSym("drawLine"), builtinProc_drawLine); /* enter all procs into global symtable */ enter_proc_decs(program, globalTable); /* do semantic checks */ checkNode(program, globalTable); /* check if "main()" is present */ e = lookup(globalTable, newSym("main")); if (e == NULL) error("procedure 'main' is missing"); if (e->kind != ENTRY_KIND_PROC) error("'main' is not a procedure"); // check that main has no params if (!e->u.procEntry.paramTypes->isEmpty) error("procedure 'main' must not have any parameters"); /* return global symbol table */ return globalTable; }
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"); } }