Changeset 109

Show
Ignore:
Timestamp:
09/11/07 14:37:45 (1 year ago)
Author:
Don Clugston
Message:

Syntax tree refactored, now works with functions.
Front-end joined to back end again.

Files:

Legend:

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

    r108 r109  
    4949*/ 
    5050 
    51 module Infix; 
     51module Blade; 
     52import SyntaxTree; 
    5253 
    5354// General utilities. 
     
    911912} 
    912913 
    913 template SSEVEC(char [] rawexpr) { 
    914  VecRetType!(rawexpr) SSEVEC(Values...)(Values values) { 
     914template SSEVECGEN(char [] rawexpr) { 
     915 VecRetType!(rawexpr) SSEVECGEN(Values...)(Values values) { 
    915916     foreach (K; values) { 
    916917        writefln("Param: ", K); 
     
    934935} 
    935936 
     937char [] makeSSE(AbstractSyntaxTree tree) 
     938{ 
     939    char [] result = "SSEVECGEN!(" ~ wrapInQuotes(tree.expression) ~ ")("; 
     940    for (int i=0; i<tree.symbolTable.length;++i) { 
     941        if (i>0) result ~=","; 
     942        result ~= tree.symbolTable[i].value; 
     943    } 
     944    return result~ ");"; 
     945} 
     946 
     947char [] SSEVEC(char [] expr) 
     948{ 
     949    return "mixin(makeSSE(" ~ syntaxtreeof(expr) ~ "));"; 
     950}         
     951 
    936952import std.stdio; 
    937953 
     
    943959    double[4] d0 = [17.0f, 28.25, 1, 56.2]; 
    944960 
     961 
     962     
    945963void main() 
    946964{ 
     
    958976        r[i]= q[i]*2213.3L; 
    959977    } 
    960     SSEVEC!("A=(B*C)")(a, d, 2.0); 
     978     
     979    mixin(SSEVEC(" a   += d*2.01")); 
     980     
    961981    writefln("a=", a); 
     982   // writefln(qqq); 
     983//    writefln(qq); 
    962984/*     
    963985//    VEC!("C+=(B*A)")( a, 2213.3, q); 
  • trunk/blade/SyntaxTree.d

    r107 r109  
    11// Written in the D programming language 1.0 
    2 /** Create an abstract syntax tree from a piece of D source code, at compile time. 
     2/**  
     3* Given an expression as a compile-time constant, create an abstract syntax tree 
     4* with semantic information, at compile time. 
    35* Part of BLADE : Basic Linear Algebra D Expressions 
     6* 
    47* Author: Don Clugston 
    58* License: Public Domain 
     9* 
     10* THEORY: 
     11*  Nested mixins are used. The outermost one tricks the compiler into 
     12* converting the expression into a standard form with precedence and 
     13* associativity information. The inner mixin determines the type and value 
     14* of each symbol in the expression, by mixing in '.stringof' expressions. 
     15* The two levels of mixins are required because of some quirks in the behaviour 
     16* of stringof. 
     17* 
     18* BUGS: 
     19*  The following syntax is not supported: 
     20*       unary operators & ! 
     21*       && and || operators 
     22*       Comparision operators and NCEG floating point operators 
     23*       ?: 
     24*       $ not really supported: a[$-1] should be replaced by a[a.length-1] 
     25*       cast 
     26*       new, delete, anonymous classes 
     27*       mixin, assert, and import expressions 
     28*       D 2.004 string literals. 
     29* QUIRKS:        
     30*  Functions are typed as function pointers in the symbol table, unless they are 
     31*  used as properties, in which case they appear as function types. 
     32*  If the expression refers to a non-existent variable, a sensible error message 
     33*  will be printed, but it will be followed by a torrent of useless error messages. 
     34*    
    635*/ 
    736module SyntaxTree; 
    837 
     38public: 
     39 
     40/** 
     41 * Returns a string, which, when mixed in, lexes, parses, and semantically  
     42 * analyses the given expression, then creates a struct literal of type 
     43 * AbstractSyntaxTree, containing a symbol table, and a syntax tree in a 
     44 * very simple placeholder format, which refers to the elements in the symbol table. 
     45 * 
     46 * Syntax trees are represented as placeholder expressions, with associativity 
     47 * and precedence indicated by parentheses. 
     48 * 
     49  
     50 * Typically, this function will be a code generator for a mixin. 
     51 */ 
     52char [] syntaxtreeof(char [] expression) 
     53{ 
     54    char [] expr=expression; 
     55    char [][] symbols = replaceSymbolsWithPlaceholders(expr); 
     56//    if (symbols.length> 25) return `static assert(0, "Too many symbols in expression.");`; 
     57    return `mixin(mixin_SymbolTable(` ~ wrapInQuotes(expression)~ `,` ~ mixin_getPrecedence(expr) ~ `))`; 
     58} 
     59 
     60 
     61/** The values of the A, B, C, ... placeholders 
     62* 
     63* Members: 
     64* type    the name of the type, as text 
     65* value   The value, as text. This will be either a symbol name, or a literal. 
     66*         Note that if it is a numeric or text literal, value[0] will be one of the characters 
     67*            0123456789"'- 
     68*/ 
     69struct Symbol { 
     70    char [] type; // the name of the type, as text 
     71    char [] value; // the value, as text. 
     72} 
     73 
     74/** The result of semantic analysis of the original expression 
     75 * 
     76 */ 
     77struct AbstractSyntaxTree { 
     78    char [] expression; /// syntax tree in Placeholder format, eg A+=(B*C) 
     79    Symbol[] symbolTable; /// The types and values of A,B,C,... 
     80} 
     81 
     82private: 
    983 
    1084//  ==== LEXER ==== 
    11  
    12 private: 
    1385 
    1486/// Return true if text is a D keyword 
     
    52124} 
    53125 
    54  
    55 public: 
    56 /** Extract all terminal symbols(identifiers, type names, and literals) from expression expr. 
     126/**  
     127 * Extract all terminal symbols(identifiers, type names, and literals) 
     128 * from expression expr. 
    57129 * Replace each identifier with a placeholder A, B, C, D, ... 
    58130 * 
     
    117189} 
    118190 
    119  
    120191//  ==== SYNTAX PASS ==== 
    121  
    122 // The values of the A, B, C, ... placeholders 
    123 struct Symbol { 
    124     char [] type; // the name of the type, as text 
    125     char [] value; // the value, as text 
    126     bool isConst; // is it a compile-time constant? 
    127 } 
    128  
    129 /** FOR MIXIN 
    130  * Given an array of symbols, return a string to be mixed in, which will 
    131  * generate the type and value associated with each symbol. 
    132  * When mixed in, a Symbol[] array literal will be generated. 
    133  */ 
    134 char[] mixin_SymbolTable(char [][] symbols) 
    135 { 
    136     // Creates an array[2] of string literals, where [0] is the type, and [1] is the value 
    137     // This is passed to the toSymTable function which determines which entries are constants. 
    138     char [] result = "toSymTable(["; 
    139     for(int i=0; i<symbols.length; ++i) { 
    140         if (i>0) result ~=","; 
    141         if (symbols[i][0]>='0' && symbols[i][0]<='9') { 
    142             result ~= "[typeof(" ~ symbols[i] ~ `).stringof, (` ~symbols[i] ~ `).stringof]`; 
    143         } else 
    144         result ~= "[typeof(" ~ symbols[i] ~ `).stringof, ` ~symbols[i] ~ `.stringof]`; 
    145     } 
    146     result ~="])"; 
    147     return result; 
    148 } 
    149  
    150 /// Converts the input [type][value] array into a Symbol[] array. 
    151 Symbol [] toSymTable(char [][2][] symboltable) 
    152 { 
    153     Symbol [] symbolTable=[]; 
    154     for (int i=0; i<symboltable.length; ++i) { 
    155         char c = symboltable[i][1][0]; 
    156         bool isConst = ((c>='0' && c<='9')||c=='-'|| c=='"' || c=='\''); 
    157         symbolTable ~= Symbol(symboltable[i][0], symboltable[i][1], isConst); 
    158     } 
    159     return symbolTable; 
    160 } 
    161  
    162192 
    163193/** Generate a syntax tree 
     
    175205   ?: 
    176206   $ not really supported: a[$-1] should be replaced by a[a.length-1] 
    177    NCEG floating point operators 
     207   Comparison and NCEG floating point operators 
    178208   cast 
    179209   new, delete, anonymous classes 
     
    257287char [] mixin_getPrecedence(char [] expr) 
    258288{ 
    259     if (expr.length<2) return `"` ~ expr ~ `"`
     289    if (expr.length<2) return "`" ~ expr ~ "`"
    260290    char [] code = "typeof("; 
    261291        for(int i=0; i<expr.length; ++i) { 
     
    275305} 
    276306 
     307//  ==== SEMANTIC PASS ==== 
     308 
     309bool isFunc(int n, char [] expr) 
     310{ 
     311    char c = n + 'A'; 
     312    for (int i=0; i<expr.length-1; ++i) { 
     313        if ((expr[i]==c) && expr[i+1]=='(') return true; 
     314    } 
     315    return false; 
     316} 
     317 
     318public: 
     319/** FOR MIXIN 
     320 * Given a raw expression, and a processed expression (with placeholders, and  
     321 * correct precedence), return a string to be mixed in, which will 
     322 * generate the type and value associated with each symbol. 
     323 * When mixed in, an AbstractSyntaxTree containing a Symbol[] array literal will be generated. 
     324 */ 
     325char [] mixin_SymbolTable(char [] expression, char [] exprWithPlaceholders) 
     326{ 
     327    char [] expr = expression; 
     328    char [][] symbols = replaceSymbolsWithPlaceholders(expr); 
     329    // Creates an array[2] of string literals, where [0] is the type, and [1] is the value 
     330    // This is passed to the toSymTable function which determines which entries are constants. 
     331    char [] result = `AbstractSyntaxTree("` ~ exprWithPlaceholders ~ `",[`; 
     332    for(int i=0; i<symbols.length; ++i) { 
     333        if (i>0) result ~=","; 
     334        if (isFunc(i, exprWithPlaceholders))  
     335            result ~= `Symbol(typeof(&` ~ symbols[i] ~ `).stringof,"` ~ symbols[i]~ `")`; 
     336        else if (symbols[i][0]>='0' && symbols[i][0]<='9') { 
     337            result ~= `Symbol(typeof(` ~ symbols[i] ~ `).stringof, (` ~symbols[i] ~ `).stringof)`; 
     338        } else 
     339        result ~= `Symbol(typeof(` ~ symbols[i] ~ `).stringof, ` ~symbols[i] ~ `.stringof)`; 
     340    }     
     341    result ~="])"; 
     342    return result; 
     343} 
     344 
     345public: 
     346char [] wrapInQuotes(char [] instr) 
     347{ 
     348    char [] str=`"`; 
     349    foreach(char c; instr) { 
     350        if (c=='"') str~=`\"`; 
     351        else str~=c;         
     352    } 
     353    return str~ `"`; 
     354}