#include "Skylark.h" #define LLOG(x) // DLOG(x) namespace Upp { void Compiler::Iterate(Vector< One >& a, Callback1< One& > op) { for(int i = 0; i < a.GetCount(); i++) op(a[i]); } void Compiler::OptimizeConst(One& exe) { One oxe; Vector stack; ExeContext x(stack); oxe.Create().value = exe->Eval(x); LLOG("OPTIMIZED constant: " << exe->Eval(stack, out)); exe = pick(oxe); optimized = true; } void Compiler::Iterate(One& exe, Callback1< One& > op) { if(ExeBlock *e = dynamic_cast(~exe)) { Iterate(e->item, op); return; } if(ExeFor *e = dynamic_cast(~exe)) { op(e->value); op(e->body); op(e->onempty); return; } if(ExeLink *e = dynamic_cast(~exe)) { Iterate(e->arg, op); return; } if(ExeFn *e = dynamic_cast(~exe)) { Iterate(e->arg, op); return; } if(ExeField *e = dynamic_cast(~exe)) { op(e->value); return; } if(ExeCond *e = dynamic_cast(~exe)) { op(e->cond); op(e->ontrue); op(e->onfalse); return; } if(ExeMap *e = dynamic_cast(~exe)) { Iterate(e->key, op); Iterate(e->value, op); return; } if(ExeArray *e = dynamic_cast(~exe)) { Iterate(e->item, op); return; } if(Exe2 *e = dynamic_cast(~exe)) { op(e->a); op(e->b); return; } if(Exe1 *e = dynamic_cast(~exe)) { op(e->a); return; } } void Compiler::CountNodes(One& exe) { count_node++; Iterate(exe, THISBACK(CountNodes)); } int Compiler::GetNodeCount(One& exe) { count_node = 0; CountNodes(exe); return count_node; } void Compiler::Optimize(One& exe) { if(!exe) return; bool optimized2 = false; #ifdef _DEBUG0 String name = "Optimizing " + String(typeid(*~exe).name()); LLOGBLOCK(name); #endif do { optimized = false; Iterate(exe, THISBACK(Optimize)); if(ExeField *e = dynamic_cast(~exe)) { if(ExeVar *e1 = dynamic_cast(~e->value)) { One oxe; ExeVarField& vf = oxe.Create(); vf.id = e->id; vf.var_index = e1->var_index; exe = pick(oxe); optimized = true; LLOG("OPTIMIZED ExeVarField"); } } if(ExeLink *e = dynamic_cast(~exe)) { ExeVarField *e1; if(e->arg.GetCount() == 1 && (e1 = dynamic_cast(~e->arg[0]))) { One oxe; ExeLinkVarField1& o = oxe.Create(); o.id = e1->id; o.var_index = e1->var_index; o.part = e->part; exe = pick(oxe); optimized = true; LLOG("OPTIMIZED ExeLinkVarField1"); } } if(ExeBlock *e = dynamic_cast(~exe)) { Vector< One >& m = e->item; int i = 0; while(i < m.GetCount() - 1) { ExeConst *e1 = dynamic_cast(~m[i]); ExeConst *e2 = dynamic_cast(~m[i + 1]); if(e1 && e2 && e1->value.Is() && e2->value.Is()) { RawHtmlText t; t.text = ValueTo(e1->value).text + ValueTo(e2->value).text; One oxe; oxe.Create().value = RawToValue(t); m[i] = pick(oxe); m.Remove(i + 1); optimized = true; LLOG("OPTIMIZED ExeBlock constant folding"); } else i++; } } if(Exe2 *e = dynamic_cast(~exe)) { if(dynamic_cast(~e->a) && dynamic_cast(~e->b)) OptimizeConst(exe); } else if(Exe1 *e = dynamic_cast(~exe)) { if(dynamic_cast(~e->a)) OptimizeConst(exe); } optimized2 = optimized2 || optimized; LLOG("---------"); } while(optimized); optimized = optimized2; } };