Browse Source

Improve logic for diverging procedures by checking if it terminates

gingerBill 4 years ago
parent
commit
41f2539484
3 changed files with 31 additions and 11 deletions
  1. 4 4
      core/runtime/core.odin
  2. 9 2
      src/check_decl.cpp
  3. 18 5
      src/check_stmt.cpp

+ 4 - 4
core/runtime/core.odin

@@ -255,7 +255,7 @@ Source_Code_Location :: struct {
 	procedure:    string,
 }
 
-Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location);
+Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location) -> !;
 
 // Allocation Stuff
 Allocator_Mode :: enum byte {
@@ -483,7 +483,7 @@ __init_context :: proc "contextless" (c: ^Context) {
 	c.logger.data = nil;
 }
 
-default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) {
+default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
 	print_caller_location(loc);
 	print_string(" ");
 	print_string(prefix);
@@ -492,6 +492,6 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code
 		print_string(message);
 	}
 	print_byte('\n');
-	debug_trap();
-	// trap();
+	// debug_trap();
+	trap();
 }

+ 9 - 2
src/check_decl.cpp

@@ -1297,13 +1297,21 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
 					error(bs->close, "Missing return statement at the end of the procedure");
 				}
 			}
+		} else if (type->Proc.diverging) {
+			if (!check_is_terminating(body, str_lit(""))) {
+				if (token.kind == Token_Ident) {
+					error(bs->close, "Missing diverging call at the end of the procedure '%.*s'", LIT(token.string));
+				} else {
+					// NOTE(bill): Anonymous procedure (lambda)
+					error(bs->close, "Missing diverging call at the end of the procedure");
+				}
+			}
 		}
 	}
 	check_close_scope(ctx);
 
 	check_scope_usage(ctx->checker, ctx->scope);
 
-#if 1
 	if (decl->parent != nullptr) {
 		Scope *ps = decl->parent->scope;
 		if (ps->flags & (ScopeFlag_File & ScopeFlag_Pkg & ScopeFlag_Global)) {
@@ -1321,7 +1329,6 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
 			}
 		}
 	}
-#endif
 }
 
 

+ 18 - 5
src/check_stmt.cpp

@@ -247,11 +247,24 @@ bool check_is_terminating(Ast *node, String const &label) {
 
 	case_ast_node(ws, WhenStmt, node);
 		// TODO(bill): Is this logic correct for when statements?
-		if (ws->else_stmt != nullptr) {
-			if (check_is_terminating(ws->body, label) &&
-			    check_is_terminating(ws->else_stmt, label)) {
-			    return true;
-		    }
+		auto const &tv = ws->cond->tav;
+		if (tv.mode != Addressing_Constant) {
+			// NOTE(bill): Check the things regardless as a bug occurred earlier
+			if (ws->else_stmt != nullptr) {
+				if (check_is_terminating(ws->body, label) &&
+				    check_is_terminating(ws->else_stmt, label)) {
+				    return true;
+			    }
+			}
+			return false;
+		}
+
+		if (tv.value.kind == ExactValue_Bool) {
+			if (tv.value.value_bool) {
+				return check_is_terminating(ws->body, label);
+			} else {
+				return check_is_terminating(ws->else_stmt, label);
+			}
 		}
 	case_end;