Changes in / [e6f1a4b:fbc84ca]
- Files:
-
- 16 edited
-
doc/theses/jiada_liang_MMath/CFAenum.tex (modified) (2 diffs)
-
src/AST/Fwd.hpp (modified) (1 diff)
-
src/AST/Pass.hpp (modified) (1 diff)
-
src/AST/Pass.impl.hpp (modified) (1 diff)
-
src/AST/Print.cpp (modified) (1 diff)
-
src/AST/Type.hpp (modified) (1 diff)
-
src/AST/Visitor.hpp (modified) (1 diff)
-
src/CodeGen/GenType.cpp (modified) (2 diffs)
-
src/Common/CodeLocationTools.cpp (modified) (1 diff)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (6 diffs)
-
src/ResolvExpr/CommonType.cpp (modified) (2 diffs)
-
src/ResolvExpr/ConversionCost.cpp (modified) (2 diffs)
-
src/ResolvExpr/ConversionCost.hpp (modified) (1 diff)
-
src/ResolvExpr/Unify.cpp (modified) (8 diffs)
-
src/SymTab/Mangler.cpp (modified) (2 diffs)
-
src/Validate/ImplementEnumFunc.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/jiada_liang_MMath/CFAenum.tex
re6f1a4b rfbc84ca 70 70 As 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. 71 71 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 75 Pseudo-functions are function-like operators that do not result in any run-time computations, \ie like @sizeof@, @alignof@, @typeof@. 76 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. 77 78 The attributes of an enumerator are accessed by pseudo-functions @posE@, @valueE@, and @labelE@. 79 \begin{cfa} 80 int jane_pos = @posE@( Names.Jane ); $\C{// 2}$ 81 char * jane_value = @valueE@( Names.Jane ); $\C{// "JANE"}$ 82 char * jane_label = @labelE@( Names.Jane ); $\C{// "Jane"}$ 83 sout | posE( Names.Jane) | labelE( Names.Jane ) | valueE( Names.Jane ); 84 \end{cfa} 85 Note the ability to print all of an enumerator's properties. 187 86 188 87 … … 371 270 372 271 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 274 The header file \lstinline[deletekeywords=enum]{<enum.hfa>} defines the set of traits containing operators and helper functions for @enum@. 275 A \CFA enumeration satisfies all of these traits allowing it to interact with runtime features in \CFA. 276 Each trait is discussed in detail. 277 278 The trait @Bounded@: 279 \begin{cfa} 280 forall( E ) trait Bounded { 281 E first(); 282 E last(); 379 283 }; 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} 285 defines the bounds of the enumeration, where @first()@ returns the first enumerator and @last()@ returns the last, \eg: 286 \begin{cfa} 287 Workday day = first(); $\C{// Mon}$ 288 Planet 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. 291 Calling 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}$ 294 sout | @last()@; 295 Workday day = first(); $\C{// day provides type Workday}$ 296 void foo( Planet p ); 297 foo( last() ); $\C{// parameter provides type Planet}$ 298 \end{cfa} 299 300 The trait @Serial@: 301 \begin{cfa} 302 forall( 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} 309 is a @Bounded@ trait, where elements can be mapped to an integer sequence. 310 A 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. 312 The mapping from a serial type to integer is defined by @fromInstance@, which returns the enumerator's position. 313 The inverse operation is @fromInt@, which performs a bound check using @first()@ and @last()@ before casting the integer into an enumerator. 314 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@. 315 316 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. 317 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()$. 318 The exception @enumRange@ is raised if the result of either operation is outside the range of type @E@. 319 320 The trait @TypedEnum@: 321 \begin{cfa} 322 forall( E, T ) trait TypedEnum { 323 T valueE( E e ); 324 char * labelE( E e ); 325 unsigned int posE( E e ); 326 }; 327 \end{cfa} 328 captures 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 { ... };@. 330 Implementing general functions across all enumeration types is possible by asserting @TypeEnum( E, T )@, \eg: 331 \begin{cfa} 332 forall( E, T | TypeEnum( E, T ) ) 333 void printEnum( E e ) { 334 sout | "Enum "| labelE( e ); 335 } 336 printEunm( MARS ); 337 \end{cfa} 338 339 Finally, there is an associated trait defining comparison operators among enumerators. 340 \begin{cfa} 341 forall( 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} 352 Note, the overloaded operators are defined only when the header @<enum.hfa>@ is included. 353 If 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> 356 enum( int ) Fruits { APPLE = 2, BANANA = 10, CHERRY = 2 }; 357 APPLE == CHERRY; // true because valueE( APPLE ) == valueE( CHERRY ) 358 359 #include <enum.hfa> 360 APPLE == CHERRY; // false because posE( APPLE ) != posE( CHERRY ) 361 \end{cfa} 362 An enumerator returns its @position@ by default. 363 In particular, @printf( ... )@ from @<stdio.h>@ functions provides no context to its parameter type, so it prints @position@. 364 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@. 365 \begin{cfa} 366 printf( "Position of BANANA is \%d", BANANA ); // Position of BANANA is 1 367 sout | "Value of BANANA is " | BANANA; // Value of BANANA is 10 368 \end{cfa} 369 Programmers 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 384 372 385 373 \section{Planet Example} -
src/AST/Fwd.hpp
re6f1a4b rfbc84ca 133 133 class OneType; 134 134 class GlobalScopeType; 135 class EnumAttrType; 135 136 136 137 class Designation; -
src/AST/Pass.hpp
re6f1a4b rfbc84ca 207 207 const ast::Type * visit( const ast::UnionInstType * ) override final; 208 208 const ast::Type * visit( const ast::EnumInstType * ) override final; 209 const ast::Type * visit( const ast::EnumAttrType * ) override final; 209 210 const ast::Type * visit( const ast::TraitInstType * ) override final; 210 211 const ast::Type * visit( const ast::TypeInstType * ) override final; -
src/AST/Pass.impl.hpp
re6f1a4b rfbc84ca 1940 1940 1941 1941 //-------------------------------------------------------------------------- 1942 // EnumAttrType 1943 template< typename core_t > 1944 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumAttrType * node ) { 1945 VISIT_START( node ); 1946 VISIT_END( Type, node ); 1947 } 1948 1949 //-------------------------------------------------------------------------- 1942 1950 // TraitInstType 1943 1951 template< typename core_t > -
src/AST/Print.cpp
re6f1a4b rfbc84ca 1576 1576 } 1577 1577 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 1578 1592 virtual const ast::Type * visit( const ast::TraitInstType * node ) override final { 1579 1593 preprint( node ); -
src/AST/Type.hpp
re6f1a4b rfbc84ca 319 319 using EnumInstType = SueInstType<EnumDecl>; 320 320 321 class EnumAttrType final : public Type { 322 public: 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 } 332 private: 333 EnumAttrType * clone() const override { return new EnumAttrType{ *this }; } 334 MUTATE_FRIEND 335 }; 336 321 337 /// An instance of a trait type. 322 338 class TraitInstType final : public BaseInstType { -
src/AST/Visitor.hpp
re6f1a4b rfbc84ca 119 119 virtual const ast::Type * visit( const ast::OneType * ) = 0; 120 120 virtual const ast::Type * visit( const ast::GlobalScopeType * ) = 0; 121 virtual const ast::Type * visit( const ast::EnumAttrType * ) = 0; 121 122 virtual const ast::Designation * visit( const ast::Designation * ) = 0; 122 123 virtual const ast::Init * visit( const ast::SingleInit * ) = 0; -
src/CodeGen/GenType.cpp
re6f1a4b rfbc84ca 47 47 void postvisit( ast::UnionInstType const * type ); 48 48 void postvisit( ast::EnumInstType const * type ); 49 void postvisit( ast::EnumAttrType const * type ); 49 50 void postvisit( ast::TypeInstType const * type ); 50 51 void postvisit( ast::TupleType const * type ); … … 240 241 } 241 242 243 void GenType::postvisit( ast::EnumAttrType const * type ) { 244 postvisit( type->instance ); 245 } 246 242 247 void GenType::postvisit( ast::TypeInstType const * type ) { 243 248 assertf( !options.genC, "TypeInstType should not reach code generation." ); -
src/Common/CodeLocationTools.cpp
re6f1a4b rfbc84ca 188 188 macro(UnionInstType, Type) \ 189 189 macro(EnumInstType, Type) \ 190 macro(EnumAttrType, Type) \ 190 191 macro(TraitInstType, Type) \ 191 192 macro(TypeInstType, Type) \ -
src/ResolvExpr/CandidateFinder.cpp
re6f1a4b rfbc84ca 906 906 } 907 907 CandidateRef & choice = winners.front(); 908 choice->cost = Cost::unsafe;908 choice->cost.incSafe(); 909 909 candidates.emplace_back( std::move(choice) ); 910 910 } … … 955 955 956 956 CandidateFinder funcFinder( context, tenv ); 957 std::string funcName;958 957 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) { 959 funcName = nameExpr->name;960 958 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 961 959 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { … … 1021 1019 CandidateList found; 1022 1020 SemanticErrorException errors; 1023 1024 1021 for ( CandidateRef & func : funcFinder ) { 1025 1022 try { … … 1096 1093 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab ); 1097 1094 1098 if (funcName == "?|?") {1099 1095 PRINT( 1100 1096 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >(); … … 1112 1108 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1113 1109 ) 1114 } 1110 1115 1111 if ( cvtCost != Cost::infinity ) { 1116 1112 withFunc->cvtCost = cvtCost; … … 1778 1774 matches.clear(); 1779 1775 } 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 } 1790 1811 } 1791 1812 } -
src/ResolvExpr/CommonType.cpp
re6f1a4b rfbc84ca 388 388 const ast::EnumDecl* enumDecl = enumInst->base; 389 389 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 ) { 390 402 ast::BasicKind kind = commonTypes[ basic->kind ][ ast::BasicKind::SignedInt ]; 391 403 if ( … … 644 656 } 645 657 658 void postvisit( const ast::EnumAttrType * ) {} 659 646 660 void postvisit( const ast::TraitInstType * ) {} 647 661 -
src/ResolvExpr/ConversionCost.cpp
re6f1a4b rfbc84ca 279 279 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) { 280 280 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 ) ) { 282 285 if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) { 283 286 cost = Cost::unsafe; … … 370 373 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) }; 371 374 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 380 void 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 } 379 405 } 380 406 -
src/ResolvExpr/ConversionCost.hpp
re6f1a4b rfbc84ca 72 72 void postvisit( const ast::ZeroType * zeroType ); 73 73 void postvisit( const ast::OneType * oneType ); 74 void postvisit( const ast::EnumAttrType * posType ); 74 75 private: 75 76 // refactor for code resue -
src/ResolvExpr/Unify.cpp
re6f1a4b rfbc84ca 275 275 276 276 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()); 279 279 ; 280 280 } … … 284 284 result = basic->kind == basic2->kind; 285 285 } 286 //result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());286 result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden()); 287 287 } 288 288 … … 293 293 noWiden()); 294 294 } 295 //result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());295 result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden()); 296 296 } 297 297 … … 311 311 312 312 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()); 315 315 } 316 316 … … 404 404 } 405 405 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 406 420 public: 407 421 void postvisit( const ast::FunctionType * func ) { … … 513 527 void postvisit( const ast::StructInstType * aggrType ) { 514 528 handleGenericRefType( aggrType, type2 ); 529 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 515 530 } 516 531 517 532 void postvisit( const ast::UnionInstType * aggrType ) { 518 533 handleGenericRefType( aggrType, type2 ); 534 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 519 535 } 520 536 521 537 void postvisit( const ast::EnumInstType * aggrType ) { 522 538 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 } 523 549 } 524 550 525 551 void postvisit( const ast::TraitInstType * aggrType ) { 526 552 handleRefType( aggrType, type2 ); 553 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 527 554 } 528 555 … … 533 560 this->result = otherInst; 534 561 } 562 result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden()); 535 563 } 536 564 … … 606 634 auto types2 = flatten( flat2 ); 607 635 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()); 610 638 } 611 639 612 640 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()); 615 643 } 616 644 617 645 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()); 620 648 } 621 649 622 650 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()); 625 653 } 626 654 }; -
src/SymTab/Mangler.cpp
re6f1a4b rfbc84ca 58 58 void postvisit( const ast::OneType * oneType ); 59 59 void postvisit( const ast::QualifiedType * qualType ); 60 void postvisit( const ast::EnumAttrType * posType ); 60 61 61 62 /// The result is the current constructed mangled name. … … 277 278 assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 278 279 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name; 280 } 281 282 void 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 279 298 } 280 299 -
src/Validate/ImplementEnumFunc.cpp
re6f1a4b rfbc84ca 72 72 ast::DeclWithType* decl = declPtr.get_and_mutate(); 73 73 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))); 74 86 } 75 87 … … 317 329 } 318 330 331 inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) { 332 return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn); 333 } 334 319 335 ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto( 320 336 const ast::EnumAttribute attr, const CodeLocation& location, … … 344 360 func->location, 345 361 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))}); 349 364 func->stmts = new ast::CompoundStmt( 350 365 func->location, {new ast::ReturnStmt(func->location, untyped)}); … … 355 370 func->location, 356 371 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)); 359 374 func->stmts = new ast::CompoundStmt( 360 375 func->location, {new ast::ReturnStmt(func->location, castExpr)});
Note:
See TracChangeset
for help on using the changeset viewer.