65 static void reportError(
string message,
SourceRange, ErrorReport::Severity);
66 static unique_ptr<ast::Scope> Parse(UniqPtr<Parser>& parser,
const string& filename,
67 const vector<string>& definitions,
68 string srcroot,
string buildroot,
bool printAST);
70 int main(
int argc,
char *argv[]) {
74 unique_ptr<Arguments> args(Arguments::Parse(argc, argv));
75 if (not args or args->help)
77 Arguments::PrintUsage(cerr);
78 return (args ? 0 : 1);
84 Bytestream::SetDebugPattern(args->debugPattern);
85 Bytestream::SetDebugStream(Bytestream::Stdout());
88 Arguments::Print(*args, argDebug);
89 argDebug << Bytestream::Reset <<
"\n";
100 const string fabfile =
101 PathIsDirectory(args->input)
102 ? JoinPath(args->input,
"fabfile")
106 if (not PathIsFile(fabfile))
107 throw UserError(
"no such file: '" + fabfile +
"'");
109 const string srcroot = AbsoluteDirectory(DirectoryOf(fabfile));
110 const string buildroot = AbsoluteDirectory(args->output);
118 unique_ptr<ast::Parser> parser(
119 new ast::Parser(types, pluginRegistry, pluginLoader, srcroot));
121 unique_ptr<ast::Scope> ast(
122 Parse(parser, fabfile, args->definitions,
123 srcroot, buildroot, args->printAST));
135 UniqPtrVec<Backend> backends;
136 vector<string> outputFiles;
137 for (
const string& format : args->outputFormats)
139 backends.emplace_back(Backend::Create(format));
141 const string filename = backends.back()->DefaultFilename();
142 if (not filename.empty())
143 outputFiles.push_back(filename);
151 auto topScope(ctx.Evaluate(*ast));
154 vector<string> targets;
155 transform(topScope.begin(), topScope.end(), back_inserter(targets),
156 [](
const pair<string,dag::ValuePtr>& i)
162 if (not outputFiles.empty())
163 ctx.builder().AddRegeneration(
164 *args, parser->files(), outputFiles);
166 unique_ptr<dag::DAG> dag = ctx.builder().dag(targets);
172 << Bytestream::Comment
174 <<
"# DAG pretty-printed from '"
186 for (UniqPtr<Backend>& backend : backends)
188 std::ofstream outfile;
189 unique_ptr<Bytestream> outfileStream;
191 const string filename =
192 JoinPath(buildroot, backend->DefaultFilename());
194 if (not args->printOutput and filename != buildroot)
196 outfile.open(filename.c_str());
202 : Bytestream::Stdout();
204 backend->Process(*dag, out, reportError);
215 << Bytestream::Error <<
"Error"
216 << Bytestream::Reset <<
": " << e
222 << Bytestream::Error << e.message()
223 << Bytestream::Reset <<
": "
224 << Bytestream::ErrorMessage << e.description()
234 << Bytestream::Error <<
"Parse error"
235 << Bytestream::Reset <<
": "
236 << Bytestream::ErrorMessage << e
241 catch (
const std::exception& e)
244 << Bytestream::Error <<
"Uncaught exception"
245 << Bytestream::Reset <<
": "
246 << Bytestream::ErrorMessage << e.what()
251 err() << Bytestream::Reset <<
"\n";
256 unique_ptr<ast::Scope> Parse(UniqPtr<Parser>& parser,
const string& filename,
257 const vector<string>& definitions,
258 string srcroot,
string buildroot,
bool printAST)
265 std::ifstream infile(filename.c_str());
268 map<string,string> builtins {
269 std::make_pair(
"srcroot", srcroot),
270 std::make_pair(
"buildroot", buildroot),
273 const string absolute =
274 PathIsAbsolute(filename) ? filename : AbsolutePath(filename);
276 unique_ptr<ast::Scope> ast(
277 parser->
ParseFile(infile, args, absolute, builtins));
281 for (
auto& error : parser->
errors())
282 err() << *error <<
"\n";
286 assert(parser->
errors().empty());
291 << Bytestream::Comment
293 <<
"# AST pretty-printed from '" << filename <<
"'\n"
298 for (
auto& val : ast->values())
299 Bytestream::Stdout() << *val <<
"\n";
308 static Bytestream& err = Bytestream::Stderr();
313 static void reportError(
string message,
SourceRange src, ErrorReport::Severity severity)
315 UniqPtr<ErrorReport> warning { ErrorReport::Create(message, src, severity) };
316 err() << *warning << Bytestream::Reset <<
"\n";
Interface for backend classes that convert a DAG to something else (e.g., a Ninja file)...
A context object that holds state for a compilation (e.g., type objects).
Declaration of fabrique::Arguments.
Declaration of fabrique::ast::EvalContext.
Declaration of fabrique::ast::Parser.
Base class for exceptions related to invalid source code.
Declaration of fabrique::plugin::Loader.
const UniqPtrVec< ErrorReport > & errors() const
Errors encountered during parsing.
const Type & ParseDefinitions(const std::vector< std::string > &defs)
Parse Fabrique fragments defined at, e.g., the command line.
std::unique_ptr< Scope > ParseFile(std::istream &input, const Type &arguments, std::string name="", StringMap< std::string > builtins=StringMap< std::string >(), SourceRange openedFrom=SourceRange::None())
Parse Fabrique input (usually a file) into a Scope.
Declaration of fabrique::ast::ASTDump.
Declaration of fabrique::TypeContext.
Declaration of fabrique::backend::Backend.
Parses Fabrique files as driven by flex/byacc.
Declaration of fabrique::dag::DAG.
An error that has an OS-specific description.
Declaration of basic Fabrique exceptions.
Declarations of OS-abstraction functions.
Support for loading plugins from shared libraries.
A ostream-like class that may support formatting.
Definition of fabrique::Lexer.
A range of characters in source code.
Declaration of fabrique::plugin::Registry.
A context for evaluating AST Expression objects.
static Bytestream & Debug(const std::string &name)
Retrieve the debug output stream or a do-nothing stream, based on the (hierarchical) debug naming sch...
Declaration of fabrique::Bytestream.
The name of a value, function, parameter or argument.
A registry for naming Fabrique Plugin objects.
A semantic error is present in the Fabrique description.
static Bytestream * Plain(std::ostream &)
Construct a plain fabrique::Bytestream to wrap an std::ostream.