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