From 35ba5771a5dbe5fec3fea8804fb46fe843478830 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 24 Feb 2018 19:03:29 +0000 Subject: [PATCH] Replace `compile_assert` with `#assert` --- core/atomics.odin | 2 +- core/c.odin | 2 +- core/opengl.odin | 2 +- core/thread.odin | 2 +- examples/demo.odin | 7 ++- examples/old_demos/demo001.odin | 2 +- examples/old_demos/demo002.odin | 4 +- examples/old_demos/demo005.odin | 4 +- examples/old_demos/demo006.odin | 6 +- examples/old_demos/old_runtime.odin | 2 +- examples/old_stuff/demo_backup.odin | 6 +- examples/punity.odin | 2 +- src/check_expr.cpp | 91 +++++++++++++++-------------- src/checker.cpp | 12 ++++ src/checker.hpp | 5 +- src/entity.cpp | 2 - src/parser.cpp | 14 +++++ 17 files changed, 96 insertions(+), 69 deletions(-) diff --git a/core/atomics.odin b/core/atomics.odin index b1dccbb89..a95f046f7 100644 --- a/core/atomics.odin +++ b/core/atomics.odin @@ -4,7 +4,7 @@ when ODIN_OS == "windows" { import win32 "core:sys/windows.odin" } -_ :: compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version +#assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version yield_thread :: proc() { win32.mm_pause(); } diff --git a/core/c.odin b/core/c.odin index 6ade83638..40be8acfb 100644 --- a/core/c.odin +++ b/core/c.odin @@ -29,7 +29,7 @@ c_double :: f64; c_complex_float :: complex64; c_complex_double :: complex128; -_ :: compile_assert(size_of(uintptr) == size_of(int)); +#assert(size_of(uintptr) == size_of(int)); c_size_t :: uint; c_ssize_t :: int; diff --git a/core/opengl.odin b/core/opengl.odin index 6869c64ff..ff5603a8f 100644 --- a/core/opengl.odin +++ b/core/opengl.odin @@ -8,7 +8,7 @@ when ODIN_OS == "windows" { export "core:opengl_constants.odin" -_ := compile_assert(ODIN_OS != "osx"); +(ODIN_OS != "osx"); @(default_calling_convention="c", link_prefix="gl") foreign lib { diff --git a/core/thread.odin b/core/thread.odin index 4bc5e4987..368abc204 100644 --- a/core/thread.odin +++ b/core/thread.odin @@ -1,4 +1,4 @@ -_ :: compile_assert(ODIN_OS == "windows"); +#assert(ODIN_OS == "windows"); when ODIN_OS == "windows" { import win32 "core:sys/windows.odin" diff --git a/examples/demo.odin b/examples/demo.odin index 0bbe0fe2d..3450e8078 100644 --- a/examples/demo.odin +++ b/examples/demo.odin @@ -101,13 +101,13 @@ general_stuff :: proc() { // If the type expression is `struct`, `union`, `enum`, `proc`, or `bit_field`, the types will always been distinct. Int32 :: i32; - compile_assert(Int32 == i32); + #assert(Int32 == i32); My_Int32 :: distinct i32; - compile_assert(My_Int32 != i32); + #assert(My_Int32 != i32); My_Struct :: struct{x: int}; - compile_assert(My_Struct != struct{x: int}); + #assert(My_Struct != struct{x: int}); } } @@ -760,6 +760,7 @@ complete_switch :: proc() { } } + main :: proc() { when true { general_stuff(); diff --git a/examples/old_demos/demo001.odin b/examples/old_demos/demo001.odin index 0d5fb8926..a3aea1cb7 100644 --- a/examples/old_demos/demo001.odin +++ b/examples/old_demos/demo001.odin @@ -328,7 +328,7 @@ miscellany :: proc() { */ // assert(false) - // compile_assert(false) + // #assert(false) // panic("Panic message goes here") } diff --git a/examples/old_demos/demo002.odin b/examples/old_demos/demo002.odin index e4640d125..e9b9988da 100644 --- a/examples/old_demos/demo002.odin +++ b/examples/old_demos/demo002.odin @@ -171,8 +171,8 @@ new_builtins :: proc() { { // Compile time assert COND :: true; - compile_assert(COND); - // compile_assert(!COND) + #assert(COND); + // #assert(!COND) // Runtime assert x := true; diff --git a/examples/old_demos/demo005.odin b/examples/old_demos/demo005.odin index 9e13d667d..c8273b03b 100644 --- a/examples/old_demos/demo005.odin +++ b/examples/old_demos/demo005.odin @@ -43,7 +43,7 @@ syntax :: proc() { Thing2 :: struct {x: f32, y: int, z: ^[]int}; // Slice interals are now just a `ptr+len+cap` - slice: []int; compile_assert(size_of(slice) == 3*size_of(int)); + slice: []int; #assert(size_of(slice) == 3*size_of(int)); // Helper type - Help the reader understand what it is quicker My_Int :: #type int; @@ -218,7 +218,7 @@ loops :: proc() { name := "你好,世界"; fmt.println(name); for r in name { - compile_assert(type_of(r) == rune); + #assert(type_of(r) == rune); fmt.printf("%r\n", r); } diff --git a/examples/old_demos/demo006.odin b/examples/old_demos/demo006.odin index 209f31381..735e7ac50 100644 --- a/examples/old_demos/demo006.odin +++ b/examples/old_demos/demo006.odin @@ -24,7 +24,7 @@ when true { * ..< and ... removed and replace with .. (half-closed range) Changed: - * `compile_assert` and `assert` return the value of the condition for semantic reasons + * `#assert` and `assert` return the value of the condition for semantic reasons * thread_local -> #thread_local * #include -> #load * Files only get checked if they are actually used @@ -159,8 +159,8 @@ when true { fmt.println(i); } - compile_assert(size_of([vector 7]bool) >= size_of([7]bool)); - compile_assert(size_of([vector 7]i32) >= size_of([7]i32)); + #assert(size_of([vector 7]bool) >= size_of([7]bool)); + #assert(size_of([vector 7]i32) >= size_of([7]i32)); // align_of([vector 7]i32) != align_of([7]i32) // this may be the case } diff --git a/examples/old_demos/old_runtime.odin b/examples/old_demos/old_runtime.odin index 655058e0a..e605e7820 100644 --- a/examples/old_demos/old_runtime.odin +++ b/examples/old_demos/old_runtime.odin @@ -46,7 +46,7 @@ memory_copy :: proc(dst, src: rawptr, n: int) #inline { } v128b :: type {4}u32 - compile_assert(align_of(v128b) == 16) + #assert(align_of(v128b) == 16) d, s: ^byte = dst, src diff --git a/examples/old_stuff/demo_backup.odin b/examples/old_stuff/demo_backup.odin index 8eeaeb357..6a7952ae1 100644 --- a/examples/old_stuff/demo_backup.odin +++ b/examples/old_stuff/demo_backup.odin @@ -50,9 +50,9 @@ general_stuff :: proc() { foo := Foo{123, 0.513, "A string"}; x, y, z := expand_to_tuple(foo); fmt.println(x, y, z); - compile_assert(type_of(x) == int); - compile_assert(type_of(y) == f32); - compile_assert(type_of(z) == string); + #assert(type_of(x) == int); + #assert(type_of(y) == f32); + #assert(type_of(z) == string); // By default, all variables are zeroed diff --git a/examples/punity.odin b/examples/punity.odin index 49d965360..e8b0532f2 100644 --- a/examples/punity.odin +++ b/examples/punity.odin @@ -10,7 +10,7 @@ CANVAS_SCALE :: 3; FRAME_TIME :: 1.0/30.0; WINDOW_TITLE :: "Punity\x00"; -_ :: compile_assert(CANVAS_WIDTH % 16 == 0); +#assert(CANVAS_WIDTH % 16 == 0); WINDOW_WIDTH :: CANVAS_WIDTH * CANVAS_SCALE; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 147c6c6a6..526932229 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2813,28 +2813,49 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id case BuiltinProc_DIRECTIVE: { ast_node(bd, BasicDirective, ce->proc); String name = bd->name; - GB_ASSERT(name == "location"); - if (ce->args.count > 1) { - error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count); - } - if (ce->args.count > 0) { - AstNode *arg = ce->args[0]; - Entity *e = nullptr; - Operand o = {}; - if (arg->kind == AstNode_Ident) { - e = check_ident(c, &o, arg, nullptr, nullptr, true); - } else if (arg->kind == AstNode_SelectorExpr) { - e = check_selector(c, &o, arg, nullptr); + if (name == "location") { + if (ce->args.count > 1) { + error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count); } - if (e == nullptr) { - error(ce->args[0], "'#location' expected a valid entity name"); + if (ce->args.count > 0) { + AstNode *arg = ce->args[0]; + Entity *e = nullptr; + Operand o = {}; + if (arg->kind == AstNode_Ident) { + e = check_ident(c, &o, arg, nullptr, nullptr, true); + } else if (arg->kind == AstNode_SelectorExpr) { + e = check_selector(c, &o, arg, nullptr); + } + if (e == nullptr) { + error(ce->args[0], "'#location' expected a valid entity name"); + } } + + operand->type = t_source_code_location; + operand->mode = Addressing_Value; + } else if (name == "assert") { + if (ce->args.count != 1) { + error(call, "'#assert' expects at 1 argument, got %td", ce->args.count); + return false; + } + if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) { + gbString str = expr_to_string(ce->args[0]); + error(call, "'%s' is not a constant boolean", str); + gb_string_free(str); + return false; + } + if (!operand->value.value_bool) { + gbString arg = expr_to_string(ce->args[0]); + error(call, "Compile time assertion: %s", arg); + gb_string_free(arg); + } + + operand->type = t_untyped_bool; + operand->mode = Addressing_Constant; + } else { + GB_PANIC("Unhandled #%.*s", LIT(name)); } - - operand->type = t_source_code_location; - operand->mode = Addressing_Value; - break; } @@ -3321,25 +3342,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id break; } - case BuiltinProc_compile_assert: - // proc compile_assert(cond: bool) -> bool - - if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) { - gbString str = expr_to_string(ce->args[0]); - error(call, "'%s' is not a constant boolean", str); - gb_string_free(str); - return false; - } - if (!operand->value.value_bool) { - gbString str = expr_to_string(ce->args[0]); - error(call, "Compile time assertion: '%s'", str); - gb_string_free(str); - } - - operand->mode = Addressing_Constant; - operand->type = t_untyped_bool; - break; - case BuiltinProc_swizzle: { // proc swizzle(v: [N]T, ...int) -> [M]T Type *type = base_type(operand->type); @@ -4805,12 +4807,15 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { ce->proc->kind == AstNode_BasicDirective) { ast_node(bd, BasicDirective, ce->proc); String name = bd->name; - GB_ASSERT(name == "location"); - operand->mode = Addressing_Builtin; - operand->builtin_id = BuiltinProc_DIRECTIVE; - operand->expr = ce->proc; - operand->type = t_invalid; - add_type_and_value(&c->info, ce->proc, operand->mode, operand->type, operand->value); + if (name == "location" || name == "assert") { + operand->mode = Addressing_Builtin; + operand->builtin_id = BuiltinProc_DIRECTIVE; + operand->expr = ce->proc; + operand->type = t_invalid; + add_type_and_value(&c->info, ce->proc, operand->mode, operand->type, operand->value); + } else { + GB_PANIC("Unhandled #%.*s", LIT(name)); + } } else { check_expr_or_type(c, operand, ce->proc); } diff --git a/src/checker.cpp b/src/checker.cpp index 1cc4c1ca9..3a11d4f94 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1,6 +1,8 @@ #include "entity.cpp" #include "types.cpp" +void check_expr(Checker *c, Operand *operand, AstNode *expression); + bool is_operand_value(Operand o) { switch (o.mode) { @@ -272,6 +274,7 @@ void destroy_scope(Scope *scope) { map_destroy(&scope->elements); array_free(&scope->shared); array_free(&scope->delayed_file_decls); + array_free(&scope->delayed_asserts); ptr_set_destroy(&scope->implicit); ptr_set_destroy(&scope->imported); ptr_set_destroy(&scope->exported); @@ -444,6 +447,7 @@ GB_COMPARE_PROC(entity_variable_pos_cmp) { return token_pos_cmp(x->token.pos, y->token.pos); } + void check_scope_usage(Checker *c, Scope *scope) { // TODO(bill): Use this? #if 0 @@ -2678,6 +2682,14 @@ bool collect_file_decls(Checker *c, Array decls) { } } case_end; + + case_ast_node(ce, CallExpr, decl); + if (ce->proc->kind == AstNode_BasicDirective && + ce->proc->BasicDirective.name == "assert") { + Operand o = {}; + check_expr(c, &o, decl); + } + case_end; } } diff --git a/src/checker.hpp b/src/checker.hpp index bb8a11658..90ced6a67 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -90,8 +90,6 @@ enum BuiltinProcId { BuiltinProc_type_of, BuiltinProc_type_info_of, - BuiltinProc_compile_assert, - BuiltinProc_swizzle, BuiltinProc_complex, @@ -134,8 +132,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_of"), 1, false, Expr_Expr}, {STR_LIT("type_info_of"), 1, false, Expr_Expr}, - {STR_LIT("compile_assert"), 1, false, Expr_Expr}, - {STR_LIT("swizzle"), 1, true, Expr_Expr}, {STR_LIT("complex"), 2, false, Expr_Expr}, @@ -221,6 +217,7 @@ struct Scope { Array shared; Array delayed_file_decls; + Array delayed_asserts; PtrSet imported; PtrSet exported; // NOTE(bhall): Contains 'using import' too bool is_proc; diff --git a/src/entity.cpp b/src/entity.cpp index f591287d6..14efe6b60 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -303,8 +303,6 @@ Entity *make_entity_label(gbAllocator a, Scope *scope, Token token, Type *type, return entity; } - - Entity *make_entity_dummy_variable(gbAllocator a, Scope *scope, Token token) { token.string = str_lit("_"); return make_entity_variable(a, scope, token, nullptr, false); diff --git a/src/parser.cpp b/src/parser.cpp index f05f9a0e1..182576913 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1659,6 +1659,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) { } else if (name.string == "location") { AstNode *tag = ast_basic_directive(f, token, name.string); return parse_call_expr(f, tag); + } else if (name.string == "assert") { + AstNode *tag = ast_basic_directive(f, token, name.string); + return parse_call_expr(f, tag); } else { operand = ast_tag_expr(f, token, name, parse_expr(f, false)); } @@ -3735,6 +3738,9 @@ AstNode *parse_stmt(AstFile *f) { break; } return s; + } else if (tag == "assert") { + AstNode *t = ast_basic_directive(f, hash_token, tag); + return parse_call_expr(f, t); } if (tag == "include") { @@ -4058,6 +4064,14 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Arraykind != AstNode_EmptyStmt && node->kind != AstNode_WhenStmt) { // NOTE(bill): Sanity check + + if (node->kind == AstNode_CallExpr && + node->CallExpr.proc->kind == AstNode_BasicDirective && + node->CallExpr.proc->BasicDirective.name == "assert") { + // NOTE(bill): Okay! + continue; + } + syntax_error(node, "Only declarations are allowed at file scope, got %.*s", LIT(ast_node_strings[node->kind])); } else if (node->kind == AstNode_ImportDecl) { ast_node(id, ImportDecl, node);