// ( 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); }
// doLoop is treated as a special case of doPlusLoop // # ( -- ) Loops back to doDo until the start equals the end public void doLoop(ref GlobalSimpleProps gsp) { gsp.DataStack.Add(1); string runTimeAction = "dPlusLoop." + gsp.BFC.ImmediateVocab; CreoleWord cw = gsp.Cfb.Dict[runTimeAction]; Codefield codeField = cw.CodeField; codeField(ref gsp); }
// ( -- ) Flags a word as immediate (so it executes instead of compiling inside a colon definition) public void doImmediate(ref GlobalSimpleProps gsp) { int newRow = gsp.Cfb.Address.Count - 1; CreoleWord newCreoleWord = gsp.Cfb.Address[newRow]; string fqName = newCreoleWord.FQNameField; newCreoleWord.CompileActionField = "EXECUTE"; newCreoleWord.Vocabulary = "IMMEDIATE"; }
// ( 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); }
// ( 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); }
// ( -- beginLoc ) Compile-time code for +LOOP public void compilePlusLoop(ref GlobalSimpleProps gsp) { int newRow = gsp.Cfb.Address.Count - 1; CreoleWord newCreoleWord = gsp.Cfb.Address[newRow]; string runTimeAction = "doPlusLoop." + gsp.BFC.ImmediateVocab; int loopAddr = gsp.Cfb.Dict[runTimeAction].IndexField; int doLoc = newCreoleWord.ParamField.Count - 1; newCreoleWord.ParamField.Add(loopAddr); newCreoleWord.ParamField.Add(doLoc); }
// ( 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); }
// ( -- 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; }
// ( 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); }
// ( -- ) 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); }
public void buildHighLevel(ref GlobalSimpleProps gsp, string code, string help) { gsp.InputArea = code; gsp.PADarea.Clear(); Modules.Interpreter.doParseInput(ref gsp); Modules.Interpreter.doOuter(ref gsp); Address[Address.Count - 1].HelpField = help; CreoleWord newDef = Address[Address.Count - 1]; Dict[newDef.FQNameField] = newDef; }
// ( 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 -- val1 val2 val1 ) Copies second stack argument to the top of the stack public void doOver(ref GlobalSimpleProps gsp) { object val2 = gsp.Pop(gsp.DataStack); object val1 = gsp.Pop(gsp.DataStack); gsp.Scratch = val1; gsp.Push(gsp.DataStack); gsp.Scratch = val2; gsp.Push(gsp.DataStack); gsp.Scratch = val1; gsp.Push(gsp.DataStack); }
// ( 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; }
// ( -- location ) Compile-time code for IF public void compileIf(ref GlobalSimpleProps gsp) { int newRow = gsp.Cfb.Address.Count - 1; CreoleWord newCreoleWord = gsp.Cfb.Address[newRow]; string runTimeAction = "0BRANCH." + gsp.BFC.ImmediateVocab; int zeroBranchAddr = gsp.Cfb.Dict[runTimeAction].IndexField; newCreoleWord.ParamField.Add(zeroBranchAddr); newCreoleWord.ParamField.Add(-1); gsp.ParamFieldPtr = newCreoleWord.ParamField.Count - 1; gsp.DataStack.Add(gsp.ParamFieldPtr); }
// ( -- beginLoc ) Compile-time code for BEGIN public void compileBegin(ref GlobalSimpleProps gsp) { int newRow = gsp.Cfb.Address.Count - 1; CreoleWord newCreoleWord = gsp.Cfb.Address[newRow]; string runTimeAction = "doBegin." + gsp.BFC.ImmediateVocab; int beginAddr = gsp.Cfb.Dict[runTimeAction].IndexField; newCreoleWord.ParamField.Add(beginAddr); int beginLoc = newCreoleWord.ParamField.Count - 1; gsp.DataStack.Add(beginLoc); }
// ( -- ) 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; }
// ( -- 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); }
// ( 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); }
// CREATE <name>. Adds a named entry into the dictionary public void doCreate(ref GlobalSimpleProps gsp) { int hereLoc = gsp.Cfb.Address.Count; string name = gsp.ParsedInput[gsp.OuterPtr + 1]; List <int> paramList = new List <int>(); List <object> data = new List <object>(); string help = "TODO: "; CreoleWord cw = new CreoleWord(name, gsp.Cfb.Modules.Compiler.doMyAddress, "Compiler.doMyAddress", gsp.CurrentVocab, "COMPINPF", help, hereLoc - 1, hereLoc, hereLoc - 1, hereLoc, paramList, data); string fqName = name + "." + gsp.CurrentVocab; gsp.Cfb.Dict[fqName] = cw; gsp.Cfb.Address.Add(gsp.Cfb.Dict[fqName]); gsp.OuterPtr += 2; }
// ( 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 ) -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 ) 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 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); }
// ( 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); }