void SymbolCheckVisitor::visit(ASTFunction& ast) { ScopedScope scope(mScopeStack); ScopedValue<ASTFunction*> scopedfunction(&mpFunction, &ast, mpFunction); ASSERT_PTR(mpFunction); visitChildren(ast); // <-- arguments if ( ast.isConstructor() && ast.getName() != mpClass->getName() ) { error(E0005, UTEXT("Function ") + ast.getName() + UTEXT(" must have a return type (or equal class name as constructor)."), ast); } if ( ast.hasBody() ) { if ( ast.getModifiers().isAbstract() ) { error(E0006, UTEXT("Abstract function ") + ast.getName() + UTEXT(" should not have a body."), ast); } else { checkReturn(ast); ast.getBody().accept(*this); } } else if ( !ast.getModifiers().isAbstract() && !ast.getModifiers().isPureNative() ) { error(E0007, UTEXT("Function ") + ast.getName() + UTEXT(" requires a body."), ast); } mCurrentType.clear(); }
void ASTFunctionTable::insert(ASTFunction& function) { for ( std::size_t index = 2; index < mFunctions.size(); index++ ) { ASTFunction* pfunction = mFunctions[index]; if ( pfunction->getName() == function.getName() && pfunction->getSignature().exactMatch(function.getSignature()) ) // for now do not allow derived types { mFunctions[index] = &function; return; } } mFunctions.push_back(&function); }
void SymbolCheckVisitor::checkReturn(const ASTFunction& function) { checkUnknown(function.getType()); if ( !function.getType().isVoid() ) { // ensure that we have a return statement bool hasunreachablecode = false; if ( !function.getBody().hasReturn(hasunreachablecode) ) { error(E0045, UTEXT("Function ") + function.getName() + UTEXT(" should return a value of type ") + function.getType().toString(), function.getPosition()); } else if ( hasunreachablecode ) { warning(W0003, UTEXT("Unreachable code in ") + function.getName(), function.getPosition()); } } }
void OOCheckVisitor::visit(ASTFunction& ast) { mpFunction = * ScopedScope scope(mScopeStack); ast.getArgumentNodes().accept(*this); if ( ast.hasAnnotations() ) { if ( ast.getAnnotations().contains(UTEXT("override")) ) { // check if the base class still has this function } } if ( ast.isConstructor() ) { // abstract classes can not have native constructors /* if ( ast.getModifiers().isNative() && mpClass->getModifiers().isAbstract() ) { mContext.getLog().error("Abstract class " + mpClass->getFullName() + " can not have native constructors."); } */ } else { if ( mpClass->hasBaseClass() ) { ASTClass& baseclass = mpClass->getBaseClass(); ASTFunction* pbasefunc = baseclass.findExactMatch(ast.getName(), ast.getSignature()); if ( pbasefunc != NULL ) { ast.setBaseFunction(*pbasefunc); } } } if ( ast.hasBody() ) { mHasNativeCall = false; ast.getBody().accept(*this); if ( mHasNativeCall ) { ast.getModifiers().setNative(true); } } }
void CodeGeneratorVisitor::visit(ASTFunction& ast) { CIL::Function* pfunction = new CIL::Function(); pfunction->setName(ast.getName()); pfunction->setReturnType(toCilType(ast.getType())); pfunction->setModifiers(toCilModifiers(ast.getModifiers())); // copy the arguments const ASTNodes& nodes = ast.getArgumentNodes(); for ( int index = 0; index < nodes.size(); ++index ) { const ASTFunctionArgument& arg = static_cast<const ASTFunctionArgument&>(nodes[index]); pfunction->addArgument(toCilType(arg.getVariable().getType())); } if ( ast.hasAnnotations() ) { const ASTAnnotations& annotations = ast.getAnnotations(); for ( int index = 0; index < annotations.size(); ++index ) { const ASTAnnotation& anno = annotations[index]; pfunction->addAnnotation(anno.mName); } } if ( !ast.getModifiers().isPureNative() ) { mCurrentType.clear(); if ( ast.hasBody() ) { mpFunction = * mBuilder.start(); ScopedScope scope(mScopeStack); const ASTBlock& block = ast.getBody(); block.accept(*this); mBuilder.end(); // set the generated content pfunction->setInstructions(mBuilder.getInstructions()); pfunction->setGuards(mBuilder.getGuards()); pfunction->setSwitchTables(mBuilder.getSwitchTables()); } // copy the locals const ASTTypeList& locals = ast.getLocals(); for ( int index = 0; index < locals.size(); ++index ) { const ASTType& local = locals[index]; yasc::Type* ptype = yasc::Type::fromString(local.toString()); pfunction->addLocal(ptype); } // clean up the code body to save memory ast.cleanup(); } mpClass->getCompiledClass().add(pfunction); }