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
Beispiel #2
0
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
Beispiel #3
0
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