`defer` has better semantics with targeted jump statements
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 6 Jan 2021 00:55:59 +0000 (18:55 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 6 Jan 2021 00:55:59 +0000 (18:55 -0600)
bin/onyx
onyx.exe
src/onyx.c
src/onyxchecker.c
src/onyxwasm.c
tests/defer_with_continue [new file with mode: 0644]
tests/defer_with_continue.onyx [new file with mode: 0644]

index 0c6aa12d88d726dfce55fed2bdd60cdbf8bbab2f..f7892b47ceea87cd34349535852b227e9b8063a6 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 3236d2a719c7565d23720b960c4d7d6fecc044cf..192f9e4f42f37470c7af4871b7de72b946607d20 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index d342d34897a14e6061f84435361e049fb2e8230c..defec5e248d15ceb5333ea578fe78d64ce6450ab 100644 (file)
@@ -234,6 +234,8 @@ static char* lookup_included_file(CompilerState* cs, char* filename) {
     #define DIR_SEPARATOR '\\'
 #endif
 
+    fori (i, 0, 128) if (fn[i] == '/') fn[i] = DIR_SEPARATOR;
+
     bh_arr_each(const char *, folder, cs->options->included_folders) {
         if ((*folder)[strlen(*folder) - 1] != DIR_SEPARATOR)
             bh_snprintf(path, 256, "%s%c%s", *folder, DIR_SEPARATOR, fn);
index f58a3cfc96d81813688ac610198f332ef428675c..d3d7d4724e6339fba2bbbaf5363b7abde11a2fbf 100644 (file)
@@ -216,6 +216,7 @@ CheckStatus check_switch(AstSwitch* switchnode) {
     if (switchnode->assignment != NULL) CHECK(statement, (AstNode *) switchnode->assignment);
 
     CHECK(expression, &switchnode->expr);
+    resolve_expression_type(switchnode->expr);
     if (!type_is_integer(switchnode->expr->type) && switchnode->expr->type->kind != Type_Kind_Enum) {
         onyx_report_error(switchnode->expr->token->pos, "expected integer or enum type for switch expression");
         return Check_Error;
@@ -387,6 +388,10 @@ CheckStatus check_call(AstCall* call) {
 
     // NOTE: Build callee's type
     fill_in_type((AstTyped *) callee);
+    if (callee->type == NULL) {
+        onyx_report_error(call->token->pos, "There was an error with looking up the type of this function.");
+        return Check_Error;
+    }
 
     if (callee->type->kind != Type_Kind_Function) {
         onyx_report_error(call->token->pos,
index 83e690a39d6962248c80714d5979d74ea83aafdf..1a9ede093a8fbcae5a6a98847c8e49c53ad069f5 100644 (file)
@@ -256,7 +256,7 @@ EMIT_FUNC(structured_jump, AstJump* jump) {
 
     static const u8 wants[Jump_Type_Count] = { 1, 2, 3 };
 
-    i32 labelidx = 0;
+    u64 labelidx = 0;
     u8 wanted = wants[jump->jump];
     b32 success = 0;
 
@@ -273,6 +273,14 @@ EMIT_FUNC(structured_jump, AstJump* jump) {
         labelidx++;
     }
 
+    if (bh_arr_length(mod->deferred_stmts) != 0) {
+        i32 i = bh_arr_length(mod->deferred_stmts) - 1;
+        while (i >= 0 && mod->deferred_stmts[i].depth >= labelidx) {
+            emit_statement(mod, &code, mod->deferred_stmts[i].stmt);
+            i--;
+        }
+    }
+
     if (success) {
         // NOTE: If the previous instruction was a non conditional jump,
         // don't emit another jump since it will never be reached.
diff --git a/tests/defer_with_continue b/tests/defer_with_continue
new file mode 100644 (file)
index 0000000..66f7581
--- /dev/null
@@ -0,0 +1,28 @@
+Doing something with Index is 0
+Doing something with Index is 1
+Doing something with Index is 2
+Skipping 3!!
+Index is 3
+Doing something with Index is 4
+Doing something with Index is 5
+Doing something with Index is 6
+Doing something with Index is 7
+Doing something with Index is 8
+Doing something with Index is 9
+i is 10
+
+
+===================================
+Doing something with Index is 0
+Doing something with Index is 1
+Doing something with Index is 2
+Skipping 3!!
+Index is 3
+i is 4
+
+
+===================================
+In block deferred!
+Deferred!
+Default!
+At the end!
diff --git a/tests/defer_with_continue.onyx b/tests/defer_with_continue.onyx
new file mode 100644 (file)
index 0000000..4519081
--- /dev/null
@@ -0,0 +1,51 @@
+#load "core/std/js"
+
+use package core
+
+main :: proc (args: [] cstr) {
+    defer println("At the end!");
+    i := 0;
+    while i < 10 {
+        defer i += 1;
+        defer printf("Index is %i\n", i);
+
+        if i == 3 {
+            printf("Skipping %i!!\n", i);
+            continue;
+        }
+
+        printf("Doing something with ");
+    }
+    printf("i is %i\n", i);
+
+    println("\n\n===================================");
+    i = 0;
+    while i < 10 {
+        defer i += 1;
+        defer printf("Index is %i\n", i);
+
+        if i == 3 {
+            printf("Skipping %i!!\n", i);
+            break;
+        }
+
+        printf("Doing something with ");
+    }
+    printf("i is %i\n", i);
+
+    println("\n\n===================================");
+    switch i {
+        case 4 {
+            defer println("Deferred!");
+            {
+                defer println("In block deferred!");
+                fallthrough;
+            }
+            println("Case 4!");
+        }
+
+        case #default {
+            println("Default!");
+        }
+    }
+}