local ds = require("DataStructures") local Dictionary, Stack, WordInfo, State = ds.Dictionary, ds.Stack, ds.WordInfo, ds.State -- helper functions local function areNumbers(state: State, a: any, b: any): boolean return a is number and b is number end local function getActiveDataStack(state: State): Stack return state.activeDataStack end local function isNumber(state: State, token: string): boolean if tonumber(token) ~= nil then return true else return false end end local function isWhitespace(state: State, chr: string): boolean return (chr == " " or chr == "\t" or chr == "\r" or chr == "\n" or chr == "\v" or chr == "\f") end local function popTwoOperands(state: State): any, any local stack = getActiveDataStack(state) local b: any = stack:pop() local a: any = stack:pop() return a, b end -- Mathematical operations local function add(state: State) local a, b = popTwoOperands(state) if areNumbers(state, a,b) then local c = (a as number) + (b as number) getActiveDataStack(state):push(c) else error("invalid operands for add operation!") end end local function sub(state: State) local a, b = popTwoOperands(state) if areNumbers(state, a, b) then local c = (a as number) - (b as number) getActiveDataStack(state):push(c) else error("invalid operands for sub operation!") end end local function mul(state: State) local a, b = popTwoOperands(state) if areNumbers(state, a, b) then local c = (a as number) * (b as number) getActiveDataStack(state):push(c) else error("invalid operands for mul operation!") end end local function div(state: State) local a, b = popTwoOperands(state) if areNumbers(state, a, b) then local c = (a as number) / (b as number) getActiveDataStack(state):push(c) else error("invalid operands for div operation!") end end -- I/O operations local function dot(state: State) local out = state.activeDataStack:pop() print(out) end local function skipWhitespace(state: State) local chr = state.activeInputStream:readCurrentCharacter() while (isWhitespace(state, chr)) do print("SKIPPING WHITESPACE") chr = state.activeInputStream:advanceOffset() end end local function parseToken(state: State): string local chr = state.activeInputStream:readCurrentCharacter() local token = "" print("paresToken called") while(not isWhitespace(state, chr)) do print("parsing....", chr) token = token..chr chr = state.activeInputStream:advanceOffset() print(chr) end print("parsed", token) return token end local CoreWords = Dictionary:new() local addInfo = WordInfo:new(add, false) local subInfo = WordInfo:new(sub, false) local mulInfo = WordInfo:new(mul, false) local divInfo = WordInfo:new(div, false) local dotInfo = WordInfo:new(dot, false) local getActiveDataStackInfo = WordInfo:new(getActiveDataStack, true) local areNumbersInfo = WordInfo:new(areNumbers, false) local isNumberInfo = WordInfo:new(isNumber, false) local isWhitespaceInfo = WordInfo:new(isWhitespace, false) local popTwoOperandsInfo = WordInfo:new(popTwoOperands, false) local parseTokenInfo = WordInfo:new(parseToken, true) local skipWhitespaceInfo = WordInfo:new(skipWhitespace, true) CoreWords:define("+", addInfo) CoreWords:define("-", subInfo) CoreWords:define("*", mulInfo) CoreWords:define("/", divInfo) CoreWords:define(".", dotInfo) CoreWords:define("GetActiveData", getActiveDataStackInfo) CoreWords:define("areNumbers", areNumbersInfo) CoreWords:define("isNumber", isNumberInfo) CoreWords:define("isWhitespace", isWhitespaceInfo) CoreWords:define("popTwo", popTwoOperandsInfo) CoreWords:define("parseToken", parseTokenInfo) CoreWords:define("skipWhitespace", skipWhitespaceInfo) return CoreWords