forth-stuff/CoreWords.tl

117 lines
2.6 KiB
Plaintext

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