diff --git a/lib/std/time/clock.c3 b/lib/std/time/clock.c3 index e247f2a53..6cb40d161 100644 --- a/lib/std/time/clock.c3 +++ b/lib/std/time/clock.c3 @@ -13,22 +13,27 @@ fn Clock now() fn NanoDuration Clock.mark(&self) { Clock mark = now(); - NanoDuration diff = (NanoDuration)(mark - *self); + NanoDuration diff = mark - *self; *self = mark; return diff; } -fn Clock Clock.add_nano_duration(self, NanoDuration nano) +fn Clock Clock.add_nano_duration(self, NanoDuration nano) @operator_s(+) @inline { return (Clock)((NanoDuration)self + nano); } -fn Clock Clock.add_duration(self, Duration duration) +fn Clock Clock.add_duration(self, Duration duration) @operator_s(+) @inline { return self.add_nano_duration(duration.to_nano()); } -fn NanoDuration Clock.to_now(self) +fn NanoDuration Clock.nano_diff(self, Clock other) @operator(-) @inline { - return (NanoDuration)(now() - self); + return (NanoDuration)self - (NanoDuration)other; +} + +fn NanoDuration Clock.to_now(self) @inline +{ + return (NanoDuration)now() - (NanoDuration)self; } \ No newline at end of file diff --git a/lib/std/time/datetime.c3 b/lib/std/time/datetime.c3 index 30dbdf5e9..276fbff33 100644 --- a/lib/std/time/datetime.c3 +++ b/lib/std/time/datetime.c3 @@ -106,7 +106,7 @@ fn TzDateTime DateTime.to_gmt_offset(self, int gmt_offset) *> fn TzDateTime TzDateTime.to_gmt_offset(self, int gmt_offset) { if (self.gmt_offset == gmt_offset) return self; - Time time = self.time + (Time)gmt_offset * (Time)time::SEC; + Time time = self.time + gmt_offset * time::SEC; DateTime dt = from_time(time); dt.time = self.time; return { dt, gmt_offset }; diff --git a/lib/std/time/time.c3 b/lib/std/time/time.c3 index b50ebefe0..04d1c865d 100644 --- a/lib/std/time/time.c3 +++ b/lib/std/time/time.c3 @@ -19,11 +19,11 @@ const Duration MONTH = 30 * DAY; const Duration YEAR = 36525 * DAY / 100; const Duration FOREVER = long.max; -fn Duration us(long l) @inline => (Duration)l * US; -fn Duration ms(long l) @inline => (Duration)l * MS; -fn Duration sec(long l) @inline => (Duration)l * SEC; -fn Duration min(long l) @inline => (Duration)l * MIN; -fn Duration hour(long l) @inline => (Duration)l * HOUR; +fn Duration us(long l) @inline => l * US; +fn Duration ms(long l) @inline => l * MS; +fn Duration sec(long l) @inline =>l * SEC; +fn Duration min(long l) @inline => l * MIN; +fn Duration hour(long l) @inline => l * HOUR; fn Duration from_float(double s) @inline => (Duration)(s * (double)SEC); struct DateTime @@ -82,21 +82,21 @@ fn Time now() $endif } -fn Time Time.add_seconds(time, long seconds) => time + (Time)(seconds * (long)SEC); -fn Time Time.add_minutes(time, long minutes) => time + (Time)(minutes * (long)MIN); -fn Time Time.add_hours(time, long hours) => time + (Time)(hours * (long)HOUR); -fn Time Time.add_days(time, long days) => time + (Time)(days * (long)DAY); -fn Time Time.add_weeks(time, long weeks) => time + (Time)(weeks * (long)WEEK); -fn Time Time.add_duration(time, Duration duration) @operator(+) => time + (Time)duration; +fn Time Time.add_seconds(time, long seconds) => time + seconds * SEC; +fn Time Time.add_minutes(time, long minutes) => time + minutes * MIN; +fn Time Time.add_hours(time, long hours) => time + hours * HOUR; +fn Time Time.add_days(time, long days) => time + days * DAY; +fn Time Time.add_weeks(time, long weeks) => time + weeks * WEEK; +fn Time Time.add_duration(time, Duration duration) @operator_s(+) @inline => (Time)((long)time + (long)duration); fn int Time.compare_to(time, Time other) { - if (time == other) return 0; + if ((long)time == (long)other) return 0; return time > other ? 1 : -1; } fn double Time.to_seconds(time) => (long)time / (double)SEC; -fn Duration Time.diff_us(time, Time other) @operator(-) => (Duration)(time - other); +fn Duration Time.diff_us(time, Time other) @operator(-) => (Duration)((long)time - (long)other); fn double Time.diff_sec(time, Time other) => (long)time.diff_us(other) / (double)SEC; fn double Time.diff_min(time, Time other) => (long)time.diff_us(other) / (double)MIN; fn double Time.diff_hour(time, Time other) => (long)time.diff_us(other) / (double)HOUR; @@ -108,6 +108,7 @@ fn long NanoDuration.to_ms(nd) => (long)nd / 1_000_000; fn Duration NanoDuration.to_duration(nd) => (Duration)nd / 1_000; fn NanoDuration Duration.to_nano(td) => (NanoDuration)td * 1_000; fn long Duration.to_ms(td) => (long)td / 1_000; +macro Duration Duration.mult(#td, long #val) @operator_s(*) @safemacro => (Duration)((long)#td * #val); fn usz? NanoDuration.to_format(&self, Formatter* formatter) @dynamic { diff --git a/releasenotes.md b/releasenotes.md index d5e4140bc..a5add73e9 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -10,12 +10,14 @@ - Assert when a macro with compile time value is discarded, e.g. `foo();` where `foo()` returns an untyped list. #2117 - Fix stringify for compound initializers #2120. - Fix No index OOB check for `[:^n]` #2123 +- Fix regression in Time diff due to operator overloading #2124 ### Stdlib changes - Added `String.quick_ztr` and `String.is_zstr` - std::ascii moved into std::core::ascii. Old _m variants are deprecated, as is uint methods. - Add `String.tokenize_all` to replace the now deprecated `String.splitter` - Add `String.count` to count the number of instances of a string. +- Add `Duration * Int` and `Clock - Clock` overload. ## 0.7.1 Change list diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 93f27c71c..ab71abf97 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1779,6 +1779,7 @@ static Decl *sema_find_exact_typed_operator_in_list(Decl **methods, OperatorOver FOREACH(Decl *, func, methods) { if (func == skipped) continue; + if (!decl_ok(func)) continue; if (func->func_decl.operator != operator_overload) continue; if (parent_type && parent_type != typeget(func->func_decl.type_parent)) continue; if ((overload_type & func->func_decl.overload_type) == 0) continue; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 44e5c84af..6bb65fa65 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -10964,19 +10964,22 @@ bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *meth Expr *resolve = method_call; if (reverse_overload) { - Decl *temp = decl_new_generated_var(method_decl->func_decl.signature.params[1]->type, VARDECL_LOCAL, parent->span); - Expr *generate = expr_generate_decl(temp, expr_copy(parent)); - parent->expr_kind = EXPR_IDENTIFIER; - parent->ident_expr = temp; - parent->resolve_status = RESOLVE_DONE; - parent->type = temp->type; - if (!sema_analyse_expr(context, generate)) return false; - Expr *copied_method = expr_copy(method_call); - expr_rewrite_two(method_call, generate, copied_method); + if (!expr_is_const(parent)) + { + Decl *temp = decl_new_generated_var(method_decl->func_decl.signature.params[1]->type, VARDECL_LOCAL, parent->span); + Expr *generate = expr_generate_decl(temp, expr_copy(parent)); + parent->expr_kind = EXPR_IDENTIFIER; + parent->ident_expr = temp; + parent->resolve_status = RESOLVE_DONE; + parent->type = temp->type; + if (!sema_analyse_expr(context, generate)) return false; + Expr *copied_method = expr_copy(method_call); + expr_rewrite_two(method_call, generate, copied_method); + method_call = copied_method; + } Expr *arg0 = arguments[0]; arguments[0] = parent; parent = arg0; - method_call = copied_method; } *method_call = (Expr) { .expr_kind = EXPR_CALL, .span = original_span, @@ -11001,19 +11004,6 @@ bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *meth expr_rewrite_insert_deref(parent); } } - else if (!expr_may_ref(parent)) - { - Expr *inner = expr_copy(parent); - parent->expr_kind = EXPR_UNARY; - Type *inner_type = inner->type; - bool optional = type_is_optional(inner->type); - parent->type = type_add_optional(type_get_ptr(type_no_optional(inner_type)), optional); - parent->unary_expr.operator = UNARYOP_TADDR; - parent->unary_expr.expr = inner; - parent->resolve_status = RESOLVE_NOT_DONE; - if (!sema_analyse_expr(context, parent)) return false; - expr_rewrite_insert_deref(parent); - } ASSERT_SPAN(method_call, parent && parent->type && first == parent->type->canonical); if (!sema_expr_analyse_general_call(context, method_call, method_decl, parent, false, NULL)) return expr_poison(method_call); diff --git a/test/unit/stdlib/time/time.c3 b/test/unit/stdlib/time/time.c3 index e67f3c980..85d2e1be5 100644 --- a/test/unit/stdlib/time/time.c3 +++ b/test/unit/stdlib/time/time.c3 @@ -2,6 +2,24 @@ module nanoduration_test @test; import std::io; import std::time; +fn void time_diff() +{ + Time t = time::now(); + Time t2 = t + time::SEC; + test::eq(t2 - t, time::SEC); + test::ne(t, t2); + test::eq(t, t); +} + +fn void clock_diff() +{ + Clock c = clock::now(); + Clock c2 = c + time::SEC.to_nano(); + test::eq(c2 - c, time::SEC.to_nano()); + c2 = c + time::DAY; + test::eq(c2 - c, time::DAY.to_nano()); +} + fn void to_format() { char[32] buffer;