// (val addr --) Stores the value in the param field at addr
        public void doStore(ref GlobalSimpleProps gsp)
        {
            int    address    = (int)gsp.Pop(gsp.DataStack);
            object valToStore = gsp.Pop(gsp.DataStack);

            gsp.Cfb.Address[address].DataField.Add(valToStore);
        }
        // ( val1 val2 -- val2 ) Removes second stack argument
        public void doNip(ref GlobalSimpleProps gsp)
        {
            object val1 = gsp.Pop(gsp.DataStack);

            gsp.Pop(gsp.DataStack);
            gsp.Scratch = val1;
            gsp.Push(gsp.DataStack);
        }
        // ( n1 n2 -- diff ) Subtracts two numbers on the stack
        public void doMinus(ref GlobalSimpleProps gsp)
        {
            object arg1, arg2, diff;

            arg2        = gsp.Pop(gsp.DataStack);
            arg1        = gsp.Pop(gsp.DataStack);
            diff        = Convert.ToDouble(arg1) - Convert.ToDouble(arg2);
            gsp.Scratch = diff;
            gsp.Push(gsp.DataStack);
        }
        // ( n1 n2 -- product ) Multiplies two numbers on the stack
        public void doMultiply(ref GlobalSimpleProps gsp)
        {
            object arg1, arg2, product;

            arg2        = gsp.Pop(gsp.DataStack);
            arg1        = gsp.Pop(gsp.DataStack);
            product     = Convert.ToDouble(arg1) * Convert.ToDouble(arg2);
            gsp.Scratch = product;
            gsp.Push(gsp.DataStack);
        }
        // ( n1 n2 -- quotient ) Divides two numbers on the stack
        public void doDivide(ref GlobalSimpleProps gsp)
        {
            object arg1, arg2, quotient;

            arg2        = gsp.Pop(gsp.DataStack);
            arg1        = gsp.Pop(gsp.DataStack);
            quotient    = Convert.ToDouble(arg1) / Convert.ToDouble(arg2);
            gsp.Scratch = quotient;
            gsp.Push(gsp.DataStack);
        }
        // ( n1 n2 -- remainder ) Returns remainder of division operation
        public void doMod(ref GlobalSimpleProps gsp)
        {
            object arg1, arg2, remainder;

            arg2        = gsp.Pop(gsp.DataStack);
            arg1        = gsp.Pop(gsp.DataStack);
            remainder   = (int)arg1 % (int)arg2;
            gsp.Scratch = remainder;
            gsp.Push(gsp.DataStack);
        }
        // ( n1 n2 -- sum ) Adds two numbers on the stack
        public void doPlus(ref GlobalSimpleProps gsp)
        {
            object arg1, arg2, sum;

            arg2        = gsp.Pop(gsp.DataStack);
            arg1        = gsp.Pop(gsp.DataStack);
            sum         = Convert.ToDouble(arg1) + Convert.ToDouble(arg2);
            gsp.Scratch = sum;
            gsp.Push(gsp.DataStack);
        }
        // ( inc -- ) Loops back to doDo until the start >= the end and increments with inc
        public void doPlusLoop(ref GlobalSimpleProps gsp)
        {
            int        incVal     = (int)gsp.Pop(gsp.DataStack);
            CreoleWord currWord   = gsp.Cfb.Address[gsp.InnerPtr];
            List <int> paramField = currWord.ParamField;
            ReturnLoc  rLoc       = (ReturnLoc)gsp.Pop(gsp.ReturnStack);
            LoopInfo   li         = (LoopInfo)gsp.Pop(gsp.ReturnStack);
            int        jumpAddr   = paramField[rLoc.ParamFieldAddr];
            int        loopLimit  = li.Limit;
            string     loopLabel  = li.Label;
            int        currIndex  = li.Index;

            if (incVal == 0)
            {
                loopLimit += incVal;
            }
            else
            {
                loopLimit -= incVal;
            }

            if ((incVal > 0) && (currIndex >= loopLimit) || (incVal < 0) && (currIndex <= loopLimit))
            {
                gsp.ParamFieldPtr++;
                rLoc.ParamFieldAddr = gsp.ParamFieldPtr;
                gsp.LoopLabelPtr--;
            }
            else
            {
                gsp.ParamFieldPtr   = jumpAddr;
                currIndex           = currIndex + incVal;
                li.Index            = currIndex;
                rLoc.ParamFieldAddr = gsp.ParamFieldPtr;
                gsp.ReturnStack.Add(li);
            }

            if (loopLabel == "I")
            {
                gsp.LoopCurrIndexes[0] = currIndex;
            }
            else if (loopLabel == "J")
            {
                gsp.LoopCurrIndexes[1] = currIndex;;
            }
            else if (loopLabel == "K")
            {
                gsp.LoopCurrIndexes[2] = currIndex;;
            }
            else
            {
                Debug.Print("Error: Invalid loop label");
            }
            gsp.ReturnStack.Add(rLoc);
        }
        // ( val1 val2 -- val2 val1 ) Swaps the positions of the top two stack arguments
        public void doSwap(ref GlobalSimpleProps gsp)
        {
            object arg1, arg2;

            arg2        = gsp.Pop(gsp.DataStack);
            arg1        = gsp.Pop(gsp.DataStack);
            gsp.Scratch = arg2;
            gsp.Push(gsp.DataStack);
            gsp.Scratch = arg1;
            gsp.Push(gsp.DataStack);
        }
        // ( val1 val2 val3 -- val2 val3 val1 ) Moves the third stack argument to the top
        public void doRot(ref GlobalSimpleProps gsp)
        {
            object val3 = gsp.Pop(gsp.DataStack);
            object val2 = gsp.Pop(gsp.DataStack);
            object val1 = gsp.Pop(gsp.DataStack);

            gsp.Scratch = val2;
            gsp.Push(gsp.DataStack);
            gsp.Scratch = val3;
            gsp.Push(gsp.DataStack);
            gsp.Scratch = val1;
            gsp.Push(gsp.DataStack);
        }
        // ( start end -- ) Starts off the Do by getting the start and end
        public void doStartDo(ref GlobalSimpleProps gsp)
        {
            ReturnLoc rLoc       = (ReturnLoc)gsp.Pop(gsp.ReturnStack);
            int       startIndex = (int)gsp.Pop(gsp.DataStack);
            int       loopEnd    = (int)gsp.Pop(gsp.DataStack);
            LoopInfo  li         = new LoopInfo(gsp.LoopLabels[gsp.LoopLabelPtr], startIndex, loopEnd);

            for (int i = 0; i < 3; i++)
            {
                gsp.LoopCurrIndexes.Add(0);
            }
            gsp.LoopLabelPtr++;
            gsp.ReturnStack.Add(li);
            gsp.ReturnStack.Add(rLoc);
        }
        // ( val1 val2 -- flag ) -1 if less than or equal to, 0 otherwise
        public void doLessThanOrEquals(ref GlobalSimpleProps gsp)
        {
            object val2 = gsp.Pop(gsp.DataStack);
            object val1 = gsp.Pop(gsp.DataStack);

            if (Convert.ToInt64(val1) <= Convert.ToInt64(val2))
            {
                gsp.Scratch = -1;
            }
            else
            {
                gsp.Scratch = 0;
            }
            gsp.Push(gsp.DataStack);
        }
        // ( val1 val2 -- flag ) 0 if equal, -1 otherwise
        public void doNotEquals(ref GlobalSimpleProps gsp)
        {
            object val2 = gsp.Pop(gsp.DataStack);
            object val1 = gsp.Pop(gsp.DataStack);

            if (val1.Equals(val2))
            {
                gsp.Scratch = 0;
            }
            else
            {
                gsp.Scratch = -1;
            }
            gsp.Push(gsp.DataStack);
        }
        // val1 val2 -- flag ) -1 if one and only one argument is non-zero, 0 otherwise
        public void doXor(ref GlobalSimpleProps gsp)
        {
            object val2 = gsp.Pop(gsp.DataStack);
            object val1 = gsp.Pop(gsp.DataStack);

            if ((Convert.ToInt64(val2) != 0 || Convert.ToInt64(val1) != 0) && !(Convert.ToInt64(val1) != 0 || Convert.ToInt64(val2) != 0))
            {
                gsp.Scratch = -1;
            }
            else
            {
                gsp.Scratch = 0;
            }
            gsp.Push(gsp.DataStack);
        }
        // ( val1 val2 -- flag ) -1 if greater than, 0 otherwise
        public void doGreaterThan(ref GlobalSimpleProps gsp)
        {
            object val2 = gsp.Pop(gsp.DataStack);
            object val1 = gsp.Pop(gsp.DataStack);

            if (Convert.ToInt64(val1) > Convert.ToInt64(val2))
            {
                gsp.Scratch = -1;
            }
            else
            {
                gsp.Scratch = 0;
            }
            gsp.Push(gsp.DataStack);
        }
        // ( val1 val2 -- flag ) -1 if both arguments are non-zero, 0 otherwise
        public void doAnd(ref GlobalSimpleProps gsp)
        {
            object val2 = gsp.Pop(gsp.DataStack);
            object val1 = gsp.Pop(gsp.DataStack);

            if (Convert.ToInt64(val2) != 0 && Convert.ToInt64(val1) != 9)
            {
                gsp.Scratch = -1;
            }
            else
            {
                gsp.Scratch = 0;
            }
            gsp.Push(gsp.DataStack);
        }
        // ( val -- val val ) Duplicates the argument on top of the stack
        public void doDup(ref GlobalSimpleProps gsp)
        {
            object arg;

            arg = gsp.Pop(gsp.DataStack);
            gsp.Push(gsp.DataStack);
            gsp.Push(gsp.DataStack);
        }
        // ( address -- ) Executes the word corresponding to the address on the stack
        public void doExecute(ref GlobalSimpleProps gsp)
        {
            int address = (int)gsp.Pop(gsp.DataStack);

            gsp.InnerPtr = address;
            CreoleWord cw = gsp.Cfb.Address[address];

            cw.CodeField(ref gsp);
        }
        //  ( -- location ) Compile-time code for THEN
        public void compileThen(ref GlobalSimpleProps gsp)
        {
            int        newRow        = gsp.Cfb.Address.Count - 1;
            CreoleWord newCreoleWord = gsp.Cfb.Address[newRow];
            int        branchPFLoc   = (int)gsp.Pop(gsp.DataStack);
            string     runTimeAction = "doThen." + gsp.BFC.ImmediateVocab;
            int        thenAddr      = gsp.Cfb.Dict[runTimeAction].IndexField;

            newCreoleWord.ParamField.Add(thenAddr);
            newCreoleWord.ParamField[branchPFLoc] = newCreoleWord.ParamField.Count - 1;
        }
        // ( flag -- ) Run-time code for IF
        public void do0Branch(ref GlobalSimpleProps gsp)
        {
            CreoleWord currWord = gsp.Cfb.Address[gsp.InnerPtr];

            List <int> paramField = currWord.ParamField;
            ReturnLoc  rLoc       = (ReturnLoc)gsp.Pop(gsp.ReturnStack);
            int        jumpAddr   = paramField[rLoc.ParamFieldAddr];
            int        branchFlag = (int)gsp.Pop(gsp.DataStack);

            if (branchFlag == 0)
            {
                gsp.ParamFieldPtr = jumpAddr;
            }
            else
            {
                gsp.ParamFieldPtr++;
            }
            rLoc.ParamFieldAddr = gsp.ParamFieldPtr;
            gsp.ReturnStack.Add(rLoc);
        }
        // ( beginLoc -- ) Compile-time code for UNTIL
        public void compileUntil(ref GlobalSimpleProps gsp)
        {
            int        newRow         = gsp.Cfb.Address.Count - 1;
            CreoleWord newCreoleWord  = gsp.Cfb.Address[newRow];
            int        beginLoc       = (int)gsp.Pop(gsp.DataStack);
            string     runTimeAction  = "0BRANCH." + gsp.BFC.ImmediateVocab;
            int        zeroBranchAddr = gsp.Cfb.Dict[runTimeAction].IndexField;

            newCreoleWord.ParamField.Add(zeroBranchAddr);
            newCreoleWord.ParamField.Add(beginLoc);
        }
        // ( -- ) Jumps unconditionally to the parameter field location next to it and is compiled by ELSE
        public void doJump(ref GlobalSimpleProps gsp)
        {
            CreoleWord currWord   = gsp.Cfb.Address[gsp.InnerPtr];
            List <int> paramField = currWord.ParamField;
            int        jumpAddr   = paramField[gsp.ParamFieldPtr + 1];
            ReturnLoc  rLoc       = (ReturnLoc)gsp.Pop(gsp.ReturnStack);

            gsp.ParamFieldPtr   = jumpAddr;
            rLoc.ParamFieldAddr = gsp.ParamFieldPtr;
            gsp.ReturnStack.Add(rLoc);
        }
        // ( n -- ) Compiles value off the TOS into the next parameter field cell
        public void doComma(ref GlobalSimpleProps gsp)
        {
            int newRow = gsp.Cfb.Address.Count - 1;

            gsp.Scratch = gsp.Pop(gsp.DataStack);
            int        token         = (int)gsp.Scratch;
            CreoleWord newCreoleWord = gsp.Cfb.Address[newRow];

            newCreoleWord.ParamField.Add(token);
            newCreoleWord.ParamFieldStart++;
            gsp.ParamFieldPtr = newCreoleWord.ParamField.Count + 1;
        }
        // ( -- lit ) Run-time code that pushes a literal onto the stack
        public void doLiteral(ref GlobalSimpleProps gsp)
        {
            CreoleWord    currWord         = gsp.Cfb.Address[gsp.InnerPtr];
            List <int>    paramField       = currWord.ParamField;
            List <object> dataField        = currWord.DataField;
            ReturnLoc     rLoc             = (ReturnLoc)gsp.Pop(gsp.ReturnStack);
            int           litDataFieldAddr = paramField[gsp.ParamFieldPtr];

            gsp.DataStack.Add(dataField[litDataFieldAddr]);
            rLoc.ParamFieldAddr++;
            gsp.ParamFieldPtr = rLoc.ParamFieldAddr;
            gsp.ReturnStack.Add(rLoc);
        }
        // ( -- ) Compiles doLit and a literal into the dictionary
        public void compileLiteral(ref GlobalSimpleProps gsp)
        {
            int        newRow        = gsp.Cfb.Address.Count - 1;
            CreoleWord newCreoleWord = gsp.Cfb.Address[newRow];
            string     runTimeAction = "doLiteral." + gsp.BFC.ImmediateVocab;
            int        doLitAddr     = gsp.Cfb.Dict[runTimeAction].IndexField;
            object     litVal        = gsp.Pop(gsp.DataStack);

            newCreoleWord.ParamField.Add(doLitAddr);
            newCreoleWord.DataField.Add(litVal);
            newCreoleWord.ParamField.Add(newCreoleWord.DataField.Count - 1);
            gsp.ParamFieldPtr = newCreoleWord.ParamField.Count - 1;
        }
        // ( addr -- val ) Fetches the value in the param field  at addr
        public void doFetch(ref GlobalSimpleProps gsp)
        {
            int           address   = (int)gsp.Pop(gsp.DataStack);
            List <object> dataField = gsp.Cfb.Address[address].DataField;

            object storedVal = null;

            if (dataField.Count > 0)
            {
                storedVal = gsp.Cfb.Address[address].DataField[0];
            }
            gsp.DataStack.Add(storedVal);
        }
        // ( val -- opval ) -1 if 0, 0 otherwise
        public void doNot(ref GlobalSimpleProps gsp)
        {
            object val = gsp.Pop(gsp.DataStack);

            if (Convert.ToInt64(val) == 0)
            {
                gsp.Scratch = -1;
            }
            else
            {
                gsp.Scratch = 0;
            }
            gsp.Push(gsp.DataStack);
        }
        //  DOES> <list of runtime actions>. When defining word is created, copies code following it into the child definition
        public void compileDoes(ref GlobalSimpleProps gsp)
        {
            ReturnLoc  rLoc             = (ReturnLoc)gsp.Pop(gsp.ReturnStack);
            int        parentRow        = rLoc.DictAddr;
            int        newRow           = gsp.Cfb.Address.Count - 1;
            CreoleWord parentCreoleWord = gsp.Cfb.Address[parentRow];
            CreoleWord childCreoleWord  = gsp.Cfb.Address[newRow];
            string     fqNameField      = childCreoleWord.FQNameField;
            int        doesAddr         = gsp.Cfb.Dict["DOES>.FORTH"].IndexField;
            int        i = 0;

            childCreoleWord.CodeField    = gsp.Cfb.Modules.Compiler.doDoes;
            childCreoleWord.CodeFieldStr = "doDoes";
            // Find the location of the does address in the parent definition
            int startCopyPoint = -1;

            while (i < parentCreoleWord.ParamField.Count)
            {
                if (parentCreoleWord.ParamField[i] == doesAddr)
                {
                    startCopyPoint = i + 1;
                    break;
                }
                else
                {
                    i++;
                }
            }

            // Need the definition's address do doDoes can get it easily either when it's being
            // called from the interpreter from from within a compiled definition
            childCreoleWord.ParamField.Add(newRow);
            childCreoleWord.ParamFieldStart = childCreoleWord.ParamField.Count;
            i = 0;
            while (startCopyPoint < parentCreoleWord.ParamField.Count)
            {
                childCreoleWord.ParamField.Add(parentCreoleWord.ParamField[startCopyPoint]);
                startCopyPoint++;
                i++;
            }
            rLoc.ParamFieldAddr += i;
            gsp.ReturnStack.Add(rLoc);
            gsp.Cfb.Address[newRow]   = childCreoleWord;
            gsp.Cfb.Dict[fqNameField] = childCreoleWord;
        }
