From 8a01efc4e0c41beeeb27aaa87948877bb44b2529 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 2 Feb 2019 19:44:41 -0800 Subject: [PATCH] Added Range (1 to 3) and a bunch of tests for inverse dicts. --- lib/core/collections.nom | 100 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/lib/core/collections.nom b/lib/core/collections.nom index dbe6900..9741faa 100644 --- a/lib/core/collections.nom +++ b/lib/core/collections.nom @@ -40,10 +40,42 @@ test: assume [: for $k = $v in {.x = 1}: add {.key = $k, .value = $v}] == [{.key = "x", .value = 1}] assume ({.x = 1, .y = 1} + {.y = 10, .z = 10}) == {.x = 1, .y = 11, .z = 10} + assume ({.x = 1, .y = 1} - {.y = 10, .z = 10}) == {.x = 1, .y = -9, .z = -10} assume ({.x = 1, .y = 1} | {.y = 10, .z = 10}) == {.x = 1, .y = 1, .z = 10} assume ({.x = 1, .y = 1} & {.y = 10, .z = 10}) == {.y = 1} assume ({.x = 1, .y = 1} ~ {.y = 10, .z = 10}) == {.x = 1, .z = 10} + # Set compliments: + assume (~{.x}).y + assume ((~{.x}).x == (nil)) + $sc = (~{.x, .y}) + $sc.y = 99 + + # For now, whether $sc.y == 99 or $sc.y == (yes) is unspecified, + (but the actual behavior is (yes)) + assume ($sc.y and (not $sc.x)) + assume ($sc == ((~{.x, .y}) | {.y = 99})) + + # Both sets: + assume (({.x, .y} & {.y, .z}) == {.y}) + assume (({.x, .y} | {.y, .z}) == {.x, .y, .z}) + assume (({.x, .y} ~ {.y, .z}) == {.z, .x}) + + # Mixed: + assume (({.x, .y} & (~{.y, .z})) == {.x}) + assume (({.x, .y} | (~{.y, .z})) == (~{.z})) + assume (({.x, .y} ~ (~{.y, .z})) == (~{.x})) + + # Mixed reversed: + assume (((~{.y, .z}) & {.x, .y}) == {.x}) + assume (((~{.y, .z}) | {.x, .y}) == (~{.z})) + assume (((~{.y, .z}) ~ {.x, .y}) == (~{.x})) + + # Both set compliments: + assume (((~{.x, .y}) & (~{.y, .z})) == (~{.x, .y, .z})) + assume (((~{.x, .y}) | (~{.y, .z})) == (~{.y})) + assume (((~{.x, .y}) ~ (~{.y, .z})) == {.x, .z}) + test: assume ((entries in {.x = 1}) == [{.key = "x", .value = 1}]) @@ -131,3 +163,71 @@ external: $unique, add $ $seen.$ = (yes) return $unique + +# Ranges: +test: + $r = (3 to 5) + assume ($r.2 == 4) + assume ($r is "a Range") + assume ((1 to 10, backwards) == (10 to 1 by -1)) + assume ((#(1 to 10 by 2)) == 5) + $visited = [] + for $ in (1 to 10 by 2): + $visited, add $ + assume ($visited == [1, 3, 5, 7, 9]) + $r = (1 to 10 by 2) + $visited = [] + for $ in $r: + $visited, add $ + assume ($visited == [1, 3, 5, 7, 9]) +$(inext) = (=lua "ipairs({})") +$range_mt = { + .__type = "a Range" + .__index = + for ($self's $key): + if ($key is "a Number"): + if (($key % 1) != 0): + return (nil) + $i = ($self.first + ($key - 1) * $self.step) + if ($self.step > 0): + if ($i > $self.last): + return (nil) + ..else: + if ($i < $self.last): + return (nil) + return $i + return $range_mt.$key + + .__len = + for $self: + $len = (($self.last - $self.first) / $self.step + 1) + if ($len < 0): + $len = 0 + return ($len, rounded down) + + .__eq = + for ($self == $other) + (($self's metatable) == ($other's metatable)) and + ($self.first == $other.first) and + ($self.last == $other.last) and ($self.step == $other.step) + + .backwards = (for $self ($self.last to $self.first by (- $self.step))) + .__ipairs = (for $self: return $(inext) $self 0) + .as_text = + for $self: + if ($self.step == 1): + return "(\($self.first) to \($self.last))" + ..else: + return "(\($self.first) to \($self.last) by \($self.step))" +} +$range_mt.reversed = $range_mt.backwards +$range_mt.__unm = $range_mt.backwards +$range_mt.__tostring = $range_mt.as_text +$range_mt.as_nomsu = $range_mt.as_text +set $range_mt's metatable to (nil) +external: + ($first to $last by $step) means + setmetatable {.first = $first, .last = $last, .step = $step} $range_mt + + ($first to $last) means + setmetatable {.first = $first, .last = $last, .step = 1} $range_mt