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