diff --git a/core/sort.odin b/core/sort.odin new file mode 100644 index 000000000..d81ee38dc --- /dev/null +++ b/core/sort.odin @@ -0,0 +1,209 @@ +bubble_sort :: proc(array: []$T, f: proc(T, T) -> int) { + assert(f != nil); + count := len(array); + + init_j, last_j := 0, count-1; + + for { + init_swap, prev_swap := -1, -1; + + for j in init_j.. 0 { + array[j], array[j+1] = array[j+1], array[j]; + prev_swap = j; + if init_swap == -1 do init_swap = j; + } + } + + if prev_swap == -1 do return; + + init_j = max(init_swap-1, 0); + last_j = prev_swap; + } +} + +bubble_sort :: proc(array: []$T) { + count := len(array); + + init_j, last_j := 0, count-1; + + for { + init_swap, prev_swap := -1, -1; + + for j in init_j.. array[j+1] { + array[j], array[j+1] = array[j+1], array[j]; + prev_swap = j; + if init_swap == -1 do init_swap = j; + } + } + + if prev_swap == -1 do return; + + init_j = max(init_swap-1, 0); + last_j = prev_swap; + } +} + +quick_sort :: proc(array: []$T, f: proc(T, T) -> int) { + assert(f != nil); + a := array; + n := len(a); + if n < 2 do return; + + p := a[n/2]; + i, j := 0, n-1; + + loop: for { + for f(a[i], p) < 0 do i += 1; + for f(p, a[j]) < 0 do j -= 1; + + if i >= j do break loop; + + a[i], a[j] = a[j], a[i]; + i += 1; + j -= 1; + } + + quick_sort(a[0..= j do break loop; + + a[i], a[j] = a[j], a[i]; + i += 1; + j -= 1; + } + + quick_sort(a[0.. int { + res := 0; + for ; n != 0; n >>= 1 do res++; + return res; +} + +merge_sort :: proc(array: []$T, f: proc(T, T) -> int) { + merge_slices :: proc(arr1, arr2, out: []$T, f: proc(T, T) -> int) { + N1, N2 := len(arr1), len(arr2); + i, j := 0, 0; + for k in 0.. m { + k := 2*a*m; + merge_slices(arr1[k..>= 1; + b = a << uint(i) << 2; + } + + if M & 1 == 0 do copy(arr2, arr1); +} + +merge_sort :: proc(array: []$T) { + merge_slices :: proc(arr1, arr2, out: []$T) { + N1, N2 := len(arr1), len(arr2); + i, j := 0, 0; + for k in 0.. m { + k := 2*a*m; + merge_slices(arr1[k..>= 1; + b = a << uint(i) << 2; + } + + if M & 1 == 0 do copy(arr2, arr1); +} + + + +compare_ints :: proc(a, b: int) -> int { + match delta := a - b; { + case delta < 0: return -1; + case delta > 0: return +1; + } + return 0; +} + +compare_f32s :: proc(a, b: f32) -> int { + match delta := a - b; { + case delta < 0: return -1; + case delta > 0: return +1; + } + return 0; +} +compare_f64s :: proc(a, b: f64) -> int { + match delta := a - b; { + case delta < 0: return -1; + case delta > 0: return +1; + } + return 0; +} +compare_strings :: proc(a, b: string) -> int { + return __string_cmp(a, b); +} diff --git a/src/check_expr.cpp b/src/check_expr.cpp index da3967805..e99706836 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -194,6 +194,8 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ DeclInfo *old_decl = decl_info_of_entity(&c->info, base_entity); GB_ASSERT(old_decl != nullptr); + + gbAllocator a = heap_allocator(); Array operands = {}; @@ -214,6 +216,8 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ }); + + CheckerContext prev_context = c->context; defer (c->context = prev_context); @@ -222,7 +226,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ c->context.scope = scope; c->context.allow_polymorphic_types = true; if (param_operands == nullptr) { - c->context.no_polymorphic_errors = false; + // c->context.no_polymorphic_errors = false; } bool generate_type_again = c->context.no_polymorphic_errors; @@ -233,6 +237,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ // Maybe it's better to check with the previous types first? Type *final_proc_type = make_type_proc(c->allocator, scope, nullptr, 0, nullptr, 0, false, pt->calling_convention); bool success = check_procedure_type(c, final_proc_type, pt->node, &operands); + if (!success) { return false; } @@ -252,6 +257,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ } } + if (generate_type_again) { // LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice @@ -350,6 +356,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ } bool check_polymorphic_procedure_assignment(Checker *c, Operand *operand, Type *type, PolyProcData *poly_proc_data) { + if (operand->expr == NULL) return false; Entity *base_entity = entity_of_ident(&c->info, operand->expr); if (base_entity == nullptr) return false; return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_proc_data, true); @@ -619,17 +626,24 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n // TODO(bill): is this a good enough error message? // TODO(bill): Actually allow built in procedures to be passed around and thus be created on use error(operand->expr, - "Cannot assign built-in procedure `%s` in %.*s", - expr_str, - LIT(context_name)); + "Cannot assign built-in procedure `%s` in %.*s", + expr_str, + LIT(context_name)); + } else if (operand->mode == Addressing_Type) { + // TODO(bill): is this a good enough error message? + // TODO(bill): Actually allow built in procedures to be passed around and thus be created on use + error(operand->expr, + "Cannot assign type `%s` as a value in %.*s", + op_type_str, + LIT(context_name)); } else { // TODO(bill): is this a good enough error message? error(operand->expr, - "Cannot assign value `%s` of type `%s` to `%s` in %.*s", - expr_str, - op_type_str, - type_str, - LIT(context_name)); + "Cannot assign value `%s` of type `%s` to `%s` in %.*s", + expr_str, + op_type_str, + type_str, + LIT(context_name)); } operand->mode = Addressing_Invalid; @@ -1376,6 +1390,7 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c case Type_Record: if (source->kind == Type_Record) { // TODO(bill): Polymorphic type assignment + // return check_is_assignable_to(c, &o, poly); } return false; case Type_Tuple: @@ -1383,8 +1398,9 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c return false; case Type_Proc: if (source->kind == Type_Proc) { + // return check_is_assignable_to(c, &o, poly); // TODO(bill): Polymorphic type assignment - #if 0 + #if 1 TypeProc *x = &poly->Proc; TypeProc *y = &source->Proc; if (x->calling_convention != y->calling_convention) { @@ -5837,10 +5853,10 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t CallArgumentError err = CallArgumentError_None; CallArgumentData data = {}; CheckerContext prev_context = c->context; + defer (c->context = prev_context); c->context.no_polymorphic_errors = true; c->context.allow_polymorphic_types = is_type_polymorphic(pt); err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data); - c->context = prev_context; if (err == CallArgumentError_None) { valids[valid_count].index = i;