aboutsummaryrefslogtreecommitdiff
path: root/src/checker/expression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/checker/expression.cpp')
-rw-r--r--src/checker/expression.cpp712
1 files changed, 358 insertions, 354 deletions
diff --git a/src/checker/expression.cpp b/src/checker/expression.cpp
index a96ae74d6..dbcfe3d10 100644
--- a/src/checker/expression.cpp
+++ b/src/checker/expression.cpp
@@ -17,7 +17,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
GB_ASSERT(struct_type->kind == Type_Structure);
auto *st = &node->struct_type;
if (st->field_count == 0) {
- print_checker_error(c, ast_node_token(node), "Empty struct{} definition");
+ checker_err(c, ast_node_token(node), "Empty struct{} definition");
return;
}
@@ -45,7 +45,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
u64 key = hash_string(name_token.string);
if (map_get(&entity_map, key)) {
// TODO(bill): Scope checking already checks the declaration
- print_checker_error(c, name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
+ checker_err(c, name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
} else {
map_set(&entity_map, key, e);
fields[field_index++] = e;
@@ -76,7 +76,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel
add_entity(c, scope, name, param);
variables[variable_index++] = param;
} else {
- print_checker_error(c, ast_node_token(name),
+ checker_err(c, ast_node_token(name),
"Invalid parameter (invalid AST)");
}
}
@@ -106,7 +106,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun
if (get_base_type(type)->kind == Type_Array) {
// TODO(bill): Should I allow array's to returned?
- print_checker_error(c, token, "You cannot return an array from a procedure");
+ checker_err(c, token, "You cannot return an array from a procedure");
}
}
tuple->tuple.variables = variables;
@@ -133,15 +133,15 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
}
-void check_identifier(Checker *c, Operand *operand, AstNode *n, Type *named_type) {
+void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
GB_ASSERT(n->kind == AstNode_Identifier);
- operand->mode = Addressing_Invalid;
- operand->expression = n;
+ o->mode = Addressing_Invalid;
+ o->expression = n;
Entity *e = NULL;
scope_lookup_parent_entity(c->curr_scope, n->identifier.token.string, NULL, &e);
if (e == NULL) {
- print_checker_error(c, n->identifier.token,
- "Undeclared type or identifier `%.*s`", LIT(n->identifier.token.string));
+ checker_err(c, n->identifier.token,
+ "Undeclared type or identifier `%.*s`", LIT(n->identifier.token.string));
return;
}
add_entity_use(c, n, e);
@@ -158,9 +158,9 @@ void check_identifier(Checker *c, Operand *operand, AstNode *n, Type *named_type
add_declaration_dependency(c, e);
if (e->type == &basic_types[Basic_Invalid])
return;
- operand->value = e->constant.value;
- GB_ASSERT(operand->value.kind != Value_Invalid);
- operand->mode = Addressing_Constant;
+ o->value = e->constant.value;
+ GB_ASSERT(o->value.kind != ExactValue_Invalid);
+ o->mode = Addressing_Constant;
break;
case Entity_Variable:
@@ -168,21 +168,21 @@ void check_identifier(Checker *c, Operand *operand, AstNode *n, Type *named_type
e->variable.used = true;
if (e->type == &basic_types[Basic_Invalid])
return;
- operand->mode = Addressing_Variable;
+ o->mode = Addressing_Variable;
break;
case Entity_TypeName:
- operand->mode = Addressing_Type;
+ o->mode = Addressing_Type;
break;
case Entity_Procedure:
add_declaration_dependency(c, e);
- operand->mode = Addressing_Value;
+ o->mode = Addressing_Value;
break;
case Entity_Builtin:
- operand->builtin_id = e->builtin.id;
- operand->mode = Addressing_Builtin;
+ o->builtin_id = e->builtin.id;
+ o->mode = Addressing_Builtin;
break;
default:
@@ -190,45 +190,45 @@ void check_identifier(Checker *c, Operand *operand, AstNode *n, Type *named_type
break;
}
- operand->type = e->type;
+ o->type = e->type;
}
-i64 check_array_count(Checker *c, AstNode *expression) {
- if (expression) {
- Operand operand = {};
- check_expression(c, &operand, expression);
- if (operand.mode != Addressing_Constant) {
- if (operand.mode != Addressing_Invalid) {
- print_checker_error(c, ast_node_token(expression), "Array count must be a constant");
+i64 check_array_count(Checker *c, AstNode *e) {
+ if (e) {
+ Operand o = {};
+ check_expression(c, &o, e);
+ if (o.mode != Addressing_Constant) {
+ if (o.mode != Addressing_Invalid) {
+ checker_err(c, ast_node_token(e), "Array count must be a constant");
}
return 0;
}
- if (is_type_untyped(operand.type) || is_type_integer(operand.type)) {
- if (operand.value.kind == Value_Integer) {
- i64 count = operand.value.value_integer;
+ if (is_type_untyped(o.type) || is_type_integer(o.type)) {
+ if (o.value.kind == ExactValue_Integer) {
+ i64 count = o.value.value_integer;
if (count >= 0)
return count;
- print_checker_error(c, ast_node_token(expression), "Invalid array count");
+ checker_err(c, ast_node_token(e), "Invalid array count");
return 0;
}
}
- print_checker_error(c, ast_node_token(expression), "Array count must be an integer");
+ checker_err(c, ast_node_token(e), "Array count must be an integer");
}
return 0;
}
-Type *check_type_expression_extra(Checker *c, AstNode *expression, Type *named_type) {
+Type *check_type_expression_extra(Checker *c, AstNode *e, Type *named_type) {
gbString err_str = NULL;
defer (gb_string_free(err_str));
- switch (expression->kind) {
+ switch (e->kind) {
case AstNode_Identifier: {
- Operand operand = {};
- check_identifier(c, &operand, expression, named_type);
- switch (operand.mode) {
+ Operand o = {};
+ check_identifier(c, &o, e, named_type);
+ switch (o.mode) {
case Addressing_Type: {
- Type *t = operand.type;
+ Type *t = o.type;
set_base_type(named_type, t);
return t;
} break;
@@ -237,28 +237,28 @@ Type *check_type_expression_extra(Checker *c, AstNode *expression, Type *named_t
break;
case Addressing_NoValue:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` used as a type", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` used as a type", err_str);
break;
default:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` used as a type when not a type", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` used as a type when not a type", err_str);
break;
}
} break;
case AstNode_ParenExpression:
- return check_type(c, expression->paren_expression.expression, named_type);
+ return check_type(c, e->paren_expression.expression, named_type);
case AstNode_ArrayType:
- if (expression->array_type.count != NULL) {
+ if (e->array_type.count != NULL) {
Type *t = make_type_array(c->allocator,
- check_type(c, expression->array_type.element),
- check_array_count(c, expression->array_type.count));
+ check_type(c, e->array_type.element),
+ check_array_count(c, e->array_type.count));
set_base_type(named_type, t);
return t;
} else {
- Type *t = make_type_slice(c->allocator, check_type(c, expression->array_type.element));
+ Type *t = make_type_slice(c->allocator, check_type(c, e->array_type.element));
set_base_type(named_type, t);
return t;
}
@@ -267,12 +267,12 @@ Type *check_type_expression_extra(Checker *c, AstNode *expression, Type *named_t
case AstNode_StructType: {
Type *t = make_type_structure(c->allocator);
set_base_type(named_type, t);
- check_struct_type(c, t, expression);
+ check_struct_type(c, t, e);
return t;
} break;
case AstNode_PointerType: {
- Type *t = make_type_pointer(c->allocator, check_type(c, expression->pointer_type.type_expression));
+ Type *t = make_type_pointer(c->allocator, check_type(c, e->pointer_type.type_expression));
set_base_type(named_type, t);
return t;
} break;
@@ -280,15 +280,15 @@ Type *check_type_expression_extra(Checker *c, AstNode *expression, Type *named_t
case AstNode_ProcedureType: {
Type *t = alloc_type(c->allocator, Type_Procedure);
set_base_type(named_type, t);
- check_open_scope(c, expression);
- check_procedure_type(c, t, expression);
+ check_open_scope(c, e);
+ check_procedure_type(c, t, e);
check_close_scope(c);
return t;
} break;
default:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` is not a type", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` is not a type", err_str);
break;
}
@@ -298,16 +298,16 @@ Type *check_type_expression_extra(Checker *c, AstNode *expression, Type *named_t
}
-Type *check_type(Checker *c, AstNode *expression, Type *named_type) {
- Value null_value = {Value_Invalid};
+Type *check_type(Checker *c, AstNode *e, Type *named_type) {
+ ExactValue null_value = {ExactValue_Invalid};
Type *type = NULL;
gbString err_str = NULL;
defer (gb_string_free(err_str));
- switch (expression->kind) {
+ switch (e->kind) {
case AstNode_Identifier: {
Operand operand = {};
- check_identifier(c, &operand, expression, named_type);
+ check_identifier(c, &operand, e, named_type);
switch (operand.mode) {
case Addressing_Type: {
type = operand.type;
@@ -319,37 +319,37 @@ Type *check_type(Checker *c, AstNode *expression, Type *named_type) {
break;
case Addressing_NoValue:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` used as a type", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` used as a type", err_str);
break;
default:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` used as a type when not a type", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` used as a type when not a type", err_str);
break;
}
} break;
case AstNode_SelectorExpression: {
- Operand operand = {};
- check_selector(c, &operand, expression);
+ Operand o = {};
+ check_selector(c, &o, e);
- if (operand.mode == Addressing_Type) {
- set_base_type(type, operand.type);
- return operand.type;
+ if (o.mode == Addressing_Type) {
+ set_base_type(type, o.type);
+ return o.type;
}
} break;
case AstNode_ParenExpression:
- return check_type(c, expression->paren_expression.expression, named_type);
+ return check_type(c, e->paren_expression.expression, named_type);
case AstNode_ArrayType: {
- if (expression->array_type.count != NULL) {
+ if (e->array_type.count != NULL) {
type = make_type_array(c->allocator,
- check_type(c, expression->array_type.element),
- check_array_count(c, expression->array_type.count));
+ check_type(c, e->array_type.element),
+ check_array_count(c, e->array_type.count));
set_base_type(named_type, type);
} else {
- type = make_type_slice(c->allocator, check_type(c, expression->array_type.element));
+ type = make_type_slice(c->allocator, check_type(c, e->array_type.element));
set_base_type(named_type, type);
}
goto end;
@@ -358,12 +358,12 @@ Type *check_type(Checker *c, AstNode *expression, Type *named_type) {
case AstNode_StructType: {
type = make_type_structure(c->allocator);
set_base_type(named_type, type);
- check_struct_type(c, type, expression);
+ check_struct_type(c, type, e);
goto end;
} break;
case AstNode_PointerType: {
- type = make_type_pointer(c->allocator, check_type(c, expression->pointer_type.type_expression));
+ type = make_type_pointer(c->allocator, check_type(c, e->pointer_type.type_expression));
set_base_type(named_type, type);
goto end;
} break;
@@ -371,13 +371,13 @@ Type *check_type(Checker *c, AstNode *expression, Type *named_type) {
case AstNode_ProcedureType: {
type = alloc_type(c->allocator, Type_Procedure);
set_base_type(named_type, type);
- check_procedure_type(c, type, expression);
+ check_procedure_type(c, type, e);
goto end;
} break;
default:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` is not a type", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` is not a type", err_str);
break;
}
@@ -386,113 +386,117 @@ Type *check_type(Checker *c, AstNode *expression, Type *named_type) {
end:
GB_ASSERT(is_type_typed(type));
- add_type_and_value(c, expression, Addressing_Type, type, null_value);
+ add_type_and_value(c, e, Addressing_Type, type, null_value);
return type;
}
-b32 check_unary_op(Checker *c, Operand *operand, Token op) {
+b32 check_unary_op(Checker *c, Operand *o, Token op) {
// TODO(bill): Handle errors correctly
gbString str = NULL;
defer (gb_string_free(str));
switch (op.kind) {
case Token_Add:
case Token_Sub:
- if (!is_type_numeric(operand->type)) {
- str = expression_to_string(operand->expression);
- print_checker_error(c, op, "Operator `%.*s` is not allowed with `%s`", LIT(op.string), str);
+ if (!is_type_numeric(o->type)) {
+ str = expression_to_string(o->expression);
+ checker_err(c, op, "Operator `%.*s` is not allowed with `%s`", LIT(op.string), str);
}
break;
case Token_Xor:
- if (!is_type_integer(operand->type)) {
- print_checker_error(c, op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
+ if (!is_type_integer(o->type)) {
+ checker_err(c, op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
}
break;
case Token_Not:
- if (!is_type_boolean(operand->type)) {
- str = expression_to_string(operand->expression);
- print_checker_error(c, op, "Operator `%.*s` is only allowed on boolean expression", LIT(op.string));
+ if (!is_type_boolean(o->type)) {
+ str = expression_to_string(o->expression);
+ checker_err(c, op, "Operator `%.*s` is only allowed on boolean expression", LIT(op.string));
}
break;
default:
- print_checker_error(c, op, "Unknown operator `%.*s`", LIT(op.string));
+ checker_err(c, op, "Unknown operator `%.*s`", LIT(op.string));
return false;
}
return true;
}
-b32 check_binary_op(Checker *c, Operand *operand, Token op) {
+b32 check_binary_op(Checker *c, Operand *o, Token op) {
// TODO(bill): Handle errors correctly
switch (op.kind) {
case Token_Add:
case Token_Sub:
case Token_Mul:
case Token_Quo:
- if (!is_type_numeric(operand->type)) {
- print_checker_error(c, op, "Operator `%.*s` is only allowed with numeric expressions", LIT(op.string));
+
+ case Token_AddEq:
+ case Token_SubEq:
+ case Token_MulEq:
+ case Token_QuoEq:
+ if (!is_type_numeric(o->type)) {
+ checker_err(c, op, "Operator `%.*s` is only allowed with numeric expressions", LIT(op.string));
+ return false;
}
break;
case Token_Mod:
+ case Token_And:
case Token_Or:
case Token_Xor:
case Token_AndNot:
- if (!is_type_integer(operand->type)) {
- print_checker_error(c, op, "Operand `%.*s` is only allowed with integers", LIT(op.string));
- }
- break;
-
- case Token_CmpAnd:
- case Token_CmpOr:
- if (!is_type_boolean(operand->type)) {
- print_checker_error(c, op, "Operator `%.*s` is only allowed with boolean expressions", LIT(op.string));
- }
- break;
- case Token_AddEq:
- case Token_SubEq:
- case Token_MulEq:
- case Token_QuoEq:
case Token_ModEq:
case Token_AndEq:
case Token_OrEq:
case Token_XorEq:
case Token_AndNotEq:
+ if (!is_type_integer(o->type)) {
+ checker_err(c, op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
+ return false;
+ }
+ break;
+
+ case Token_CmpAnd:
+ case Token_CmpOr:
+
case Token_CmpAndEq:
case Token_CmpOrEq:
- // TODO(bill): is this okay?
- return true;
-
+ if (!is_type_boolean(o->type)) {
+ checker_err(c, op, "Operator `%.*s` is only allowed with boolean expressions", LIT(op.string));
+ return false;
+ }
+ break;
default:
- print_checker_error(c, op, "Unknown operator `%.*s`", LIT(op.string));
+ checker_err(c, op, "Unknown operator `%.*s`", LIT(op.string));
return false;
}
return true;
}
-b32 check_value_is_expressible(Checker *c, Value in_value, Type *type, Value *out_value) {
- if (in_value.kind == Value_Invalid)
+b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value) {
+ if (in_value.kind == ExactValue_Invalid)
return true;
if (is_type_boolean(type)) {
- return in_value.kind == Value_Bool;
+ return in_value.kind == ExactValue_Bool;
} else if (is_type_string(type)) {
- return in_value.kind == Value_String;
+ return in_value.kind == ExactValue_String;
} else if (is_type_integer(type)) {
- if (in_value.kind != Value_Integer)
+ if (in_value.kind != ExactValue_Integer)
return false;
if (out_value) *out_value = in_value;
i64 i = in_value.value_integer;
i64 s = 8*type_size_of(c->sizes, c->allocator, type);
u64 umax = ~0ull;
- if (s < 64)
+ if (s < 64) {
umax = (1ull << s) - 1ull;
+ }
i64 imax = (1ll << (s-1ll));
@@ -517,8 +521,8 @@ b32 check_value_is_expressible(Checker *c, Value in_value, Type *type, Value *ou
default: GB_PANIC("Compiler error: Unknown integer type!"); break;
}
} else if (is_type_float(type)) {
- Value v = value_to_float(in_value);
- if (v.kind != Value_Float)
+ ExactValue v = exact_value_to_float(in_value);
+ if (v.kind != ExactValue_Float)
return false;
switch (type->basic.kind) {
@@ -534,9 +538,9 @@ b32 check_value_is_expressible(Checker *c, Value in_value, Type *type, Value *ou
return true;
}
} else if (is_type_pointer(type)) {
- if (in_value.kind == Value_Pointer)
+ if (in_value.kind == ExactValue_Pointer)
return true;
- if (in_value.kind == Value_Integer)
+ if (in_value.kind == ExactValue_Integer)
return true;
if (out_value) *out_value = in_value;
}
@@ -544,65 +548,65 @@ b32 check_value_is_expressible(Checker *c, Value in_value, Type *type, Value *ou
return false;
}
-void check_is_expressible(Checker *c, Operand *operand, Type *type) {
+void check_is_expressible(Checker *c, Operand *o, Type *type) {
GB_ASSERT(type->kind == Type_Basic);
- GB_ASSERT(operand->mode == Addressing_Constant);
- if (!check_value_is_expressible(c, operand->value, type, &operand->value)) {
- gbString a = type_to_string(operand->type);
+ GB_ASSERT(o->mode == Addressing_Constant);
+ if (!check_value_is_expressible(c, o->value, type, &o->value)) {
+ gbString a = type_to_string(o->type);
gbString b = type_to_string(type);
defer (gb_string_free(a));
defer (gb_string_free(b));
- if (is_type_numeric(operand->type) && is_type_numeric(type)) {
- if (!is_type_integer(operand->type) && is_type_integer(type)) {
- print_checker_error(c, ast_node_token(operand->expression), "`%s` truncated to `%s`", a, b);
+ if (is_type_numeric(o->type) && is_type_numeric(type)) {
+ if (!is_type_integer(o->type) && is_type_integer(type)) {
+ checker_err(c, ast_node_token(o->expression), "`%s` truncated to `%s`", a, b);
} else {
- print_checker_error(c, ast_node_token(operand->expression), "`%s` overflows to `%s`", a, b);
+ checker_err(c, ast_node_token(o->expression), "`%s` overflows to `%s`", a, b);
}
} else {
- print_checker_error(c, ast_node_token(operand->expression), "Cannot convert `%s` to `%s`", a, b);
+ checker_err(c, ast_node_token(o->expression), "Cannot convert `%s` to `%s`", a, b);
}
- operand->mode = Addressing_Invalid;
+ o->mode = Addressing_Invalid;
}
}
-void check_unary_expression(Checker *c, Operand *operand, Token op, AstNode *node) {
+void check_unary_expression(Checker *c, Operand *o, Token op, AstNode *node) {
if (op.kind == Token_Pointer) { // Pointer address
- if (operand->mode != Addressing_Variable) {
+ if (o->mode != Addressing_Variable) {
gbString str = expression_to_string(node->unary_expression.operand);
defer (gb_string_free(str));
- print_checker_error(c, op, "Cannot take the pointer address of `%s`", str);
- operand->mode = Addressing_Invalid;
+ checker_err(c, op, "Cannot take the pointer address of `%s`", str);
+ o->mode = Addressing_Invalid;
return;
}
- operand->mode = Addressing_Value;
- operand->type = make_type_pointer(c->allocator, operand->type);
+ o->mode = Addressing_Value;
+ o->type = make_type_pointer(c->allocator, o->type);
return;
}
- if (!check_unary_op(c, operand, op)) {
- operand->mode = Addressing_Invalid;
+ if (!check_unary_op(c, o, op)) {
+ o->mode = Addressing_Invalid;
return;
}
- if (operand->mode == Addressing_Constant) {
- Type *type = get_base_type(operand->type);
+ if (o->mode == Addressing_Constant) {
+ Type *type = get_base_type(o->type);
GB_ASSERT(type->kind == Type_Basic);
i32 precision = 0;
if (is_type_unsigned(type))
precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
- operand->value = unary_operator_value(op, operand->value, precision);
+ o->value = exact_unary_operator_value(op, o->value, precision);
if (is_type_typed(type)) {
if (node != NULL)
- operand->expression = node;
- check_is_expressible(c, operand, type);
+ o->expression = node;
+ check_is_expressible(c, o, type);
}
return;
}
- operand->mode = Addressing_Value;
+ o->mode = Addressing_Value;
}
void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
@@ -641,13 +645,13 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
}
if (err_str) {
- print_checker_error(c, op, "Cannot compare expression, %s", err_str);
+ checker_err(c, op, "Cannot compare expression, %s", err_str);
return;
}
if (x->mode == Addressing_Constant &&
y->mode == Addressing_Constant) {
- x->value = make_value_bool(compare_values(op, x->value, y->value));
+ x->value = make_exact_value_bool(compare_exact_values(op, x->value, y->value));
} else {
// TODO(bill): What should I do?
}
@@ -657,42 +661,42 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
void check_binary_expression(Checker *c, Operand *x, AstNode *node) {
GB_ASSERT(node->kind == AstNode_BinaryExpression);
- Operand y = {};
+ Operand y_ = {}, *y = &y_;
gbString err_str = NULL;
defer (gb_string_free(err_str));
check_expression(c, x, node->binary_expression.left);
- check_expression(c, &y, node->binary_expression.right);
+ check_expression(c, y, node->binary_expression.right);
if (x->mode == Addressing_Invalid) return;
- if (y.mode == Addressing_Invalid) {
+ if (y->mode == Addressing_Invalid) {
x->mode = Addressing_Invalid;
- x->expression = y.expression;
+ x->expression = y->expression;
return;
}
- convert_to_typed(c, x, y.type);
+ convert_to_typed(c, x, y->type);
if (x->mode == Addressing_Invalid) return;
- convert_to_typed(c, &y, x->type);
- if (y.mode == Addressing_Invalid) {
+ convert_to_typed(c, y, x->type);
+ if (y->mode == Addressing_Invalid) {
x->mode = Addressing_Invalid;
return;
}
Token op = node->binary_expression.op;
if (token_is_comparison(op)) {
- check_comparison(c, x, &y, op);
+ check_comparison(c, x, y, op);
return;
}
- if (!are_types_identical(x->type, y.type)) {
+ if (!are_types_identical(x->type, y->type)) {
if (x->type != &basic_types[Basic_Invalid] &&
- y.type != &basic_types[Basic_Invalid]) {
+ y->type != &basic_types[Basic_Invalid]) {
gbString xt = type_to_string(x->type);
- gbString yt = type_to_string(y.type);
+ gbString yt = type_to_string(y->type);
defer (gb_string_free(xt));
defer (gb_string_free(yt));
err_str = expression_to_string(x->expression);
- print_checker_error(c, op, "Mismatched types in binary expression `%s` : `%s` vs `%s`", err_str, xt, yt);
+ checker_err(c, op, "Mismatched types in binary expression `%s` : `%s` vs `%s`", err_str, xt, yt);
}
x->mode = Addressing_Invalid;
return;
@@ -703,40 +707,44 @@ void check_binary_expression(Checker *c, Operand *x, AstNode *node) {
return;
}
- if ((op.kind == Token_Quo || op.kind == Token_Mod) &&
- (x->mode == Addressing_Constant || is_type_integer(x->type)) &&
- y.mode == Addressing_Constant) {
- b32 fail = false;
- switch (y.value.kind) {
- case Value_Integer:
- if (y.value.value_integer == 0)
- fail = true;
- break;
- case Value_Float:
- if (y.value.value_float == 0.0)
- fail = true;
- break;
- }
+ switch (op.kind) {
+ case Token_Quo:
+ case Token_Mod:
+ case Token_QuoEq:
+ case Token_ModEq:
+ if ((x->mode == Addressing_Constant || is_type_integer(x->type)) &&
+ y->mode == Addressing_Constant) {
+ b32 fail = false;
+ switch (y->value.kind) {
+ case ExactValue_Integer:
+ if (y->value.value_integer == 0)
+ fail = true;
+ break;
+ case ExactValue_Float:
+ if (y->value.value_float == 0.0)
+ fail = true;
+ break;
+ }
- if (fail) {
- print_checker_error(c, ast_node_token(y.expression),
- "Division by zero not allowed");
- x->mode = Addressing_Invalid;
- return;
+ if (fail) {
+ checker_err(c, ast_node_token(y->expression), "Division by zero not allowed");
+ x->mode = Addressing_Invalid;
+ return;
+ }
}
}
if (x->mode == Addressing_Constant &&
- y.mode == Addressing_Constant) {
- Value a = x->value;
- Value b = y.value;
+ y->mode == Addressing_Constant) {
+ ExactValue a = x->value;
+ ExactValue b = y->value;
Type *type = get_base_type(x->type);
GB_ASSERT(type->kind == Type_Basic);
if (op.kind == Token_Quo && is_type_integer(type)) {
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
}
- x->value = binary_operator_value(op, a, b);
+ x->value = exact_binary_operator_value(op, a, b);
if (is_type_typed(type)) {
if (node != NULL)
x->expression = node;
@@ -749,36 +757,36 @@ void check_binary_expression(Checker *c, Operand *x, AstNode *node) {
}
-void update_expression_type(Checker *c, AstNode *expression, Type *type, b32 final) {
- ExpressionInfo *found = map_get(&c->untyped, hash_pointer(expression));
+void update_expression_type(Checker *c, AstNode *e, Type *type) {
+ ExpressionInfo *found = map_get(&c->untyped, hash_pointer(e));
if (!found)
return;
- switch (expression->kind) {
+ switch (e->kind) {
case AstNode_UnaryExpression:
- if (found->value.kind != Value_Invalid)
+ if (found->value.kind != ExactValue_Invalid)
break;
- update_expression_type(c, expression->unary_expression.operand, type, final);
+ update_expression_type(c, e->unary_expression.operand, type);
break;
case AstNode_BinaryExpression:
- if (found->value.kind != Value_Invalid)
+ if (found->value.kind != ExactValue_Invalid)
break;
- if (!token_is_comparison(expression->binary_expression.op)) {
- update_expression_type(c, expression->binary_expression.left, type, final);
- update_expression_type(c, expression->binary_expression.right, type, final);
+ if (!token_is_comparison(e->binary_expression.op)) {
+ update_expression_type(c, e->binary_expression.left, type);
+ update_expression_type(c, e->binary_expression.right, type);
}
}
- if (!final && is_type_untyped(type)) {
+ if (is_type_untyped(type)) {
found->type = get_base_type(type);
} else {
found->type = type;
}
}
-void update_expression_value(Checker *c, AstNode *expression, Value value) {
- ExpressionInfo *found = map_get(&c->untyped, hash_pointer(expression));
+void update_expression_value(Checker *c, AstNode *e, ExactValue value) {
+ ExpressionInfo *found = map_get(&c->untyped, hash_pointer(e));
if (found)
found->value = value;
}
@@ -796,7 +804,7 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) {
extra_text = " - Did you want `null`?";
}
}
- print_checker_error(c, ast_node_token(operand->expression), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text);
+ checker_err(c, ast_node_token(operand->expression), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text);
operand->mode = Addressing_Invalid;
}
@@ -815,7 +823,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
if (is_type_numeric(x) && is_type_numeric(y)) {
if (x < y) {
operand->type = target_type;
- update_expression_type(c, operand->expression, target_type, false);
+ update_expression_type(c, operand->expression, target_type);
}
} else if (x != y) {
convert_untyped_error(c, operand, target_type);
@@ -887,8 +895,8 @@ b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *valu
if (!is_type_integer(operand.type)) {
gbString expr_str = expression_to_string(operand.expression);
- print_checker_error(c, ast_node_token(operand.expression),
- "Index `%s` must be an integer", expr_str);
+ checker_err(c, ast_node_token(operand.expression),
+ "Index `%s` must be an integer", expr_str);
gb_string_free(expr_str);
if (value) *value = 0;
return false;
@@ -896,11 +904,11 @@ b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *valu
if (operand.mode == Addressing_Constant) {
if (max_count >= 0) { // NOTE(bill): Do array bound checking
- i64 i = value_to_integer(operand.value).value_integer;
+ i64 i = exact_value_to_integer(operand.value).value_integer;
if (i < 0) {
gbString expr_str = expression_to_string(operand.expression);
- print_checker_error(c, ast_node_token(operand.expression),
- "Index `%s` cannot be a negative value", expr_str);
+ checker_err(c, ast_node_token(operand.expression),
+ "Index `%s` cannot be a negative value", expr_str);
gb_string_free(expr_str);
if (value) *value = 0;
return false;
@@ -910,8 +918,8 @@ b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *valu
if (i >= max_count) {
gbString expr_str = expression_to_string(operand.expression);
- print_checker_error(c, ast_node_token(operand.expression),
- "Index `%s` is out of bounds range [0, %lld)", expr_str, max_count);
+ checker_err(c, ast_node_token(operand.expression),
+ "Index `%s` is out of bounds range [0, %lld)", expr_str, max_count);
gb_string_free(expr_str);
return false;
}
@@ -964,8 +972,7 @@ void check_selector(Checker *c, Operand *operand, AstNode *node) {
gbString sel_str = expression_to_string(selector);
defer (gb_string_free(op_str));
defer (gb_string_free(sel_str));
- print_checker_error(c, ast_node_token(op_expr), "`%s` has no field `%s`",
- op_str, sel_str);
+ checker_err(c, ast_node_token(op_expr), "`%s` has no field `%s`", op_str, sel_str);
operand->mode = Addressing_Invalid;
operand->expression = node;
return;
@@ -994,9 +1001,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
if (ce->arg_list_count > bp->arg_count && !bp->variadic)
err = "Too many";
if (err) {
- print_checker_error(c, ce->close, "`%s` arguments for `%.*s`, expected %td, got %td",
- err, LIT(call->call_expression.proc->identifier.token.string),
- bp->arg_count, ce->arg_list_count);
+ checker_err(c, ce->close, "`%s` arguments for `%.*s`, expected %td, got %td",
+ err, LIT(call->call_expression.proc->identifier.token.string),
+ bp->arg_count, ce->arg_list_count);
return false;
}
}
@@ -1016,12 +1023,12 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
// size_of :: proc(Type)
Type *type = check_type(c, ce->arg_list);
if (!type) {
- print_checker_error(c, ast_node_token(ce->arg_list), "Expected a type for `size_of`");
+ checker_err(c, ast_node_token(ce->arg_list), "Expected a type for `size_of`");
return false;
}
operand->mode = Addressing_Constant;
- operand->value = make_value_integer(type_size_of(c->sizes, c->allocator, type));
+ operand->value = make_exact_value_integer(type_size_of(c->sizes, c->allocator, type));
operand->type = &basic_types[Basic_int];
} break;
@@ -1033,7 +1040,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
return false;
operand->mode = Addressing_Constant;
- operand->value = make_value_integer(type_size_of(c->sizes, c->allocator, operand->type));
+ operand->value = make_exact_value_integer(type_size_of(c->sizes, c->allocator, operand->type));
operand->type = &basic_types[Basic_int];
break;
@@ -1041,11 +1048,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
// align_of :: proc(Type)
Type *type = check_type(c, ce->arg_list);
if (!type) {
- print_checker_error(c, ast_node_token(ce->arg_list), "Expected a type for `align_of`");
+ checker_err(c, ast_node_token(ce->arg_list), "Expected a type for `align_of`");
return false;
}
operand->mode = Addressing_Constant;
- operand->value = make_value_integer(type_align_of(c->sizes, c->allocator, type));
+ operand->value = make_exact_value_integer(type_align_of(c->sizes, c->allocator, type));
operand->type = &basic_types[Basic_int];
} break;
@@ -1056,7 +1063,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
return false;
operand->mode = Addressing_Constant;
- operand->value = make_value_integer(type_align_of(c->sizes, c->allocator, operand->type));
+ operand->value = make_exact_value_integer(type_align_of(c->sizes, c->allocator, operand->type));
operand->type = &basic_types[Basic_int];
break;
@@ -1066,12 +1073,12 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
AstNode *field_arg = unparen_expression(ce->arg_list->next);
if (type) {
if (type->kind != Type_Structure) {
- print_checker_error(c, ast_node_token(ce->arg_list), "Expected a structure type for `offset_of`");
+ checker_err(c, ast_node_token(ce->arg_list), "Expected a structure type for `offset_of`");
return false;
}
if (field_arg == NULL ||
field_arg->kind != AstNode_Identifier) {
- print_checker_error(c, ast_node_token(field_arg), "Expected an identifier for field argument");
+ checker_err(c, ast_node_token(field_arg), "Expected an identifier for field argument");
return false;
}
}
@@ -1080,13 +1087,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
Entity *entity = lookup_field(type, field_arg, &index);
if (entity == NULL) {
gbString type_str = type_to_string(type);
- print_checker_error(c, ast_node_token(ce->arg_list),
+ checker_err(c, ast_node_token(ce->arg_list),
"`%s` has no field named `%.*s`", type_str, LIT(field_arg->identifier.token.string));
return false;
}
operand->mode = Addressing_Constant;
- operand->value = make_value_integer(type_offset_of(c->sizes, c->allocator, type, index));
+ operand->value = make_exact_value_integer(type_offset_of(c->sizes, c->allocator, type, index));
operand->type = &basic_types[Basic_int];
} break;
@@ -1095,7 +1102,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
AstNode *arg = unparen_expression(ce->arg_list);
if (arg->kind != AstNode_SelectorExpression) {
gbString str = expression_to_string(arg);
- print_checker_error(c, ast_node_token(arg), "`%s` is not a selector expression", str);
+ checker_err(c, ast_node_token(arg), "`%s` is not a selector expression", str);
return false;
}
auto *s = &arg->selector_expression;
@@ -1115,13 +1122,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
Entity *entity = lookup_field(type, s->selector, &index);
if (entity == NULL) {
gbString type_str = type_to_string(type);
- print_checker_error(c, ast_node_token(arg),
- "`%s` has no field named `%.*s`", type_str, LIT(s->selector->identifier.token.string));
+ checker_err(c, ast_node_token(arg),
+ "`%s` has no field named `%.*s`", type_str, LIT(s->selector->identifier.token.string));
return false;
}
operand->mode = Addressing_Constant;
- operand->value = make_value_integer(type_offset_of(c->sizes, c->allocator, type, index));
+ operand->value = make_exact_value_integer(type_offset_of(c->sizes, c->allocator, type, index));
operand->type = &basic_types[Basic_int];
} break;
@@ -1133,15 +1140,15 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
!is_type_boolean(operand->type)) {
gbString str = expression_to_string(ce->arg_list);
defer (gb_string_free(str));
- print_checker_error(c, ast_node_token(call),
- "`%s` is not a constant boolean", str);
+ checker_err(c, ast_node_token(call),
+ "`%s` is not a constant boolean", str);
return false;
}
if (!operand->value.value_bool) {
gbString str = expression_to_string(ce->arg_list);
defer (gb_string_free(str));
- print_checker_error(c, ast_node_token(call),
- "Static assertion: `%s`", str);
+ checker_err(c, ast_node_token(call),
+ "Static assertion: `%s`", str);
return true;
}
break;
@@ -1152,7 +1159,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
Type *t = get_base_type(operand->type);
AddressingMode mode = Addressing_Invalid;
- Value value = {};
+ ExactValue value = {};
switch (t->kind) {
case Type_Basic:
@@ -1160,7 +1167,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
if (is_type_string(t)) {
if (operand->mode == Addressing_Constant) {
mode = Addressing_Constant;
- value = make_value_integer(operand->value.value_string.len);
+ value = make_exact_value_integer(operand->value.value_string.len);
} else {
mode = Addressing_Value;
}
@@ -1170,7 +1177,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
case Type_Array:
mode = Addressing_Constant;
- value = make_value_integer(t->array.count);
+ value = make_exact_value_integer(t->array.count);
break;
case Type_Slice:
@@ -1180,9 +1187,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
if (mode == Addressing_Invalid) {
gbString str = expression_to_string(operand->expression);
- print_checker_error(c, ast_node_token(operand->expression),
- "Invalid expression `%s` for `%.*s`",
- str, LIT(bp->name));
+ checker_err(c, ast_node_token(operand->expression),
+ "Invalid expression `%s` for `%.*s`",
+ str, LIT(bp->name));
gb_string_free(str);
return false;
}
@@ -1211,7 +1218,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
src_type = s->slice.element;
if (dest_type == NULL || src_type == NULL) {
- print_checker_error(c, ast_node_token(call), "`copy` only expects slices as arguments");
+ checker_err(c, ast_node_token(call), "`copy` only expects slices as arguments");
return false;
}
@@ -1224,9 +1231,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
defer (gb_string_free(s_arg));
defer (gb_string_free(d_str));
defer (gb_string_free(s_str));
- print_checker_error(c, ast_node_token(call),
- "Arguments to `copy`, %s, %s, have different element types: %s vs %s",
- d_arg, s_arg, d_str, s_str);
+ checker_err(c, ast_node_token(call),
+ "Arguments to `copy`, %s, %s, have different element types: %s vs %s",
+ d_arg, s_arg, d_str, s_str);
return false;
}
@@ -1251,7 +1258,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
src_type = s;
if (dest_type == NULL || src_type == NULL) {
- print_checker_error(c, ast_node_token(call), "`copy_bytes` only expects pointers for the destintation and source");
+ checker_err(c, ast_node_token(call), "`copy_bytes` only expects pointers for the destintation and source");
return false;
}
@@ -1265,13 +1272,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
op.type->basic.kind != Basic_int) {
gbString str = type_to_string(op.type);
defer (gb_string_free(str));
- print_checker_error(c, ast_node_token(call), "`copy_bytes` 3rd argument must be of type `int`, a `%s` was given", str);
+ checker_err(c, ast_node_token(call), "`copy_bytes` 3rd argument must be of type `int`, a `%s` was given", str);
return false;
}
if (op.mode == Addressing_Constant) {
- if (value_to_integer(op.value).value_integer <= 0) {
- print_checker_error(c, ast_node_token(call), "You cannot copy a zero or negative amount of bytes with `copy_bytes`");
+ if (exact_value_to_integer(op.value).value_integer <= 0) {
+ checker_err(c, ast_node_token(call), "You cannot copy a zero or negative amount of bytes with `copy_bytes`");
return false;
}
}
@@ -1364,7 +1371,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
}
gbString proc_str = expression_to_string(ce->proc);
- print_checker_error(c, ast_node_token(call), err_fmt, proc_str, param_count);
+ checker_err(c, ast_node_token(call), err_fmt, proc_str, param_count);
gb_string_free(proc_str);
operand->mode = Addressing_Invalid;
@@ -1398,8 +1405,7 @@ ExpressionKind check_call_expression(Checker *c, Operand *operand, AstNode *call
AstNode *e = operand->expression;
gbString str = expression_to_string(e);
defer (gb_string_free(str));
- print_checker_error(c, ast_node_token(e),
- "Cannot call a non-procedure: `%s`", str);
+ checker_err(c, ast_node_token(e), "Cannot call a non-procedure: `%s`", str);
operand->mode = Addressing_Invalid;
operand->expression = call;
@@ -1407,6 +1413,7 @@ ExpressionKind check_call_expression(Checker *c, Operand *operand, AstNode *call
return Expression_Statement;
}
+
check_call_arguments(c, operand, proc_type, call);
auto *proc = &proc_type->procedure;
@@ -1486,8 +1493,7 @@ void check_cast_expression(Checker *c, Operand *operand, Type *type) {
gbString type_str = type_to_string(type);
defer (gb_string_free(expr_str));
defer (gb_string_free(type_str));
- print_checker_error(c, ast_node_token(operand->expression),
- "Cannot cast `%s` to `%s`", expr_str, type_str);
+ checker_err(c, ast_node_token(operand->expression), "Cannot cast `%s` to `%s`", expr_str, type_str);
operand->mode = Addressing_Invalid;
return;
@@ -1498,18 +1504,18 @@ void check_cast_expression(Checker *c, Operand *operand, Type *type) {
-ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *node, Type *type_hint) {
+ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
ExpressionKind kind = Expression_Statement;
- operand->mode = Addressing_Invalid;
- operand->type = &basic_types[Basic_Invalid];
+ o->mode = Addressing_Invalid;
+ o->type = &basic_types[Basic_Invalid];
switch (node->kind) {
case AstNode_BadExpression:
goto error;
case AstNode_Identifier:
- check_identifier(c, operand, node, type_hint);
+ check_identifier(c, o, node, type_hint);
break;
case AstNode_BasicLiteral: {
BasicKind basic_kind = Basic_Invalid;
@@ -1521,97 +1527,95 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *node
case Token_Rune: basic_kind = Basic_UntypedRune; break;
default: GB_PANIC("Unknown literal"); break;
}
- operand->mode = Addressing_Constant;
- operand->type = &basic_types[basic_kind];
- operand->value = make_value_from_basic_literal(lit);
+ o->mode = Addressing_Constant;
+ o->type = &basic_types[basic_kind];
+ o->value = make_exact_value_from_basic_literal(lit);
} break;
case AstNode_ParenExpression:
- kind = check_expression_base(c, operand, node->paren_expression.expression, type_hint);
- operand->expression = node;
+ kind = check_expression_base(c, o, node->paren_expression.expression, type_hint);
+ o->expression = node;
break;
case AstNode_TagExpression:
// TODO(bill): Tag expressions
- print_checker_error(c, ast_node_token(node), "Tag expressions are not supported yet");
- kind = check_expression_base(c, operand, node->tag_expression.expression, type_hint);
- operand->expression = node;
+ checker_err(c, ast_node_token(node), "Tag expressions are not supported yet");
+ kind = check_expression_base(c, o, node->tag_expression.expression, type_hint);
+ o->expression = node;
break;
case AstNode_UnaryExpression:
- check_expression(c, operand, node->unary_expression.operand);
- if (operand->mode == Addressing_Invalid)
+ check_expression(c, o, node->unary_expression.operand);
+ if (o->mode == Addressing_Invalid)
goto error;
- check_unary_expression(c, operand, node->unary_expression.op, node);
- if (operand->mode == Addressing_Invalid)
+ check_unary_expression(c, o, node->unary_expression.op, node);
+ if (o->mode == Addressing_Invalid)
goto error;
break;
case AstNode_BinaryExpression:
- check_binary_expression(c, operand, node);
- if (operand->mode == Addressing_Invalid)
+ check_binary_expression(c, o, node);
+ if (o->mode == Addressing_Invalid)
goto error;
break;
case AstNode_SelectorExpression:
- check_expression_base(c, operand, node->selector_expression.operand);
- check_selector(c, operand, node);
+ check_expression_base(c, o, node->selector_expression.operand);
+ check_selector(c, o, node);
break;
case AstNode_IndexExpression: {
- check_expression(c, operand, node->index_expression.expression);
- if (operand->mode == Addressing_Invalid)
+ check_expression(c, o, node->index_expression.expression);
+ if (o->mode == Addressing_Invalid)
goto error;
b32 valid = false;
i64 max_count = -1;
- Type *t = get_base_type(operand->type);
+ Type *t = get_base_type(o->type);
switch (t->kind) {
case Type_Basic:
if (is_type_string(t)) {
valid = true;
- if (operand->mode == Addressing_Constant) {
- max_count = operand->value.value_string.len;
+ if (o->mode == Addressing_Constant) {
+ max_count = o->value.value_string.len;
}
- operand->mode = Addressing_Value;
- operand->type = &basic_types[Basic_u8];
+ o->mode = Addressing_Value;
+ o->type = &basic_types[Basic_u8];
}
break;
case Type_Array:
valid = true;
max_count = t->array.count;
- if (operand->mode != Addressing_Variable)
- operand->mode = Addressing_Value;
- operand->type = t->array.element;
+ if (o->mode != Addressing_Variable)
+ o->mode = Addressing_Value;
+ o->type = t->array.element;
break;
case Type_Slice:
valid = true;
- operand->type = t->slice.element;
- operand->mode = Addressing_Variable;
+ o->type = t->slice.element;
+ o->mode = Addressing_Variable;
break;
case Type_Pointer:
valid = true;
- operand->mode = Addressing_Variable;
- operand->type = get_base_type(t->pointer.element);
+ o->mode = Addressing_Variable;
+ o->type = get_base_type(t->pointer.element);
break;
}
if (!valid) {
- gbString str = expression_to_string(operand->expression);
- print_checker_error(c, ast_node_token(operand->expression),
- "Cannot index `%s`", str);
+ gbString str = expression_to_string(o->expression);
+ checker_err(c, ast_node_token(o->expression), "Cannot index `%s`", str);
gb_string_free(str);
goto error;
}
if (node->index_expression.value == NULL) {
- gbString str = expression_to_string(operand->expression);
- print_checker_error(c, ast_node_token(operand->expression),
- "Missing index for `%s`", str);
+ gbString str = expression_to_string(o->expression);
+ checker_err(c, ast_node_token(o->expression), "Missing index for `%s`", str);
gb_string_free(str);
goto error;
}
@@ -1622,53 +1626,52 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *node
case AstNode_SliceExpression: {
auto *se = &node->slice_expression;
- check_expression(c, operand, se->expression);
- if (operand->mode == Addressing_Invalid)
+ check_expression(c, o, se->expression);
+ if (o->mode == Addressing_Invalid)
goto error;
b32 valid = false;
i64 max_count = -1;
- Type *t = get_base_type(operand->type);
+ Type *t = get_base_type(o->type);
switch (t->kind) {
case Type_Basic:
if (is_type_string(t)) {
valid = true;
- if (operand->mode == Addressing_Constant) {
- max_count = operand->value.value_string.len;
+ if (o->mode == Addressing_Constant) {
+ max_count = o->value.value_string.len;
}
- operand->mode = Addressing_Value;
+ o->mode = Addressing_Value;
}
break;
case Type_Array:
valid = true;
max_count = t->array.count;
- if (operand->mode != Addressing_Variable) {
+ if (o->mode != Addressing_Variable) {
gbString str = expression_to_string(node);
- print_checker_error(c, ast_node_token(node), "Cannot slice array `%s`, value is not addressable", str);
+ checker_err(c, ast_node_token(node), "Cannot slice array `%s`, value is not addressable", str);
gb_string_free(str);
goto error;
}
- operand->type = make_type_slice(c->allocator, t->array.element);
- operand->mode = Addressing_Value;
+ o->type = make_type_slice(c->allocator, t->array.element);
+ o->mode = Addressing_Value;
break;
case Type_Slice:
valid = true;
- operand->mode = Addressing_Value;
+ o->mode = Addressing_Value;
break;
case Type_Pointer:
valid = true;
- operand->type = make_type_slice(c->allocator, get_base_type(t->pointer.element));
- operand->mode = Addressing_Value;
+ o->type = make_type_slice(c->allocator, get_base_type(t->pointer.element));
+ o->mode = Addressing_Value;
break;
}
if (!valid) {
- gbString str = expression_to_string(operand->expression);
- print_checker_error(c, ast_node_token(operand->expression),
- "Cannot slice `%s`", str);
+ gbString str = expression_to_string(o->expression);
+ checker_err(c, ast_node_token(o->expression), "Cannot slice `%s`", str);
gb_string_free(str);
goto error;
}
@@ -1696,7 +1699,7 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *node
for (isize j = i+1; j < gb_count_of(indices); j++) {
i64 b = indices[j];
if (a > b && b >= 0) {
- print_checker_error(c, se->close, "Invalid slice indices: [%td > %td]", a, b);
+ checker_err(c, se->close, "Invalid slice indices: [%td > %td]", a, b);
}
}
}
@@ -1705,28 +1708,27 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *node
case AstNode_CastExpression: {
Type *cast_type = check_type(c, node->cast_expression.type_expression);
- check_expression_or_type(c, operand, node->cast_expression.operand);
- if (operand->mode != Addressing_Invalid)
- check_cast_expression(c, operand, cast_type);
+ check_expression_or_type(c, o, node->cast_expression.operand);
+ if (o->mode != Addressing_Invalid)
+ check_cast_expression(c, o, cast_type);
} break;
case AstNode_CallExpression:
- return check_call_expression(c, operand, node);
+ return check_call_expression(c, o, node);
case AstNode_DereferenceExpression:
- check_expression_or_type(c, operand, node->dereference_expression.operand);
- if (operand->mode == Addressing_Invalid) {
+ check_expression_or_type(c, o, node->dereference_expression.operand);
+ if (o->mode == Addressing_Invalid) {
goto error;
} else {
- Type *t = get_base_type(operand->type);
+ Type *t = get_base_type(o->type);
if (t->kind == Type_Pointer) {
- operand->mode = Addressing_Variable;
- operand->type = t->pointer.element;
+ o->mode = Addressing_Variable;
+ o->type = t->pointer.element;
} else {
- gbString str = expression_to_string(operand->expression);
- print_checker_error(c, ast_node_token(operand->expression),
- "Cannot dereference `%s`", str);
+ gbString str = expression_to_string(o->expression);
+ checker_err(c, ast_node_token(o->expression), "Cannot dereference `%s`", str);
gb_string_free(str);
goto error;
}
@@ -1737,24 +1739,26 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *node
case AstNode_PointerType:
case AstNode_ArrayType:
case AstNode_StructType:
- operand->mode = Addressing_Type;
- operand->type = check_type(c, node);
+ o->mode = Addressing_Type;
+ o->type = check_type(c, node);
break;
}
kind = Expression_Expression;
- operand->expression = node;
- goto after_error;
+ o->expression = node;
+ return kind;
error:
- operand->mode = Addressing_Invalid;
- operand->expression = node;
- goto after_error;
+ o->mode = Addressing_Invalid;
+ o->expression = node;
+ return kind;
+}
-after_error:
+ExpressionKind check_expression_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
+ ExpressionKind kind = check__expression_base(c, o, node, type_hint);
Type *type = NULL;
- Value value = {Value_Invalid};
- switch (operand->mode) {
+ ExactValue value = {ExactValue_Invalid};
+ switch (o->mode) {
case Addressing_Invalid:
type = &basic_types[Basic_Invalid];
break;
@@ -1762,76 +1766,76 @@ after_error:
type = NULL;
break;
case Addressing_Constant:
- type = operand->type;
- value = operand->value;
+ type = o->type;
+ value = o->value;
break;
default:
- type = operand->type;
+ type = o->type;
break;
}
- if (type) {
+ if (type != NULL) {
if (is_type_untyped(type)) {
- add_untyped(c, node, false, operand->mode, type, value);
+ add_untyped(c, node, false, o->mode, type, value);
} else {
- add_type_and_value(c, node, operand->mode, type, value);
+ add_type_and_value(c, node, o->mode, type, value);
}
}
return kind;
}
-void check_multi_expression(Checker *c, Operand *operand, AstNode *expression) {
+
+void check_multi_expression(Checker *c, Operand *o, AstNode *e) {
gbString err_str = NULL;
defer (gb_string_free(err_str));
- check_expression_base(c, operand, expression);
- switch (operand->mode) {
+ check_expression_base(c, o, e);
+ switch (o->mode) {
default:
return; // NOTE(bill): Valid
case Addressing_NoValue:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` used as value", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` used as value", err_str);
break;
case Addressing_Type:
- err_str = expression_to_string(expression);
- print_checker_error(c, ast_node_token(expression), "`%s` is not an expression", err_str);
+ err_str = expression_to_string(e);
+ checker_err(c, ast_node_token(e), "`%s` is not an expression", err_str);
break;
}
- operand->mode = Addressing_Invalid;
+ o->mode = Addressing_Invalid;
}
-// NOTE(bill): Just a santity checker
-// TODO(bill): Remove this entirely
-void check_not_tuple(Checker *c, Operand *operand) {
- if (operand->mode == Addressing_Value) {
+// TODO(bill): Should I remove this entirely?
+void check_not_tuple(Checker *c, Operand *o) {
+ if (o->mode == Addressing_Value) {
// NOTE(bill): Tuples are not first class thus never named
- if (operand->type->kind == Type_Tuple) {
- isize count = operand->type->tuple.variable_count;
+ if (o->type->kind == Type_Tuple) {
+ isize count = o->type->tuple.variable_count;
GB_ASSERT(count != 1);
- print_checker_error(c, ast_node_token(operand->expression),
- gb_bprintf("%td-valued tuple found where single value expected", count));
- operand->mode = Addressing_Invalid;
+ checker_err(c, ast_node_token(o->expression),
+ "%td-valued tuple found where single value expected", count);
+ o->mode = Addressing_Invalid;
}
}
}
-void check_expression(Checker *c, Operand *operand, AstNode *expression) {
- check_multi_expression(c, operand, expression);
- check_not_tuple(c, operand);
+void check_expression(Checker *c, Operand *o, AstNode *e) {
+ check_multi_expression(c, o, e);
+ check_not_tuple(c, o);
}
-void check_expression_or_type(Checker *c, Operand *operand, AstNode *expression) {
- check_expression_base(c, operand, expression);
- check_not_tuple(c, operand);
- if (operand->mode == Addressing_NoValue) {
- AstNode *e = operand->expression;
+void check_expression_or_type(Checker *c, Operand *o, AstNode *e) {
+ check_expression_base(c, o, e);
+ check_not_tuple(c, o);
+ if (o->mode == Addressing_NoValue) {
+ AstNode *e = o->expression;
gbString str = expression_to_string(e);
defer (gb_string_free(str));
- print_checker_error(c, ast_node_token(e),
- "`%s` used as value or type", str);
- operand->mode = Addressing_Invalid;
+ checker_err(c, ast_node_token(e),
+ "`%s` used as value or type", str);
+ o->mode = Addressing_Invalid;
}
}