Changes in / [42cdd07d:0188539c]


Ignore:
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/builtins.c

    r42cdd07d r0188539c  
    178178} // distribution
    179179
    180 struct quasi_void {};
    181 static inline void ?{}(quasi_void &) {}
    182 static inline void ?{}(quasi_void &, quasi_void) {}
    183 static inline void ^?{}(quasi_void &) {}
    184 static inline quasi_void ?=?(quasi_void &, quasi_void & _src) { return _src; }
    185 
    186180// Local Variables: //
    187181// mode: c //
  • libcfa/src/enum.cfa

    r42cdd07d r0188539c  
    11#include "enum.hfa"
    2 #include "fstream.hfa"
    32
    43#pragma GCC visibility push(default)
    54
    6 forall(ostype & | basic_ostream(ostype), E, V| CfaEnum(E, V))
    7 ostype & ?|?(ostype& os, E e) {
    8     return os | type_name(e) | "." | labelE(e);
     5forall(T, E| TypedEnum(T, E)) {
     6    // constructors
     7
     8    // comparison
     9    int ?==?(E l, E r) { return posE(l) == posE(r); }
     10    int ?!=?(E l, E r) { return posE(l) != posE(r); }
     11    int ?!=?(E l, zero_t) { return !( posE(l) == 0 ); }
     12    int ?<?(E l, E r) { return posE(l) < posE(r); }
     13    int ?<=?(E l, E r) { return posE(l) <= posE(r); }
     14    int ?>?(E l, E r) { return posE(l) > posE(r); }
     15    int ?>=?(E l, E r) {  return posE(l) >= posE(r); }
    916}
    10 
    11 forall(ostype & | basic_ostream(ostype), E| CfaEnum(E, quasi_void))
    12 ostype & ?|?(ostype& os, E e) {
    13     return os | type_name(e) | "." | labelE(e);
    14 }
  • libcfa/src/enum.hfa

    r42cdd07d r0188539c  
    11#pragma once
    22
    3 #include "iostream.hfa"
     3forall(T) { // T is the based type of enum(T)
     4    forall(E) trait Bounded {
     5        E lowerBound();
     6        E upperBound();
     7    };
    48
    5 forall(E) trait Bounded {
    6     E lowerBound();
    7     E upperBound();
    8 };
     9    forall(E| Bounded(T, E)) trait Serial {
     10        unsigned fromInstance(E e);
     11        E fromInt(unsigned i);
     12        E succ(E e);
     13        E pred(E e);
     14    };
    915
    10 forall(E | Bounded(E)) trait Serial {
    11     unsigned fromInstance(E e);
    12     E fromInt(unsigned i);
    13     E succ(E e);
    14     E pred(E e);
    15 };
     16    // Opague Enum + TypedEnum
     17    forall(E | Serial(T, E)) trait CfaEnum {
     18        char * labelE(E e);
     19        unsigned int posE(E e);
     20    };
    1621
    17 // Design one
    18 forall(E, V | Serial(E)) trait CfaEnum {
    19     char* labelE(E e);
    20     unsigned int posE(E e);
    21     V valueE(E e);
    22     char* type_name(E e);
    23 };
     22    forall(E| CfaEnum(T, E)) trait TypedEnum {
     23        T valueE(E e);
     24    };
    2425
    25 forall(ostype & | basic_ostream(ostype), E, V| CfaEnum(E, V))
    26 ostype & ?|?(ostype&, E);
    27 
    28 forall(ostype & | basic_ostream(ostype), E| CfaEnum(E, quasi_void))
    29 ostype & ?|?(ostype&, E);
    30 
    31 // Design two <- should go for this if we have change the cost model
    32 // forall(E | Serial(E)) trait CfaEnum {
    33 //     char* labelE(E e);
    34 //     unsigned int posE(E e);
    35 // };
    36 
    37 // forall(E, V| CfaEnum(E)) trait TypedEnum {
    38 //     V valueE(E e);
    39 // };
     26        forall(E | TypedEnum(T, E)) {
     27                // comparison
     28                int ?==?(E l, E r);                                                             // true if l and r are same enumerators
     29                int ?!=?(E l, E r);                                                             // true if l and r are different enumerators
     30                int ?!=?(E l, zero_t);                                                  // true if l is not the first enumerator
     31                int ?<?(E l, E r);                                                              // true if l is an enuemerator before r
     32                int ?<=?(E l, E r);                                                             // true if l before or the same as r
     33                int ?>?(E l, E r);                                                              // true if l is an enuemrator after r
     34                int ?>=?(E l, E r);                                                             // true if l after or the same as r
     35        }
     36}
  • src/AST/Decl.cpp

    r42cdd07d r0188539c  
    170170
    171171const std::string EnumDecl::getUnmangeldArrayName( const ast::EnumAttribute attr ) const {
    172         switch( attr ) {
    173                 case ast::EnumAttribute::Value: return "values_" + name ;
    174                 case ast::EnumAttribute::Label: return "labels_" + name;
    175                 default: /* Posn does not generate array */
    176                         return "";
     172                switch( attr ) {
     173                        case ast::EnumAttribute::Value: return "values_" + name ;
     174                        case ast::EnumAttribute::Label: return "labels_" + name;
     175                        default: /* Posn does not generate array */
     176                                return "";
     177                }
    177178        }
    178 }
    179 
    180 unsigned EnumDecl::calChildOffset(const std::string & target) const{
    181         unsigned offset = 0;
    182         for (auto childEnum: inlinedDecl) {
    183                 auto childDecl = childEnum->base;
    184                 if (childDecl->name == target) {
    185                         return offset;
    186                 }
    187                 offset += childDecl->members.size();
    188         }
    189     std::cerr << "Cannot find the target enum" << std::endl;
    190         return 0;
    191 }
    192 
    193 unsigned EnumDecl::calChildOffset(const ast::EnumInstType * target) const{
    194         return calChildOffset(target->base->name);
    195 }
    196 
    197 bool EnumDecl::isSubTypeOf(const ast::EnumDecl * other) const {
    198         if (name == other->name) return true;
    199         for (auto inlined: other->inlinedDecl) {
    200                 if (isSubTypeOf(inlined->base)) return true;
    201         }
    202         return false;
    203 }
    204179
    205180}
  • src/AST/Decl.hpp

    r42cdd07d r0188539c  
    7575        bool isDeleted = false;
    7676        bool isTypeFixed = false;
    77         bool isHidden = false;
    7877
    7978        DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
     
    314313        ptr<Type> base;
    315314        enum class EnumHiding { Visible, Hide } hide;
    316         std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums
    317 
    318315        EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false,
    319316                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
     
    331328
    332329        const std::string getUnmangeldArrayName( const EnumAttribute attr ) const;
    333 
    334         unsigned calChildOffset(const std::string & childEnum) const;
    335         unsigned calChildOffset(const ast::EnumInstType * childEnum) const;
    336 
    337         bool isSubTypeOf(const ast::EnumDecl *) const;
    338330private:
    339331        EnumDecl * clone() const override { return new EnumDecl{ *this }; }
  • src/AST/Expr.hpp

    r42cdd07d r0188539c  
    256256public:
    257257        ptr<Decl> type_decl;
    258         const std::string type_name;
    259         const std::string name;
     258        std::string name;
    260259
    261260        QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n )
    262         : Expr( loc ), type_decl( d ), type_name(""), name( n ) {}
    263 
    264         QualifiedNameExpr( const CodeLocation & loc, const std::string & type_name, const std::string & name)
    265         : Expr( loc ), type_name( type_name ), name( name ) {}
     261        : Expr( loc ), type_decl( d ), name( n ) {}
    266262
    267263        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Pass.impl.hpp

    r42cdd07d r0188539c  
    560560
    561561        if ( __visit_children() ) {
    562                 maybe_accept( node, &EnumDecl::base        );
    563                 maybe_accept( node, &EnumDecl::params      );
    564                 maybe_accept( node, &EnumDecl::members     );
    565                 maybe_accept( node, &EnumDecl::attributes  );
    566                 maybe_accept( node, &EnumDecl::inlinedDecl );
     562                if ( node->hide == ast::EnumDecl::EnumHiding::Hide ) {
     563                        guard_symtab guard { *this };
     564                        maybe_accept( node, &EnumDecl::base );
     565                        maybe_accept( node, &EnumDecl::params     );
     566                        maybe_accept( node, &EnumDecl::members    );
     567                        maybe_accept( node, &EnumDecl::attributes );
     568                } else {
     569                        maybe_accept( node, &EnumDecl::base );
     570                        maybe_accept( node, &EnumDecl::params     );
     571                        maybe_accept( node, &EnumDecl::members    );
     572                        maybe_accept( node, &EnumDecl::attributes );
     573                }
    567574        }
    568575
  • src/AST/SymbolTable.cpp

    r42cdd07d r0188539c  
    159159}
    160160
    161 std::vector<SymbolTable::IdData> SymbolTable::lookupIdIgnoreHidden( const std::string &id ) const {
    162         std::vector<IdData> out;
    163         std::vector<IdData> lookupResult = lookupId(id);
    164         for ( auto candidate: lookupResult) {
    165                 if ( candidate.id ) {
    166                         if (candidate.id->isHidden) continue;
    167                 }
    168                 out.push_back(candidate);
    169         }
    170         return out;
    171 }
    172 
    173161std::vector<SymbolTable::IdData> SymbolTable::specialLookupId( SymbolTable::SpecialFunctionKind kind, const std::string & otypeKey ) const {
    174162        static Stats::Counters::CounterGroup * special_stats = Stats::Counters::build<Stats::Counters::CounterGroup>("Special Lookups");
  • src/AST/SymbolTable.hpp

    r42cdd07d r0188539c  
    121121        /// Gets all declarations with the given ID
    122122        std::vector<IdData> lookupId( const std::string &id ) const;
    123         /// Gets all declarations with the given ID, ignoring hidden members from enumeration
    124         std::vector<IdData> lookupIdIgnoreHidden( const std::string &id ) const;
    125123        /// Gets special functions associated with a type; if no key is given, returns everything
    126124        std::vector<IdData> specialLookupId( SpecialFunctionKind kind, const std::string & otypeKey = "" ) const;
  • src/AST/Util.cpp

    r42cdd07d r0188539c  
    352352        void previsit( EnumDecl const * decl ) {
    353353                enumDecls.insert( decl );
    354                 for ( auto & member : decl->members ) {
    355                         typedDecls.insert( member.strict_as<ast::DeclWithType>() );
     354                if ( ast::EnumDecl::EnumHiding::Visible == decl->hide ) {
     355                        for ( auto & member : decl->members ) {
     356                                typedDecls.insert( member.strict_as<ast::DeclWithType>() );
     357                        }
    356358                }
    357359                beginScope();
  • src/GenPoly/Lvalue.cpp

    r42cdd07d r0188539c  
    389389                assert( 0 == diff );
    390390                // Remove useless generated casts.
    391                 if ( expr->isGenerated == ast::GeneratedFlag::GeneratedCast &&
     391                if ( expr->isGenerated &&
    392392                                ResolvExpr::typesCompatible(
    393393                                        expr->result,
     
    398398                                std::cerr << "-- " << expr->arg->result << std::endl;
    399399                        )
    400                         auto argAsEnum = expr->arg.as<ast::EnumInstType>();
    401                         auto resultAsEnum = expr->result.as<ast::EnumInstType>();
    402                         if (argAsEnum && resultAsEnum) {
    403                                 if (argAsEnum->base->name != resultAsEnum->base->name) {
    404                                         return expr;
    405                                 }
    406                         }
    407400                        return ast::mutate_field( expr->arg.get(),
    408401                                        &ast::Expr::env, expr->env.get() );
  • src/Parser/TypeData.cpp

    r42cdd07d r0188539c  
    14651465        ret->hide = td->aggregate.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
    14661466        for ( const DeclarationNode * cur = td->aggregate.fields ; cur != nullptr ; cur = cur->next, ++members ) {
    1467                 if (cur->enumInLine) continue;
    1468                 ast::Decl * member = members->get_and_mutate();
    1469                 ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
    1470                 object->isHidden = ast::EnumDecl::EnumHiding::Hide == ret->hide;
    1471                 if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
     1467                if ( cur->enumInLine ) {
     1468                        // Do Nothing
     1469                } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
    14721470                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
    14731471                } else if ( cur->has_enumeratorValue() ) {
     1472                        ast::Decl * member = members->get_and_mutate();
     1473                        ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
    14741474                        object->init = new ast::SingleInit(
    14751475                                td->location,
     
    14771477                                ast::NoConstruct
    14781478                        );
    1479                 }
     1479                } else if ( !cur->initializer ) {
     1480                        if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
     1481                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
     1482                        }
     1483                }
    14801484                // else cur is a List Initializer and has been set as init in buildList()
    14811485                // if
  • src/Parser/parser.yy

    r42cdd07d r0188539c  
    28272827        | enumerator_list ',' visible_hide_opt identifier_or_type_name enumerator_value_opt
    28282828                { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
    2829         | enumerator_list ',' INLINE type_name
    2830                 { $$ = $1->set_last( DeclarationNode::newEnumInLine( $4->symbolic.name ) ); }
     2829        | enumerator_list ',' INLINE type_name enumerator_value_opt
     2830                { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); }
    28312831        ;
    28322832
  • src/ResolvExpr/CandidateFinder.cpp

    r42cdd07d r0188539c  
    513513                                        // add new result
    514514                                        assert( common );
    515 
    516                                         auto paramAsEnum = dynamic_cast<const ast::EnumInstType *>(paramType);
    517                                         auto argAsEnum =dynamic_cast<const ast::EnumInstType *>(argType);
    518                                         if (paramAsEnum && argAsEnum) {
    519                                                 if (paramAsEnum->base->name != argAsEnum->base->name) {
    520                                                         Cost c = castCost(argType, paramType, expr, context.symtab, env);
    521                                                         if (c < Cost::infinity) {
    522                                                                 CandidateFinder subFinder( context, env );
    523                                                                 expr = subFinder.makeEnumOffsetCast(argAsEnum, paramAsEnum, expr, c);
    524                                                                 results.emplace_back(
    525                                                                         i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    526                                                                         nextArg + 1, nTuples, expl.cost + c, expl.exprs.size() == 1 ? 0 : 1, j );
    527                                                                 continue;
    528                                                         } else {
    529                                                                 std::cerr << "Cannot instantiate " << paramAsEnum->base->name <<  " with " << argAsEnum->base->name << std::endl;
    530                                                         }
    531                                                 }
    532                                         }
    533                                         results.emplace_back(
    534                                                 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    535                                                 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
     515                                                results.emplace_back(
     516                                                        i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
     517                                                        nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
     518                                        //}
    536519                                }
    537520                        }
     
    649632                        const ast::BaseInstType * aggrInst, const ast::Expr * expr,
    650633                        const Candidate & cand, const Cost & addedCost, const std::string & name
    651                 );
    652 
    653                 void addEnumValueAsCandidate(const ast::EnumInstType * instType, const ast::Expr * expr,
    654                         const Cost & addedCost
    655634                );
    656635
     
    697676                void postvisit( const ast::QualifiedNameExpr * qualifiedExpr );
    698677
    699                 const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src,
    700                         const ast::EnumInstType * dst
    701                         , const ast::Expr * expr, Cost minCost );
    702 
    703678                void postvisit( const ast::InitExpr * ) {
    704679                        assertf( false, "CandidateFinder should never see a resolved InitExpr." );
     
    901876        }
    902877
    903         void Finder::addEnumValueAsCandidate( const ast::EnumInstType * enumInst, const ast::Expr * expr,
    904                 const Cost & addedCost
    905         ) {
    906                 if ( enumInst->base->base ) {
    907                         CandidateFinder finder( context, tenv );
    908                         auto location = expr->location;
    909                         auto callExpr = new ast::UntypedExpr(
    910                                 location, new ast::NameExpr( location, "valueE" ), {expr}
    911                         );
    912                         finder.find( callExpr );
    913                         CandidateList winners = findMinCost( finder.candidates );
    914                         if (winners.size() != 1) {
    915                                 SemanticError( callExpr, "Ambiguous expression in valueE..." );
    916                         }
    917                         CandidateRef & choice = winners.front();
    918                         choice->cost += addedCost;
    919                         addAnonConversions(choice);
    920                         candidates.emplace_back( std::move(choice) );
    921                 }
    922         }
    923 
    924878        /// Adds implicit struct-conversions to the alternative list
    925879        void Finder::addAnonConversions( const CandidateRef & cand ) {
     
    940894                        addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" );
    941895                } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
    942                         addEnumValueAsCandidate(enumInst, aggrExpr, Cost::unsafe);
    943                 }
    944         }
    945        
     896                        if ( enumInst->base->base ) {
     897                                CandidateFinder finder( context, tenv );
     898                                auto location = aggrExpr->location;
     899                                auto callExpr = new ast::UntypedExpr(
     900                                        location, new ast::NameExpr( location, "valueE" ), {aggrExpr}
     901                                );
     902                                finder.find( callExpr );
     903                                CandidateList winners = findMinCost( finder.candidates );
     904                                if (winners.size() != 1) {
     905                                        SemanticError( callExpr, "Ambiguous expression in valueE..." );
     906                                }
     907                                CandidateRef & choice = winners.front();
     908                                choice->cost = Cost::unsafe;
     909                                candidates.emplace_back( std::move(choice) );
     910                        }
     911
     912                }
     913        }
    946914
    947915        /// Adds aggregate member interpretations
     
    12121180        }
    12131181
    1214         // src is a subset of dst
    1215         const ast::Expr * Finder::makeEnumOffsetCast( const ast::EnumInstType * src,
    1216                 const ast::EnumInstType * dst,
    1217                 const ast::Expr * expr,
    1218                 Cost minCost ) {
    1219                
    1220                 auto srcDecl = src->base;
    1221                 auto dstDecl = dst->base;
    1222 
    1223                 if (srcDecl->name == dstDecl->name) return expr;
    1224 
    1225                 for (auto& dstChild: dstDecl->inlinedDecl) {
    1226                         Cost c = castCost(src, dstChild, false, symtab, tenv);
    1227                         ast::CastExpr * castToDst;
    1228                         if (c<minCost) {
    1229                                 unsigned offset = dstDecl->calChildOffset(dstChild.get());
    1230                                 if (offset > 0) {
    1231                                         auto untyped = ast::UntypedExpr::createCall(
    1232                                                 expr->location,
    1233                                                 "?+?",
    1234                                                 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ),
    1235                                                 ast::ConstantExpr::from_int(expr->location, offset)});
    1236                                         CandidateFinder finder(context, tenv);
    1237                                         finder.find( untyped );
    1238                                         CandidateList winners = findMinCost( finder.candidates );
    1239                                         CandidateRef & choice = winners.front();
    1240                                         // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    1241                                         choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast);
    1242                                         // castToDst = new ast::CastExpr(choice->expr, dstChild);
    1243                                         castToDst = new ast::CastExpr(
    1244                                                 makeEnumOffsetCast( src, dstChild, choice->expr, minCost ),
    1245                                          dst);
    1246 
    1247                                 } else {
    1248                                         castToDst = new ast::CastExpr( expr, dst );
    1249                                 }
    1250                                 return castToDst;
    1251                         }
    1252                 }
    1253                 SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name);
    1254                 return nullptr;
    1255         }
    1256 
    12571182        void Finder::postvisit( const ast::CastExpr * castExpr ) {
    12581183                ast::ptr< ast::Type > toType = castExpr->result;
     
    13041229                                        ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )
    13051230                                        : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );
    1306                        
    1307                         // Redefine enum cast
    1308                         auto argAsEnum = cand->expr->result.as<ast::EnumInstType>();
    1309                         auto toAsEnum = toType.as<ast::EnumInstType>();
    1310                         if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) {     
    1311                                 ast::ptr<ast::Expr> offsetExpr = makeEnumOffsetCast(argAsEnum, toAsEnum, cand->expr, thisCost);
    1312                                 cand->expr = offsetExpr;
    1313                         }
    13141231
    13151232                        PRINT(
     
    13291246                                        minCastCost = thisCost;
    13301247                                        matches.clear();
    1331                                 }
    1332                                 // ambigious case, still output candidates to print in error message
     1248
     1249
     1250                                }
     1251                                // ambiguous case, still output candidates to print in error message
    13331252                                if ( cand->cost == minExprCost && thisCost == minCastCost ) {
    13341253                                        CandidateRef newCand = std::make_shared<Candidate>(
     
    13451264                }
    13461265                candidates = std::move(matches);
     1266
    13471267                //CandidateList minArgCost = findMinCost( matches );
    13481268                //promoteCvtCost( minArgCost );
     
    14541374                        }
    14551375                } else {
    1456                         declList = symtab.lookupIdIgnoreHidden( nameExpr->name );
     1376                        declList = symtab.lookupId( nameExpr->name );
    14571377                }
    14581378                PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     
    14661386                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    14671387
     1388                        // bool bentConversion = false;
     1389                        // if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) {
     1390                        //      if ( inst->base && inst->base->base ) {
     1391                        //              bentConversion = true;
     1392                        //      }
     1393                        // }
     1394
     1395                        // CandidateRef newCand = std::make_shared<Candidate>(
     1396                        //      newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero,
     1397                        //      cost );
    14681398                        CandidateRef newCand = std::make_shared<Candidate>(
    14691399                                newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     
    18831813                        if ( const ast::EnumInstType * enumInstType =
    18841814                                dynamic_cast<const ast::EnumInstType *>( t ) ) {
    1885                                 if ( (enumInstType->base->name == expr->type_name)
    1886                                         || (expr->type_decl && enumInstType->base->name == expr->type_decl->name) ) {
     1815                                if ( enumInstType->base->name == expr->type_decl->name ) {
    18871816                                        Cost cost = Cost::zero;
    18881817                                        ast::Expr * newExpr = data.combine( expr->location, cost );
     1818                                        // CandidateRef newCand =
     1819                                        //      std::make_shared<Candidate>(
     1820                                        //              newExpr, copy( tenv ), ast::OpenVarSet{},
     1821                                        //              ast::AssertionSet{}, Cost::safe, cost
     1822                                        //      );
    18891823                                        CandidateRef newCand =
    18901824                                                std::make_shared<Candidate>(
     
    21622096
    21632097        return expr;
    2164 }
    2165 
    2166 const ast::Expr * CandidateFinder::makeEnumOffsetCast( const ast::EnumInstType * src,
    2167         const ast::EnumInstType * dst,
    2168         const ast::Expr * expr,
    2169         Cost minCost ) {
    2170        
    2171         auto srcDecl = src->base;
    2172         auto dstDecl = dst->base;
    2173 
    2174         if (srcDecl->name == dstDecl->name) return expr;
    2175 
    2176         for (auto& dstChild: dstDecl->inlinedDecl) {
    2177                 Cost c = castCost(src, dstChild, false, context.symtab, env);
    2178                 ast::CastExpr * castToDst;
    2179                 if (c<minCost) {
    2180                         unsigned offset = dstDecl->calChildOffset(dstChild.get());
    2181                         if (offset > 0) {
    2182                                 auto untyped = ast::UntypedExpr::createCall(
    2183                                         expr->location,
    2184                                         "?+?",
    2185                                         { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ),
    2186                                         ast::ConstantExpr::from_int(expr->location, offset)});
    2187                                 CandidateFinder finder(context, env);
    2188                                 finder.find( untyped );
    2189                                 CandidateList winners = findMinCost( finder.candidates );
    2190                                 CandidateRef & choice = winners.front();
    2191                                 choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast);
    2192                                 castToDst = new ast::CastExpr(
    2193                                         makeEnumOffsetCast( src, dstChild, choice->expr, minCost ),
    2194                                         dst);
    2195                         } else {
    2196                                 castToDst = new ast::CastExpr( expr, dst );
    2197                         }
    2198                         return castToDst;
    2199                 }
    2200         }
    2201         SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name);
    2202         return nullptr;
    22032098}
    22042099
  • src/ResolvExpr/CandidateFinder.hpp

    r42cdd07d r0188539c  
    5858        iterator end() { return candidates.end(); }
    5959        const_iterator end() const { return candidates.end(); }
    60 
    61         const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src,
    62                 const ast::EnumInstType * dst, const ast::Expr * expr, Cost minCost );
    6360};
    6461
  • src/ResolvExpr/CastCost.cpp

    r42cdd07d r0188539c  
    3636namespace ResolvExpr {
    3737
    38 Cost castCost(
    39         const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    40         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    41 );
    42 
    4338namespace {
    4439        struct CastCost : public ConversionCost {
     
    5045                        const ast::TypeEnvironment & env, CostCalculation costFunc )
    5146                : ConversionCost( dst, srcIsLvalue, symtab, env, costFunc ) {}
    52 
    53                 void postvisit( const ast::EnumInstType * enumInst ) {
    54                         cost = conversionCost( enumInst, dst, srcIsLvalue, symtab, env );
    55                 }
    5647
    5748                void postvisit( const ast::BasicType * basicType ) {
     
    113104                                        cost = Cost::unsafe;
    114105                                }
     106                        }
     107                }
     108
     109                void postvist( const ast::EnumInstType * ) {
     110                        if ( auto basic = dynamic_cast< const ast::BasicType * >(dst) ) {
     111                                if ( basic->isInteger() ) cost = Cost::unsafe;
    115112                        }
    116113                }
  • src/ResolvExpr/CommonType.cpp

    r42cdd07d r0188539c  
    636636        void postvisit( const ast::UnionInstType * ) {}
    637637
    638         void postvisit( const ast::EnumInstType * param ) {
    639                 auto argAsEnumInst = dynamic_cast<const ast::EnumInstType *>(type2);
    640                 if ( argAsEnumInst ) {
    641                         const ast::EnumDecl* paramDecl = param->base;
    642                         const ast::EnumDecl* argDecl = argAsEnumInst->base;
    643                         if (argDecl->isSubTypeOf(paramDecl)) result = param;
    644                 } else if ( param->base && !param->base->isTyped ) {
     638        void postvisit( const ast::EnumInstType * enumInst ) {
     639                if ( enumInst->base && !enumInst->base->isTyped ) {
    645640                        auto basicType = new ast::BasicType( ast::BasicKind::UnsignedInt );
    646641                        result = commonType( basicType, type2, tenv, need, have, open, widen);
  • src/ResolvExpr/ConversionCost.cpp

    r42cdd07d r0188539c  
    191191}
    192192
    193 Cost enumCastCost (
    194         const ast::EnumInstType * src, const ast::EnumInstType * dst,
    195         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    196 );
    197 
    198193static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    199194                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     
    364359
    365360void ConversionCost::postvisit( const ast::EnumInstType * inst ) {
    366         if ( auto dstInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
    367                 cost = enumCastCost(inst, dstInst, symtab, env);
     361        if ( auto dstAsInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
     362                if (inst->base && dstAsInst->base) {
     363                        if (inst->base->name == dstAsInst->base->name) {
     364                                cost = Cost::zero;
     365                                return;
     366                        }
     367                }
    368368                return;
    369369        }
     
    481481}
    482482
    483 // (dst) src is safe is src is a subtype of dst, or dst {inline src, ...}
    484 Cost enumCastCost (
    485         const ast::EnumInstType * src, const ast::EnumInstType * dst,
    486         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    487 ) {
    488         auto srcDecl = src->base;
    489         auto dstDecl = dst->base;
    490         if (srcDecl->name == dstDecl->name) return Cost::safe;
    491         Cost minCost = Cost::infinity;
    492         for (auto child: dstDecl->inlinedDecl) {
    493                 Cost c = enumCastCost(src, child, symtab, env) + Cost::safe;
    494                 if (c<minCost) minCost = c;
    495         }
    496         return minCost;
    497 }
    498 
    499 
    500483// size_t ConversionCost::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
    501484
  • src/ResolvExpr/Resolver.cpp

    r42cdd07d r0188539c  
    201201                                && typesCompatible( castExpr->arg->result, castExpr->result )
    202202                        ) {
    203                                 auto argAsEnum = castExpr->arg.as<ast::EnumInstType>();
    204                                 auto resultAsEnum = castExpr->result.as<ast::EnumInstType>();
    205                                 if (argAsEnum && resultAsEnum) {
    206                                         if (argAsEnum->base->name != resultAsEnum->base->name) {
    207                                                 std::cerr << "Enum Cast: " << argAsEnum->base->name << " to " << resultAsEnum->base->name << std::endl;
    208                                                 return castExpr;
    209                                         }
    210                                 }
    211203                                // generated cast is the same type as its argument, remove it after keeping env
    212204                                return ast::mutate_field(
  • src/Validate/Autogen.cpp

    r42cdd07d r0188539c  
    410410}
    411411
    412 /// Use the current type T to create `T ?=?(T & _dst, T _src)`.
     412/// Use the current type T to create `T ?{}(T & _dst, T _src)`.
    413413ast::FunctionDecl * FuncGenerator::genAssignProto() const {
    414414        // Only the name is different, so just reuse the generation function.
  • src/Validate/EnumAndPointerDecay.cpp

    r42cdd07d r0188539c  
    4747                                new ast::EnumInstType( decl, ast::CV::Const ) ) );
    4848                } else if ( auto value = member.as<ast::InlineMemberDecl>() ) {
    49                         auto targetEnum = symtab.lookupEnum( value->name );
    50                         // assert( targetEnum );
    51                         if (!targetEnum) {
    52                                 SemanticError(value, "Only another enum is allowed for enum inline syntax ");
    53                         }
    54                         const ast::EnumInstType * instType = new ast::EnumInstType(targetEnum);
    55                         mut->inlinedDecl.push_back( std::move(instType) );
    56                         for ( auto enumMember : targetEnum->members ) {
    57                                 auto enumObject = enumMember.strict_as<ast::ObjectDecl>();
    58                                 buffer.push_back(new ast::ObjectDecl(
    59                                         // Get the location from the "inline" declaration.
    60                                         value->location,
    61                                         enumObject->name,
    62                                         // Construct a new EnumInstType as the type.
    63                                         new ast::EnumInstType( decl, ast::CV::Const ),
    64                                         enumObject->init,
    65                                         enumObject->storage,
    66                                         enumObject->linkage,
    67                                         enumObject->bitfieldWidth,
    68                                         {},
    69                                         enumObject->funcSpec
    70                                 ));
     49                        if ( auto targetEnum = symtab.lookupEnum( value->name ) ) {
     50                                for ( auto enumMember : targetEnum->members ) {
     51                                        auto enumObject = enumMember.strict_as<ast::ObjectDecl>();
     52                                        buffer.push_back( new ast::ObjectDecl(
     53                                                // Get the location from the "inline" declaration.
     54                                                value->location,
     55                                                enumObject->name,
     56                                                // Construct a new EnumInstType as the type.
     57                                                new ast::EnumInstType( decl, ast::CV::Const ),
     58                                                enumObject->init,
     59                                                enumObject->storage,
     60                                                enumObject->linkage,
     61                                                enumObject->bitfieldWidth,
     62                                                {},
     63                                                enumObject->funcSpec
     64                                        ) );
     65                                }
    7166                        }
    7267                }
  • src/Validate/ImplementEnumFunc.cpp

    r42cdd07d r0188539c  
    1010        const ast::EnumDecl* decl;
    1111        unsigned int functionNesting;
    12         const ast::StructDecl* quasi_void_decl;
    1312        ast::Linkage::Spec proto_linkage;
    1413
     
    2524                : decl(decl),
    2625                  functionNesting{functionNesting},
    27                   quasi_void_decl(new ast::StructDecl(decl->location,
    28                         "quasi_void", ast::AggregateDecl::Struct,
    29                         {}, ast::Linkage::AutoGen)),
    3026                  proto_linkage{ast::Linkage::Cforall} {}
    3127
     
    5652        void genSuccPredBody(ast::FunctionDecl *, const char *) const;
    5753
    58         void genTypeNameFunc();
    59 
    6054        // Implement TypedEnum trait
    6155        void genTypedEnumFuncs();
     
    6458        ast::FunctionDecl* genLabelProto() const;
    6559        ast::FunctionDecl* genValueProto() const;
    66         ast::FunctionDecl* genQuasiValueProto() const;
    67         ast::FunctionDecl* genTypeNameProto() const;
    68 
    6960        void genValueOrLabelBody(
    7061                ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
    7162        void genPosnBody(ast::FunctionDecl* func) const;
    72         void genQuasiValueBody(ast::FunctionDecl* func) const;
    73         void genTypeNameBody(ast::FunctionDecl* func) const;
     63
     64        ////////////////
     65
     66        // ---------------------------------------------------
     67        // ast::FunctionDecl* genAttrCtorProto() const;
     68        /// Changes the node inside a pointer so that it has the unused attribute.
     69        void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) {
     70                ast::DeclWithType* decl = declPtr.get_and_mutate();
     71                decl->attributes.push_back(new ast::Attribute("unused"));
     72        }
    7473
    7574        // ----------------------------------------------------
     
    118117        return inits;
    119118}
    120 
    121119const ast::Init* EnumAttrFuncGenerator::getAutoInit(
    122120        const ast::Init* prev) const {
     
    191189
    192190ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
    193         if (decl->base)
    194                 return genProto(
    195                         "valueE",
    196                         {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    197                         {new ast::ObjectDecl(getLocation(), "_ret",
    198                                                                 ast::deepCopy(decl->base))});
    199         else
    200                 return genQuasiValueProto();
    201 }
    202 
    203 ast::FunctionDecl* EnumAttrFuncGenerator::genQuasiValueProto() const {
    204191        return genProto(
    205192                "valueE",
    206193                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    207194                {new ast::ObjectDecl(getLocation(), "_ret",
    208                                                 new ast::StructInstType(quasi_void_decl))});
     195                                     ast::deepCopy(decl->base))});
    209196}
    210197
     
    223210                {new ast::ObjectDecl(getLocation(), "_ret", new ast::BasicType(ast::BasicKind::UnsignedInt))}
    224211        );
    225 }
    226 
    227 ast::FunctionDecl* EnumAttrFuncGenerator::genTypeNameProto() const {
    228         return genProto(
    229                 "type_name",
    230                 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
    231                 {new ast::ObjectDecl(
    232                         getLocation(), "_ret",
    233                         new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}))});
    234212}
    235213
     
    290268        );
    291269}
     270
    292271
    293272void EnumAttrFuncGenerator::genSerialTraitFuncs() {
     
    323302        const CodeLocation & loc = func->location;
    324303        auto mem = func->name=="lowerBound"?  decl->members.front() : decl->members.back();
    325         // auto expr = new ast::NameExpr( loc, mem->name );
    326         auto expr = new ast::QualifiedNameExpr( loc, decl->name, mem->name );
     304        auto expr = new ast::NameExpr( loc, mem->name );
    327305        func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});
    328306}
     
    371349}
    372350
    373 void EnumAttrFuncGenerator::genQuasiValueBody(ast::FunctionDecl* func) const {
    374         auto location = func->location;
    375         const ast::ObjectDecl * objDecl = new ast::ObjectDecl(
    376                 location, "_out", new ast::StructInstType( quasi_void_decl ));
    377         const ast::DeclStmt * declStmt = new ast::DeclStmt(location, objDecl);
    378         const ast::VariableExpr * varExpr = new ast::VariableExpr(location, objDecl);
    379         const ast::ReturnStmt * retStmt = new ast::ReturnStmt(location, varExpr);
    380 
    381         func->stmts = new ast::CompoundStmt(
    382                 location, {declStmt, retStmt}
    383         );
    384 }
    385 
    386351void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
    387352        auto castExpr = new ast::CastExpr(
     
    394359}
    395360
    396 void EnumAttrFuncGenerator::genTypeNameBody(ast::FunctionDecl* func) const {
    397         const ast::Expr * type_name = ast::ConstantExpr::from_string(func->location, decl->name);
    398         func->stmts = new ast::CompoundStmt(
    399                 func->location, {new ast::ReturnStmt(func->location, type_name)}
    400         );
    401 }
    402 
    403361void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) {
    404         if (attr == ast::EnumAttribute::Value) {
    405                 if (decl->base) {
    406                         // TypedEnum's backing arrays
    407                         std::vector<ast::ptr<ast::Init>> inits = genValueInit();
    408                         ast::ObjectDecl* arrayProto =
    409                                 genAttrArrayProto(attr, getLocation(), inits);
    410                         forwards.push_back(arrayProto);
    411 
    412                         ast::FunctionDecl* funcProto = genValueProto();
    413                         produceForwardDecl(funcProto);
    414                         genValueOrLabelBody(funcProto, arrayProto);
    415                         produceDecl(funcProto);
    416                 }  else {
    417                         ast::FunctionDecl* funcProto = genQuasiValueProto();
    418                         produceForwardDecl(funcProto);
    419                         genQuasiValueBody(funcProto);
    420                         produceDecl(funcProto);
    421                 }
    422         } else if (attr == ast::EnumAttribute::Label) {
    423                 std::vector<ast::ptr<ast::Init>> inits = genLabelInit();
     362        if (attr == ast::EnumAttribute::Value ||
     363                attr == ast::EnumAttribute::Label) {
     364                // TypedEnum's backing arrays
     365                std::vector<ast::ptr<ast::Init>> inits =
     366                        attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit();
    424367                ast::ObjectDecl* arrayProto =
    425368                        genAttrArrayProto(attr, getLocation(), inits);
    426369                forwards.push_back(arrayProto);
    427                 ast::FunctionDecl* funcProto = genLabelProto();
     370
     371                ast::FunctionDecl* funcProto = ( attr == ast::EnumAttribute::Value )
     372                                               ? genValueProto()
     373                                               : genLabelProto();
    428374                produceForwardDecl(funcProto);
    429375                genValueOrLabelBody(funcProto, arrayProto);
     
    438384
    439385void EnumAttrFuncGenerator::genTypedEnumFuncs() {
    440         genTypedEnumFunction(ast::EnumAttribute::Value);
     386        if (decl->base) genTypedEnumFunction(ast::EnumAttribute::Value);
    441387        genTypedEnumFunction(ast::EnumAttribute::Label);
    442388        genTypedEnumFunction(ast::EnumAttribute::Posn);
    443 }
    444 
    445 void EnumAttrFuncGenerator::genTypeNameFunc() {
    446         ast::FunctionDecl* funcProto = genTypeNameProto();
    447         produceForwardDecl(funcProto);
    448         genTypeNameBody(funcProto);
    449         produceDecl(funcProto);
    450389}
    451390
     
    453392        std::list<ast::ptr<ast::Decl>>& decls) {
    454393        // Generate the functions (they go into forwards and definitions).
    455         genTypeNameFunc();
    456394        genTypedEnumFuncs();
    457395        genSerialTraitFuncs();
  • tests/enum_tests/.expect/enumInlineValue.txt

    r42cdd07d r0188539c  
    1 Symbols (enumerator) should have the same values:
    2 Symbol a: (10) 10, 10, 10
    3 Symbol b: (20) 20, 20
    4 Symbol ab: (30) 30
    5 Symbol c: (40) 40, 40, 40
    6 Symbol d: (50) 50, 50, 50
    7 Symbol cd: (60) 60, 60
    8 Symbol acd: (70) 70
    9 Casting/Upcasting:
    10 Symbol a: (10) 10, 10, 10
    11 Symbol b: (20) 20, 20
    12 Symbol ab: (30) 30
    13 Symbol c: (40) 40, 40, 40, 40, 40
    14 Symbol d: (50) 50, 50, 50, 50
    15 Symbol cd: (60) 60, 60
    16 Symbol acd: (70) 70
    17 Function Call:
    18 Symbol a: (10) 10, 10
    19 Symbol c: (40) 40, 40
    20 Symbol d: (50) 50, 50
    21 Symbol cd: (60) 60, 60
    22 Symbol acd: (70) 70
     1enumB.A is 5
     2enumB.B is 6
     3enumB.D is 11
     4enumB.E is 12
  • tests/enum_tests/enumInlineValue.cfa

    r42cdd07d r0188539c  
    11#include <fstream.hfa>
    2 #include <enum.hfa>
    3 
    4 enum(int) A !{
    5     a = 10
     2enum enumA {
     3    A=5, B, C=10, D
    64};
    75
    8 enum(int) B {
    9     b = 20
     6enum enumB {
     7    inline enumA,
     8    E
    109};
    1110
    12 enum(int) AB {
    13     inline A,
    14     inline B,
    15     ab = 30
    16 };
    17 
    18 enum(int) C {
    19     c = 40
    20 };
    21 
    22 enum(int) D {
    23     d = 50
    24 };
    25 
    26 enum(int) CD {
    27     inline C,
    28     inline D,
    29     cd = 60
    30 };
    31 
    32 enum(int) ACD {
    33     inline A,
    34     inline CD,
    35     acd = 70
    36 };
    37 
    38 // Note: variable name (cat in this case) cannot be overloaded with those declared in enum,
    39 // Probably for the same reason as const overloading problem
    40 // i.e. int identity_t(enum ACD a) would not work as the valueE(a) is ambigious currently
    41 int identity_t(enum ACD cat) {
    42     return valueE(cat);
     11int main() {
     12    enum enumB val = A;
     13    sout | "enumB.A is" | val;
     14    enum enumB val2 = enumB.B;
     15    sout | "enumB.B is" | val2;
     16    sout | "enumB.D is" | enumB.D;
     17    sout | "enumB.E is" | enumB.E;
    4318}
    44 
    45 int main() {
    46     // Note: We need to use qualified name syntax even if no ! hidding
    47     // Because Inline introduce ambiguity on symbols
    48     sout | "Symbols (enumerator) should have the same values:" |nl;
    49     sout | "Symbol a: (10) " | valueE(A.a) | "," | valueE(AB.a) | "," | valueE(ACD.a) | nl;
    50     sout | "Symbol b: (20) " | valueE(B.b) | "," | valueE(AB.b) | nl;
    51     sout | "Symbol ab: (30) " | valueE(AB.ab) | nl;
    52     sout | "Symbol c: (40) " | valueE(C.c) | "," | valueE(CD.c) | "," | valueE(ACD.c) | nl;
    53     sout | "Symbol d: (50) " | valueE(D.d) | "," | valueE(CD.d) | "," | valueE(ACD.d) | nl;
    54     sout | "Symbol cd: (60) " | valueE(CD.cd) | "," | valueE(ACD.cd) | nl;
    55     sout | "Symbol acd: (70) " | valueE(ACD.acd) | nl;
    56 
    57     sout | "Casting/Upcasting:" | nl;
    58     sout | "Symbol a: (10) " | valueE((A)A.a) | "," | valueE((AB)A.a) | "," | valueE((ACD)A.a) | nl;
    59     sout | "Symbol b: (20) " | valueE((B)B.b) | "," | valueE((AB)B.b) | nl;
    60     sout | "Symbol ab: (30) " | valueE((AB)AB.ab) | nl;
    61     sout | "Symbol c: (40) " | valueE((C)C.c) | "," | valueE((CD)C.c) | "," | valueE((ACD)C.c) | "," | valueE((CD)CD.c)| "," | valueE((ACD)CD.c) | nl;
    62     sout | "Symbol d: (50) " | valueE((D)D.d) | "," | valueE((CD)D.d) | "," | valueE((ACD)D.d) | "," | valueE((ACD)CD.d) | nl;
    63     sout | "Symbol cd: (60) " | valueE((CD)CD.cd) | "," | valueE((ACD)CD.cd) | nl;
    64     sout | "Symbol acd: (70) " | valueE((ACD)ACD.acd) | nl;
    65 
    66     sout | "Function Call:" | nl;
    67     sout | "Symbol a: (10) " | identity_t(A.a) | "," | identity_t(ACD.a) | nl;
    68     sout | "Symbol c: (40) " | identity_t(C.c) | "," | identity_t(ACD.c) | nl;
    69     sout | "Symbol d: (50) " | identity_t(D.d) | "," | identity_t(ACD.d) | nl;
    70     sout | "Symbol cd: (60) " | identity_t(CD.cd) | "," | identity_t(ACD.cd) | nl;
    71     sout | "Symbol acd: (70) " | identity_t(ACD.acd) | nl;
    72 }
Note: See TracChangeset for help on using the changeset viewer.