local ds = require("DataStructures") local Dictionary, Stack, WordInfo, State = ds.Dictionary, ds.Stack, ds.WordInfo, ds.State -- helper functions function areNumbers(a: any, b: any): boolean return a is number and b is number end function getActiveDataStack(state: State): Stack return state.activeDataStack end function isNumber(token: string): boolean if tonumber(token) ~= nil then return true else return false end end function isWhitespace(chr: string): boolean return (chr == " " or chr == "\t" or chr == "\r" or chr == "\n" or chr == "\v" or chr == "\f") end 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 function add(state: State) local a, b = popTwoOperands(state) if areNumbers(a,b) then local c = (a as number) + (b as number) getActiveDataStack(state):push(c) else error("invalid operands for add operation!") end end function sub(state: State) local a, b = popTwoOperands(state) if areNumbers(a, b) then local c = (a as number) - (b as number) getActiveDataStack(state):push(c) else error("invalid operands for sub operation!") end end function mul(state: State) local a, b = popTwoOperands(state) if areNumbers(a, b) then local c = (a as number) * (b as number) getActiveDataStack(state):push(c) else error("invalid operands for mul operation!") end end function div(state: State) local a, b = popTwoOperands(state) if areNumbers(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 function dot(state: State) local out = state.activeDataStack:pop() print(out) end function skipWhitespace(state: State) local chr = state.activeInputStream:readCurrentCharacter() while (isWhitespace(chr)) do chr = state.activeInputStream:advanceOffset() end end function parseToken(state: State): string local chr = state.activeInputStream:readCurrentCharacter() local token = "" while(not isWhitespace(chr)) do token = token..chr chr = state.activeInputStream:advanceOffset() end 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) CoreWords:define("+", AddInfo) CoreWords:define("-", SubInfo) CoreWords:define("*", MulInfo) CoreWords:define("/", DivInfo) return CoreWords