aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-06-26 11:57:26 +0100
committerGinger Bill <bill@gingerbill.org>2017-06-26 11:57:26 +0100
commitc642e326cecd3dc33ca5a9efb6330e757c378dd9 (patch)
treec8bd1554fa2fc9e9d31012d4e98261755a7ced3a /src/check_expr.cpp
parent362a11878283eea69cf5a18b7f05c964643a7a64 (diff)
Undef value `---` (for setting a value to be uninitialized/undefined)
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp38
1 files changed, 35 insertions, 3 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 2f39a6b77..1fa0117ac 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -166,6 +166,13 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
Type *src = base_type(s);
Type *dst = base_type(type);
+ if (is_type_untyped_undef(src)) {
+ if (type_has_undef(dst)) {
+ return 1;
+ }
+ return -1;
+ }
+
if (is_type_untyped_nil(src)) {
if (type_has_nil(dst)) {
return 1;
@@ -328,6 +335,11 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
operand->mode = Addressing_Invalid;
return;
}
+ if (type == NULL && is_type_untyped_undef(operand->type)) {
+ error(operand->expr, "Use of --- in %.*s", LIT(context_name));
+ operand->mode = Addressing_Invalid;
+ return;
+ }
target_type = default_type(operand->type);
if (type != NULL && !is_type_any(type)) {
GB_ASSERT_MSG(is_type_typed(target_type), "%s", type_to_string(type));
@@ -3366,7 +3378,9 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
default:
- if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
+ if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
+ target_type = t_untyped_undef;
+ } else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
operand->mode = Addressing_Invalid;
convert_untyped_error(c, operand, target_type);
return;
@@ -5043,6 +5057,9 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
} else {
// NOTE(bill): Generate the procedure type for this generic instance
// TODO(bill): Clean this shit up!
+
+ ProcedureInfo proc_info = {};
+
if (pt->is_generic) {
GB_ASSERT(entity != NULL);
DeclInfo *old_decl = decl_info_of_entity(&c->info, entity);
@@ -5091,8 +5108,13 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
add_entity_and_decl_info(c, ident, gen_entity, d);
gen_entity->scope = entity->scope;
add_entity_use(c, ident, gen_entity);
- check_procedure_later(c, c->curr_ast_file, token, d, final_proc_type, pd->body, tags);
+ proc_info.file = c->curr_ast_file;
+ proc_info.token = token;
+ proc_info.decl = d;
+ proc_info.type = final_proc_type;
+ proc_info.body = pd->body;
+ proc_info.tags = tags;
if (found) {
array_add(found, gen_entity);
@@ -5107,7 +5129,6 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
GB_ASSERT(gen_entity != NULL);
}
-
TypeProc *pt = &final_proc_type->Proc;
GB_ASSERT(pt->params != NULL);
@@ -5124,6 +5145,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
continue;
} else if (o.mode != Addressing_Type) {
error(o.expr, "Expected a type for the argument");
+ err = CallArgumentError_WrongTypes;
}
if (are_types_identical(e->type, o.type)) {
@@ -5180,6 +5202,10 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
score += s;
}
}
+
+ if (gen_entity != NULL && err == CallArgumentError_None) {
+ check_procedure_later(c, proc_info);
+ }
}
}
@@ -5748,6 +5774,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
return kind;
}
+ init_preload(c);
o->mode = Addressing_Value;
o->type = t_context;
break;
@@ -5761,6 +5788,11 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
check_ident(c, o, node, NULL, type_hint, false);
case_end;
+ case_ast_node(u, Undef, node);
+ o->mode = Addressing_Value;
+ o->type = t_untyped_undef;
+ case_end;
+
case_ast_node(bl, BasicLit, node);
Type *t = t_invalid;