Changes in / [e6f1a4b:fbc84ca]


Ignore:
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/jiada_liang_MMath/CFAenum.tex

    re6f1a4b rfbc84ca  
    7070As in Section~\ref{s:EnumeratorVisibility}, opening multiple scoped enumerations in a @with@ can result in duplicate enumeration names, but \CFA implicit type resolution and explicit qualification/casting handle ambiguities.
    7171
    72 \section{Enumeration Trait}
    73 
    74 The header file \lstinline[deletekeywords=enum]{<enum.hfa>} defines the set of traits containing operators and helper functions for @enum@.
    75 A \CFA enumeration satisfies all of these traits allowing it to interact with runtime features in \CFA.
    76 Each trait is discussed in detail.
    77 
    78 The trait @Bounded@:
    79 \begin{cfa}
    80 forall( E ) trait Bounded {
    81         E first();
    82         E last();
    83 };
    84 \end{cfa}
    85 defines the bounds of the enumeration, where @first()@ returns the first enumerator and @last()@ returns the last, \eg:
    86 \begin{cfa}
    87 Workday day = first();                                  $\C{// Mon}$
    88 Planet outermost = last();                              $\C{// NEPTUNE}$
    89 \end{cfa}
    90 @first()@ and @last()@ are overloaded with return types only, so in the example, the enumeration type is found on the left-hand side of the assignment.
    91 Calling either functions without a context results in a type ambiguity, except in the rare case where the type environment has only one enumeration.
    92 \begin{cfa}
    93 @first();@                                                              $\C{// ambiguous Workday and Planet implement Bounded}$
    94 sout | @last()@;
    95 Workday day = first();                                  $\C{// day provides type Workday}$
    96 void foo( Planet p );
    97 foo( last() );                                                  $\C{// parameter provides type Planet}$
    98 \end{cfa}
    99 
    100 The trait @Serial@:
    101 \begin{cfa}
    102 forall( E | Bounded( E ) ) trait Serial {
    103         unsigned fromInstance( E e );
    104         E fromInt( unsigned int posn );
    105         E succ( E e );
    106         E pred( E e );
    107 };
    108 \end{cfa}
    109 is a @Bounded@ trait, where elements can be mapped to an integer sequence.
    110 A type @T@ matching @Serial@ can project to an unsigned @int@ type, \ie an instance of type T has a corresponding integer value.
    111 %However, the inverse may not be possible, and possible requires a bound check.
    112 The mapping from a serial type to integer is defined by @fromInstance@, which returns the enumerator's position.
    113 The inverse operation is @fromInt@, which performs a bound check using @first()@ and @last()@ before casting the integer into an enumerator.
    114 Specifically, for enumerator @E@ declaring $N$ enumerators, @fromInt( i )@ returns the $i-1_{th}$ enumerator, if $0 \leq i < N$, or raises the exception @enumBound@.
    115 
    116 The @Serial@ trait also requires interface functions @succ( E e )@ and @pred( E e )@ be implemented for a serial type, which imply the enumeration positions are consecutive and ordinal.
    117 Specifically, if @e@ is the $i_{th}$ enumerator, @succ( e )@ returns the $i+1_{th}$ enumerator when $e \ne last()$, and @pred( e )@ returns the $i-1_{th}$ enumerator when $e \ne first()$.
    118 The exception @enumRange@ is raised if the result of either operation is outside the range of type @E@.
    119 
    120 The trait @TypedEnum@:
    121 \begin{cfa}
    122 forall( E, T ) trait TypedEnum {
    123         T valueE( E e );
    124         char * labelE( E e );
    125         unsigned int posE( E e );
    126 };
    127 \end{cfa}
    128 captures three basic attributes of an enumeration type: value, label, and position.
    129 @TypedEnum@ asserts two types @E@ and @T@, with @T@ being the base type of the enumeration @E@, \eg @enum( T ) E { ... };@.
    130 Implementing general functions across all enumeration types is possible by asserting @TypeEnum( E, T )@, \eg:
    131 \begin{cfa}
    132 forall( E, T | TypeEnum( E, T ) )
    133 void printEnum( E e ) {
    134         sout | "Enum "| labelE( e );
    135 }
    136 printEunm( MARS );
    137 \end{cfa}
    138 
    139 Finally, there is an associated trait defining comparison operators among enumerators.
    140 \begin{cfa}
    141 forall( E, T | TypedEnum( E, T ) ) {
    142         // comparison
    143         int ?==?( E l, E r );           $\C{// true if l and r are same enumerators}$
    144         int ?!=?( E l, E r );           $\C{// true if l and r are different enumerators}$
    145         int ?!=?( E l, zero_t );        $\C{// true if l is not the first enumerator}$
    146         int ?<?( E l, E r );            $\C{// true if l is an enumerator before r}$
    147         int ?<=?( E l, E r );           $\C{// true if l before or the same as r}$
    148         int ?>?( E l, E r );            $\C{// true if l is an enumerator after r}$
    149         int ?>=?( E l, E r );           $\C{// true if l after or the same as r}$         
    150 }
    151 \end{cfa}
    152 Note, the overloaded operators are defined only when the header @<enum.hfa>@ is included.
    153 If not, the compiler converts an enumerator to its value, and applies the operators defined for the value type @E@, \eg:
    154 \begin{cfa}
    155 // if not include <enum.hfa>
    156 enum( int ) Fruits { APPLE = 2, BANANA = 10, CHERRY = 2 };
    157 APPLE == CHERRY; // true because valueE( APPLE ) == valueE( CHERRY )
    158 
    159 #include <enum.hfa>
    160 APPLE == CHERRY; // false because posE( APPLE ) != posE( CHERRY )
    161 \end{cfa}
    162 An enumerator returns its @position@ by default.
    163 In particular, @printf( ... )@ from @<stdio.h>@ functions provides no context to its parameter type, so it prints @position@.
    164 On the other hand, the pipeline operator @?|?( ostream os, E enumType )@ provides type context for type @E@, and \CFA has overwritten this operator to print the enumeration @value@ over @position@.
    165 \begin{cfa}
    166 printf( "Position of BANANA is \%d", BANANA ); // Position of BANANA is 1
    167 sout | "Value of BANANA is " | BANANA; // Value of BANANA is 10
    168 \end{cfa}
    169 Programmers can overwrite this behaviour by overloading the pipeline operator themselves.
    170 \PAB{This needs discussing because including \lstinline{<enum.hfa>} can change the entire meaning of a program.}
    171 
    172 
    173 % \section{Enumeration Pseudo-functions}
    174 
    175 % Pseudo-functions are function-like operators that do not result in any run-time computations, \ie like @sizeof@, @alignof@, @typeof@.
    176 % A pseudo-function call is often substituted with information extracted from the compilation symbol-table, like storage size or alignment associated with the underlying architecture.
    177 
    178 % The attributes of an enumerator are accessed by pseudo-functions @posE@, @valueE@, and @labelE@.
    179 % \begin{cfa}
    180 % int jane_pos = @posE@( Names.Jane );   $\C{// 2}$
    181 % char * jane_value = @valueE@( Names.Jane ); $\C{// "JANE"}$
    182 % char * jane_label = @labelE@( Names.Jane ); $\C{// "Jane"}$
    183 % sout | posE( Names.Jane) | labelE( Names.Jane ) | valueE( Names.Jane );
    184 % \end{cfa}
    185 % Note the ability to print all of an enumerator's properties.
    186 
     72
     73\section{Enumeration Pseudo-functions}
     74
     75Pseudo-functions are function-like operators that do not result in any run-time computations, \ie like @sizeof@, @alignof@, @typeof@.
     76A pseudo-function call is often substituted with information extracted from the compilation symbol-table, like storage size or alignment associated with the underlying architecture.
     77
     78The attributes of an enumerator are accessed by pseudo-functions @posE@, @valueE@, and @labelE@.
     79\begin{cfa}
     80int jane_pos = @posE@( Names.Jane );   $\C{// 2}$
     81char * jane_value = @valueE@( Names.Jane ); $\C{// "JANE"}$
     82char * jane_label = @labelE@( Names.Jane ); $\C{// "Jane"}$
     83sout | posE( Names.Jane) | labelE( Names.Jane ) | valueE( Names.Jane );
     84\end{cfa}
     85Note the ability to print all of an enumerator's properties.
    18786
    18887
     
    371270
    372271
    373 
    374 \section{Enumerated Arrays}
    375 Enumerated array use an \CFA array as their index.
    376 \begin{cfa}
    377 enum() Colour {
    378         Red, Orange, Yellow, Green, Blue, Indigo, Violet
     272\section{Enumeration Trait}
     273
     274The header file \lstinline[deletekeywords=enum]{<enum.hfa>} defines the set of traits containing operators and helper functions for @enum@.
     275A \CFA enumeration satisfies all of these traits allowing it to interact with runtime features in \CFA.
     276Each trait is discussed in detail.
     277
     278The trait @Bounded@:
     279\begin{cfa}
     280forall( E ) trait Bounded {
     281        E first();
     282        E last();
    379283};
    380 
    381 string colourCode[Colour] = { "#e81416", "#ffa500", "#ffa500", "#ffa500", "#487de7", "#4b369d", "#70369d" };
    382 sout | "Colour Code of Orange is " | colourCode[Orange];
    383 \end{cfa}
     284\end{cfa}
     285defines the bounds of the enumeration, where @first()@ returns the first enumerator and @last()@ returns the last, \eg:
     286\begin{cfa}
     287Workday day = first();                                  $\C{// Mon}$
     288Planet outermost = last();                              $\C{// NEPTUNE}$
     289\end{cfa}
     290@first()@ and @last()@ are overloaded with return types only, so in the example, the enumeration type is found on the left-hand side of the assignment.
     291Calling either functions without a context results in a type ambiguity, except in the rare case where the type environment has only one enumeration.
     292\begin{cfa}
     293@first();@                                                              $\C{// ambiguous Workday and Planet implement Bounded}$
     294sout | @last()@;
     295Workday day = first();                                  $\C{// day provides type Workday}$
     296void foo( Planet p );
     297foo( last() );                                                  $\C{// parameter provides type Planet}$
     298\end{cfa}
     299
     300The trait @Serial@:
     301\begin{cfa}
     302forall( E | Bounded( E ) ) trait Serial {
     303        unsigned fromInstance( E e );
     304        E fromInt( unsigned int posn );
     305        E succ( E e );
     306        E pred( E e );
     307};
     308\end{cfa}
     309is a @Bounded@ trait, where elements can be mapped to an integer sequence.
     310A type @T@ matching @Serial@ can project to an unsigned @int@ type, \ie an instance of type T has a corresponding integer value.
     311%However, the inverse may not be possible, and possible requires a bound check.
     312The mapping from a serial type to integer is defined by @fromInstance@, which returns the enumerator's position.
     313The inverse operation is @fromInt@, which performs a bound check using @first()@ and @last()@ before casting the integer into an enumerator.
     314Specifically, for enumerator @E@ declaring $N$ enumerators, @fromInt( i )@ returns the $i-1_{th}$ enumerator, if $0 \leq i < N$, or raises the exception @enumBound@.
     315
     316The @Serial@ trait also requires interface functions @succ( E e )@ and @pred( E e )@ be implemented for a serial type, which imply the enumeration positions are consecutive and ordinal.
     317Specifically, if @e@ is the $i_{th}$ enumerator, @succ( e )@ returns the $i+1_{th}$ enumerator when $e \ne last()$, and @pred( e )@ returns the $i-1_{th}$ enumerator when $e \ne first()$.
     318The exception @enumRange@ is raised if the result of either operation is outside the range of type @E@.
     319
     320The trait @TypedEnum@:
     321\begin{cfa}
     322forall( E, T ) trait TypedEnum {
     323        T valueE( E e );
     324        char * labelE( E e );
     325        unsigned int posE( E e );
     326};
     327\end{cfa}
     328captures three basic attributes of an enumeration type: value, label, and position.
     329@TypedEnum@ asserts two types @E@ and @T@, with @T@ being the base type of the enumeration @E@, \eg @enum( T ) E { ... };@.
     330Implementing general functions across all enumeration types is possible by asserting @TypeEnum( E, T )@, \eg:
     331\begin{cfa}
     332forall( E, T | TypeEnum( E, T ) )
     333void printEnum( E e ) {
     334        sout | "Enum "| labelE( e );
     335}
     336printEunm( MARS );
     337\end{cfa}
     338
     339Finally, there is an associated trait defining comparison operators among enumerators.
     340\begin{cfa}
     341forall( E, T | TypedEnum( E, T ) ) {
     342        // comparison
     343        int ?==?( E l, E r );           $\C{// true if l and r are same enumerators}$
     344        int ?!=?( E l, E r );           $\C{// true if l and r are different enumerators}$
     345        int ?!=?( E l, zero_t );        $\C{// true if l is not the first enumerator}$
     346        int ?<?( E l, E r );            $\C{// true if l is an enumerator before r}$
     347        int ?<=?( E l, E r );           $\C{// true if l before or the same as r}$
     348        int ?>?( E l, E r );            $\C{// true if l is an enumerator after r}$
     349        int ?>=?( E l, E r );           $\C{// true if l after or the same as r}$         
     350}
     351\end{cfa}
     352Note, the overloaded operators are defined only when the header @<enum.hfa>@ is included.
     353If not, the compiler converts an enumerator to its value, and applies the operators defined for the value type @E@, \eg:
     354\begin{cfa}
     355// if not include <enum.hfa>
     356enum( int ) Fruits { APPLE = 2, BANANA = 10, CHERRY = 2 };
     357APPLE == CHERRY; // true because valueE( APPLE ) == valueE( CHERRY )
     358
     359#include <enum.hfa>
     360APPLE == CHERRY; // false because posE( APPLE ) != posE( CHERRY )
     361\end{cfa}
     362An enumerator returns its @position@ by default.
     363In particular, @printf( ... )@ from @<stdio.h>@ functions provides no context to its parameter type, so it prints @position@.
     364On the other hand, the pipeline operator @?|?( ostream os, E enumType )@ provides type context for type @E@, and \CFA has overwritten this operator to print the enumeration @value@ over @position@.
     365\begin{cfa}
     366printf( "Position of BANANA is \%d", BANANA ); // Position of BANANA is 1
     367sout | "Value of BANANA is " | BANANA; // Value of BANANA is 10
     368\end{cfa}
     369Programmers can overwrite this behaviour by overloading the pipeline operator themselves.
     370\PAB{This needs discussing because including \lstinline{<enum.hfa>} can change the entire meaning of a program.}
     371
    384372
    385373\section{Planet Example}
  • src/AST/Fwd.hpp

    re6f1a4b rfbc84ca  
    133133class OneType;
    134134class GlobalScopeType;
     135class EnumAttrType;
    135136
    136137class Designation;
  • src/AST/Pass.hpp

    re6f1a4b rfbc84ca  
    207207        const ast::Type *             visit( const ast::UnionInstType        * ) override final;
    208208        const ast::Type *             visit( const ast::EnumInstType         * ) override final;
     209        const ast::Type *             visit( const ast::EnumAttrType         * ) override final;
    209210        const ast::Type *             visit( const ast::TraitInstType        * ) override final;
    210211        const ast::Type *             visit( const ast::TypeInstType         * ) override final;
  • src/AST/Pass.impl.hpp

    re6f1a4b rfbc84ca  
    19401940
    19411941//--------------------------------------------------------------------------
     1942// EnumAttrType
     1943template< typename core_t >
     1944const ast::Type * ast::Pass< core_t >::visit( const ast::EnumAttrType * node ) {
     1945        VISIT_START( node );
     1946        VISIT_END( Type, node );
     1947}
     1948
     1949//--------------------------------------------------------------------------
    19421950// TraitInstType
    19431951template< typename core_t >
  • src/AST/Print.cpp

    re6f1a4b rfbc84ca  
    15761576        }
    15771577
     1578        virtual const ast::Type * visit( const ast::EnumAttrType * node ) override final {
     1579                preprint( node );
     1580                os << "enum attr ";
     1581                if ( node->attr == ast::EnumAttribute::Label ) {
     1582                        os << "Label ";
     1583                } else if ( node->attr == ast::EnumAttribute::Value ) {
     1584                        os << "Value ";
     1585                } else {
     1586                        os << "Posn ";
     1587                }
     1588                (*(node->instance)).accept( *this );
     1589                return node;
     1590        }
     1591
    15781592        virtual const ast::Type * visit( const ast::TraitInstType * node ) override final {
    15791593                preprint( node );
  • src/AST/Type.hpp

    re6f1a4b rfbc84ca  
    319319using EnumInstType = SueInstType<EnumDecl>;
    320320
     321class EnumAttrType final : public Type {
     322public:
     323        readonly<EnumInstType> instance;
     324        EnumAttribute attr;
     325        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     326        EnumAttrType( const EnumInstType * instance, EnumAttribute attr = EnumAttribute::Posn )
     327                : instance(instance), attr(attr) {}
     328
     329        bool match( const ast::EnumAttrType * other) const {
     330                return instance->base->name == other->instance->base->name && attr == other->attr;
     331        }
     332private:
     333        EnumAttrType * clone() const override { return new EnumAttrType{ *this }; }
     334        MUTATE_FRIEND
     335};
     336
    321337/// An instance of a trait type.
    322338class TraitInstType final : public BaseInstType {
  • src/AST/Visitor.hpp

    re6f1a4b rfbc84ca  
    119119    virtual const ast::Type *             visit( const ast::OneType              * ) = 0;
    120120    virtual const ast::Type *             visit( const ast::GlobalScopeType      * ) = 0;
     121    virtual const ast::Type *             visit( const ast::EnumAttrType         * ) = 0;
    121122    virtual const ast::Designation *      visit( const ast::Designation          * ) = 0;
    122123    virtual const ast::Init *             visit( const ast::SingleInit           * ) = 0;
  • src/CodeGen/GenType.cpp

    re6f1a4b rfbc84ca  
    4747        void postvisit( ast::UnionInstType const * type );
    4848        void postvisit( ast::EnumInstType const * type );
     49        void postvisit( ast::EnumAttrType const * type );
    4950        void postvisit( ast::TypeInstType const * type );
    5051        void postvisit( ast::TupleType const * type );
     
    240241}
    241242
     243void GenType::postvisit( ast::EnumAttrType const * type ) {
     244        postvisit( type->instance );
     245}
     246
    242247void GenType::postvisit( ast::TypeInstType const * type ) {
    243248        assertf( !options.genC, "TypeInstType should not reach code generation." );
  • src/Common/CodeLocationTools.cpp

    re6f1a4b rfbc84ca  
    188188    macro(UnionInstType, Type) \
    189189    macro(EnumInstType, Type) \
     190    macro(EnumAttrType, Type) \
    190191    macro(TraitInstType, Type) \
    191192    macro(TypeInstType, Type) \
  • src/ResolvExpr/CandidateFinder.cpp

    re6f1a4b rfbc84ca  
    906906                                }
    907907                                CandidateRef & choice = winners.front();
    908                                 choice->cost = Cost::unsafe;
     908                                choice->cost.incSafe();
    909909                                candidates.emplace_back( std::move(choice) );
    910910                        }
     
    955955
    956956                CandidateFinder funcFinder( context, tenv );
    957                 std::string funcName;
    958957                if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
    959                         funcName = nameExpr->name;
    960958                        auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
    961959                        if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
     
    10211019                CandidateList found;
    10221020                SemanticErrorException errors;
    1023                
    10241021                for ( CandidateRef & func : funcFinder ) {
    10251022                        try {
     
    10961093                        Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );
    10971094
    1098                         if (funcName == "?|?") {
    10991095                        PRINT(
    11001096                                auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();
     
    11121108                                std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    11131109                        )
    1114                         }
     1110
    11151111                        if ( cvtCost != Cost::infinity ) {
    11161112                                withFunc->cvtCost = cvtCost;
     
    17781774                                                matches.clear();
    17791775                                        }
    1780                                         CandidateRef newCand = std::make_shared<Candidate>(
    1781                                                 new ast::InitExpr{
    1782                                                         initExpr->location,
    1783                                                         restructureCast( cand->expr, toType ),
    1784                                                         initAlt.designation },
    1785                                                 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
    1786                                         // currently assertions are always resolved immediately so this should have no effect.
    1787                                         // if this somehow changes in the future (e.g. delayed by indeterminate return type)
    1788                                         // we may need to revisit the logic.
    1789                                         inferParameters( newCand, matches );
     1776                                        // ambiguous case, still output candidates to print in error message
     1777                                        if ( cand->cost == minExprCost && thisCost == minCastCost ) {
     1778                                                auto commonAsEnumAttr = common.as<ast::EnumAttrType>();
     1779                                                if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) {
     1780                                                        auto callExpr = new ast::UntypedExpr(
     1781                                                                cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} );
     1782                                                        CandidateFinder finder( context, env );
     1783                                                        finder.find( callExpr );
     1784                                                        CandidateList winners = findMinCost( finder.candidates );
     1785                                                        if (winners.size() != 1) {
     1786                                                                SemanticError( callExpr, "Ambiguous expression in valueE..." );
     1787                                                        }
     1788                                                        CandidateRef & choice = winners.front();
     1789                                                        // assert( valueCall->result );
     1790                                                        CandidateRef newCand = std::make_shared<Candidate>(
     1791                                                                new ast::InitExpr{
     1792                                                                        initExpr->location,
     1793                                                                        // restructureCast( cand->expr, toType ),
     1794                                                                        choice->expr,
     1795                                                                        initAlt.designation },
     1796                                                                std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
     1797                                                                inferParameters( newCand, matches );
     1798                                                } else {
     1799                                                        CandidateRef newCand = std::make_shared<Candidate>(
     1800                                                                new ast::InitExpr{
     1801                                                                        initExpr->location,
     1802                                                                        restructureCast( cand->expr, toType ),
     1803                                                                        initAlt.designation },
     1804                                                                std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
     1805                                                        // currently assertions are always resolved immediately so this should have no effect.
     1806                                                        // if this somehow changes in the future (e.g. delayed by indeterminate return type)
     1807                                                        // we may need to revisit the logic.
     1808                                                        inferParameters( newCand, matches );
     1809                                                }
     1810                                        }
    17901811                                }
    17911812                        }
  • src/ResolvExpr/CommonType.cpp

    re6f1a4b rfbc84ca  
    388388                        const ast::EnumDecl* enumDecl = enumInst->base;
    389389                        if ( !enumDecl->base ) {
     390                                ast::BasicKind kind = commonTypes[ basic->kind ][ ast::BasicKind::SignedInt ];
     391                                if (
     392                                        ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
     393                                                || widen.first )
     394                                        && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
     395                                                || widen.second )
     396                                ) {
     397                                        result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
     398                                }
     399                        }
     400                } else if ( auto type2AsAttr = dynamic_cast< const ast::EnumAttrType * >( type2 ) ) {
     401                        if ( type2AsAttr->attr == ast::EnumAttribute::Posn ) {
    390402                                ast::BasicKind kind = commonTypes[ basic->kind ][ ast::BasicKind::SignedInt ];
    391403                                if (
     
    644656        }
    645657
     658        void postvisit( const ast::EnumAttrType * ) {}
     659
    646660        void postvisit( const ast::TraitInstType * ) {}
    647661
  • src/ResolvExpr/ConversionCost.cpp

    re6f1a4b rfbc84ca  
    279279        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
    280280                conversionCostFromBasicToBasic( basicType, dstAsBasic );
    281         }       else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     281        } else if ( dynamic_cast< const ast::EnumAttrType *>(dst) ) {
     282                static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
     283                cost = costCalc( basicType, integer, srcIsLvalue, symtab, env );
     284        } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    282285                if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) {
    283286                        cost = Cost::unsafe;
     
    370373        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
    371374        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
    372         if ( !inst->base->isTyped ) {
    373                 if ( cost < Cost::unsafe ) {
    374                         cost.incSafe();
    375                 }
    376                 return;
    377         }
    378         cost.incUnsafe();
     375        if ( cost < Cost::unsafe ) {
     376                cost.incSafe();
     377        }
     378}
     379
     380void ConversionCost::postvisit( const ast::EnumAttrType * src ) {
     381        auto dstAsEnumAttrType = dynamic_cast<const ast::EnumAttrType *>(dst);
     382        assert( src->attr != ast::EnumAttribute::Label );
     383        if ( src->attr == ast::EnumAttribute::Value ) {
     384                if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Value) {
     385                        cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env );
     386                } else {
     387                        auto baseType = src->instance->base->base;
     388                        cost = costCalc( baseType, dst, srcIsLvalue, symtab, env );
     389                        if ( cost < Cost::infinity ) {
     390                                cost.incUnsafe();
     391                        }
     392                }
     393        } else { // ast::EnumAttribute::Posn
     394                if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
     395                        cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env );
     396                        if ( cost < Cost::unsafe ) cost.incSafe();
     397                } else {
     398                        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };
     399                        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     400                        if ( cost < Cost::unsafe ) {
     401                                cost.incSafe();
     402                        }
     403                }
     404        }
    379405}
    380406
  • src/ResolvExpr/ConversionCost.hpp

    re6f1a4b rfbc84ca  
    7272        void postvisit( const ast::ZeroType * zeroType );
    7373        void postvisit( const ast::OneType * oneType );
     74        void postvisit( const ast::EnumAttrType * posType );
    7475private:
    7576        // refactor for code resue
  • src/ResolvExpr/Unify.cpp

    re6f1a4b rfbc84ca  
    275275
    276276        void postvisit( const ast::VoidType * vt) {
    277                 result = dynamic_cast< const ast::VoidType * >( type2 );
    278                         // || tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden());
     277                result = dynamic_cast< const ast::VoidType * >( type2 )
     278                        || tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden());
    279279                ;
    280280        }
     
    284284                        result = basic->kind == basic2->kind;
    285285                }
    286                 // result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());
     286                result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());
    287287        }
    288288
     
    293293                                noWiden());
    294294                }
    295                 // result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());
     295                result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());
    296296        }
    297297
     
    311311
    312312                result = unifyExact(
    313                         array->base, array2->base, tenv, need, have, open, noWiden());
    314                         // || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden());
     313                        array->base, array2->base, tenv, need, have, open, noWiden())
     314                        || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden());
    315315        }
    316316
     
    404404        }
    405405
     406        bool tryToUnifyWithEnumValue( const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     407                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     408                WidenMode widen) {
     409                if ( auto attrType2 = dynamic_cast<const ast::EnumAttrType *>(type2)) {
     410                        if (attrType2->attr == ast::EnumAttribute::Value) {
     411                                return unifyExact( type1, attrType2->instance->base->base, env, need, have, open,
     412                                        widen);
     413                        } else if (attrType2->attr == ast::EnumAttribute::Posn) {
     414                                return unifyExact( type1, attrType2->instance, env, need, have, open, widen );
     415                        }
     416                }
     417                return false;
     418        }
     419
    406420public:
    407421        void postvisit( const ast::FunctionType * func ) {
     
    513527        void postvisit( const ast::StructInstType * aggrType ) {
    514528                handleGenericRefType( aggrType, type2 );
     529                result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    515530        }
    516531
    517532        void postvisit( const ast::UnionInstType * aggrType ) {
    518533                handleGenericRefType( aggrType, type2 );
     534                result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    519535        }
    520536
    521537        void postvisit( const ast::EnumInstType * aggrType ) {
    522538                handleRefType( aggrType, type2 );
     539                result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
     540        }
     541
     542        void postvisit( const ast::EnumAttrType * enumAttr ) {
     543                // Lazy approach for now
     544                if ( auto otherPos = dynamic_cast< const ast::EnumAttrType *>( type2 ) ) {
     545                        if ( enumAttr->match(otherPos) ) {
     546                                result = otherPos;
     547                        }
     548                }
    523549        }
    524550
    525551        void postvisit( const ast::TraitInstType * aggrType ) {
    526552                handleRefType( aggrType, type2 );
     553                result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    527554        }
    528555
     
    533560                        this->result = otherInst;
    534561                }
     562                result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden());
    535563        }
    536564
     
    606634                auto types2 = flatten( flat2 );
    607635
    608                 result = unifyList( types, types2, tenv, need, have, open );
    609                         // || tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden());
     636                result = unifyList( types, types2, tenv, need, have, open )
     637                        || tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden());
    610638        }
    611639
    612640        void postvisit( const ast::VarArgsType * vat) {
    613                 result = dynamic_cast< const ast::VarArgsType * >( type2 );
    614                         // || tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden());
     641                result = dynamic_cast< const ast::VarArgsType * >( type2 )
     642                        || tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden());
    615643        }
    616644
    617645        void postvisit( const ast::ZeroType * zt) {
    618                 result = dynamic_cast< const ast::ZeroType * >( type2 );
    619                         // || tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden());
     646                result = dynamic_cast< const ast::ZeroType * >( type2 )
     647                        || tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden());
    620648        }
    621649
    622650        void postvisit( const ast::OneType * ot) {
    623                 result = dynamic_cast< const ast::OneType * >( type2 );
    624                         // || tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden());
     651                result = dynamic_cast< const ast::OneType * >( type2 )
     652                        || tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden());
    625653        }
    626654};
  • src/SymTab/Mangler.cpp

    re6f1a4b rfbc84ca  
    5858        void postvisit( const ast::OneType * oneType );
    5959        void postvisit( const ast::QualifiedType * qualType );
     60        void postvisit( const ast::EnumAttrType * posType );
    6061
    6162        /// The result is the current constructed mangled name.
     
    277278        assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
    278279        mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
     280}
     281
     282void Mangler::postvisit( const ast::EnumAttrType * enumAttr ) {
     283        postvisit( enumAttr->instance );
     284        // mangleName += "_pos";
     285        switch ( enumAttr->attr )
     286        {
     287                case ast::EnumAttribute::Label:
     288                        mangleName += "_label_";
     289                        break;
     290                case ast::EnumAttribute::Posn:
     291                        mangleName += "_posn_";
     292                        break;
     293                case ast::EnumAttribute::Value:
     294                        mangleName += "_value_";
     295                        break;
     296        }
     297
    279298}
    280299
  • src/Validate/ImplementEnumFunc.cpp

    re6f1a4b rfbc84ca  
    7272                ast::DeclWithType* decl = declPtr.get_and_mutate();
    7373                decl->attributes.push_back(new ast::Attribute("unused"));
     74        }
     75
     76        ast::ObjectDecl* dstParam() const {
     77                return new ast::ObjectDecl(getLocation(), "_dst",
     78                                           new ast::ReferenceType(new ast::EnumAttrType(
     79                                               ast::deepCopy(instType))));
     80        }
     81
     82        ast::ObjectDecl* srcParam() const {
     83                return new ast::ObjectDecl(
     84                        getLocation(), "_src",
     85                        new ast::EnumAttrType(ast::deepCopy(instType)));
    7486        }
    7587
     
    317329}
    318330
     331inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
     332        return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
     333}
     334
    319335ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
    320336        const ast::EnumAttribute attr, const CodeLocation& location,
     
    344360                        func->location,
    345361                        new ast::VariableExpr( func->location, func->params.front() ),
    346                         new ast::BasicType( ast::BasicKind::UnsignedInt ),
    347                         ast::GeneratedFlag::ExplicitCast
    348                 )});
     362                        new ast::EnumAttrType( new ast::EnumInstType(decl),
     363                                ast::EnumAttribute::Posn))});
    349364        func->stmts = new ast::CompoundStmt(
    350365                func->location, {new ast::ReturnStmt(func->location, untyped)});
     
    355370                func->location,
    356371                new ast::VariableExpr(func->location, func->params.front()),
    357                 new ast::BasicType( ast::BasicKind::UnsignedInt ),
    358                         ast::GeneratedFlag::ExplicitCast);
     372                new ast::EnumAttrType(new ast::EnumInstType(decl),
     373                                                          ast::EnumAttribute::Posn));
    359374        func->stmts = new ast::CompoundStmt(
    360375                func->location, {new ast::ReturnStmt(func->location, castExpr)});
Note: See TracChangeset for help on using the changeset viewer.