void Unparse_Jovial::unparseIfStmt(SgStatement* stmt, SgUnparse_Info& info) { SgIfStmt* if_stmt = isSgIfStmt(stmt); ROSE_ASSERT(if_stmt != NULL); ROSE_ASSERT(if_stmt->get_conditional()); // condition curprint("IF ("); info.set_inConditional(); SgExprStatement* expressionStatement = isSgExprStatement(if_stmt->get_conditional()); unparseExpression(expressionStatement->get_expression(), info); info.unset_inConditional(); curprint(") ;"); unp->cur.insert_newline(1); // true body ROSE_ASSERT(if_stmt->get_true_body()); unparseStatement(if_stmt->get_true_body(), info); // false body if (if_stmt->get_false_body() != NULL) { curprint("ELSE"); unp->cur.insert_newline(1); unparseStatement(if_stmt->get_false_body(), info); } }
string Doxygen::getQualifiedPrototype(SgNode *node) { SgClassDeclaration *cd = dynamic_cast<SgClassDeclaration *>(node); if (cd) return getProtoName(cd); SgUnparse_Info info; info.set_SkipSemiColon(); info.set_SkipFunctionDefinition(); info.set_forceQualifiedNames(); info.set_skipCheckAccess(); info.set_SkipClassSpecifier(); info.set_SkipInitializer(); info.set_current_scope(TransformationSupport::getGlobalScope(node)); string proto = node->unparseToString(&info); while (proto[proto.size()-1] == '\n') { /* sometimes the prototype will be unparsed with a newline at the end */ proto.resize(proto.size()-1); } return proto; }
// DQ (8/14/2007): This function does not make sense for Fortran. void UnparseFortran_type::unparseClassType(SgType* type, SgUnparse_Info& info) { // printf ("Inside of UnparserFortran::unparseClassType \n"); SgClassType* class_type = isSgClassType(type); ROSE_ASSERT(class_type != NULL); // DQ (10/7/2004): We need to output just the name when isTypeFirstPart == false and isTypeSecondPart == false // this allows us to handle: "doubleArray* arrayPtr2 = new doubleArray();" if (info.isTypeSecondPart() == false) { // Fortran is not as complex as C++, so we can, at least for now, skip the name qualification! ROSE_ASSERT(class_type != NULL); curprint("TYPE ( "); curprint(class_type->get_name().str()); curprint(" ) "); } }
string FixupTemplateArguments::generate_string_name (SgType* type, SgNode* nodeReferenceToType) { // DQ (2/11/2017): This function has been added to support debugging. It is a current problem that // the substitution of private types in template arguments with type aliases not containing private // types, is that the typename can be generated to be extremely large (e.g 803+ million characters long). SgUnparse_Info* unparseInfoPointer = new SgUnparse_Info(); ROSE_ASSERT (unparseInfoPointer != NULL); unparseInfoPointer->set_outputCompilerGeneratedStatements(); // Avoid unpasing the class definition when unparseing the type. unparseInfoPointer->set_SkipClassDefinition(); // DQ (5/8/2013): Added specification to skip enum definitions also (see test2012_202.C). unparseInfoPointer->set_SkipEnumDefinition(); // Associate the unparsing of this type with the statement or scope where it occures. // This is the key to use in the lookup of the qualified name. But this is the correct key.... // unparseInfoPointer->set_reference_node_for_qualification(positionStatement); // unparseInfoPointer->set_reference_node_for_qualification(currentScope); unparseInfoPointer->set_reference_node_for_qualification(nodeReferenceToType); // DQ (5/7/2013): A problem with this is that it combines the first and second parts of the // type into a single string (e.g. the array type will include two parts "base_type" <array name> "[index]". // When this is combined for types that have two parts (most types don't) the result is an error // when the type is unparsed. It is not clear, but a solution might be for this to be built here // as just the 1st part, and let the second part be generated when the array type is unparsed. // BTW, the reason why it is computed here is that there may be many nested types that require // name qualifications and so it is required that we save the whole string. However, name // qualification might only apply to the first part of types. So we need to investigate this. // This is a problem demonstrated in test2013_156.C and test2013_158.C. // DQ (5/8/2013): Set the SgUnparse_Info so that only the first part will be unparsed. unparseInfoPointer->set_isTypeFirstPart(); // DQ (8/19/2013): Added specification to skip class specifier (fixes problem with test2013_306.C). unparseInfoPointer->set_SkipClassSpecifier(); string typeNameString = globalUnparseToString(type,unparseInfoPointer); return typeNameString; }
string Doxygen::getProtoName(SgDeclarationStatement *st) { SgScopeStatement *scope; if (SgVariableDeclaration* varDeclSt = isSgVariableDeclaration(st)) { // TODO: uncomment SgVariableDeclaration::get_scope removing need for this code scope = varDeclSt->get_variables().front()->get_scope(); } else { scope = st->get_scope(); } if (isSgGlobal(scope)) { return getDeclStmtName(st); } else { SgUnparse_Info info; info.set_SkipSemiColon(); info.set_SkipFunctionDefinition(); info.set_forceQualifiedNames(); info.set_skipCheckAccess(); info.set_SkipInitializer(); info.set_SkipClassSpecifier(); //AS(091507) In the new version of ROSE global qualifiers are paret of the qualified name of //a scope statement. For the documentation work we do not want that and we therefore use string::substr() //to trim of "::" from the front of the qualified name. if( scope->get_qualified_name().getString().length() > 2 ) { return scope->get_qualified_name().getString().substr(2)+("::"+getDeclStmtName(st)); } else { return getDeclStmtName(st); } //return scope->get_qualified_name().str()+("::"+getDeclStmtName(st)); } }
void UnparseFortran_type::unparseFunctionType(SgType* type, SgUnparse_Info& info) { SgFunctionType* func_type = isSgFunctionType(type); ROSE_ASSERT (func_type != NULL); SgUnparse_Info ninfo(info); // DQ (1/24/2011): The case of a procedure type in Fortran is quite simple. // Note that test2011_28.f90 demonstrates an example of this. // curprint("procedure()"); curprint("procedure(), pointer"); #if 0 int needParen = 0; if (ninfo.isReferenceToSomething() || ninfo.isPointerToSomething()) { needParen=1; } // DQ (10/8/2004): Skip output of class definition for return type! C++ standard does not permit // a defining declaration within a return type, function parameter, or sizeof expression. ninfo.set_SkipClassDefinition(); if (ninfo.isTypeFirstPart()) { if (needParen) { ninfo.unset_isReferenceToSomething(); ninfo.unset_isPointerToSomething(); unparseType(func_type->get_return_type(), ninfo); curprint("("); } else { unparseType(func_type->get_return_type(), ninfo); } } else { if (ninfo.isTypeSecondPart()) { if (needParen) { curprint(")"); info.unset_isReferenceToSomething(); info.unset_isPointerToSomething(); } // print the arguments SgUnparse_Info ninfo2(info); ninfo2.unset_SkipBaseType(); ninfo2.unset_isTypeSecondPart(); ninfo2.unset_isTypeFirstPart(); curprint("("); SgTypePtrList::iterator p = func_type->get_arguments().begin(); while(p != func_type->get_arguments().end()) { // printf ("Output function argument ... \n"); unparseType(*p, ninfo2); p++; if (p != func_type->get_arguments().end()) { curprint(", "); } } curprint(")"); unparseType(func_type->get_return_type(), info); // catch the 2nd part of the rtype } else { ninfo.set_isTypeFirstPart(); unparseType(func_type, ninfo); ninfo.set_isTypeSecondPart(); unparseType(func_type, ninfo); } } #endif }
void UnparseFortran_type::unparsePointerType(SgType* type, SgUnparse_Info& info, bool printAttrs) { #if 0 // printf ("Inside of UnparserFort::unparsePointerType \n"); // cur << "\n/* Inside of UnparserFort::unparsePointerType */\n"; curprint ("\n! Inside of UnparserFort::unparsePointerType \n"); #endif // DQ (1/16/2011): Note that pointers in fortran are not expressed the same as in C/C++, are are // only a part of the type which is managed more directly using attributes in the variable declaration. // Not clear that we want to do anything here in the unparser... SgPointerType* pointer_type = isSgPointerType(type); ROSE_ASSERT(pointer_type != NULL); #if 0 /* special cases: ptr to array, int (*p) [10] */ /* ptr to function, int (*p)(int) */ /* ptr to ptr to .. int (**p) (int) */ if (isSgReferenceType(pointer_type->get_base_type()) || isSgPointerType(pointer_type->get_base_type()) || isSgArrayType(pointer_type->get_base_type()) || isSgFunctionType(pointer_type->get_base_type()) || isSgMemberFunctionType(pointer_type->get_base_type()) || isSgModifierType(pointer_type->get_base_type()) ) { info.set_isPointerToSomething(); } // If not isTypeFirstPart nor isTypeSecondPart this unparse call // is not controlled from the statement level but from the type level if (info.isTypeFirstPart() == true) { unparseType(pointer_type->get_base_type(), info); // DQ (9/21/2004): Moved this conditional into this branch (to fix test2004_93.C) // DQ (9/21/2004): I think we can assert this, and if so we can simplify the logic below ROSE_ASSERT(info.isTypeSecondPart() == false); curprint("*"); } else { if (info.isTypeSecondPart() == true) { unparseType(pointer_type->get_base_type(), info); } else { SgUnparse_Info ninfo(info); ninfo.set_isTypeFirstPart(); unparseType(pointer_type, ninfo); ninfo.set_isTypeSecondPart(); unparseType(pointer_type, ninfo); } } #else if (info.supressStrippedTypeName() == false) { // DQ (1/16/2011): We only want to output the name of the stripped type once! SgType* stripType = pointer_type->stripType(); unparseType(stripType, info); info.set_supressStrippedTypeName(); } curprint(type->get_isCoArray()? ", COPOINTER": ", POINTER"); // DQ (1/16/2011): Plus unparse the base type...(unless it will just output the stripped types name). if (pointer_type->get_base_type()->containsInternalTypes() == true) { unparseType(pointer_type->get_base_type(), info, printAttrs); } #endif #if 0 // printf ("Leaving of UnparserFort::unparsePointerType \n"); // cur << "\n/* Leaving of UnparserFort::unparsePointerType */\n"; curprint ("\n! Leaving UnparserFort::unparsePointerType \n"); #endif }
void UnparseFortran_type::unparseArrayType(SgType* type, SgUnparse_Info& info, bool printDim) { // Examples: // real, dimension(10, 10) :: A1, A2 // real, dimension(:) :: B1 // character(len=*) :: s1 #if 0 curprint ("\n! Inside of UnparserFort::unparseArrayType \n"); #endif SgArrayType* array_type = isSgArrayType(type); ROSE_ASSERT(array_type != NULL); // I think that supressStrippedTypeName() and SkipBaseType() are redundant... if (info.supressStrippedTypeName() == false) { // DQ (1/16/2011): We only want to output the name of the stripped type once! SgType* stripType = array_type->stripType(); unparseType(stripType, info); info.set_supressStrippedTypeName(); } // DQ (8/5/2010): It is an error to treat an array of char as a string (see test2010_16.f90). #if 0 // dimension information SgExprListExp* dim = array_type->get_dim_info(); // if (isCharType(array_type->get_base_type())) // if (false && isCharType(array_type->get_base_type())) if (isCharType(array_type->get_base_type())) { // a character type: must be treated specially ROSE_ASSERT(array_type->get_rank() == 1); curprint("(len="); SgExpressionPtrList::iterator it = dim->get_expressions().begin(); if (it != dim->get_expressions().end()) { SgExpression* expr = *it; if (expr->variantT() == V_SgSubscriptExpression) { // this is a subscript expression but all we want to unparse is the length // of the string, which should be the upper bound of the subscript expression SgSubscriptExpression* sub_expr = isSgSubscriptExpression(expr); ROSE_ASSERT(sub_expr != NULL); ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); unp->u_fortran_locatedNode->unparseExpression(sub_expr->get_upperBound(), info); } else { // unparse the entire expression ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); unp->u_fortran_locatedNode->unparseExpression(*it, info); } } else { curprint("*"); } curprint(")"); } else { // a non-character type // explicit-shape (explicit rank and bounds/extents) // assumed-shape (explicit rank; unspecified bounds/extents) // deferred-shape (explicit rank; unspecified bounds/extents) // assumed-size (explicit ranks, explicit bounds/extents except last dim) ROSE_ASSERT(array_type->get_rank() >= 1); curprint(", DIMENSION"); ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); // unp->u_fortran_locatedNode->unparseExprList(dim, info); // adds parens // unp->u_fortran_locatedNode->UnparseLanguageIndependentConstructs::unparseExprList(dim, info); // adds parens // curprint("("); // curprint( StringUtility::numberToString(array_type->get_rank()) ); // curprint(")"); // unp->u_fortran_locatedNode->unparseExpression(array_type->get_dim_info(),info); unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true); } #else if (printDim) { ROSE_ASSERT(array_type->get_rank() >= 1); curprint(array_type->get_isCoArray()? ", CODIMENSION": ", DIMENSION"); ROSE_ASSERT(unp != NULL); ROSE_ASSERT(unp->u_fortran_locatedNode != NULL); if (array_type->get_isCoArray()) { // print codimension info curprint("["); unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* do not output parens */ false); curprint("]"); } else // print dimension info unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true); } // DQ (1/16/2011): Plus unparse the base type...(unless it will just output the stripped types name). if (array_type->get_base_type()->containsInternalTypes() == true) { unparseType(array_type->get_base_type(), info, printDim); } #endif #if 0 curprint ("\n! Leaving UnparserFort::unparseArrayType \n"); #endif }
void Unparse_Java::unparseEnumType(SgEnumType* type, SgUnparse_Info& info) { SgEnumType* enum_type = isSgEnumType(type); ROSE_ASSERT(enum_type); if (info.isTypeSecondPart() == false) { SgEnumDeclaration *edecl = isSgEnumDeclaration(enum_type->get_declaration()); SgClassDefinition *cdefn = NULL; SgNamespaceDefinitionStatement* namespaceDefn = NULL; ROSE_ASSERT(edecl != NULL); // Build reference to any possible enclosing scope represented by a SgClassDefinition or SgNamespaceDefinition // to be used check if name qualification is required. unp->u_exprStmt->initializeDeclarationsFromParent ( edecl, cdefn, namespaceDefn ); if (info.isTypeFirstPart() == true && info.SkipEnumDefinition() == false) { unp->u_exprStmt->unparseAttachedPreprocessingInfo(edecl, info, PreprocessingInfo::before); } curprint ( "enum "); SgNamedType *ptype = NULL; if (cdefn != NULL) { ptype = isSgNamedType(cdefn->get_declaration()->get_type()); } if (SageInterface::is_C_language() == true || SageInterface::is_C99_language() == true) { curprint ( enum_type->get_name().getString() + " "); } else { // DQ (7/20/2011): Test compilation without the generateNameQualifier() functions. // The C++ support is more complex and can require qualified names! // SgName nameQualifier = unp->u_name->generateNameQualifier( edecl , info ); SgName nameQualifier; // printf ("nameQualifier (from unp->u_name->generateNameQualifier function) = %s \n",nameQualifier.str()); // curprint ( "\n/* nameQualifier (from unp->u_name->generateNameQualifier function) = " + nameQualifier + " */ \n "; curprint ( nameQualifier.str()); SgName nm = enum_type->get_name(); if (nm.getString() != "") { // printf ("Output qualifier of current types to the name = %s \n",nm.str()); curprint ( nm.getString() + " "); } } } if (info.isTypeFirstPart() == true) { // info.display("info before constructing ninfo"); SgUnparse_Info ninfo(info); // don't skip the semicolon in the output of the statement in the class definition ninfo.unset_SkipSemiColon(); ninfo.set_isUnsetAccess(); // printf ("info.SkipEnumDefinition() = %s \n",(info.SkipEnumDefinition() == true) ? "true" : "false"); if ( info.SkipEnumDefinition() == false) { SgUnparse_Info ninfo(info); ninfo.set_inEnumDecl(); SgInitializer *tmp_init = NULL; SgName tmp_name; SgEnumDeclaration *enum_stmt = isSgEnumDeclaration(enum_type->get_declaration()); ROSE_ASSERT(enum_stmt != NULL); // This permits support of the empty enum case! "enum x{};" curprint ( "{"); SgInitializedNamePtrList::iterator p = enum_stmt->get_enumerators().begin(); if (p != enum_stmt->get_enumerators().end()) { // curprint ( "{"; while (1) { unp->u_exprStmt->unparseAttachedPreprocessingInfo(*p, info, PreprocessingInfo::before); tmp_name=(*p)->get_name(); tmp_init=(*p)->get_initializer(); curprint ( tmp_name.str()); if(tmp_init) { curprint ( "="); unp->u_exprStmt->unparseExpression(tmp_init, ninfo); } p++; if (p != enum_stmt->get_enumerators().end()) { curprint ( ","); } else break; } // curprint ( "}"; } // Putting the "inside" info right here is just a wild guess as to where it might really belong. unp->u_exprStmt->unparseAttachedPreprocessingInfo(enum_stmt, info, PreprocessingInfo::inside); curprint ( "}"); unp->u_exprStmt->unparseAttachedPreprocessingInfo(enum_stmt, info, PreprocessingInfo::after); } } }
string PrefixSuffixGenerationTraversal::DeclarationOrCommentListElement:: generateDeclarationString ( SgDeclarationStatement* declaration ) const { // This function generates a string for a declaration. The string is required for // the intermediate file to make sure that all transformation code will compile // (since it could depend on declarations defined within the code). // Details: // 1) Only record declarations found within the source file (exclude all header files // since they will be seen when the same header files are included). // 2) Resort the variable declarations to remove redundent entries. // WRONG: variable declarations could have dependences upon class declarations! // 3) Don't sort all declarations since some could have dependences. // a) class declarations // b) typedefs // c) function declarations // d) template declarations // e) variable definition??? ROSE_ASSERT (this != NULL); ROSE_ASSERT ( declaration != NULL ); string declarationString; // Build a SgUnparse_Info object to represent formatting options for // this statement (use the default values). SgUnparse_Info info; // exclude comments info.set_SkipComments(); // exclude all CPP directives (since they have already been evaluated by the front-end) info.set_SkipCPPDirectives(); switch ( declaration->variantT() ) { // Enum declarations should not skip their definition since // this is where the constants are declared. case V_SgEnumDeclaration: case V_SgVariableDeclaration: case V_SgTemplateDeclaration: case V_SgTypedefDeclaration: // Need to figure out if a forward declaration would work or be // more conservative and always output the complete class definition. // turn off output of initializer values info.set_SkipInitializer(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; case V_SgClassDeclaration: // Need to figure out if a forward declaration would work or be // more conservative and always output the complete class definition. // turn off the generation of the function definitions only // (we still want the restof the class definition since these // define all member data and member functions). // info.set_SkipClassDefinition(); info.set_SkipFunctionDefinition(); info.set_AddSemiColonAfterDeclaration(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; // For functions just output the declaration and skip the definition // (This also avoids the generation of redundent definitions since the // function we are in when we generate all declarations would be included). case V_SgMemberFunctionDeclaration: case V_SgFunctionDeclaration: { // turn off the generation of the definition info.set_SkipFunctionDefinition(); info.set_AddSemiColonAfterDeclaration(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; } case V_SgFunctionParameterList: { // Handle generation of declaration strings this case differnetly from unparser // since want to generate declaration strings and not function parameter lists // (function parameter lists would be delimited by "," while declarations would // be delimited by ";"). SgFunctionParameterList* parameterListDeclaration = dynamic_cast<SgFunctionParameterList*>(declaration); ROSE_ASSERT (parameterListDeclaration != NULL); SgInitializedNamePtrList & argList = parameterListDeclaration->get_args(); SgInitializedNamePtrList::iterator i; for (i = argList.begin(); i != argList.end(); i++) { printf ("START: Calling unparseToString on type! \n"); ROSE_ASSERT((*i) != NULL); ROSE_ASSERT((*i)->get_type() != NULL); string typeNameString = (*i)->get_type()->unparseToString(); printf ("DONE: Calling unparseToString on type! \n"); string variableName; if ( (*i)->get_name().getString() != "") { variableName = (*i)->get_name().getString(); declarationString += typeNameString + " " + variableName + "; "; } else { // Don't need the tailing ";" if there is no variable name (I think) declarationString += typeNameString + " "; } } break; } // ignore this case ... not really a declaration case V_SgCtorInitializerList: // printf ("Ignore the SgCtorInitializerList (constructor initializer list) \n"); break; case V_SgVariableDefinition: printf ("ERROR: SgVariableDefinition nodes not used in AST \n"); ROSE_ABORT(); break; // default case should always be an error default: printf ("Default reached in AST_Rewrite::AccumulatedDeclarationsAttribute::generateDeclarationString() \n"); printf (" declaration->sage_class_name() = %s \n",declaration->sage_class_name()); ROSE_ABORT(); break; } // Add a space to make it easier to read (not required) declarationString += " "; // printf ("For this scope: declarationString = %s \n",declarationString.c_str()); return declarationString; }
void POETAstInterface::unparse(POETCode_ext* n, std::ostream& out, int align) { static SgUnparse_Info info; static Unparser* roseUnparser = 0; static POETCode* linebreak=ASTFactory::inst()->new_string("\n"); static POETCode* comma=ASTFactory::inst()->new_string(","); static bool template_only=false; static POETCode* left_over = 0; SgNode * input = (SgNode*)n->get_content(); POETCode* res = POETAstInterface::find_Ast2POET(input); if (res == n) { if (template_only && input->variantT() == V_SgFunctionDeclaration) { left_over = LIST(n,left_over); } else { std::string res = input->unparseToCompleteString(); out << res; } } else { if (roseUnparser == 0) { /* QY/2013: copied from the global unparseFile to use a different ostream and delegate*/ bool UseAutoKeyword = false; bool generateLineDirectives = true; bool useOverloadedOperators = false; bool num = false; bool _this = true; bool caststring = false; bool _debug = false; bool _class = false; bool _forced_transformation_format = false; bool _unparse_includes = false; Unparser_Opt roseOptions( UseAutoKeyword, generateLineDirectives, useOverloadedOperators, num, _this, caststring, _debug, _class, _forced_transformation_format, _unparse_includes ); roseUnparser = new Unparser(&out, "", roseOptions); } switch (input->variantT()) { case V_SgSourceFile: { SgSourceFile* f = isSgSourceFile(input); info.set_current_scope(f->get_globalScope()); template_only = true; code_gen(out, n->get_children(), 0, 0, align); template_only = false; if (left_over != 0) { code_gen(out, left_over, 0, 0, align); left_over = 0; } break; } case V_SgFunctionDeclaration: if (template_only) { left_over = LIST(n, left_over); break; } case V_SgTemplateInstantiationFunctionDecl: { SgFunctionDeclaration* d = isSgFunctionDeclaration(input); roseUnparser->u_exprStmt->unparseAttachedPreprocessingInfo(d,info,PreprocessingInfo::before); POETCode_ext_delegate repl(n, out); roseUnparser->repl = &repl; roseUnparser->u_exprStmt->unparseFuncDeclStmt(d, info); break; } case V_SgFunctionDefinition: { SgStatement* d = isSgStatement(input); POETCode_ext_delegate repl(n, out); roseUnparser->repl = &repl; roseUnparser->u_exprStmt->unparseStatement(d, info); assert(n->get_children() != n); out << "{"; code_gen(out, linebreak, 0, 0, align + 2); code_gen(out, n->get_children(), 0, linebreak, align+2); code_gen(out, linebreak, 0, 0, align); out << "}"; break; } case V_SgPragmaDeclaration: { out << "#pragma "; POETTuple* c = dynamic_cast<POETTuple*>(n->get_children()); assert(c != 0); code_gen(out, c->get_entry(0)); roseUnparser->cur << " "; roseUnparser->cur.insert_newline(1,align); code_gen(out, c->get_entry(1), 0, 0, align); break; } case V_SgForStatement: { out << "for (" ; POETTuple* c = dynamic_cast<POETTuple*>(n->get_children()); assert(c != 0); code_gen(out, c->get_entry(0)); code_gen(out, c->get_entry(1)); out << ";"; code_gen(out, c->get_entry(2)); out << ")"; break; } case V_SgExprStatement: code_gen(out, n->get_children(), 0, 0, align); out << ";"; break; case V_SgTemplateInstantiationMemberFunctionDecl: break; default: std::cerr << "Unsupported unparsing for : " << input->class_name() << input->unparseToString() << "\n"; //assert(0); } } }
SgName Unparser_Nameq::generateNameQualifierSupport ( SgScopeStatement* scope, const SgUnparse_Info& info, bool qualificationOfType ) { // DQ (5/28/2011): We need this information to be passed in from the outside (qualificationOfType): // qualificationOfName == true implies this is name qualification for a name vs a type. // qualificationOfName == false implies this is name qualification for a type. // note that the complete minimally qualified name is stored and retrieved from the map using // either SgNode::get_globalQualifiedNameMapForNames() or SgNode::get_globalQualifiedNameMapForTypes(). // bool qualificationOfType = false; SgName qualifiedName; // If the name qualification length required is zero then we can return an empty string and avoid the logic below. if (info.get_name_qualification_length() > 0) { // DQ (5/28/2011): Adding support for qualified name lookup. SgNode* nameQualificationReferenceNode = info.get_reference_node_for_qualification(); if (nameQualificationReferenceNode != NULL) { if (qualificationOfType == false) { std::map<SgNode*,std::string>::iterator i = SgNode::get_globalQualifiedNameMapForNames().find(nameQualificationReferenceNode); if (i != SgNode::get_globalQualifiedNameMapForNames().end()) { qualifiedName = i->second; } else { printf ("key not found in node map nameQualificationReferenceNode = %s \n",nameQualificationReferenceNode->class_name().c_str()); ROSE_ASSERT(false); } } else { std::map<SgNode*,std::string>::iterator i = SgNode::get_globalQualifiedNameMapForTypes().find(nameQualificationReferenceNode); if (i != SgNode::get_globalQualifiedNameMapForTypes().end()) { qualifiedName = i->second; } else { // Debugging support... printf ("key not found in type map nameQualificationReferenceNode = %s \n",nameQualificationReferenceNode->class_name().c_str()); // Extra Debugging support... switch(nameQualificationReferenceNode->variantT()) { case V_SgInitializedName: { SgInitializedName* initializedName = isSgInitializedName(nameQualificationReferenceNode); printf ("initializedName = %s \n",initializedName->get_name().str()); break; } default: { printf ("Default reached in switch(nameQualificationReferenceNode->variantT()) \n"); ROSE_ASSERT(false); } } ROSE_ASSERT(false); } } } else { // This should be an error. printf ("Error: nameQualificationReferenceNode == NULL but info.get_name_qualification_length() = %d \n",info.get_name_qualification_length()); ROSE_ASSERT(false); } } else { // printf ("return empty qualified name since info.get_name_qualification_length() == 0 \n"); } return qualifiedName; }
SgName Unparser_Nameq::generateNameQualifier( SgDeclarationStatement* declarationStatement, const SgUnparse_Info & info, bool qualificationOfType ) { // This unparser support for name qualification is C++ specific. #if 0 printf ("In Unparser_Nameq::generateNameQualifier(): qualificationOfType = %s \n",qualificationOfType ? "true" : "false"); printf ("In Unparser_Nameq::generateNameQualifier(): info.get_name_qualification_length() = %d \n",info.get_name_qualification_length()); printf ("In Unparser_Nameq::generateNameQualifier(): info.get_type_elaboration_required() = %s \n",info.get_type_elaboration_required() ? "true" : "false"); printf ("In Unparser_Nameq::generateNameQualifier(): info.get_global_qualification_required() = %s \n",info.get_global_qualification_required() ? "true" : "false"); #endif ROSE_ASSERT(declarationStatement != NULL); return generateNameQualifierSupport(declarationStatement->get_scope(),info,qualificationOfType); }
void UnparseFormat::format(SgLocatedNode* node, SgUnparse_Info& info, FormatOpt opt) { // DQ (added comments): this function addes new line formatting to the unparse statements // depending on the type of statement and the options with which it is called. if (info.get_outputCodeGenerationFormatDelimiters() == true) { // printf ("In UnparseFormat::format(%s,opt=%d) \n",node->class_name().c_str(),opt); // (*this) << formatOptionToString(opt) << ":" << node->class_name() << "["; (*this) << formatOptionToString(opt) << ":" << node->class_name() << "["; } #if 0 printf ("UnparseFormat::format(): node = %p = %s currentLine = %d chars_on_line = %d \n",node,node->class_name().c_str(),currentLine,chars_on_line); #endif // DQ (3/18/2006): The default is TABINDENT but we get a value from formatHelp if available int tabIndentSize = TABINDENT; if (formatHelpInfo != NULL) tabIndentSize = formatHelpInfo->tabIndent(); // This provides a default implementation when the user has not specificed any help to control the unparsing if ( formatHelp(node, info, opt) == false ) { int v = node->variantT(); int v1 = (prevnode == 0) ? 0 : prevnode->variantT(); switch (opt) { case FORMAT_AFTER_STMT: if (v == V_SgFunctionDefinition || v == V_SgClassDefinition) insert_newline(1); // DXN: changed from 2 to 1 break; case FORMAT_BEFORE_STMT: { #if 0 printf ("UnparseFormat::format(): case FORMAT_BEFORE_STMT: node = %p = %s \n",node,node->class_name().c_str()); #endif switch(v) { case V_SgBasicBlock: // DQ (3/18/2006): Added SgNullStatement as something that should not generate formatting in this case case V_SgNullStatement: break; default: { #if 0 printf ("UnparseFormat::format(): case FORMAT_BEFORE_STMT: info.inConditional() = %s \n",info.inConditional() ? "true" : "false"); #endif if (!info.inConditional()) { linewrap = MAXCHARSONLINE; prevnode = node; if (v == V_SgFunctionDefinition || v == V_SgClassDefinition) { insert_newline(2,stmtIndent); } else { insert_newline(1,stmtIndent); } } } } break; } case FORMAT_BEFORE_DIRECTIVE: linewrap = -1; insert_newline(1,0); break; case FORMAT_AFTER_DIRECTIVE: linewrap = MAXCHARSONLINE; insert_newline(); break; case FORMAT_BEFORE_BASIC_BLOCK1: if ( v1 != V_SgCatchOptionStmt && v1 != V_SgDoWhileStmt && v1 != V_SgForStatement && v1 != V_SgIfStmt && v1 != V_SgSwitchStatement && v1 != V_SgWhileStmt ) insert_newline(); break; case FORMAT_AFTER_BASIC_BLOCK1: stmtIndent += tabIndentSize; break; case FORMAT_BEFORE_BASIC_BLOCK2: stmtIndent -= tabIndentSize; insert_newline(1,stmtIndent); break; case FORMAT_AFTER_BASIC_BLOCK2: break; case FORMAT_BEFORE_NESTED_STATEMENT: if (v != V_SgBasicBlock) { stmtIndent += tabIndentSize; } break; case FORMAT_AFTER_NESTED_STATEMENT: if (v != V_SgBasicBlock) { stmtIndent -= tabIndentSize; } break; default: { printf ("Error: default reached in switch for formatting within unparsing ... \n"); ROSE_ASSERT(false); } } } if (info.get_outputCodeGenerationFormatDelimiters() == true) { // printf ("Leaving UnparseFormat::format(%s,opt=%d) \n",node->class_name().c_str(),opt); (*this) << "]" << node->class_name(); } #if 0 printf ("Leaving UnparseFormat::format(): node = %p = %s currentLine = %d chars_on_line = %d \n",node,node->class_name().c_str(),currentLine,chars_on_line); #endif }
string globalUnparseToString ( SgNode* astNode, SgUnparse_Info* inputUnparseInfoPointer ) { // This global function permits any SgNode (including it's subtree) to be turned into a string // DQ (3/2/2006): Let's make sure we have a valid IR node! ROSE_ASSERT(astNode != NULL); string returnString; // all options are now defined to be false. When these options can be passed in // from the prompt, these options will be set accordingly. bool _auto = false; bool linefile = false; bool useOverloadedOperators = false; bool num = false; // It is an error to have this always turned off (e.g. pointer = this; will not unparse correctly) bool _this = true; bool caststring = false; bool _debug = false; bool _class = false; bool _forced_transformation_format = false; bool _unparse_includes = false; // printf ("In globalUnparseToString(): astNode->sage_class_name() = %s \n",astNode->sage_class_name()); Unparser_Opt roseOptions( _auto, linefile, useOverloadedOperators, num, _this, caststring, _debug, _class, _forced_transformation_format, _unparse_includes ); int lineNumber = 0; // Zero indicates that ALL lines should be unparsed // Initialize the Unparser using a special string stream inplace of the usual file stream ostringstream outputString; SgLocatedNode* locatedNode = isSgLocatedNode(astNode); string fileNameOfStatementsToUnparse; if (locatedNode == NULL) { // printf ("WARNING: applying AST -> string for non expression/statement AST objects \n"); fileNameOfStatementsToUnparse = "defaultFileNameInGlobalUnparseToString"; } else { ROSE_ASSERT (locatedNode != NULL); // DQ (5/31/2005): Get the filename from a traversal back through the parents to the SgFile // fileNameOfStatementsToUnparse = locatedNode->getFileName(); // fileNameOfStatementsToUnparse = rose::getFileNameByTraversalBackToFileNode(locatedNode); if (locatedNode->get_parent() == NULL) { // DQ (7/29/2005): // Allow this function to be called with disconnected AST fragments not connected to // a previously generated AST. This happens in Qing's interface where AST fragements // are built and meant to be unparsed. Only the parent of the root of the AST // fragement is expected to be NULL. fileNameOfStatementsToUnparse = locatedNode->getFileName(); } else { fileNameOfStatementsToUnparse = rose::getFileNameByTraversalBackToFileNode(locatedNode); } } ROSE_ASSERT (fileNameOfStatementsToUnparse.size() > 0); Unparser roseUnparser ( &outputString, fileNameOfStatementsToUnparse, roseOptions, lineNumber ); // Information that is passed down through the tree (inherited attribute) // Use the input SgUnparse_Info object if it is available. SgUnparse_Info* inheritedAttributeInfoPointer = NULL; if (inputUnparseInfoPointer != NULL) { // printf ("Using the input inputUnparseInfoPointer object \n"); // Use the user provided SgUnparse_Info object inheritedAttributeInfoPointer = inputUnparseInfoPointer; } else { // DEFINE DEFAULT BEHAVIOUR FOR THE CASE WHEN NO inputUnparseInfoPointer (== NULL) IS // PASSED AS ARGUMENT TO THE FUNCTION // printf ("Building a new Unparse_Info object \n"); // If no input parameter has been specified then allocate one // inheritedAttributeInfoPointer = new SgUnparse_Info (NO_UNPARSE_INFO); inheritedAttributeInfoPointer = new SgUnparse_Info(); ROSE_ASSERT (inheritedAttributeInfoPointer != NULL); // MS: 09/30/2003: comments de-activated in unparsing ROSE_ASSERT (inheritedAttributeInfoPointer->SkipComments() == false); // Skip all comments in unparsing inheritedAttributeInfoPointer->set_SkipComments(); ROSE_ASSERT (inheritedAttributeInfoPointer->SkipComments() == true); // Skip all whitespace in unparsing (removed in generated string) inheritedAttributeInfoPointer->set_SkipWhitespaces(); ROSE_ASSERT (inheritedAttributeInfoPointer->SkipWhitespaces() == true); // Skip all directives (macros are already substituted by the front-end, so this has no effect on those) inheritedAttributeInfoPointer->set_SkipCPPDirectives(); ROSE_ASSERT (inheritedAttributeInfoPointer->SkipCPPDirectives() == true); } ROSE_ASSERT (inheritedAttributeInfoPointer != NULL); SgUnparse_Info & inheritedAttributeInfo = *inheritedAttributeInfoPointer; // Turn ON the error checking which triggers an error if the default SgUnparse_Info constructor is called // SgUnparse_Info::forceDefaultConstructorToTriggerError = true; #if 1 // DQ (10/19/2004): Cleaned up this code, remove this dead code after we are sure that this worked properly // Actually, this code is required to be this way, since after this branch the current function returns and // some data must be cleaned up differently! So put this back and leave it this way, and remove the // "Implementation Note". // Both SgProject and SgFile are handled via recursive calls if ( (isSgProject(astNode) != NULL) || (isSgFile(astNode) != NULL) ) { // printf ("Implementation Note: Put these cases (unparsing the SgProject and SgFile into the cases for nodes derived from SgSupport below! \n"); // Handle recursive call for SgProject if (isSgProject(astNode) != NULL) { SgProject* project = isSgProject(astNode); ROSE_ASSERT(project != NULL); for (int i = 0; i < project->numberOfFiles(); i++) { SgFile* file = &(project->get_file(i)); ROSE_ASSERT(file != NULL); string unparsedFileString = globalUnparseToString(file,inputUnparseInfoPointer); string prefixString = string("/* TOP:") + string(rose::getFileName(file)) + string(" */ \n"); string suffixString = string("\n/* BOTTOM:") + string(rose::getFileName(file)) + string(" */ \n\n"); returnString += prefixString + unparsedFileString + suffixString; } } // Handle recursive call for SgFile if (isSgFile(astNode) != NULL) { SgFile* file = isSgFile(astNode); ROSE_ASSERT(file != NULL); SgGlobal* globalScope = file->get_root(); ROSE_ASSERT(globalScope != NULL); returnString = globalUnparseToString(globalScope,inputUnparseInfoPointer); } } else #endif { // DQ (1/12/2003): Only now try to trap use of SgUnparse_Info default constructor // Turn ON the error checking which triggers an error if the default SgUnparse_Info constructor is called SgUnparse_Info::set_forceDefaultConstructorToTriggerError(true); if (isSgStatement(astNode) != NULL) { SgStatement* stmt = isSgStatement(astNode); roseUnparser.unparseStatement ( stmt, inheritedAttributeInfo ); } if (isSgExpression(astNode) != NULL) { SgExpression* expr = isSgExpression(astNode); roseUnparser.unparseExpression ( expr, inheritedAttributeInfo ); } if (isSgType(astNode) != NULL) { SgType* type = isSgType(astNode); roseUnparser.unparseType ( type, inheritedAttributeInfo ); } if (isSgSymbol(astNode) != NULL) { SgSymbol* symbol = isSgSymbol(astNode); roseUnparser.unparseSymbol ( symbol, inheritedAttributeInfo ); } if (isSgSupport(astNode) != NULL) { // Handle different specific cases derived from SgSupport // (e.g. template parameters and template arguments). switch (astNode->variantT()) { #if 0 case V_SgProject: { SgProject* project = isSgProject(astNode); ROSE_ASSERT(project != NULL); for (int i = 0; i < project->numberOfFiles(); i++) { SgFile* file = &(project->get_file(i)); ROSE_ASSERT(file != NULL); string unparsedFileString = globalUnparseToString(file,inputUnparseInfoPointer); string prefixString = string("/* TOP:") + string(rose::getFileName(file)) + string(" */ \n"); string suffixString = string("\n/* BOTTOM:") + string(rose::getFileName(file)) + string(" */ \n\n"); returnString += prefixString + unparsedFileString + suffixString; } break; } case V_SgFile: { SgFile* file = isSgFile(astNode); ROSE_ASSERT(file != NULL); SgGlobal* globalScope = file->get_root(); ROSE_ASSERT(globalScope != NULL); returnString = globalUnparseToString(globalScope,inputUnparseInfoPointer); break; } #endif case V_SgTemplateParameter: { SgTemplateParameter* templateParameter = isSgTemplateParameter(astNode); roseUnparser.unparseTemplateParameter(templateParameter,inheritedAttributeInfo); break; } case V_SgTemplateArgument: { SgTemplateArgument* templateArgument = isSgTemplateArgument(astNode); roseUnparser.unparseTemplateArgument(templateArgument,inheritedAttributeInfo); break; } case V_SgInitializedName: { // QY: not sure how to implement this // DQ (7/23/2004): This should unparse as a declaration // (type and name with initializer). break; } case V_Sg_File_Info: { // DQ (5/11/2006): Not sure how or if we shoul implement this break; } // Perhaps the support for SgFile and SgProject shoud be moved to this location? default: printf ("Error: default reached in node derived from SgSupport astNode = %s \n",astNode->sage_class_name()); ROSE_ABORT(); } } // Turn OFF the error checking which triggers an if the default SgUnparse_Info constructor is called SgUnparse_Info::set_forceDefaultConstructorToTriggerError(false); // MS: following is the rewritten code of the above outcommented // code to support ostringstream instead of ostrstream. returnString = outputString.str(); // Call function to tighten up the code to make it more dense if (inheritedAttributeInfo.SkipWhitespaces() == true) { returnString = roseUnparser.removeUnwantedWhiteSpace ( returnString ); } // delete the allocated SgUnparse_Info object if (inputUnparseInfoPointer == NULL) delete inheritedAttributeInfoPointer; } return returnString; }
void generateModFile(SgFile *sfile) { ROSE_ASSERT(sfile != NULL); // file name, with full path. string originalModuleFilenameWithPath = sfile->get_file_info()->get_filenameString(); #if 0 // DQ (10/24/2010): This is overly restrictive...we still want to generate the rmod file. // It does not matter is we compile or not compile any generated file. This premature // exit will cause F03 code to fail to be processed by ROSE since any mod file required // will not generated. // FMZ (10/28/2009): don't generate the .rmod for the readin .rmod file if (sfile->get_skipfinalCompileStep() == true) { if (SgProject::get_verbose() > 0) printf ("Skipping generation of rmod file: %s \n",originalModuleFilenameWithPath.c_str()); return; } #endif // Cause the output of a message with verbose level is turned on. if (SgProject::get_verbose() > 0) { printf ("In generateModFile(): Generating a Fortran 90 specific module (*.rmod file) for file = %s \n",originalModuleFilenameWithPath.c_str()); } // Get the list of SgModuleStatement objects for the current AST. Rose_STL_Container<SgNode*> moduleDeclarationList = NodeQuery::querySubTree (sfile,V_SgModuleStatement); #if 0 // DQ: I think this case is not required since the loop (below) would be empty. if (moduleDeclarationList.empty()) { // no module in the file return; } #endif for (Rose_STL_Container<SgNode*>::iterator i = moduleDeclarationList.begin(); i != moduleDeclarationList.end(); i++) { // For a module named "xx" generate a file "xx.rose_mod" which contains // all the variable definitions and function declarations SgModuleStatement* module_stmt = isSgModuleStatement(*i); ROSE_ASSERT(module_stmt != NULL); string outputDir = get_rmod_dir(sfile); string outputFilename; if (outputDir !="") outputFilename =outputDir + module_stmt->get_name() + MOD_FILE_SUFFIX; else outputFilename = module_stmt->get_name() + MOD_FILE_SUFFIX; string lowerCaseOutputFilename = StringUtility::convertToLowerCase(outputFilename); // Cause the output of a message with verbose level is turned on. if (SgProject::get_verbose() > 0) { printf ("In generateModFile() (loop over module declarations): Generating a Fortran 90 specific module file %s for module = %s \n",lowerCaseOutputFilename.c_str(),outputFilename.c_str()); } // Use a lower case generate filename for the generated ROSE mod (or rmod) file. // fstream Module_OutputFile(outputFilename.c_str(),ios::out); fstream Module_OutputFile(lowerCaseOutputFilename.c_str(),ios::out); if (!Module_OutputFile) { cout << "Error detected in opening file " << lowerCaseOutputFilename.c_str() << "for output" << endl; ROSE_ASSERT(false); } // Output header at the top of the generate *.rmod file. Module_OutputFile << endl << "! =================================================================================== \n" << "! <<Automatically generated for Rose Fortran Separate Compilation, DO NOT MODIFY IT>> \n" << "! =================================================================================== \n" << endl; SgUnparse_Info ninfo; ninfo.set_current_scope((SgScopeStatement*)module_stmt); ninfo.set_SkipFormatting(); // set the flag bit "outputFortranModFile" ninfo.set_outputFortranModFile(); ostringstream outputString; Unparser_Opt options(false, false,false,false,true,false,false,false,false,false); // This is a confusing use of originalModuleFilename vs. outputFilename (Oh, the first one has the full path!). // The originalModuleFilename will be used to build a FortranCodeGeneration_locatedNode using // the originalModuleFilename as a basis. // printf ("originalModuleFilenameWithPath = %s outputFilename = %s \n",originalModuleFilenameWithPath.c_str(),outputFilename.c_str()); Unparser unp(&Module_OutputFile, originalModuleFilenameWithPath,options,NULL,NULL); unp.currentFile = sfile; // The outputFilename is the name that will be matched against in the selection of statements to unparse. // However, that its suffix is ".rmod" will cause UnparseLanguageIndependentConstructs::statementFromFile() // to always return true. So use of outputFilename should map to the file from the file constructed. FortranCodeGeneration_locatedNode myunp(&unp, outputFilename); // This calls the unparser for just the module declaration. myunp.unparseClassDeclStmt_module((SgStatement*)module_stmt,(SgUnparse_Info&)ninfo); Module_OutputFile.flush(); Module_OutputFile.close(); } }