From 423a482276a8167108f256eb3e37d865121f0298 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Fri, 22 Sep 2023 00:07:08 +0200 Subject: [PATCH 01/22] Add Chrono package --- packages/Chrono/_package.candy | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/Chrono/_package.candy diff --git a/packages/Chrono/_package.candy b/packages/Chrono/_package.candy new file mode 100644 index 000000000..e69de29bb From c4ab6d9c62548c7e80678f86fec901835211d34f Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Fri, 22 Sep 2023 00:07:29 +0200 Subject: [PATCH 02/22] Add constants --- packages/Chrono/_.candy | 1 + packages/Chrono/constants.candy | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 packages/Chrono/_.candy create mode 100644 packages/Chrono/constants.candy diff --git a/packages/Chrono/_.candy b/packages/Chrono/_.candy new file mode 100644 index 000000000..1a4073d7b --- /dev/null +++ b/packages/Chrono/_.candy @@ -0,0 +1 @@ +constants := use ".constants" diff --git a/packages/Chrono/constants.candy b/packages/Chrono/constants.candy new file mode 100644 index 000000000..1c35432a2 --- /dev/null +++ b/packages/Chrono/constants.candy @@ -0,0 +1,37 @@ +[int] = use "Core" + +daysPerNormalWeek := 7 + +hoursPerNormalDay := 24 +hoursPerNormalWeek := hoursPerNormalDay | int.multiply daysPerNormalWeek + +minutesPerHour := 60 +minutesPerNormalDay := minutesPerHour | int.multiply hoursPerNormalDay +minutesPerNormalWeek := minutesPerNormalDay | int.multiply daysPerNormalWeek + +secondsPerMinute := 60 +secondsPerHour := secondsPerMinute | int.multiply minutesPerHour +secondsPerNormalDay := secondsPerHour | int.multiply hoursPerNormalDay +secondsPerNormalWeek := secondsPerNormalDay | int.multiply daysPerNormalWeek + +millisecondsPerSecond := 1000 +millisecondsPerMinute := millisecondsPerSecond | int.multiply secondsPerMinute +millisecondsPerHour := millisecondsPerMinute | int.multiply minutesPerHour +millisecondsPerNormalDay := millisecondsPerHour | int.multiply hoursPerNormalDay +millisecondsPerNormalWeek := millisecondsPerNormalDay | int.multiply daysPerNormalWeek + +microsecondsPerMillisecond := 1000 +microsecondsPerSecond := microsecondsPerMillisecond | int.multiply millisecondsPerSecond +microsecondsPerMinute := microsecondsPerSecond | int.multiply secondsPerMinute +microsecondsPerHour := microsecondsPerMinute | int.multiply minutesPerHour +microsecondsPerNormalDay := microsecondsPerHour | int.multiply hoursPerNormalDay +microsecondsPerNormalWeek := microsecondsPerNormalDay | int.multiply daysPerNormalWeek + +nanosecondsPerMicrosecond := 1000 +nanosecondsPerMillisecond := nanosecondsPerMicrosecond | int.multiply microsecondsPerMillisecond +nanosecondsPerSecond := nanosecondsPerMillisecond | int.multiply millisecondsPerSecond +nanosecondsPerMinute := nanosecondsPerSecond | int.multiply secondsPerMinute +nanosecondsPerHour := nanosecondsPerMinute | int.multiply minutesPerHour +nanosecondsPerNormalDay := nanosecondsPerHour | int.multiply hoursPerNormalDay +nanosecondsPerNormalWeek := nanosecondsPerNormalDay | int.multiply daysPerNormalWeek + From 378de9623f308a351e7add35f9fbb584f52e2cca Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Fri, 22 Sep 2023 00:07:55 +0200 Subject: [PATCH 03/22] Add zero to fixedDecimal --- packages/Core/fixedDecimal.candy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/Core/fixedDecimal.candy b/packages/Core/fixedDecimal.candy index 19c85b09d..d7de055dc 100644 --- a/packages/Core/fixedDecimal.candy +++ b/packages/Core/fixedDecimal.candy @@ -36,6 +36,8 @@ floorToInt a := needs (is a) a | minorUnits | int.divideTruncating (a | scale | scaleFactor) +zero := fromInt 0 + rescaledMinorUnits a targetScale = needs (is a) needs (isScale targetScale) From 6d2fe40e3dff6e1463045dcf5bd7b6c9137f26b9 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Fri, 22 Sep 2023 00:08:08 +0200 Subject: [PATCH 04/22] Add duration --- packages/Chrono/_.candy | 1 + packages/Chrono/duration.candy | 199 +++++++++++++++++++++++++++++++++ packages/Core/text.candy | 28 ++++- 3 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 packages/Chrono/duration.candy diff --git a/packages/Chrono/_.candy b/packages/Chrono/_.candy index 1a4073d7b..e5425f6f1 100644 --- a/packages/Chrono/_.candy +++ b/packages/Chrono/_.candy @@ -1 +1,2 @@ constants := use ".constants" +duration := use ".duration" diff --git a/packages/Chrono/duration.candy b/packages/Chrono/duration.candy new file mode 100644 index 000000000..9b180aaea --- /dev/null +++ b/packages/Chrono/duration.candy @@ -0,0 +1,199 @@ +[fixedDecimal, tag, check, equals, bool, ifElse, int, toDebugText, text] = use "Core" +constants = use "..constants" + +# Storage Format: Duration (fixedDecimal of nanoseconds) +is d := d % + Duration nanoseconds -> fixedDecimal.is nanoseconds + _ -> False + +isNumber n = int.is n | bool.lazyOr {fixedDecimal.is n} +numberAsFixedDecimal n = + needs (isNumber n) + ifElse (fixedDecimal.is n) {n} {fixedDecimal.fromInt n} + +zero := Duration fixedDecimal.zero + +fromNanoseconds nanoseconds := + needs (isNumber nanoseconds) + Duration (numberAsFixedDecimal nanoseconds) +fromMicroseconds microseconds := + needs (isNumber microseconds) + Duration (numberAsFixedDecimal microseconds | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerMicrosecond)) +fromMilliseconds milliseconds := + needs (isNumber milliseconds) + Duration (numberAsFixedDecimal milliseconds | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerMillisecond)) +fromSeconds seconds := + needs (isNumber seconds) + Duration (numberAsFixedDecimal seconds | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerSecond)) +fromMinutes minutes := + needs (isNumber minutes) + Duration (numberAsFixedDecimal minutes | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerMinute)) +fromHours hours := + needs (isNumber hours) + Duration (numberAsFixedDecimal hours | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerHour)) +fromNormalDays days := + needs (isNumber days) + Duration (numberAsFixedDecimal days | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerNormalDay)) + +# TODO: Do this without truncating division if possible +totalNanoseconds duration := + needs (is duration) + tag.getValue duration +totalMicroseconds duration := + needs (is duration) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerHour) +totalMilliseconds duration := + needs (is duration) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerMillisecond) +totalSeconds duration := + needs (is duration) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerSecond) +totalMinutes duration := + needs (is duration) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerMinute) +totalHours duration := + needs (is duration) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerHour) +totalNormalDays duration := + needs (is duration) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerNormalDay) + +add summandA summandB := + needs (is summandA) + needs (is summandB) + Duration (fixedDecimal.add (tag.getValue summandA) (tag.getValue summandB)) +subtract minuend subtrahend := + needs (is minuend) + needs (is subtrahend) + Duration (fixedDecimal.subtract (tag.getValue minuend) (tag.getValue subtrahend)) +negate value := + needs (is value) + Duration (value | tag.getValue | fixedDecimal.negate) +multiply factorA factorB := + needs (is factorA) + needs (isNumber factorB) + Duration (fixedDecimal.multiply (tag.getValue factorA) (numberAsFixedDecimal factorB)) +divideTruncating dividend divisor := + needs (is dividend) + needs (isNumber divisor) + needs (divisor | numberAsFixedDecimal | equals fixedDecimal.zero | bool.not) "You can't divide by zero." + Duration (fixedDecimal.divideTruncating (tag.getValue dividend) (numberAsFixedDecimal divisor)) + +subNormalDayComponent duration := + needs (is duration) + subtract duration (fromNormalDays (totalNormalDays duration | fixedDecimal.floorToInt)) +subHourComponent duration := + needs (is duration) + subtract duration (fromHours (totalHours duration | fixedDecimal.floorToInt)) +subMinuteComponent duration := + needs (is duration) + subtract duration (fromMinutes (totalMinutes duration | fixedDecimal.floorToInt)) +subSecondComponent duration := + needs (is duration) + subtract duration (fromSeconds (totalSeconds duration | fixedDecimal.floorToInt)) +subMillisecondComponent duration := + needs (is duration) + subtract duration (fromMilliseconds (totalMilliseconds duration | fixedDecimal.floorToInt)) +subMicrosecondComponent duration := + needs (is duration) + subtract duration (fromMicroseconds (totalMicroseconds duration | fixedDecimal.floorToInt)) +subNanosecondComponent duration := + needs (is duration) + subtract duration (fromNanoseconds (totalNanoseconds duration | fixedDecimal.floorToInt)) + +normalDays duration := + needs (is duration) + duration | totalNormalDays | fixedDecimal.floorToInt +hours duration := + needs (is duration) + duration | subNormalDayComponent | totalHours | fixedDecimal.floorToInt +minutes duration := + needs (is duration) + duration | subHourComponent | totalMinutes | fixedDecimal.floorToInt +seconds duration := + needs (is duration) + duration | subMinuteComponent | totalSeconds | fixedDecimal.floorToInt +milliseconds duration := + needs (is duration) + duration | subSecondComponent | totalHours | fixedDecimal.floorToInt +microseconds duration := + needs (is duration) + duration | subMillisecondComponent | totalMicroseconds | fixedDecimal.floorToInt +nanoseconds duration := + needs (is duration) + duration | subMicrosecondComponent | totalNanoseconds | fixedDecimal.floorToInt + +compareTo valueA valueB := + needs (is valueA) + needs (is valueB) + result = (tag.getValue valueA) | fixedDecimal.compareTo (tag.getValue valueB) + check (equals result Equal | bool.implies (equals valueA valueB)) + result +isLessThan valueA valueB := + needs (is valueA) + needs (is valueB) + equals (compareTo valueA valueB) Less +isGreaterThan valueA valueB := + needs (is valueA) + needs (is valueB) + equals (compareTo valueA valueB) Greater +isLessThanOrEqualTo valueA valueB := + needs (is valueA) + needs (is valueB) + valueA | isGreaterThan valueB | bool.not +isGreaterThanOrEqualTo valueA valueB := + needs (is valueA) + needs (is valueB) + valueA | isLessThan valueB | bool.not + +isPositive value := + needs (is value) + value | tag.getValue | fixedDecimal.isPositive +isNonPositive value := + needs (is value) + value | isPositive | bool.not +isNegative value := + needs (is value) + value | tag.getValue | fixedDecimal.isNegative +isNonNegative value := + needs (is value) + value | isNegative | bool.not +absolute value := + needs (is value) + ifElse (isNegative value) { negate value } { value } + +min valueA valueB := + needs (is valueA) + needs (is valueB) + ifElse (valueA | isLessThanOrEqualTo valueB) { valueA } { valueB } +max valueA valueB := + needs (is valueA) + needs (is valueB) + ifElse (valueA | isGreaterThanOrEqualTo valueB) { valueA } { valueB } +coerceAtLeast value minimum := + needs (is value) + needs (is minimum) + max value minimum +coerceAtMost value maximum := + needs (is value) + needs (is maximum) + min value maximum +coerceIn value minimum maximum := + needs (is value) + needs (is minimum) + needs (is maximum) + needs (minimum | isLessThanOrEqualTo maximum) + value | coerceAtLeast minimum | coerceAtMost maximum + +# default format: -D:hh:mm:ss.FFFFFFFFF +toText duration := + needs (is duration) + sign = ifElse (isNegative duration) {"-"} {""} + d = duration | normalDays + hh = duration | hours | toDebugText | text.padStart 2 "0" + mm = duration | minutes | toDebugText | text.padStart 2 "0" + ss = duration | seconds | toDebugText | text.padStart 2 "0" + f = duration | subSecondComponent | tag.getValue | fixedDecimal.toText + dotIndex = f | text.firstIndexOf "." + f = f | text.getRange (dotIndex | int.add 1) (int.min (dotIndex | int.add 10) (text.length f)) | text.padEnd 9 "0" + "{sign}{d}:{hh}:{mm}:{ss}.{f}" diff --git a/packages/Core/text.candy b/packages/Core/text.candy index f46cf6f27..ff45f44bc 100644 --- a/packages/Core/text.candy +++ b/packages/Core/text.candy @@ -1,6 +1,6 @@ builtins = use "Builtins" bool = use "..bool" -[ifElse] = use "..controlFlow" +[ifElse, recursive] = use "..controlFlow" [equals] = use "..equality" int = use "..int" # iterable = use "..iterable" @@ -120,3 +120,29 @@ trimEnd := builtins.textTrimEnd trim text := needs (is text) text | trimStart | trimEnd + +firstIndexOf text char := + needs (is text) + needs (is char) + needs (length char | equals 1) + recursive 0 { recurse i -> + ifElse (text | length | int.isGreaterThanOrEqualTo i) {ifElse (text | characterAt i | equals char) {i} {i | int.add 1 | recurse}} {int.negate 1} + } + +padStart text len char := + needs (is text) + needs (int.is len) + needs (is char) + needs (char | length | equals 1) + recursive text { recurse text -> + ifElse (text | length | int.isGreaterThanOrEqualTo len) {text} {char | concatenate text | recurse} + } + +padEnd text len char := + needs (is text) + needs (int.is len) + needs (is char) + needs (char | length | equals 1) + recursive text { recurse text -> + ifElse (text | length | int.isGreaterThanOrEqualTo len) {text} {text | concatenate char | recurse} + } From 8dd0b21f069f994da8a79b4ba892eca33d35fb61 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Fri, 22 Sep 2023 18:40:50 +0200 Subject: [PATCH 05/22] Add example using chrono --- packages/Examples/chrono.candy | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 packages/Examples/chrono.candy diff --git a/packages/Examples/chrono.candy b/packages/Examples/chrono.candy new file mode 100644 index 000000000..904402fa1 --- /dev/null +++ b/packages/Examples/chrono.candy @@ -0,0 +1,9 @@ +[duration] = use "Chrono" + +main := { environment -> + print message = environment.stdout message + + dur = duration.fromSeconds 4 | duration.add (duration.fromMinutes 2) + + print "{duration.toText dur}" +} From 75de86e9debc33f69d3857ca2d229d0ff135c83a Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Tue, 3 Oct 2023 16:17:33 +0200 Subject: [PATCH 06/22] Add instant --- packages/Chrono/constants.candy | 1 - packages/Chrono/instant.candy | 78 +++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 packages/Chrono/instant.candy diff --git a/packages/Chrono/constants.candy b/packages/Chrono/constants.candy index 1c35432a2..1c9ab7754 100644 --- a/packages/Chrono/constants.candy +++ b/packages/Chrono/constants.candy @@ -34,4 +34,3 @@ nanosecondsPerMinute := nanosecondsPerSecond | int.multiply secondsPerMinute nanosecondsPerHour := nanosecondsPerMinute | int.multiply minutesPerHour nanosecondsPerNormalDay := nanosecondsPerHour | int.multiply hoursPerNormalDay nanosecondsPerNormalWeek := nanosecondsPerNormalDay | int.multiply daysPerNormalWeek - diff --git a/packages/Chrono/instant.candy b/packages/Chrono/instant.candy new file mode 100644 index 000000000..c38d92f6a --- /dev/null +++ b/packages/Chrono/instant.candy @@ -0,0 +1,78 @@ +[fixedDecimal, tag, check, equals, bool, ifElse] = use "Core" +constants = use "..constants" +duration = use "..duration" + +# Storage Format: Instant (fixedDecimal of nanoseconds since the Unix Epoch) +is i := i % + Instant nanoseconds -> fixedDecimal.is nanoseconds + _ -> False + +startOfUnixEpoch := Instant fixedDecimal.zero + +fromUnixDuration dur := + needs (duration.is dur) + Instant (tag.getValue dur) + +addDuration instant dur := + needs (is instant) + needs (duration.is dur) + Instant (fixedDecimal.add (tag.getValue instant) (tag.getValue dur)) +subtract instant dur := + needs (is instant) + needs (duration.is dur) + Instant (fixedDecimal.subtract (tag.getValue instant) (tag.getValue dur)) + +durationBetween instantA instantB := + needs (is instantA) + needs (is instantB) + duration.fromNanoseconds (fixedDecimal.subtract (tag.getValue instantA) (tag.getValue instantB)) + +compareTo valueA valueB := + needs (is valueA) + needs (is valueB) + result = (tag.getValue valueA) | fixedDecimal.compareTo (tag.getValue valueB) + check (equals result Equal | bool.implies (equals valueA valueB)) + result +isLessThan valueA valueB := + needs (is valueA) + needs (is valueB) + equals (compareTo valueA valueB) Less +isGreaterThan valueA valueB := + needs (is valueA) + needs (is valueB) + equals (compareTo valueA valueB) Greater +isLessThanOrEqualTo valueA valueB := + needs (is valueA) + needs (is valueB) + valueA | isGreaterThan valueB | bool.not +isGreaterThanOrEqualTo valueA valueB := + needs (is valueA) + needs (is valueB) + valueA | isLessThan valueB | bool.not + +min valueA valueB := + needs (is valueA) + needs (is valueB) + ifElse (valueA | isLessThanOrEqualTo valueB) { valueA } { valueB } +max valueA valueB := + needs (is valueA) + needs (is valueB) + ifElse (valueA | isGreaterThanOrEqualTo valueB) { valueA } { valueB } +coerceAtLeast value minimum := + needs (is value) + needs (is minimum) + max value minimum +coerceAtMost value maximum := + needs (is value) + needs (is maximum) + min value maximum +coerceIn value minimum maximum := + needs (is value) + needs (is minimum) + needs (is maximum) + needs (minimum | isLessThanOrEqualTo maximum) + value | coerceAtLeast minimum | coerceAtMost maximum + +toUnixTimeDuration instant := + needs (is instant) + duration.fromNanoseconds (tag.getValue instant) From 7068c4a5d94f3ef65f94311a359b19743091c53d Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Tue, 3 Oct 2023 18:12:53 +0200 Subject: [PATCH 07/22] Fix duration::toText --- packages/Chrono/duration.candy | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/Chrono/duration.candy b/packages/Chrono/duration.candy index 9b180aaea..70c3db190 100644 --- a/packages/Chrono/duration.candy +++ b/packages/Chrono/duration.candy @@ -194,6 +194,5 @@ toText duration := mm = duration | minutes | toDebugText | text.padStart 2 "0" ss = duration | seconds | toDebugText | text.padStart 2 "0" f = duration | subSecondComponent | tag.getValue | fixedDecimal.toText - dotIndex = f | text.firstIndexOf "." - f = f | text.getRange (dotIndex | int.add 1) (int.min (dotIndex | int.add 10) (text.length f)) | text.padEnd 9 "0" + f = f | text.getRange 0 (f | text.firstIndexOf ".") | text.padEnd 9 "0" "{sign}{d}:{hh}:{mm}:{ss}.{f}" From 04197344dfc30e117fc2fa5ae595340546f22d41 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Tue, 3 Oct 2023 18:13:15 +0200 Subject: [PATCH 08/22] Add clock --- compiler/vm/src/environment.rs | 18 ++++++++++++++++-- compiler/vm/src/heap/mod.rs | 6 +++++- packages/Chrono/_.candy | 2 ++ packages/Chrono/clock.candy | 21 +++++++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 packages/Chrono/clock.candy diff --git a/compiler/vm/src/environment.rs b/compiler/vm/src/environment.rs index 36ee36e06..cdaa3ee9e 100644 --- a/compiler/vm/src/environment.rs +++ b/compiler/vm/src/environment.rs @@ -1,6 +1,6 @@ use crate::{ byte_code::ByteCode, - heap::{Data, Handle, Heap, InlineObject, List, Struct, Tag, Text}, + heap::{Data, Handle, Heap, InlineObject, Int, List, Struct, Tag, Text}, tracer::Tracer, vm::VmHandleCall, StateAfterRun, StateAfterRunForever, Vm, VmFinished, @@ -9,6 +9,7 @@ use itertools::Itertools; use std::{ borrow::Borrow, io::{self, BufRead}, + time::SystemTime, }; use tracing::info; @@ -49,6 +50,7 @@ impl, T: Tracer> Vm { pub struct DefaultEnvironment { stdin_handle: Handle, stdout_handle: Handle, + system_clock_handle: Handle, } impl DefaultEnvironment { pub fn new(heap: &mut Heap, args: &[String]) -> (InlineObject, Self) { @@ -59,6 +61,7 @@ impl DefaultEnvironment { let arguments = List::create(heap, true, arguments.as_slice()); let stdin_handle = Handle::new(heap, 0); let stdout_handle = Handle::new(heap, 1); + let system_clock_handle = Handle::new(heap, 0); let environment_object = Struct::create_with_symbol_keys( heap, true, @@ -66,11 +69,13 @@ impl DefaultEnvironment { (heap.default_symbols().arguments, arguments.into()), (heap.default_symbols().stdout, **stdout_handle), (heap.default_symbols().stdin, **stdin_handle), + (heap.default_symbols().system_clock, **system_clock_handle), ], ); let environment = Self { stdin_handle, stdout_handle, + system_clock_handle, }; (environment_object.into(), environment) } @@ -81,7 +86,16 @@ impl Environment for DefaultEnvironment { heap: &mut Heap, call: VmHandleCall, ) -> Vm { - if call.handle == self.stdin_handle { + if call.handle == self.system_clock_handle { + let [] = call.arguments.as_slice() else { + unreachable!() + }; + + let now = SystemTime::now(); + let since_unix_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let nanoseconds = Int::create(heap, true, since_unix_epoch.as_nanos()); + call.complete(heap, nanoseconds) + } else if call.handle == self.stdin_handle { let input = { let stdin = io::stdin(); stdin.lock().lines().next().unwrap().unwrap() diff --git a/compiler/vm/src/heap/mod.rs b/compiler/vm/src/heap/mod.rs index b5f603814..69fa3cd94 100644 --- a/compiler/vm/src/heap/mod.rs +++ b/compiler/vm/src/heap/mod.rs @@ -245,6 +245,7 @@ pub struct DefaultSymbols { pub stdin: Text, pub stdout: Text, pub struct_: Text, + pub system_clock: Text, pub tag: Text, pub text: Text, pub true_: Text, @@ -270,6 +271,7 @@ impl DefaultSymbols { stdin: Text::create(heap, false, "Stdin"), stdout: Text::create(heap, false, "Stdout"), struct_: Text::create(heap, false, "Struct"), + system_clock: Text::create(heap, false, "SystemClock"), tag: Text::create(heap, false, "Tag"), text: Text::create(heap, false, "Text"), true_: Text::create(heap, false, "True"), @@ -308,6 +310,7 @@ impl DefaultSymbols { stdin: clone_to_heap(heap, address_map, self.stdin), stdout: clone_to_heap(heap, address_map, self.stdout), struct_: clone_to_heap(heap, address_map, self.struct_), + system_clock: clone_to_heap(heap, address_map, self.system_clock), tag: clone_to_heap(heap, address_map, self.tag), text: clone_to_heap(heap, address_map, self.text), true_: clone_to_heap(heap, address_map, self.true_), @@ -323,7 +326,7 @@ impl DefaultSymbols { .map(|it| symbols[it]) } #[must_use] - pub const fn all_symbols(&self) -> [Text; 21] { + pub const fn all_symbols(&self) -> [Text; 22] { [ self.arguments, self.builtin, @@ -343,6 +346,7 @@ impl DefaultSymbols { self.stdin, self.stdout, self.struct_, + self.system_clock, self.tag, self.text, self.true_, diff --git a/packages/Chrono/_.candy b/packages/Chrono/_.candy index e5425f6f1..63c17ea3b 100644 --- a/packages/Chrono/_.candy +++ b/packages/Chrono/_.candy @@ -1,2 +1,4 @@ +clock := use ".clock" constants := use ".constants" duration := use ".duration" +instant := use ".instant" diff --git a/packages/Chrono/clock.candy b/packages/Chrono/clock.candy new file mode 100644 index 000000000..f72ff340f --- /dev/null +++ b/packages/Chrono/clock.candy @@ -0,0 +1,21 @@ +[tag, function] = use "Core" +instant = use "..instant" +duration = use "..duration" + +is c := c % + Clock f -> function.is0 f + _ -> False + +fromSystemClock systemClock := + needs (function.is0 systemClock) + Clock { + systemClock | function.run | duration.fromNanoseconds | instant.fromUnixDuration + } + +mockFromInstant inst := + needs (instant.is inst) + Clock { instant } + +now clock := + needs (is clock) + function.run (tag.getValue clock) From 17ea1d1a5665a28dc71143cb8d6508b161a897a8 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Tue, 3 Oct 2023 18:13:26 +0200 Subject: [PATCH 09/22] Add clock example --- packages/Examples/chrono.candy | 9 --------- packages/Examples/clock.candy | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) delete mode 100644 packages/Examples/chrono.candy create mode 100644 packages/Examples/clock.candy diff --git a/packages/Examples/chrono.candy b/packages/Examples/chrono.candy deleted file mode 100644 index 904402fa1..000000000 --- a/packages/Examples/chrono.candy +++ /dev/null @@ -1,9 +0,0 @@ -[duration] = use "Chrono" - -main := { environment -> - print message = environment.stdout message - - dur = duration.fromSeconds 4 | duration.add (duration.fromMinutes 2) - - print "{duration.toText dur}" -} diff --git a/packages/Examples/clock.candy b/packages/Examples/clock.candy new file mode 100644 index 000000000..214f9c876 --- /dev/null +++ b/packages/Examples/clock.candy @@ -0,0 +1,10 @@ +[clock, duration, instant] = use "Chrono" +[tag, fixedDecimal] = use "Core" + +main := { environment -> + print message = environment.stdout message + + c = clock.fromSystemClock environment.systemClock + now = clock.now c + print "It has been {now | instant.toUnixTimeDuration | duration.toText} since the start the of unix epoch" +} From fa8cabcea4d5de20772cdbb51944a5155e70b2c0 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 25 Oct 2023 14:45:57 +0200 Subject: [PATCH 10/22] fix merge error --- compiler/vm/src/heap/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/vm/src/heap/mod.rs b/compiler/vm/src/heap/mod.rs index c26a1489a..f05a0af56 100644 --- a/compiler/vm/src/heap/mod.rs +++ b/compiler/vm/src/heap/mod.rs @@ -329,7 +329,7 @@ impl DefaultSymbols { .map(|it| symbols[it]) } #[must_use] - pub const fn all_symbols(&self) -> [Text; 22] { + pub const fn all_symbols(&self) -> [Text; 23] { [ self.arguments, self.builtin, From 94a98d760f9f8da173538092be667f11cf59b1a6 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Thu, 2 Nov 2023 23:25:29 +0100 Subject: [PATCH 11/22] Typo Co-authored-by: Jonas Wanke --- packages/Examples/clock.candy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Examples/clock.candy b/packages/Examples/clock.candy index 214f9c876..ab59d2d45 100644 --- a/packages/Examples/clock.candy +++ b/packages/Examples/clock.candy @@ -6,5 +6,5 @@ main := { environment -> c = clock.fromSystemClock environment.systemClock now = clock.now c - print "It has been {now | instant.toUnixTimeDuration | duration.toText} since the start the of unix epoch" + print "It has been {now | instant.toUnixTimeDuration | duration.toText} since the start the of Unix epoch" } From cdfd11cca2ea7c65c5b8bd707bd5aeecd76081b0 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:28:13 +0100 Subject: [PATCH 12/22] Update packages/Chrono/clock.candy Co-authored-by: Jonas Wanke --- packages/Chrono/clock.candy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Chrono/clock.candy b/packages/Chrono/clock.candy index f72ff340f..0902f2a75 100644 --- a/packages/Chrono/clock.candy +++ b/packages/Chrono/clock.candy @@ -18,4 +18,4 @@ mockFromInstant inst := now clock := needs (is clock) - function.run (tag.getValue clock) + clock | tag.getValue | function.run From 6c8860b1564a1119d7dc2c5a3d31c06b09c8c67c Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:28:26 +0100 Subject: [PATCH 13/22] Update packages/Chrono/duration.candy Co-authored-by: Jonas Wanke --- packages/Chrono/duration.candy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Chrono/duration.candy b/packages/Chrono/duration.candy index 70c3db190..bea2c586c 100644 --- a/packages/Chrono/duration.candy +++ b/packages/Chrono/duration.candy @@ -1,7 +1,7 @@ [fixedDecimal, tag, check, equals, bool, ifElse, int, toDebugText, text] = use "Core" constants = use "..constants" -# Storage Format: Duration (fixedDecimal of nanoseconds) +## Storage Format: Duration (fixedDecimal of nanoseconds) is d := d % Duration nanoseconds -> fixedDecimal.is nanoseconds _ -> False From 3f1d9d9b2178c0e44b91e2f8a518849c9226162e Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:28:37 +0100 Subject: [PATCH 14/22] Update packages/Chrono/duration.candy Co-authored-by: Jonas Wanke --- packages/Chrono/duration.candy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Chrono/duration.candy b/packages/Chrono/duration.candy index bea2c586c..d9e8bcd3a 100644 --- a/packages/Chrono/duration.candy +++ b/packages/Chrono/duration.candy @@ -35,7 +35,7 @@ fromNormalDays days := needs (isNumber days) Duration (numberAsFixedDecimal days | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerNormalDay)) -# TODO: Do this without truncating division if possible +## TODO: Do this without truncating division if possible totalNanoseconds duration := needs (is duration) tag.getValue duration From 75031136f4b0c7d4e86ad98cf73bb604a097f0e4 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:36:59 +0100 Subject: [PATCH 15/22] Update packages/Core/text.candy Co-authored-by: Jonas Wanke --- packages/Core/text.candy | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/Core/text.candy b/packages/Core/text.candy index ff45f44bc..46f9a05d9 100644 --- a/packages/Core/text.candy +++ b/packages/Core/text.candy @@ -137,7 +137,6 @@ padStart text len char := recursive text { recurse text -> ifElse (text | length | int.isGreaterThanOrEqualTo len) {text} {char | concatenate text | recurse} } - padEnd text len char := needs (is text) needs (int.is len) From 523fc09473c7819cba24ed82c8cf4a0d3c2716a5 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:43:13 +0100 Subject: [PATCH 16/22] Update packages/Chrono/instant.candy Co-authored-by: Jonas Wanke --- packages/Chrono/instant.candy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Chrono/instant.candy b/packages/Chrono/instant.candy index c38d92f6a..54a4b0ee9 100644 --- a/packages/Chrono/instant.candy +++ b/packages/Chrono/instant.candy @@ -13,7 +13,7 @@ fromUnixDuration dur := needs (duration.is dur) Instant (tag.getValue dur) -addDuration instant dur := +add instant dur := needs (is instant) needs (duration.is dur) Instant (fixedDecimal.add (tag.getValue instant) (tag.getValue dur)) From e16f7291f63592721e8f415789c17b05ec239190 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:45:51 +0100 Subject: [PATCH 17/22] Change doc comment to normal comment --- packages/Chrono/instant.candy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Chrono/instant.candy b/packages/Chrono/instant.candy index 54a4b0ee9..9d9cd17f3 100644 --- a/packages/Chrono/instant.candy +++ b/packages/Chrono/instant.candy @@ -2,7 +2,7 @@ constants = use "..constants" duration = use "..duration" -# Storage Format: Instant (fixedDecimal of nanoseconds since the Unix Epoch) +## Storage Format: Instant (fixedDecimal of nanoseconds since the Unix Epoch) is i := i % Instant nanoseconds -> fixedDecimal.is nanoseconds _ -> False From cff2e40414a342465f20280d9ba01faad8d93380 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 19:01:15 +0100 Subject: [PATCH 18/22] improve pad functions --- packages/Core/text.candy | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/Core/text.candy b/packages/Core/text.candy index 46f9a05d9..5ca84fa49 100644 --- a/packages/Core/text.candy +++ b/packages/Core/text.candy @@ -78,7 +78,8 @@ rick := " Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye - Never gonna tell a lie and hurt you" + Never gonna tell a lie and hurt you +" fromUtf8 := builtins.textFromUtf8 @@ -126,7 +127,20 @@ firstIndexOf text char := needs (is char) needs (length char | equals 1) recursive 0 { recurse i -> - ifElse (text | length | int.isGreaterThanOrEqualTo i) {ifElse (text | characterAt i | equals char) {i} {i | int.add 1 | recurse}} {int.negate 1} + ifElse + text | length | int.isGreaterThan i + { ifElse (text | characterAt i | equals char) { i } { i | int.add 1 | recurse } } + { int.negate 1 } + } + +repeat text times := + needs (is text) + needs (int.is times) + needs (times | int.isGreaterThanOrEqualTo 1) + recursive (text, times) { recurse (repeatedText, times) -> + ifElse (times | equals 1) { repeatedText } { + (repeatedText | concatenate text, times | int.subtract 1) | recurse + } } padStart text len char := @@ -134,14 +148,16 @@ padStart text len char := needs (int.is len) needs (is char) needs (char | length | equals 1) - recursive text { recurse text -> - ifElse (text | length | int.isGreaterThanOrEqualTo len) {text} {char | concatenate text | recurse} + textLength = text | length + ifElse (textLength | int.isGreaterThanOrEqualTo len) { text } { + (char | repeat (len | int.subtract textLength)) | concatenate text } padEnd text len char := needs (is text) needs (int.is len) needs (is char) needs (char | length | equals 1) - recursive text { recurse text -> - ifElse (text | length | int.isGreaterThanOrEqualTo len) {text} {text | concatenate char | recurse} + textLength = text | length + ifElse (textLength | int.isGreaterThanOrEqualTo len) { text } { + text | concatenate (char | repeat (len | int.subtract textLength)) } From e3dbd9e598703c86ce1d814aca4ae3db5fb8f725 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Wed, 29 Nov 2023 19:29:53 +0100 Subject: [PATCH 19/22] start fractions after seconds instead of nanoseconds --- packages/Chrono/duration.candy | 33 +++++++++++++++++---------------- packages/Chrono/instant.candy | 8 ++++---- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/Chrono/duration.candy b/packages/Chrono/duration.candy index d9e8bcd3a..39a82f2df 100644 --- a/packages/Chrono/duration.candy +++ b/packages/Chrono/duration.candy @@ -1,9 +1,9 @@ [fixedDecimal, tag, check, equals, bool, ifElse, int, toDebugText, text] = use "Core" constants = use "..constants" -## Storage Format: Duration (fixedDecimal of nanoseconds) +## Storage Format: Duration (fixedDecimal of seconds) is d := d % - Duration nanoseconds -> fixedDecimal.is nanoseconds + Duration seconds -> fixedDecimal.is seconds _ -> False isNumber n = int.is n | bool.lazyOr {fixedDecimal.is n} @@ -13,50 +13,51 @@ numberAsFixedDecimal n = zero := Duration fixedDecimal.zero +## TODO: Do this without truncating division if possible fromNanoseconds nanoseconds := needs (isNumber nanoseconds) - Duration (numberAsFixedDecimal nanoseconds) + Duration (numberAsFixedDecimal nanoseconds | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerSecond)) fromMicroseconds microseconds := needs (isNumber microseconds) - Duration (numberAsFixedDecimal microseconds | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerMicrosecond)) + Duration (numberAsFixedDecimal microseconds | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.microsecondsPerSecond)) fromMilliseconds milliseconds := needs (isNumber milliseconds) - Duration (numberAsFixedDecimal milliseconds | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerMillisecond)) + Duration (numberAsFixedDecimal milliseconds | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.millisecondsPerSecond)) fromSeconds seconds := needs (isNumber seconds) - Duration (numberAsFixedDecimal seconds | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerSecond)) + Duration (numberAsFixedDecimal seconds) fromMinutes minutes := needs (isNumber minutes) - Duration (numberAsFixedDecimal minutes | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerMinute)) + Duration (numberAsFixedDecimal minutes | fixedDecimal.multiply (fixedDecimal.fromInt constants.secondsPerMinute)) fromHours hours := needs (isNumber hours) - Duration (numberAsFixedDecimal hours | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerHour)) + Duration (numberAsFixedDecimal hours | fixedDecimal.multiply (fixedDecimal.fromInt constants.secondsPerHour)) fromNormalDays days := needs (isNumber days) - Duration (numberAsFixedDecimal days | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerNormalDay)) + Duration (numberAsFixedDecimal days | fixedDecimal.multiply (fixedDecimal.fromInt constants.secondsPerNormalDay)) ## TODO: Do this without truncating division if possible totalNanoseconds duration := needs (is duration) - tag.getValue duration + tag.getValue duration | fixedDecimal.multiply (fixedDecimal.fromInt constants.nanosecondsPerSecond) totalMicroseconds duration := needs (is duration) - tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerHour) + tag.getValue duration | fixedDecimal.multiply (fixedDecimal.fromInt constants.microsecondsPerSecond) totalMilliseconds duration := needs (is duration) - tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerMillisecond) + tag.getValue duration | fixedDecimal.multiply (fixedDecimal.fromInt constants.millisecondsPerSecond) totalSeconds duration := needs (is duration) - tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerSecond) + tag.getValue duration totalMinutes duration := needs (is duration) - tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerMinute) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.secondsPerMinute) totalHours duration := needs (is duration) - tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerHour) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.secondsPerHour) totalNormalDays duration := needs (is duration) - tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.nanosecondsPerNormalDay) + tag.getValue duration | fixedDecimal.divideTruncating (fixedDecimal.fromInt constants.secondsPerNormalDay) add summandA summandB := needs (is summandA) diff --git a/packages/Chrono/instant.candy b/packages/Chrono/instant.candy index 9d9cd17f3..ac884d1ff 100644 --- a/packages/Chrono/instant.candy +++ b/packages/Chrono/instant.candy @@ -2,9 +2,9 @@ constants = use "..constants" duration = use "..duration" -## Storage Format: Instant (fixedDecimal of nanoseconds since the Unix Epoch) +## Storage Format: Instant (fixedDecimal of seconds since the Unix Epoch) is i := i % - Instant nanoseconds -> fixedDecimal.is nanoseconds + Instant seconds -> fixedDecimal.is seconds _ -> False startOfUnixEpoch := Instant fixedDecimal.zero @@ -25,7 +25,7 @@ subtract instant dur := durationBetween instantA instantB := needs (is instantA) needs (is instantB) - duration.fromNanoseconds (fixedDecimal.subtract (tag.getValue instantA) (tag.getValue instantB)) + duration.fromSeconds (fixedDecimal.subtract (tag.getValue instantA) (tag.getValue instantB)) compareTo valueA valueB := needs (is valueA) @@ -75,4 +75,4 @@ coerceIn value minimum maximum := toUnixTimeDuration instant := needs (is instant) - duration.fromNanoseconds (tag.getValue instant) + duration.fromSeconds (tag.getValue instant) From de41cb962fc1902f2dae0ec8b8a1b2cd114067dd Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:47:12 +0100 Subject: [PATCH 20/22] combine instant:subtract and instant:durationBetween --- packages/Chrono/instant.candy | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/Chrono/instant.candy b/packages/Chrono/instant.candy index ac884d1ff..f9aaa42e4 100644 --- a/packages/Chrono/instant.candy +++ b/packages/Chrono/instant.candy @@ -17,15 +17,13 @@ add instant dur := needs (is instant) needs (duration.is dur) Instant (fixedDecimal.add (tag.getValue instant) (tag.getValue dur)) -subtract instant dur := +subtract instant durationOrInstant := needs (is instant) - needs (duration.is dur) - Instant (fixedDecimal.subtract (tag.getValue instant) (tag.getValue dur)) - -durationBetween instantA instantB := - needs (is instantA) - needs (is instantB) - duration.fromSeconds (fixedDecimal.subtract (tag.getValue instantA) (tag.getValue instantB)) + needs (is durationOrInstant | bool.lazyOr { duration.is durationOrInstant }) + ifElse + (is durationOrInstant) + { duration.fromSeconds (fixedDecimal.subtract (tag.getValue instant) (tag.getValue durationOrInstant)) } + { Instant (fixedDecimal.subtract (tag.getValue instant) (tag.getValue durationOrInstant)) } compareTo valueA valueB := needs (is valueA) From e9de978305401fd2feee41abbf34a4a3d10557fb Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:52:02 +0100 Subject: [PATCH 21/22] store duration in instant instead of fixed decimal --- packages/Chrono/instant.candy | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/Chrono/instant.candy b/packages/Chrono/instant.candy index f9aaa42e4..16c573c38 100644 --- a/packages/Chrono/instant.candy +++ b/packages/Chrono/instant.candy @@ -1,34 +1,33 @@ -[fixedDecimal, tag, check, equals, bool, ifElse] = use "Core" +[tag, check, equals, bool, ifElse] = use "Core" constants = use "..constants" duration = use "..duration" -## Storage Format: Instant (fixedDecimal of seconds since the Unix Epoch) +## Storage Format: Instant (Duration since the Unix Epoch) is i := i % - Instant seconds -> fixedDecimal.is seconds + Instant dur -> duration.is dur _ -> False -startOfUnixEpoch := Instant fixedDecimal.zero +startOfUnixEpoch := Instant duration.zero fromUnixDuration dur := needs (duration.is dur) - Instant (tag.getValue dur) + Instant dur add instant dur := needs (is instant) needs (duration.is dur) - Instant (fixedDecimal.add (tag.getValue instant) (tag.getValue dur)) + Instant (duration.add (tag.getValue instant) dur) subtract instant durationOrInstant := needs (is instant) needs (is durationOrInstant | bool.lazyOr { duration.is durationOrInstant }) - ifElse - (is durationOrInstant) - { duration.fromSeconds (fixedDecimal.subtract (tag.getValue instant) (tag.getValue durationOrInstant)) } - { Instant (fixedDecimal.subtract (tag.getValue instant) (tag.getValue durationOrInstant)) } + durationOrInstant % + Instant dur -> duration.subtract (tag.getValue instant) dur + dur -> Instant (duration.subtract (tag.getValue instant) dur) compareTo valueA valueB := needs (is valueA) needs (is valueB) - result = (tag.getValue valueA) | fixedDecimal.compareTo (tag.getValue valueB) + result = (tag.getValue valueA) | duration.compareTo (tag.getValue valueB) check (equals result Equal | bool.implies (equals valueA valueB)) result isLessThan valueA valueB := From b8c127d06af9df257dd3797f6696107d4d37db9b Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak <81387843+skyz1@users.noreply.github.com> Date: Mon, 25 Dec 2023 16:14:14 +0100 Subject: [PATCH 22/22] Fix type mistake Co-authored-by: Jonas Wanke --- packages/Chrono/instant.candy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Chrono/instant.candy b/packages/Chrono/instant.candy index 16c573c38..9a948fc46 100644 --- a/packages/Chrono/instant.candy +++ b/packages/Chrono/instant.candy @@ -72,4 +72,4 @@ coerceIn value minimum maximum := toUnixTimeDuration instant := needs (is instant) - duration.fromSeconds (tag.getValue instant) + tag.getValue instant