Pastebin is 300% more awesome when you are logged in. Sign Up, it's FREE!
Guest

Alex D

By: a guest on Nov 25th, 2010  |  syntax: D  |  size: 4.69 KB  |  hits: 74  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. module sum_example ;
  2.  
  3. import std.stdio ;
  4. import std.conv ;
  5. import ast_parser ;      
  6.  
  7. string indent (int n)
  8. {
  9.     string indent_str = "    " ;
  10.     string result = "" ;
  11.     foreach (i ; 0 .. n)
  12.         result ~= indent_str ;
  13.     return result ;
  14. }
  15.  
  16. string sumImpl (string astStr)
  17. {
  18.     string AST_ERROR_STR = "Sum AST error : incorrect sum syntax" ;
  19.     string loop_var   [] ;
  20.     string loop_start [] ;
  21.     string loop_end   [] ;
  22.     string loop_inc   [] ;
  23.     string loop_cond  [] ;
  24.     string loop_body ;
  25.    
  26.     auto ast = TokenList.parseD (astStr) ;
  27.     assert (ast.length >= 3, AST_ERROR_STR) ;    
  28.     assert (ast.getStringItem (0) == ";", "Sum AST error : sum must be separeted by semicolons") ;
  29.    
  30.     foreach (i ; 1 .. ast.length - 1)
  31.     {
  32.         auto arg = ast.getItem (i) ;
  33.         TokenList ast_cycle ;
  34.         if (arg.getStringItem (0) == ",")
  35.         {
  36.             ast_cycle = arg.getItem (1) ;
  37.             loop_cond ~= arg.getItem (2).toD_String () ;
  38.         }
  39.         else
  40.         {
  41.             loop_cond ~= null ;
  42.             ast_cycle = arg ;
  43.         }
  44.         assert (ast_cycle.getStringItem (0) == "=", AST_ERROR_STR) ;
  45.         loop_var ~= ast_cycle.getStringItem (1) ;
  46.        
  47.         // (: 1 1 10)
  48.         // (: 1 10)
  49.         ast_cycle = ast_cycle.getItem (2) ;
  50.         assert (ast_cycle.getStringItem (0) == ":", AST_ERROR_STR) ;
  51.         loop_start ~= ast_cycle.getItem (1).toD_String () ;
  52.         if (ast_cycle.length == 4)
  53.         {
  54.             loop_inc ~= ast_cycle.getItem (2).toD_String () ;
  55.             loop_end ~= ast_cycle.getItem (3).toD_String () ;
  56.         }
  57.         else
  58.         if (ast_cycle.length == 3)
  59.         {
  60.             loop_inc ~= null ;
  61.             loop_end ~= ast_cycle.getItem (2).toD_String () ;
  62.         }                                      
  63.         else
  64.             assert (0, AST_ERROR_STR) ;        
  65.     }          
  66.     loop_body = ast.getItem (ast.length - 1).toD_String () ;
  67.    
  68.     auto sum_i = new string [ast.length - 2] ;
  69.     string result = "function int () {\n" ;
  70.     int idt = 1 ;
  71.     foreach (i ; 0 .. ast.length - 2)
  72.     {
  73.         sum_i [i] = "sum_" ~ to!string (i) ;
  74.         result ~=
  75. indent (idt) ~ "int " ~ sum_i [i] ~ " ;\n" ~
  76. indent (idt) ~ "for (int " ~ loop_var [i] ~ " = " ~ loop_start [i] ~ " ; " ~ loop_var [i] ~ " < " ~ loop_end [i] ~ " ; " ;
  77.  
  78.         if (loop_inc [i] is null)
  79.             result ~= "++" ~ loop_var [i] ;
  80.         else
  81.             result ~= loop_var [i] ~ " += " ~ loop_inc [i] ;
  82.        
  83.         result ~= " )\n" ~
  84.             indent (idt) ~ "{\n" ;
  85.        
  86.         if (loop_cond [i] !is null)
  87.         {
  88.             ++ idt ;
  89.             result ~= indent (idt) ~ loop_cond [i] ~ "\n"
  90.                 ~ indent (idt) ~ "{\n";
  91.         }
  92.        
  93.         if (i == ast.length - 3)
  94.         {
  95.             result ~= indent (idt + 1) ~ sum_i [i] ~ " += " ~ loop_body ~ " ;\n" ;
  96.             if (loop_cond [i] !is null)
  97.             {
  98.                 result ~= indent (idt) ~ "}\n" ;
  99.                 -- idt ;
  100.             }                      
  101.             result ~= indent (idt) ~ "}\n" ;
  102.         }
  103.         else
  104.             ++ idt ;
  105.     }
  106.     foreach_reverse (i ; 0 .. ast.length - 3)
  107.     {
  108.         string res = indent (idt) ~ sum_i [i] ~ " += " ~ sum_i [i+1] ~ " ;\n" ;
  109.         if (loop_cond [i] !is null)
  110.         {
  111.             result ~= res ;
  112.             -- idt ;
  113.             result ~= indent (idt) ~ "}\n" ;
  114.         }
  115.         else
  116.             result ~= res ;
  117.         -- idt ;
  118.         result ~= indent (idt) ~ "}\n" ;
  119.     }
  120.    
  121.     result ~= indent (1) ~ "return sum_0 ;\n"
  122.         ~ "} ()" ;
  123.     return result ;
  124. }
  125.  
  126. string sumImpl2 (string loop_var, string loop_start, string loop_end, string loop_body)
  127. {
  128.     return
  129. "() {\n" ~
  130. "int sum_ ;\n" ~
  131. "foreach ( " ~ loop_var ~ " ; " ~ loop_start ~ " .. "  ~ loop_end ~ " )\n" ~
  132. "{\n" ~
  133. "    sum_ += " ~ loop_body ~ " ;\n" ~
  134. "}\n" ~    
  135. "return sum_ ;\n" ~
  136. "} ()" ;
  137. }
  138.  
  139. template sum (string loop_var, string loop_start, string loop_end, string loop_body)
  140. {
  141.     mixin ("enum sum = " ~ sumImpl2 (loop_var, loop_start, loop_end, loop_body)  ~ " ;") ;
  142. }
  143.  
  144. template sum2 (string s)
  145. {
  146.     mixin ("enum sum2  = " ~ s ~ ";") ;
  147. }
  148.  
  149. void main ()
  150. {
  151.     int x = sum2 !(q{1 + sum2!("2")}) ;
  152.     writeln (x) ;
  153.  
  154.     // (1) error would be if you change "1+j" to "i+j"
  155.     x = 1 + sum! ("i", "1", "10", q{i * sum!("j", "0", "9", "1+j")}) ;
  156.     writeln (x) ;
  157.  
  158.     //here is workaround for (1)
  159.     x = 1 + mixin (sumImpl2 ("i", "1", "10", q{i * mixin( sumImpl2 ("j", "0", "9", "i+j"))}) ) ;
  160.     writeln (x) ;
  161.        
  162.     writeln (sumImpl ("i = 1:10 ; j = 1:2:n+1, if (j != i) ; k = i:j, if (k != 3) ;  i*i/(k+j^3) + 2")) ;
  163. }