// (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; }
// 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; }