forth-stuff/CoreWords.tl

132 lines
3.6 KiB
Plaintext
Raw Normal View History

2021-05-12 08:32:25 +00:00
local ds = require("DataStructures")
local Dictionary, Stack, WordInfo, State = ds.Dictionary, ds.Stack, ds.WordInfo, ds.State
2021-05-11 08:19:54 +00:00
-- helper functions
local function areNumbers(state: State, a: any, b: any): boolean
2021-05-11 08:19:54 +00:00
return a is number and b is number
end
2021-05-12 08:32:25 +00:00
local function getActiveDataStack(state: State): Stack
2021-05-11 08:19:54 +00:00
return state.activeDataStack
end
2021-05-12 08:32:25 +00:00
local function isNumber(state: State, token: string): boolean
2021-05-12 08:32:25 +00:00
if tonumber(token) ~= nil then
return true
else
return false
end
end
local function isWhitespace(state: State, chr: string): boolean
2021-05-12 08:32:25 +00:00
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
2021-05-11 08:19:54 +00:00
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)
2021-05-11 08:19:54 +00:00
local a, b = popTwoOperands(state)
if areNumbers(state, a,b) then
2021-05-11 08:19:54 +00:00
local c = (a as number) + (b as number)
getActiveDataStack(state):push(c)
2021-05-11 06:58:09 +00:00
else
error("invalid operands for add operation!")
end
end
local function sub(state: State)
2021-05-11 08:19:54 +00:00
local a, b = popTwoOperands(state)
if areNumbers(state, a, b) then
2021-05-11 08:19:54 +00:00
local c = (a as number) - (b as number)
getActiveDataStack(state):push(c)
else
error("invalid operands for sub operation!")
end
2021-05-11 06:58:09 +00:00
end
local function mul(state: State)
2021-05-11 08:19:54 +00:00
local a, b = popTwoOperands(state)
if areNumbers(state, a, b) then
2021-05-11 08:19:54 +00:00
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)
2021-05-11 08:19:54 +00:00
local a, b = popTwoOperands(state)
if areNumbers(state, a, b) then
2021-05-11 08:19:54 +00:00
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)
2021-05-11 08:19:54 +00:00
local out = state.activeDataStack:pop()
print(out)
end
local function skipWhitespace(state: State)
2021-05-12 08:32:25 +00:00
local chr = state.activeInputStream:readCurrentCharacter()
while (isWhitespace(state, chr)) do
2021-05-12 08:32:25 +00:00
chr = state.activeInputStream:advanceOffset()
end
end
local function parseToken(state: State): string
2021-05-12 08:32:25 +00:00
local chr = state.activeInputStream:readCurrentCharacter()
local token = ""
while(not isWhitespace(state, chr)) do
2021-05-12 08:32:25 +00:00
token = token..chr
chr = state.activeInputStream:advanceOffset()
end
return token
2021-05-12 08:32:25 +00:00
end
2021-05-11 08:19:54 +00:00
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)
2021-05-11 08:19:54 +00:00
return CoreWords
2021-05-11 06:55:13 +00:00