Mercurial > projects > dil
changeset 778:78be32e3e157
Implemented conditional compilation.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Wed, 20 Feb 2008 22:09:29 +0100 |
parents | 9f61e8af55d5 |
children | 8e6fed11bb68 |
files | trunk/src/cmd/DDoc.d trunk/src/config.d trunk/src/dil/Compilation.d trunk/src/dil/Settings.d trunk/src/dil/SettingsLoader.d trunk/src/dil/semantic/Analysis.d trunk/src/dil/semantic/Pass1.d trunk/src/main.d |
diffstat | 8 files changed, 231 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/src/cmd/DDoc.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/cmd/DDoc.d Wed Feb 20 22:09:29 2008 +0100 @@ -21,6 +21,7 @@ import dil.semantic.Pass1; import dil.semantic.Symbol; import dil.semantic.Symbols; +import dil.Compilation; import dil.Information; import dil.Converter; import dil.SourceText; @@ -33,7 +34,8 @@ import tango.io.FilePath; void execute(string[] filePaths, string destDir, string[] macroPaths, - bool incUndoc, bool verbose, InfoManager infoMan) + bool incUndoc, bool verbose, CompilationContext context, + InfoManager infoMan) { // Parse macro files. MacroTable mtable; @@ -60,7 +62,7 @@ continue; // Start semantic analysis. - auto pass1 = new SemanticPass1(mod); + auto pass1 = new SemanticPass1(mod, context); pass1.start(); // Generate documentation. @@ -771,8 +773,20 @@ } D visit(DebugDeclaration d) - { return d; } + { + d.compiledDecls && visitD(d.compiledDecls); + return d; + } D visit(VersionDeclaration d) - { return d; } + { + d.compiledDecls && visitD(d.compiledDecls); + return d; + } + + D visit(StaticIfDeclaration d) + { + d.ifDecls && visitD(d.ifDecls); + return d; + } }
--- a/trunk/src/config.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/config.d Wed Feb 20 22:09:29 2008 +0100 @@ -3,6 +3,10 @@ /// Relative paths are resolved from the directory of the executable. module config; +/// Predefined version identifiers. +var version_ids = ["X86", "linux", "LittleEndian"]; +// "X86_64", "Windows", "Win32", "Win64", "BigEndian" + /// Path to the language file. var langfile = "lang_en.d";
--- a/trunk/src/dil/Compilation.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/dil/Compilation.d Wed Feb 20 22:09:29 2008 +0100 @@ -9,11 +9,61 @@ /// A group of settings relevant to the compilation process. class CompilationContext { + alias typeof(this) CC; + CC parent; string[] importPaths; uint debugLevel; uint versionLevel; bool[string] debugIds; bool[string] versionIds; bool releaseBuild; - uint structAlign; + uint structAlign = 4; + + this(CC parent = null) + { + this.parent = parent; + if (parent) + { + this.importPaths = parent.importPaths; + this.debugLevel = parent.debugLevel; + this.versionLevel = parent.versionLevel; + this.releaseBuild = parent.releaseBuild; + this.structAlign = parent.structAlign; + } + } + + void addDebugId(string id) + { + debugIds[id] = true; + } + + void addVersionId(string id) + { + versionIds[id] = true; + } + + bool findDebugId(string id) + { + auto pId = id in debugIds; + if (pId) + return true; + if (!isRoot()) + return parent.findDebugId(id); + return false; + } + + bool findVersionId(string id) + { + auto pId = id in versionIds; + if (pId) + return true; + if (!isRoot()) + return parent.findVersionId(id); + return false; + } + + bool isRoot() + { + return parent is null; + } }
--- a/trunk/src/dil/Settings.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/dil/Settings.d Wed Feb 20 22:09:29 2008 +0100 @@ -5,9 +5,12 @@ module dil.Settings; import common; +/// Global application settings. struct GlobalSettings { static: + /// Predefined version identifiers. + string[] versionIds; /// Path to the language file. string langFile = "lang_en.d"; /// Language code of loaded messages catalogue.
--- a/trunk/src/dil/SettingsLoader.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/dil/SettingsLoader.d Wed Feb 20 22:09:29 2008 +0100 @@ -12,6 +12,7 @@ import dil.semantic.Symbol; import dil.semantic.Symbols; import dil.Information; +import dil.Compilation; import common; import tango.io.FilePath; @@ -77,9 +78,14 @@ if (mod.hasErrors) return; - auto pass1 = new SemanticPass1(mod); + auto context = new CompilationContext; + auto pass1 = new SemanticPass1(mod, context); pass1.start(); + if (auto array = getValue!(ArrayInitExpression)("version_ids")) + foreach (value; array.values) + if (auto str = castTo!(StringExpression)(value)) + GlobalSettings.versionIds ~= str.getString(); if (auto val = getValue!(StringExpression)("langfile")) GlobalSettings.langFile = val.getString(); if (auto array = getValue!(ArrayInitExpression)("import_paths")) @@ -109,7 +115,7 @@ if (mod.hasErrors) return; - pass1 = new SemanticPass1(mod); + pass1 = new SemanticPass1(mod, context); pass1.start(); if (auto array = getValue!(ArrayInitExpression)("messages")) @@ -149,7 +155,8 @@ if (mod.hasErrors) return null; - auto pass1 = new SemanticPass1(mod); + auto context = new CompilationContext; + auto pass1 = new SemanticPass1(mod, context); pass1.start(); string[string] map;
--- a/trunk/src/dil/semantic/Analysis.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/dil/semantic/Analysis.d Wed Feb 20 22:09:29 2008 +0100 @@ -8,6 +8,7 @@ import dil.ast.Expressions; import dil.semantic.Scope; import dil.lexer.IdTable; +import dil.Compilation; import common; /// Common semantics for pragma declarations and statements. @@ -69,3 +70,37 @@ // scop.error(e.begin, "expression must evaluate to a string"); } } + +/// Returns true if the first branch (of a debug declaration/statement) or +/// false if the else-branch should be compiled in. +bool debugBranchChoice(Token* cond, CompilationContext context) +{ + if (cond) + { + if (cond.kind == TOK.Identifier) + { + if (context.findDebugId(cond.ident.str)) + return true; + } + else if (cond.uint_ <= context.debugLevel) + return true; + } + else if (1 <= context.debugLevel) + return true; + return false; +} + +/// Returns true if the first branch (of a version declaration/statement) or +/// false if the else-branch should be compiled in. +bool versionBranchChoice(Token* cond, CompilationContext context) +{ + assert(cond); + if (cond.kind == TOK.Identifier) + { + if (context.findVersionId(cond.ident.str)) + return true; + } + else if (cond.uint_ >= context.versionLevel) + return true; + return false; +}
--- a/trunk/src/dil/semantic/Pass1.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/dil/semantic/Pass1.d Wed Feb 20 22:09:29 2008 +0100 @@ -18,6 +18,7 @@ dil.semantic.Scope, dil.semantic.Module, dil.semantic.Analysis; +import dil.Compilation; import dil.Location; import dil.Information; import dil.Messages; @@ -25,32 +26,31 @@ import dil.CompilerInfo; import common; -/++ - The first pass is the declaration pass. - - The basic task of this class is to traverse the parse tree, - find all kinds of declarations and add them - to the symbol tables of their respective scopes. -+/ +/// The first pass is the declaration pass. +/// +/// The basic task of this class is to traverse the parse tree, +/// find all kinds of declarations and add them +/// to the symbol tables of their respective scopes. class SemanticPass1 : Visitor { Scope scop; /// The current scope. Module modul; /// The module to be semantically checked. + CompilationContext context; // Attributes: LinkageType linkageType; Protection protection; StorageClass storageClass; - uint alignSize = DEFAULT_ALIGN_SIZE; + uint alignSize; - /++ - Construct a SemanticPass1 object. - Params: - modul = the module to be processed. - +/ - this(Module modul) + /// Construct a SemanticPass1 object. + /// Params: + /// modul = the module to be processed. + this(Module modul, CompilationContext context) { this.modul = modul; + this.context = new CompilationContext(context); + this.alignSize = context.structAlign; } /// Start semantic analysis. @@ -352,14 +352,40 @@ { if (d.isSpecification) { - + if (d.spec.kind == TOK.Identifier) + context.addDebugId(d.spec.ident.str); + else + context.debugLevel = d.spec.uint_; } - return null; + else + { + if (debugBranchChoice(d.cond, context)) + d.compiledDecls = d.decls; + else + d.compiledDecls = d.elseDecls; + d.compiledDecls && visitD(d.compiledDecls); + } + return d; } D visit(VersionDeclaration d) { - return null; + if (d.isSpecification) + { + if (d.spec.kind == TOK.Identifier) + context.addVersionId(d.spec.ident.str); + else + context.versionLevel = d.spec.uint_; + } + else + { + if (versionBranchChoice(d.cond, context)) + d.compiledDecls = d.decls; + else + d.compiledDecls = d.elseDecls; + d.compiledDecls && visitD(d.compiledDecls); + } + return d; } D visit(TemplateDeclaration d)
--- a/trunk/src/main.d Wed Feb 20 01:24:19 2008 +0100 +++ b/trunk/src/main.d Wed Feb 20 22:09:29 2008 +0100 @@ -24,6 +24,7 @@ import dil.CompilerInfo; import dil.Information; import dil.SourceText; +import dil.Compilation; import cmd.Generate; import cmd.Statistics; @@ -55,8 +56,16 @@ if (args.length < 2) return printHelp("compile"); + string[] filePaths; + auto context = newCompilationContext(); + foreach (arg; args[2..$]) + { + if (parseDebugOrVersion(arg, context)) + {} + else + filePaths ~= arg; + } infoMan = new InfoManager(); - auto filePaths = args[2..$]; foreach (filePath; filePaths) { auto mod = new Module(filePath, infoMan); @@ -66,7 +75,7 @@ continue; // Start semantic analysis. - auto pass1 = new SemanticPass1(mod); + auto pass1 = new SemanticPass1(mod, context); pass1.start(); void printSymbolTable(ScopeSymbol scopeSym, char[] indent) @@ -98,9 +107,12 @@ bool incUndoc; bool verbose; // Parse arguments. + auto context = newCompilationContext(); foreach (arg; args[3..$]) { - if (arg == "-i") + if (parseDebugOrVersion(arg, context)) + {} + else if (arg == "-i") incUndoc = true; else if (arg == "-v") verbose = true; @@ -112,7 +124,7 @@ infoMan = new InfoManager(); // Execute command. - cmd.DDoc.execute(filePaths, destination, macroPaths, incUndoc, verbose, infoMan); + cmd.DDoc.execute(filePaths, destination, macroPaths, incUndoc, verbose, context, infoMan); infoMan.hasInfo && printErrors(infoMan); break; case "gen", "generate": @@ -323,6 +335,49 @@ return false; } +/// Creates the global compilation context. +CompilationContext newCompilationContext() +{ + auto cc = new CompilationContext; + cc.importPaths = GlobalSettings.importPaths; + cc.addVersionId("dil"); + cc.addVersionId("all"); +version(D2) + cc.addVersionId("D_Version2"); + foreach (versionId; GlobalSettings.versionIds) + if (!Lexer.isReservedIdentifier(versionId)) + cc.versionIds[versionId] = true; + return cc; +} + +bool parseDebugOrVersion(string arg, CompilationContext context) +{ + if (strbeg(arg, "-debug")) + { + if (arg.length > 7) + { + auto val = arg[7..$]; + if (isdigit(val[0])) + context.debugLevel = Integer.toInt(val); + else if (!Lexer.isReservedIdentifier(val)) + context.addDebugId(val); + } + else + context.debugLevel = 1; + } + else if (arg.length > 9 && strbeg(arg, "-version=")) + { + auto val = arg[9..$]; + if (isdigit(val[0])) + context.versionLevel = Integer.toInt(val); + else if (!Lexer.isReservedIdentifier(val)) + context.addVersionId(val); + } + else + return false; + return true; +} + void printErrors(InfoManager infoMan) { foreach (info; infoMan.info) @@ -354,7 +409,7 @@ switch (command) { case "c", "compile": - msg = "Compile D source files. + msg = `Compile D source files. Usage: dil compile file.d [file2.d, ...] [Options] @@ -362,9 +417,14 @@ Errors are printed to standard error output. Options: + -debug : include debug code + -debug=level : include debug(l) code where l <= level + -debug=ident : include debug(ident) code + -version=level : include version(l) code where l >= level + -version=ident : include version(ident) code Example: - dil c src/main.d"; + dil c src/main.d`; break; case "ddoc", "d": msg = `Generate documentation from DDoc comments in D source files. @@ -379,7 +439,7 @@ -v : verbose output Example: - dil d doc/ src/main.d mymacros.ddoc -i`; + dil d doc/ src/main.d src/macros_dil.ddoc -i`; break; case "gen", "generate": // msg = GetMsg(MID.HelpGenerate);