Changeset c36298d


Ignore:
Timestamp:
Jun 17, 2019, 11:01:04 AM (2 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
arm-eh, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
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.

Location:
src
Files:
6 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        }
  • src/AST/Expr.cpp

    r6a1dfda rc36298d  
    194194        if ( const BasicType * bty = result.as< BasicType >() ) {
    195195                if ( bty->isInteger() ) {
    196                         return val.ival;
     196                        assert(ival);
     197                        return ival.value();
    197198                }
    198199        } else if ( result.as< ZeroType >() ) {
     
    204205}
    205206
    206 double ConstantExpr::floatValue() const {
    207         if ( const BasicType * bty = result.as< BasicType >() ) {
    208                 if ( ! bty->isInteger() ) {
    209                         return val.dval;
    210                 }
    211         }
    212         SemanticError( this, "Constant expression of non-floating-point type " );
    213 }
    214 
    215207ConstantExpr * ConstantExpr::from_bool( const CodeLocation & loc, bool b ) {
    216208        return new ConstantExpr{
    217209                loc, new BasicType{ BasicType::Bool }, b ? "1" : "0", (unsigned long long)b };
    218 }
    219 
    220 ConstantExpr * ConstantExpr::from_char( const CodeLocation & loc, char c ) {
    221         return new ConstantExpr{
    222                 loc, new BasicType{ BasicType::Char }, std::to_string( c ), (unsigned long long)c };
    223210}
    224211
     
    232219                loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ),
    233220                (unsigned long long)i };
    234 }
    235 
    236 ConstantExpr * ConstantExpr::from_double( const CodeLocation & loc, double d ) {
    237         return new ConstantExpr{ loc, new BasicType{ BasicType::Double }, std::to_string( d ), d };
    238221}
    239222
  • src/AST/Expr.hpp

    r6a1dfda rc36298d  
    2222#include <utility>        // for move
    2323#include <vector>
     24#include <optional>
    2425
    2526#include "Fwd.hpp"        // for UniqueId
     
    3233
    3334class ConverterOldToNew;
     35class ConverterNewToOld;
    3436
    3537namespace ast {
     
    346348};
    347349
    348 /// A compile-time constant
     350/// A compile-time constant.
     351/// Mostly carries C-source text from parse to code-gen, without interpretation.  E.g. strings keep their outer quotes and never have backslashes interpreted.
     352/// Integer constants get special treatment, e.g. for verifying array operations, when an integer constant occurs as the length of an array.
    349353class ConstantExpr final : public Expr {
    350         union Val {
    351                 unsigned long long ival;
    352                 double dval;
    353 
    354                 Val( unsigned long long i ) : ival( i ) {}
    355                 Val( double d ) : dval( d ) {}
    356         } val;
    357 public:
     354public:
     355        // Representation of this constant, as it occurs in .cfa source and .cfa.cc result.
    358356        std::string rep;
    359         enum Kind { Integer, FloatingPoint, String } kind;
    360357
    361358        ConstantExpr(
    362                 const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v,
    363                 Kind k = Integer )
    364         : Expr( loc, ty ), val( v ), rep( r ), kind( k ) {}
    365         ConstantExpr( const CodeLocation & loc, const Type * ty, const std::string & r, double v )
    366         : Expr( loc, ty ), val( v ), rep( r ), kind( FloatingPoint ) {}
    367 
    368         /// Gets the value of this constant as an integer
     359                const CodeLocation & loc, const Type * ty, const std::string & r,
     360                        std::optional<unsigned long long> i )
     361        : Expr( loc, ty ), rep( r ), ival( i ) {}
     362
     363        /// Gets the integer value of this constant, if one is appropriate to its type.
     364        /// Throws a SemanticError if the type is not appropriate for value-as-integer.
     365        /// Suffers an assertion failure the type is appropriate but no integer value was supplied to the constructor.
    369366        long long int intValue() const;
    370         /// Gets the value of this constant as floating point
    371         double floatValue() const;
    372367
    373368        /// generates a boolean constant of the given bool
    374369        static ConstantExpr * from_bool( const CodeLocation & loc, bool b );
    375         /// generates a char constant of the given char
    376         static ConstantExpr * from_char( const CodeLocation & loc, char c );
    377370        /// generates an integer constant of the given int
    378371        static ConstantExpr * from_int( const CodeLocation & loc, int i );
    379372        /// generates an integer constant of the given unsigned long int
    380373        static ConstantExpr * from_ulong( const CodeLocation & loc, unsigned long i );
    381         /// generates a floating point constant of the given double
    382         static ConstantExpr * from_double( const CodeLocation & loc, double d );
    383374        /// generates a null pointer value for the given type. void * if omitted.
    384375        static ConstantExpr * null( const CodeLocation & loc, const Type * ptrType = nullptr );
     
    388379        ConstantExpr * clone() const override { return new ConstantExpr{ *this }; }
    389380        MUTATE_FRIEND
     381
     382        std::optional<unsigned long long> ival;
     383
     384        // Intended only for legacy support of roundtripping the old AST.
     385        // Captures the very-locally inferred type, before the resolver modifies the type of this ConstantExpression.
     386        // In the old AST it's constExpr->constant.type
     387        ptr<Type> underlyer;
     388        friend class ::ConverterOldToNew;
     389        friend class ::ConverterNewToOld;
    390390};
    391391
  • src/Parser/ExpressionNode.cc

    r6a1dfda rc36298d  
    354354                strtype = new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char );
    355355        } // switch
    356         Expression * ret = new ConstantExpr( Constant::from_string( str, strtype ) );
     356        ArrayType * at = new ArrayType( noQualifiers, strtype,
     357                                                                        new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
     358                                                                        false, false );
     359        Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) );
    357360        if ( units.length() != 0 ) {
    358361                ret = new UntypedExpr( new NameExpr( units ), { ret } );
  • src/SynTree/Constant.cc

    r6a1dfda rc36298d  
    2222#include "Type.h"    // for BasicType, Type, Type::Qualifiers, PointerType
    2323
    24 Constant::Constant( Type * type, std::string rep, unsigned long long val ) : type( type ), rep( rep ), val( val ) {}
    25 Constant::Constant( Type * type, std::string rep, double val ) : type( type ), rep( rep ), val( val ) {}
     24Constant::Constant( Type * type, std::string rep, std::optional<unsigned long long> ival ) : type( type ), rep( rep ), ival( ival ) {}
    2625
    27 Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), val( other.val ) {
     26Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), ival( other.ival ) {
    2827        type = other.type->clone();
    2928}
     
    3534}
    3635
    37 Constant Constant::from_char( char c ) {
    38         return Constant( new BasicType( Type::Qualifiers(), BasicType::Char ), std::to_string( c ), (unsigned long long int)c );
    39 }
    40 
    4136Constant Constant::from_int( int i ) {
    4237        return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ), (unsigned long long int)i );
     
    4540Constant Constant::from_ulong( unsigned long i ) {
    4641        return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ), (unsigned long long int)i );
    47 }
    48 
    49 Constant Constant::from_double( double d ) {
    50         return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ), d );
    51 }
    52 
    53 Constant Constant::from_string( std::string const & cEscapedVal, Type *charType ) {
    54         assert(cEscapedVal.length() >= 2);
    55         assert(cEscapedVal.front() == '"');
    56         assert(cEscapedVal.back() == '"');
    57         ArrayType * at = new ArrayType( noQualifiers, charType,
    58                                                                         new ConstantExpr( Constant::from_ulong( cEscapedVal.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
    59                                                                         false, false );
    60         return Constant( at, cEscapedVal, (unsigned long long int)0 );
    6142}
    6243
     
    7455unsigned long long Constant::get_ival() const {
    7556        assertf( strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." );
    76         return val.ival;
    77 }
    78 
    79 double Constant::get_dval() const {
    80         assertf( ! strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve dval from integer constant." );
    81         return val.dval;
     57        return ival.value();
    8258}
    8359
    8460void Constant::print( std::ostream &os, Indenter ) const {
    85         os << "(" << rep << " " << val.ival;
     61        os << "(" << rep << " " << (ival ? toString(ival.value()) : "") ;
    8662        if ( type ) {
    8763                os << ": ";
  • src/SynTree/Constant.h

    r6a1dfda rc36298d  
    1818#include <iosfwd>     // for ostream
    1919#include <string>     // for string
     20#include <optional>   // for optional
    2021
    2122#include "BaseSyntaxNode.h"
     
    2728class Constant : public BaseSyntaxNode {
    2829  public:
    29         Constant( Type * type, std::string rep, unsigned long long val );
    30         Constant( Type * type, std::string rep, double val );
     30        Constant( Type * type, std::string rep, std::optional<unsigned long long> i );
    3131        Constant( const Constant & other );
    3232        virtual ~Constant();
     
    3939        void set_value( std::string newValue ) { rep = newValue; }
    4040        unsigned long long get_ival() const;
    41         double get_dval() const;
    4241
    4342        /// generates a boolean constant of the given bool
    4443        static Constant from_bool( bool b );
    45         /// generates a char constant of the given char
    46         static Constant from_char( char c );
    4744        /// generates an integer constant of the given int
    4845        static Constant from_int( int i );
    4946        /// generates an integer constant of the given unsigned long int
    5047        static Constant from_ulong( unsigned long i );
    51         /// generates a floating point constant of the given double
    52         static Constant from_double( double d );
    53         /// generates an array of chars constant of the given string
    54         static Constant from_string( std::string const & cEscapedVal, Type *charType  );
    5548
    5649        /// generates a null pointer value for the given type. void * if omitted.
     
    6356        Type * type;
    6457        std::string rep;
    65         union Val {
    66                 unsigned long long ival;
    67                 double dval;
    68                 Val( unsigned long long ival ) : ival( ival ) {}
    69                 Val( double dval ) : dval( dval ) {}
    70         } val;
     58        std::optional<unsigned long long> ival;
     59
     60        friend class ConverterOldToNew;
    7161};
    7262
Note: See TracChangeset for help on using the changeset viewer.