aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-01-27 15:27:38 +0000
committergingerBill <bill@gingerbill.org>2021-01-27 15:27:38 +0000
commite64eb74eef40c4c79b493006feadce4499a8a9dd (patch)
tree72278b3f965d49d7029a0c5f591d250e83f03dfa /src/check_expr.cpp
parentc71c86f563cb79601b042571a01e6ea70cc25b2d (diff)
Fix #831
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 63b275c99..b001ed7a8 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1801,6 +1801,50 @@ void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) {
o->mode = Addressing_Value;
}
+void add_comparison_procedures_for_fields(CheckerContext *c, Type *t) {
+ if (t == nullptr) {
+ return;
+ }
+ t = base_type(t);
+ if (!is_type_comparable(t)) {
+ return;
+ }
+ switch (t->kind) {
+ case Type_Basic:
+ switch (t->Basic.kind) {
+ case Basic_complex64:
+ add_package_dependency(c, "runtime", "complex64_eq");
+ add_package_dependency(c, "runtime", "complex64_ne");
+ break;
+ case Basic_complex128:
+ add_package_dependency(c, "runtime", "complex128_eq");
+ add_package_dependency(c, "runtime", "complex128_ne");
+ break;
+ case Basic_quaternion128:
+ add_package_dependency(c, "runtime", "quaternion128_eq");
+ add_package_dependency(c, "runtime", "quaternion128_ne");
+ break;
+ case Basic_quaternion256:
+ add_package_dependency(c, "runtime", "quaternion256_eq");
+ add_package_dependency(c, "runtime", "quaternion256_ne");
+ break;
+ case Basic_cstring:
+ add_package_dependency(c, "runtime", "cstring_to_string");
+ /*fallthrough*/
+ case Basic_string:
+ add_package_dependency(c, "runtime", "string_eq");
+ add_package_dependency(c, "runtime", "string_ne");
+ break;
+ }
+ break;
+ case Type_Struct:
+ for_array(i, t->Struct.fields) {
+ add_comparison_procedures_for_fields(c, t->Struct.fields[i]->type);
+ }
+ break;
+ }
+}
+
void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
if (x->mode == Addressing_Type && y->mode == Addressing_Type) {
@@ -1867,6 +1911,13 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
defer (gb_string_free(type_string));
err_str = gb_string_make(temporary_allocator(),
gb_bprintf("operator '%.*s' not defined for type '%s'", LIT(token_strings[op]), type_string));
+ } else {
+ Type *comparison_type = x->type;
+ if (x->type == err_type && is_operand_nil(*x)) {
+ comparison_type = y->type;
+ }
+
+ add_comparison_procedures_for_fields(c, comparison_type);
}
} else {
gbString xt, yt;