1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity average) 4 module dil.semantic.Analysis; 5 6 import dil.ast.Node, 7 dil.ast.Expressions; 8 import dil.semantic.Scope, 9 dil.semantic.Types, 10 dil.semantic.TypesEnum; 11 import dil.lexer.IdTable; 12 import dil.Compilation; 13 import common; 14 15 /// Common semantics for pragma declarations and statements. 16 void pragmaSemantic(Scope scop, Token* pragmaLoc, 17 Identifier* ident, 18 Expression[] args) 19 { 20 if (ident is Ident.msg) 21 pragma_msg(scop, pragmaLoc, args); 22 else if (ident is Ident.lib) 23 pragma_lib(scop, pragmaLoc, args); 24 // else 25 // scop.error(begin, "unrecognized pragma"); 26 } 27 28 /// Evaluates a msg pragma. 29 void pragma_msg(Scope scop, Token* pragmaLoc, Expression[] args) 30 { 31 if (args.length == 0) 32 return /*scop.error(pragmaLoc, "expected expression arguments to pragma")*/; 33 34 foreach (arg; args) 35 { 36 auto e = arg/+.evaluate()+/; 37 if (e is null) 38 { 39 // scop.error(e.begin, "expression is not evaluatable at compile time"); 40 } 41 else if (auto stringExpr = e.Is!(StringExpr)) 42 // Print string to standard output. 43 Stdout(stringExpr.getString()); 44 else 45 { 46 // scop.error(e.begin, "expression must evaluate to a string"); 47 } 48 } 49 // Print a newline at the end. 50 Stdout('\n'); 51 } 52 53 /// Evaluates a lib pragma. 54 void pragma_lib(Scope scop, Token* pragmaLoc, Expression[] args) 55 { 56 if (args.length != 1) 57 return /*scop.error(pragmaLoc, "expected one expression argument to pragma")*/; 58 59 auto e = args[0]/+.evaluate()+/; 60 if (e is null) 61 { 62 // scop.error(e.begin, "expression is not evaluatable at compile time"); 63 } 64 else if (auto stringExpr = e.Is!(StringExpr)) 65 { 66 // TODO: collect library paths in Module? 67 // scop.modul.addLibrary(stringExpr.getString()); 68 } 69 else 70 { 71 // scop.error(e.begin, "expression must evaluate to a string"); 72 } 73 } 74 75 /// Returns true if the first branch (of a debug declaration/statement) or 76 /// false if the else-branch should be compiled in. 77 bool debugBranchChoice(Token* cond, CompilationContext context) 78 { 79 if (cond) 80 { 81 if (cond.kind == TOK.Identifier) 82 { 83 if (context.findDebugId(cond.ident.str)) 84 return true; 85 } 86 else if (cond.uint_ <= context.debugLevel) 87 return true; 88 } 89 else if (1 <= context.debugLevel) 90 return true; 91 return false; 92 } 93 94 /// Returns true if the first branch (of a version declaration/statement) or 95 /// false if the else-branch should be compiled in. 96 bool versionBranchChoice(Token* cond, CompilationContext context) 97 { 98 assert(cond); 99 if (cond.kind == TOK.Identifier || cond.kind == TOK.Unittest) 100 { 101 if (context.findVersionId(cond.ident.str)) 102 return true; 103 } 104 else if (cond.uint_ >= context.versionLevel) 105 return true; 106 return false; 107 } 108 109 /// Performs an integer promotion on the type of e, according to spec. 110 void integerPromotion(Expression e) 111 { 112 assert(e.type !is null); 113 switch (e.type.baseType().tid) 114 { 115 case TYP.Bool, TYP.Int8, TYP.UInt8, TYP.Int16, 116 TYP.UInt16, TYP.Char, TYP.WChar: 117 e.type = Types.Int32; 118 break; 119 case TYP.DChar: 120 e.type = Types.UInt32; 121 break; 122 default: 123 } 124 }