aboutsummaryrefslogtreecommitdiff
path: root/lib/core/collections.nom
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-01-14 15:42:48 -0800
committerBruce Hill <bruce@bruce-hill.com>2019-01-14 15:43:24 -0800
commitc1c32688a4afc43f6addb99b8b5fa878944a70e3 (patch)
treec886f21b5b08a9053aa74fcba4b241dae5ede76d /lib/core/collections.nom
parent2309b696fc34b24f05f6658b94f9105ca8ee76e4 (diff)
Overhaul in progress, mostly working. Moved all the nomsu packages into
lib/, including core/*. Changes to how nomsu environments and importing work.
Diffstat (limited to 'lib/core/collections.nom')
-rw-r--r--lib/core/collections.nom145
1 files changed, 145 insertions, 0 deletions
diff --git a/lib/core/collections.nom b/lib/core/collections.nom
new file mode 100644
index 0000000..4cf54cd
--- /dev/null
+++ b/lib/core/collections.nom
@@ -0,0 +1,145 @@
+#!/usr/bin/env nomsu -V6.14
+#
+ This file contains code that supports manipulating and using collections like lists
+ and dictionaries.
+
+use "core/metaprogramming"
+use "core/control_flow"
+use "core/operators"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# List functionality:
+test:
+ $list = [1, 2, 3, 4, 5]
+ $visited = {}
+ for $i = $x in $list:
+ $visited.$i = (yes)
+ assume ($visited == {.1, .2, .3, .4, .5})
+ $visited = {}
+ for $x in $list:
+ $visited.$x = (yes)
+ assume ($visited == {.1, .2, .3, .4, .5})
+ assume (($list, 2 nd to last) == 4)
+ assume (($list, first) == 1)
+ assume ($list, has 3)
+ assume (($list, index of 3) == 3)
+ assume ((size of $list) == 5)
+ $list, add 6
+ assume (($list, last) == 6)
+ $list, pop
+ assume (($list, last) == 5)
+ $list, remove index 1
+ assume (($list, first) == 2)
+ assume (([1, 2] + [3, 4]) == [1, 2, 3, 4])
+
+# Dict functionality
+test:
+ $dict = {.x = 1, .y = 2, .z = 3}
+ assume (size of $dict) == 3
+ 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 = 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}
+
+test:
+ assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4])
+
+externally ($lists flattened) means:
+ $flat = []
+ for $item in recursive $lists:
+ if ($item is a "List"):
+ for $ in $item:
+ recurse $item on $
+ ..else:
+ $flat, add $item
+ return $flat
+
+test:
+ assume ((entries in {.x = 1}) == [{.key = "x", .value = 1}])
+
+(entries in $dict) parses as [
+ : for $k = $v in $dict:
+ add {.key = $k, .value = $v}
+]
+
+test:
+ assume ((keys in {.x = 1}) == ["x"])
+
+[keys in $dict, keys of $dict] all parse as [: for $k = $v in $dict: add $k]
+test:
+ assume ((values in {.x = 1}) == [1])
+[values in $dict, values of $dict] all parse as [: for $k = $v in $dict: add $v]
+
+# Metatable stuff
+test:
+ $t = {}
+ set $t's metatable to {.__tostring = ($ -> "XXX")}
+ assume ("\$t" == "XXX")
+
+(set $dict's metatable to $metatable) compiles to
+ "setmetatable(\($dict as lua expr), \($metatable as lua expr));"
+
+[$'s metatable, $'metatable] all compile to "getmetatable(\($ as lua expr))"
+test:
+ assume (({} with fallback $ -> ($ + 1)).10 == 11)
+
+($dict with fallback $key -> $value) compiles to ("
+ (function(d)
+ local mt = {}
+ for k,v in pairs(getmetatable(d) or {}) do mt[k] = v end
+ mt.__index = function(self, \($key as lua expr))
+ local value = \($value as lua expr)
+ self[\($key as lua expr)] = value
+ return value
+ end
+ return setmetatable(d, mt)
+ end)(\($dict as lua expr))
+")
+
+# Sorting
+test:
+ $x = [3, 1, 2]
+ sort $x
+ assume ($x == [1, 2, 3])
+ sort $x by $ = (- $)
+ assume ($x == [3, 2, 1])
+ $keys = {.1 = 999, .2 = 0, .3 = 50}
+ sort $x by $ = $keys.$
+ assume ($x == [2, 3, 1])
+(sort $items) compiles to "table.sort(\($items as lua expr));"
+[sort $items by $item = $key_expr, sort $items by $item -> $key_expr]
+..all parse as
+ do:
+ $keys = ({} with fallback $item -> $key_expr)
+ lua> "table.sort(\$items, function(x,y) return \$keys[x] < \$keys[y] end)"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+test:
+ assume ((sorted [3, 1, 2]) == [1, 2, 3])
+
+externally [$items sorted, sorted $items] all mean:
+ $copy = [: for $ in $items: add $]
+ sort $copy
+ return $copy
+
+[$items sorted by $item = $key, $items sorted by $item -> $key] all parse as
+ result of:
+ $copy = [: for $ in $items: add $]
+ sort $copy by $item = $key
+ return $copy
+
+test:
+ assume ((unique [1, 2, 1, 3, 2, 3]) == [1, 2, 3])
+
+externally (unique $items) means:
+ $unique = []
+ $seen = {}
+ for $ in $items:
+ unless $seen.$:
+ $unique, add $
+ $seen.$ = (yes)
+ return $unique