#include "__for.h" #include "Exception.h" #include namespace jet { __for::__for(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, this) { double counter = 0.0f; bool nameDefined = keywordDefined("name"); if(keywordDefined("start")) { counter = resolveKeyword("start").asDouble(); keywords["start"].reset(); } if(!keywordDefined("end")) throw coreutils::Exception("for tag requires end keyword."); if(!keywordDefined("step")) throw coreutils::Exception("for tag requires step keyword."); // Where to write the loop counter (which variables map, and under // what name) is a static property of this 's own invocation - // "scope"/"name" have no sensible reason to change mid-loop, so // resolve and branch on them once instead of re-resolving both // (and re-checking scope with up to 3 comparisons) on every single // iteration. Loop bounds (end/step) are deliberately left // re-resolved per iteration exactly as before - real content could // plausibly rely on a bound that changes as a side effect of the // loop body itself, and there's no clear evidence either way, so // that part stays conservative/unchanged. coreutils::MString counterVarName; enum { SCOPE_GLOBAL, SCOPE_LOCAL, SCOPE_PARENT } counterScope = SCOPE_GLOBAL; if(nameDefined) { counterVarName = resolveKeyword("name"); if(keywordDefined("scope")) { coreutils::MString scopeVal = resolveKeyword("scope"); if(scopeVal == "global") counterScope = SCOPE_GLOBAL; else if(scopeVal == "local") counterScope = SCOPE_LOCAL; else if(scopeVal == "parent") counterScope = SCOPE_PARENT; else throw coreutils::Exception("scope value is not valid."); } } for(double ix = counter; ix <= resolveKeyword("end").asDouble(); ix += resolveKeyword("step").asDouble()) { resolveKeyword("end").reset(); resolveKeyword("step").reset(); if(nameDefined) { if(counterScope == SCOPE_GLOBAL) global.variables[counterVarName] = ix; else if(counterScope == SCOPE_LOCAL) this->local->variables[counterVarName] = ix; else parent->local->variables[counterVarName] = ix; } processContainer(container); container.reset(); } } }