// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // main.cc -- // // Author : Richard C. Bilson // Created On : Fri May 15 23:12:02 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Sat Aug 6 16:17:41 2016 // Update Count : 210 // #include #include #include #include #include #include "Parser/Parser.h" #include "Parser/ParseNode.h" #include "Parser/LinkageSpec.h" #include "SynTree/Declaration.h" #include "SynTree/Visitor.h" #include "GenPoly/Lvalue.h" #include "GenPoly/Specialize.h" #include "GenPoly/Box.h" #include "GenPoly/CopyParams.h" #include "GenPoly/InstantiateGeneric.h" #include "CodeGen/Generate.h" #include "CodeGen/FixNames.h" #include "ControlStruct/Mutate.h" #include "Tuples/Mutate.h" #include "Tuples/FunctionChecker.h" #include "SymTab/Mangler.h" #include "SymTab/Indexer.h" #include "SymTab/Validate.h" #include "ResolvExpr/AlternativePrinter.h" #include "ResolvExpr/Resolver.h" #include "MakeLibCfa.h" #include "InitTweak/Mutate.h" #include "InitTweak/GenInit.h" #include "InitTweak/FixInit.h" //#include "Explain/GenProlog.h" //#include "Try/Visit.h" #include "Common/SemanticError.h" #include "Common/UnimplementedError.h" #include "../config.h" using namespace std; #define OPTPRINT(x) \ if ( errorp ) std::cerr << x << std::endl; static void parse( FILE * input, LinkageSpec::Type t, bool shouldExit = false ); static void dump( std::list< Declaration * > & translationUnit, std::ostream & out = std::cout ); bool astp = false, bresolvep = false, bboxp = false, ctorinitp = false, exprp = false, expraltp = false, grammarp = false, libcfap = false, nopreludep = false, noprotop = false, parsep = false, resolvep = false, // used in AlternativeFinder symtabp = false, treep = false, validp = false, errorp = false, codegenp = false; enum { Ast, Bbox, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, }; static struct option long_opts[] = { { "ast", no_argument, 0, Ast }, { "before-box", no_argument, 0, Bbox }, { "before-resolver", no_argument, 0, Bresolver }, { "ctorinitfix", no_argument, 0, CtorInitFix }, { "expr", no_argument, 0, Expr }, { "expralt", no_argument, 0, ExprAlt }, { "grammar", no_argument, 0, Grammar }, { "libcfa", no_argument, 0, LibCFA }, { "no-preamble", no_argument, 0, Nopreamble }, { "parse", no_argument, 0, Parse }, { "no-prototypes", no_argument, 0, Prototypes }, { "resolver", no_argument, 0, Resolver }, { "symbol", no_argument, 0, Symbol }, { "tree", no_argument, 0, Tree }, { "validate", no_argument, 0, Validate }, { 0, 0, 0, 0 } }; int main( int argc, char *argv[] ) { FILE *input; std::ostream *output = &std::cout; int long_index; std::list< Declaration * > translationUnit; const char *filename = NULL; opterr = 0; // prevent getopt from printing error messages int c; while ( (c = getopt_long( argc, argv, "abBcefglnpqrstvyzD:F:", long_opts, &long_index )) != -1 ) { switch ( c ) { case Ast: case 'a': // dump AST astp = true; break; case Bresolver: case 'b': // print before resolver steps bresolvep = true; break; case 'B': // print before resolver steps bboxp = true; break; case CtorInitFix: case 'c': ctorinitp = true; break; case Expr: case 'e': // dump AST after expression analysis exprp = true; break; case ExprAlt: case 'f': // print alternatives for expressions expraltp = true; break; case Grammar: case 'g': // bison debugging info (grammar rules) grammarp = true; break; case LibCFA: case 'l': // generate libcfa.c libcfap = true; break; case Nopreamble: case 'n': // do not read preamble nopreludep = true; break; case Prototypes: case 'p': // generate prototypes for preamble functions noprotop = true; break; case Parse: case 'q': // dump parse tree parsep = true; break; case Resolver: case 'r': // print resolver steps resolvep = true; break; case Symbol: case 's': // print symbol table events symtabp = true; break; case Tree: case 't': // build in tree treep = true; break; case 'v': // dump AST after decl validation pass validp = true; break; case 'y': errorp = true; break; case 'z': codegenp = true; break; case 'D': // ignore -Dxxx break; case 'F': // source file-name without suffix filename = optarg; break; case '?': cout << "Unknown option: '" << (char)optopt << "'" << endl; exit( EXIT_FAILURE ); default: abort(); } // switch } // while try { // choose to read the program from a file or stdin if ( optind < argc ) { input = fopen( argv[ optind ], "r" ); if ( ! input ) { std::cout << "Error: cannot open " << argv[ optind ] << std::endl; exit( EXIT_FAILURE ); } // if // if running cfa-cpp directly, might forget to pass -F option (and really shouldn't have to) if ( filename == NULL ) filename = argv[ optind ]; // prelude filename comes in differently if ( libcfap ) filename = "prelude.cf"; optind += 1; } else { input = stdin; // if running cfa-cpp directly, might forget to pass -F option. Since this takes from stdin, pass // a fake name along if ( filename == NULL ) filename = "stdin"; } // if if ( optind < argc ) { output = new ofstream( argv[ optind ] ); } // if Parser::get_parser().set_debug( grammarp ); // read in the builtins, extras, and the prelude if ( ! nopreludep ) { // include gcc builtins // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here. FILE * builtins = fopen( libcfap | treep ? "builtins.cf" : CFA_LIBDIR "/builtins.cf", "r" ); if ( builtins == NULL ) { std::cerr << "Error: cannot open builtins.cf" << std::endl; exit( EXIT_FAILURE ); } // if parse( builtins, LinkageSpec::Compiler ); // read the extra prelude in, if not generating the cfa library FILE * extras = fopen( libcfap | treep ? "extras.cf" : CFA_LIBDIR "/extras.cf", "r" ); if ( extras == NULL ) { std::cerr << "Error: cannot open extras.cf" << std::endl; exit( EXIT_FAILURE ); } // if parse( extras, LinkageSpec::C ); if ( ! libcfap ) { // read the prelude in, if not generating the cfa library FILE * prelude = fopen( treep ? "prelude.cf" : CFA_LIBDIR "/prelude.cf", "r" ); if ( prelude == NULL ) { std::cerr << "Error: cannot open prelude.cf" << std::endl; exit( EXIT_FAILURE ); } // if parse( prelude, LinkageSpec::Intrinsic ); } // if } // if parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, grammarp ); if ( parsep ) { Parser::get_parser().get_parseTree()->printList( std::cout ); Parser::get_parser().freeTree(); return 0; } // if buildList( Parser::get_parser().get_parseTree(), translationUnit ); Parser::get_parser().freeTree(); if ( astp ) { dump( translationUnit ); return 0; } // if // add the assignment statement after the initialization of a type parameter OPTPRINT( "validate" ) SymTab::validate( translationUnit, symtabp ); if ( symtabp ) { return 0; } // if if ( expraltp ) { ResolvExpr::AlternativePrinter printer( std::cout ); acceptAll( translationUnit, printer ); return 0; } // if if ( validp ) { dump( translationUnit ); return 0; } // if OPTPRINT( "mutate" ) ControlStruct::mutate( translationUnit ); OPTPRINT( "fixNames" ) CodeGen::fixNames( translationUnit ); OPTPRINT( "tweakInit" ) InitTweak::genInit( translationUnit ); if ( libcfap ) { // generate the bodies of cfa library functions LibCfa::makeLibCfa( translationUnit ); } // if if ( bresolvep ) { dump( translationUnit ); return 0; } // if OPTPRINT( "resolve" ) ResolvExpr::resolve( translationUnit ); if ( exprp ) { dump( translationUnit ); return 0; } // fix ObjectDecl - replaces ConstructorInit nodes OPTPRINT( "fixInit" ) InitTweak::fix( translationUnit, filename, libcfap || treep ); if ( ctorinitp ) { dump ( translationUnit ); return 0; } OPTPRINT("instantiateGenerics") GenPoly::instantiateGeneric( translationUnit ); OPTPRINT( "copyParams" ); GenPoly::copyParams( translationUnit ); OPTPRINT( "convertSpecializations" ) GenPoly::convertSpecializations( translationUnit ); OPTPRINT( "convertLvalue" ) GenPoly::convertLvalue( translationUnit ); if ( bboxp ) { dump( translationUnit ); return 0; } OPTPRINT( "box" ) GenPoly::box( translationUnit ); // print tree right before code generation if ( codegenp ) { dump( translationUnit ); return 0; } // if CodeGen::generate( translationUnit, *output, ! noprotop ); if ( output != &std::cout ) { delete output; } // if } catch ( SemanticError &e ) { if ( errorp ) { std::cerr << "---AST at error:---" << std::endl; dump( translationUnit, std::cerr ); std::cerr << std::endl << "---End of AST, begin error message:---\n" << std::endl; } e.print( std::cerr ); if ( output != &std::cout ) { delete output; } // if return 1; } catch ( UnimplementedError &e ) { std::cout << "Sorry, " << e.get_what() << " is not currently implemented" << std::endl; if ( output != &std::cout ) { delete output; } // if return 1; } catch ( CompilerError &e ) { std::cerr << "Compiler Error: " << e.get_what() << std::endl; std::cerr << "(please report bugs to " << std::endl; if ( output != &std::cout ) { delete output; } // if return 1; } // try deleteAll( translationUnit ); return 0; } // main static void parse( FILE * input, LinkageSpec::Type linkage, bool shouldExit ) { Parser::get_parser().set_linkage( linkage ); Parser::get_parser().parse( input ); fclose( input ); if ( shouldExit || Parser::get_parser().get_parseStatus() != 0 ) { exit( Parser::get_parser().get_parseStatus() ); } // if } static bool notPrelude( Declaration * decl ) { return ! LinkageSpec::isBuiltin( decl->get_linkage() ); } static void dump( std::list< Declaration * > & translationUnit, std::ostream & out ) { std::list< Declaration * > decls; if ( noprotop ) { filter( translationUnit.begin(), translationUnit.end(), std::back_inserter( decls ), notPrelude ); } else { decls = translationUnit; } printAll( decls, out ); deleteAll( translationUnit ); } // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //