/** * Checks for invalid methods (e.g., overloading vs. overriding) */ void typecheck::CheckScope::checkMethods(ClassNode* cls) { string* superName = cls->getSuper(); if(superName == nullptr) { return; } Groot* groot = cls->getLexParent(); /* For every method defined in this class... */ for(auto method_kv : cls->getMethods()) { string methodSig = getMethodSig(cls, string(method_kv.first)); /* Step up the inheritance tree, checking for another method with the same signature */ while(superName != nullptr) { ClassNode* superClass = groot->getClasses()[*superName]; // Get the node for the symbol class. Note that cls->getLexParent() returns Groot. superName = superClass->getSuper(); /* If this super doesn't have a method by the correct name, don't bother checking the signatures */ if(superClass->getMethods().find(method_kv.first) == superClass->getMethods().end()) { continue; } if(methodSig != getMethodSig(superClass, method_kv.first)) { std::stringstream msg; msg << "Error: Method '" << method_kv.first << "' has a different signature from the super class"; throw ScopeCheckErr(msg.str().c_str()); } } } }
/** * Defines the requirements for a valid class scope * Throws a ScopeCheckErr exception if there's a problem. */ void typecheck::CheckScope::checkClass(typecheck::ClassNode* cls) { string* superName = cls->getSuper(); if(superName == nullptr) { return; } /* Register the super class if it exists, but flag it as unimplemented. If the class already exists in the confirmedClasses map, don't reset it (we don't want to stomp a value of true with a value of false) */ if(confirmedClasses.find(*superName) == confirmedClasses.end()) { confirmedClasses.insert(std::pair<string, bool>(*superName, false)); } /* Make sure there aren't any attributes defined in this class that are also defined in its parent. */ Groot* groot = cls->getLexParent(); for(auto attr_kv : cls->getMembers()) { /* Step up the inheritance tree, checking for variables with similar names */ while(superName != nullptr) { ClassNode* superClass = groot->getClasses()[*superName]; // Get the node for the symbol class. Note that cls->getLexParent() returns Groot. /* If the this super class has the same variable, throw error */ if(superClass->getMembers().count(attr_kv.first) >= 1) { std::stringstream msg; msg << "Error: Instance variable '" << attr_kv.first << "' already exists in a super class '" << *superName << "'" << endl; throw ScopeCheckErr(msg.str().c_str()); } superName = superClass->getSuper(); } } }
/** * Checks for inheritance cycles of classes. */ void typecheck::CheckScope::checkInheritanceCycles(typecheck::ClassNode* cls) { Groot* groot = cls->getLexParent(); std::set<ClassNode*> visitedClasses; ClassNode* cur = cls; string* superName = cls->getSuper(); while(superName != nullptr) { if(visitedClasses.find(cur) == visitedClasses.end()) { visitedClasses.insert(cur); } else { std::stringstream msg; msg << "Error: Class '" << *superName << "' is in an inheritance cycle." << endl; throw ScopeCheckErr(msg.str().c_str()); } cur = groot->getClasses()[*superName]; superName = cur->getSuper(); } }