From 3ddc671cb3f7ba08dfed823d655fb974245e77b5 Mon Sep 17 00:00:00 2001 From: Starfflame Date: Tue, 25 May 2021 23:27:18 -0500 Subject: [PATCH] Add colon and semicolon operators --- CoreHelpers.tl | 16 +++++++++++++--- CoreWords.tl | 26 +++++++++++++++++++++++++- DataStructures.tl | 9 ++++++--- Interpreters.tl | 43 +++++++++++++++++++++++++++++++------------ tests.lua | 5 +++++ 5 files changed, 80 insertions(+), 19 deletions(-) diff --git a/CoreHelpers.tl b/CoreHelpers.tl index 7f03d20..e541c46 100644 --- a/CoreHelpers.tl +++ b/CoreHelpers.tl @@ -156,6 +156,7 @@ function CoreHelpers.recNumber(env: Environment) dataStack:push(CoreHelpers.literal) -- return success dataStack:push(true) + return end dataStack:push(token) dataStack:push(false) @@ -172,15 +173,24 @@ function CoreHelpers.recWord(env: Environment) -- interpret dataStack:push(CoreHelpers.execute) -- compile - dataStack:push(CoreHelpers.compile) + if (wordinfo as WordInfo).immediate then + dataStack:push(CoreHelpers.execute) + else + dataStack:push(CoreHelpers.compile) + end -- immediate dataStack:push(CoreHelpers.postpone) -- return success dataStack:push(true) + return end - dataStack:push(token) - dataStack:push(false) end + dataStack:push(token) + dataStack:push(false) +end + +function CoreHelpers.ack(e: Environment) + io.write("ok\n") end return CoreHelpers diff --git a/CoreWords.tl b/CoreWords.tl index 5398ab4..ba95b3a 100644 --- a/CoreWords.tl +++ b/CoreWords.tl @@ -164,6 +164,29 @@ local function exitCompileMode(e: Environment) e.compileState = false end +local function colon(e: Environment) + skipWhitespace(e) + local name: string | nil = parseToken(e) + if not name then + e.running = false + return + end + e.currentDefinitionName = name as string + enterCompileMode(e) +end + +local function semicolon(e: Environment) + table.insert(e.currentDefinition, helpers.ret) + local instrs = e.currentDefinition + local call = helpers.makeCall(instrs) + local dict = e.dictionaries[1] + defineWord(dict, e.currentDefinitionName, call, false) + e.currentDefinitionName = nil + e.currentDefinition = {} + exitCompileMode(e) +end + + local CoreWords = Dictionary:new() local addInfo = WordInfo:new(add, false) local subInfo = WordInfo:new(sub, false) @@ -188,7 +211,8 @@ defineWord(CoreWords, "[", exitCompileMode, true) defineWord(CoreWords, "]", enterCompileMode, false) defineWord(CoreWords, "COMPILE,", compile, true) defineWord(CoreWords, "LITERAL", literal, true) - +defineWord(CoreWords, ":", colon, true) +defineWord(CoreWords, ";", semicolon, true) CoreWords:define("+", addInfo) CoreWords:define("-", subInfo) diff --git a/DataStructures.tl b/DataStructures.tl index a73ca96..cde5171 100644 --- a/DataStructures.tl +++ b/DataStructures.tl @@ -46,7 +46,7 @@ local type DataStructures = record recognizers: {function(Environment)} instructionPointer: Pointer running: boolean - + currentDefinitionName: string | nil currentDefinition: {function(Environment)} end @@ -71,8 +71,11 @@ function Environment:new(input: InputStream, dict: {Dictionary} ): Environment returnStack = Stack:new(), dictionaries = dicts, activeInputStream = input, - running = true - } as Environment, + running = true, + recognizers = {}, + compileState = false, + currentDefinition = {} + } as Environment, state_mt) end diff --git a/Interpreters.tl b/Interpreters.tl index ea35633..a068b1a 100644 --- a/Interpreters.tl +++ b/Interpreters.tl @@ -15,6 +15,8 @@ function Interpreters.start(env: Environment) local interpreterInstructions = {} table.insert(interpreterInstructions, Interpreters.outer) table.insert(interpreterInstructions, helpers.reset) + table.insert(env.recognizers, helpers.recNumber) + table.insert(env.recognizers, helpers.recWord) local startPointer = Pointer:new() startPointer.referant = interpreterInstructions env.instructionPointer = startPointer @@ -22,29 +24,46 @@ function Interpreters.start(env: Environment) end +function selectRecXT(env: Environment): function(Environment) + local dataStack = env.activeDataStack + if env.compileState then + dataStack:pop() + local selected = dataStack:pop() + dataStack:pop() + return selected as function(Environment) + else + dataStack:pop() + dataStack:pop() + return dataStack:pop() as function(Environment) + end +end + function Interpreters.outer(env: Environment) + local dataStack = env.activeDataStack skipWhitespace(env) local token: string | nil = parseToken(env) if not token then env.running = false return end - if isNumber(token) then - env.activeDataStack:push(tonumber(token)) - else - for _, dictionary in ipairs(env.dictionaries) do - local wordinfo = dictionary:lookup(token) - if wordinfo then - (wordinfo as WordInfo).func(env) - goto continue - end + for _, rec in ipairs(env.recognizers) do + dataStack:push(token) + rec(env) + local result = dataStack:pop() as boolean + if not result then + token = dataStack:pop() as string + end + if result then + (selectRecXT(env))(env) + return end - print(string.format('%q ?', token)) - ::continue:: end + + -- We did not recognize the token. + io.write("\""..token.."\"?\n") end - + function Interpreters.inner(env: Environment) while(env.running) do env.instructionPointer:deref() as function(Environment)(env) diff --git a/tests.lua b/tests.lua index f6ab915..7bcaf4f 100644 --- a/tests.lua +++ b/tests.lua @@ -231,6 +231,11 @@ describe("Interpreter tests", function() assert.are.same(expectedResult,testEnv.activeDataStack.contents[1]) end end) + it("does not push anything when a garbage input is given", function() + local testEnv = buildEnvironment("BOGUS") + interpreters.start(testEnv) + assert.are.same({}, testEnv.activeDataStack.contents) + end) end) describe("Core word tests", function() describe("DUP tests", function()