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()); } } }
bool ASTNaryFunctionNode::isSqrt() const { bool valid = false; if (getType() == AST_FUNCTION_ROOT) { // a sqrt can have either one child that is not the degree qualifier // or two where the first is the degree of 2 if (getNumChildren() == 1) { /* HACK to replicate OLD AST whic says a sqrt must have two children*/ valid = false; //ASTBase * base1 = getChild(0); //if (base1->isQualifier() == false) //{ // valid = true; //} } else if (getNumChildren() == 2) { ASTBase * base1 = ASTFunctionBase::getChild(0); ASTFunction* fun = dynamic_cast<ASTFunction*>(base1); if (fun != NULL) { if (fun->getType() == AST_QUALIFIER_DEGREE && fun->getNumChildren() == 1) { ASTBase *base2 = fun->getChild(0); if (base2->getType() == AST_INTEGER) { ASTNumber *child = static_cast<ASTNumber*>(base2); if (child->getInteger() == 2) { valid = true; } } } } else { // here we are working the ASTNode so the casting // is more difficult ASTNode* newAST = dynamic_cast<ASTNode*>(base1); if (newAST != NULL && newAST->getType() == AST_QUALIFIER_DEGREE && newAST->getNumChildren() == 1) { ASTNode* newAST1 = newAST->getChild(0); if (newAST1->getType() == AST_INTEGER) { if (newAST1->getInteger() == 2) { valid = true; } } } else { if (newAST != NULL && newAST->getType() == AST_INTEGER) { if (newAST->getInteger() == 2) { valid = true; } } } } } } return valid; }
bool ASTNaryFunctionNode::isLog10() const { bool valid = false; if (getType() == AST_FUNCTION_LOG) { // a log can have either one child that is not the logbase qualifier // or two where the first is the logbase of 10 if (getNumChildren() == 1) { ASTBase * base1 = ASTFunctionBase::getChild(0); if (base1->isQualifier() == false) { valid = true; } } else if (getNumChildren() == 2) { ASTBase * base1 = ASTFunctionBase::getChild(0); ASTFunction* fun = dynamic_cast<ASTFunction*>(base1); if (fun != NULL) { if (fun->getType() == AST_QUALIFIER_LOGBASE && fun->getNumChildren() == 1) { ASTBase *base2 = fun->getChild(0); if (base2->getType() == AST_INTEGER) { ASTNumber *child = static_cast<ASTNumber*>(base2); if (child->getInteger() == 10) { valid = true; } } } } else { // here we are working the ASTNode so the casting // is more difficult ASTNode* newAST = dynamic_cast<ASTNode*>(base1); if (newAST != NULL && newAST->getType() == AST_QUALIFIER_LOGBASE && newAST->getNumChildren() == 1 ) { ASTNode* newAST1 = newAST->getChild(0); if (newAST1->getType() == AST_INTEGER) { if (newAST1->getInteger() == 10) { valid = true; } } } else { if (newAST != NULL && newAST->getType() == AST_INTEGER) { if (newAST->getInteger() == 10) { valid = true; } } } } } } return valid; }
bool ASTBinaryFunctionNode::isSqrt() const { bool valid = false; ASTBase * base1 = NULL; if (getType() == AST_FUNCTION_ROOT) { if (getNumChildren() == 2) { base1 = getChild(0); ASTFunction* fun = dynamic_cast<ASTFunction*>(base1); if (fun != NULL) { if (fun->getType() == AST_QUALIFIER_DEGREE && fun->getNumChildren() == 1) { ASTBase *base2 = fun->getChild(0); if (base2->getType() == AST_INTEGER) { ASTNumber *child = static_cast<ASTNumber*>(base2); if (child->getInteger() == 2) { valid = true; } } } } else { // here we are working the ASTNode so the casting // is more difficult ASTNode* newAST = dynamic_cast<ASTNode*>(base1); if (newAST != NULL && newAST->getType() == AST_QUALIFIER_DEGREE && newAST->getNumChildren() == 1) { ASTNode* newAST1 = newAST->getChild(0); if (newAST1->getType() == AST_INTEGER) { if (newAST1->getInteger() == 2) { valid = true; } } } else { if (newAST != NULL && newAST->getType() == AST_INTEGER) { if (newAST->getInteger() == 2) { valid = true; } } } } } } return valid; }
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); }