Example #1
0
/**
 * 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());
      }
    }
  }
}
Example #2
0
/**
 * 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();
    }
  }
}
Example #3
0
/**
 * 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();
  }
}