Changes in / [fca6ca6:91d6584]


Ignore:
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/builtins.c

    rfca6ca6 r91d6584  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  5 21:40:38 2018
    13 // Update Count     : 20
     12// Last Modified On : Sun Mar 10 10:52:50 2019
     13// Update Count     : 31
    1414//
    1515
     
    2626// increment/decrement unification
    2727
    28 static inline forall( dtype T | { T& ?+=?( T&, one_t ); } )
    29 T& ++? ( T& x ) { return x += 1; }
     28static inline forall( dtype T | { T & ?+=?( T &, one_t ); } )
     29T & ++? ( T & x ) { return x += 1; }
    3030
    31 static inline forall( dtype T | sized(T) | { void ?{}( T&, T ); void ^?{}( T& ); T& ?+=?( T&, one_t ); } )
    32 T& ?++ ( T& x ) { T tmp = x; x += 1; return tmp; }
     31static inline forall( dtype T | sized(T) | { void ?{}( T &, T ); void ^?{}( T & ); T & ?+=?( T &, one_t ); } )
     32T & ?++ ( T & x ) { T tmp = x; x += 1; return tmp; }
    3333
    34 static inline forall( dtype T | { T& ?-=?( T&, one_t ); } )
    35 T& --? ( T& x ) { return x -= 1; }
     34static inline forall( dtype T | { T & ?-=?( T &, one_t ); } )
     35T & --? ( T & x ) { return x -= 1; }
    3636
    37 static inline forall( dtype T | sized(T) | { void ?{}( T&, T ); void ^?{}( T& ); T& ?-=?( T&, one_t ); } )
    38 T& ?-- ( T& x ) { T tmp = x; x -= 1; return tmp; }
     37static inline forall( dtype T | sized(T) | { void ?{}( T &, T ); void ^?{}( T & ); T & ?-=?( T &, one_t ); } )
     38T & ?-- ( T & x ) { T tmp = x; x -= 1; return tmp; }
     39
     40// universal typed pointer constant
     41
     42static inline forall( dtype T ) T * intptr( uintptr_t addr ) { return (T *)addr; }
    3943
    4044// exponentiation operator implementation
  • libcfa/prelude/prelude-gen.cc

    rfca6ca6 r91d6584  
    1010// Created On       : Sat Feb 16 08:44:58 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Feb 18 09:47:33 2019
    13 // Update Count     : 22
     12// Last Modified On : Fri Mar  8 16:00:22 2019
     13// Update Count     : 26
    1414//
    1515
     
    287287        cout << "forall(ftype FT) FT *                  ?=?( FT *          &, zero_t );" << endl;
    288288        cout << "forall(ftype FT) FT *                  ?=?( FT * volatile &, zero_t );" << endl;
    289         cout << "forall( ftype FT ) void        ?{}( FT *          & );" << endl;
    290         cout << "forall( ftype FT ) void        ^?{}( FT *         & );" << endl;
     289        cout << "forall(ftype FT) void  ?{}( FT *          & );" << endl;
     290        cout << "forall(ftype FT) void  ^?{}( FT *         & );" << endl;
    291291        cout << endl;
    292292
     
    295295        cout << "///////////////////////" << endl;
    296296
    297         cout << "forall( ftype FT ) FT *                        ?=?( FT *&, FT * );" << endl;
    298         cout << "forall( ftype FT ) FT *                        ?=?( FT * volatile &, FT * );" << endl;
    299         cout << "forall( ftype FT ) int !?( FT * );" << endl;
    300         cout << "forall( ftype FT ) signed int ?==?( FT *, FT * );" << endl;
    301         cout << "forall( ftype FT ) signed int ?!=?( FT *, FT * );" << endl;
    302         cout << "forall( ftype FT ) FT &                 *?( FT * );" << endl;
    303 
     297        cout << "forall(ftype FT) FT *                  ?=?( FT *&, FT * );" << endl;
     298        cout << "forall(ftype FT) FT *                  ?=?( FT * volatile &, FT * );" << endl;
     299        cout << "forall(ftype FT) int !?( FT * );" << endl;
     300        cout << "forall(ftype FT) signed int ?==?( FT *, FT * );" << endl;
     301        cout << "forall(ftype FT) signed int ?!=?( FT *, FT * );" << endl;
     302        cout << "forall(ftype FT) FT &           *?( FT * );" << endl;
    304303
    305304        for (auto op : pointerOperators) {
  • src/BasicTypes-gen.cc

    rfca6ca6 r91d6584  
    7070} graph[NUMBER_OF_BASIC_TYPES] = {
    7171        { Bool, "Bool", "B", "_Bool", "b", Signed, Char, SignedChar, -1, 0 }, // root
     72
    7273        { Char, "Char", "C", "char", "c", Signed, SignedChar, UnsignedChar, ShortSignedInt, 1 },
    7374        { SignedChar, "SignedChar", "SC", "signed char", "a", Signed, UnsignedChar, ShortSignedInt, -1, 1 },
    7475        { UnsignedChar, "UnsignedChar", "UC", "unsigned char", "h", Unsigned, ShortUnsignedInt, ShortSignedInt, -1, 1 },
     76
    7577        { ShortSignedInt, "ShortSignedInt", "SI", "signed short int", "s", Signed, ShortUnsignedInt, SignedInt, -1, 2 },
    7678        { ShortUnsignedInt, "ShortUnsignedInt", "SUI", "unsigned short int", "t", Unsigned, UnsignedInt, SignedInt, -1, 2 },
     79
    7780        { SignedInt, "SignedInt", "I", "signed int", "i", Signed, UnsignedInt, LongSignedInt, -1, 3 },
    7881        { UnsignedInt, "UnsignedInt", "UI", "unsigned int", "j", Unsigned, LongUnsignedInt, LongSignedInt, -1, 3 },
     82
    7983        { LongSignedInt, "LongSignedInt", "LI", "signed long int", "l", Signed, LongUnsignedInt, LongLongSignedInt, -1, 4 },
    8084        { LongUnsignedInt, "LongUnsignedInt", "LUI", "unsigned long int", "m", Unsigned, LongLongSignedInt, LongLongUnsignedInt, -1, 4 },
     85
    8186        { LongLongSignedInt, "LongLongSignedInt", "LLI", "signed long long int", "x", Signed, LongLongUnsignedInt, SignedInt128, -1, 5 },
    8287        { LongLongUnsignedInt, "LongLongUnsignedInt", "LLUI", "unsigned long long int", "y", Unsigned, SignedInt128, UnsignedInt128, -1, 5 },
     88
    8389        { SignedInt128, "SignedInt128", "IB", "__int128", "n", Signed, UnsignedInt128, uFloat16, -1, 6 },
    8490        { UnsignedInt128, "UnsignedInt128", "UIB", "unsigned __int128", "o", Unsigned, uFloat16, -1, -1, 6 },
     91
    8592        { uFloat16, "uFloat16", "_FH", "_Float16", "DF16_", Floating, uFloat32, uFloat16Complex, -1, 7 },
    8693        { uFloat16Complex, "uFloat16Complex", "_FH", "_Float16 _Complex", "CDF16_", Floating, uFloat32Complex, -1, -1, 7 },
     
    9097        { FloatComplex, "FloatComplex", "FC", "float _Complex", "Cf", Floating, uFloat32xComplex, -1, -1, 9 },
    9198        // { FloatImaginary, "FloatImaginary", "FI", "float _Imaginary", "If", false, DoubleImaginary, FloatComplex, -1, 9 },
     99
    92100        { uFloat32x, "uFloat32x", "_FX", "_Float32x", "DF32x_", Floating, uFloat64, uFloat32xComplex, -1, 10 },
    93101        { uFloat32xComplex, "uFloat32xComplex", "_FXC", "_Float32x _Complex", "CDF32x_", Floating, uFloat64Complex, -1, -1, 10 },
     
    97105        { DoubleComplex, "DoubleComplex", "DC", "double _Complex", "Cd", Floating, uFloat64xComplex, -1, -1, 12 },
    98106        // { DoubleImaginary, "DoubleImaginary", "DI", "double _Imaginary", "Id", false, LongDoubleImaginary, DoubleComplex, -1, 12 },
     107
    99108        { uFloat64x, "uFloat64x", "F80X", "_Float64x", "DF64x_", Floating, uuFloat80, uFloat64xComplex, -1, 13 },
    100109        { uFloat64xComplex, "uFloat64xComplex", "_FDXC", "_Float64x _Complex", "CDF64x_", Floating, uFloat128Complex, -1, -1, 13 },
     
    106115        { LongDoubleComplex, "LongDoubleComplex", "LDC", "long double _Complex", "Ce", Floating, uFloat128xComplex, -1, -1, 17 },
    107116        // { LongDoubleImaginary, "LongDoubleImaginary", "LDI", "long double _Imaginary", "Ie", false, LongDoubleComplex, -1, -1, 17 },
     117
    108118        { uFloat128x, "uFloat128x", "_FBX", "_Float128x", "DF128x_", Floating, uFloat128xComplex, -1, -1, 18 },
    109119        { uFloat128xComplex, "uFloat128xComplex", "_FLDXC", "_Float128x _Complex", "CDF128x_", Floating, -1, -1, -1, 18 }
     
    250260
    251261        #define STARTMK "// GENERATED START, DO NOT EDIT"
    252         #define BYMK "// GENERATED BY " __FILE__
    253262        #define ENDMK "// GENERATED END"
     263        string BYMK( __FILE__ );
     264        string::size_type posn = BYMK.find_last_of( "/" );
     265        if ( posn != string::npos ) BYMK.erase( 0, posn - 1); // remove directories
     266        BYMK = "// GENERATED BY " + BYMK;
     267
    254268        fstream file;
    255269        stringstream buffer, code;
  • src/Parser/ExpressionNode.cc

    rfca6ca6 r91d6584  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 28 21:36:38 2019
    13 // Update Count     : 933
     12// Last Modified On : Sun Mar 10 16:10:32 2019
     13// Update Count     : 976
    1414//
    1515
     
    6666void lnthSuffix( string & str, int & type, int & ltype ) {
    6767        string::size_type posn = str.find_last_of( "lL" );
    68         if ( posn != string::npos ) {
    69                 type = 3;                                                                               // default
    70                 posn += 1;                                                                              // advance to size
    71                 if ( str[posn] == '3' ) {                                               // 32
    72                         type = ltype = 2; str.erase( posn, 2 );
    73                 } else if ( str[posn] == '6' ) {                                // 64
    74                         type = ltype = 3; str.erase( posn, 2 );
    75                 } else if ( str[posn] == '8' ) {                                // 8
    76                         type = ltype = 1; str.erase( posn, 1 );
    77                 } else if ( str[posn] == '1' ) {
    78                         if ( str[posn + 1] == '6' ) {                           // 16
    79                                 type = ltype = 0; str.erase( posn, 2 );
    80                         } else {                                                                        // 128
    81                                 type = ltype = 5; str.erase( posn, 3 );
    82                         } // if
    83                 } // if
    84         } // if
     68
     69        if ( posn == string::npos ) return;                                     // no suffix
     70        if ( posn == str.length() - 1 ) { type = 3; return; } // no length => long
     71
     72        string::size_type next = posn + 1;                                      // advance to length
     73        if ( str[next] == '3' ) {                                                       // 32
     74                type = ltype = 2;
     75        } else if ( str[next] == '6' ) {                                        // 64
     76                type = ltype = 3;
     77        } else if ( str[next] == '8' ) {                                        // 8
     78                type = ltype = 1;
     79        } else if ( str[next] == '1' ) {
     80                if ( str[next + 1] == '6' ) {                                   // 16
     81                        type = ltype = 0;
     82                } else {                                                                                // 128
     83                        type = 5; ltype = 6;
     84                } // if
     85        } // if
     86        // remove "lL" for these cases because it may not imply long
     87        str.erase( posn );                                                                      // remove length
    8588} // lnthSuffix
    8689
     90void valueToType( unsigned long long int & v, bool dec, int & type, bool & Unsigned ) {
     91        // use value to determine type
     92        if ( v <= INT_MAX ) {                                                           // signed int
     93                type = 2;
     94        } else if ( v <= UINT_MAX && ! dec ) {                          // unsigned int
     95                type = 2;
     96                Unsigned = true;                                                                // unsigned
     97        } else if ( v <= LONG_MAX ) {                                           // signed long int
     98                type = 3;
     99        } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int
     100                type = 3;
     101                Unsigned = true;                                                                // unsigned long int
     102        } else if ( v <= LLONG_MAX ) {                                          // signed long long int
     103                type = 4;
     104        } else {                                                                                        // unsigned long long int
     105                type = 4;
     106                Unsigned = true;                                                                // unsigned long long int
     107        } // if
     108} // valueToType
     109
    87110Expression * build_constantInteger( string & str ) {
    88         static const BasicType::Kind kind[2][6] = {
     111        static const BasicType::Kind kind[2][7] = {
    89112                // short (h) must be before char (hh) because shorter type has the longer suffix
    90113                { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },
     
    92115        };
    93116
    94         static const char * lnthsInt[2][5] = {
    95                 { "int16_t",  "int8_t",  "int32_t",  "int64_t",  "size_t", },
    96                 { "uint16_t", "uint8_t", "uint32_t", "uint64_t", "size_t", },
     117        static const char * lnthsInt[2][6] = {
     118                { "int16_t",  "int8_t",  "int32_t",  "int64_t",  "size_t",  "uintptr_t", },
     119                { "uint16_t", "uint8_t", "uint32_t", "uint64_t", "size_t",  "uintptr_t", },
    97120        }; // lnthsInt
    98 
    99         bool dec = true, Unsigned = false;                                      // decimal, unsigned constant
    100         int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
    101         int ltype = -1;                                                                         // literal length
    102121
    103122        unsigned long long int v;                                                       // converted integral value
    104123        size_t last = str.length() - 1;                                         // last subscript of constant
    105124        Expression * ret;
    106         string fred( str );
     125        //string fred( str );
     126
     127        int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     128        int ltype = -1;                                                                         // 0 => 16 bits, 1 => 8 bits, 2 => 32 bits, 3 => 64 bits, 4 => size_t, 5 => intptr, 6 => pointer
     129        bool dec = true, Unsigned = false;                                      // decimal, unsigned constant
    107130
    108131        // special constants
     
    116139        } // if
    117140
    118         // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall so always generate
     141        // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
    119142
    120143        if ( str[0] == '0' ) {                                                          // radix character ?
     
    125148                } else if ( checkB( str[1] ) ) {                                // binary constant ?
    126149                        v = 0;                                                                          // compute value
    127                         for ( unsigned int i = 2;; ) {
     150                        for ( unsigned int i = 2;; ) {                          // ignore prefix
    128151                                if ( str[i] == '1' ) v |= 1;
    129152                                i += 1;
     
    145168        if ( isdigit( str[last] ) ) {                                           // no suffix ?
    146169                lnthSuffix( str, type, ltype );                                 // could have length suffix
    147                 if ( type == -1 ) {
    148                         // no suffix type, use value to determine type
    149                         if ( v <= INT_MAX ) {                                           // signed int
    150                                 type = 2;
    151                         } else if ( v <= UINT_MAX && ! dec ) {          // unsigned int
    152                                 type = 2;
    153                                 Unsigned = true;                                                // unsigned
    154                         } else if ( v <= LONG_MAX ) {                           // signed long int
    155                                 type = 3;
    156                         } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int
    157                                 type = 3;
    158                                 Unsigned = true;                                                // unsigned long int
    159                         } else if ( v <= LLONG_MAX ) {                          // signed long long int
    160                                 type = 4;
    161                         } else {                                                                        // unsigned long long int
    162                                 type = 4;
    163                                 Unsigned = true;                                                // unsigned long long int
    164                         } // if
     170                if ( type == -1 ) {                                                             // no suffix
     171                        valueToType( v, dec, type, Unsigned );
    165172                } // if
    166173        } else {
    167174                // At least one digit in integer constant, so safe to backup while looking for suffix.
    168175
     176                posn = str.find_last_of( "pP" );
     177                if ( posn != string::npos ) { valueToType( v, dec, type, Unsigned ); ltype = 5; str.erase( posn, 1 ); goto FINI; }
     178
     179                posn = str.find_last_of( "zZ" );
     180                if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
     181
     182                // 'u' can appear before or after length suffix
    169183                if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
    170184
     
    181195                if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
    182196
    183                 posn = str.find_last_of( "zZ" );
    184                 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
    185 
    186197                if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
    187198
    188199                lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
    189                 if ( type == -1 ) { type = 3; goto FINI; }
     200                if ( type == -1 ) {                                                             // only 'u' suffix ?
     201                        valueToType( v, dec, type, Unsigned );
     202                } // if
    190203          FINI: ;
    191204        } // if
    192205
    193         //if ( !( 0 <= type && type < 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
    194         assert( 0 <= type && type < 6 );
     206        //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
     207        assert( 0 <= type && type <= 6 );
    195208
    196209        // Constant type is correct for overload resolving.
     
    200213                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
    201214        } else if ( ltype != -1 ) {                                                     // explicit length ?
    202                 if ( ltype == 5 ) {                                                             // int128 ?
    203                         type = 5;
     215                if ( ltype == 6 ) {                                                             // int128, (int128)constant
    204216                        ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
    205                 } else {
     217                } else {                                                                                // explicit length, (length_type)constant
    206218                        ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
     219                        if ( ltype == 5 ) {                                                     // pointer, intptr( (uintptr_t)constant )
     220                                ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) );                                                             
     221                        } // if
    207222                } // if
    208223        } // if
  • src/Parser/lex.ll

    rfca6ca6 r91d6584  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Wed Feb 27 22:44:03 2019
    13  * Update Count     : 704
     12 * Last Modified On : Sun Mar 10 09:13:09 2019
     13 * Update Count     : 706
    1414 */
    1515
     
    9999hex_quad {hex}("_"?{hex}){3}
    100100size_opt (8|16|32|64|128)?
     101                                // CFA: explicit l8/l16/l32/l64/l128, char 'hh', short 'h', int 'n'
    101102length ("ll"|"LL"|[lL]{size_opt})|("hh"|"HH"|[hHnN])
    102 integer_suffix_opt ("_"?(([uU]({length}?[iI]?)|([iI]{length}))|([iI]({length}?[uU]?)|([uU]{length}))|({length}([iI]?[uU]?)|([uU][iI]))|[zZ]))?
     103                                // CFA: size_t 'z', pointer 'p', which define a sign and length
     104integer_suffix_opt ("_"?(([uU]({length}?[iI]?)|([iI]{length}))|([iI]({length}?[uU]?)|([uU]{length}))|({length}([iI]?[uU]?)|([uU][iI]))|[zZ]|[pP]))?
    103105
    104106octal_digits ({octal})|({octal}({octal}|"_")*{octal})
  • src/ResolvExpr/CommonType.cc

    rfca6ca6 r91d6584  
    177177
    178178        // GENERATED START, DO NOT EDIT
    179         // GENERATED BY ../../main/src/BasicTypes-gen.cc
     179        // GENERATED BY BasicTypes-gen.cc
    180180        #define BT BasicType::
    181181        static const BasicType::Kind commonTypes[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // nearest common ancestor
  • src/ResolvExpr/ConversionCost.cc

    rfca6ca6 r91d6584  
    182182
    183183        // GENERATED START, DO NOT EDIT
    184         // GENERATED BY ../../main/src/BasicTypes-gen.cc
     184        // GENERATED BY BasicTypes-gen.cc
    185185        /* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves)
    186186                                 _Bool
     
    207207
    208208        // GENERATED START, DO NOT EDIT
    209         // GENERATED BY ../../main/src/BasicTypes-gen.cc
     209        // GENERATED BY BasicTypes-gen.cc
    210210        static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
    211211                /*             B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
     
    254254
    255255        // GENERATED START, DO NOT EDIT
    256         // GENERATED BY ../../main/src/BasicTypes-gen.cc
     256        // GENERATED BY BasicTypes-gen.cc
    257257        static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
    258258                /*             B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
  • src/SymTab/ManglerCommon.cc

    rfca6ca6 r91d6584  
    2424
    2525                        // GENERATED START, DO NOT EDIT
    26                         // GENERATED BY ../../main/src/BasicTypes-gen.cc
     26                        // GENERATED BY BasicTypes-gen.cc
    2727                        // NOTES ON MANGLING:
    2828                        // * Itanium spec says that Float80 encodes to "e" (like LongDouble), but the distinct lengths cause resolution problems.
  • src/SynTree/Type.h

    rfca6ca6 r91d6584  
    208208  public:
    209209        // GENERATED START, DO NOT EDIT
    210         // GENERATED BY ../../main/src/BasicTypes-gen.cc
     210        // GENERATED BY BasicTypes-gen.cc
    211211        enum Kind {
    212212                Bool,
  • tests/.expect/completeTypeError.txt

    rfca6ca6 r91d6584  
    8787   void
    8888 )
    89  Environment:( _73_0_T ) -> instance of type T (not function type) (no widening)
     89 Environment:( _74_0_T ) -> instance of type T (not function type) (no widening)
    9090
    9191
Note: See TracChangeset for help on using the changeset viewer.