aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrendan Punsky <bpunsky@gmail.com>2018-02-24 14:29:30 -0500
committerBrendan Punsky <bpunsky@gmail.com>2018-02-24 14:29:30 -0500
commitf6c45fc68a5ec82d261ef6821abd3896b9b8405c (patch)
tree17f9b3f62710b11cb7d4dea0d19ab9bad9d8da5e /src
parent60a54f404b94218aa213c6b7547bebfa91158b32 (diff)
parent35ba5771a5dbe5fec3fea8804fb46fe843478830 (diff)
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp89
-rw-r--r--src/checker.cpp12
-rw-r--r--src/checker.hpp5
-rw-r--r--src/entity.cpp2
-rw-r--r--src/parser.cpp22
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);