local InputStream = require("InputStream") local type DataStructures = record record Stack contents: {integer:any} top: integer push: function(Stack, any) pop: function(Stack) new: function(Stack): Stack end record Dictionary contents: {string: WordInfo} wordCount: integer define: function(Dictionary, string, WordInfo) end record WordInfo toFunc: function(Environment) func: function(Environment) immediate: boolean new: function(WordInfo, function(Environment), boolean): WordInfo end record Pointer index: number referant: {number: any} deref: function(self: Pointer): any inc: function(self: Pointer) new: function(self: Pointer, body: {function(Environment)}, idx: number): Pointer end record Environment dataStacks: {Stack} compilerStack: Stack returnStack: Stack activeDataStack: Stack interrupts: {function(Environment)} activeInputStream: InputStream dictionaries: {Dictionary} compileState: boolean new: function(Environment): Environment addDataStack: function(Environment, Stack) changeCompilerStack: function(Environment, Stack) changeActiveDataStack: function(Environment, number) recognizers: {function(Environment)} instructionPointer: Pointer running: boolean currentDefinitionName: string | nil currentDefinition: {function(Environment)} mostRecentDefinition: string toMode: boolean locals: Dictionary localBuffer: {function(integer, Environment)} values: {any} end end local Stack, Environment, Dictionary, WordInfo = DataStructures.Stack, DataStructures.Environment, DataStructures.Dictionary, DataStructures.WordInfo local Pointer = DataStructures.Pointer local wordi_mt = {__index = WordInfo} function WordInfo:new(funct: function(Environment, ...: any), imm: boolean, toFunct: function(Environment) | nil): WordInfo return setmetatable({func = funct, immediate = imm, toFunc = toFunct} as WordInfo, wordi_mt) end --function Environment:changeActiveDataStack(stackIndex: number) -- assert(stackIndex <= #self.dataStacks and stackIndex > 0) -- self.activeDataStack = self.dataStacks[stackIndex] --end function Stack:push(val: any) self.top = self.top + 1 table.insert(self.contents,val) end function 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 = Stack} function Stack:new(): Stack return setmetatable({contents = {}, top = 0} as Stack, stack_mt) end -- operations function Dictionary:lookup(word: string): WordInfo | nil return self.contents[word] end function Dictionary:define(word: string, info: WordInfo) if not self.contents[word] then self.wordCount = self.wordCount + 1 end self.contents[word] = info end local dict_mt = {__index = Dictionary} function Dictionary:new(): Dictionary return setmetatable({contents = {}, wordCount = 0} as Dictionary, dict_mt) end local state_mt = {__index = Environment} function Environment:new(input: InputStream, dict: {Dictionary} ): Environment local dicts = dict or {} return setmetatable( { activeDataStack= Stack:new(), compilerStack = Stack:new(), returnStack = Stack:new(), dictionaries = dicts, activeInputStream = input, running = true, recognizers = {}, compileState = false, currentDefinition = {}, locals = Dictionary:new(), localBuffer = {}, values = {} } as Environment, state_mt) end function Environment:addDataStack(data: Stack) table.insert(self.dataStacks, data) end function Environment:changeCompilerStack(compilerStack: Stack) self.compilerStack = compilerStack end function Pointer:deref(): any return self.referant[self.index] end function Pointer:inc() self.index = self.index + 1 end local pointer_mt = {__index = Pointer} function Pointer:new(): Pointer return setmetatable({referant = {}, index = 1} as Pointer, pointer_mt) end function Pointer:new(body: {function(Environment)}, idx: number): Pointer local tbl = body or {} local jdx = idx or 1 return setmetatable({referant = tbl, index = jdx} as Pointer, pointer_mt) end return DataStructures