diff --git a/CoreHelpers.tl b/CoreHelpers.tl index 33022b7..24dba75 100644 --- a/CoreHelpers.tl +++ b/CoreHelpers.tl @@ -15,6 +15,7 @@ function CoreHelpers.standardInputRefill(): string return input end + function CoreHelpers._oneReadRefill(str: string): function(): string local alreadyRead: boolean = false 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 diff --git a/CoreWords.tl b/CoreWords.tl index e165a64..4d320ba 100644 --- a/CoreWords.tl +++ b/CoreWords.tl @@ -8,84 +8,83 @@ local defineWord = helpers.defineWord local ret = helpers.ret local makeCall = helpers.makeCall -- Mathematical operations -local function add(state: Environment) - local a, b = popTwoOperands(state) +local function add(env: Environment) + local a, b = popTwoOperands(env) if areNumbers(a,b) then local c = (a as number) + (b as number) - getActiveDataStack(state):push(c) + getActiveDataStack(env):push(c) else error("invalid operands for add operation!") end end -local function sub(state: Environment) - local a, b = popTwoOperands(state) +local function sub(env: Environment) + local a, b = popTwoOperands(env) if areNumbers(a, b) then local c = (a as number) - (b as number) - getActiveDataStack(state):push(c) + getActiveDataStack(env):push(c) else error("invalid operands for sub operation!") end end -local function mul(state: Environment) - local a, b = popTwoOperands(state) +local function mul(env: Environment) + local a, b = popTwoOperands(env) if areNumbers(a, b) then local c = (a as number) * (b as number) - getActiveDataStack(state):push(c) + getActiveDataStack(env):push(c) else error("invalid operands for mul operation!") end end -local function div(state: Environment) - local a, b = popTwoOperands(state) +local function div(env: Environment) + local a, b = popTwoOperands(env) if areNumbers(a, b) then local c = (a as number) / (b as number) - getActiveDataStack(state):push(c) + getActiveDataStack(env):push(c) else error("invalid operands for div operation!") end end -local function dup(state: Environment) - local stack = getActiveDataStack(state) +local function dup(env: Environment) + local stack = getActiveDataStack(env) local top = stack:pop() stack:push(top) stack:push(top) end -local function swap(state: Environment) - local stack = getActiveDataStack(state) - local a, b = popTwoOperands(state) +local function swap(env: Environment) + local stack = getActiveDataStack(env) + local a, b = popTwoOperands(env) stack:push(b) stack:push(a) end -local function rot(state: Environment) - local stack = getActiveDataStack(state) +local function rot(env: Environment) + local stack = getActiveDataStack(env) local c, b, a= stack:pop(), stack:pop(), stack:pop() stack:push(b) stack:push(c) stack:push(a) end -local function drop(state: Environment) - local stack = getActiveDataStack(state) +local function drop(env: Environment) + local stack = getActiveDataStack(env) stack:pop() end -local function over(state: Environment) - local stack = getActiveDataStack(state) +local function over(env: Environment) + local stack = getActiveDataStack(env) local b, a = stack:pop(), stack:pop() stack:push(a) stack:push(b) stack:push(a) end -- I/O operations -local function dot(state: Environment) - local out = state.activeDataStack:pop() +local function dot(env: Environment) + local out = env.activeDataStack:pop() io.write(tostring(out) as string.."\n") end -local function twoDup(state: Environment) - over(state) - over(state) -end -local function twoSwap(state: Environment) - local stack = getActiveDataStack(state) + +local twoDup = helpers.makeCall{over, over, ret} + +local function twoSwap(env: Environment) + local stack = getActiveDataStack(env) local d, c, b, a = stack:pop(), stack:pop(), stack:pop(), stack:pop() stack:push(c) stack:push(d) @@ -94,8 +93,8 @@ local function twoSwap(state: Environment) end -local function twoOver(state: Environment) - local stack = getActiveDataStack(state) +local function twoOver(env: Environment) + local stack = getActiveDataStack(env) local d, c, b, a = stack:pop(), stack:pop(), stack:pop(), stack:pop() stack:push(a) stack:push(b) @@ -104,17 +103,16 @@ local function twoOver(state: Environment) stack:push(a) stack:push(b) end -local function nip(state: Environment) - local stack = getActiveDataStack(state) +local function nip(env: Environment) + local stack = getActiveDataStack(env) local b, _ = stack:pop(), stack:pop() stack:push(b) end -local function tuck(state: Environment) - swap(state) - over(state) -end -local function roll(state: Environment) - local stack = getActiveDataStack(state) + +local tuck = helpers.makeCall{swap, over, ret} + +local function roll(env: Environment) + local stack = getActiveDataStack(env) local u = stack:pop() local bufferStack = Stack:new() if u is number then @@ -136,11 +134,11 @@ local function roll(state: Environment) error("u is not a number") end end -local function getExecutionToken(state: Environment) - local stack = getActiveDataStack(state) - skipWhitespace(state) - local name: string = parseToken(state) - for _, dictionary in ipairs(state.dictionaries) do +local function getExecutionToken(env: Environment) + local stack = getActiveDataStack(env) + skipWhitespace(env) + local name: string = parseToken(env) + for _, dictionary in ipairs(env.dictionaries) do local wordinfo = dictionary:lookup(name) if wordinfo then stack:push((wordinfo as WordInfo).func) @@ -149,10 +147,34 @@ local function getExecutionToken(state: Environment) end end -local function execute(state: Environment) - local stack = getActiveDataStack(state) +local function execute(env: Environment) + local stack = getActiveDataStack(env) 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) + +end +local function literal(env: Environment) + local stack = env.activeDataStack + local fun = function(e: Environment) + + + end +end + +local function postpone(env: Environment) + + end local CoreWords = Dictionary:new() @@ -175,6 +197,8 @@ defineWord(CoreWords, "TUCK", tuck, false) defineWord(CoreWords, "ROLL", roll, false) defineWord(CoreWords, "'", getExecutionToken, false) defineWord(CoreWords, "EXECUTE", execute, false) +defineWord(CoreWords, "[", exitCompileMode, false) +defineWord(CoreWords, "]", enterCompileMode, false) CoreWords:define("+", addInfo) CoreWords:define("-", subInfo) diff --git a/DataStructures.tl b/DataStructures.tl index c206643..428695e 100644 --- a/DataStructures.tl +++ b/DataStructures.tl @@ -38,7 +38,7 @@ local type DataStructures = record interrupts: {function(Environment)} activeInputStream: InputStream dictionaries: {Dictionary} - state: boolean + compileState: boolean new: function(Environment): Environment addDataStack: function(Environment, Stack) changeCompilerStack: function(Environment, Stack) diff --git a/tests.lua b/tests.lua index 445bb8f..f6ab915 100644 --- a/tests.lua +++ b/tests.lua @@ -390,6 +390,22 @@ describe("Interpreter tests", function() assert.are.equal(3, testEnv.activeDataStack.contents[1]) 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)