added: clarifying error message when statement code block is used in expression context
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 4 Dec 2023 18:00:12 +0000 (12:00 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 4 Dec 2023 18:00:12 +0000 (12:00 -0600)
compiler/include/astnodes.h
compiler/src/checker.c
compiler/src/parser.c

index 0c294da85b9975e627568688a9eafeaf2a4ef14a..33a76ed9023da3e61442803bb965aae622e0682d 100644 (file)
@@ -1540,6 +1540,8 @@ struct AstCodeBlock {
 
     AstNode *code;
     bh_arr(OnyxToken *) binding_symbols;
+
+    b32 is_expression: 1;
 };
 
 struct AstDirectiveInsert {
index ab4e71d839e1eb5c072b7f560e729c08eaf75c60..bdf8277f9074cba7dce1f5bd9d63844c605e116c 100644 (file)
@@ -104,7 +104,7 @@ CheckStatus check_function_header(AstFunction* func);
 CheckStatus check_memres_type(AstMemRes* memres);
 CheckStatus check_memres(AstMemRes* memres);
 CheckStatus check_type(AstType** ptype);
-CheckStatus check_insert_directive(AstDirectiveInsert** pinsert);
+CheckStatus check_insert_directive(AstDirectiveInsert** pinsert, b32 expected_expression);
 CheckStatus check_directive_solidify(AstDirectiveSolidify** psolid);
 CheckStatus check_do_block(AstDoBlock** pdoblock);
 CheckStatus check_constraint(AstConstraint *constraint);
@@ -2424,7 +2424,7 @@ CheckStatus check_expression(AstTyped** pexpr) {
             break;
 
         case Ast_Kind_Directive_Insert:
-            retval = check_insert_directive((AstDirectiveInsert **) pexpr);
+            retval = check_insert_directive((AstDirectiveInsert **) pexpr, 1);
             break;
 
         case Ast_Kind_Code_Block:
@@ -2519,7 +2519,7 @@ CheckStatus check_global(AstGlobal* global) {
     return Check_Success;
 }
 
-CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) {
+CheckStatus check_insert_directive(AstDirectiveInsert** pinsert, b32 expected_expression) {
     AstDirectiveInsert* insert = *pinsert;
     if (insert->flags & Ast_Flag_Has_Been_Checked) return Check_Success;
 
@@ -2551,6 +2551,12 @@ CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) {
         ERROR(insert->token->pos, "Expected compile-time known expression of type 'Code'.");
     }
 
+    if (!code_block->is_expression && expected_expression) {
+        onyx_report_error(insert->token->pos, Error_Critical, "Expected a code block that is an expression here, but got a code block that is statements.");
+        onyx_report_error(code_block->token->pos, Error_Critical, "Try changing { expr } into ( expr ) here.");
+        return Check_Error;
+    }
+
     u32 bound_symbol_count = bh_arr_length(code_block->binding_symbols);
     u32 bound_expr_count   = bh_arr_length(insert->binding_exprs);
     if (bound_symbol_count > bound_expr_count) {
@@ -2746,6 +2752,7 @@ CheckStatus check_statement(AstNode** pstmt) {
         case Ast_Kind_Block:      return check_block((AstBlock *) stmt);
         case Ast_Kind_Defer:      return check_statement(&((AstDefer *) stmt)->stmt);
         case Ast_Kind_Directive_Remove: return check_remove_directive((AstDirectiveRemove *) stmt);
+        case Ast_Kind_Directive_Insert: return check_insert_directive((AstDirectiveInsert **) pstmt, 0);
         case Ast_Kind_Call: {
             CHECK(call, (AstCall **) pstmt);
             (*pstmt)->flags |= Ast_Flag_Expr_Ignored;
index a9ef24a8ae0377386a501631f220599fcdd5411b..7fc935160a41cbfc50418b75d663141c17295d8c 100644 (file)
@@ -664,6 +664,7 @@ static AstTyped* parse_factor(OnyxParser* parser) {
                     ((AstBlock *) code_block->code)->rules = Block_Rule_Code_Block;
                 } else {
                     code_block->code = (AstNode *) parse_expression(parser, 1);
+                    code_block->is_expression = 1;
                 }
 
                 retval = (AstTyped *) code_block;