Changeset 117
- Timestamp:
- 10/12/07 10:10:49 (11 months ago)
- Files:
-
- trunk/blade/Blade.d (modified) (1 diff)
- trunk/blade/BladeDemo.d (modified) (4 diffs)
- trunk/blade/BladeRank.d (modified) (5 diffs)
- trunk/blade/BladeUtil.d (modified) (2 diffs)
- trunk/blade/CodegenX86.d (modified) (7 diffs)
- trunk/blade/SyntaxTree.d (modified) (14 diffs)
- trunk/blade/SyntaxTreeDemo.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/blade/Blade.d
r115 r117 49 49 */ 50 50 51 module Blade;51 module blade.Blade; 52 52 53 public import SyntaxTree : mixin_SymbolTable, AbstractSyntaxTree, syntaxtreeof, AST, Symbol; 54 private import BladeUtil : wrapInQuotes; 55 private import BladeRank; 56 public import CodegenX86 : generateCodeForAsmX87, generateCodeForSSE2, isSSE2AsmPossible; 57 58 //----------------------------- 59 60 char [][] getFuncParams(char [] expr) 61 { 62 char [][] p = []; 63 int last=0; 64 for (int i=0; i<expr.length; ++i) { 65 if (expr[i]==',') { p ~= expr[last..i]; last=i+1; } 66 } 67 p ~= expr[last..$]; 68 return p; 69 } 70 71 template VecRetType(char [] expr) { 72 static if (expr.length>6 && expr[0..4]=="dot(" && expr[$-1]==')') { 73 alias real VecRetType; 74 } else alias void VecRetType; 75 } 76 77 template VEC(char [] rawexpr) { 78 VecRetType!(rawexpr) VEC(Values...)(Values values) { 79 const typelist = vectorTupleToString!(Values); 80 const ranklist = TupleRank!(Values); 81 static if (rawexpr.length>6 && rawexpr[0..4]=="dot(" && rawexpr[$-1]==')') { 82 const char [][] par = getFuncParams(rawexpr[4..$-1]); 83 const char [] expr = "(" ~ par[0]~ ")*(" ~ par[1]~ ")"; 84 const char combineOp = '+'; 85 } else { 86 const char [] expr = rawexpr; 87 const char combineOp = 0; 88 } 89 90 static if (isX87AsmPossible(typelist, ranklist, expr)) { 91 pragma(msg, generateCodeForAsmX87(typelist, ranklist, expr, combineOp)); 92 mixin(generateCodeForAsmX87(typelist, ranklist, expr, combineOp)); 93 } else pragma(msg, "x87 is impossible"); 94 } 95 } 53 public import blade.SyntaxTree : AbstractSyntaxTree, syntaxtreeof, AST, Symbol; 54 private import blade.BladeUtil : wrapInQuotes; 55 private import blade.BladeRank; 56 public import blade.CodegenX86 : generateCodeForAsmX87, generateCodeForSSE2, isSSE2AsmPossible; 96 57 97 58 public: 98 59 99 60 template SSEVECGEN(char [] rawexpr) { 100 VecRetType!(rawexpr)SSEVECGEN(Values...)(Values values) {61 void SSEVECGEN(Values...)(Values values) { 101 62 const typelist = elementTupleToString!(Values); 102 63 const ranklist = TupleRank!(Values); 103 static if (rawexpr.length>6 && rawexpr[0..4]=="dot(" && rawexpr[$-1]==')') { 104 const char [][] par = getFuncParams(rawexpr[4..$-1]); 105 const char [] expr = "(" ~ par[0]~ ")*(" ~ par[1]~ ")"; 106 const char combineOp = '+'; 107 } else { 108 const char [] expr = rawexpr; 109 const char combineOp = 0; 110 } 64 const char [] expr = rawexpr; 65 const char combineOp = 0; 111 66 112 67 static if (isSSE2AsmPossible(typelist, expr)) { 113 68 pragma(msg, generateCodeForSSE2(ranklist, expr, combineOp)); 114 69 mixin(generateCodeForSSE2(ranklist, expr, combineOp)); 115 } else pragma(msg, "SSE2 is impossible ");70 } else pragma(msg, "SSE2 is impossible for: " ~ rawexpr); 116 71 } 117 72 } 118 119 73 120 74 char [] makeSSE(AbstractSyntaxTree tree) 121 75 { 122 76 char [] result = "SSEVECGEN!(" ~ wrapInQuotes(tree.expression) ~ ")("; 77 int knt=0; 123 78 for (int i=0; i<tree.symbolTable.length;++i) { 124 if ( i>0) result ~=",";79 if (knt>0) result ~=","; 125 80 result ~= tree.symbolTable[i].value; 81 ++knt; 126 82 } 127 83 return result~ ");"; trunk/blade/BladeDemo.d
r110 r117 6 6 7 7 module BladeDemo; 8 import Blade; 9 10 8 import blade.Blade; 11 9 import std.stdio; 12 10 … … 14 12 // This causes segfaults if trying to use SSE. For now, only use heap arrays 15 13 // with SSE2. 16 17 double[4] a0 = [3.4, 565, 31.3, 41.8];18 double[4] d0 = [17.0f, 28.25, 1, 56.2];19 20 21 14 22 15 void main() … … 26 19 double [] a = new double[4]; 27 20 double [] d = new double[4]; 28 a[0..$] = a0;29 d[0..$] = d0;21 a[0..$] = [3.4, 565, 31.3, 41.8]; 22 d[0..$] = [17.0, 28.25, 1, 56.2];; 30 23 auto w2=z.ptr; 31 24 float[] q = [17.0f, 28.25, 1]; … … 37 30 38 31 mixin(SSEVEC(" a += d*2.01")); 32 // mixin(SSEVEC("dot(d,d)")); 39 33 40 34 writefln("a=", a); 41 // writefln(qqq);42 // writefln(qq);43 /*44 // VEC!("C+=(B*A)")( a, 2213.3, q);45 VEC!("C+=(B*(A+D))")( 2213.3,a, q, d);46 // VEC!("B*=A")( 2213.3L,q);47 writefln(q);48 writefln(r);49 double y = VEC!("dot(B,A)")( 2213.3L,a);50 writefln(y);51 // pragma(msg, makePostfixForX87("A+(B*C)", null));52 */53 35 } trunk/blade/BladeRank.d
r112 r117 4 4 */ 5 5 6 module BladeRank;6 module blade.BladeRank; 7 7 8 8 // ------------------------------------------------ … … 39 39 static assert( elementTupleToString!() == cast(char[][])([])); 40 40 } 41 42 41 43 42 /// Determine the rank of every item of the tuple T. … … 127 126 if (s[0]>='A' && s[0]<='Z') 128 127 return 0; 128 int i = 0; 129 if (s[0]>='a' && s[0]<='z') i=1; // next char is a parenthesis - so the code 130 // below works 131 129 132 int numParens = 0; 130 for ( int i=0; i<s.length; ++i) {133 for (; i<s.length; ++i) { 131 134 if (s[i]=='(') { 132 135 numParens++; … … 150 153 { 151 154 int x = exprLength(expr); 155 int y = x+1; 156 if (expr[x+2]=='=') ++y; // deal with op=. 152 157 153 char [] op = expr[x+1.. x+2];158 char [] op = expr[x+1..y+1]; 154 159 char [] left = expr[0..x+1]; 155 char [] right = expr[ x+2..$];160 char [] right = expr[y+1..$]; 156 161 int lrank = (left.length==1)? rank[left[0]-'A'] : exprRank(left[1..$-1], rank); 157 162 int rrank = (right.length==1)? rank[right[0]-'A'] : exprRank(right[1..$-1], rank); 158 if (op=="+" || op=="-" || op=="=" ) {163 if (op=="+" || op=="-" || op=="=" || op=="+=" || op=="-=") { 159 164 assert(lrank==rrank, "Rank error in expression"); 160 165 return lrank; 161 166 } 167 // For *, /, only scalar operations are permitted 162 168 if (lrank==0) return rrank; 163 169 if (rrank==0) return lrank; … … 169 175 assert(exprRank("A+(B*C)", [1,1,0])==1); 170 176 assert(exprRank("A+(B*C)", [0,0,0])==0); 171 assert(exprRank("A+(B*C)", [2,0,2])==2); 177 assert(exprRank("A=(B*C)", [2,0,2])==2); 178 assert(exprRank("D+=((A+C)*B)", [2,0,2,2])==2); 172 179 } 173 180 trunk/blade/BladeUtil.d
r110 r117 5 5 */ 6 6 7 module BladeUtil;7 module blade.BladeUtil; 8 8 9 9 public: … … 30 30 char [] str=`"`; 31 31 foreach(char c; instr) { 32 if (c=='"' ) str~=`\"`;33 else str~=c;32 if (c=='"' || c=='\\') str ~= `\`; 33 str ~= c; 34 34 } 35 return str ~ `"`;35 return str ~ `"`; 36 36 } 37 trunk/blade/CodegenX86.d
r112 r117 49 49 */ 50 50 51 module CodegenX86;52 private import BladeUtil;53 private import BladeRank;51 module blade.CodegenX86; 52 private import blade.BladeUtil; 53 private import blade.BladeRank; 54 54 55 55 private: … … 123 123 124 124 125 // num chars before we get a comma. 126 int paramLength(char [] s) 127 { 128 for (int i=0; i<s.length; ++i) { 129 if (s[i]==',') return i; 130 } 131 assert(0); 132 } 133 125 134 /// Converts an infix string into postfix. 126 135 /// Apply SSE/SSE2-specific optimisations during the conversion. … … 141 150 if (first[0]=='(') { 142 151 first = makePostfixForSSE(first[1..first.length-1], ranklist); 143 }else assert(first.length<2, "Missing () in expression: " ~ first); 152 } else if (first[0]=='d') { // dot product 153 return "AA="; 154 // assert(0, "xxx" ~ first ~ " " ~ second); 155 // first="A"; 156 // int comma = paramLength(first[2..$-1]); 157 // char [] right = first[comma+1..$-1]; 158 // first = '#' ~ makePostfixForSSE(first[2..comma], ranklist) ~ makePostfixForSSE(right, ranklist) ~ "*+"; 159 } else assert(first.length<2, "Missing () in expression: " ~ first); 144 160 if (second[0]=='(') { 145 161 second = makePostfixForSSE(second[1..second.length-1], ranklist); … … 334 350 char [] indexedSSEVector(int [] ranklist, char var) 335 351 { 336 return "[" ~ vectorRegister[vectorNum(ranklist, var)] ~ " + 8* EAX]";352 return "[" ~ vectorRegister[vectorNum(ranklist, var)] ~ " + 8*EAX]"; 337 353 } 338 354 … … 562 578 result~= " auto vec" ~ itoa(i) ~ " = values[" ~itoa(i) ~"].ptr; // " ~ cast(char)('A'+i)~ \n; 563 579 ++vecnum; 564 } else result~= " auto val" ~ itoa(i) ~ " = values["~itoa(i)~"]; // " ~ cast(char)('A'+i)~ \n;580 } 565 581 } 566 582 result ~= " int veclength = values[" ~itoa(findFirstVector(ranklist)) ~"].length;\n"; … … 584 600 ++numvecs; 585 601 } else if (ranklist[i]==0) { 586 // result ~= " movsd " ~ XMM(numconsts) ~ ", double ptrvalues["~ itoa(i) ~"]; "587 result ~= " movsd " ~ XMM(numconsts) ~ ", double ptr val"~ itoa(i) ~"; "602 result ~= " movsd " ~ XMM(numconsts) ~ ", values["~ itoa(i) ~"]; " 603 // result ~= " movsd " ~ XMM(numconsts) ~ ", double ptr val"~ itoa(i) ~"; " 588 604 " shufpd " ~ XMM(numconsts) ~", " ~ XMM(numconsts) ~ ",0; //" ~ cast(char)('A'+i) ~ \n; 589 605 ++numconsts; … … 623 639 // If it's a float or double, we can combine the load+arithmetic op 624 640 // into a single instruction. 625 if (operations[done+1]=='=') mainbody ~= " movapd " ~ indexedSSEVector(ranklist, operations[$-2] ) ~ ", XMM" ~ itoa(numOnStack-1) ~"; // " ~ operations[$-2..$] ~ \n;641 if (operations[done+1]=='=') mainbody ~= " movapd " ~ indexedSSEVector(ranklist, operations[$-2] ) ~ ", XMM" ~ itoa(numOnStack-1) ~"; // " ~ operations[$-2..$] ~ \n; 626 642 else mainbody ~= " " ~ opToSSE2[operations[done+1]] ~ " " ~ XMM(numOnStack-1) ~ ", " 627 643 ~ indexedSSEVector(ranklist, operations[done] ) ~ "; // " ~ operations[done..done+2] ~ \n; trunk/blade/SyntaxTree.d
r116 r117 9 9 * 10 10 * THEORY: 11 * Nested mixins are used. The outermost onetricks the compiler into11 * Nested mixins are used. One mixin tricks the compiler into 12 12 * converting the expression into a standard form with precedence and 13 13 * associativity information. The inner mixin determines the type and value … … 16 16 * us to probe the compiler's symbol table. Because it can be applied to any 17 17 * expression or type, we can get away with a very rudimentary lexer. 18 * The two levels of mixins are required because of some quirks in the behaviour19 * of stringof.20 18 * 21 19 * BUGS: … … 30 28 * mixin, assert, and import expressions 31 29 * D 2.004 string literals. 30 * NOTES: 31 * Functions (including properties) are typed as function pointers in the symbol table. 32 32 * QUIRKS: 33 * Functions are typed as function pointers in the symbol table, unless they are34 * used as properties, in which case they appear as function types.35 33 * If the expression refers to a non-existent variable, a sensible error message 36 * will be printed, but it will be followed by a torrent of useless error messages.37 * 34 * will be printed, but it will be followed by a torrent of useless error messages. 35 * The syntaxtreeof() function and the Symbol and AST classes must be visible to the user code. 38 36 */ 39 module SyntaxTree;40 import BladeUtil : wrapInQuotes;37 module blade.SyntaxTree; 38 import blade.BladeUtil : wrapInQuotes; 41 39 42 40 public: … … 45 43 * Returns a string, which, when mixed in, lexes, parses, and semantically 46 44 * analyses the given expression, then creates a struct literal of type 47 * AbstractSyntaxTree, containing a symbol table and a syntax tree. 45 * AbstractSyntaxTree, containing a syntax tree and a symbol table. 46 * The symbol table contains the type, and value for each symbol. 48 47 * 49 48 * Syntax trees are represented as placeholder expressions, with associativity … … 51 50 * the symbol table. 52 51 * 53 54 52 * Typically, this function will be a code generator for a mixin. 55 53 */ 56 54 char [] syntaxtreeof(char [] expression) 57 55 { 58 char [] expr = expression; 59 char [][] symbols = replaceSymbolsWithPlaceholders(expr); 60 // if (symbols.length> 25) return `static assert(0, "Too many symbols in expression.");`; 61 return `mixin(mixin_SymbolTable(` ~ wrapInQuotes(expression)~ `,` ~ mixin_getPrecedence(expr) ~ `))`; 62 } 63 56 char [][] symbols = replaceSymbolsWithPlaceholders(expression); 57 char [] result = `AbstractSyntaxTree(` ~ mixin_getPrecedence(expression) ~ `,[`; 58 for(int i=0; i<symbols.length; ++i) { 59 if (i>0) result ~=","; 60 result ~= `Symbol(` ~ mixin_typeOf(symbols[i]) 61 ~ `,` ~ mixin_valueOf(symbols[i]) ~ `)`; 62 } 63 result ~="])"; 64 return "mixin(" ~ wrapInQuotes(result) ~ ")"; 65 } 66 67 /** The result of semantic analysis of the original expression 68 * 69 */ 70 struct AbstractSyntaxTree { 71 char [] expression; /// syntax tree in Placeholder format, eg A+=(B*C) 72 Symbol[] symbolTable; /// Textual form of the types and values of A,B,C,... 73 } 64 74 65 75 /** The values of the A, B, C, ... placeholders … … 68 78 * type the name of the type, as text 69 79 * value The value, as text. This will be either a symbol name, or a literal. 70 * Note that if it is a numeric or text literal, value[0] will be one of the characters71 * 0123456789"'-80 * Note that if it is a numeric or text literal, value[0] will be one of 81 * the characters 0123456789"'- 72 82 */ 73 83 struct Symbol { 74 char [] type; // the name of the type, as text 75 char [] value; // the value, as text. 76 } 77 78 /** The result of semantic analysis of the original expression 79 * 80 */ 81 struct AbstractSyntaxTree { 82 char [] expression; /// syntax tree in Placeholder format, eg A+=(B*C) 83 Symbol[] symbolTable; /// Textual form of the types and values of A,B,C,... 84 char [] type; /// the name of the type, as text 85 char [] value; /// the value, as text. 86 char [] element; /// mangleof the type of the elements, if an array. 87 int rank; /// the tensor rank (0=scalar, 1=vector, 2 = matrix, 3=tensor) 84 88 } 85 89 … … 112 116 } 113 117 114 // return -1 if not found115 int indexInArray(char [] str, char [][] array)116 {117 for (int i=0; i<array.length;++i) {118 if (str==array[i]) return i;119 }120 return -1;121 }122 123 118 /** 124 119 * Extract all terminal symbols(identifiers, type names, and literals) … … 128 123 * Returns: an array of symbols (with no duplicates, though aliasing may exist) 129 124 * 130 * Supports allD syntax, except D2.004 string literals.125 * Supports *all* D syntax, except D2.004 string literals. 131 126 */ 132 127 char [][] replaceSymbolsWithPlaceholders(inout char [] expr) … … 140 135 char c = expr[i]; 141 136 // Deal with string literals 142 if (quote !=0) {143 symbol ~=c;144 if (c ==quote && (symbol.length<1 || symbol[$-1]!='\\')) quote=0;137 if (quote != 0) { 138 symbol ~= c; 139 if (c == quote && (symbol.length<1 || symbol[$-1]!='\\')) quote = 0; 145 140 continue; 146 } else if (c =='"' || c=='`' || c == '\'') { // Is a string literal beginning?147 symbol ~=c;148 quote =c;141 } else if (c == '"' || c == '`' || c == '\'') { // Is a string literal beginning? 142 symbol ~= c; 143 quote = c; 149 144 continue; 150 145 } 146 // Identifiers and numeric literals 151 147 if ((c >='a' && c <= 'z') || (c>='A' && c<='Z')|| (c>='0' && c<='9')||(c=='_')||(c=='$')||(c>0x7F)){ 152 148 symbol ~= c; 153 149 } else { 154 150 if ((c=='+' || c=='-') && symbol.length>1 && (symbol[0]>='0' && symbol[0]<='9') && (symbol[$-1]=='e' ||symbol[$-1]=='p'|| symbol[$-1]=='E' || symbol[$-1]=='P')) { 155 symbol ~= c; // + and - are part of the symbol, if it is a floating-point literal151 symbol ~= c; // + and - are part of the symbol, if it is a floating-point literal 156 152 continue; 157 153 } … … 166 162 } 167 163 if (symbol.length>0) { 168 int k = indexInArray(symbol, symbols); 169 if (k>=0) { // it's already in the symbol table. 170 code ~= cast(char)('A' + k); 171 } else { 172 // assign a letter to this symbol 173 code ~= cast(char)('A'+symbols.length); 174 // and add it to the symbol table 164 // Find it, and add it to the symbol table if not already present. 165 int k=0; 166 while(k < symbols.length && symbol!=symbols[k]) ++k; 167 code ~= cast(char)('A' + k); 168 if (k==symbols.length) { 175 169 symbols ~= symbol; 176 170 } … … 184 178 code ~= c; 185 179 } else { 186 // Remove comments.180 // Ignore comments. 187 181 if (expr[i..i+2]=="//") { 188 182 for ( ; i<expr.length && expr[i]!='\n' ; ++i) {} … … 208 202 } 209 203 210 unittest {211 char [] expr = "xyzzy+ y/+ comment/++ /++//++/+/ +/*2";212 char [][] symbols = replaceSymbolsWithPlaceholders(expr);213 assert(expr == "A+ B*C");214 }215 204 216 205 // ==== SYNTAX PASS ==== … … 294 283 } 295 284 296 297 285 /** 298 286 * Insert parentheses around each symbol, to enforce normal D precedence rules. … … 321 309 } 322 310 311 // ==== SEMANTIC PASS ==== 312 313 // Returns typeof(sym).stringof, with workarounds for compiler bugs 314 char [] mixin_typeOf(char [] sym) 315 { 316 // Compiler bug: typeof(x).stringof doesn't compile if x is a function. 317 return `mixin(is(typeof(` ~ sym ~ `)==function)?` ~ wrapInQuotes("typeof(&" ~ sym ~ ").stringof")~`:` ~ wrapInQuotes("typeof(" ~ sym ~ ").stringof") ~ `)`; 318 } 319 320 321 // Returns sym.stringof, with workarounds for compiler bugs 322 char [] mixin_valueOf(char [] sym) 323 { 324 // This function would just return sym.stringof, except for a couple of compiler bugs. 325 // (1) 1.23.stringof fails to compile. Fortunately (1.23).stringof works. 326 // (2) x.stringof doesn't compile, if x is a function. Just return x instead. 327 if (sym[0]>='0' && sym[0]<='9') { // numeric literal 328 return "(" ~ sym ~ ").stringof"; 329 } 330 return `mixin(is(typeof(` ~ sym ~ `)==function)?` ~ wrapInQuotes(wrapInQuotes(sym)) ~ `:` ~ wrapInQuotes(sym ~ ".stringof") ~ ")"; 331 } 332 333 // ==== TESTS ==== 334 323 335 unittest { 324 assert(mixin(mixin_getPrecedence("D -= A+B *C"))=="D-=(A+(B*C))"); 325 assert(mixin(mixin_getPrecedence("D -= ++A"))=="D-=(++A)"); 326 assert(mixin(mixin_getPrecedence("A[B,C/D]=E+F"))=="A[B,(C/D)]=(E+F)"); 327 assert(mixin(mixin_getPrecedence("G-=A[B][C..B^D][D]*E+F"))=="G-=((A[B][C..(B^D)][D]*E)+F)"); 328 assert(mixin(mixin_getPrecedence("E=A[B,C/D]*F"))=="E=(A[B,(C/D)]*F)"); 329 assert(mixin(mixin_getPrecedence("(A+B) in(C^D)"))=="(A+B)in(C^D)"); 330 assert(mixin(mixin_getPrecedence("A"))=="A"); 331 } 332 333 // ==== SEMANTIC PASS ==== 334 335 bool isFunc(int n, char [] expr) 336 { 337 char c = n + 'A'; 338 for (int i=0; i<expr.length-1; ++i) { 339 if ((expr[i]==c) && expr[i+1]=='(') return true; 340 } 341 return false; 342 } 343 344 public: 345 /** FOR MIXIN 346 * Given a raw expression, and a processed expression (with placeholders, and 347 * correct precedence), return a string to be mixed in, which will 348 * generate the type and value associated with each symbol. 349 * When mixed in, an AbstractSyntaxTree containing a Symbol[] array literal will be generated. 350 */ 351 char [] mixin_SymbolTable(char [] expression, char [] exprWithPlaceholders) 352 { 353 char [] expr = expression; 336 char [] expr = "xyzzy+ y/+ comment/++ /++//++/+/ +/*2"; 354 337 char [][] symbols = replaceSymbolsWithPlaceholders(expr); 355 char [] result = `AbstractSyntaxTree("` ~ exprWithPlaceholders ~ `",[`; 356 for(int i=0; i<symbols.length; ++i) { 357 if (i>0) result ~=","; 358 if (isFunc(i, exprWithPlaceholders)) 359 result ~= `Symbol(typeof(&` ~ symbols[i] ~ `).stringof,"` ~ symbols[i]~ `")`; 360 else if (symbols[i][0]>='0' && symbols[i][0]<='9') { 361 result ~= `Symbol(typeof(` ~ symbols[i] ~ `).stringof, (` ~symbols[i] ~ `).stringof)`; 362 } else 363 result ~= `Symbol(typeof(` ~ symbols[i] ~ `).stringof, ` ~symbols[i] ~ `.stringof)`; 364 } 365 result ~="])"; 366 return result; 367 } 338 assert(expr == "A+ B*C"); 339 340 assert(mixin(mixin_getPrecedence("D -= A+B *C"))=="D-=(A+(B*C))"); 341 assert(mixin(mixin_getPrecedence("D -= ++A"))=="D-=(++A)"); 342 assert(mixin(mixin_getPrecedence("A[B,C/D]=E+F"))=="A[B,(C/D)]=(E+F)"); 343 assert(mixin(mixin_getPrecedence("G-=A[B][C..B^D][D]*E+F"))=="G-=((A[B][C..(B^D)][D]*E)+F)"); 344 assert(mixin(mixin_getPrecedence("E=A[B,C/D]*F"))=="E=(A[B,(C/D)]*F)"); 345 assert(mixin(mixin_getPrecedence("(A+B) in(C^D)"))=="(A+B)in(C^D)"); 346 assert(mixin(mixin_getPrecedence("A"))=="A"); 347 } trunk/blade/SyntaxTreeDemo.d
r109 r117 10 10 */ 11 11 12 module SyntaxTreeDemo;13 import SyntaxTree;12 module blade.SyntaxTreeDemo; 13 import blade.SyntaxTree : syntaxtreeof, AbstractSyntaxTree, Symbol, AST; 14 14 15 15 // Display the syntax tree … … 49 49 char [] displayParseResult(AbstractSyntaxTree tree) 50 50 { 51 char [] sym=" ";51 char [] sym=" Rank\tType\tValue\n"; 52 52 for (int i=0; i<tree.symbolTable.length; ++i) { 53 53 Symbol q = tree.symbolTable[i]; 54 sym~=cast(char)('A'+i) ~ ": " ~ q.type ~ \t ~ q.value ~ \t;54 sym~=cast(char)('A'+i) ~ ": " ~ q.type ~ \t ~ q.value ~ \t; 55 55 char c = q.value[0]; 56 56 bool isConst = ((c>='0' && c<='9')||c=='-'|| c=='"' || c=='\''); … … 84 84 85 85 const QUAL = Blah!(7)("abc", 4); 86 import std.math; 87 86 88 void main() 87 89 { … … 97 99 mixin(vec("func(d*35,d+ 4)")); 98 100 mixin(vec("QUAL")); 101 mixin(vec("sin(3.45)")); 99 102 }
