diff options
| author | Brendan Punsky <bpunsky@gmail.com> | 2018-02-24 14:29:30 -0500 |
|---|---|---|
| committer | Brendan Punsky <bpunsky@gmail.com> | 2018-02-24 14:29:30 -0500 |
| commit | f6c45fc68a5ec82d261ef6821abd3896b9b8405c (patch) | |
| tree | 17f9b3f62710b11cb7d4dea0d19ab9bad9d8da5e /src | |
| parent | 60a54f404b94218aa213c6b7547bebfa91158b32 (diff) | |
| parent | 35ba5771a5dbe5fec3fea8804fb46fe843478830 (diff) | |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.cpp | 89 | ||||
| -rw-r--r-- | src/checker.cpp | 12 | ||||
| -rw-r--r-- | src/checker.hpp | 5 | ||||
| -rw-r--r-- | src/entity.cpp | 2 | ||||
| -rw-r--r-- | src/parser.cpp | 22 |
5 files changed, 76 insertions, 54 deletions
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,27 +2813,48 @@ 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_source_code_location; - operand->mode = Addressing_Value; + operand->type = t_untyped_bool; + operand->mode = Addressing_Constant; + } else { + GB_PANIC("Unhandled #%.*s", LIT(name)); + } 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<AstNode *> 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<Scope *> shared; Array<AstNode *> delayed_file_decls; + Array<AstNode *> delayed_asserts; PtrSet<Scope *> imported; PtrSet<Scope *> 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 d54c63cd9..182576913 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1358,6 +1358,7 @@ void expect_semicolon(AstFile *f, AstNode *s) { switch (f->curr_token.kind) { case Token_CloseBrace: case Token_CloseParen: + case Token_else: return; } } @@ -1658,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)); } @@ -3175,7 +3179,7 @@ AstNode *parse_when_stmt(AstFile *f) { break; case Token_do: { Token arrow = expect_token(f, Token_do); - body = convert_stmt_to_body(f, parse_stmt(f)); + else_stmt = convert_stmt_to_body(f, parse_stmt(f)); } break; default: syntax_error(f->curr_token, "Expected when statement block statement"); @@ -3184,11 +3188,6 @@ AstNode *parse_when_stmt(AstFile *f) { } } - // if (f->curr_proc == nullptr && f->when_level > 1) { - // syntax_error(token, "Nested when statements are not currently supported at the file scope"); - // return ast_bad_stmt(f, token, f->curr_token); - // } - return ast_when_stmt(f, token, cond, body, else_stmt); } @@ -3739,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") { @@ -4062,6 +4064,14 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod node->kind != 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); |