comparison src/main.d @ 806:bcb74c9b895c

Moved out files in the trunk folder to the root.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 09 Mar 2008 00:12:19 +0100
parents trunk/src/main.d@dcd30b0ba711
children a2880c95eda3
comparison
equal deleted inserted replaced
805:a3fab8b74a7d 806:bcb74c9b895c
1 /++
2 Author: Aziz Köksal
3 License: GPL3
4 +/
5 module main;
6
7 import dil.parser.Parser;
8 import dil.lexer.Lexer,
9 dil.lexer.Token;
10 import dil.ast.Declarations,
11 dil.ast.Expressions,
12 dil.ast.Node,
13 dil.ast.Visitor;
14 import dil.semantic.Module;
15 import dil.semantic.Symbols;
16 import dil.semantic.Pass1,
17 dil.semantic.Pass2,
18 dil.semantic.Interpreter;
19 import dil.translator.German;
20 import dil.doc.Doc;
21 import dil.Messages;
22 import dil.CompilerInfo;
23 import dil.Information;
24 import dil.SourceText;
25 import dil.Compilation;
26
27 import cmd.Generate;
28 import cmd.Statistics;
29 import cmd.ImportGraph;
30 import cmd.DDoc;
31
32 import Settings;
33 import SettingsLoader;
34 // import TypeRules;
35 import common;
36
37 import Integer = tango.text.convert.Integer;
38 import tango.stdc.stdio;
39 import tango.io.File;
40 import tango.text.Util;
41 import tango.time.StopWatch;
42 import tango.text.Ascii : icompare;
43
44 /// Entry function of dil.
45 void main(char[][] args)
46 {
47 auto infoMan = new InfoManager();
48 SettingsLoader.SettingsLoader(infoMan).load();
49 if (infoMan.hasInfo)
50 return printErrors(infoMan);
51
52 if (args.length <= 1)
53 return Stdout(helpMain()).newline;
54
55 string command = args[1];
56 switch (command)
57 {
58 case "c", "compile":
59 if (args.length < 2)
60 return printHelp("compile");
61
62 string[] filePaths;
63 auto context = newCompilationContext();
64 foreach (arg; args[2..$])
65 {
66 if (parseDebugOrVersion(arg, context))
67 {}
68 else
69 filePaths ~= arg;
70 }
71 infoMan = new InfoManager();
72 foreach (filePath; filePaths)
73 {
74 auto mod = new Module(filePath, infoMan);
75 // Parse the file.
76 mod.parse();
77 if (mod.hasErrors)
78 continue;
79
80 // Start semantic analysis.
81 auto pass1 = new SemanticPass1(mod, context);
82 pass1.start();
83
84 void printSymbolTable(ScopeSymbol scopeSym, char[] indent)
85 {
86 foreach (member; scopeSym.members)
87 {
88 auto tokens = getDocTokens(member.node);
89 char[] docText;
90 foreach (token; tokens)
91 docText ~= token.srcText;
92 Stdout(indent).formatln("Id:{}, Symbol:{}, DocText:{}", member.name.str, member.classinfo.name, docText);
93 if (auto s = cast(ScopeSymbol)member)
94 printSymbolTable(s, indent ~ "→ ");
95 }
96 }
97
98 printSymbolTable(mod, "");
99 }
100
101 infoMan.hasInfo && printErrors(infoMan);
102 break;
103 case "ddoc", "d":
104 if (args.length < 4)
105 return printHelp("ddoc");
106
107 auto destination = args[2];
108 auto macroPaths = GlobalSettings.ddocFilePaths;
109 char[][] filePaths;
110 bool incUndoc;
111 bool writeXML;
112 bool verbose;
113 // Parse arguments.
114 auto context = newCompilationContext();
115 foreach (arg; args[3..$])
116 {
117 if (parseDebugOrVersion(arg, context))
118 {}
119 else if (arg == "--xml")
120 writeXML = true;
121 else if (arg == "-i")
122 incUndoc = true;
123 else if (arg == "-v")
124 verbose = true;
125 else if (arg.length > 5 && icompare(arg[$-4..$], "ddoc") == 0)
126 macroPaths ~= arg;
127 else
128 filePaths ~= arg;
129 }
130
131 infoMan = new InfoManager();
132 // Execute command.
133 cmd.DDoc.execute(filePaths, destination, macroPaths, writeXML,
134 incUndoc, verbose, context, infoMan);
135 infoMan.hasInfo && printErrors(infoMan);
136 break;
137 case "gen", "generate":
138 char[] fileName;
139 GenOption options = GenOption.Tokens;
140 foreach (arg; args[2..$])
141 {
142 switch (arg)
143 {
144 case "--syntax":
145 options |= GenOption.Syntax; break;
146 case "--xml":
147 options |= GenOption.XML; break;
148 case "--html":
149 options |= GenOption.HTML; break;
150 case "--lines":
151 options |= GenOption.PrintLines; break;
152 default:
153 fileName = arg;
154 }
155 }
156 if (!(options & (GenOption.XML | GenOption.HTML)))
157 options |= GenOption.XML; // Default to XML.
158 cmd.Generate.execute(fileName, options, infoMan);
159 infoMan.hasInfo && printErrors(infoMan);
160 break;
161 case "importgraph", "igraph":
162 string filePath;
163 string[] regexps;
164 string siStyle = "dashed"; // static import style
165 string piStyle = "bold"; // public import style
166 uint levels;
167 IGraphOption options;
168 auto context = newCompilationContext();
169 foreach (arg; args[2..$])
170 {
171 if (parseDebugOrVersion(arg, context))
172 {}
173 else if (strbeg(arg, "-I"))
174 context.importPaths ~= arg[2..$];
175 else if(strbeg(arg, "-r"))
176 regexps ~= arg[2..$];
177 else if(strbeg(arg, "-l"))
178 levels = Integer.toInt(arg[2..$]);
179 else if(strbeg(arg, "-si"))
180 siStyle = arg[3..$];
181 else if(strbeg(arg, "-pi"))
182 piStyle = arg[3..$];
183 else
184 switch (arg)
185 {
186 case "--dot":
187 options |= IGraphOption.PrintDot; break;
188 case "--paths":
189 options |= IGraphOption.PrintPaths; break;
190 case "--list":
191 options |= IGraphOption.PrintList; break;
192 case "-i":
193 options |= IGraphOption.IncludeUnlocatableModules; break;
194 case "-hle":
195 options |= IGraphOption.HighlightCyclicEdges; break;
196 case "-hlv":
197 options |= IGraphOption.HighlightCyclicVertices; break;
198 case "-gbp":
199 options |= IGraphOption.GroupByPackageNames; break;
200 case "-gbf":
201 options |= IGraphOption.GroupByFullPackageName; break;
202 case "-m":
203 options |= IGraphOption.MarkCyclicModules; break;
204 default:
205 filePath = arg;
206 }
207 }
208 cmd.ImportGraph.execute(filePath, context, regexps, levels, siStyle, piStyle, options);
209 break;
210 case "stats", "statistics":
211 char[][] filePaths;
212 bool printTokensTable;
213 bool printNodesTable;
214 foreach (arg; args[2..$])
215 if (arg == "--toktable")
216 printTokensTable = true;
217 else if (arg == "--asttable")
218 printNodesTable = true;
219 else
220 filePaths ~= arg;
221 cmd.Statistics.execute(filePaths, printTokensTable, printNodesTable);
222 break;
223 case "tok", "tokenize":
224 SourceText sourceText;
225 char[] filePath;
226 char[] separator;
227 bool ignoreWSToks;
228 bool printWS;
229
230 foreach (arg; args[2..$])
231 {
232 if (strbeg(arg, "-s"))
233 separator = arg[2..$];
234 else if (arg == "-")
235 sourceText = new SourceText("stdin", readStdin());
236 else if (arg == "-i")
237 ignoreWSToks = true;
238 else if (arg == "-ws")
239 printWS = true;
240 else
241 filePath = arg;
242 }
243
244 separator || (separator = "\n");
245 if (!sourceText)
246 sourceText = new SourceText(filePath, true);
247
248 infoMan = new InfoManager();
249 auto lx = new Lexer(sourceText, infoMan);
250 lx.scanAll();
251 auto token = lx.firstToken();
252
253 for (; token.kind != TOK.EOF; token = token.next)
254 {
255 if (token.kind == TOK.Newline || ignoreWSToks && token.isWhitespace)
256 continue;
257 if (printWS && token.ws)
258 Stdout(token.wsChars);
259 Stdout(token.srcText)(separator);
260 }
261
262 infoMan.hasInfo && printErrors(infoMan);
263 break;
264 case "trans", "translate":
265 if (args.length < 3)
266 return printHelp("trans");
267
268 if (args[2] != "German")
269 return Stdout.formatln("Error: unrecognized target language \"{}\"", args[2]);
270
271 infoMan = new InfoManager();
272 auto filePath = args[3];
273 auto mod = new Module(filePath, infoMan);
274 // Parse the file.
275 mod.parse();
276 if (!mod.hasErrors)
277 { // Translate
278 auto german = new GermanTranslator(Stdout, " ");
279 german.translate(mod.root);
280 }
281 printErrors(infoMan);
282 break;
283 case "profile":
284 if (args.length < 3)
285 break;
286 char[][] filePaths;
287 if (args[2] == "dstress")
288 {
289 auto text = cast(char[])(new File("dstress_files")).read();
290 filePaths = split(text, "\0");
291 }
292 else
293 filePaths = args[2..$];
294
295 StopWatch swatch;
296 swatch.start;
297
298 foreach (filePath; filePaths)
299 (new Lexer(new SourceText(filePath, true))).scanAll();
300
301 Stdout.formatln("Scanned in {:f10}s.", swatch.stop);
302 break;
303 // case "parse":
304 // if (args.length == 3)
305 // parse(args[2]);
306 // break;
307 case "?", "help":
308 printHelp(args.length >= 3 ? args[2] : "");
309 break;
310 // case "typerules":
311 // genHTMLTypeRulesTables();
312 // break;
313 default:
314 }
315 }
316
317 char[] readStdin()
318 {
319 char[] text;
320 while (1)
321 {
322 auto c = getc(stdin);
323 if (c == EOF)
324 break;
325 text ~= c;
326 }
327 return text;
328 }
329
330 /// Available commands.
331 const char[] COMMANDS =
332 " compile (c)\n"
333 " ddoc (d)\n"
334 " generate (gen)\n"
335 " help (?)\n"
336 " importgraph (igraph)\n"
337 " statistics (stats)\n"
338 " tokenize (tok)\n"
339 " translate (trans)\n";
340
341 bool strbeg(char[] str, char[] begin)
342 {
343 if (str.length >= begin.length)
344 {
345 if (str[0 .. begin.length] == begin)
346 return true;
347 }
348 return false;
349 }
350
351 /// Creates the global compilation context.
352 CompilationContext newCompilationContext()
353 {
354 auto cc = new CompilationContext;
355 cc.importPaths = GlobalSettings.importPaths;
356 cc.addVersionId("dil");
357 cc.addVersionId("all");
358 version(D2)
359 cc.addVersionId("D_Version2");
360 foreach (versionId; GlobalSettings.versionIds)
361 if (!Lexer.isReservedIdentifier(versionId))
362 cc.versionIds[versionId] = true;
363 return cc;
364 }
365
366 bool parseDebugOrVersion(string arg, CompilationContext context)
367 {
368 if (strbeg(arg, "-debug"))
369 {
370 if (arg.length > 7)
371 {
372 auto val = arg[7..$];
373 if (isdigit(val[0]))
374 context.debugLevel = Integer.toInt(val);
375 else if (!Lexer.isReservedIdentifier(val))
376 context.addDebugId(val);
377 }
378 else
379 context.debugLevel = 1;
380 }
381 else if (arg.length > 9 && strbeg(arg, "-version="))
382 {
383 auto val = arg[9..$];
384 if (isdigit(val[0]))
385 context.versionLevel = Integer.toInt(val);
386 else if (!Lexer.isReservedIdentifier(val))
387 context.addVersionId(val);
388 }
389 else
390 return false;
391 return true;
392 }
393
394 /// Prints the errors collected in infoMan.
395 void printErrors(InfoManager infoMan)
396 {
397 foreach (info; infoMan.info)
398 {
399 char[] errorFormat;
400 if (info.classinfo is LexerError.classinfo)
401 errorFormat = GlobalSettings.lexerErrorFormat;
402 else if (info.classinfo is ParserError.classinfo)
403 errorFormat = GlobalSettings.parserErrorFormat;
404 else if (info.classinfo is SemanticError.classinfo)
405 errorFormat = GlobalSettings.semanticErrorFormat;
406 else if (info.classinfo is Warning.classinfo)
407 errorFormat = "{0}: Warning: {3}";
408 else
409 continue;
410 auto err = cast(Problem)info;
411 Stderr.formatln(errorFormat, err.filePath, err.loc, err.col, err.getMsg);
412 }
413 }
414
415 /// Prints the compiler's main help message.
416 char[] helpMain()
417 {
418 auto COMPILED_WITH = __VENDOR__;
419 auto COMPILED_VERSION = Format("{}.{,:d3}", __VERSION__/1000, __VERSION__%1000);
420 auto COMPILED_DATE = __TIMESTAMP__;
421 return FormatMsg(MID.HelpMain, VERSION, COMMANDS, COMPILED_WITH,
422 COMPILED_VERSION, COMPILED_DATE);
423 }
424
425 /// Prints a help message for command.
426 void printHelp(char[] command)
427 {
428 char[] msg;
429 switch (command)
430 {
431 case "c", "compile":
432 msg = `Compile D source files.
433 Usage:
434 dil compile file.d [file2.d, ...] [Options]
435
436 This command only parses the source files and does little semantic analysis.
437 Errors are printed to standard error output.
438
439 Options:
440 -debug : include debug code
441 -debug=level : include debug(l) code where l <= level
442 -debug=ident : include debug(ident) code
443 -version=level : include version(l) code where l >= level
444 -version=ident : include version(ident) code
445
446 Example:
447 dil c src/main.d`;
448 break;
449 case "ddoc", "d":
450 msg = `Generate documentation from DDoc comments in D source files.
451 Usage:
452 dil ddoc Destination file.d [file2.d, ...] [Options]
453
454 Destination is the folder where the documentation files are written to.
455 Files with the extension .ddoc are recognized as macro definition files.
456
457 Options:
458 --xml : write XML instead of HTML documents
459 -i : include undocumented symbols
460 -v : verbose output
461
462 Example:
463 dil d doc/ src/main.d src/macros_dil.ddoc -i`;
464 break;
465 case "gen", "generate":
466 // msg = GetMsg(MID.HelpGenerate);
467 msg = `Generate an XML or HTML document from a D source file.
468 Usage:
469 dil gen file.d [Options]
470
471 Options:
472 --syntax : generate tags for the syntax tree
473 --xml : use XML format (default)
474 --html : use HTML format
475 --lines : print line numbers
476
477 Example:
478 dil gen Parser.d --html --syntax > Parser.html`;
479 break;
480 case "importgraph", "igraph":
481 // msg = GetMsg(MID.HelpImportGraph);
482 msg = `Parse a module and build a module dependency graph based on its imports.
483 Usage:
484 dil igraph file.d Format [Options]
485
486 The directory of file.d is implicitly added to the list of import paths.
487
488 Format:
489 --dot : generate a dot document (default)
490 Options related to --dot:
491 -gbp : Group modules by package names
492 -gbf : Group modules by full package name
493 -hle : highlight cyclic edges in the graph
494 -hlv : highlight modules in cyclic relationships
495 -siSTYLE : the edge style to use for static imports
496 -piSTYLE : the edge style to use for public imports
497 STYLE can be: "dashed", "dotted", "solid", "invis" or "bold"
498
499 --paths : print the file paths of the modules in the graph
500
501 --list : print the names of the module in the graph
502 Options common to --paths and --list:
503 -lN : print N levels.
504 -m : use '*' to mark modules in cyclic relationships
505
506 Options:
507 -Ipath : add 'path' to the list of import paths where modules are
508 looked for
509 -rREGEXP : exclude modules whose names match the regular expression
510 REGEXP
511 -i : include unlocatable modules
512
513 Example:
514 dil igraph src/main.d --list
515 dil igraph src/main.d | dot -Tpng > main.png`;
516 break;
517 case "tok", "tokenize":
518 msg = `Print the tokens of a D source file.
519 Usage:
520 dil tok file.d [Options]
521
522 Options:
523 - : reads text from the standard input.
524 -sSEPARATOR : print SEPARATOR instead of newline between tokens.
525 -i : ignore whitespace tokens (e.g. comments, shebang etc.)
526 -ws : print a token's preceding whitespace characters.
527
528 Example:
529 echo "module foo; void func(){}" | dil tok -
530 dil tok main.d | grep ^[0-9]`;
531 break;
532 case "stats", "statistics":
533 msg = "Gather statistics about D source files.
534 Usage:
535 dil stat file.d [file2.d, ...] [Options]
536
537 Options:
538 --toktable : print the count of all kinds of tokens in a table.
539 --asttable : print the count of all kinds of nodes in a table.
540
541 Example:
542 dil stat src/dil/Parser.d src/dil/Lexer.d";
543 break;
544 case "trans", "translate":
545 msg = `Translate a D source file to another language.
546 Usage:
547 dil translate Language file.d
548
549 Languages that are supported:
550 *) German
551
552 Example:
553 dil trans German src/main.d`;
554 break;
555 default:
556 msg = helpMain();
557 }
558 Stdout(msg).newline;
559 }
560
561 /+void parse(string fileName)
562 {
563 auto mod = new Module(fileName);
564 mod.parse();
565
566 void print(Node[] decls, char[] indent)
567 {
568 foreach(decl; decls)
569 {
570 assert(decl !is null);
571 Stdout.formatln("{}{}: begin={} end={}", indent, decl.classinfo.name, decl.begin ? decl.begin.srcText : "\33[31mnull\33[0m", decl.end ? decl.end.srcText : "\33[31mnull\33[0m");
572 print(decl.children, indent ~ " ");
573 }
574 }
575 print(mod.root.children, "");
576 }+/