diff --git a/CoreWords.tl b/CoreWords.tl index c24258b..e4940d1 100644 --- a/CoreWords.tl +++ b/CoreWords.tl @@ -1,17 +1,33 @@ -local Dictionary = require("Dictionary") -local Stack = require("Stack") -local WordInfo = require("WordInfo") -local State = require("State") - +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() @@ -64,6 +80,24 @@ function dot(state: State) 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) diff --git a/DataStructures.tl b/DataStructures.tl new file mode 100644 index 0000000..5a3dd22 --- /dev/null +++ b/DataStructures.tl @@ -0,0 +1,93 @@ +local type DataStructures = record + record Stack + contents: {any} + top: number + push: function(Stack, any) + pop: function(Stack) + new: function(Stack): Stack + end + + record Dictionary + contents: {string: WordInfo} + end + record WordInfo + func: function(State) + immediate: boolean + end + + record State + dataStacks: {Stack} + compilerStack: Stack + activeDataStack: Stack + interrupts: {function(State)} + activeInputStream: InputStream + dictionaries: {Dictionary} + end +end + +local ds = DataStructures + + +local wordi_mt = {__index = ds.WordInfo} +function ds.WordInfo:new(funct: function(State), imm: boolean): ds.WordInfo + return setmetatable({func = funct, immediate = imm} as ds.WordInfo, wordi_mt) +end + + +local state_mt = {__index = State} +function ds.State:new(): State + return setmetatable( + { + dataStacks = {}, + compilerStack = Stack:new() + } as State, + state_mt) +end + +function ds.State:addDataStack(data: Stack) + table.insert(self.dataStacks, data) +end + +function ds.State:changeCompilerStack(compilerStack: Stack) + self.compilerStack = compilerStack +end +function ds.State:changeActiveDataStack(stackIndex: number) + assert(stackIndex <= #self.dataStacks and stackIndex > 0) + self.activeDataStack = self.dataStacks[stackIndex] +end + + + + +function ds.Stack:push(val: any) + self.top = self.top + 1 + table.insert(self.contents,val) +end +function ds.Stack:pop(): any + self.top = self.top -1 + if self.top < 0 then + error("Stack underflow") + end + return table.remove(self.contents) +end +local stack_mt = {__index = ds.Stack} +function ds.Stack:new(): ds.Stack + return setmetatable({contents = {}, top = 0} as ds.Stack, stack_mt) +end + + +-- operations + + + + + + +function ds.Dictionary:define(word: string, info: WordInfo) + self.contents[word] = info +end +local dict_mt = {__index = Dictionary} +function ds.Dictionary:new(): ds.Dictionary + return setmetatable({contents = {}} as Dictionary, dict_mt) +end + diff --git a/Dictionary.tl b/Dictionary.tl index bbd74c2..69ed71d 100644 --- a/Dictionary.tl +++ b/Dictionary.tl @@ -1,4 +1,3 @@ -local State = require("State") local WordInfo = require("WordInfo") diff --git a/ForthInterpreter.tl b/ForthInterpreter.tl new file mode 100644 index 0000000..51a9701 --- /dev/null +++ b/ForthInterpreter.tl @@ -0,0 +1,24 @@ + +-- helper functions + +function isNumber(token: string): boolean + if tonumber(token) ~= nil then + return true + else + return false + end +end + + + + +for line in io.lines() do + local tokens = {} + for token in line:gmatch("%S+") do + table.insert(tokens, token) + end + for idx, val in ipairs(tokens) do + print(idx, val, isNumber(val)) + end +end + diff --git a/State.tl b/State.tl index 2631dec..458978c 100644 --- a/State.tl +++ b/State.tl @@ -1,14 +1,14 @@ local Stack = require("Stack") - - - +local InputStream = require("InputStream") +local Dictionary = require("Dictionary") local type State = record dataStacks: {Stack} compilerStack: Stack activeDataStack: Stack interrupts: {function(State)} - -- dictionaries: {string:any} + activeInputStream: InputStream + dictionaries: {Dictionary} end local state_mt = {__index = State} @@ -34,7 +34,4 @@ function State:changeActiveDataStack(stackIndex: number) end - - - return State