Beispiel #29
0
        // Run time code for colon definitions
        public void doColon(ref GlobalSimpleProps gsp)
        {
            CreoleWord currWord   = gsp.Cfb.Address[gsp.InnerPtr];
            List <int> paramField = currWord.ParamField;

            while (gsp.ParamFieldPtr < paramField.Count)
            {
                int       addrInPF  = paramField[gsp.ParamFieldPtr];
                Codefield codeField = gsp.Cfb.Address[addrInPF].CodeField;
                gsp.ParamFieldPtr++;
                ReturnLoc rLoc = new ReturnLoc(gsp.InnerPtr, gsp.ParamFieldPtr);
                gsp.Scratch = rLoc;
                gsp.Push(gsp.ReturnStack);
                codeField(ref gsp);
                rLoc              = (ReturnLoc)gsp.Pop(gsp.ReturnStack);
                gsp.InnerPtr      = rLoc.DictAddr;
                gsp.ParamFieldPtr = rLoc.ParamFieldAddr;
            }
        }
        // ( -- location ) Compile-time code for ELSE
        public void compileElse(ref GlobalSimpleProps gsp)
        {
            int        newRow         = gsp.Cfb.Address.Count - 1;
            CreoleWord newCreoleWord  = gsp.Cfb.Address[newRow];
            string     jumpAddrLookup = "JUMP." + gsp.BFC.ImmediateVocab;
            int        jumpAddr       = gsp.Cfb.Dict[jumpAddrLookup].IndexField;
            string     elseAddrLookup = "doElse." + gsp.BFC.ImmediateVocab;
            int        elseAddr       = gsp.Cfb.Dict[elseAddrLookup].IndexField;

            newCreoleWord.ParamField.Add(jumpAddr);
            newCreoleWord.ParamField.Add(-1);
            int jumpAddrPFLoc = newCreoleWord.ParamField.Count - 1;

            newCreoleWord.ParamField.Add(elseAddr);
            int zeroBrAddrPFLoc = (int)gsp.Pop(gsp.DataStack);

            newCreoleWord.ParamField[zeroBrAddrPFLoc] = newCreoleWord.ParamField.Count - 1;
            gsp.DataStack.Add(jumpAddrPFLoc);
            gsp.ParamFieldPtr = newCreoleWord.ParamField.Count - 1;
        }