@@ -1523,6 +1523,49 @@ export class Compiler extends DiagnosticEmitter {
15231523 return true ;
15241524 }
15251525
1526+ private ensureEnumToString ( enumElement : Enum , reportNode : Node ) : string | null {
1527+ if ( enumElement . toStringFunctionName ) return enumElement . toStringFunctionName ;
1528+
1529+ if ( ! this . compileEnum ( enumElement ) ) return null ;
1530+ if ( enumElement . is ( CommonFlags . Const ) ) {
1531+ this . errorRelated (
1532+ DiagnosticCode . A_const_enum_member_can_only_be_accessed_using_a_string_literal ,
1533+ reportNode . range , enumElement . identifierNode . range
1534+ ) ;
1535+ return null ;
1536+ }
1537+
1538+ let members = enumElement . members ;
1539+ if ( ! members ) return null ;
1540+
1541+ let module = this . module ;
1542+ const isInline = enumElement . hasDecorator ( DecoratorFlags . Inline ) ;
1543+
1544+ const functionName = `${ enumElement . internalName } #${ CommonNames . EnumToString } ` ;
1545+ enumElement . toStringFunctionName = functionName ;
1546+
1547+ let exprs = new Array < ExpressionRef > ( ) ;
1548+ // when the values are the same, TS returns the last enum value name that appears
1549+ for ( let _keys = Map_keys ( members ) , _values = Map_values ( members ) , i = 1 , k = _keys . length ; i <= k ; ++ i ) {
1550+ let enumValueName = unchecked ( _keys [ k - i ] ) ;
1551+ let member = unchecked ( _values [ k - i ] ) ;
1552+ if ( member . kind != ElementKind . EnumValue ) continue ;
1553+ let enumValue = < EnumValue > member ;
1554+ const enumValueExpr = isInline
1555+ ? module . i32 ( i64_low ( enumValue . constantIntegerValue ) )
1556+ : module . global_get ( enumValue . internalName , TypeRef . I32 ) ;
1557+ let expr = module . if (
1558+ module . binary ( BinaryOp . EqI32 , enumValueExpr , module . local_get ( 0 , TypeRef . I32 ) ) ,
1559+ module . return ( this . ensureStaticString ( enumValueName ) )
1560+ ) ;
1561+ exprs . push ( expr ) ;
1562+ }
1563+ exprs . push ( module . unreachable ( ) ) ;
1564+ module . addFunction ( functionName , TypeRef . I32 , TypeRef . I32 , null , module . block ( null , exprs , TypeRef . I32 ) ) ;
1565+
1566+ return functionName ;
1567+ }
1568+
15261569 // === Functions ================================================================================
15271570
15281571 /** Compiles a priorly resolved function. */
@@ -7093,7 +7136,17 @@ export class Compiler extends DiagnosticEmitter {
70937136 ) : ExpressionRef {
70947137 let module = this . module ;
70957138 let targetExpression = expression . expression ;
7096- let targetType = this . resolver . resolveExpression ( targetExpression , this . currentFlow ) ; // reports
7139+ let resolver = this . resolver ;
7140+ let targetElement = resolver . lookupExpression ( targetExpression , this . currentFlow , Type . auto , ReportMode . Swallow ) ;
7141+ if ( targetElement && targetElement . kind == ElementKind . Enum ) {
7142+ const elementExpr = this . compileExpression ( expression . elementExpression , Type . i32 , Constraints . ConvImplicit ) ;
7143+ const toStringFunctionName = this . ensureEnumToString ( < Enum > targetElement , expression ) ;
7144+ this . currentType = this . program . stringInstance . type ;
7145+ if ( toStringFunctionName == null ) return module . unreachable ( ) ;
7146+ return module . call ( toStringFunctionName , [ elementExpr ] , TypeRef . I32 ) ;
7147+ }
7148+
7149+ let targetType = resolver . resolveExpression ( targetExpression , this . currentFlow ) ;
70977150 if ( targetType ) {
70987151 let classReference = targetType . getClassOrWrapper ( this . program ) ;
70997152 if ( classReference ) {
0 commit comments