a 'do' statement is now allowed anywhere a single statement block would be
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 31 Jul 2020 01:37:10 +0000 (20:37 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 31 Jul 2020 01:37:10 +0000 (20:37 -0500)
12 files changed:
docs/plan
include/onyxastnodes.h
include/onyxlex.h
onyx
progs/alloc.onyx
progs/alloc_test.onyx
progs/print_funcs.onyx
src/onyxchecker.c
src/onyxlex.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index c1ce3901747a95608a09c2ea5645cee179528e44..ebb99d2f67b052b5b9ce83ee4fc4c930dd701344 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -140,6 +140,8 @@ HOW:
 
         [ ] Hex literals
 
+        [ ] All code paths return correct value
+
         [ ] #file_contents
 
         [ ] #initialize structs
index 60e592fe8d0cb07235d095ac648440e5b6e1dee2..ccfcb5924bf1f3414551314e4811fc0459509f8a 100644 (file)
@@ -276,7 +276,7 @@ struct AstContinue      { AstNode_base; u64 count; };
 
 // Structure Nodes
 struct AstBlock         { AstNode_base; AstNode *body; Scope *scope; };
-struct AstWhile         { AstNode_base; AstTyped *cond; AstNode *stmt; };
+struct AstWhile         { AstNode_base; AstTyped *cond; AstBlock *stmt; };
 struct AstDefer         { AstNode_base; AstNode *stmt; };
 struct AstFor           {
     AstNode_base;
@@ -289,14 +289,14 @@ struct AstFor           {
 
     AstTyped *start, *end, *step;
 
-    AstNode *stmt;
+    AstBlock *stmt;
 };
 struct AstIf {
     AstNode_base;
     AstTyped *cond;
 
-    AstNode* true_stmt;
-    AstNode* false_stmt;
+    AstBlock *true_stmt;
+    AstBlock *false_stmt;
 };
 
 // Type Nodes
index e122fda305e3ffb025fe06a46aedcd56b5037c83..d7c4f468a70ad653a5c783d9819061a5798e3ea7 100644 (file)
@@ -29,6 +29,7 @@ typedef enum TokenType {
     Token_Type_Keyword_Sizeof,
     Token_Type_Keyword_Alignof,
     Token_Type_Keyword_Defer,
+    Token_Type_Keyword_Do,
 
     Token_Type_Right_Arrow,
     Token_Type_Left_Arrow,
diff --git a/onyx b/onyx
index 3cab3d483ca8c30499bf05a483639ec8a28ded7a..c72c7889fac77d065f72b2c5533253b5ba912ca2 100755 (executable)
Binary files a/onyx and b/onyx differ
index f5899f07a77d197f640bd0c5c612b3ed60cb2044..56fdf7ef1960597d03b745ff4d10597d4bbf0da2 100644 (file)
@@ -59,7 +59,7 @@ heap_init :: proc {
 }
 
 heap_alloc :: proc (size_: u32, align: u32) -> rawptr {
-    if size_ == 0 return null;
+    if size_ == 0 do return null;
 
     size := size_ + sizeof heap_block;
     if size % align != 0 {
@@ -91,7 +91,7 @@ heap_alloc :: proc (size_: u32, align: u32) -> rawptr {
         return cast(rawptr) (cast(u32) ret + sizeof heap_block);
     }
 
-    new_pages :: (size - heap_state.remaining_space) >> 16;
+    new_pages :: ((size - heap_state.remaining_space) >> 16) + 1;
     if memory_grow(new_pages) == -1 {
         // out of memory    
         return null;
@@ -121,7 +121,7 @@ heap_free :: proc (ptr: rawptr) {
 }
 
 heap_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
-    if aa == AllocAction.Alloc return heap_alloc(size, align);
+    if aa == AllocAction.Alloc do return heap_alloc(size, align);
     if aa == AllocAction.Free {
         heap_free(oldptr);
         return null;
index f6d6dea7ef15d5faa69a13a04a455bd8f8780ab1..e5cf6d5ba93a4613e0644700e58da44bbb879550 100644 (file)
@@ -6,10 +6,10 @@ use package printing
 
 deferred_example :: proc -> i32 {
     arr := cast([] i32) malloc(sizeof [8] i32);
-    defer if cast(rawptr) arr != null mfree(arr);
+    defer if cast(rawptr) arr != null do mfree(arr);
 
-    for i: 0, 8 arr[i] = i * i;
-    for i: 0, 8 print(arr[i]);
+    for i: 0, 8 do arr[i] = i * i;
+    for i: 0, 8 do print(arr[i]);
 
     return arr[1] + arr[7];
 }
@@ -21,16 +21,16 @@ proc #export "main" {
     print(deferred_example());
 
     first := cast([] i32) malloc(sizeof [4] i32);
-    for i: 0, 4 first[i] = i * 2;
+    for i: 0, 4 do first[i] = i * 2;
 
     second := cast([] f32) malloc(sizeof [24] f32);
-    for i: 0, 24 second[i] = cast(f32) i;
+    for i: 0, 24 do second[i] = cast(f32) i;
 
     print(cast(u32) first);
     print(cast(u32) second);
 
-    for i: 0, 4 print(first[i]);
-    for i: 0, 24 print(second[i]);
+    for i: 0, 4  do print(first[i]);
+    for i: 0, 24 do print(second[i]);
 
     mfree(first);
 
index 15f17cbbeae6b03279dbe788259985d91972244f..d368c5f71ee8bbc894f7e6b96a4685fd7afa4a51 100644 (file)
@@ -12,19 +12,19 @@ PrintableArray :: struct {
 }
 
 print_i32arr :: proc (arr: [] i32, len: i32) {
-    for i: 0, len print(arr[i]);
+    for i: 0, len do print(arr[i]);
 }
 
 print_i64arr :: proc (arr: [] i64, len: i32) {
-    for i: 0, len print(arr[i]);
+    for i: 0, len do print(arr[i]);
 }
 
 print_f32arr :: proc (arr: [] f32, len: i32) {
-    for i: 0, len print(arr[i]);
+    for i: 0, len do print(arr[i]);
 }
 
 print_f64arr :: proc (arr: [] f64, len: i32) {
-    for i: 0, len print(arr[i]);
+    for i: 0, len do print(arr[i]);
 }
 
 // NOTE: print null-terminated string
@@ -37,7 +37,7 @@ print_str :: proc (str: ^u8) {
 }
 
 print_str_len :: proc (str: [] u8, len: i32) {
-    for i: 0, len print(cast(i32) str[i]);
+    for i: 0, len do print(cast(i32) str[i]);
 }
 
 print :: proc #overloaded {
index 63bf046efb4a76ffa2f5698507f3492b3949ab6c..baea6318fc86bc7cc7fbd4c3af4b1d11eac0c8e3 100644 (file)
@@ -65,8 +65,8 @@ CHECK(if, AstIf* ifnode) {
         return 1;
     }
 
-    if (ifnode->true_stmt)  if (check_statement(ifnode->true_stmt))  return 1;
-    if (ifnode->false_stmt) if (check_statement(ifnode->false_stmt)) return 1;
+    if (ifnode->true_stmt)  if (check_statement((AstNode *) ifnode->true_stmt))  return 1;
+    if (ifnode->false_stmt) if (check_statement((AstNode *) ifnode->false_stmt)) return 1;
 
     return 0;
 }
@@ -81,7 +81,7 @@ CHECK(while, AstWhile* whilenode) {
         return 1;
     }
 
-    return check_statement(whilenode->stmt);
+    return check_block(whilenode->stmt);
 }
 
 CHECK(for, AstFor* fornode) {
@@ -116,7 +116,7 @@ CHECK(for, AstFor* fornode) {
         }
 
 
-    if (check_statement(fornode->stmt)) return 1;
+    if (check_block(fornode->stmt)) return 1;
 
     return 0;
 }
index a08b46e8f021dd3c19dc723b81ad7c45bf334903..9546f7bdb0c56787cb8de61f60cb8d6b78b5489a 100644 (file)
@@ -27,6 +27,7 @@ static const char* token_type_names[] = {
     "sizeof",
     "alignof",
     "defer",
+    "do",
 
     "->",
     "<-",
@@ -164,6 +165,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
     LITERAL_TOKEN("sizeof",     1, Token_Type_Keyword_Sizeof);
     LITERAL_TOKEN("alignof",    1, Token_Type_Keyword_Alignof);
     LITERAL_TOKEN("defer",      1, Token_Type_Keyword_Defer);
+    LITERAL_TOKEN("do",         1, Token_Type_Keyword_Do);
     LITERAL_TOKEN("true",       1, Token_Type_Literal_True);
     LITERAL_TOKEN("false",      1, Token_Type_Literal_False);
     LITERAL_TOKEN("->",         0, Token_Type_Right_Arrow);
index 17903d2c4ab39e4396749a25b6655d98705dc16c..7702fd91e5fdddb263f7f8dcb0c9af4b3e131dde 100644 (file)
@@ -512,7 +512,7 @@ static AstIf* parse_if_stmt(OnyxParser* parser) {
     expect_token(parser, Token_Type_Keyword_If);
 
     AstTyped* cond = parse_expression(parser);
-    AstNode*  true_stmt = parse_statement(parser);
+    AstBlock* true_stmt = parse_block(parser);
 
     AstIf* if_node = make_node(AstIf, Ast_Kind_If);
     AstIf* root_if = if_node;
@@ -526,20 +526,20 @@ static AstIf* parse_if_stmt(OnyxParser* parser) {
         AstIf* elseif_node = make_node(AstIf, Ast_Kind_If);
 
         cond = parse_expression(parser);
-        true_stmt = parse_statement(parser);
+        true_stmt = parse_block(parser);
 
         elseif_node->cond = cond;
         if (true_stmt != NULL)
             elseif_node->true_stmt = true_stmt;
 
-        if_node->false_stmt = (AstNode *) elseif_node;
+        if_node->false_stmt = (AstBlock *) elseif_node;
         if_node = elseif_node;
     }
 
     if (parser->curr->type == Token_Type_Keyword_Else) {
         consume_token(parser);
 
-        AstNode* false_stmt = parse_statement(parser);
+        AstBlock* false_stmt = parse_block(parser);
         if (false_stmt != NULL)
             if_node->false_stmt = false_stmt;
     }
@@ -552,7 +552,7 @@ static AstWhile* parse_while_stmt(OnyxParser* parser) {
     OnyxToken* while_token = expect_token(parser, Token_Type_Keyword_While);
 
     AstTyped* cond = parse_expression(parser);
-    AstNode*  stmt = parse_statement(parser);
+    AstBlock* stmt = parse_block(parser);
 
     AstWhile* while_node = make_node(AstWhile, Ast_Kind_While);
     while_node->token = while_token;
@@ -582,7 +582,7 @@ static AstFor* parse_for_stmt(OnyxParser* parser) {
         for_node->step = parse_expression(parser);
     }
 
-    for_node->stmt = parse_statement(parser);
+    for_node->stmt = parse_block(parser);
 
     return for_node;
 }
@@ -681,6 +681,7 @@ static AstNode* parse_statement(OnyxParser* parser) {
 
         case '{':
         case Token_Type_Empty_Block:
+        case Token_Type_Keyword_Do:
             needs_semicolon = 0;
             retval = (AstNode *) parse_block(parser);
             break;
@@ -785,6 +786,17 @@ static AstBlock* parse_block(OnyxParser* parser) {
         return block;
     }
 
+    if (parser->curr->type == Token_Type_Keyword_Do) {
+        consume_token(parser);
+        block->body = parse_statement(parser);
+        return block;
+    }
+
+    if (parser->curr->type != '{') {
+        expect_token(parser, '{');
+        find_token(parser, '}');
+        return block;
+    }
     expect_token(parser, '{');
 
     AstNode** next = &block->body;
index 0e9dca6883a0d77965e78dcd941cf00d60de6c69..3015662bcde270c754a20a0912f7cfc8e03f1b78 100644 (file)
@@ -273,13 +273,13 @@ static void symres_if(AstIf* ifnode) {
     //
     // The declaration will cause a problem but semantically the above
     // doesn't make sense.
-    if (ifnode->true_stmt != NULL)  symres_statement(ifnode->true_stmt);
-    if (ifnode->false_stmt != NULL) symres_statement(ifnode->false_stmt);
+    if (ifnode->true_stmt != NULL)  symres_statement((AstNode *) ifnode->true_stmt);
+    if (ifnode->false_stmt != NULL) symres_statement((AstNode *) ifnode->false_stmt);
 }
 
 static void symres_while(AstWhile* whilenode) {
     symres_expression(&whilenode->cond);
-    symres_statement(whilenode->stmt);
+    symres_block(whilenode->stmt);
 }
 
 static void symres_for(AstFor* fornode) {
@@ -293,7 +293,7 @@ static void symres_for(AstFor* fornode) {
     symres_expression(&fornode->end);
     if (fornode->step) symres_expression(&fornode->step);
 
-    symres_statement(fornode->stmt);
+    symres_block(fornode->stmt);
 
     scope_leave();
 }
index c1d963aae82832832244fa33a9cff96b706f0f16..4bd78cc91d4a0497084511ff138303d231bd9663 100644 (file)
@@ -498,24 +498,20 @@ COMPILE_FUNC(if, AstIf* if_node) {
     bh_arr_push(mod->structured_jump_target, 0);
 
     if (if_node->true_stmt) {
-        if (if_node->true_stmt->kind == Ast_Kind_Block) {
-            forll (AstNode, stmt, ((AstBlock *) if_node->true_stmt)->body, next) {
-                compile_statement(mod, &code, stmt);
-            }
-        } else {
-            compile_statement(mod, &code, if_node->true_stmt);
+        forll (AstNode, stmt, if_node->true_stmt->body, next) {
+            compile_statement(mod, &code, stmt);
         }
     }
 
     if (if_node->false_stmt) {
         WI(WI_ELSE);
 
-        if (if_node->false_stmt->kind == Ast_Kind_Block) {
+        if (if_node->false_stmt->kind == Ast_Kind_If) {
+            compile_if(mod, &code, (AstIf *) if_node->false_stmt);
+        } else {
             forll (AstNode, stmt, ((AstBlock *) if_node->false_stmt)->body, next) {
                 compile_statement(mod, &code, stmt);
             }
-        } else {
-            compile_statement(mod, &code, if_node->false_stmt);
         }
     }
 
@@ -541,12 +537,8 @@ COMPILE_FUNC(while, AstWhile* while_node) {
     bh_arr_push(mod->structured_jump_target, 1);
     bh_arr_push(mod->structured_jump_target, 2);
 
-    if (while_node->stmt->kind == Ast_Kind_Block) {
-        forll (AstNode, stmt, ((AstBlock *) while_node->stmt)->body, next) {
-            compile_statement(mod, &code, stmt);
-        }
-    } else {
-        compile_statement(mod, &code, while_node->stmt);
+    forll (AstNode, stmt, while_node->stmt->body, next) {
+        compile_statement(mod, &code, stmt);
     }
 
     compile_deferred_stmts(mod, &code, (AstNode *) while_node);
@@ -581,12 +573,8 @@ COMPILE_FUNC(for, AstFor* for_node) {
     WI(WI_I32_GE_S);
     WID(WI_COND_JUMP, 0x01);
 
-    if (for_node->stmt->kind == Ast_Kind_Block) {
-        forll (AstNode, stmt, ((AstBlock *) for_node->stmt)->body, next) {
-            compile_statement(mod, &code, stmt);
-        }
-    } else {
-        compile_statement(mod, &code, for_node->stmt);
+    forll (AstNode, stmt, for_node->stmt->body, next) {
+        compile_statement(mod, &code, stmt);
     }
 
     if (for_node->step == NULL)