module sum_example ;
import std.stdio ;
import std.conv ;
import ast_parser ;
string indent (int n)
{
string indent_str = " " ;
string result = "" ;
foreach (i ; 0 .. n)
result ~= indent_str ;
return result ;
}
string sumImpl (string astStr)
{
string AST_ERROR_STR = "Sum AST error : incorrect sum syntax" ;
string loop_var [] ;
string loop_start [] ;
string loop_end [] ;
string loop_inc [] ;
string loop_cond [] ;
string loop_body ;
auto ast = TokenList.parseD (astStr) ;
assert (ast.length >= 3, AST_ERROR_STR) ;
assert (ast.getStringItem (0) == ";", "Sum AST error : sum must be separeted by semicolons") ;
foreach (i ; 1 .. ast.length - 1)
{
auto arg = ast.getItem (i) ;
TokenList ast_cycle ;
if (arg.getStringItem (0) == ",")
{
ast_cycle = arg.getItem (1) ;
loop_cond ~= arg.getItem (2).toD_String () ;
}
else
{
loop_cond ~= null ;
ast_cycle = arg ;
}
assert (ast_cycle.getStringItem (0) == "=", AST_ERROR_STR) ;
loop_var ~= ast_cycle.getStringItem (1) ;
// (: 1 1 10)
// (: 1 10)
ast_cycle = ast_cycle.getItem (2) ;
assert (ast_cycle.getStringItem (0) == ":", AST_ERROR_STR) ;
loop_start ~= ast_cycle.getItem (1).toD_String () ;
if (ast_cycle.length == 4)
{
loop_inc ~= ast_cycle.getItem (2).toD_String () ;
loop_end ~= ast_cycle.getItem (3).toD_String () ;
}
else
if (ast_cycle.length == 3)
{
loop_inc ~= null ;
loop_end ~= ast_cycle.getItem (2).toD_String () ;
}
else
assert (0, AST_ERROR_STR) ;
}
loop_body = ast.getItem (ast.length - 1).toD_String () ;
auto sum_i = new string [ast.length - 2] ;
string result = "function int () {\n" ;
int idt = 1 ;
foreach (i ; 0 .. ast.length - 2)
{
sum_i [i] = "sum_" ~ to!string (i) ;
result ~=
indent (idt) ~ "int " ~ sum_i [i] ~ " ;\n" ~
indent (idt) ~ "for (int " ~ loop_var [i] ~ " = " ~ loop_start [i] ~ " ; " ~ loop_var [i] ~ " < " ~ loop_end [i] ~ " ; " ;
if (loop_inc [i] is null)
result ~= "++" ~ loop_var [i] ;
else
result ~= loop_var [i] ~ " += " ~ loop_inc [i] ;
result ~= " )\n" ~
indent (idt) ~ "{\n" ;
if (loop_cond [i] !is null)
{
++ idt ;
result ~= indent (idt) ~ loop_cond [i] ~ "\n"
~ indent (idt) ~ "{\n";
}
if (i == ast.length - 3)
{
result ~= indent (idt + 1) ~ sum_i [i] ~ " += " ~ loop_body ~ " ;\n" ;
if (loop_cond [i] !is null)
{
result ~= indent (idt) ~ "}\n" ;
-- idt ;
}
result ~= indent (idt) ~ "}\n" ;
}
else
++ idt ;
}
foreach_reverse (i ; 0 .. ast.length - 3)
{
string res = indent (idt) ~ sum_i [i] ~ " += " ~ sum_i [i+1] ~ " ;\n" ;
if (loop_cond [i] !is null)
{
result ~= res ;
-- idt ;
result ~= indent (idt) ~ "}\n" ;
}
else
result ~= res ;
-- idt ;
result ~= indent (idt) ~ "}\n" ;
}
result ~= indent (1) ~ "return sum_0 ;\n"
~ "} ()" ;
return result ;
}
string sumImpl2 (string loop_var, string loop_start, string loop_end, string loop_body)
{
return
"function int () {\n" ~
"int sum_ ;\n" ~
"foreach ( " ~ loop_var ~ " ; " ~ loop_start ~ " .. " ~ loop_end ~ " )\n" ~
"{\n" ~
" sum_ += " ~ loop_body ~ " ;\n" ~
"}\n" ~
"return sum_ ;\n" ~
"} ()" ;
}
template sum (string loop_var, string loop_start, string loop_end, string loop_body)
{
mixin ("enum sum = " ~ sumImpl2 (loop_var, loop_start, loop_end, loop_body) ~ " ;") ;
}
template sum2 (string s)
{
mixin ("enum sum2 = " ~ s ~ ";") ;
}
void main ()
{
int x = sum2 !(q{1 + sum2!("2")}) ;
writeln (x) ;
x = 1 + sum! ("i", "1", "10", q{i * sum!("j", "0", "9", "1+j")}) ;
writeln (x) ;
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")) ;
}