Ignore:
Timestamp:
Jun 17, 2019, 11:01:04 AM (5 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
b4d34fa
Parents:
6a1dfda
Message:

Fixed handling of "literals.cfa" string-detail test cases by simplifying constant analysis. Now a ConstantExpr? is a minial passthrough from parser to code generator, with special-case analysis only for integer values. Awareness of how to build a string-constant type is back in ExpressionNode?.cc; now, this knowlede is only needed there. AST conversion no longer specializes string-int-float constants; it just converts types and passes values through. Unused constant API features are removed, notably from-to-float and from-string.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r6a1dfda rc36298d  
    740740
    741741        const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
    742                 ConstantExpr *rslt = nullptr;
    743                 switch ( node->kind ) {
    744                 case ast::ConstantExpr::Integer:
    745                         rslt = new ConstantExpr{Constant{
    746                                 get<Type>().accept1( node->result ),
    747                                 node->rep,
    748                                 (unsigned long long) node->intValue()
    749                         }};
    750                         break;
    751                 case ast::ConstantExpr::FloatingPoint:
    752                         rslt = new ConstantExpr{Constant{
    753                                 get<Type>().accept1(node->result),
    754                                 node->rep,
    755                                 (double) node->floatValue()
    756                         }};
    757                         break;
    758                 case ast::ConstantExpr::String:
    759                         // Old world:   two types: rslt->constant.type, rslt->result
    760                         // New workd:   one type: node->result
    761                         // Both worlds: the outer, expression-level type can change during resolution
    762                         //              in case of string, that's char[k] before-resolve and char * after
    763                         // Old world:   the inner Constant type stays what it was built with
    764                         //              in case of string, that's char[k]
    765                         // Both worlds: the "rep" field of a string constant is the string value it was initialized from, wrapped in quotes, but not otherwise escaped
    766                         ast::ptr<ast::Type> charType = nullptr;
    767                         if (const ast::ArrayType *arrRslt = node->result.as<ast::ArrayType>()) {
    768                                 charType = arrRslt->base;
    769                         } else {
    770                                 const ast::PointerType *ptrRslt = node->result.as<ast::PointerType>();
    771                                 assert(ptrRslt);
    772                                 charType = ptrRslt->base;
    773                         }
    774                         rslt = new ConstantExpr(Constant::from_string(
    775                                 node->rep, get<Type>().accept1(charType)));          // rslt->result is char[k]
    776                         rslt->set_result( get<Type>().accept1( node->result ) ); // rslt->result is [[ node->rsult ]]
    777                         break;
    778                 }
    779                 assert(rslt);
     742                // Old world:   two types: rslt->constant.type, rslt->result
     743                // New workd:   one public type: node->result, plus node->underlyer only to support roundtrip conversion
     744                //              preserving underlyer because the correct type for string literals is complicated to construct,
     745            //              and distinguishing a string from other literals using the type is hard to do accurately
     746                // Both worlds: the outer, expression-level type can change during resolution
     747                //              for a string, that's char[k] before-resolve and char * after
     748                // Old world:   the inner Constant type stays what it was built with
     749                //              for a string, that's char[k] always
     750                // Both worlds: the "rep" field of a constant is the C source file fragment that compiles to the desired value
     751        //              for a string, that includes outer quotes, backslashes, et al cases from the Literals test
     752                ConstantExpr *rslt = new ConstantExpr(Constant(
     753                        get<Type>().accept1(node->underlyer),
     754                        node->rep,
     755                        node->ival));
    780756                auto expr = visitBaseExpr( node, rslt );
    781757                this->node = expr;
     
    21622138        }
    21632139
    2164         bool isIntlikeConstantType(const Type *t) {
    2165                 if ( const BasicType * basicType = dynamic_cast< const BasicType * >( t ) ) {
    2166                         if ( basicType->isInteger() ) {
    2167                                 return true;
    2168                         }
    2169                 } else if ( dynamic_cast< const OneType * >( t ) ) {
    2170                         return true;
    2171                 } else if ( dynamic_cast< const ZeroType * >( t ) ) {
    2172                         return true;
    2173                 } else if ( dynamic_cast< const PointerType * >( t ) ) {
    2174                         // null pointer constants, with zero int-values
    2175                         return true;
    2176                 }
    2177                 return false;
    2178         }
    2179 
    2180         int isFloatlikeConstantType(const Type *t) {
    2181                 if ( const BasicType * bty = dynamic_cast< const BasicType * >( t ) ) {
    2182                         if ( ! bty->isInteger() ) {
    2183                                 return true;
    2184                         }
    2185                 }
    2186                 return false;
    2187         }
    2188 
    2189         int isStringlikeConstantType(const Type *t) {
    2190                 const Type *referentType = nullptr;
    2191                 if ( const ArrayType * aty = dynamic_cast< const ArrayType * >( t ) ) {
    2192                         referentType = aty->base;
    2193                 } else if ( const PointerType * pty = dynamic_cast< const PointerType * >( t ) ) {
    2194                         referentType = pty->base;
    2195                 }
    2196                 if (referentType) {
    2197                         if ( const BasicType * bty = dynamic_cast< const BasicType * >( referentType ) ) {
    2198                            if ( bty->kind == BasicType::Kind::Char ) {
    2199                                    return true;
    2200                            }
    2201                         }
    2202                 }
    2203                 return false;
    2204         }
    2205 
    22062140        virtual void visit( ConstantExpr * old ) override final {
    2207                 ast::ConstantExpr *rslt = nullptr;
    2208                 if (isStringlikeConstantType(old->result)) {
    2209                         rslt = new ast::ConstantExpr(
    2210                                 old->location,
    2211                                 GET_ACCEPT_1(result, Type), // preserve the expression-level type (old->result, not old->constant.type); see new-to-old
    2212                                 old->constant.get_value(),
    2213                                 0,
    2214                                 ast::ConstantExpr::Kind::String
    2215                         );
    2216                 } else if (isIntlikeConstantType(old->result)) {
    2217                         rslt = new ast::ConstantExpr(
    2218                                 old->location,
    2219                                 GET_ACCEPT_1(result, Type),
    2220                                 old->constant.get_value(),
    2221                                 (unsigned long long) old->intValue(),
    2222                                 ast::ConstantExpr::Kind::Integer
    2223                         );
    2224                 } else if (isFloatlikeConstantType(old->result)) {
    2225                         rslt = new ast::ConstantExpr(
    2226                                 old->location,
    2227                                 GET_ACCEPT_1(result, Type),
    2228                                 old->constant.get_value(),
    2229                                 (double) old->constant.get_dval()
    2230                         );
    2231                 }
    2232                 assert(rslt);
     2141                ast::ConstantExpr *rslt = new ast::ConstantExpr(
     2142                        old->location,
     2143                        GET_ACCEPT_1(result, Type),
     2144                        old->constant.get_value(),
     2145                        old->constant.ival
     2146                );
     2147                rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.get_type() );
    22332148                this->node = visitBaseExpr( old, rslt );
    22342149        }
Note: See TracChangeset for help on using the changeset viewer.