From 35799cabfadebde3adbaafad9b348f85c3147ae5 Mon Sep 17 00:00:00 2001 From: Chris Rybicki Date: Fri, 2 Aug 2024 11:49:04 -0400 Subject: [PATCH] feat!: replace `elif` with `else if` (#6976) --- docs/api/03-language/04-flow-controls.md | 8 +- docs/api/05-language-reference.md | 6 +- .../04-flow-controls.md_example_3/main.w | 6 +- .../tests/sdk_tests/bucket/signed_url.test.w | 4 +- .../sdk_tests/function/aws-function.test.w | 2 +- examples/tests/valid/dynamo.test.w | 4 +- examples/tests/valid/dynamo_awscdk.test.w | 4 +- examples/tests/valid/optionals.test.w | 6 +- examples/tests/valid/statements_if.test.w | 18 ++-- libs/tree-sitter-wing/grammar.js | 15 ++-- libs/tree-sitter-wing/queries/folds.scm | 2 +- libs/tree-sitter-wing/src/grammar.json | 28 +++--- .../test/corpus/statements/statements.txt | 34 ++++---- libs/wingc/src/ast.rs | 14 +-- libs/wingc/src/fold.rs | 44 +++++----- libs/wingc/src/jsify.rs | 85 ++++++++++--------- libs/wingc/src/lsp/symbol_locator.rs | 10 +-- libs/wingc/src/parser.rs | 30 +++---- libs/wingc/src/type_check.rs | 30 +++---- libs/wingc/src/visit.rs | 30 +++---- .../valid/optionals.test.w_compile_tf-aws.md | 18 ++-- .../statements_if.test.w_compile_tf-aws.md | 12 +-- 22 files changed, 212 insertions(+), 198 deletions(-) diff --git a/docs/api/03-language/04-flow-controls.md b/docs/api/03-language/04-flow-controls.md index 0149726bbcb..ce8c63e45c4 100644 --- a/docs/api/03-language/04-flow-controls.md +++ b/docs/api/03-language/04-flow-controls.md @@ -48,7 +48,7 @@ for value in 1..=5 { } ``` -### If elif else +### If / else if / else ```ts playground example let grade = (score: num): str => { @@ -56,11 +56,11 @@ let grade = (score: num): str => { // However, curly braces are required in `if/else` statements. if 0 < score && score < 55 { return "F"; - } elif 55 <= score && score < 65 { + } else if 55 <= score && score < 65 { return "C"; - } elif 65 <= score && score < 75 { + } else if 65 <= score && score < 75 { return "B"; - } elif 75 <= score && score <= 100 { + } else if 75 <= score && score <= 100 { return "A"; } else { return "Invalid grade"; diff --git a/docs/api/05-language-reference.md b/docs/api/05-language-reference.md index 08ac45f6206..5e29186a8dd 100644 --- a/docs/api/05-language-reference.md +++ b/docs/api/05-language-reference.md @@ -1284,8 +1284,8 @@ includes for and while loops currently. ### 2.5 if -Flow control can be done with `if/elif/else` statements. -The **if** statement is optionally followed by **elif** and **else**. +Flow control can be done with `if/else if/else` statements. +The **if** statement is optionally followed by **else if** and **else**. > ```TS > // Wing program: @@ -1293,7 +1293,7 @@ The **if** statement is optionally followed by **elif** and **else**. > let y = "sample"; > if x == 2 { > log("x is 2"); -> } elif y != "sample" { +> } else if y != "sample" { > log("y is not sample"); > } else { > log("x is 1 and y is sample"); diff --git a/examples/tests/doc_examples/valid/04-flow-controls.md_example_3/main.w b/examples/tests/doc_examples/valid/04-flow-controls.md_example_3/main.w index c7281a6d58f..3921f02001a 100644 --- a/examples/tests/doc_examples/valid/04-flow-controls.md_example_3/main.w +++ b/examples/tests/doc_examples/valid/04-flow-controls.md_example_3/main.w @@ -5,11 +5,11 @@ let grade = (score: num): str => { // However, curly braces are required in `if/else` statements. if 0 < score && score < 55 { return "F"; - } elif 55 <= score && score < 65 { + } else if 55 <= score && score < 65 { return "C"; - } elif 65 <= score && score < 75 { + } else if 65 <= score && score < 75 { return "B"; - } elif 75 <= score && score <= 100 { + } else if 75 <= score && score <= 100 { return "A"; } else { return "Invalid grade"; diff --git a/examples/tests/sdk_tests/bucket/signed_url.test.w b/examples/tests/sdk_tests/bucket/signed_url.test.w index 02123a408cb..83ce560b826 100644 --- a/examples/tests/sdk_tests/bucket/signed_url.test.w +++ b/examples/tests/sdk_tests/bucket/signed_url.test.w @@ -75,7 +75,7 @@ test "signedUrl duration option is respected" { if target == "tf-aws" { result = output.contains("AccessDeniedRequest has expired"); - } elif target == "tf-gcp" { + } else if target == "tf-gcp" { result = output.contains("ExpiredTokenInvalid argument."); } @@ -95,4 +95,4 @@ test "signedUrl duration option is respected" { let output = util.shell("curl \"{getSignedUrl}\""); expect.equal(isExpiredTokenError(output), true); -} \ No newline at end of file +} diff --git a/examples/tests/sdk_tests/function/aws-function.test.w b/examples/tests/sdk_tests/function/aws-function.test.w index c78b8d2a09a..0164c3455ed 100644 --- a/examples/tests/sdk_tests/function/aws-function.test.w +++ b/examples/tests/sdk_tests/function/aws-function.test.w @@ -44,7 +44,7 @@ new std.Test(inflight () => { assert(info.get("functionArn").contains(":function:")); assert(info.get("functionArn").contains("aws-wing-function")); assert(info.get("functionName").contains("aws-wing-function")); - } elif target == "awscdk" { + } else if target == "awscdk" { assert(info.get("functionArn").contains("arn:aws:lambda:")); assert(info.get("functionArn").contains(":function:")); assert(info.get("functionArn").contains("awswingfunction")); diff --git a/examples/tests/valid/dynamo.test.w b/examples/tests/valid/dynamo.test.w index c16b4ec0fd7..eda854e8be5 100644 --- a/examples/tests/valid/dynamo.test.w +++ b/examples/tests/valid/dynamo.test.w @@ -78,9 +78,9 @@ class DynamoTable { inflight _attributeTypeToString(type: AttributeType): str { if type == AttributeType.String { return "S"; - } elif type == AttributeType.Number { + } else if type == AttributeType.Number { return "N"; - } elif type == AttributeType.Binary { + } else if type == AttributeType.Binary { return "B"; } } diff --git a/examples/tests/valid/dynamo_awscdk.test.w b/examples/tests/valid/dynamo_awscdk.test.w index a06492abc14..c4cbb3b4cbb 100644 --- a/examples/tests/valid/dynamo_awscdk.test.w +++ b/examples/tests/valid/dynamo_awscdk.test.w @@ -88,9 +88,9 @@ class DynamoTable { inflight _attributeTypeToString(type: AttributeType): str { if type == AttributeType.String { return "S"; - } elif type == AttributeType.Number { + } else if type == AttributeType.Number { return "N"; - } elif type == AttributeType.Binary { + } else if type == AttributeType.Binary { return "B"; } } diff --git a/examples/tests/valid/optionals.test.w b/examples/tests/valid/optionals.test.w index 528ba1d1ee1..bd5e538dc07 100644 --- a/examples/tests/valid/optionals.test.w +++ b/examples/tests/valid/optionals.test.w @@ -60,9 +60,9 @@ let json_obj = Json { ghost: "spooky" }; let var something_else = false; if let y = json_obj.tryAsBool() { assert(y == true || y == false); -} elif let y = json_obj.tryAsNum() { +} else if let y = json_obj.tryAsNum() { assert(y + 0 == y); -} elif let y = json_obj.tryAsStr() { +} else if let y = json_obj.tryAsStr() { assert(y.length >= 0); } else { something_else = true; @@ -199,7 +199,7 @@ let str2: str? = nil; if let s1 = str1 { assert(false); // Should not happen -} elif let s2 = str2 { +} else if let s2 = str2 { assert(true); } diff --git a/examples/tests/valid/statements_if.test.w b/examples/tests/valid/statements_if.test.w index 4477622ab27..c594db1a322 100644 --- a/examples/tests/valid/statements_if.test.w +++ b/examples/tests/valid/statements_if.test.w @@ -6,11 +6,11 @@ if true { if true && x + 2 == 4 { if true && x + 3 == 4 { assert(false); - } elif true && x + 3 == 6 { + } else if true && x + 3 == 6 { assert(false); - } elif false || x + 3 == 5 { + } else if false || x + 3 == 5 { assert(true); - } elif !f { + } else if !f { assert(!!!f); } else { assert(false); @@ -26,9 +26,9 @@ test "test" { if true && x + 2 == 4 { if true && x + 3 == 4 { assert(false); - } elif true && x + 3 == 6 { + } else if true && x + 3 == 6 { assert(false); - } elif false || x + 3 == 5 { + } else if false || x + 3 == 5 { assert(true); } else { assert(false); @@ -45,9 +45,9 @@ if true { let c: str? = "c"; if let d = a { assert(false); - } elif b != nil { + } else if b != nil { assert(true); - } elif let e = c { + } else if let e = c { assert(false); } else { assert(false); @@ -60,9 +60,9 @@ if true { let c: str? = "c"; if let d = a { assert(false); - } elif let e = c { + } else if let e = c { assert(true); - } elif b != nil { + } else if b != nil { assert(false); } else { assert(false); diff --git a/libs/tree-sitter-wing/grammar.js b/libs/tree-sitter-wing/grammar.js index b642e1c5e44..3d17e25194a 100644 --- a/libs/tree-sitter-wing/grammar.js +++ b/libs/tree-sitter-wing/grammar.js @@ -309,16 +309,17 @@ module.exports = grammar({ field("block", $.block), repeat( choice( - field("elif_let_block", $.elif_let_block), - field("elif_block", $.elif_block) + field("else_if_let_block", $.else_if_let_block), + field("else_if_block", $.else_if_block) ) ), optional(seq("else", field("else_block", $.block))) ), - elif_let_block: ($) => + else_if_let_block: ($) => seq( - "elif", + "else", + "if", "let", optional(field("reassignable", $.reassignable)), field("name", $.identifier), @@ -332,12 +333,12 @@ module.exports = grammar({ "if", field("condition", $.expression), field("block", $.block), - repeat(field("elif_block", $.elif_block)), + repeat(field("else_if_block", $.else_if_block)), optional(seq("else", field("else_block", $.block))) ), - elif_block: ($) => - seq("elif", field("condition", $.expression), field("block", $.block)), + else_if_block: ($) => + seq("else", "if", field("condition", $.expression), field("block", $.block)), try_catch_statement: ($) => seq( diff --git a/libs/tree-sitter-wing/queries/folds.scm b/libs/tree-sitter-wing/queries/folds.scm index 60de6116dac..2c1207db6ca 100644 --- a/libs/tree-sitter-wing/queries/folds.scm +++ b/libs/tree-sitter-wing/queries/folds.scm @@ -7,7 +7,7 @@ (while_statement) (if_statement) (if_let_statement) - (elif_block) + (else_if_block) (struct_definition) (enum_definition) (try_catch_statement) diff --git a/libs/tree-sitter-wing/src/grammar.json b/libs/tree-sitter-wing/src/grammar.json index 6993511fde8..0cecda07eda 100644 --- a/libs/tree-sitter-wing/src/grammar.json +++ b/libs/tree-sitter-wing/src/grammar.json @@ -1708,18 +1708,18 @@ "members": [ { "type": "FIELD", - "name": "elif_let_block", + "name": "else_if_let_block", "content": { "type": "SYMBOL", - "name": "elif_let_block" + "name": "else_if_let_block" } }, { "type": "FIELD", - "name": "elif_block", + "name": "else_if_block", "content": { "type": "SYMBOL", - "name": "elif_block" + "name": "else_if_block" } } ] @@ -1752,12 +1752,16 @@ } ] }, - "elif_let_block": { + "else_if_let_block": { "type": "SEQ", "members": [ { "type": "STRING", - "value": "elif" + "value": "else" + }, + { + "type": "STRING", + "value": "if" }, { "type": "STRING", @@ -1836,10 +1840,10 @@ "type": "REPEAT", "content": { "type": "FIELD", - "name": "elif_block", + "name": "else_if_block", "content": { "type": "SYMBOL", - "name": "elif_block" + "name": "else_if_block" } } }, @@ -1870,12 +1874,16 @@ } ] }, - "elif_block": { + "else_if_block": { "type": "SEQ", "members": [ { "type": "STRING", - "value": "elif" + "value": "else" + }, + { + "type": "STRING", + "value": "if" }, { "type": "FIELD", diff --git a/libs/tree-sitter-wing/test/corpus/statements/statements.txt b/libs/tree-sitter-wing/test/corpus/statements/statements.txt index 10098f6d6a8..b4a6224a981 100644 --- a/libs/tree-sitter-wing/test/corpus/statements/statements.txt +++ b/libs/tree-sitter-wing/test/corpus/statements/statements.txt @@ -159,10 +159,10 @@ if false {} else {} else_block: (block))) ================================================================================ -If Elif Else +If Else If Else ================================================================================ -if false {} elif false {} else {} +if false {} else if false {} else {} -------------------------------------------------------------------------------- @@ -170,16 +170,16 @@ if false {} elif false {} else {} (if_statement condition: (bool) block: (block) - elif_block: (elif_block + else_if_block: (else_if_block condition: (bool) block: (block)) else_block: (block))) ================================================================================ -If More Than One Elif Else +If More Than One Else If Else ================================================================================ -if false {} elif false {} elif true {} else {} +if false {} else if false {} else if true {} else {} -------------------------------------------------------------------------------- @@ -187,10 +187,10 @@ if false {} elif false {} elif true {} else {} (if_statement condition: (bool) block: (block) - elif_block: (elif_block + else_if_block: (else_if_block condition: (bool) block: (block)) - elif_block: (elif_block + else_if_block: (else_if_block condition: (bool) block: (block)) else_block: (block))) @@ -447,10 +447,10 @@ if let x = y {} else {} else_block: (block))) ================================================================================ -If Let Elif Let Else +If Let Else If Let Else ================================================================================ -if let x = y {} elif let x = z {} else {} +if let x = y {} else if let x = z {} else {} -------------------------------------------------------------------------------- @@ -460,7 +460,7 @@ if let x = y {} elif let x = z {} else {} value: (reference (reference_identifier)) block: (block) - elif_let_block: (elif_let_block + else_if_let_block: (else_if_let_block name: (identifier) value: (reference (reference_identifier)) @@ -468,10 +468,10 @@ if let x = y {} elif let x = z {} else {} else_block: (block))) ================================================================================ -(If Let) (Elif) (Elif Let) (Else) +(If Let) (Else If) (Else If Let) (Else) ================================================================================ -if let x = y {} elif let x = z {} else {} +if let x = y {} else if let x = z {} else {} -------------------------------------------------------------------------------- @@ -481,7 +481,7 @@ if let x = y {} elif let x = z {} else {} value: (reference (reference_identifier)) block: (block) - elif_let_block: (elif_let_block + else_if_let_block: (else_if_let_block name: (identifier) value: (reference (reference_identifier)) @@ -489,10 +489,10 @@ if let x = y {} elif let x = z {} else {} else_block: (block))) ================================================================================ -(If Let) (Elif Let) (Elif) (Else) +(If Let) (Else If Let) (Else If) (Else) ================================================================================ -if let x = y {} elif let x = z {} elif v {} else {} +if let x = y {} else if let x = z {} else if v {} else {} -------------------------------------------------------------------------------- @@ -502,12 +502,12 @@ if let x = y {} elif let x = z {} elif v {} else {} value: (reference (reference_identifier)) block: (block) - elif_let_block: (elif_let_block + else_if_let_block: (else_if_let_block name: (identifier) value: (reference (reference_identifier)) block: (block)) - elif_block: (elif_block + else_if_block: (else_if_block condition: (reference (reference_identifier)) block: (block)) diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index 206c62825cf..fdfe39b15f8 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -309,13 +309,13 @@ pub struct Stmt { } #[derive(Debug)] -pub struct ElifBlock { +pub struct ElseIfBlock { pub condition: Expr, pub statements: Scope, } #[derive(Debug)] -pub struct ElifLetBlock { +pub struct ElseIfLetBlock { pub reassignable: bool, pub var_name: Symbol, pub value: Expr, @@ -444,14 +444,14 @@ pub struct IfLet { pub var_name: Symbol, pub value: Expr, pub statements: Scope, - pub elif_statements: Vec, + pub else_if_statements: Vec, pub else_statements: Option, } #[derive(Debug)] -pub enum Elifs { - ElifBlock(ElifBlock), - ElifLetBlock(ElifLetBlock), +pub enum ElseIfs { + ElseIfBlock(ElseIfBlock), + ElseIfLetBlock(ElseIfLetBlock), } #[derive(Debug)] @@ -482,7 +482,7 @@ pub enum StmtKind { If { condition: Expr, statements: Scope, - elif_statements: Vec, + else_if_statements: Vec, else_statements: Option, }, Break, diff --git a/libs/wingc/src/fold.rs b/libs/wingc/src/fold.rs index 0c2d97ee3c6..d13c8d514e4 100644 --- a/libs/wingc/src/fold.rs +++ b/libs/wingc/src/fold.rs @@ -1,8 +1,8 @@ use crate::ast::{ - ArgList, BringSource, CalleeKind, CatchBlock, Class, ClassField, ElifBlock, ElifLetBlock, Elifs, Enum, ExplicitLift, - Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, IfLet, Interface, - InterpolatedString, InterpolatedStringPart, Intrinsic, LiftQualification, Literal, New, Reference, Scope, Stmt, - StmtKind, Struct, StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType, + ArgList, BringSource, CalleeKind, CatchBlock, Class, ClassField, ElseIfBlock, ElseIfLetBlock, ElseIfs, Enum, + ExplicitLift, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, IfLet, + Interface, InterpolatedString, InterpolatedStringPart, Intrinsic, LiftQualification, Literal, New, Reference, Scope, + Stmt, StmtKind, Struct, StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType, }; /// Similar to the `visit` module in `wingc` except each method takes ownership of an @@ -124,28 +124,28 @@ where statements, reassignable, var_name, - elif_statements, + else_if_statements, else_statements, }) => StmtKind::IfLet(IfLet { value: f.fold_expr(value), statements: f.fold_scope(statements), reassignable, var_name: f.fold_symbol(var_name), - elif_statements: elif_statements + else_if_statements: else_if_statements .into_iter() - .map(|elif_block| match elif_block { - Elifs::ElifBlock(elif_block) => { - return Elifs::ElifBlock(ElifBlock { - condition: f.fold_expr(elif_block.condition), - statements: f.fold_scope(elif_block.statements), + .map(|else_if_block| match else_if_block { + ElseIfs::ElseIfBlock(else_if_block) => { + return ElseIfs::ElseIfBlock(ElseIfBlock { + condition: f.fold_expr(else_if_block.condition), + statements: f.fold_scope(else_if_block.statements), }) } - Elifs::ElifLetBlock(elif_let_block) => { - return Elifs::ElifLetBlock(ElifLetBlock { - reassignable: elif_let_block.reassignable, - statements: f.fold_scope(elif_let_block.statements), - value: f.fold_expr(elif_let_block.value), - var_name: f.fold_symbol(elif_let_block.var_name), + ElseIfs::ElseIfLetBlock(else_if_let_block) => { + return ElseIfs::ElseIfLetBlock(ElseIfLetBlock { + reassignable: else_if_let_block.reassignable, + statements: f.fold_scope(else_if_let_block.statements), + value: f.fold_expr(else_if_let_block.value), + var_name: f.fold_symbol(else_if_let_block.var_name), }); } }) @@ -155,16 +155,16 @@ where StmtKind::If { condition, statements, - elif_statements, + else_if_statements, else_statements, } => StmtKind::If { condition: f.fold_expr(condition), statements: f.fold_scope(statements), - elif_statements: elif_statements + else_if_statements: else_if_statements .into_iter() - .map(|elif_block| ElifBlock { - condition: f.fold_expr(elif_block.condition), - statements: f.fold_scope(elif_block.statements), + .map(|else_if_block| ElseIfBlock { + condition: f.fold_expr(else_if_block.condition), + statements: f.fold_scope(else_if_block.statements), }) .collect(), else_statements: else_statements.map(|statements| f.fold_scope(statements)), diff --git a/libs/wingc/src/jsify.rs b/libs/wingc/src/jsify.rs index 05f37a673a4..8b2d15b3abd 100644 --- a/libs/wingc/src/jsify.rs +++ b/libs/wingc/src/jsify.rs @@ -12,7 +12,7 @@ use std::{borrow::Borrow, cell::RefCell, cmp::Ordering, collections::BTreeMap, v use crate::{ ast::{ - AccessModifier, ArgList, AssignmentKind, BinaryOperator, BringSource, CalleeKind, Class as AstClass, Elifs, Enum, + AccessModifier, ArgList, AssignmentKind, BinaryOperator, BringSource, CalleeKind, Class as AstClass, ElseIfs, Enum, Expr, ExprKind, FunctionBody, FunctionDefinition, IfLet, InterpolatedStringPart, IntrinsicKind, Literal, New, Phase, Reference, Scope, Stmt, StmtKind, Symbol, UnaryOperator, UserDefinedType, }, @@ -1091,16 +1091,16 @@ impl<'a> JSifier<'a> { } } - // To avoid a performance penalty when evaluating assignments made in the elif statement, + // To avoid a performance penalty when evaluating assignments made in the else if statement, // it was necessary to nest the if statements. // // Thus, this code in Wing: // // if let x = tryA() { // ... - // } elif let x = tryB() { + // } else if let x = tryB() { // ... - // } elif let x = TryC() { + // } else if let x = TryC() { // ... // } else { // ... @@ -1112,65 +1112,70 @@ impl<'a> JSifier<'a> { // if ($if_let_value !== undefined) { // ... // } else { - // let $elif_let_value0 = tryB(); - // if ($elif_let_value0 !== undefined) { + // let $else_if_let_value0 = tryB(); + // if ($else_if_let_value0 !== undefined) { // ... // } else { - // let $elif_let_value1 = tryC(); - // if ($elif_let_value1 !== undefined) { + // let $else_if_let_value1 = tryC(); + // if ($else_if_let_value1 !== undefined) { // ... // } else { // ... // } // } // } - fn jsify_elif_statements( + fn jsify_else_if_statements( &self, code: &mut CodeMaker, - elif_statements: &Vec, + else_if_statements: &Vec, index: usize, else_statements: &Option, ctx: &mut JSifyContext, ) { - match elif_statements.get(index).unwrap() { - Elifs::ElifLetBlock(elif_let_to_jsify) => { - // Emit a JavaScript "else {" for each Wing "elif_let_block", + match else_if_statements.get(index).unwrap() { + ElseIfs::ElseIfLetBlock(else_if_let_to_jsify) => { + // Emit a JavaScript "else {" for each Wing "else_if_let_block", // and emit the closing "}" bracket in jsify_statement()'s StmtKind::IfLet match case code.open("else {"); - let elif_let_value = "$elif_let_value"; + let else_if_let_value = "$else_if_let_value"; - let value = format!("{}{}", elif_let_value, index); + let value = format!("{}{}", else_if_let_value, index); code.line(new_code!( - &elif_let_to_jsify.value.span, + &else_if_let_to_jsify.value.span, "const ", value, " = ", - self.jsify_expression(&elif_let_to_jsify.value, ctx), + self.jsify_expression(&else_if_let_to_jsify.value, ctx), ";" )); - let value = format!("{}{}", elif_let_value, index); + let value = format!("{}{}", else_if_let_value, index); code.open(format!("if ({value} != undefined) {{")); - if elif_let_to_jsify.reassignable { - code.line(format!("let {} = {};", elif_let_to_jsify.var_name, value)); + if else_if_let_to_jsify.reassignable { + code.line(format!("let {} = {};", else_if_let_to_jsify.var_name, value)); } else { - code.line(format!("const {} = {};", elif_let_to_jsify.var_name, value)); + code.line(format!("const {} = {};", else_if_let_to_jsify.var_name, value)); } - code.add_code(self.jsify_scope_body(&elif_let_to_jsify.statements, ctx)); + code.add_code(self.jsify_scope_body(&else_if_let_to_jsify.statements, ctx)); code.close("}"); } - Elifs::ElifBlock(elif_to_jsify) => { - let condition = self.jsify_expression(&elif_to_jsify.condition, ctx); + ElseIfs::ElseIfBlock(else_if_to_jsify) => { + let condition = self.jsify_expression(&else_if_to_jsify.condition, ctx); // TODO: this puts the "else if" in a separate line from the closing block but // technically that shouldn't be a problem, its just ugly - code.open(new_code!(&elif_to_jsify.condition.span, "else if (", condition, ") {")); - code.add_code(self.jsify_scope_body(&elif_to_jsify.statements, ctx)); + code.open(new_code!( + &else_if_to_jsify.condition.span, + "else if (", + condition, + ") {" + )); + code.add_code(self.jsify_scope_body(&else_if_to_jsify.statements, ctx)); code.close("}"); } } - if index < elif_statements.len() - 1 { - self.jsify_elif_statements(code, elif_statements, index + 1, else_statements, ctx); + if index < else_if_statements.len() - 1 { + self.jsify_else_if_statements(code, else_if_statements, index + 1, else_statements, ctx); } else if let Some(else_scope) = else_statements { code.open("else {"); code.add_code(self.jsify_scope_body(else_scope, ctx)); @@ -1292,7 +1297,7 @@ impl<'a> JSifier<'a> { value, statements, var_name, - elif_statements, + else_if_statements, else_statements, }) => { // To enable shadowing variables in if let statements, the following does some scope trickery @@ -1342,13 +1347,13 @@ impl<'a> JSifier<'a> { code.add_code(self.jsify_scope_body(statements, ctx)); code.close("}"); - if elif_statements.len() > 0 { - self.jsify_elif_statements(&mut code, elif_statements, 0, else_statements, ctx); - for elif_statement in elif_statements { - if let Elifs::ElifLetBlock(_) = elif_statement { - // "elif_let_block" statements emit "else {" in jsify_elif_statements(), + if else_if_statements.len() > 0 { + self.jsify_else_if_statements(&mut code, else_if_statements, 0, else_statements, ctx); + for else_if_statement in else_if_statements { + if let ElseIfs::ElseIfLetBlock(_) = else_if_statement { + // "else_if_let_block" statements emit "else {" in jsify_else_if_statements(), // but no closing bracket "}". The closing brackets are emitted here instead to - // deal with properly nesting "elif_let_block", "elif_block", and "else" statements + // deal with properly nesting "else_if_let_block", "else_if_block", and "else" statements code.close("}"); } } @@ -1363,7 +1368,7 @@ impl<'a> JSifier<'a> { StmtKind::If { condition, statements, - elif_statements, + else_if_statements, else_statements, } => { code.open(new_code!( @@ -1375,12 +1380,12 @@ impl<'a> JSifier<'a> { code.add_code(self.jsify_scope_body(statements, ctx)); code.close("}"); - for elif_block in elif_statements { - let condition = self.jsify_expression(&elif_block.condition, ctx); + for else_if_block in else_if_statements { + let condition = self.jsify_expression(&else_if_block.condition, ctx); // TODO: this puts the "else if" in a separate line from the closing block but // technically that shouldn't be a problem, its just ugly - code.open(new_code!(&elif_block.condition.span, "else if (", condition, ") {")); - code.add_code(self.jsify_scope_body(&elif_block.statements, ctx)); + code.open(new_code!(&else_if_block.condition.span, "else if (", condition, ") {")); + code.add_code(self.jsify_scope_body(&else_if_block.statements, ctx)); code.close("}"); } diff --git a/libs/wingc/src/lsp/symbol_locator.rs b/libs/wingc/src/lsp/symbol_locator.rs index 7c6fa79acae..7a63d94856c 100644 --- a/libs/wingc/src/lsp/symbol_locator.rs +++ b/libs/wingc/src/lsp/symbol_locator.rs @@ -274,17 +274,17 @@ impl<'a> Visit<'a> for SymbolLocator<'a> { StmtKind::IfLet(IfLet { var_name, statements, - elif_statements, + else_if_statements, .. }) => { self.push_scope_env(&statements); self.visit_symbol(var_name); self.ctx.pop_env(); - for elif in elif_statements { - if let Elifs::ElifLetBlock(elif_let_block) = elif { - self.push_scope_env(&elif_let_block.statements); - self.visit_symbol(&elif_let_block.var_name); + for else_if in else_if_statements { + if let ElseIfs::ElseIfLetBlock(else_if_let_block) = else_if { + self.push_scope_env(&else_if_let_block.statements); + self.visit_symbol(&else_if_let_block.var_name); self.ctx.pop_env(); } } diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index ccb59f4209d..8a70bbf499c 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -11,7 +11,7 @@ use tree_sitter::Node; use crate::ast::{ AccessModifier, ArgList, AssignmentKind, BinaryOperator, BringSource, CalleeKind, CatchBlock, Class, ClassField, - ElifBlock, ElifLetBlock, Elifs, Enum, ExplicitLift, Expr, ExprKind, FunctionBody, FunctionDefinition, + ElseIfBlock, ElseIfLetBlock, ElseIfs, Enum, ExplicitLift, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, IfLet, Interface, InterpolatedString, InterpolatedStringPart, Intrinsic, IntrinsicKind, LiftQualification, Literal, New, Phase, Reference, Scope, Spanned, Stmt, StmtKind, Struct, StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UnaryOperator, UserDefinedType, @@ -78,6 +78,7 @@ static RESERVED_WORDS: phf::Set<&'static str> = phf_set! { "instanceof", "int", "interface", + "is", "let", "long", "native", @@ -115,7 +116,6 @@ static RESERVED_WORDS: phf::Set<&'static str> = phf_set! { "test", "inflight", "preflight", - "elif", "any", "num", "str", @@ -812,30 +812,30 @@ impl<'s> Parser<'s> { let value = self.build_expression(&statement_node.child_by_field_name("value").unwrap(), phase)?; let name = self.check_reserved_symbol(&statement_node.child_by_field_name("name").unwrap())?; - let mut elif_vec = vec![]; + let mut else_if_vec = vec![]; let mut cursor = statement_node.walk(); for node in statement_node.children(&mut cursor) { match node.kind() { - "elif_let_block" => { + "else_if_let_block" => { let statements = self.build_scope(&node.child_by_field_name("block").unwrap(), phase); let value = self.build_expression(&node.child_by_field_name("value").unwrap(), phase)?; let name = self.check_reserved_symbol(&node.child_by_field_name("name").unwrap())?; - let elif = Elifs::ElifLetBlock(ElifLetBlock { + let else_if = ElseIfs::ElseIfLetBlock(ElseIfLetBlock { reassignable: node.child_by_field_name("reassignable").is_some(), statements: statements, value: value, var_name: name, }); - elif_vec.push(elif); + else_if_vec.push(else_if); } - "elif_block" => { + "else_if_block" => { let conditions = self.build_expression(&node.child_by_field_name("condition").unwrap(), phase); let statements = self.build_scope(&node.child_by_field_name("block").unwrap(), phase); - let elif = Elifs::ElifBlock(ElifBlock { + let else_if = ElseIfs::ElseIfBlock(ElseIfBlock { condition: conditions.unwrap(), statements: statements, }); - elif_vec.push(elif); + else_if_vec.push(else_if); } _ => {} } @@ -851,23 +851,23 @@ impl<'s> Parser<'s> { reassignable, value, statements: if_block, - elif_statements: elif_vec, + else_if_statements: else_if_vec, else_statements: else_block, })) } fn build_if_statement(&self, statement_node: &Node, phase: Phase) -> DiagnosticResult { let if_block = self.build_scope(&statement_node.child_by_field_name("block").unwrap(), phase); - let mut elif_vec = vec![]; + let mut else_if_vec = vec![]; let mut cursor = statement_node.walk(); - for node in statement_node.children_by_field_name("elif_block", &mut cursor) { + for node in statement_node.children_by_field_name("else_if_block", &mut cursor) { let conditions = self.build_expression(&node.child_by_field_name("condition").unwrap(), phase); let statements = self.build_scope(&node.child_by_field_name("block").unwrap(), phase); - let elif = ElifBlock { + let else_if = ElseIfBlock { condition: conditions.unwrap(), statements: statements, }; - elif_vec.push(elif); + else_if_vec.push(else_if); } let else_block = if let Some(else_block) = statement_node.child_by_field_name("else_block") { Some(self.build_scope(&else_block, phase)) @@ -877,7 +877,7 @@ impl<'s> Parser<'s> { Ok(StmtKind::If { condition: self.build_expression(&statement_node.child_by_field_name("condition").unwrap(), phase)?, statements: if_block, - elif_statements: elif_vec, + else_if_statements: else_if_vec, else_statements: else_block, }) } diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 765b499481f..f3ec0fcd49c 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -11,7 +11,7 @@ use crate::ast::{ FunctionDefinition, IfLet, Intrinsic, IntrinsicKind, New, TypeAnnotationKind, }; use crate::ast::{ - ArgList, BinaryOperator, Class as AstClass, Elifs, Enum as AstEnum, Expr, ExprKind, FunctionBody, + ArgList, BinaryOperator, Class as AstClass, ElseIfs, Enum as AstEnum, Expr, ExprKind, FunctionBody, FunctionParameter as AstFunctionParameter, Interface as AstInterface, InterpolatedStringPart, Literal, Phase, Reference, Scope, Spanned, Stmt, StmtKind, Struct as AstStruct, Symbol, TypeAnnotation, UnaryOperator, UserDefinedType, @@ -4194,10 +4194,10 @@ new cloud.Function(@inflight("./handler.ts"), lifts: { bucket: ["put"] }); StmtKind::If { condition, statements, - elif_statements, + else_if_statements, else_statements, } => { - tc.type_check_if(condition, statements, elif_statements, else_statements, env); + tc.type_check_if(condition, statements, else_if_statements, else_statements, env); } StmtKind::Expression(e) => { tc.type_check_exp(e, env); @@ -5003,14 +5003,14 @@ new cloud.Function(@inflight("./handler.ts"), lifts: { bucket: ["put"] }); &mut self, condition: &Expr, statements: &Scope, - elif_statements: &Vec, + else_if_statements: &Vec, else_statements: &Option, env: &mut SymbolEnv, ) { self.type_check_if_statement(condition, statements, env); - for elif_scope in elif_statements { - self.type_check_if_statement(&elif_scope.condition, &elif_scope.statements, env); + for else_if_scope in else_if_statements { + self.type_check_if_statement(&else_if_scope.condition, &else_if_scope.statements, env); } if let Some(else_scope) = else_statements { @@ -5034,17 +5034,17 @@ new cloud.Function(@inflight("./handler.ts"), lifts: { bucket: ["put"] }); env, ); - for elif_scope in &iflet.elif_statements { - match elif_scope { - Elifs::ElifBlock(elif_block) => { - self.type_check_if_statement(&elif_block.condition, &elif_block.statements, env); + for else_if_scope in &iflet.else_if_statements { + match else_if_scope { + ElseIfs::ElseIfBlock(else_if_block) => { + self.type_check_if_statement(&else_if_block.condition, &else_if_block.statements, env); } - Elifs::ElifLetBlock(elif_let_block) => { + ElseIfs::ElseIfLetBlock(else_if_let_block) => { self.type_check_if_let_statement( - &elif_let_block.value, - &elif_let_block.statements, - &elif_let_block.reassignable, - &elif_let_block.var_name, + &else_if_let_block.value, + &else_if_let_block.statements, + &else_if_let_block.reassignable, + &else_if_let_block.var_name, env, ); } diff --git a/libs/wingc/src/visit.rs b/libs/wingc/src/visit.rs index 839fc2c611f..2aee42a1002 100644 --- a/libs/wingc/src/visit.rs +++ b/libs/wingc/src/visit.rs @@ -1,5 +1,5 @@ use crate::ast::{ - ArgList, BringSource, CalleeKind, Class, Elifs, Enum, Expr, ExprKind, FunctionBody, FunctionDefinition, + ArgList, BringSource, CalleeKind, Class, ElseIfs, Enum, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, IfLet, Interface, InterpolatedStringPart, Literal, New, Reference, Scope, Stmt, StmtKind, Struct, Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType, }; @@ -141,22 +141,22 @@ where statements, reassignable: _, var_name, - elif_statements, + else_if_statements, else_statements, }) => { v.visit_symbol(var_name); v.visit_expr(value); v.visit_scope(statements); - for elif in elif_statements { - match elif { - Elifs::ElifBlock(elif_block) => { - v.visit_expr(&elif_block.condition); - v.visit_scope(&elif_block.statements); + for else_if in else_if_statements { + match else_if { + ElseIfs::ElseIfBlock(else_if_block) => { + v.visit_expr(&else_if_block.condition); + v.visit_scope(&else_if_block.statements); } - Elifs::ElifLetBlock(elif_let_block) => { - v.visit_symbol(&elif_let_block.var_name); - v.visit_expr(&elif_let_block.value); - v.visit_scope(&elif_let_block.statements); + ElseIfs::ElseIfLetBlock(else_if_let_block) => { + v.visit_symbol(&else_if_let_block.var_name); + v.visit_expr(&else_if_let_block.value); + v.visit_scope(&else_if_let_block.statements); } } } @@ -167,14 +167,14 @@ where StmtKind::If { condition, statements, - elif_statements, + else_if_statements, else_statements, } => { v.visit_expr(condition); v.visit_scope(statements); - for elif in elif_statements { - v.visit_expr(&elif.condition); - v.visit_scope(&elif.statements); + for else_if in else_if_statements { + v.visit_expr(&else_if.condition); + v.visit_scope(&else_if.statements); } if let Some(statements) = else_statements { v.visit_scope(statements); diff --git a/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md index b25fabf1660..d3eea9e8846 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md @@ -276,15 +276,15 @@ class $Root extends $stdlib.std.Resource { $helpers.assert(($helpers.eq(y, true) || $helpers.eq(y, false)), "y == true || y == false"); } else { - const $elif_let_value0 = $macros.__Json_tryAsNum(false, json_obj, ); - if ($elif_let_value0 != undefined) { - const y = $elif_let_value0; + const $else_if_let_value0 = $macros.__Json_tryAsNum(false, json_obj, ); + if ($else_if_let_value0 != undefined) { + const y = $else_if_let_value0; $helpers.assert($helpers.eq((y + 0), y), "y + 0 == y"); } else { - const $elif_let_value1 = $macros.__Json_tryAsStr(false, json_obj, ); - if ($elif_let_value1 != undefined) { - const y = $elif_let_value1; + const $else_if_let_value1 = $macros.__Json_tryAsStr(false, json_obj, ); + if ($else_if_let_value1 != undefined) { + const y = $else_if_let_value1; $helpers.assert((y.length >= 0), "y.length >= 0"); } else { @@ -407,9 +407,9 @@ class $Root extends $stdlib.std.Resource { $helpers.assert(false, "false"); } else { - const $elif_let_value0 = str2; - if ($elif_let_value0 != undefined) { - const s2 = $elif_let_value0; + const $else_if_let_value0 = str2; + if ($else_if_let_value0 != undefined) { + const s2 = $else_if_let_value0; $helpers.assert(true, "true"); } } diff --git a/tools/hangar/__snapshots__/test_corpus/valid/statements_if.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/statements_if.test.w_compile_tf-aws.md index 30581ef49d9..2acbd1108d7 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/statements_if.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/statements_if.test.w_compile_tf-aws.md @@ -138,9 +138,9 @@ class $Root extends $stdlib.std.Resource { $helpers.assert(true, "true"); } else { - const $elif_let_value1 = c; - if ($elif_let_value1 != undefined) { - const e = $elif_let_value1; + const $else_if_let_value1 = c; + if ($else_if_let_value1 != undefined) { + const e = $else_if_let_value1; $helpers.assert(false, "false"); } else { @@ -160,9 +160,9 @@ class $Root extends $stdlib.std.Resource { $helpers.assert(false, "false"); } else { - const $elif_let_value0 = c; - if ($elif_let_value0 != undefined) { - const e = $elif_let_value0; + const $else_if_let_value0 = c; + if ($else_if_let_value0 != undefined) { + const e = $else_if_let_value0; $helpers.assert(true, "true"); } else if ($helpers.neq(b, undefined)) {