requires: {#Set. #ExtensibleArray}. provides: {#FileModule. #Module}. globals modules: (globals modules as: ExtensibleArray). "Overrides the interpreter's type for this global." _@lobby enterModule: name "Overrides the interpreter's hook of the same signature." [ globals modules include: name. currentModule: name ]. globals ensureNamespace: #Modules. "TODO: make it a collection?" prototypes addPrototype: #Module derivedFrom: {Cloneable}. "Modules are a collection of objects and methods, which together provide certain features, and require other modules' features to function." Module addSlot: #requirements valued: Set newEmpty. "Requirements are the set of modules that the given one requires before it can be loaded." Module addSlot: #imports valued: Set newEmpty. "Imports are objects and features referenced by the module's code." Module addSlot: #exports valued: Set newEmpty. "Exports are objects and features provided by the module's code." Module addSlot: #objects valued: Set newEmpty. "These are the non-method objects that the module defines and installs." Module addSlot: #methods valued: Set newEmpty. "These are the closures that the module defines and installs, whether named or dispatched or anonymous." m@(Module traits) initialize "Reset all of the module's attributes." [ m requirements: m requirements newEmpty. m imports: m imports newEmpty. m exports: m exports newEmpty. m objects: m objects newEmpty. m methods: m methods newEmpty. m ]. m@(Module traits) newEmpty [ m clone initialize ]. m@(Module traits) newForFileNamed: filename [ FileModule newForFileNamed: filename ]. m@(Module traits) copy [| newM | newM: m clone. newM requirements: m requirements copy. newM imports: m imports copy. newM exports: m exports copy. newM objects: m objects copy. newM methods: m methods copy. newM ]. m@(Module traits) newBasedOn: moduleSet [| newM | newM: m clone initialize. newM requirements: (moduleSet select: [| :each | each is: Module]). newM ]. m@(Module traits) provide: obj [ "TODO: include some check here to avoid arbitrary provision." m exports include: obj ]. m@(Module traits) provides: obj [ "TODO: do modules automatically export their imports?" m exports includes: obj ]. m@(Module traits) import: obj from: prereq [ (prereq provides: obj) ifTrue: [m requirements include: prereq. m imports include: obj]. m ]. m@(Module traits) importAll: c from: prereq [ c do: [| :each | (prereq provides: each) ifFalse: [^ (prereq error: prereq name ; ' does not provide ' ; (each as: String))]]. m requirements include: prereq. c do: [| :each | m imports include: each]. m ]. m@(Module traits) load "Loads the Module's contents, if external." [overrideThis]. m@(Module traits) build "Compiles the Module's contents, if external." [overrideThis]. prototypes addPrototype: #FileModule derivedFrom: {Module}. "FileModules are Modules which are drastically simplified for the purposes of bootstrapping. Requirements and provisions are symbols, and other features are ignored." FileModule addSlot: #filename valued: ''. m@(FileModule traits) newForFileNamed: filename [| newM | newM: m newEmpty. newM filename: filename. newM ]. m@(FileModule traits) load [ FileStream fileIn: m filename. ]. m@(FileModule traits) build [ compileFileNamed: m filename. ]. m@(FileModule traits) readDefinitions "Reads in a file, building the module's collections while evaluating the contents." "TODO: implement it!" [| input | input: (FileStream newForInputNamed: m filename). input close. m ]. m@(FileModule traits) metaInfoFilename [| basename | basename: (m filename sliceFrom: 0 to: (m filename indexOfSubSeq: '.slate')). basename ; '.module' ]. m@(FileModule traits) writeOutInfo "Writes out a source definition of the Module object described by the given filename." "TODO: implement it!" [| output | output: (FileStream newForOutputNamed: m metaInfoFilename). output ; '[| m |\n'. output ; 'm: Module newForFileNamed: ' ; m filename ; '.\n'. output ; 'm imports: '. m imports printOn: output. output ; '.\n'. output ; 'm exports: '. m exports printOn: output. output ; '.\n'. output ; 'modules include: m.\n'. output ; 'm] value.\n'. output close. m ]. "SourceWriter print: ([| M | M: Module newForFileNamed: (m filename) `unquote. M imports: (m imports) `unquote. M exports: (m exports) `unquote. modules include: M. M] value. ) `quote on: output." m@(FileModule traits) readInInfo "Reads from a source definition of the Module object described by the given filename." "TODO: implement it!" [| input | input: (FileStream newForInputNamed: m metaInfoFilename). input close. m ]. lobby ensureNamespace: #systems. prototypes addPrototype: #System derivedFrom: {Cloneable}. System addSlot: #modules valued: Set newEmpty. s@(System traits) newForAll: modules "Creates a new System object for the given Module objects." [| newS | newS: s clone. newS modules: (modules as: s modules). newS modules do: [| :each | newS fillRequirementsFor: each]. newS ]. s@(System traits) fillRequirementsFor: module "Fills the requirements slot of the module, based on the knowledge that the System has by holding several other Modules, and return the requirements." [| features covered | features: module imports. covered: (Set newSizeOf: features). s modules do: [| :each coverage | coverage: (each exports intersection: features). coverage isEmpty ifFalse: [module requirements include: each. covered includeAll: coverage]]. module requirements ]. s@(System traits) add: module [ s modules include: module. s fillRequirementsFor: module. module ]. s@(System traits) build "Compile the System's modules." [ s modules do: [| :each | each build]. ]. s@(System traits) load "Load the System's modules in a consistent order." [| remaining | remaining: s modules copy. [remaining isEmpty] whileFalse: [remaining do: [| :each | (features includesAllOf: each requirements) ifTrue: [each load. remaining remove: each]]]. ]. s@(System traits) load: module "Loads the given module and recursively re-loads modules that depend upon it." [ module load. s modules do: [| :each | (each dependsOn: module) ifTrue: [s load: each]]. ]. systems addSlot: #Core valued: (System newForAll: globals modules). "This relies on being loaded just after all the standard libraries, and more importantly before other systems."