diff --git a/CoreHelpers.tl b/CoreHelpers.tl new file mode 100644 index 0000000..523e51d --- /dev/null +++ b/CoreHelpers.tl @@ -0,0 +1,56 @@ +local ds = require("DataStructures") +local Dictionary, Stack, WordInfo, State = ds.Dictionary, ds.Stack, ds.WordInfo, ds.State + +local CoreHelpers = {} + +function CoreHelpers.areNumbers(a: any, b: any): boolean + return a is number and b is number +end + +function CoreHelpers.getActiveDataStack(state: State): Stack + return state.activeDataStack +end + +function CoreHelpers.isNumber(token: string): boolean + if tonumber(token) ~= nil then + return true + else + return false + end +end + +function CoreHelpers.isWhitespace(chr: string): boolean + return (chr == " " or + chr == "\t" or + chr == "\r" or + chr == "\n" or + chr == "\v" or + chr == "\f") +end +function CoreHelpers.skipWhitespace(state: State) + local chr = state.activeInputStream:readCurrentCharacter() + while (CoreHelpers.isWhitespace(chr)) do + chr = state.activeInputStream:advanceOffset() + end +end + +function CoreHelpers.popTwoOperands(state: State): any, any + local stack = CoreHelpers.getActiveDataStack(state) + local b: any = stack:pop() + local a: any = stack:pop() + return a, b +end + + +function CoreHelpers.parseToken(state: State): string + local chr = state.activeInputStream:readCurrentCharacter() + local token = "" + while(not CoreHelpers.isWhitespace(chr)) do + token = token..chr + chr = state.activeInputStream:advanceOffset() + end + return token +end + +return CoreHelpers + diff --git a/CoreWords.tl b/CoreWords.tl index 11178dd..fb87e8c 100644 --- a/CoreWords.tl +++ b/CoreWords.tl @@ -1,45 +1,14 @@ 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 - +local helpers = require("CoreHelpers") +local areNumbers, getActiveDataStack, isNumber, isWhitespace= helpers.areNumbers, helpers.getActiveDataStack, helpers.isNumber, helpers.isWhitespace +local skipWhitespace, parseToken = helpers.skipWhitespace, helpers.parseToken +local popTwoOperands = helpers.popTwoOperands -- Mathematical operations local function add(state: State) local a, b = popTwoOperands(state) - if areNumbers(state, a,b) then + if areNumbers(a,b) then local c = (a as number) + (b as number) getActiveDataStack(state):push(c) else @@ -48,7 +17,7 @@ local function add(state: State) end local function sub(state: State) local a, b = popTwoOperands(state) - if areNumbers(state, a, b) then + if areNumbers(a, b) then local c = (a as number) - (b as number) getActiveDataStack(state):push(c) else @@ -57,7 +26,7 @@ local function sub(state: State) end local function mul(state: State) local a, b = popTwoOperands(state) - if areNumbers(state, a, b) then + if areNumbers(a, b) then local c = (a as number) * (b as number) getActiveDataStack(state):push(c) else @@ -66,7 +35,7 @@ local function mul(state: State) end local function div(state: State) local a, b = popTwoOperands(state) - if areNumbers(state, a, b) then + if areNumbers(a, b) then local c = (a as number) / (b as number) getActiveDataStack(state):push(c) else @@ -80,50 +49,17 @@ local function dot(state: State) end -local function skipWhitespace(state: State) - local chr = state.activeInputStream:readCurrentCharacter() - while (isWhitespace(state, chr)) do - chr = state.activeInputStream:advanceOffset() - end -end - -local function parseToken(state: State): string - local chr = state.activeInputStream:readCurrentCharacter() - local token = "" - while(not isWhitespace(state, chr)) do - token = token..chr - chr = state.activeInputStream:advanceOffset() - end - 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 diff --git a/ForthInterpreter.tl b/ForthInterpreter.tl index 1ddc98b..d3942ab 100644 --- a/ForthInterpreter.tl +++ b/ForthInterpreter.tl @@ -2,7 +2,8 @@ local CoreWords = require("CoreWords") local ds = require("DataStructures") local istream = require("InputStream") local Stack, Dictionary, WordInfo, State = ds.Stack, ds.Dictionary, ds.WordInfo, ds.State - +local helpers = require("CoreHelpers") +local isNumber, skipWhitespace, parseToken = helpers.isNumber, helpers.skipWhitespace, helpers.parseToken local machineState = State:new() function standardInputRefill(): string @@ -16,18 +17,11 @@ machineState.activeInputStream = standardInputStream machineState.activeDataStack = Stack:new() table.insert(machineState.dictionaries, CoreWords) -local getActiveDataStacks = (CoreWords:lookup("GetActiveData") as WordInfo).func -local areNumbers = (CoreWords:lookup("areNumbers") as WordInfo).func -local isNumber = (CoreWords:lookup("isNumber") as WordInfo).func -local isWhitespace = (CoreWords:lookup("isWhitespace") as WordInfo).func -local popTwoOperands = (CoreWords:lookup("popTwo") as WordInfo).func -local skipWhitespace = (CoreWords:lookup("skipWhitespace") as WordInfo).func -local parseToken = (CoreWords:lookup("parseToken") as WordInfo).func while(true) do skipWhitespace(machineState) local token: string = parseToken(machineState) - if isNumber(machineState, token) then + if isNumber(token) then machineState.activeDataStack:push(tonumber(token)) else for i, dictionary in ipairs(machineState.dictionaries) do