From 03321fd713c6edaf2cb60c752ff1554c02bef31d Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 1 Feb 2024 19:38:41 +0100 Subject: [PATCH 1/6] Add Range package --- packages/Examples/range.candy | 11 ++++ packages/Range/_.candy | 103 ++++++++++++++++++++++++++++++++++ packages/Range/_package.candy | 0 packages/Range/bound.candy | 7 +++ 4 files changed, 121 insertions(+) create mode 100644 packages/Examples/range.candy create mode 100644 packages/Range/_.candy create mode 100644 packages/Range/_package.candy create mode 100644 packages/Range/bound.candy diff --git a/packages/Examples/range.candy b/packages/Examples/range.candy new file mode 100644 index 000000000..bf43ae616 --- /dev/null +++ b/packages/Examples/range.candy @@ -0,0 +1,11 @@ +range = use "Range" +[iterator] = use "Core" + +main := { environment -> + a = 1 | range.until 10 + environment.stdout a + + 1 | range.until 10 | range.iterate | iterator.forEach { a -> + environment.stdout a + } +} diff --git a/packages/Range/_.candy b/packages/Range/_.candy new file mode 100644 index 000000000..e265987e4 --- /dev/null +++ b/packages/Range/_.candy @@ -0,0 +1,103 @@ +bound = use ".bound" +[bool, ifElse, int, iterator] = use "Core" +[print] = use "Builtins" + +is range := range % + Empty -> True + All -> True + [start, end] -> bound.is start | bool.and (bound.is end) + _ -> False + +from a := + needs (int.is a) + [Start: a, End: Unbounded] +to a b := + needs (int.is a) + needs (int.is b) + [Start: Inclusive a, End: Exclusive b] +until a b := + needs (int.is a) + needs (int.is b) + [Start: Inclusive a, End: Inclusive b] + +normalize range := + needs (is range) + range % + Empty -> Empty + All -> All + [start, end] -> + if (start | int.isGreaterThanOrEqualTo end) { + Empty + } { + (start, end) % + (Unbounded, Unbounded) -> All + _ -> [start, end] + } + +contains range value := + needs (is range) + range % + Empty -> False + All -> True + [start, end] -> bool.and + start % + Unbounded -> True + Inclusive a -> value | int.isGreaterThanOrEqualTo a + Exclusive a -> value | int.isGreaterThan a + end % + Unbounded -> True + Inclusive a -> value | int.isGreaterThanOrEqualTo a + Exclusive a -> value | int.isGreaterThan a + +union a b = + needs (is a) + needs (is b) + (a, b) % + (Empty, _) -> Empty + (_, Empty) -> Empty + (All, b) -> b + (a, All) -> a + (a, b) -> [ + Start: a.start % + Unbounded -> b.start + Inclusive a -> b.start % + Unbounded -> Inclusive a + Inclusive b -> Inclusive (max a b) + Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } + Exclusive a -> b % + Unbounded -> Exclusive a + Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } + Exclusive b -> Exclusive (min a b), + End: a.end % + Unbounded -> b.end + Inclusive a -> b.end % + Unbounded -> Inclusive a + Inclusive b -> Inclusive (max a b) + Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } + Exclusive a -> b % + Unbounded -> Exclusive a + Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } + Exclusive b -> Exclusive (min a b), + ] + +iterate range := + needs (is range) + range.start % + Unbounded -> needs False "The range needs to have a bounded start." + _ -> Nothing + first = range.start % + Inclusive a -> a + Exclusive a -> a | int.add 1 + range.end % + Unbounded -> iterator.generateWithState first { next -> + More [Item: next, State: next | int.add 1] + } + bound -> + end = bound % + Inclusive a -> a | int.add 1 + Exclusive a -> a + iterator.generateWithState [Next: first, end] { state -> + ifElse (state.next | int.isGreaterThanOrEqualTo state.end) { Empty } { + More [Item: state.next, State: [Next: state.next | int.add 1, End: state.end]] + } + } diff --git a/packages/Range/_package.candy b/packages/Range/_package.candy new file mode 100644 index 000000000..e69de29bb diff --git a/packages/Range/bound.candy b/packages/Range/bound.candy new file mode 100644 index 000000000..5797806d3 --- /dev/null +++ b/packages/Range/bound.candy @@ -0,0 +1,7 @@ +[int] = use "Core" + +is bound := bound % + Unbounded -> True + Inclusive a -> int.is a + Exclusive a -> int.is a + _ -> False From 72368e05a298fde582dfeffbe3601bf2b151ecb0 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Sat, 23 Mar 2024 20:54:41 +0100 Subject: [PATCH 2/6] Implement suggestions --- packages/Range/_.candy | 48 +++++++++---------- packages/Range/bound.candy | 3 +- .../range.candy => Range/example.candy} | 2 +- 3 files changed, 24 insertions(+), 29 deletions(-) rename packages/{Examples/range.candy => Range/example.candy} (100%) diff --git a/packages/Range/_.candy b/packages/Range/_.candy index e265987e4..bff8b6dba 100644 --- a/packages/Range/_.candy +++ b/packages/Range/_.candy @@ -3,42 +3,37 @@ bound = use ".bound" [print] = use "Builtins" is range := range % - Empty -> True - All -> True - [start, end] -> bound.is start | bool.and (bound.is end) + Range range -> + range % + Empty -> True + [start, end] -> bound.is start | bool.and (bound.is end) + _ -> False _ -> False +fromBounds start end := + isEmpty = (start, end) % + (Inclusive a, Inclusive b) -> a | int.isGreaterThan b + (Inclusive a, Exclusive b) -> a | int.isGreaterThanOrEqualTo b + (Exclusive a, Inclusive b) -> a | int.isGreaterThanOrEqualTo b + (Exclusive a, Exclusive b) -> a | int.subtract b | int.absolute | int.isGreaterThanOrEqualTo 2 + ifElse isEmpty { Range Empty } { Range [start, end] } from a := needs (int.is a) - [Start: a, End: Unbounded] + fromBounds (Inclusive a) Unbounded to a b := needs (int.is a) needs (int.is b) - [Start: Inclusive a, End: Exclusive b] + fromBounds (Inclusive a) (Exclusive b) until a b := needs (int.is a) needs (int.is b) - [Start: Inclusive a, End: Inclusive b] - -normalize range := - needs (is range) - range % - Empty -> Empty - All -> All - [start, end] -> - if (start | int.isGreaterThanOrEqualTo end) { - Empty - } { - (start, end) % - (Unbounded, Unbounded) -> All - _ -> [start, end] - } + fromBounds (Inclusive a) (Inclusive b) contains range value := needs (is range) + Range range = range range % Empty -> False - All -> True [start, end] -> bool.and start % Unbounded -> True @@ -52,12 +47,12 @@ contains range value := union a b = needs (is a) needs (is b) + Range a = a + Range b = b (a, b) % - (Empty, _) -> Empty - (_, Empty) -> Empty - (All, b) -> b - (a, All) -> a - (a, b) -> [ + (Empty, _) -> Range Empty + (_, Empty) -> Range Empty + (a, b) -> Range [ Start: a.start % Unbounded -> b.start Inclusive a -> b.start % @@ -82,6 +77,7 @@ union a b = iterate range := needs (is range) + Range range = range range.start % Unbounded -> needs False "The range needs to have a bounded start." _ -> Nothing diff --git a/packages/Range/bound.candy b/packages/Range/bound.candy index 5797806d3..072a3cd93 100644 --- a/packages/Range/bound.candy +++ b/packages/Range/bound.candy @@ -2,6 +2,5 @@ is bound := bound % Unbounded -> True - Inclusive a -> int.is a - Exclusive a -> int.is a + Inclusive a | Exclusive a -> int.is a _ -> False diff --git a/packages/Examples/range.candy b/packages/Range/example.candy similarity index 100% rename from packages/Examples/range.candy rename to packages/Range/example.candy index bf43ae616..8e4aecf2f 100644 --- a/packages/Examples/range.candy +++ b/packages/Range/example.candy @@ -1,5 +1,5 @@ -range = use "Range" [iterator] = use "Core" +range = use "Range" main := { environment -> a = 1 | range.until 10 From 6e1d6cb989d5a8d03d9c99f568bf5e10936f312f Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 28 Mar 2024 21:47:53 +0100 Subject: [PATCH 3/6] Fix some things --- packages/Range/_.candy | 52 +++++++++++++++++++++--------------- packages/Range/example.candy | 5 +++- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/packages/Range/_.candy b/packages/Range/_.candy index bff8b6dba..3b7911e9a 100644 --- a/packages/Range/_.candy +++ b/packages/Range/_.candy @@ -2,21 +2,29 @@ bound = use ".bound" [bool, ifElse, int, iterator] = use "Core" [print] = use "Builtins" -is range := range % - Range range -> - range % - Empty -> True - [start, end] -> bound.is start | bool.and (bound.is end) - _ -> False - _ -> False - fromBounds start end := + needs (bound.is start) + needs (bound.is end) isEmpty = (start, end) % (Inclusive a, Inclusive b) -> a | int.isGreaterThan b (Inclusive a, Exclusive b) -> a | int.isGreaterThanOrEqualTo b + (Inclusive a, Unbounded) -> False (Exclusive a, Inclusive b) -> a | int.isGreaterThanOrEqualTo b (Exclusive a, Exclusive b) -> a | int.subtract b | int.absolute | int.isGreaterThanOrEqualTo 2 + (Exclusive a, Unbounded) -> False + (Unbounded, _) -> False ifElse isEmpty { Range Empty } { Range [start, end] } + +is range := range % + Range range -> + range % + Empty -> True + [start, end] -> bound.is start | bool.and (bound.is end) | bool.lazyAnd { + fromBounds start end | equals range + } + _ -> False + _ -> False + from a := needs (int.is a) fromBounds (Inclusive a) Unbounded @@ -41,39 +49,40 @@ contains range value := Exclusive a -> value | int.isGreaterThan a end % Unbounded -> True - Inclusive a -> value | int.isGreaterThanOrEqualTo a - Exclusive a -> value | int.isGreaterThan a + Inclusive a -> value | int.isLessThanOrEqualTo a + Exclusive a -> value | int.isLessThan a -union a b = +intersection a b = needs (is a) needs (is b) Range a = a Range b = b - (a, b) % + [start, end] = (a, b) % (Empty, _) -> Range Empty (_, Empty) -> Range Empty - (a, b) -> Range [ + (a, b) -> [ Start: a.start % Unbounded -> b.start Inclusive a -> b.start % Unbounded -> Inclusive a - Inclusive b -> Inclusive (max a b) + Inclusive b -> Inclusive (int.max a b) Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } - Exclusive a -> b % + Exclusive a -> b.start % Unbounded -> Exclusive a Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } - Exclusive b -> Exclusive (min a b), + Exclusive b -> Exclusive (int.min a b), End: a.end % Unbounded -> b.end Inclusive a -> b.end % Unbounded -> Inclusive a - Inclusive b -> Inclusive (max a b) + Inclusive b -> Inclusive (int.max a b) Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } - Exclusive a -> b % + Exclusive a -> b.end % Unbounded -> Exclusive a Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } - Exclusive b -> Exclusive (min a b), + Exclusive b -> Exclusive (int.min a b), ] + fromBounds start end iterate range := needs (is range) @@ -85,9 +94,8 @@ iterate range := Inclusive a -> a Exclusive a -> a | int.add 1 range.end % - Unbounded -> iterator.generateWithState first { next -> - More [Item: next, State: next | int.add 1] - } + Unbounded -> + iterator.generateWithState first { next -> More [Item: next, State: next | int.add 1] } bound -> end = bound % Inclusive a -> a | int.add 1 diff --git a/packages/Range/example.candy b/packages/Range/example.candy index 8e4aecf2f..4562cf999 100644 --- a/packages/Range/example.candy +++ b/packages/Range/example.candy @@ -1,6 +1,9 @@ -[iterator] = use "Core" +[checkEquals, iterator] = use "Core" range = use "Range" +checkEquals (is 2) True +checkEquals (is Foo) False + main := { environment -> a = 1 | range.until 10 environment.stdout a From 699ca3dcaaacc6a188d1ba27d4482be65b4b40fa Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Fri, 29 Mar 2024 14:44:20 +0100 Subject: [PATCH 4/6] Fix more things --- packages/Range/_.candy | 10 ++++---- packages/Range/example.candy | 49 ++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/packages/Range/_.candy b/packages/Range/_.candy index 3b7911e9a..b8a56a818 100644 --- a/packages/Range/_.candy +++ b/packages/Range/_.candy @@ -1,5 +1,5 @@ -bound = use ".bound" -[bool, ifElse, int, iterator] = use "Core" +bound := use ".bound" +[bool, equals, ifElse, int, iterator] = use "Core" [print] = use "Builtins" fromBounds start end := @@ -10,7 +10,7 @@ fromBounds start end := (Inclusive a, Exclusive b) -> a | int.isGreaterThanOrEqualTo b (Inclusive a, Unbounded) -> False (Exclusive a, Inclusive b) -> a | int.isGreaterThanOrEqualTo b - (Exclusive a, Exclusive b) -> a | int.subtract b | int.absolute | int.isGreaterThanOrEqualTo 2 + (Exclusive a, Exclusive b) -> b | int.subtract a | int.absolute | int.isLessThanOrEqualTo 1 (Exclusive a, Unbounded) -> False (Unbounded, _) -> False ifElse isEmpty { Range Empty } { Range [start, end] } @@ -20,8 +20,8 @@ is range := range % range % Empty -> True [start, end] -> bound.is start | bool.and (bound.is end) | bool.lazyAnd { - fromBounds start end | equals range - } + fromBounds start end | equals range + } _ -> False _ -> False diff --git a/packages/Range/example.candy b/packages/Range/example.candy index 4562cf999..fb7db583b 100644 --- a/packages/Range/example.candy +++ b/packages/Range/example.candy @@ -1,14 +1,53 @@ [checkEquals, iterator] = use "Core" range = use "Range" +bound = range.bound -checkEquals (is 2) True -checkEquals (is Foo) False +checkEquals (bound.is Unbounded) True +checkEquals (bound.is (Inclusive 2)) True +checkEquals (bound.is (Exclusive 3)) True +checkEquals (bound.is Foo) False + +checkEquals (range.fromBounds Unbounded Unbounded) (Range [Start: Unbounded, End: Unbounded]) +checkEquals (range.fromBounds (Inclusive 2) Unbounded) (Range [Start: Inclusive 2, End: Unbounded]) +checkEquals (range.fromBounds (Exclusive 3) Unbounded) (Range [Start: Exclusive 3, End: Unbounded]) +checkEquals (range.fromBounds Unbounded (Inclusive 1)) (Range [Start: Unbounded, End: Inclusive 1]) +checkEquals (range.fromBounds Unbounded (Exclusive 1)) (Range [Start: Unbounded, End: Exclusive 1]) +checkEquals + range.fromBounds (Inclusive 1) (Inclusive 1) + Range [Start: Inclusive 1, End: Inclusive 1] +checkEquals (range.fromBounds (Inclusive 1) (Inclusive 0)) (Range Empty) +checkEquals (range.fromBounds (Inclusive 1) (Exclusive 1)) (Range Empty) +checkEquals + range.fromBounds (Inclusive 1) (Exclusive 2) + Range [Start: Inclusive 1, End: Exclusive 2] +checkEquals (range.fromBounds (Exclusive 1) (Inclusive 1)) (Range Empty) +checkEquals (range.fromBounds (Exclusive 1) (Exclusive 1)) (Range Empty) +checkEquals + range.fromBounds (Exclusive 1) (Exclusive 3) + Range [Start: Exclusive 1, End: Exclusive 3] +checkEquals + range.fromBounds (Exclusive 1) (Inclusive 4) + Range [Start: Exclusive 1, End: Inclusive 4] + +checkEquals (range.is (Range Empty)) True +checkEquals (range.is (Range [Start: Inclusive 1, End: Inclusive 2])) True + +checkEquals (range.contains (Range [Start: Inclusive 1, End: Inclusive 2]) 2) True +checkEquals (range.contains (Range [Start: Inclusive 1, End: Exclusive 2]) 2) False +checkEquals (range.contains (Range [Start: Inclusive 1, End: Inclusive 2]) 3) False +checkEquals (range.contains (Range [Start: Inclusive 1, End: Inclusive 2]) 1) True +checkEquals (range.contains (Range [Start: Inclusive 2, End: Inclusive 2]) 1) False +checkEquals (range.contains (Range [Start: Exclusive 1, End: Inclusive 2]) 1) False + +checkEquals + range.intersection + Range [Start: Inclusive 1, End: Inclusive 5] + Range [Start: Inclusive 3, End: Inclusive 8] + Range [Start: Inclusive 3, End: Inclusive 5] main := { environment -> a = 1 | range.until 10 environment.stdout a - 1 | range.until 10 | range.iterate | iterator.forEach { a -> - environment.stdout a - } + 1 | range.until 10 | range.iterate | iterator.forEach { a -> environment.stdout a } } From c412fc9333d8e1b61102ffd9d9fe44b6d3d51263 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 4 Apr 2024 18:15:02 +0200 Subject: [PATCH 5/6] Fix code --- packages/Range/_.candy | 81 +++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/packages/Range/_.candy b/packages/Range/_.candy index b8a56a818..689b8121a 100644 --- a/packages/Range/_.candy +++ b/packages/Range/_.candy @@ -6,13 +6,12 @@ fromBounds start end := needs (bound.is start) needs (bound.is end) isEmpty = (start, end) % + (Unbounded, _) -> False + (_, Unbounded) -> False (Inclusive a, Inclusive b) -> a | int.isGreaterThan b (Inclusive a, Exclusive b) -> a | int.isGreaterThanOrEqualTo b - (Inclusive a, Unbounded) -> False (Exclusive a, Inclusive b) -> a | int.isGreaterThanOrEqualTo b (Exclusive a, Exclusive b) -> b | int.subtract a | int.absolute | int.isLessThanOrEqualTo 1 - (Exclusive a, Unbounded) -> False - (Unbounded, _) -> False ifElse isEmpty { Range Empty } { Range [start, end] } is range := range % @@ -20,7 +19,7 @@ is range := range % range % Empty -> True [start, end] -> bound.is start | bool.and (bound.is end) | bool.lazyAnd { - fromBounds start end | equals range + fromBounds start end | equals (Range range) } _ -> False _ -> False @@ -42,47 +41,47 @@ contains range value := Range range = range range % Empty -> False - [start, end] -> bool.and - start % - Unbounded -> True - Inclusive a -> value | int.isGreaterThanOrEqualTo a - Exclusive a -> value | int.isGreaterThan a - end % - Unbounded -> True - Inclusive a -> value | int.isLessThanOrEqualTo a - Exclusive a -> value | int.isLessThan a + [start, end] -> + bool.and + start % + Unbounded -> True + Inclusive a -> value | int.isGreaterThanOrEqualTo a + Exclusive a -> value | int.isGreaterThan a + end % + Unbounded -> True + Inclusive a -> value | int.isLessThanOrEqualTo a + Exclusive a -> value | int.isLessThan a -intersection a b = +intersection a b := needs (is a) needs (is b) Range a = a Range b = b - [start, end] = (a, b) % + (a, b) % (Empty, _) -> Range Empty (_, Empty) -> Range Empty - (a, b) -> [ - Start: a.start % - Unbounded -> b.start - Inclusive a -> b.start % - Unbounded -> Inclusive a - Inclusive b -> Inclusive (int.max a b) - Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } - Exclusive a -> b.start % - Unbounded -> Exclusive a - Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } - Exclusive b -> Exclusive (int.min a b), - End: a.end % - Unbounded -> b.end - Inclusive a -> b.end % - Unbounded -> Inclusive a - Inclusive b -> Inclusive (int.max a b) - Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } - Exclusive a -> b.end % - Unbounded -> Exclusive a - Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } - Exclusive b -> Exclusive (int.min a b), - ] - fromBounds start end + (a, b) -> + fromBounds + a.start % + Unbounded -> b.start + Inclusive a -> b.start % + Unbounded -> Inclusive a + Inclusive b -> Inclusive (int.max a b) + Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } + Exclusive a -> b.start % + Unbounded -> Exclusive a + Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } + Exclusive b -> Exclusive (int.max a b), + a.end % + Unbounded -> b.end + Inclusive a -> b.end % + Unbounded -> Inclusive a + Inclusive b -> Inclusive (int.min a b) + Exclusive b -> if (a | int.isGreaterThanOrEqualTo b) { Inclusive a } { Exclusive b } + Exclusive a -> b.end % + Unbounded -> Exclusive a + Inclusive b -> if (b | int.isGreaterThan a) { Inclusive a } { Exclusive b } + Exclusive b -> Exclusive (int.min a b), iterate range := needs (is range) @@ -100,8 +99,8 @@ iterate range := end = bound % Inclusive a -> a | int.add 1 Exclusive a -> a - iterator.generateWithState [Next: first, end] { state -> - ifElse (state.next | int.isGreaterThanOrEqualTo state.end) { Empty } { - More [Item: state.next, State: [Next: state.next | int.add 1, End: state.end]] + iterator.generateWithState first { next -> + ifElse (next | int.isGreaterThanOrEqualTo end) { Empty } { + More [Item: next, State: next | int.add 1] } } From 448a5f740683a723cba1f6cfb865e51e7e44c866 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 4 Apr 2024 19:04:12 +0200 Subject: [PATCH 6/6] Apply suggestions --- packages/Range/_.candy | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/Range/_.candy b/packages/Range/_.candy index 689b8121a..31cfbd6a5 100644 --- a/packages/Range/_.candy +++ b/packages/Range/_.candy @@ -6,12 +6,11 @@ fromBounds start end := needs (bound.is start) needs (bound.is end) isEmpty = (start, end) % - (Unbounded, _) -> False - (_, Unbounded) -> False + (Unbounded, _) | (_, Unbounded) -> False (Inclusive a, Inclusive b) -> a | int.isGreaterThan b (Inclusive a, Exclusive b) -> a | int.isGreaterThanOrEqualTo b (Exclusive a, Inclusive b) -> a | int.isGreaterThanOrEqualTo b - (Exclusive a, Exclusive b) -> b | int.subtract a | int.absolute | int.isLessThanOrEqualTo 1 + (Exclusive a, Exclusive b) -> b | int.subtract a | int.isLessThanOrEqualTo 1 ifElse isEmpty { Range Empty } { Range [start, end] } is range := range % @@ -58,8 +57,7 @@ intersection a b := Range a = a Range b = b (a, b) % - (Empty, _) -> Range Empty - (_, Empty) -> Range Empty + (Empty, _) | (_, Empty) -> Range Empty (a, b) -> fromBounds a.start %