ZBoolean ZCsl::Variable::match(const ZString& aName) { ZFUNCTRACE_DEVELOP("ZCsl::Variable::match(const ZString& aName)"); if (pureVarName(aName) != iName) return zFalse; const char* a = (const char*)aName+iName.length(); iIndex = 0; int dim(0); int dimcnt(dims()); while (*a == '[' && dim < MAXDIMS) { a++; long index(0); while ('0'<=*a && *a<='9') { index = 10 * index + *a - '0'; a++; } if (*a++ != ']' || !iDims[dim]) iParent->throwExcept(msgInvalidIndex, aName); if (index >= iDims[dim] && iParent->iState!=isCompiling) iParent->throwExcept(msgInvalidIndex, aName); for (int k = dim+1; k < dimcnt; k++) index *= iDims[k]; iIndex += index; dim++; } // while if (*a) iParent->throwExcept(msgInvalidIndex, aName); iSize = 1; while (dim < dimcnt) iSize *= iDims[dim++]; return zTrue; } // match
ZCsl::Variable::Variable (ZCsl * aParent, const ZString & aVarName, const ZString & aInitValue, ZBoolean aIsConst, ZBoolean aIsRef, ZBoolean aIsKnown, ZBoolean aIsExtern, Variable * aPrev): iIsConst (aIsConst), iIsKnown (aIsKnown && aIsConst), iIsExtern (aIsExtern), iIsGlobal (zFalse), iPrev (aPrev), iRef (0), iParent (aParent) { ZFUNCTRACE_DEVELOP ("ZCsl::Variable::Variable(...)"); iName = pureVarName (aVarName); const char *a = (const char *) aVarName + iName.length (); if (aIsRef) { iRef = iParent->iCalls->iPrev->findVar (aInitValue); // set up dimensions int refDims = iRef->dims () - _dims (aInitValue); int myDims = _dims (a); if (refDims != myDims) iParent->throwExcept (msgDimsMismatch, aVarName); int dim; for (dim = 0; dim < MAXDIMS; dim++) iDims[dim] = 0; for (dim = 0; dim < myDims; dim++) iDims[dim] = iRef->iDims[iRef->dims () - myDims + dim]; // get array offset iRef->match (aInitValue); iVals = &iRef->iVals[iRef->iIndex]; // set const & name iIsConst = iRef->iIsConst || aIsConst; } else { int dim; for (dim = 0; dim < MAXDIMS; dim++) iDims[dim] = 0; dim = 0; while (*a == '[' && dim < MAXDIMS) { a++; while ('0' <= *a && *a <= '9') { iDims[dim] = 10 * iDims[dim] + *a - '0'; a++; } if (*a++ != ']' || !iDims[dim++]) iParent->throwExcept (msgInvalidIndex, aVarName); } // while if (*a) iParent->throwExcept (msgInvalidIndex, aVarName); long sz = size (); iVals = new ZString[sz]; for (int i = 0; i < sz; i++) iVals[i] = aInitValue; } // if } // Variable
void ZCsl::interpret (Function * aFunc) { ZFUNCTRACE_DEVELOP ("ZCsl::interpret(Function* aFunc)"); ZException *excpt = 0; PackedInstruction *loAddr = aFunc->iPcode; PackedInstruction *hiAddr = loAddr + aFunc->iPsize - 1; PackedInstruction *i = loAddr; ZString v2; Variable *v; double d2; long i2; ZBoolean head (zTrue); while (zTrue) { try { if (iTraceMode & traceCode) { if (head) { trace ('#'); trace ('#', funcHeader (aFunc).constBuffer ()); trace ('#'); trace ('#', "address opcode parameter tos tos-1"); trace ('#', "-------- ------ -------------------- -------------------- --------------------"); head = zFalse; } // if trace ('#', dumpInstr (i - aFunc->iPcode, i, zTrue).constBuffer ()); } switch (i->iCode) { case cdOpen: aFunc->openBlock (i->iText); i++; break; case cdClose: aFunc->closeBlock (); i++; break; case cdSize: push (aFunc->findVar (pop ())->iSize); i++; break; case cdRSize: { ZString varName (pop ()); aFunc->findVar (pureVarName (varName))->resize (varName); i++; break; } case cdTrace: if (iTraceMode & traceMsgs) trace ('>', pop ().constBuffer ()); else pop (); i++; break; case cdExist: { ZString ret (One); try { Variable *var = aFunc->findVar (pop (), zFalse); if (!var || var->iIsExtern || var->iIndex < 0 || var->iIndex >= var->size ()) ret = Zero; } // try catch (const ZException & exc) { ret = Zero; } // catch push (ret); i++; break; } case cdNeg: checkNum (*iTos); *iTos = ZString (-iTos->asDouble ()); i++; break; case cdNot: if (isNumber (iTos->constBuffer ())) *iTos = iTos->asDouble ()? Zero : One; else *iTos = *iTos == "" ? One : Zero; i++; break; case cdLoad: *iTos = aFunc->findVar (*iTos)->value (); i++; break; case cdStore: { Variable *var = aFunc->findVar (pop ()); var->set (pop ()); i++; break; } case cdStorC: { Variable *var = aFunc->findVar (pop ()); var->set (pop (), zTrue); i++; break; } case cdPush: push (decodeString (i->iText)); i++; break; case cdPop: pop (); i++; break; case cdDupl: push (*iTos); i++; break; case cdDivI: i2 = pop ().asInt (); if (!i2) throwExcept (msgDivZero); checkNum (*iTos); *iTos = ZString (iTos->asInt () / i2); i++; break; case cdMod: i2 = pop ().asInt (); if (!i2) throwExcept (msgDivZero); checkNum (*iTos); *iTos = ZString (iTos->asInt () % i2); i++; break; case cdMul: v2 = pop (); checkNum (v2); checkNum (*iTos); *iTos = ZString (iTos->asDouble () * v2.asDouble ()); i++; break; case cdDiv: d2 = pop ().asDouble (); if (!d2) throwExcept (msgDivZero); checkNum (*iTos); *iTos = ZString (iTos->asDouble () / d2); i++; break; case cdAdd: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos += v2; else *iTos = ZString (iTos->asDouble () + v2.asDouble ()); i++; break; case cdSub: v2 = pop (); checkNum (v2); checkNum (*iTos); *iTos = ZString (iTos->asDouble () - v2.asDouble ()); i++; break; case cdCat: v2 = pop (); *iTos += v2; i++; break; case cdMulV: v = aFunc->findVar (pop ()); v2 = pop (); checkNum (v2); checkNum (v->value ()); v->set (v->value ().asDouble () * v2.asDouble ()); i++; break; case cdDivV: v = aFunc->findVar (pop ()); d2 = pop ().asDouble (); if (!d2) throwExcept (msgDivZero); checkNum (v->value ()); v->set (v->value ().asDouble () / d2); i++; break; case cdDivIV: v = aFunc->findVar (pop ()); i2 = pop ().asInt (); if (!i2) throwExcept (msgDivZero); checkNum (v->value ()); v->set (v->value ().asInt () / i2); i++; break; case cdModV: v = aFunc->findVar (pop ()); i2 = pop ().asInt (); if (!i2) throwExcept (msgDivZero); checkNum (v->value ()); v->set (v->value ().asInt () % i2); i++; break; case cdAddV: v = aFunc->findVar (pop ()); v2 = pop (); if (!isNumber (v->value ().constBuffer ()) || !isNumber (v2.constBuffer ())) v->set (v->value () + v2); else v->set (v->value ().asDouble () + v2.asDouble ()); i++; break; case cdSubV: v = aFunc->findVar (pop ()); v2 = pop (); checkNum (v2); checkNum (v->value ()); v->set (v->value ().asDouble () - v2.asDouble ()); i++; break; case cdCatV: v = aFunc->findVar (pop ()); v2 = pop (); v->set (v->value () + v2); i++; break; case cdIncV: v = aFunc->findVar (pop ()); checkNum (v->value ()); v->set (v->value ().asDouble () + 1.0); i++; break; case cdDecV: v = aFunc->findVar (pop ()); checkNum (v->value ()); v->set (v->value ().asDouble () - 1.0); i++; break; case cdLss: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = *iTos < v2 ? One : Zero; else *iTos = iTos->asDouble () < v2.asDouble ()? One : Zero; i++; break; case cdLeq: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = *iTos <= v2 ? One : Zero; else *iTos = iTos->asDouble () <= v2.asDouble ()? One : Zero; i++; break; case cdGtr: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = *iTos > v2 ? One : Zero; else *iTos = iTos->asDouble () > v2.asDouble ()? One : Zero; i++; break; case cdGeq: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = *iTos >= v2 ? One : Zero; else *iTos = iTos->asDouble () >= v2.asDouble ()? One : Zero; i++; break; case cdEql: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = *iTos == v2 ? One : Zero; else *iTos = iTos->asDouble () == v2.asDouble ()? One : Zero; i++; break; case cdNeq: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = *iTos != v2 ? One : Zero; else *iTos = iTos->asDouble () != v2.asDouble ()? One : Zero; i++; break; case cdAnd: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = (iTos->size () > 0 && v2.size () > 0) ? One : Zero; else *iTos = (iTos->asDouble () != 0.0 && v2.asDouble () != 0.0) ? One : Zero; i++; break; case cdOr: v2 = pop (); if (!isNumber (v2.constBuffer ()) || !isNumber (iTos->constBuffer ())) *iTos = (iTos->size () > 0 || v2.size () > 0) ? One : Zero; else *iTos = (iTos->asDouble () != 0.0 || v2.asDouble () != 0.0) ? One : Zero; i++; break; case cdJmp: i = loAddr + i->iAddr; break; case cdJF: { v2 = pop (); ZBoolean ok; if (isNumber (v2.constBuffer ())) ok = v2.asDouble () == 0.0; else ok = v2 == ""; i = ok ? loAddr + i->iAddr : i + 1; break; } case cdJT: { v2 = pop (); ZBoolean ok; if (isNumber (v2.constBuffer ())) ok = v2.asDouble () != 0.0; else ok = v2 != ""; i = ok ? loAddr + i->iAddr : i + 1; break; } case cdCall: exec ((Function *) i->iFunc); i++; head = zTrue; break; case cdRet: return; case cdTry: aFunc->iBlocks->iCatch = i->iAddr; aFunc->iBlocks->iTos = iTos; i++; break; case cdThrow: throw ZException (pop ()); case cdThroV: { v = aFunc->findVar (pop ()); int cnt (v->iSize); ZException exc (v->value ()); for (int i = 1; i < cnt; i++) exc.addAsLast (v->iVals[v->iIndex + i]); throw exc; } case cdAllTV: case cdAllTC: { if (!excpt) throw ZException (msgInvCatch); int cnt (excpt->count ()); Variable *var = aFunc->iBlocks->addVar (decodeString (i->iText) + "[" + ZString (cnt ? cnt : 1) + "]", "", i->iCode == cdAllTC); for (int c = 0; c < cnt; c++) var->iVals[c] = (*excpt)[c]; delete excpt; excpt = 0; i++; break; } case cdAllV: v2 = pop (); aFunc->iBlocks->addVar (v2, pop ()); i++; break; case cdAllC: v2 = pop (); aFunc->iBlocks->addVar (v2, pop (), zTrue); i++; break; case cdAllVR: v2 = pop (); aFunc->iBlocks->addVar (v2, pop (), zFalse, zTrue); i++; break; case cdAllCR: v2 = pop (); aFunc->iBlocks->addVar (v2, pop (), zTrue, zTrue); i++; break; case cdNop: i++; break; default: throwExcept (msgIllgInstr); } // switch if (i < loAddr || i > hiAddr) throwExcept (msgNoReturn); } // try catch (const ZException & exc) { while (aFunc->iBlocks->iPrev && aFunc->iBlocks->iCatch < 0) aFunc->closeBlock (); if (aFunc->iBlocks->iPrev) { i = loAddr + aFunc->iBlocks->iCatch; iTos = aFunc->iBlocks->iTos; aFunc->closeBlock (); if (excpt) delete excpt; excpt = new ZException (exc); } else throw; } // catch } // while } // interpret