Changeset 123

Show
Ignore:
Timestamp:
10/30/07 14:00:23 (10 months ago)
Author:
Don Clugston
Message:

* Use of an undeclared variable in an expression no longer spews a torrent of template/mixin error messages.
* Now asserts vector length equality before calling either x87 or SSE code.

Files:

Legend:

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

    r122 r123  
    5353 
    5454public import blade.SyntaxTree : AbstractSyntaxTree, syntaxtreeof, AST, Symbol; 
    55 private import blade.BladeUtil : wrapInQuotes
     55private import blade.BladeUtil : wrapInQuotes, startsWith
    5656private import blade.BladeRank; 
    5757public import blade.CodegenX86 : generateCodeForAsmX87, generateCodeForSSE2, MAX_X87_VECTORS, MAX_SSE_VECTORS; 
     
    8686 
    8787// ------------------------------------ 
    88 // return true if the first characters of x are y. 
    89 bool startsWith(char [] x, char [] y) 
    90 { 
    91     return (x.length>=y.length && x[0..y.length]==y); 
    92 } 
    9388 
    9489// ------------------------------------ 
     
    142137} 
    143138 
    144  
    145139//------------------------------------------------------- 
    146140//                Invoker functions 
    147141//------------------------------------------------------- 
    148 // These are CTFE functions which, when mixed in, will call 
    149 // the BLAS function. They ensure that all types are converted into standard 
     142// These are CTFE functions which, when mixed in, will call the BLAS template 
     143// function. They ensure that all types are converted into standard 
    150144// simple forms, ensure that the vector lengths are equal, and pass in all 
    151145// of the parameters. 
     
    154148char [] invokeX87(AbstractSyntaxTree tree) 
    155149{ 
    156     char [] result = "X87VECGEN!(" ~ wrapInQuotes(tree.expression); 
     150    char [] result = assertAllVectorLengthsEqual(tree); 
     151    result ~= "X87VECGEN!(" ~ wrapInQuotes(tree.expression); 
    157152    for (int i=0; i<tree.symbolTable.length;++i) { 
    158153        char [] t = tree.symbolTable[i].type; 
     
    162157            // We convert everything else to double, since that uses less 
    163158            // FPU stack space.            
    164             if (t == "real" || t=="double" || t=="float") result ~= "," ~ t; 
    165             else if (t=="long" || t=="ulong") result~=",real"; 
     159            if (t == "real" || t == "double" || t == "float") result ~= "," ~ t; 
     160            else if (t == "long" || t == "ulong") result ~= ",real"; 
    166161            else result ~= "double"; // Convert all other scalars into doubles. 
    167162         } 
     
    183178/// Generate code which will call the SSE2 function 
    184179char [] invokeSSE2(AbstractSyntaxTree tree) 
     180{ 
     181    char [] result = assertAllVectorLengthsEqual(tree); 
     182     
     183    result ~= "SSEVECGEN!(" ~ wrapInQuotes(tree.expression);         
     184    // For SSE2, everything must be implicitly convertible to double. 
     185    for (int i=0; i<tree.symbolTable.length;++i) { 
     186        if (tree.symbolTable[i].rank==0) result ~= ",double"; 
     187        else result ~= ",double[]"; 
     188    } 
     189    result ~= ")("; 
     190    int knt=0; 
     191    for (int i=0; i<tree.symbolTable.length;++i) { 
     192        if (knt>0) result ~=","; 
     193        result ~= tree.symbolTable[i].value; 
     194        ++knt; 
     195    } 
     196    return result ~ ");"; 
     197} 
     198 
     199 
     200char [] assertAllVectorLengthsEqual(AbstractSyntaxTree tree) 
    185201{ 
    186202    char [] result =""; 
     
    197213        } 
    198214    } 
    199      
    200     result ~= "SSEVECGEN!(" ~ wrapInQuotes(tree.expression);         
    201     // For SSE2, everything must be implicitly convertible to double. 
    202     for (int i=0; i<tree.symbolTable.length;++i) { 
    203         if (tree.symbolTable[i].rank==0) result ~= ",double"; 
    204         else result ~= ",double[]"; 
    205     } 
    206     result ~= ")("; 
    207     int knt=0; 
    208     for (int i=0; i<tree.symbolTable.length;++i) { 
    209         if (knt>0) result ~=","; 
    210         result ~= tree.symbolTable[i].value; 
    211         ++knt; 
    212     } 
    213     return result ~ ");"; 
    214 
     215    return result; 
     216
     217 
     218/* 
     219// Return a vector which contains the length of the expression. 
     220int findVectorForLength(AbstractSyntaxTree tree) 
     221
     222
     223*/ 
    215224 
    216225// Categorise the expression, and dispatch to the appropriate code generator. 
  • trunk/blade/BladeDemo.d

    r122 r123  
    2222    d[0..$] = [17.0, 28.25, 1, 56.2];; 
    2323    auto w2=z.ptr; 
    24     float[] q = [17.0f, 28.25, 1]; 
    25     float [3] r; 
    26     idouble [] p = [2.3i, 254i, 0.1i]; 
     24    float[] q = [17.0f, 28.25, 1, 0]; 
     25    float [4] r; 
     26    idouble [] p = [2.3i, 254i, 0.1i, 1.2i]; 
    2727    for(int i=0; i<r.length;++i) { 
    2828//        r[i]= q[i]+ a[i]*2213.3; 
    2929        r[i]= q[i]*2213.3L; 
    3030    } 
    31      
     31 
    3232    mixin(vectorize(" a   += d*2.01")); 
     33    mixin(vectorize(" a   += r*2.01")); 
    3334     
    3435    writefln("a=", a); 
  • trunk/blade/BladeUtil.d

    r120 r123  
    11//  Written in the D programming language 1.0 
    22/** 
    3 * Utility functions 
     3* General CTFE string utility functions 
    44* BLADE 0.3Alpha -- Basic Linear Algebra D Expressions 
    55*/ 
     
    99public: 
    1010 
    11 // General utilities
     11// Convert from integral type to string
    1212char [] itoa(T)(T x) 
    1313{ 
     
    2525} 
    2626 
     27 
    2728unittest { 
    2829    assert(blade.BladeUtil.itoa(-5)=="-5"); 
    2930} 
    3031 
     32/** 
     33 * return true if the first characters of x are y. 
     34 */ 
     35bool startsWith(char [] x, char [] y) 
     36{ 
     37    return (x.length>=y.length && x[0..y.length]==y); 
     38} 
     39 
     40 
     41/** Add quotes to the start and end of the string, 
     42 * escaping any quotes and backslashes inside it. 
     43 */ 
    3144char [] wrapInQuotes(char [] instr) 
    3245{ 
  • trunk/blade/CodegenX86.d

    r121 r123  
    439439     
    440440    if (operations.length>2 && operations[$-1]=='=') { 
    441         storage ~= "  fstp " ~ indexedVectorPrev(typelist, ranklist, operations[$-2] ) ~ ";  // " ~ operations[done..done+2] ~ \n; 
     441        storage ~= "  fstp " ~ indexedVectorPrev(typelist, ranklist, operations[$-2] ) ~ ";  // " ~ operations[$-2..$-1] ~ "=" ~ \n; 
    442442        operations=operations[0..$-2]; 
    443443    } 
     
    479479        } else { 
    480480            // For scalar float or double values, we can multiply directly, saving one slot on the FP stack. 
    481             next = "  fmul " ~ operandSize(typelist[operations[done]-'A']) ~ "val" ~ itoa(operations[done]-'A') ~";\n"; 
     481            next = "  fmul " ~ operandSize(typelist[operations[done]-'A']) ~ "val" ~ itoa(operations[done]-'A') ~"; // * " ~ operations[done..done+1] ~ "\n"; 
    482482            mainbody ~= next; firstbody ~= next; 
    483483        } 
  • trunk/blade/SyntaxTree.d

    r118 r123  
    3030* NOTES: 
    3131*  Functions (including properties) are typed as function pointers in the symbol table. 
    32 * QUIRKS:        
    33 *  If the expression refers to a non-existent variable, a sensible error message 
    34 *   will be printed, but it will be followed by a torrent of useless error messages. 
     32* ERROR HANDLING: 
     33*  If the expression refers to a non-existent variable, the type will be an empty string, 
     34*  and the value will be the name of the variable. 
     35*  Syntax errors in the expression generate normal D errors in the user code, except 
     36*  for mismatched parentheses. 
     37* QUIRKS: 
    3538*  The syntaxtreeof() function and the Symbol and AST classes must be visible to the user code. 
    3639*/ 
     
    5659{ 
    5760    char [][] symbols = replaceSymbolsWithPlaceholders(expression); 
    58     char [] result = `AbstractSyntaxTree(` ~ mixin_getPrecedence(expression) ~ `,[`; 
     61    char [] result = `AbstractSyntaxTree(` ~ mixin_getPrecedence(expression) ~ `,[`;     
    5962    for(int i=0; i<symbols.length; ++i) { 
    6063        if (i>0) result ~=","; 
     
    6366                      ~ `,` ~ mixin_rankOf(symbols[i]) ~ `)`; 
    6467    }     
     68     
    6569    result ~="])"; 
    6670    return "mixin(" ~ wrapInQuotes(result) ~ ")"; 
     
    317321{ 
    318322    // Compiler bug: typeof(x).stringof doesn't compile if x is a function. 
    319     return `mixin(is(typeof(` ~ sym ~ `)==function)?` ~ wrapInQuotes("typeof(&" ~ sym ~ ").stringof")~`:` ~ wrapInQuotes("typeof(" ~ sym ~ ").stringof") ~ `)`; 
     323    // If it doesn't compile at all, return an empty string. 
     324    return `mixin(!is(typeof(` ~ sym ~ `))?"\"\"" : is(typeof(` ~ sym ~ `)==function)?` ~ wrapInQuotes("typeof(&" ~ sym ~ ").stringof")~`:` ~ wrapInQuotes("typeof(" ~ sym ~ ").stringof") ~ `)`; 
    320325} 
    321326 
     
    327332    // (1) 1.23.stringof fails to compile. Fortunately (1.23).stringof works. 
    328333    // (2) x.stringof doesn't compile, if x is a function. Just return x instead. 
     334    //     We also return x if x doesn't compile (eg, is an undefined variable). 
    329335    if (sym[0]>='0' && sym[0]<='9') { // numeric literal 
    330336        return "(" ~ sym ~ ").stringof"; 
    331337    } 
    332     return `mixin(is(typeof(` ~ sym ~ `)==function)?` ~ wrapInQuotes(wrapInQuotes(sym)) ~ `:` ~ wrapInQuotes(sym ~ ".stringof") ~ ")"; 
     338    return `mixin(is(typeof(` ~ sym ~ `)==function) || !is(typeof(` ~ sym ~ `))?` ~ wrapInQuotes(wrapInQuotes(sym)) ~ `:` ~ wrapInQuotes(sym ~ ".stringof") ~ ")"; 
    333339} 
    334340 
  • trunk/blade/SyntaxTreeDemo.d

    r118 r123  
    5151char [] displayParseResult(AbstractSyntaxTree tree) 
    5252{ 
    53     char [] sym="  Rank\tConst?\tType\tValue\n"; 
     53    char [] sym="  Rank\tLiteral\tType\tValue\n"; 
    5454    for (int i=0; i<tree.symbolTable.length; ++i) { 
    5555    Symbol q = tree.symbolTable[i]; 
    5656        sym~=cast(char)('A'+i) ~ ": " ~ cast(char)('0' + q.rank) ~ \t; 
    5757        char c = q.value[0]; 
    58         bool isConst = ((c>='0' && c<='9')||c=='-'|| c=='"' || c=='\''); 
    59         if (isConst) sym~="CONST";         
     58        if (tree.symbolTable[i].type=="") sym ~= "ERROR"; 
     59        else if ((c>='0' && c<='9')||c=='-') sym ~= "Numeric"; 
     60        else if (c=='"' || c=='\'') sym ~= "String"; 
    6061        sym ~=\t ~ q.type ~ \t ~ q.value ~ \n; 
    6162    } 
    62     return `Expression is: ` ~ tree.expression ~ \n ~ prettyTree(tree.expression) ~ \n ~ sym; 
     63    return `Expression is: ` ~ tree.expression ~ \n ~ prettyTree(tree.expression) ~ \n ~ sym;    
    6364} 
    6465 
     
    7778const int butNotThis=6; 
    7879 
    79 int func(int x, int itsInterestingThatYouCanSeeThis = butNotThis ) { return 2; } 
    80  
     80int func(int x, int youCanSeeThis = butNotThis ) { return 2; } 
    8181 
    8282struct Blah(int Y) { 
     
    100100    mixin(vec("b = ags.af[fróg*2..56] in s")); 
    101101    mixin(vec("func(d*35,d+  4)")); 
    102     mixin(vec("QUAL^s")); 
     102    mixin(vec("QUAL^st")); 
    103103    mixin(vec("sin(3.45)")); 
    104104}