diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2025-11-26 15:04:55 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-26 15:04:55 +0000 |
| commit | f48e87d77d1376f03cf53afbc51b695698d6e5a7 (patch) | |
| tree | 01688dc28a690a16a2f5bf8d18236b65cf655021 /src | |
| parent | 5caaefddb1551670d6f4e58cb53e29fec6ae4ccf (diff) | |
| parent | e53bc165ae29d83e55645d1b7af356063ff0f2c9 (diff) | |
Merge pull request #5930 from odin-lang/bill/os2-file-stream
`os2.File_Stream`
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_builtin.cpp | 124 | ||||
| -rw-r--r-- | src/checker_builtin_procs.hpp | 2 |
2 files changed, 126 insertions, 0 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index b2d28afc0..1b3e6912c 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2485,6 +2485,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_min: case BuiltinProc_max: case BuiltinProc_type_is_subtype_of: + case BuiltinProc_type_is_superset_of: case BuiltinProc_objc_send: case BuiltinProc_objc_find_selector: case BuiltinProc_objc_find_class: @@ -7397,6 +7398,129 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->type = t_untyped_bool; } break; + case BuiltinProc_type_is_superset_of: + { + Operand op_super = {}; + Operand op_sub = {}; + + check_expr_or_type(c, &op_super, ce->args[0]); + if (op_super.mode != Addressing_Type) { + gbString e = expr_to_string(op_super.expr); + error(op_super.expr, "'%.*s' expects a type, got %s", LIT(builtin_name), e); + gb_string_free(e); + return false; + } + check_expr_or_type(c, &op_sub, ce->args[1]); + if (op_sub.mode != Addressing_Type) { + gbString e = expr_to_string(op_sub.expr); + error(op_sub.expr, "'%.*s' expects a type, got %s", LIT(builtin_name), e); + gb_string_free(e); + return false; + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; + + Type *super = op_super.type; + Type *sub = op_sub.type; + if (are_types_identical(super, sub)) { + operand->value = exact_value_bool(true); + return true; + } + + super = base_type(super); + sub = base_type(sub); + if (are_types_identical(super, sub)) { + operand->value = exact_value_bool(true); + return true; + } + + if (super->kind != sub->kind) { + gbString a = type_to_string(op_super.type); + gbString b = type_to_string(op_sub.type); + error(op_super.expr, "'%.*s' expects types of the same kind, got %s vs %s", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + + if (super->kind == Type_Enum) { + if (sub->Enum.fields.count > super->Enum.fields.count) { + operand->value = exact_value_bool(false); + return true; + } + + + Type *base_super = base_enum_type(super); + Type *base_sub = base_enum_type(sub); + if (base_super == base_sub && base_super == nullptr) { + // okay + } else if (!are_types_identical(base_type(base_super), base_type(base_sub))) { + operand->value = exact_value_bool(false); + return true; + } + + for (Entity *f_sub : sub->Enum.fields) { + bool found = false; + + if (f_sub->kind != Entity_Constant) { + continue; + } + + for (Entity *f_super : super->Enum.fields) { + if (f_super->kind != Entity_Constant) { + continue; + } + + if (f_sub->token.string == f_super->token.string) { + if (compare_exact_values(Token_CmpEq, f_sub->Constant.value, f_super->Constant.value)) { + found = true; + break; + } + } + } + + if (!found) { + operand->value = exact_value_bool(false); + return true; + } + } + + operand->value = exact_value_bool(true); + return true; + + } else if (super->kind == Type_Union) { + if (sub->Union.variants.count > super->Union.variants.count) { + operand->value = exact_value_bool(false); + return true; + } + if (sub->Union.kind != super->Union.kind) { + operand->value = exact_value_bool(false); + return true; + } + + for_array(i, sub->Union.variants) { + Type *t_sub = sub->Union.variants[i]; + Type *t_super = super->Union.variants[i]; + if (!are_types_identical(t_sub, t_super)) { + operand->value = exact_value_bool(false); + return true; + } + } + + operand->value = exact_value_bool(true); + return true; + + } + gbString a = type_to_string(op_super.type); + gbString b = type_to_string(op_sub.type); + error(op_super.expr, "'%.*s' expects types of the same kind and either an enum or union, got %s vs %s", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + + case BuiltinProc_type_field_index_of: { Operand op = {}; diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 663274cdc..5b446cc1c 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -336,6 +336,7 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_polymorphic_record_parameter_value, BuiltinProc_type_is_subtype_of, + BuiltinProc_type_is_superset_of, BuiltinProc_type_field_index_of, @@ -708,6 +709,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_polymorphic_record_parameter_value"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_subtype_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_superset_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics }, {STR_LIT("type_field_index_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, |