Changeset 117

Show
Ignore:
Timestamp:
10/12/07 10:10:49 (11 months ago)
Author:
Don Clugston
Message:

* Major simplification of SyntaxTree?, which now supports functions properly.
* Correct SSE code generation. I've disabled x87 codegen for now -- but it will be back!

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/blade/Blade.d

    r115 r117  
    4949*/ 
    5050 
    51 module Blade; 
     51module blade.Blade; 
    5252 
    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 
     53public import blade.SyntaxTree : AbstractSyntaxTree, syntaxtreeof, AST, Symbol; 
     54private import blade.BladeUtil : wrapInQuotes; 
     55private import blade.BladeRank; 
     56public import blade.CodegenX86 : generateCodeForAsmX87, generateCodeForSSE2, isSSE2AsmPossible; 
    9657 
    9758public: 
    9859 
    9960template SSEVECGEN(char [] rawexpr) { 
    100  VecRetType!(rawexpr) SSEVECGEN(Values...)(Values values) { 
     61 void SSEVECGEN(Values...)(Values values) { 
    10162    const typelist = elementTupleToString!(Values); 
    10263    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; 
    11166     
    11267    static if (isSSE2AsmPossible(typelist, expr)) { 
    11368        pragma(msg, generateCodeForSSE2(ranklist, expr, combineOp)); 
    11469        mixin(generateCodeForSSE2(ranklist, expr, combineOp)); 
    115     } else pragma(msg, "SSE2 is impossible"); 
     70    } else pragma(msg, "SSE2 is impossible for: " ~ rawexpr); 
    11671 } 
    11772} 
    118  
    11973 
    12074char [] makeSSE(AbstractSyntaxTree tree) 
    12175{ 
    12276    char [] result = "SSEVECGEN!(" ~ wrapInQuotes(tree.expression) ~ ")("; 
     77    int knt=0; 
    12378    for (int i=0; i<tree.symbolTable.length;++i) { 
    124         if (i>0) result ~=","; 
     79        if (knt>0) result ~=","; 
    12580        result ~= tree.symbolTable[i].value; 
     81        ++knt; 
    12682    } 
    12783    return result~ ");"; 
  • trunk/blade/BladeDemo.d

    r110 r117  
    66 
    77module BladeDemo; 
    8 import Blade; 
    9  
    10  
     8import blade.Blade; 
    119import std.stdio; 
    1210 
     
    1412// This causes segfaults if trying to use SSE. For now, only use heap arrays 
    1513// 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  
    2114     
    2215void main() 
     
    2619    double [] a = new double[4]; 
    2720    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];
    3023    auto w2=z.ptr; 
    3124    float[] q = [17.0f, 28.25, 1]; 
     
    3730     
    3831    mixin(SSEVEC(" a   += d*2.01")); 
     32//    mixin(SSEVEC("dot(d,d)")); 
    3933     
    4034    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 */ 
    5335} 
  • trunk/blade/BladeRank.d

    r112 r117  
    44*/ 
    55 
    6 module BladeRank; 
     6module blade.BladeRank; 
    77 
    88// ------------------------------------------------ 
     
    3939static assert( elementTupleToString!() == cast(char[][])([])); 
    4040} 
    41  
    4241 
    4342/// Determine the rank of every item of the tuple T. 
     
    127126    if (s[0]>='A' && s[0]<='Z') 
    128127        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 
    129132    int numParens = 0; 
    130     for (int i=0; i<s.length; ++i) { 
     133    for (; i<s.length; ++i) { 
    131134        if (s[i]=='(') { 
    132135            numParens++; 
     
    150153{ 
    151154    int x = exprLength(expr); 
     155    int y = x+1; 
     156    if (expr[x+2]=='=') ++y; // deal with op=. 
    152157     
    153     char [] op = expr[x+1..x+2];     
     158    char [] op = expr[x+1..y+1];     
    154159    char [] left = expr[0..x+1]; 
    155     char [] right = expr[x+2..$]; 
     160    char [] right = expr[y+1..$]; 
    156161    int lrank = (left.length==1)?  rank[left[0]-'A'] : exprRank(left[1..$-1], rank); 
    157162    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=="-=") { 
    159164        assert(lrank==rrank, "Rank error in expression"); 
    160165        return lrank; 
    161166    } 
     167    // For *, /, only scalar operations are permitted 
    162168    if (lrank==0) return rrank; 
    163169    if (rrank==0) return lrank; 
     
    169175    assert(exprRank("A+(B*C)", [1,1,0])==1); 
    170176    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); 
    172179} 
    173180 
  • trunk/blade/BladeUtil.d

    r110 r117  
    55*/ 
    66 
    7 module BladeUtil; 
     7module blade.BladeUtil; 
    88 
    99public: 
     
    3030    char [] str=`"`; 
    3131    foreach(char c; instr) { 
    32         if (c=='"') str~=`\"`; 
    33         else str~=c;         
     32        if (c=='"' || c=='\\') str ~= `\`; 
     33        str ~= c;         
    3434    } 
    35     return str~ `"`; 
     35    return str ~ `"`; 
    3636} 
     37 
  • trunk/blade/CodegenX86.d

    r112 r117  
    4949*/ 
    5050 
    51 module CodegenX86; 
    52 private import BladeUtil; 
    53 private import BladeRank; 
     51module blade.CodegenX86; 
     52private import blade.BladeUtil; 
     53private import blade.BladeRank; 
    5454 
    5555private: 
     
    123123 
    124124 
     125// num chars before we get a comma. 
     126int 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 
    125134/// Converts an infix string into postfix. 
    126135/// Apply SSE/SSE2-specific optimisations during the conversion. 
     
    141150    if (first[0]=='(') { 
    142151        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); 
    144160    if (second[0]=='(') { 
    145161        second = makePostfixForSSE(second[1..second.length-1], ranklist); 
     
    334350char [] indexedSSEVector(int [] ranklist, char var) 
    335351{ 
    336     return "[" ~ vectorRegister[vectorNum(ranklist, var)] ~ " + 8* EAX]"; 
     352    return "[" ~ vectorRegister[vectorNum(ranklist, var)] ~ " + 8*EAX]"; 
    337353} 
    338354 
     
    562578            result~= "  auto vec" ~ itoa(i) ~ " = values[" ~itoa(i) ~"].ptr; // " ~ cast(char)('A'+i)~ \n; 
    563579            ++vecnum; 
    564         } else result~= " auto val" ~ itoa(i) ~ " = values["~itoa(i)~"]; // " ~ cast(char)('A'+i)~ \n; 
     580        } 
    565581    } 
    566582    result ~= "  int veclength = values[" ~itoa(findFirstVector(ranklist)) ~"].length;\n"; 
     
    584600        ++numvecs; 
    585601      } else if (ranklist[i]==0) { 
    586 //          result ~= "  movsd " ~ XMM(numconsts) ~ ", double ptr values["~ 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) ~"; " 
    588604            "  shufpd " ~ XMM(numconsts) ~", " ~ XMM(numconsts) ~ ",0; //" ~ cast(char)('A'+i) ~ \n; 
    589605          ++numconsts; 
     
    623639             // If it's a float or double, we can combine the load+arithmetic op 
    624640             // 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; 
    626642            else mainbody ~= "  " ~ opToSSE2[operations[done+1]] ~ " " ~ XMM(numOnStack-1) ~ ", " 
    627643              ~ indexedSSEVector(ranklist, operations[done] ) ~ "; // " ~ operations[done..done+2] ~ \n; 
  • trunk/blade/SyntaxTree.d

    r116 r117  
    99* 
    1010* THEORY: 
    11 * Nested mixins are used. The outermost one tricks the compiler into 
     11* Nested mixins are used. One mixin tricks the compiler into 
    1212* converting the expression into a standard form with precedence and 
    1313* associativity information. The inner mixin determines the type and value 
     
    1616* us to probe the compiler's symbol table. Because it can be applied to any 
    1717* 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 behaviour 
    19 * of stringof. 
    2018* 
    2119* BUGS: 
     
    3028*       mixin, assert, and import expressions 
    3129*       D 2.004 string literals. 
     30* NOTES: 
     31*  Functions (including properties) are typed as function pointers in the symbol table. 
    3232* QUIRKS:        
    33 *  Functions are typed as function pointers in the symbol table, unless they are 
    34 *  used as properties, in which case they appear as function types. 
    3533*  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. 
     35The syntaxtreeof() function and the Symbol and AST classes must be visible to the user code. 
    3836*/ 
    39 module SyntaxTree; 
    40 import BladeUtil : wrapInQuotes; 
     37module blade.SyntaxTree; 
     38import blade.BladeUtil : wrapInQuotes; 
    4139 
    4240public: 
     
    4543 * Returns a string, which, when mixed in, lexes, parses, and semantically  
    4644 * 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. 
    4847 * 
    4948 * Syntax trees are represented as placeholder expressions, with associativity 
     
    5150 * the symbol table. 
    5251 * 
    53   
    5452 * Typically, this function will be a code generator for a mixin. 
    5553 */ 
    5654char [] syntaxtreeof(char [] expression) 
    5755{ 
    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 */ 
     70struct 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
    6474 
    6575/** The values of the A, B, C, ... placeholders 
     
    6878* type    the name of the type, as text 
    6979* 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 characters 
    71 *           0123456789"'- 
     80*         Note that if it is a numeric or text literal, value[0] will be one of  
     81*         the characters 0123456789"'- 
    7282*/ 
    7383struct 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) 
    8488} 
    8589 
     
    112116} 
    113117 
    114 // return -1 if not found  
    115 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  
    123118/**  
    124119 * Extract all terminal symbols(identifiers, type names, and literals) 
     
    128123 * Returns: an array of symbols (with no duplicates, though aliasing may exist) 
    129124 * 
    130  * Supports all D syntax, except D2.004 string literals. 
     125 * Supports *all* D syntax, except D2.004 string literals. 
    131126 */ 
    132127char [][] replaceSymbolsWithPlaceholders(inout char [] expr) 
     
    140135        char c = expr[i]; 
    141136        // 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; 
    145140            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; 
    149144            continue; 
    150145        } 
     146        // Identifiers and numeric literals 
    151147        if ((c >='a' && c <= 'z') || (c>='A' && c<='Z')|| (c>='0' && c<='9')||(c=='_')||(c=='$')||(c>0x7F)){ 
    152148           symbol ~= c; 
    153149        } else { 
    154150            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 literal 
     151                symbol ~= c; // + and - are part of the symbol, if it is a floating-point literal 
    156152                continue; 
    157153            } 
     
    166162            } 
    167163            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) { 
    175169                   symbols ~= symbol; 
    176170                } 
     
    184178                code ~= c; 
    185179           } else { 
    186                 // Remove comments. 
     180                // Ignore comments. 
    187181                if (expr[i..i+2]=="//") { 
    188182                    for ( ; i<expr.length && expr[i]!='\n' ; ++i) {} 
     
    208202} 
    209203 
    210 unittest { 
    211     char [] expr = "xyzzy+ y/+ comment/++ /++//++/+/ +/*2"; 
    212     char [][] symbols = replaceSymbolsWithPlaceholders(expr); 
    213     assert(expr == "A+ B*C"); 
    214 } 
    215204 
    216205//  ==== SYNTAX PASS ==== 
     
    294283} 
    295284 
    296  
    297285/** 
    298286 * Insert parentheses around each symbol, to enforce normal D precedence rules. 
     
    321309} 
    322310 
     311//  ==== SEMANTIC PASS ==== 
     312 
     313// Returns typeof(sym).stringof, with workarounds for compiler bugs 
     314char [] 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 
     322char [] 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 
    323335unittest { 
    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"; 
    354337    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  
    1010*/ 
    1111 
    12 module SyntaxTreeDemo; 
    13 import SyntaxTree
     12module blade.SyntaxTreeDemo; 
     13import blade.SyntaxTree : syntaxtreeof, AbstractSyntaxTree, Symbol, AST
    1414 
    1515// Display the syntax tree 
     
    4949char [] displayParseResult(AbstractSyntaxTree tree) 
    5050{ 
    51     char [] sym=""; 
     51    char [] sym="   Rank\tType\tValue\n"; 
    5252    for (int i=0; i<tree.symbolTable.length; ++i) { 
    5353    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; 
    5555        char c = q.value[0]; 
    5656        bool isConst = ((c>='0' && c<='9')||c=='-'|| c=='"' || c=='\''); 
     
    8484 
    8585const QUAL = Blah!(7)("abc", 4); 
     86import std.math; 
     87 
    8688void main() 
    8789{ 
     
    9799    mixin(vec("func(d*35,d+  4)")); 
    98100    mixin(vec("QUAL")); 
     101    mixin(vec("sin(3.45)")); 
    99102}