#!/usr/bin/env nomsu -V5.12.12.8 # This file contains code that supports manipulating and using collections like lists and dictionaries. use "core/metaprogramming.nom" use "core/control_flow.nom" use "core/operators.nom" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 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 $ in {x: 1}: add $] == [{key: "x", value: 1}] 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