private void handleMethod(Method method, boolean isVirtual) throws SemanticError { MethodType methodType = (MethodType) TypeAdapter.adaptType(method); // check if method legally overrides superclass method ISymbolTable methodSymTable = method.getEnclosingScope(); if (methodSymTable == null) throw new RuntimeException("Unconnected ASTNode to scope"); SymbolTable classSymTable = methodSymTable.getParentSymbolTable(); if (classSymTable == null) throw new RuntimeException("Method super-scope is null"); ISymbolTable superClassSymTable = classSymTable.getParentSymbolTable(); if (superClassSymTable != null && superClassSymTable.isClassTable()) { Symbol superMethodSym = superClassSymTable.lookup(method.getName(), method); // in case method name is not found in parent, disregard override // check if (superMethodSym != null) { // check illegal override if (!methodType.equals(superMethodSym.getIdType())) { throw new SemanticError( "method " + method.getName() + " in type " + classSymTable.getId() + " is overridden illegally (type mismatch)", method); } if ((isVirtual && superMethodSym.isStaticMethod()) || (!isVirtual && superMethodSym.isVirtualMethod())) { throw new SemanticError( "method " + method.getName() + " in type " + classSymTable.getId() + " is overridden illegally (virtual/static mismatch)", method); } } } // iterate all statements for (Statement stmt : method.getStatements()) stmt.accept(this); Types.Type methodRetType = methodType.getReturnType(); // Check return paths if (!methodRetType.equals(TypeTable.voidType) && !this.hasReturnOnControlPaths(method.getStatements())) throw new SemanticError( "The method must return a result of type " + methodType.getReturnType(), method); }