Metaclass.st
changeset 68 59faa75185ba
parent 49 f1c2d75f2eb6
child 77 6c38ca59927f
equal deleted inserted replaced
67:e52341804063 68:59faa75185ba
    21 
    21 
    22 COPYRIGHT (c) 1988 by Claus Gittinger
    22 COPYRIGHT (c) 1988 by Claus Gittinger
    23               All Rights Reserved
    23               All Rights Reserved
    24 
    24 
    25 every class-class is a subclass of Metaclass
    25 every class-class is a subclass of Metaclass
    26 - this adds support for creating new subclasses or changing the definition
    26 Metaclass provides support for creating new (sub)classes and/or 
    27 of an already existing class.
    27 changing the definition of an already existing class.
    28 
    28 
    29 $Header: /cvs/stx/stx/libbasic/Metaclass.st,v 1.9 1994-02-05 12:21:45 claus Exp $
    29 $Header: /cvs/stx/stx/libbasic/Metaclass.st,v 1.10 1994-03-30 09:32:39 claus Exp $
    30 '!
    30 '!
    31 
    31 
    32 !Metaclass methodsFor:'creating classes'!
    32 !Metaclass methodsFor:'creating classes'!
    33 
    33 
    34 name:newName inEnvironment:aSystemDictionary
    34 name:newName inEnvironment:aSystemDictionary
    55     |newClass newMetaclass nInstVars nameString classSymbol oldClass 
    55     |newClass newMetaclass nInstVars nameString classSymbol oldClass 
    56      allSubclasses classVarChange instVarChange superClassChange newComment
    56      allSubclasses classVarChange instVarChange superClassChange newComment
    57      changeSet1 changeSet2 offset oldOffsets newOffsets addedNames
    57      changeSet1 changeSet2 offset oldOffsets newOffsets addedNames
    58      anyChange oldInstVars newInstVars oldClassVars newClassVars upd superFlags newFlags|
    58      anyChange oldInstVars newInstVars oldClassVars newClassVars upd superFlags newFlags|
    59 
    59 
    60     "this method is too complex and should be splitted into managable pieces ..."
    60     "NOTICE:
       
    61      this method is too complex and should be splitted into managable pieces ...
       
    62      I dont like it anymore :-)
       
    63     "
    61 
    64 
    62     newName = aClass name ifTrue:[
    65     newName = aClass name ifTrue:[
    63         self error:'trying to create circular class definition'.
    66         self error:'trying to create circular class definition'.
    64         ^ nil
    67         ^ nil
    65     ].
    68     ].
    74     nameString := newName asString.
    77     nameString := newName asString.
    75     classSymbol := newName asSymbol.
    78     classSymbol := newName asSymbol.
    76     newComment := commentString.
    79     newComment := commentString.
    77 
    80 
    78     "look, if it already exists as a class"
    81     "look, if it already exists as a class"
    79     (aSystemDictionary includesKey:classSymbol) ifTrue:[
    82     oldClass := aSystemDictionary at:classSymbol ifAbsent:[nil].
    80         oldClass := aSystemDictionary at:classSymbol.
    83     oldClass isBehavior ifFalse:[
    81         (oldClass isBehavior not or:[oldClass name ~= newName]) ifTrue:[
    84         oldClass := nil.
    82             oldClass := nil.
    85     ] ifTrue:[
    83         ] ifFalse:[
    86         oldClass superclass notNil ifTrue:[
    84             oldClass allSuperclasses do:[:aClass |
    87             oldClass allSuperclasses do:[:cls |
    85                 aClass name = newName ifTrue:[
    88                 cls name = nameString ifTrue:[
       
    89                     self error:'trying to create circular class definition'.
       
    90                     ^ nil
       
    91                 ]
       
    92             ]
       
    93         ].
       
    94 
       
    95         aClass superclass notNil ifTrue:[
       
    96             aClass allSuperclasses do:[:cls |
       
    97                 cls name = nameString ifTrue:[
    86                     self error:'trying to create circular class definition'.
    98                     self error:'trying to create circular class definition'.
    87                     ^ nil
    99                     ^ nil
    88                 ]
   100                 ]
    89             ].
   101             ].
    90 
   102         ].
    91             newComment isNil ifTrue:[
   103 
    92                 newComment := oldClass comment
   104         newComment isNil ifTrue:[
    93             ]
   105             newComment := oldClass comment
    94         ]
   106         ].
    95     ].
   107 
    96 
   108         "
    97     "I dont like the confirmers below - we need a notifying: argument, to give
   109          warn, if it exists with different category and different instvars,
       
   110          and the existing is not an autoload class.
       
   111          Usually, this indicates that someone wants to create a new class with
       
   112          a name, which already exists (it happened a few times to myself, while 
       
   113          I wanted to create a new class called ReturnNode ...).
       
   114          This will be much less of a problem, once multiple name spaces are
       
   115          implemented and classes can be put into separate packages.
       
   116         "
       
   117         oldClass isLoaded ifTrue:[
       
   118             oldClass category ~= categoryString ifTrue:[
       
   119                 oldClass instanceVariableString asCollectionOfWords 
       
   120                 ~= stringOfInstVarNames asCollectionOfWords ifTrue:[
       
   121                     (self confirm:'a class named ' , oldClass name , ' already exists -
       
   122 
       
   123 create (i.e. change) anyway ?' withCRs)
       
   124                     ifFalse:[
       
   125                         ^ nil
       
   126                     ]
       
   127                 ]
       
   128             ]
       
   129         ]
       
   130     ].
       
   131 
       
   132     "
       
   133      Check for some 'considered bad-style' things, like lower case names.
       
   134      But only do these checks for new classes - 
       
   135      - thus, once confirmed, the warnings will not come again and again.
       
   136 
       
   137      NOTICE:
       
   138      I dont like the confirmers below - we need a notifying: argument, to give
    98      the outer codeview a chance to highlight the error.
   139      the outer codeview a chance to highlight the error.
    99      (but thats how PP defined it in the book - maybe it will change anyway"
   140      (but thats how its defined in the book - maybe I will change anyway).
       
   141     "
   100 
   142 
   101     oldClass isNil ifTrue:[
   143     oldClass isNil ifTrue:[
   102         "let user confirm, if the classname is no good"
   144         "let user confirm, if the classname is no good"
   103         newName first isUppercase ifFalse:[
   145         newName first isUppercase ifFalse:[
   104             (self confirm:'classenames should start with an uppercase letter
   146             (self confirm:'classenames should start with an uppercase letter
   105 (by convention)
   147 (by convention only)
   106 
   148 
   107 install anyway ?' withCRs)
   149 install anyway ?' withCRs)
   108                 ifFalse:[
   150                 ifFalse:[
   109                     ^ nil
   151                     ^ nil
   110                 ]
   152                 ]
   147 
   189 
   148     "create the metaclass first"
   190     "create the metaclass first"
   149     newMetaclass := Metaclass new.
   191     newMetaclass := Metaclass new.
   150     newMetaclass setSuperclass:(aClass class).
   192     newMetaclass setSuperclass:(aClass class).
   151     newMetaclass instSize:(aClass class instSize).
   193     newMetaclass instSize:(aClass class instSize).
   152     newMetaclass flags:0.            "not indexed"
       
   153     newMetaclass setName:(nameString , 'class').
   194     newMetaclass setName:(nameString , 'class').
   154     newMetaclass classVariableString:'' "stringOfClassVarNames".
   195     newMetaclass classVariableString:'' "stringOfClassVarNames".
   155     newMetaclass setComment:newComment category:categoryString.
   196     newMetaclass setComment:newComment category:categoryString.
   156 
   197 
       
   198     "the let the meta create the class"
   157     newClass := newMetaclass new.
   199     newClass := newMetaclass new.
   158     newClass setSuperclass:aClass.
   200     newClass setSuperclass:aClass.
   159     newClass instSize:(aClass instSize + nInstVars).
   201     newClass instSize:(aClass instSize + nInstVars).
   160 
   202     newClass setName:nameString.
       
   203 
       
   204     "
       
   205      Allowing non-booleans as variableBoolean
       
   206      is a hack for backward (ST-80) compatibility:
       
   207 
       
   208      ST-80 code will pass true or false as variableBoolean,
       
   209      while ST/X also calls it with symbols such as #float, #double etc.
       
   210     "
   161     (variableBoolean == true) ifTrue:[
   211     (variableBoolean == true) ifTrue:[
   162         pointersBoolean ifTrue:[
   212         pointersBoolean ifTrue:[
   163             newFlags := 4         "pointerarray"
   213             newFlags := Behavior flagPointers
   164         ] ifFalse:[
   214         ] ifFalse:[
   165             wordsBoolean ifTrue:[
   215             wordsBoolean ifTrue:[
   166                 newFlags := 2     "wordarray"
   216                 newFlags := Behavior flagWords
   167             ] ifFalse:[
   217             ] ifFalse:[
   168                 newFlags := 1     "bytearray"
   218                 newFlags := Behavior flagBytes
   169             ]
   219             ]
   170         ]
   220         ]
   171     ] ifFalse:[
   221     ] ifFalse:[
   172         "this is a backward compatible hack"
       
   173 
       
   174         (variableBoolean == #float) ifTrue:[
   222         (variableBoolean == #float) ifTrue:[
   175             newFlags := 6         "float array"
   223             newFlags := Behavior flagFloats
   176         ] ifFalse:[
   224         ] ifFalse:[
   177             (variableBoolean == #double) ifTrue:[
   225             (variableBoolean == #double) ifTrue:[
   178                 newFlags := 7     "double array"
   226                 newFlags := Behavior flagDoubles
   179             ] ifFalse:[
   227             ] ifFalse:[
   180                 (variableBoolean == #long) ifTrue:[
   228                 (variableBoolean == #long) ifTrue:[
   181                     newFlags := 3     "long array"
   229                     newFlags := Behavior flagLongs
   182                 ] ifFalse:[
   230                 ] ifFalse:[
   183                     newFlags := 0   
   231                     newFlags := Behavior flagNotIndexed   
   184                 ]
   232                 ]
   185             ]
   233             ]
   186         ].
   234         ].
   187     ].
   235     ].
   188     superFlags := aClass flags bitAnd:16rFFFF0. "everything except indexed-spec"
   236     superFlags := aClass flags bitAnd:(Behavior maskIndexType bitInvert). "preserve other bits"
   189 
   237     oldClass notNil ifTrue:[
   190     newClass flags:(newFlags bitOr:superFlags). "keep the special bits around"
   238         oldClass isBuiltInClass ifTrue:[
   191 
   239             "
   192     newClass setName:nameString.
   240              special care when redefining Method, Block and other built-in classes,
       
   241              which might have other flag bits ...
       
   242             "
       
   243 
       
   244             newFlags := newFlags bitOr:(oldClass flags bitAnd:(Behavior maskIndexType bitInvert))
       
   245         ]
       
   246     ].
       
   247     newClass flags:(newFlags bitOr:superFlags). "preserve  inherited special bits"
       
   248 
   193     (nInstVars ~~ 0) ifTrue:[
   249     (nInstVars ~~ 0) ifTrue:[
   194         newClass instanceVariableString:stringOfInstVarNames
   250         newClass instanceVariableString:stringOfInstVarNames
   195     ].
   251     ].
   196     oldClass notNil ifTrue:[
   252     oldClass notNil ifTrue:[
   197         "setting first will make new class clear obsolete classvars"
   253         "setting first will make new class clear obsolete classvars"
   198         newClass setClassVariableString:(oldClass classVariableString)
   254         newClass setClassVariableString:(oldClass classVariableString)
   199     ].
   255     ].
   200     newClass classVariableString:stringOfClassVarNames.
   256     newClass classVariableString:stringOfClassVarNames.
   201 
   257 
       
   258     "
       
   259      for new classes, we are almost done here
       
   260     "
   202     oldClass isNil ifTrue:[
   261     oldClass isNil ifTrue:[
   203         self addChangeRecordForClass:newClass.
   262         self addChangeRecordForClass:newClass.
   204 
   263 
   205         commentString notNil ifTrue:[
   264         commentString notNil ifTrue:[
   206             newClass comment:commentString
   265             newClass comment:commentString
   207         ].
   266         ].
       
   267 
   208         aSystemDictionary at:classSymbol put:newClass.
   268         aSystemDictionary at:classSymbol put:newClass.
   209         Smalltalk changed.
   269         aSystemDictionary changed.
   210         ^ newClass
   270         ^ newClass
   211     ].
   271     ].
   212 
   272 
       
   273 
       
   274     "
       
   275      here comes the hard part - we are actually changing the
       
   276      definition of an existing class ....
       
   277      Try hard to get away WITHOUT recompiling, since it makes all
       
   278      compiled code into interpreted ...
       
   279     "
   213 
   280 
   214     oldInstVars := oldClass instanceVariableString asCollectionOfWords.
   281     oldInstVars := oldClass instanceVariableString asCollectionOfWords.
   215     newInstVars := newClass instanceVariableString asCollectionOfWords.
   282     newInstVars := newClass instanceVariableString asCollectionOfWords.
   216     oldClassVars := oldClass classVariableString asCollectionOfWords.
   283     oldClassVars := oldClass classVariableString asCollectionOfWords.
   217     newClassVars := newClass classVariableString asCollectionOfWords.
   284     newClassVars := newClass classVariableString asCollectionOfWords.
   218 
   285 
   219     "if only category/comment has changed, do not recompile .."
   286     "
   220 
   287      we are on the bright side of life, if the instance layout and
       
   288      inheritance do not change.
       
   289      In this case, we can go ahead and patch the class object.
       
   290     "
   221     (oldClass superclass == newClass superclass) ifTrue:[
   291     (oldClass superclass == newClass superclass) ifTrue:[
   222       (oldClass instSize == newClass instSize) ifTrue:[
   292       (oldClass instSize == newClass instSize) ifTrue:[
   223         (oldClass flags == newClass flags) ifTrue:[
   293         (oldClass flags == newClass flags) ifTrue:[
   224           (oldClass name = newClass name) ifTrue:[
   294           (oldClass name = newClass name) ifTrue:[
   225             (oldInstVars = newInstVars) ifTrue:[
   295             (oldInstVars = newInstVars) ifTrue:[
       
   296 
       
   297               (newComment ~= oldClass comment) ifTrue:[
       
   298                   oldClass comment:newComment.        "writes a change-chunk"
       
   299               ]. 
       
   300 
   226               (oldClassVars = newClassVars) ifTrue:[
   301               (oldClassVars = newClassVars) ifTrue:[
       
   302                 "
       
   303                  really no change (just comment and/or category)
       
   304                 "
   227                 anyChange := false.
   305                 anyChange := false.
   228 
       
   229 
   306 
   230                 oldClass instanceVariableString:(newClass instanceVariableString).
   307                 oldClass instanceVariableString:(newClass instanceVariableString).
   231                 oldClass setClassVariableString:(newClass classVariableString).
   308                 oldClass setClassVariableString:(newClass classVariableString).
   232 
   309 
   233                 (newComment ~= oldClass comment) ifTrue:[
       
   234                     oldClass comment:newComment.        "already writes change-chunk"
       
   235                 ]. 
       
   236                 oldClass category ~= categoryString ifTrue:[
   310                 oldClass category ~= categoryString ifTrue:[
   237                     "notify change of organization"
   311                     "notify change of organization"
       
   312 
   238                     oldClass category:categoryString. 
   313                     oldClass category:categoryString. 
   239                     self addChangeRecordForClass:newClass.
   314                     self addChangeRecordForClass:newClass.
   240                     Smalltalk changed
   315                     aSystemDictionary changed
   241                 ].
   316                 ].
   242                 "notify change of class"
   317                 "notify change of class"
   243                 oldClass changed.
   318                 oldClass changed.
   244                 ^ oldClass
   319                 ^ oldClass
   245               ].
   320               ].
   246 
   321 
   247               "when we arrive here, class variables have changed"
   322               "
   248 
   323                when we arrive here, class variables have changed
   249               (newComment ~= oldClass comment) ifTrue:[
   324               "
   250                   oldClass comment:newComment.        "already writes change-chunk"
       
   251               ]. 
       
   252               oldClass category ~= categoryString ifTrue:[
   325               oldClass category ~= categoryString ifTrue:[
   253                   "notify change of organization"
   326                   "notify change of organization"
   254                   oldClass category:categoryString. 
   327                   oldClass category:categoryString. 
   255                   Smalltalk changed
   328                   aSystemDictionary changed
   256               ].
   329               ].
   257 
   330 
       
   331               "
       
   332                set class variable string; 
       
   333                this also updates the set of class variables
       
   334                by creating new / deleting obsolete ones.
       
   335               "
   258               oldClass classVariableString:stringOfClassVarNames.
   336               oldClass classVariableString:stringOfClassVarNames.
   259 
   337 
       
   338               "
       
   339                get the set of changed class variables
       
   340               "
   260               changeSet1 := Set new.
   341               changeSet1 := Set new.
   261               oldClassVars do:[:nm |
   342               oldClassVars do:[:nm |
   262                   (newClassVars includes:nm) ifFalse:[
   343                   (newClassVars includes:nm) ifFalse:[
   263                       changeSet1 add:nm
   344                       changeSet1 add:nm
   264                   ]
   345                   ]
   267                   (oldClassVars includes:nm) ifFalse:[
   348                   (oldClassVars includes:nm) ifFalse:[
   268                       changeSet1 add:nm
   349                       changeSet1 add:nm
   269                   ]
   350                   ]
   270               ].
   351               ].
   271 
   352 
   272               "recompile all methods accessing set of changed classvars
   353               "
   273                here and also in all subclasses ..."
   354                recompile all methods accessing set of changed classvars
   274 
   355                here and also in all subclasses ...
   275               "dont update change file for the recompilation"
   356               "
       
   357 
       
   358               "
       
   359                dont update change file for the recompilation
       
   360               "
   276               upd := Class updateChanges:false.
   361               upd := Class updateChanges:false.
   277 " "
   362               [
   278               Transcript showCr:'recompiling class&inst methods accessing ' , changeSet1 printString.
   363 " "
   279 " "
   364                   Transcript showCr:'recompiling class & inst methods accessing ' , changeSet1 printString.
   280               oldClass withAllSubclasses do:[:aClass |
   365                   Transcript endEntry.
   281                   aClass class recompileMethodsAccessingAny:changeSet1.
   366 " "
   282                   aClass recompileMethodsAccessingAny:changeSet1.
   367                   oldClass withAllSubclasses do:[:aClass |
       
   368                       aClass class recompileMethodsAccessingAny:changeSet1.
       
   369                       aClass recompileMethodsAccessingAny:changeSet1.
       
   370                   ].
       
   371               ] valueNowOrOnUnwindDo:[
       
   372                   Class updateChanges:upd.
   283               ].
   373               ].
   284               Class updateChanges:upd.
       
   285 
   374 
   286               "notify change of class"
   375               "notify change of class"
   287               self addChangeRecordForClass:oldClass.
   376               self addChangeRecordForClass:oldClass.
   288               oldClass changed.
   377               oldClass changed.
   289 
   378 
   292           ]
   381           ]
   293         ]
   382         ]
   294       ]
   383       ]
   295     ].
   384     ].
   296 
   385 
   297     "tell dependents of class ..."
   386     "tell dependents ..."
       
   387 "OLD:
   298     oldClass changed.
   388     oldClass changed.
   299 
   389 "
   300     "catch special case, where superclass changed its layout and thus
   390 
   301      forced redefinition of this class - this will not be logged here"
   391 
       
   392     "
       
   393      here we enter the darkness of mordor ...
       
   394     "
   302 
   395 
   303     (newComment ~= oldClass comment) ifTrue:[
   396     (newComment ~= oldClass comment) ifTrue:[
   304         newClass comment:newComment
   397         newClass comment:newComment
   305     ].
   398     ].
   306 
   399 
   307     superClassChange := oldClass superclass ~~ newClass superclass.
   400     superClassChange := oldClass superclass ~~ newClass superclass.
   308 
   401 
   309     "dont allow built-in classes to be modified"
   402     "
       
   403      dont allow built-in classes to be modified this way
       
   404     "
   310     (oldClass notNil and:[oldClass isBuiltInClass and:[superClassChange]]) ifTrue:[
   405     (oldClass notNil and:[oldClass isBuiltInClass and:[superClassChange]]) ifTrue:[
   311         self error:'the inheritance of this class is fixed - you cannot change it'.
   406         self error:'the inheritance of this class is fixed - you cannot change it'.
   312         ^ oldClass
   407         ^ oldClass
   313     ].
   408     ].
   314 
   409 
       
   410     "
       
   411      catch special case, where superclass changed its layout and thus
       
   412      forced redefinition of this class; 
       
   413      only log if this is not the case.
       
   414     "
   315     (superClassChange 
   415     (superClassChange 
   316      and:[(oldClass superclass isNil or:[oldClass superclass name = newClass superclass name])
   416      and:[(oldClass superclass isNil or:[oldClass superclass name = newClass superclass name])
   317      and:[(oldClassVars = newClassVars) 
   417      and:[(oldClassVars = newClassVars) 
   318      and:[(oldInstVars = newInstVars)
   418      and:[(oldInstVars = newInstVars)
   319      and:[newComment = oldClass comment]]]]) ifFalse:[
   419      and:[newComment = oldClass comment]]]]) ifFalse:[
   320         self addChangeRecordForClass:newClass.
   420         self addChangeRecordForClass:newClass.
   321     ].
   421     ].
   322 
   422 
       
   423     "
       
   424      care for class methods ...
       
   425     "
   323     changeSet1 := Set new.
   426     changeSet1 := Set new.
   324     changeSet2 := Set new.
       
   325 
   427 
   326     classVarChange := false.
   428     classVarChange := false.
   327 
   429 
   328     superClassChange ifTrue:[
   430     superClassChange ifTrue:[
   329         "superclass changed,
   431         "
   330          must recompile all class methods accessing any classvar"
   432          superclass changed:
       
   433          must recompile all class methods accessing ANY classvar
       
   434          (
       
   435           actually, we could be less strict and handle the case where
       
   436           both the old and the new superclass have a common ancestor,
       
   437           and both have no new classvariables in between.
       
   438           This would speedup the case when a class is inserted into
       
   439           the inheritance chain.
       
   440          )
       
   441         "
   331 
   442 
   332         oldClass allClassVarNames do:[:nm | changeSet1 add:nm].
   443         oldClass allClassVarNames do:[:nm | changeSet1 add:nm].
   333         newClass allClassVarNames do:[:nm | changeSet1 add:nm].
   444         newClass allClassVarNames do:[:nm | changeSet1 add:nm].
   334 
   445 
   335 " "
   446 " "
   336         Transcript showCr:'recompiling class methods accessing any classvar'.
   447         Transcript showCr:'recompiling class methods accessing any classvar'.
       
   448         Transcript endEntry.
   337 " "
   449 " "
   338         self copyInvalidatedMethodsFrom:(oldClass class) for:newMetaclass accessingAny:changeSet1.
   450         self copyInvalidatedMethodsFrom:(oldClass class) for:newMetaclass accessingAny:changeSet1.
   339         newMetaclass recompileInvalidatedMethods.
   451         newMetaclass recompileInvalidatedMethods.
   340     ] ifFalse:[
   452     ] ifFalse:[
   341         "same superclass, find out which classvars have changed"
   453         "
   342 
   454          same superclass, find out which classvars have changed
       
   455         "
   343         classVarChange := oldClassVars ~= newClassVars.
   456         classVarChange := oldClassVars ~= newClassVars.
   344         classVarChange ifTrue:[
   457         classVarChange ifTrue:[
   345             oldClassVars do:[:nm |
   458             oldClassVars do:[:nm |
   346                 (newClassVars includes:nm) ifFalse:[
   459                 (newClassVars includes:nm) ifFalse:[
   347                     changeSet1 add:nm
   460                     changeSet1 add:nm
   352                     changeSet1 add:nm
   465                     changeSet1 add:nm
   353                 ]
   466                 ]
   354             ].
   467             ].
   355         ].
   468         ].
   356 
   469 
   357 " "
       
   358         Transcript showCr:'recompiling class methods accessing ' , changeSet1 printString.
       
   359 " "
       
   360         classVarChange ifTrue:[
   470         classVarChange ifTrue:[
   361             "must recompile class-methods"
   471             "
       
   472              must recompile some class-methods
       
   473             "
       
   474 " "
       
   475             Transcript showCr:'recompiling class methods accessing ' , changeSet1 printString.
       
   476             Transcript endEntry.
       
   477 " "
   362             self copyInvalidatedMethodsFrom:(oldClass class) for:newMetaclass accessingAny:changeSet1.
   478             self copyInvalidatedMethodsFrom:(oldClass class) for:newMetaclass accessingAny:changeSet1.
   363             newMetaclass recompileInvalidatedMethods.
   479             newMetaclass recompileInvalidatedMethods.
   364         ] ifFalse:[
   480         ] ifFalse:[
   365             "class methods still work"
   481             "
       
   482              class methods still work
       
   483             "
   366             self copyMethodsFrom:(oldClass class) for:newMetaclass
   484             self copyMethodsFrom:(oldClass class) for:newMetaclass
   367         ].
   485         ].
   368     ].
   486     ].
       
   487 
       
   488     "
       
   489      care for instance methods ...
       
   490     "
       
   491     changeSet2 := Set new.
   369 
   492 
   370     superClassChange ifTrue:[
   493     superClassChange ifTrue:[
   371         "superclass changed,
   494         "superclass changed,
   372          must recompile all class methods accessing any class or instvar"
   495          must recompile all methods accessing any class or instvar.
   373 
   496          If number of instvars (i.e. the instances instSize) is the same,
   374         "no, if number of instvars is the same, only the changed ones ..."
   497          we can limit the set of recompiled instance methods to those methods,
   375 
   498          which refer to an instvar with a different inst-index
   376         "find set of changed instvars"
   499         "
   377 
   500 
       
   501         "
       
   502          collect the instvar-indices in the old and new class
       
   503         "
   378         offset := 0. oldOffsets := Dictionary new.
   504         offset := 0. oldOffsets := Dictionary new.
   379         oldClass allInstVarNames do:[:nm | offset := offset + 1. oldOffsets at:nm put:offset].
   505         oldClass allInstVarNames do:[:nm | offset := offset + 1. oldOffsets at:nm put:offset].
   380         offset := 0. newOffsets := Dictionary new.
   506         offset := 0. newOffsets := Dictionary new.
   381         newClass allInstVarNames do:[:nm | offset := offset + 1. newOffsets at:nm put:offset].
   507         newClass allInstVarNames do:[:nm | offset := offset + 1. newOffsets at:nm put:offset].
   382 
   508 
       
   509         "
       
   510          the changeset consists of instance variables, 
       
   511          whith a different position
       
   512         "
   383         oldOffsets associationsDo:[:a |
   513         oldOffsets associationsDo:[:a |
   384             |k|
   514             |k|
   385 
   515 
   386             k := a key.
   516             k := a key.
   387             (newOffsets includesKey:k) ifFalse:[
   517             (newOffsets includesKey:k) ifFalse:[
   403                     changeSet2 add:k
   533                     changeSet2 add:k
   404                 ]
   534                 ]
   405             ]
   535             ]
   406         ].
   536         ].
   407 
   537 
       
   538         "
       
   539          merge in the changed class variables
       
   540         "
   408         changeSet1 do:[:nm | changeSet2 add:nm].
   541         changeSet1 do:[:nm | changeSet2 add:nm].
   409 " "
   542 
   410         Transcript showCr:'recompiling instance methods accessing ' , changeSet2 printString , '
   543 " "
   411  ...'.
   544         Transcript showCr:'recompiling instance methods accessing ' , changeSet2 printString , ' ...'.
       
   545         Transcript endEntry.
   412 " "
   546 " "
   413         self copyInvalidatedMethodsFrom:oldClass for:newClass accessingAny:changeSet2.
   547         self copyInvalidatedMethodsFrom:oldClass for:newClass accessingAny:changeSet2.
   414         newClass recompileInvalidatedMethods.
   548         newClass recompileInvalidatedMethods.
   415 
   549 
   416 false ifTrue:[
       
   417         oldClass allClassVarNames do:[:nm | changeSet1 add:nm].
       
   418         newClass allClassVarNames do:[:nm | changeSet1 add:nm].
       
   419         oldClass allInstVarNames do:[:nm | changeSet1 add:nm].
       
   420         newClass allInstVarNames do:[:nm | changeSet1 add:nm].
       
   421 
       
   422 " "
       
   423         Transcript showCr:'recompiling instance methods accessing any class or instvar' .
       
   424 " "
       
   425         self copyInvalidatedMethodsFrom:oldClass for:newClass accessingAny:changeSet1.
       
   426         newClass recompileInvalidatedMethods.
       
   427 ]
       
   428     ] ifFalse:[
   550     ] ifFalse:[
       
   551         "
       
   552          same inheritance ...
       
   553         "
   429         instVarChange := oldInstVars ~= newInstVars.
   554         instVarChange := oldInstVars ~= newInstVars.
   430         instVarChange ifFalse:[
   555         instVarChange ifFalse:[
       
   556             "
       
   557              same instance variables ...
       
   558             "
   431             classVarChange ifTrue:[
   559             classVarChange ifTrue:[
   432                 "recompile all inst methods accessing classvars"
   560                 "recompile all inst methods accessing changed classvars"
   433 
   561 
   434 " "
   562 " "
   435                 Transcript showCr:'recompiling instance methods accessing ' , changeSet1 printString , ' ...'.
   563                 Transcript showCr:'recompiling instance methods accessing ' , changeSet1 printString , ' ...'.
       
   564                 Transcript endEntry.
   436 " "
   565 " "
   437                 self copyInvalidatedMethodsFrom:oldClass for:newClass accessingAny:changeSet1.
   566                 self copyInvalidatedMethodsFrom:oldClass for:newClass accessingAny:changeSet1.
   438                 newClass recompileInvalidatedMethods.
   567                 newClass recompileInvalidatedMethods.
   439             ]
   568             ]
   440         ] ifTrue:[
   569         ] ifTrue:[
   441             instVarChange := (oldInstVars ~= newInstVars).
   570             "
   442 
   571              dont allow built-in classes to be modified
   443             "dont allow built-in classes to be modified"
   572             "
   444             (oldClass notNil and:[oldClass isBuiltInClass and:[instVarChange]]) ifTrue:[
   573             (oldClass notNil and:[oldClass isBuiltInClass and:[instVarChange]]) ifTrue:[
   445                 self error:'the layout of this class is fixed - you cannot change it'.
   574                 self error:'the layout of this class is fixed - you cannot change it'.
   446                 ^ oldClass
   575                 ^ oldClass
   447             ].
   576             ].
   448 
   577 
   449             instVarChange ifTrue:[
   578             ((oldInstVars size == 0) 
   450 
   579             or:[newInstVars startsWith:oldInstVars]) ifTrue:[
   451                 ((oldInstVars size == 0) 
   580                 "
   452                 or:[newInstVars startsWith:oldInstVars]) ifTrue:[
   581                  only new inst variable(s) has/have been added - 
   453                     "new variable(s) has/have been added - old methods still work"
   582                  old methods still work (the existing inst-indices are still valid)
   454 
   583                 "
   455                     Transcript showCr:'copying methods ...'.
   584 " "
   456                     self copyMethodsFrom:oldClass for:newClass.
   585                 Transcript showCr:'copying methods ...'.
   457 
   586                 Transcript endEntry.
   458                     "but have to recompile methods accessing stuff now defined
   587 " "
   459                      (it might have been a global before ...)"
   588                 self copyMethodsFrom:oldClass for:newClass.
   460 
   589 
   461                     addedNames := newInstVars select:[:nm | (oldInstVars includes:nm) not].
   590                 "
   462                     changeSet1 do:[:nm | addedNames add:nm].
   591                  but: we have to recompile all methods accessing new instars
   463 
   592                  (it might have been a classVar/global before ...)
   464 " "
   593                 "
   465                     Transcript showCr:'recompiling instance methods accessing ' , addedNames printString ,  '...'.
   594                 addedNames := newInstVars select:[:nm | (oldInstVars includes:nm) not].
   466 " "
   595                 "merge in class variables"
   467                     newClass recompileMethodsAccessingAny:addedNames.
   596                 changeSet1 do:[:nm | addedNames add:nm].
   468                 ] ifFalse:[
   597 
   469                     "find set of changed instvars"
   598 " "
   470 
   599                 Transcript showCr:'recompiling instance methods accessing ' , addedNames printString ,  '...'.
   471                     offset := 0. oldOffsets := Dictionary new.
   600                 Transcript endEntry.
   472                     oldInstVars do:[:nm | offset := offset + 1. oldOffsets at:nm put:offset].
   601 " "
   473                     offset := 0. newOffsets := Dictionary new.
   602                 newClass recompileMethodsAccessingAny:addedNames.
   474                     newInstVars do:[:nm | offset := offset + 1. newOffsets at:nm put:offset].
   603             ] ifFalse:[
   475 
   604                 "
   476                     oldOffsets associationsDo:[:a |
   605                  collect the instvar-indices in the old and new class
   477                         |k|
   606                 "
   478 
   607                 offset := 0. oldOffsets := Dictionary new.
   479                         k := a key.
   608                 oldInstVars do:[:nm | offset := offset + 1. oldOffsets at:nm put:offset].
   480                         (newOffsets includesKey:k) ifFalse:[
   609                 offset := 0. newOffsets := Dictionary new.
       
   610                 newInstVars do:[:nm | offset := offset + 1. newOffsets at:nm put:offset].
       
   611 
       
   612                 "
       
   613                  the changeset consists of instance variables, 
       
   614                  whith a different position
       
   615                 "
       
   616                 oldOffsets associationsDo:[:a |
       
   617                     |k|
       
   618 
       
   619                     k := a key.
       
   620                     (newOffsets includesKey:k) ifFalse:[
       
   621                         changeSet2 add:k
       
   622                     ] ifTrue:[
       
   623                         (a value ~~ (newOffsets at:k)) ifTrue:[
   481                             changeSet2 add:k
   624                             changeSet2 add:k
   482                         ] ifTrue:[
       
   483                             (a value ~~ (newOffsets at:k)) ifTrue:[
       
   484                                 changeSet2 add:k
       
   485                             ]
       
   486                         ]
   625                         ]
   487                     ].
   626                     ]
   488                     newOffsets associationsDo:[:a |
   627                 ].
   489                         |k|
   628                 newOffsets associationsDo:[:a |
   490 
   629                     |k|
   491                         k := a key.
   630 
   492                         (oldOffsets includesKey:k) ifFalse:[
   631                     k := a key.
       
   632                     (oldOffsets includesKey:k) ifFalse:[
       
   633                         changeSet2 add:k
       
   634                     ] ifTrue:[
       
   635                         (a value ~~ (oldOffsets at:k)) ifTrue:[
   493                             changeSet2 add:k
   636                             changeSet2 add:k
   494                         ] ifTrue:[
       
   495                             (a value ~~ (oldOffsets at:k)) ifTrue:[
       
   496                                 changeSet2 add:k
       
   497                             ]
       
   498                         ]
   637                         ]
   499                     ].
   638                     ]
   500 
       
   501                     changeSet1 do:[:nm | changeSet2 add:nm].
       
   502 " "
       
   503                     Transcript showCr:'recompiling instance methods accessing ' , changeSet2 printString , ' ...'.
       
   504 " "
       
   505                     self copyInvalidatedMethodsFrom:oldClass for:newClass accessingAny:changeSet2.
       
   506                     newClass recompileInvalidatedMethods.
       
   507 
       
   508                 ].
   639                 ].
       
   640                 "merge in class variables"
       
   641                 changeSet1 do:[:nm | changeSet2 add:nm].
       
   642 " "
       
   643                 Transcript showCr:'recompiling instance methods accessing ' , changeSet2 printString , ' ...'.
       
   644                 Transcript endEntry.
       
   645 " "
       
   646                 self copyInvalidatedMethodsFrom:oldClass for:newClass accessingAny:changeSet2.
       
   647                 newClass recompileInvalidatedMethods.
   509             ].
   648             ].
   510         ].
   649         ].
   511     ].
   650     ].
   512 
   651 
   513     "get list of all subclasses - do before superclass is changed"
   652     "
   514 
   653      WOW, everything done for this class
       
   654      what about subclasses ?
       
   655     "
       
   656 
       
   657     "
       
   658      get list of all subclasses - do this before superclass is changed
       
   659     "
       
   660 "no longer needed"
       
   661 "
   515     allSubclasses := oldClass allSubclasses.
   662     allSubclasses := oldClass allSubclasses.
   516 
   663 "
   517     "update superclass of immediate subclasses - this forces recompilation if needed"
   664 
   518 
   665     "
   519     "dont update change file for the subclass changes"
   666      update superclass of immediate subclasses - 
       
   667      this forces recompilation (recursively) if needed
       
   668      (dont update change file for the subclass changes)
       
   669     "
   520     upd := Class updateChanges:false.
   670     upd := Class updateChanges:false.
   521     [
   671     [
   522         oldClass subclassesDo:[:aClass |
   672         oldClass subclassesDo:[:aClass |
   523 " "
   673 " "
   524             Transcript showCr:'changing superclass of:' , aClass name.
   674             Transcript showCr:'changing superclass of:' , aClass name.
       
   675             Transcript endEntry.
   525 " "
   676 " "
   526             aClass superclass:newClass
   677             aClass superclass:newClass
   527         ]
   678         ]
   528     ] valueNowOrOnUnwindDo:[
   679     ] valueNowOrOnUnwindDo:[
   529         Class updateChanges:upd.
   680         Class updateChanges:upd.
   530     ].
   681     ].
   531 
   682 
       
   683     "
       
   684      change category in oldClass - so we see immediately what it is ...
       
   685     "
       
   686     oldClass category:'obsolete'.
       
   687     oldClass class category:'obsolete'.
       
   688 
       
   689     "
       
   690      and make the new class globally known
       
   691     "
   532     aSystemDictionary at:classSymbol put:newClass.
   692     aSystemDictionary at:classSymbol put:newClass.
       
   693 
       
   694     oldClass category ~= categoryString ifTrue:[
       
   695         "notify change of organization"
       
   696         aSystemDictionary changed
       
   697     ].
       
   698 
       
   699     "
       
   700      Not becoming the old class creates some update problems;
       
   701      the browsers must check carefully - a simple identity compare is
       
   702      not enought ...
       
   703      QUESTION: is this a good idea ?
       
   704     "
       
   705 
       
   706     newClass dependents:(oldClass dependents).
       
   707     newClass changed.
       
   708 
       
   709     "just to make certain ..."
       
   710     oldClass changed.
       
   711 
   533     ObjectMemory flushCaches.
   712     ObjectMemory flushCaches.
       
   713 
   534     ^ newClass
   714     ^ newClass
   535 !
   715 !
   536 
   716 
   537 new
   717 new
   538     "create & return a new metaclass (a classes class)"
   718     "create & return a new metaclass (a classes class)"
   559      allSubclasses t oldVars
   739      allSubclasses t oldVars
   560      oldNames newNames addedNames
   740      oldNames newNames addedNames
   561      oldOffsets newOffsets offset changeSet delta
   741      oldOffsets newOffsets offset changeSet delta
   562      oldToNew newSubMeta newSub oldSubMeta oldSuper|
   742      oldToNew newSubMeta newSub oldSubMeta oldSuper|
   563 
   743 
   564     "cleanup needed here: extract common things with name:inEnvironment:...
   744     "
   565      and structure things ... currently way too complex."
   745      cleanup needed here: extract common things with name:inEnvironment:...
       
   746      and restructure things ... currently way too complex.
       
   747     "
   566 
   748 
   567     oldVars := self instanceVariableString.
   749     oldVars := self instanceVariableString.
   568     aString = oldVars ifTrue:[
   750     aString = oldVars ifTrue:[
   569 "
   751 "
   570         Transcript showCr:'no change (', oldVars , ') -> (', aString , ')'.
   752         Transcript showCr:'no change (', oldVars , ') -> (', aString , ')'.
   582         "no real change (just formatting)"
   764         "no real change (just formatting)"
   583         self instanceVariableString:aString.
   765         self instanceVariableString:aString.
   584         ^ self
   766         ^ self
   585     ]. 
   767     ]. 
   586 
   768 
   587     "let user confirm, if any name is no good (and was good before)"
   769     "
       
   770      let user confirm, if any name is no good (and was good before)
       
   771     "
   588     (oldNames inject:true
   772     (oldNames inject:true
   589                into:[:okSoFar :word |
   773                 into:[:okSoFar :word |
   590                          okSoFar and:[word first isUppercase]
   774                          okSoFar and:[word first isUppercase]
   591                      ])
   775                      ])
   592     ifTrue:[
   776     ifTrue:[
   593         "was ok before"
   777         "was ok before"
   594         (newNames inject:true
   778         (newNames inject:true
   595                    into:[:okSoFar :word |
   779                     into:[:okSoFar :word |
   596                              okSoFar and:[word first isUppercase]
   780                              okSoFar and:[word first isUppercase]
   597                          ])
   781                          ])
   598         ifFalse:[
   782         ifFalse:[
   599             (self confirm:'class instance variable names should start with an uppercase letter
   783             (self confirm:'class instance variable names should start with an uppercase letter
   600 (by convention only)
   784 (by convention only)
   678 
   862 
   679     ((oldNames size == 0) 
   863     ((oldNames size == 0) 
   680     or:[newNames startsWith:oldNames]) ifTrue:[
   864     or:[newNames startsWith:oldNames]) ifTrue:[
   681         "new variable(s) has/have been added - old methods still work"
   865         "new variable(s) has/have been added - old methods still work"
   682 
   866 
       
   867 " "
   683         Transcript showCr:'copying methods ...'.
   868         Transcript showCr:'copying methods ...'.
       
   869         Transcript endEntry.
       
   870 " "
   684         self copyMethodsFrom:self for:newMetaclass.
   871         self copyMethodsFrom:self for:newMetaclass.
   685         self copyMethodsFrom:oldClass for:newClass.
   872         self copyMethodsFrom:oldClass for:newClass.
   686 
   873 
   687         "but have to recompile methods accessing stuff now defined
   874         "but have to recompile methods accessing stuff now defined
   688          (it might have been a global before ...)"
   875          (it might have been a global before ...)"
   689 
   876 
   690         addedNames := newNames select:[:nm | (oldNames includes:nm) not].
   877         addedNames := newNames select:[:nm | (oldNames includes:nm) not].
   691 "
   878 "
   692         Transcript showCr:'recompiling methods accessing ' , 
   879         Transcript showCr:'recompiling methods accessing ' , addedNames printString ,  '...'.
   693                           addedNames printString ,  '...'.
   880         Transcript endEntry.
   694 "
   881 "
   695         "recompile class-methods"
   882         "recompile class-methods"
   696         newMetaclass recompileMethodsAccessingAny:addedNames.
   883         newMetaclass recompileMethodsAccessingAny:addedNames.
   697     ] ifFalse:[
   884     ] ifFalse:[
   698 "
   885 "
   699         Transcript showCr:'recompiling methods accessing ' ,
   886         Transcript showCr:'recompiling methods accessing ' , changeSet printString , ' ...'.
   700                           changeSet printString , ' ...'.
   887         Transcript endEntry.
   701 "
   888 "
   702         "recompile class-methods"
   889         "recompile class-methods"
   703         self copyInvalidatedMethodsFrom:self for:newMetaclass accessingAny:changeSet.
   890         self copyInvalidatedMethodsFrom:self for:newMetaclass accessingAny:changeSet.
   704         newMetaclass recompileInvalidatedMethods.
   891         newMetaclass recompileInvalidatedMethods.
   705 
   892 
   706         self copyMethodsFrom:oldClass for:newClass.
   893         self copyMethodsFrom:oldClass for:newClass.
   707     ].
   894     ].
   708 
   895 
   709     delta := newNames size - oldNames size.
   896     delta := newNames size - oldNames size.
   710 
   897 
   711     "get list of all subclasses - do before superclass is changed"
   898     "
   712 
   899      get list of all subclasses - do before superclass is changed
       
   900     "
   713     allSubclasses := oldClass allSubclasses.
   901     allSubclasses := oldClass allSubclasses.
   714     allSubclasses := allSubclasses asSortedCollection:[:a :b |
   902     allSubclasses := allSubclasses asSortedCollection:[:a :b |
   715                                 b isSubclassOf:a
   903                                 b isSubclassOf:a
   716                      ].
   904                      ].
   717 
   905 
   740         oldSuper == oldClass ifTrue:[
   928         oldSuper == oldClass ifTrue:[
   741             newSub setSuperclass:newClass.
   929             newSub setSuperclass:newClass.
   742         ] ifFalse:[
   930         ] ifFalse:[
   743             newSub setSuperclass:(oldToNew at:oldSuper).
   931             newSub setSuperclass:(oldToNew at:oldSuper).
   744         ].
   932         ].
   745         newSub setSelectors:(aSubclass selectors).
   933         newSub setSelectors:(aSubclass selectorArray).
   746         newSub setMethodDictionary:(aSubclass methodDictionary).
   934         newSub setMethodDictionary:(aSubclass methodArray).
   747         newSub setName:(aSubclass name).
   935         newSub setName:(aSubclass name).
   748         newSub classVariableString:(aSubclass classVariableString).
   936         newSub classVariableString:(aSubclass classVariableString).
   749         newSub setComment:(aSubclass comment).
   937         newSub setComment:(aSubclass comment).
   750         newSub category:(aSubclass category).
   938         newSub category:(aSubclass category).
   751 
   939 
   752         oldToNew at:aSubclass put:newSub.
   940         oldToNew at:aSubclass put:newSub.
   753 
   941 
       
   942 "
   754         aSubclass setName:(aSubclass name , '-old').
   943         aSubclass setName:(aSubclass name , '-old').
   755         aSubclass category:'obsolete classes'
   944         aSubclass category:'obsolete classes'
       
   945 "
       
   946         aSubclass category:'obsolete'.
       
   947         aSubclass class category:'obsolete'.
   756     ].
   948     ].
   757 
   949 
   758     "recompile what needs to be"
   950     "recompile what needs to be"
   759 
   951 
   760     delta == 0 ifTrue:[
   952     delta == 0 ifTrue:[
   761         "only have to recompile class methods accessing 
   953         "only have to recompile class methods accessing 
   762          class instvars from changeset"
   954          class instvars from changeset
       
   955         "
   763 
   956 
   764         allSubclasses do:[:aClass |
   957         allSubclasses do:[:aClass |
   765             aClass class recompileMethodsAccessingAny:changeSet.
   958             aClass class recompileMethodsAccessingAny:changeSet.
   766         ]
   959         ]
   767     ] ifFalse:[
   960     ] ifFalse:[
   768         "have to recompile all class methods accessing class instvars"
   961         "
       
   962          have to recompile all class methods accessing class instvars
       
   963         "
   769 
   964 
   770         allSubclasses do:[:aClass |
   965         allSubclasses do:[:aClass |
   771             |classInstVars|
   966             |classInstVars|
   772 
   967 
   773             classInstVars := aClass class allInstVarNames.
   968             classInstVars := aClass class allInstVarNames.
   784     allSubclasses do:[:aClass |
   979     allSubclasses do:[:aClass |
   785         Smalltalk at:(oldToNew at:aClass) name asSymbol put:(oldToNew at:aClass).
   980         Smalltalk at:(oldToNew at:aClass) name asSymbol put:(oldToNew at:aClass).
   786         ObjectMemory flushCachesFor:aClass.
   981         ObjectMemory flushCachesFor:aClass.
   787     ].
   982     ].
   788 
   983 
   789     "tell dependents of class ..."
   984     "tell dependents ..."
   790 
   985 
   791     oldClass changed.
   986     oldClass changed.
   792     self changed.
   987     self changed.
       
   988 
   793     ^ newMetaclass
   989     ^ newMetaclass
   794 ! !
   990 ! !
   795 
   991 
   796 !Metaclass methodsFor:'queries'!
   992 !Metaclass methodsFor:'queries'!
   797 
   993 
   802     ^ true
   998     ^ true
   803 ! !
   999 ! !
   804 
  1000 
   805 !Metaclass methodsFor:'private'!
  1001 !Metaclass methodsFor:'private'!
   806 
  1002 
       
  1003 invalidMethod
       
  1004     "When recompiling classes after a definition-change, all
       
  1005      uncompilable methods will be bound to this method here,
       
  1006      so that evaluating such an uncompilable method will trigger an error.
       
  1007      Can also happen when Compiler/runtime system is broken."
       
  1008 
       
  1009     self error:'invalid method - this method failed to compile when the class was changed'
       
  1010 !
       
  1011 
   807 copyMethodsFrom:oldClass for:newClass
  1012 copyMethodsFrom:oldClass for:newClass
   808     "when a class has changed, but metaclass is unaffected (i.e. classVars
  1013     "when a class has changed, but metaclass is unaffected (i.e. classVars
   809      have not changed) there is no need to recompile them"
  1014      have not changed) there is no need to recompile them"
   810 
  1015 
   811     newClass selectors:(oldClass selectors copy) methods:(oldClass methodDictionary copy)
  1016     newClass selectors:(oldClass selectorArray copy) 
       
  1017                methods:(oldClass methodArray copy)
   812 !
  1018 !
   813 
  1019 
   814 copyInvalidatedMethodsFrom:oldClass for:newClass
  1020 copyInvalidatedMethodsFrom:oldClass for:newClass
   815     "when a class has been changed, copy all old methods into the new class
  1021     "when a class has been changed, copy all old methods into the new class
   816      - changing code to a trap method giving an error message;
  1022      - changing code to a trap method giving an error message;
   817      this allows us to keep the source while trapping uncompilable (due to
  1023      this allows us to keep the source while trapping uncompilable (due to
   818      now undefined instvars) methods"
  1024      now undefined instvars) methods"
   819 
  1025 
   820     |trap trapCode trapByteCode newMethod oldMethodArray newMethodArray|
  1026     |trap trapCode trapByteCode newMethod oldMethodArray newMethodArray|
   821 
  1027 
   822     trap := Method compiledMethodAt:#invalidMethod.
  1028     trap := Metaclass compiledMethodAt:#invalidMethod.
   823     trapCode := trap code.
  1029     trapCode := trap code.
   824     trapByteCode := trap byteCode.
  1030     trapByteCode := trap byteCode.
   825 
  1031 
   826     oldMethodArray := oldClass methodDictionary.
  1032     oldMethodArray := oldClass methodArray.
   827     newMethodArray := Array new:(oldMethodArray size).
  1033     newMethodArray := Array new:(oldMethodArray size).
   828     newClass selectors:(oldClass selectors copy) methods:newMethodArray.
  1034     newClass selectors:(oldClass selectorArray copy) 
       
  1035                methods:newMethodArray.
   829     1 to:oldMethodArray size do:[:i |
  1036     1 to:oldMethodArray size do:[:i |
   830         newMethod := (oldMethodArray at:i) copy.
  1037         newMethod := (oldMethodArray at:i) copy.
   831         newMethod code:trapCode.
  1038         newMethod code:trapCode.
   832         newMethod literals:nil.
  1039         newMethod literals:nil.
   833         newMethod byteCode:trapByteCode.
  1040         newMethod byteCode:trapByteCode.
   840      a variable in setOfNames will be copied as invalid method, leading to
  1047      a variable in setOfNames will be copied as invalid method, leading to
   841      a trap when its executed."
  1048      a trap when its executed."
   842 
  1049 
   843     |trap trapCode trapByteCode p oldMethod newMethod oldMethodArray newMethodArray|
  1050     |trap trapCode trapByteCode p oldMethod newMethod oldMethodArray newMethodArray|
   844 
  1051 
   845     trap := Method compiledMethodAt:#invalidMethod.
  1052     trap := Metaclass compiledMethodAt:#invalidMethod.
   846     trapCode := trap code.
  1053     trapCode := trap code.
   847     trapByteCode := trap byteCode.
  1054     trapByteCode := trap byteCode.
   848 
  1055 
   849     oldMethodArray := oldClass methodDictionary.
  1056     oldMethodArray := oldClass methodArray.
   850     newMethodArray := Array new:(oldMethodArray size).
  1057     newMethodArray := Array new:(oldMethodArray size).
   851     newClass selectors:(oldClass selectors copy) methods:newMethodArray.
  1058     newClass selectors:(oldClass selectorArray copy) 
       
  1059                methods:newMethodArray.
   852     1 to:oldMethodArray size do:[:i |
  1060     1 to:oldMethodArray size do:[:i |
   853         oldMethod := oldMethodArray at:i.
  1061         oldMethod := oldMethodArray at:i.
   854         p := Parser parseMethod:(oldMethod source) in:newClass.
  1062         p := Parser parseMethod:(oldMethod source) in:newClass.
   855         (p isNil or:[p usedVars notNil and:[p usedVars includesAny:setOfNames]]) ifTrue:[
  1063         (p isNil or:[p usedVars notNil and:[p usedVars includesAny:setOfNames]]) ifTrue:[
   856             newMethod := oldMethod copy.
  1064             newMethod := oldMethod copy.
   867 anyInvalidatedMethodsIn:aClass
  1075 anyInvalidatedMethodsIn:aClass
   868     "return true, if aClass has any invalidated methods in it"
  1076     "return true, if aClass has any invalidated methods in it"
   869 
  1077 
   870     |trap trapCode trapByteCode|
  1078     |trap trapCode trapByteCode|
   871 
  1079 
   872     trap := Method compiledMethodAt:#invalidMethod.
  1080     trap := Metaclass compiledMethodAt:#invalidMethod.
   873     trapCode := trap code.
  1081     trapCode := trap code.
   874     trapByteCode := trap byteCode.
  1082     trapByteCode := trap byteCode.
   875 
  1083 
   876     aClass methodDictionary do:[:aMethod |
  1084     aClass methodArray do:[:aMethod |
   877         trapCode notNil ifTrue:[
  1085         trapCode notNil ifTrue:[
   878             (aMethod code == trapCode) ifTrue:[^ true]
  1086             (aMethod code == trapCode) ifTrue:[^ true]
   879         ].
  1087         ].
   880         trapByteCode notNil ifTrue:[
  1088         trapByteCode notNil ifTrue:[
   881             (aMethod byteCode == trapByteCode) ifTrue:[^ true]
  1089             (aMethod byteCode == trapByteCode) ifTrue:[^ true]