diff --git a/kernel/Autoload.st b/kernel/Autoload.st index 4097620..20e6a6c 100644 --- a/kernel/Autoload.st +++ b/kernel/Autoload.st @@ -32,10 +32,27 @@ +Kernel.PackageInfo extend [ + autoload [ + + + self fileIn + ] +] + +FilePath extend [ + autoload [ + + + self withReadStreamDo: [:rs | rs fileIn ] + ] +] + Namespace current: Kernel [ nil subclass: AutoloadClass [ - | superClass methodDictionary instanceSpec subClasses instanceVariables environment name fileName | + "Warning: instance variable indices appear below in #class:in:from:" + | superClass methodDictionary instanceSpec subClasses instanceVariables environment name loader | + AutoloadClass class >> class: nameSymbol in: aNamespace loader: aLoader [ + | autoload behavior newClass | + "Create the metaclass and its sole instance" + behavior := Behavior new superclass: Autoload. + + "Turn the metaclass into an instance of AutoloadClass. To do + this we create a `prototype' in the form of an array..." + newClass := Array new: Kernel.AutoloadClass allInstVarNames size. + 1 to: behavior class instSize + do: [:i | newClass at: i put: (behavior instVarAt: i)]. + + newClass + at: 6 put: aNamespace; + at: 7 put: nameSymbol; + at: 8 put: aLoader. + + "... and change its class magically after it is initialized." + newClass changeClassTo: Kernel.AutoloadClass. + + "Now create the instance. We go through some hops because of + the very limited set of messages that these classes know + about." + autoload := behavior new. + behavior become: newClass. + ^autoload + ] + name [ "Answer the name of the class to be autoloaded" @@ -50,13 +94,6 @@ and have the class autoloaded.'> ^name ] - name: aSymbol [ - "Set to aSymbol the name of the class to be autoloaded" - - - name := aSymbol - ] - environment [ "Answer the namespace in which the class will be autoloaded" @@ -64,59 +101,37 @@ and have the class autoloaded.'> ^environment ] - environment: aNamespace [ - "Set to aNamespace the namespace in which the class will be autoloaded" - - - environment := aNamespace - ] - - fileName [ - "Answer the name of the file from which the class will be autoloaded" - - - ^fileName - ] - - fileName: aString [ - "Set to aString the name of the file from which the class will be autoloaded" - - - fileName := aString - ] - doesNotUnderstand: aMessage [ "Load the class and resend the message to its metaclass." - ^aMessage reinvokeFor: self loadedMetaclass + ^aMessage reinvokeFor: self loadedMetaclass_ ] - loadedMetaclass [ + loadedMetaclass_ [ "File-in the file and answer the metaclass for the new value of the association which held the receiver" - ^self loadedClass class + ^self loadedClass_ class ] - loadedClass [ + loadedClass_ [ "File-in the file and answer the new value of the association which held the receiver" - | class file | - self fileName isNil + | class saveLoader | + loader isNil ifFalse: - [file := self fileName. - self fileName: nil. - self environment at: self name put: nil. - FileStream fileIn: file]. - class := self environment at: self name ifAbsent: [nil]. + [saveLoader := loader. + loader := nil. + environment at: name put: nil. + saveLoader autoload]. + class := environment at: name ifAbsent: [nil]. class isNil ifTrue: - [^Autoload error: 'Autoloaded file should have defined class "' , name - , '" but didn''t']. + [^Autoload error: '%1 should have defined class %2.%3 but didn''t' % {saveLoader. environment. name asString}]. ^class ] ] @@ -152,32 +167,24 @@ as #methodsFor: to extend it with class-side methods).'> "Check if the file exists." - | autoload behavior newClass | - (FileDescriptor open: fileNameString mode: FileStream read) close. - - "Create the metaclass and its sole instance" - behavior := Behavior new superclass: Autoload. + | autoload file | + file := fileNameString asFile. + file withReadStreamDo: [ :rs | ]. "Turn the metaclass into an instance of AutoloadClass. To do this we create a `prototype' in the form of an array and then..." - newClass := Array new: Kernel.AutoloadClass allInstVarNames size. - 1 to: behavior class instSize - do: [:i | newClass at: i put: (behavior instVarAt: i)]. + ^self class: nameSymbol in: aNamespace loader: file + ] - "... change its class magically." - newClass changeClassTo: Kernel.AutoloadClass. + Autoload class >> class: nameSymbol in: aNamespace loader: aLoader [ + "Make Smalltalk automatically load the class named nameSymbol + and residing in aNamespace from fileNameString when needed" - "We can now initialize it." - newClass - name: nameSymbol; - fileName: fileNameString; - environment: aNamespace. + + "Check if the file exists." - "Now create the instance. We go through some hops because of - the very limited set of messages that these classes know - about." - autoload := behavior new. - behavior become: newClass. + | autoload file | + autoload := Kernel.AutoloadClass class: nameSymbol in: aNamespace loader: aLoader. ^aNamespace at: nameSymbol put: autoload ] @@ -194,7 +201,7 @@ as #methodsFor: to extend it with class-side methods).'> "Load the class and resend the message to it" - ^aMessage reinvokeFor: self class loadedClass + ^aMessage reinvokeFor: self class loadedClass_ ] ] diff --git a/libgst/files.c b/libgst/files.c index 4b58bbc..535bba2 100644 --- a/libgst/files.c +++ b/libgst/files.c @@ -282,14 +282,14 @@ static const char standard_files[] = { /* Goodies */ "DynVariable.st\0" - "Autoload.st\0" "DLD.st\0" "Getopt.st\0" "Generator.st\0" "StreamOps.st\0" "ObjDumper.st\0" - "PkgLoader.st\0" "Regex.st\0" + "PkgLoader.st\0" + "Autoload.st\0" }; /* The argc and argv that are passed to libgst via gst_smalltalk_args.