@@ -16,7 +16,7 @@ use std::{
1616
1717use crate :: {
1818 ast:: {
19- ArgList , BinaryOperator , BringSource , CalleeKind , Class as AstClass , Expr , ExprKind , FunctionBody ,
19+ ArgList , BinaryOperator , BringSource , CalleeKind , Class as AstClass , ElifLetBlock , Expr , ExprKind , FunctionBody ,
2020 FunctionDefinition , InterpolatedStringPart , Literal , NewExpr , Phase , Reference , Scope , Stmt , StmtKind , StructField ,
2121 Symbol , TypeAnnotationKind , UnaryOperator , UserDefinedType ,
2222 } ,
@@ -765,6 +765,78 @@ impl<'a> JSifier<'a> {
765765 code
766766 }
767767
768+ // To avoid a performance penalty when evaluating assignments made in the elif statement,
769+ // it was necessary to nest the if statements.
770+ //
771+ // Thus, this code in Wing:
772+ //
773+ // if let x = tryA() {
774+ // ...
775+ // } elif let x = tryB() {
776+ // ...
777+ // } elif let x = TryC() {
778+ // ...
779+ // } else {
780+ // ...
781+ // }
782+ //
783+ // In JavaScript, will become this:
784+ //
785+ // const $if_let_value = tryA();
786+ // if ($if_let_value !== undefined) {
787+ // ...
788+ // } else {
789+ // let $elif_let_value0 = tryB();
790+ // if ($elif_let_value0 !== undefined) {
791+ // ...
792+ // } else {
793+ // let $elif_let_value1 = tryC();
794+ // if ($elif_let_value1 !== undefined) {
795+ // ...
796+ // } else {
797+ // ...
798+ // }
799+ // }
800+ // }
801+ fn jsify_elif_statements (
802+ & self ,
803+ code : & mut CodeMaker ,
804+ elif_statements : & Vec < ElifLetBlock > ,
805+ index : usize ,
806+ else_statements : & Option < Scope > ,
807+ ctx : & mut JSifyContext ,
808+ ) {
809+ let elif_let_value = "$elif_let_value" ;
810+
811+ let value = format ! ( "{}{}" , elif_let_value, index) ;
812+ code. line ( format ! (
813+ "const {} = {};" ,
814+ value,
815+ self . jsify_expression( & elif_statements. get( index) . unwrap( ) . value, ctx)
816+ ) ) ;
817+ let value = format ! ( "{}{}" , elif_let_value, index) ;
818+ code. open ( format ! ( "if ({value} != undefined) {{" ) ) ;
819+ let elif_block = elif_statements. get ( index) . unwrap ( ) ;
820+ if elif_block. reassignable {
821+ code. line ( format ! ( "let {} = {};" , elif_block. var_name, value) ) ;
822+ } else {
823+ code. line ( format ! ( "const {} = {};" , elif_block. var_name, value) ) ;
824+ }
825+ code. add_code ( self . jsify_scope_body ( & elif_block. statements , ctx) ) ;
826+ code. close ( "}" ) ;
827+
828+ if index < elif_statements. len ( ) - 1 {
829+ code. open ( "else {" ) ;
830+ self . jsify_elif_statements ( code, elif_statements, index + 1 , else_statements, ctx) ;
831+ code. close ( "}" ) ;
832+ } else if let Some ( else_scope) = else_statements {
833+ code. open ( "else {" ) ;
834+ code. add_code ( self . jsify_scope_body ( else_scope, ctx) ) ;
835+ code. close ( "}" ) ;
836+ }
837+ return ;
838+ }
839+
768840 fn jsify_statement ( & self , env : & SymbolEnv , statement : & Stmt , ctx : & mut JSifyContext ) -> CodeMaker {
769841 CompilationContext :: set ( CompilationPhase :: Jsifying , & statement. span ) ;
770842 match & statement. kind {
@@ -836,6 +908,7 @@ impl<'a> JSifier<'a> {
836908 value,
837909 statements,
838910 var_name,
911+ elif_statements,
839912 else_statements,
840913 } => {
841914 let mut code = CodeMaker :: default ( ) ;
@@ -867,12 +940,13 @@ impl<'a> JSifier<'a> {
867940 // The temporary scope is created so that intermediate variables created by consecutive `if let` clauses
868941 // do not interfere with each other.
869942 code. open ( "{" ) ;
870- let if_let_value = "$IF_LET_VALUE " . to_string ( ) ;
943+ let if_let_value = "$if_let_value " . to_string ( ) ;
871944 code. line ( format ! (
872945 "const {} = {};" ,
873946 if_let_value,
874947 self . jsify_expression( value, ctx)
875948 ) ) ;
949+
876950 code. open ( format ! ( "if ({if_let_value} != undefined) {{" ) ) ;
877951 if * reassignable {
878952 code. line ( format ! ( "let {} = {};" , var_name, if_let_value) ) ;
@@ -882,7 +956,11 @@ impl<'a> JSifier<'a> {
882956 code. add_code ( self . jsify_scope_body ( statements, ctx) ) ;
883957 code. close ( "}" ) ;
884958
885- if let Some ( else_scope) = else_statements {
959+ if elif_statements. len ( ) > 0 {
960+ code. open ( "else {" ) ;
961+ self . jsify_elif_statements ( & mut code, elif_statements, 0 , else_statements, ctx) ;
962+ code. close ( "}" ) ;
963+ } else if let Some ( else_scope) = else_statements {
886964 code. open ( "else {" ) ;
887965 code. add_code ( self . jsify_scope_body ( else_scope, ctx) ) ;
888966 code. close ( "}" ) ;
0 commit comments