Compare commits
2 Commits
c2c9a6bcc2
...
70e8c7e959
Author | SHA1 | Date |
---|---|---|
Starfflame | 70e8c7e959 | |
Starfflame | 7fa57cf474 |
|
@ -15,6 +15,7 @@ function CoreHelpers.standardInputRefill(): string
|
||||||
return input
|
return input
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function CoreHelpers._oneReadRefill(str: string): function(): string
|
function CoreHelpers._oneReadRefill(str: string): function(): string
|
||||||
local alreadyRead: boolean = false
|
local alreadyRead: boolean = false
|
||||||
return function(): string
|
return function(): string
|
||||||
|
@ -115,6 +116,14 @@ end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function CoreHelpers.recNumber(env: Environment)
|
||||||
|
local dataStack = CoreHelpers.getActiveDataStack(env)
|
||||||
|
local token = dataStack:pop() as string
|
||||||
|
if CoreHelpers.isNumber(token) then
|
||||||
|
-- push the XTs onto the stack
|
||||||
|
dataStack:push(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
return CoreHelpers
|
return CoreHelpers
|
||||||
|
|
129
CoreWords.tl
129
CoreWords.tl
|
@ -8,84 +8,83 @@ local defineWord = helpers.defineWord
|
||||||
local ret = helpers.ret
|
local ret = helpers.ret
|
||||||
local makeCall = helpers.makeCall
|
local makeCall = helpers.makeCall
|
||||||
-- Mathematical operations
|
-- Mathematical operations
|
||||||
local function add(state: Environment)
|
local function add(env: Environment)
|
||||||
local a, b = popTwoOperands(state)
|
local a, b = popTwoOperands(env)
|
||||||
if areNumbers(a,b) then
|
if areNumbers(a,b) then
|
||||||
local c = (a as number) + (b as number)
|
local c = (a as number) + (b as number)
|
||||||
getActiveDataStack(state):push(c)
|
getActiveDataStack(env):push(c)
|
||||||
else
|
else
|
||||||
error("invalid operands for add operation!")
|
error("invalid operands for add operation!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function sub(state: Environment)
|
local function sub(env: Environment)
|
||||||
local a, b = popTwoOperands(state)
|
local a, b = popTwoOperands(env)
|
||||||
if areNumbers(a, b) then
|
if areNumbers(a, b) then
|
||||||
local c = (a as number) - (b as number)
|
local c = (a as number) - (b as number)
|
||||||
getActiveDataStack(state):push(c)
|
getActiveDataStack(env):push(c)
|
||||||
else
|
else
|
||||||
error("invalid operands for sub operation!")
|
error("invalid operands for sub operation!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function mul(state: Environment)
|
local function mul(env: Environment)
|
||||||
local a, b = popTwoOperands(state)
|
local a, b = popTwoOperands(env)
|
||||||
if areNumbers(a, b) then
|
if areNumbers(a, b) then
|
||||||
local c = (a as number) * (b as number)
|
local c = (a as number) * (b as number)
|
||||||
getActiveDataStack(state):push(c)
|
getActiveDataStack(env):push(c)
|
||||||
else
|
else
|
||||||
error("invalid operands for mul operation!")
|
error("invalid operands for mul operation!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function div(state: Environment)
|
local function div(env: Environment)
|
||||||
local a, b = popTwoOperands(state)
|
local a, b = popTwoOperands(env)
|
||||||
if areNumbers(a, b) then
|
if areNumbers(a, b) then
|
||||||
local c = (a as number) / (b as number)
|
local c = (a as number) / (b as number)
|
||||||
getActiveDataStack(state):push(c)
|
getActiveDataStack(env):push(c)
|
||||||
else
|
else
|
||||||
error("invalid operands for div operation!")
|
error("invalid operands for div operation!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dup(state: Environment)
|
local function dup(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
local top = stack:pop()
|
local top = stack:pop()
|
||||||
stack:push(top)
|
stack:push(top)
|
||||||
stack:push(top)
|
stack:push(top)
|
||||||
end
|
end
|
||||||
local function swap(state: Environment)
|
local function swap(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
local a, b = popTwoOperands(state)
|
local a, b = popTwoOperands(env)
|
||||||
stack:push(b)
|
stack:push(b)
|
||||||
stack:push(a)
|
stack:push(a)
|
||||||
end
|
end
|
||||||
local function rot(state: Environment)
|
local function rot(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
local c, b, a= stack:pop(), stack:pop(), stack:pop()
|
local c, b, a= stack:pop(), stack:pop(), stack:pop()
|
||||||
stack:push(b)
|
stack:push(b)
|
||||||
stack:push(c)
|
stack:push(c)
|
||||||
stack:push(a)
|
stack:push(a)
|
||||||
end
|
end
|
||||||
local function drop(state: Environment)
|
local function drop(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
stack:pop()
|
stack:pop()
|
||||||
end
|
end
|
||||||
local function over(state: Environment)
|
local function over(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
local b, a = stack:pop(), stack:pop()
|
local b, a = stack:pop(), stack:pop()
|
||||||
stack:push(a)
|
stack:push(a)
|
||||||
stack:push(b)
|
stack:push(b)
|
||||||
stack:push(a)
|
stack:push(a)
|
||||||
end
|
end
|
||||||
-- I/O operations
|
-- I/O operations
|
||||||
local function dot(state: Environment)
|
local function dot(env: Environment)
|
||||||
local out = state.activeDataStack:pop()
|
local out = env.activeDataStack:pop()
|
||||||
io.write(tostring(out) as string.."\n")
|
io.write(tostring(out) as string.."\n")
|
||||||
end
|
end
|
||||||
local function twoDup(state: Environment)
|
|
||||||
over(state)
|
local twoDup = helpers.makeCall{over, over, ret}
|
||||||
over(state)
|
|
||||||
end
|
local function twoSwap(env: Environment)
|
||||||
local function twoSwap(state: Environment)
|
local stack = getActiveDataStack(env)
|
||||||
local stack = getActiveDataStack(state)
|
|
||||||
local d, c, b, a = stack:pop(), stack:pop(), stack:pop(), stack:pop()
|
local d, c, b, a = stack:pop(), stack:pop(), stack:pop(), stack:pop()
|
||||||
stack:push(c)
|
stack:push(c)
|
||||||
stack:push(d)
|
stack:push(d)
|
||||||
|
@ -94,8 +93,8 @@ local function twoSwap(state: Environment)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function twoOver(state: Environment)
|
local function twoOver(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
local d, c, b, a = stack:pop(), stack:pop(), stack:pop(), stack:pop()
|
local d, c, b, a = stack:pop(), stack:pop(), stack:pop(), stack:pop()
|
||||||
stack:push(a)
|
stack:push(a)
|
||||||
stack:push(b)
|
stack:push(b)
|
||||||
|
@ -104,17 +103,16 @@ local function twoOver(state: Environment)
|
||||||
stack:push(a)
|
stack:push(a)
|
||||||
stack:push(b)
|
stack:push(b)
|
||||||
end
|
end
|
||||||
local function nip(state: Environment)
|
local function nip(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
local b, _ = stack:pop(), stack:pop()
|
local b, _ = stack:pop(), stack:pop()
|
||||||
stack:push(b)
|
stack:push(b)
|
||||||
end
|
end
|
||||||
local function tuck(state: Environment)
|
|
||||||
swap(state)
|
local tuck = helpers.makeCall{swap, over, ret}
|
||||||
over(state)
|
|
||||||
end
|
local function roll(env: Environment)
|
||||||
local function roll(state: Environment)
|
local stack = getActiveDataStack(env)
|
||||||
local stack = getActiveDataStack(state)
|
|
||||||
local u = stack:pop()
|
local u = stack:pop()
|
||||||
local bufferStack = Stack:new()
|
local bufferStack = Stack:new()
|
||||||
if u is number then
|
if u is number then
|
||||||
|
@ -136,11 +134,11 @@ local function roll(state: Environment)
|
||||||
error("u is not a number")
|
error("u is not a number")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function getExecutionToken(state: Environment)
|
local function getExecutionToken(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
skipWhitespace(state)
|
skipWhitespace(env)
|
||||||
local name: string = parseToken(state)
|
local name: string = parseToken(env)
|
||||||
for _, dictionary in ipairs(state.dictionaries) do
|
for _, dictionary in ipairs(env.dictionaries) do
|
||||||
local wordinfo = dictionary:lookup(name)
|
local wordinfo = dictionary:lookup(name)
|
||||||
if wordinfo then
|
if wordinfo then
|
||||||
stack:push((wordinfo as WordInfo).func)
|
stack:push((wordinfo as WordInfo).func)
|
||||||
|
@ -149,10 +147,38 @@ local function getExecutionToken(state: Environment)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function execute(state: Environment)
|
local function execute(env: Environment)
|
||||||
local stack = getActiveDataStack(state)
|
local stack = getActiveDataStack(env)
|
||||||
local func: function(Environment) = stack:pop() as function(Environment)
|
local func: function(Environment) = stack:pop() as function(Environment)
|
||||||
func(state)
|
func(env)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function enterCompileMode(e: Environment)
|
||||||
|
e.compileState = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function exitCompileMode(e: Environment)
|
||||||
|
e.compileState = false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function compile(env: Environment)
|
||||||
|
local stack = env.activeDataStack
|
||||||
|
local f = stack:pop() as function(Environment)
|
||||||
|
table.insert(env.currentDefinition, f)
|
||||||
|
end
|
||||||
|
local function literal(env: Environment)
|
||||||
|
local stack = env.activeDataStack
|
||||||
|
local val = stack:pop()
|
||||||
|
local fun = function(e: Environment)
|
||||||
|
local s = e.activeDataStack
|
||||||
|
s:push(val)
|
||||||
|
end
|
||||||
|
table.insert(env.currentDefinition, fun)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function postpone(env: Environment)
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local CoreWords = Dictionary:new()
|
local CoreWords = Dictionary:new()
|
||||||
|
@ -175,6 +201,11 @@ defineWord(CoreWords, "TUCK", tuck, false)
|
||||||
defineWord(CoreWords, "ROLL", roll, false)
|
defineWord(CoreWords, "ROLL", roll, false)
|
||||||
defineWord(CoreWords, "'", getExecutionToken, false)
|
defineWord(CoreWords, "'", getExecutionToken, false)
|
||||||
defineWord(CoreWords, "EXECUTE", execute, false)
|
defineWord(CoreWords, "EXECUTE", execute, false)
|
||||||
|
defineWord(CoreWords, "[", exitCompileMode, true)
|
||||||
|
defineWord(CoreWords, "]", enterCompileMode, false)
|
||||||
|
defineWord(CoreWords, "COMPILE,", compile, true)
|
||||||
|
defineWord(CoreWords, "LITERAL", literal, true)
|
||||||
|
|
||||||
|
|
||||||
CoreWords:define("+", addInfo)
|
CoreWords:define("+", addInfo)
|
||||||
CoreWords:define("-", subInfo)
|
CoreWords:define("-", subInfo)
|
||||||
|
|
|
@ -38,7 +38,7 @@ local type DataStructures = record
|
||||||
interrupts: {function(Environment)}
|
interrupts: {function(Environment)}
|
||||||
activeInputStream: InputStream
|
activeInputStream: InputStream
|
||||||
dictionaries: {Dictionary}
|
dictionaries: {Dictionary}
|
||||||
state: boolean
|
compileState: boolean
|
||||||
new: function(Environment): Environment
|
new: function(Environment): Environment
|
||||||
addDataStack: function(Environment, Stack)
|
addDataStack: function(Environment, Stack)
|
||||||
changeCompilerStack: function(Environment, Stack)
|
changeCompilerStack: function(Environment, Stack)
|
||||||
|
@ -46,6 +46,8 @@ local type DataStructures = record
|
||||||
recognizers: {function(Environment)}
|
recognizers: {function(Environment)}
|
||||||
instructionPointer: Pointer
|
instructionPointer: Pointer
|
||||||
running: boolean
|
running: boolean
|
||||||
|
|
||||||
|
currentDefinition: {function(Environment)}
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
16
tests.lua
16
tests.lua
|
@ -390,6 +390,22 @@ describe("Interpreter tests", function()
|
||||||
assert.are.equal(3, testEnv.activeDataStack.contents[1])
|
assert.are.equal(3, testEnv.activeDataStack.contents[1])
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
describe("[ tests", function()
|
||||||
|
it("Switches the environment's state to interpretation mode.", function()
|
||||||
|
local testEnv = buildEnvironment("[")
|
||||||
|
testEnv.compileState = true
|
||||||
|
interpreters.start(testEnv)
|
||||||
|
assert.are.equal(false, testEnv.compileState)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
describe("] tests", function()
|
||||||
|
it("Switches the environment's state to compilation mode.", function()
|
||||||
|
local testEnv = buildEnvironment("]")
|
||||||
|
testEnv.compileState = false
|
||||||
|
interpreters.start(testEnv)
|
||||||
|
assert.are.equal(true, testEnv.compileState)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue