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
|
|
|
|
function areNumbers(a: any, b: any): boolean
|
|
|
|
return a is number and b is number
|
|
|
|
end
|
2021-05-12 08:32:25 +00:00
|
|
|
|
2021-05-11 08:19:54 +00:00
|
|
|
function getActiveDataStack(state: State): Stack
|
|
|
|
return state.activeDataStack
|
|
|
|
end
|
2021-05-12 08:32:25 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2021-05-11 08:19:54 +00:00
|
|
|
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)
|
2021-05-11 06:58:09 +00:00
|
|
|
else
|
|
|
|
error("invalid operands for add operation!")
|
|
|
|
end
|
|
|
|
end
|
2021-05-11 08:19:54 +00:00
|
|
|
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
|
2021-05-11 06:58:09 +00:00
|
|
|
end
|
2021-05-11 08:19:54 +00:00
|
|
|
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
|
|
|
|
|
2021-05-12 08:32:25 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
CoreWords:define("+", AddInfo)
|
|
|
|
CoreWords:define("-", SubInfo)
|
|
|
|
CoreWords:define("*", MulInfo)
|
|
|
|
CoreWords:define("/", DivInfo)
|
|
|
|
|
|
|
|
return CoreWords
|
|
|
|
|
2021-05-11 06:55:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|