@@ -1522,6 +1522,58 @@ export class Compiler extends DiagnosticEmitter {
1522
1522
return true ;
1523
1523
}
1524
1524
1525
+ private ensureEnumToString ( enumElement : Enum ) : string | null {
1526
+ if ( ! this . compileEnum ( enumElement ) ) return null ;
1527
+ let members = enumElement . members ;
1528
+ if ( ! members ) return null ; // TODO
1529
+
1530
+ let module = this . module ;
1531
+ const functionName = `${ enumElement . internalName } #${ CommonNames . EnumToString } ` ;
1532
+ const isInline = enumElement . is ( CommonFlags . Const ) || enumElement . hasDecorator ( DecoratorFlags . Inline ) ;
1533
+ let _keys = Map_keys ( members ) , _values = Map_values ( members ) ;
1534
+ if ( isInline ) {
1535
+ let valueToNames : Map < i32 , string > = new Map ( ) ;
1536
+ for ( let i = 0 , k = _keys . length ; i < k ; ++ i ) {
1537
+ let name = unchecked ( _keys [ i ] ) ;
1538
+ let member = unchecked ( _values [ i ] ) ;
1539
+ if ( member . kind != ElementKind . EnumValue ) continue ;
1540
+ let enumValue = < EnumValue > member ;
1541
+ valueToNames . set ( i64_low ( enumValue . constantIntegerValue ) , name ) ;
1542
+ }
1543
+ let exprs = new Array < ExpressionRef > ( ) ;
1544
+ for ( let [ value , names ] of valueToNames ) {
1545
+ let expr = module . if (
1546
+ module . binary ( BinaryOp . EqI32 , module . i32 ( value ) , module . local_get ( 0 , TypeRef . I32 ) ) ,
1547
+ module . return ( this . ensureStaticString ( names ) )
1548
+ ) ;
1549
+ exprs . push ( expr ) ;
1550
+ }
1551
+ exprs . push ( module . unreachable ( ) ) ;
1552
+ module . addFunction ( functionName , TypeRef . I32 , TypeRef . I32 , null , module . block ( null , exprs , TypeRef . I32 ) ) ;
1553
+ return functionName ;
1554
+ } else {
1555
+ let internalNameToNames : Map < string , string > = new Map ( ) ;
1556
+ for ( let i = 0 , k = _keys . length ; i < k ; ++ i ) {
1557
+ let name = unchecked ( _keys [ i ] ) ;
1558
+ let member = unchecked ( _values [ i ] ) ;
1559
+ if ( member . kind != ElementKind . EnumValue ) continue ;
1560
+ let enumValue = < EnumValue > member ;
1561
+ internalNameToNames . set ( enumValue . internalName , name ) ;
1562
+ }
1563
+ let exprs = new Array < ExpressionRef > ( ) ;
1564
+ for ( let [ internalName , names ] of internalNameToNames ) {
1565
+ let expr = module . if (
1566
+ module . binary ( BinaryOp . EqI32 , module . global_get ( internalName , TypeRef . I32 ) , module . local_get ( 0 , TypeRef . I32 ) ) ,
1567
+ module . return ( this . ensureStaticString ( names ) )
1568
+ ) ;
1569
+ exprs . push ( expr ) ;
1570
+ }
1571
+ exprs . push ( module . unreachable ( ) ) ;
1572
+ module . addFunction ( functionName , TypeRef . I32 , TypeRef . I32 , null , module . block ( null , exprs , TypeRef . I32 ) ) ;
1573
+ return functionName ;
1574
+ }
1575
+ }
1576
+
1525
1577
// === Functions ================================================================================
1526
1578
1527
1579
/** Compiles a priorly resolved function. */
@@ -7092,7 +7144,16 @@ export class Compiler extends DiagnosticEmitter {
7092
7144
) : ExpressionRef {
7093
7145
let module = this . module ;
7094
7146
let targetExpression = expression . expression ;
7095
- let targetType = this . resolver . resolveExpression ( targetExpression , this . currentFlow ) ; // reports
7147
+ let resolver = this . resolver ;
7148
+ let targetElement = resolver . lookupExpression ( targetExpression , this . currentFlow , Type . auto , ReportMode . Swallow ) ;
7149
+ if ( targetElement && targetElement . kind == ElementKind . Enum ) {
7150
+ const toStringFunctionName = this . ensureEnumToString ( < Enum > targetElement ) ;
7151
+ if ( toStringFunctionName == null ) return module . unreachable ( ) ;
7152
+ const elementExpr = this . compileExpression ( expression . elementExpression , Type . i32 , Constraints . ConvImplicit ) ;
7153
+ return module . call ( toStringFunctionName , [ elementExpr ] , TypeRef . I32 ) ;
7154
+ }
7155
+
7156
+ let targetType = resolver . resolveExpression ( targetExpression , this . currentFlow ) ;
7096
7157
if ( targetType ) {
7097
7158
let classReference = targetType . getClassOrWrapper ( this . program ) ;
7098
7159
if ( classReference ) {
0 commit comments