2018-11-19 17:37:37 -08:00
|
|
|
#!/usr/bin/env nomsu -V4.11.12.8
|
2018-05-15 18:55:55 -07:00
|
|
|
#
|
2018-01-11 18:51:21 -08:00
|
|
|
This file contains code that supports manipulating and using collections like lists
|
|
|
|
and dictionaries.
|
2018-11-11 15:50:46 -08:00
|
|
|
|
2018-02-02 15:48:28 -08:00
|
|
|
use "core/metaprogramming.nom"
|
|
|
|
use "core/control_flow.nom"
|
|
|
|
use "core/operators.nom"
|
2017-09-21 00:10:26 -07:00
|
|
|
|
2018-11-08 15:23:22 -08:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2018-08-29 19:38:14 -07:00
|
|
|
# List functionality:
|
2018-07-17 23:08:13 -07:00
|
|
|
test:
|
2018-07-18 01:27:56 -07:00
|
|
|
%list = [1, 2, 3, 4, 5]
|
2018-08-29 19:38:14 -07:00
|
|
|
%visited = {}
|
2018-08-30 14:16:09 -07:00
|
|
|
for %i = %x in %list:
|
|
|
|
%visited.%i = (yes)
|
2018-11-11 16:45:48 -08:00
|
|
|
assume (%visited == {1, 2, 3, 4, 5})
|
2018-08-29 19:38:14 -07:00
|
|
|
%visited = {}
|
2018-08-30 14:16:09 -07:00
|
|
|
for %x in %list:
|
|
|
|
%visited.%x = (yes)
|
2018-11-11 16:45:48 -08:00
|
|
|
assume (%visited == {1, 2, 3, 4, 5})
|
2018-08-29 19:38:14 -07:00
|
|
|
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)
|
2018-08-29 16:05:14 -07:00
|
|
|
%list::add 6
|
2018-08-29 19:38:14 -07:00
|
|
|
assume ((%list::last) == 6)
|
2018-08-29 15:59:30 -07:00
|
|
|
%list::pop
|
2018-08-29 19:38:14 -07:00
|
|
|
assume ((%list::last) == 5)
|
2018-08-29 15:59:30 -07:00
|
|
|
%list::remove index 1
|
2018-08-29 19:38:14 -07:00
|
|
|
assume ((%list::first) == 2)
|
2018-08-30 14:26:32 -07:00
|
|
|
assume (([1, 2] + [3, 4]) == [1, 2, 3, 4])
|
2017-09-21 21:11:13 -07:00
|
|
|
|
2018-08-29 19:38:14 -07:00
|
|
|
# Dict functionality
|
|
|
|
test:
|
2018-11-11 15:50:46 -08:00
|
|
|
%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}
|
2018-07-10 15:00:01 -07:00
|
|
|
|
2018-07-20 20:27:15 -07:00
|
|
|
test:
|
|
|
|
assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4])
|
2018-11-11 15:50:46 -08:00
|
|
|
|
2018-10-30 23:42:04 -07:00
|
|
|
externally (%lists flattened) means:
|
2018-07-18 01:27:56 -07:00
|
|
|
%flat = []
|
2018-11-11 15:50:46 -08:00
|
|
|
for %item in recursive %lists:
|
|
|
|
if (%item is a "List"):
|
|
|
|
for % in %item:
|
|
|
|
recurse %item on %
|
|
|
|
..else:
|
|
|
|
%flat::add %item
|
2018-06-18 15:44:29 -07:00
|
|
|
return %flat
|
|
|
|
|
2018-07-20 20:27:15 -07:00
|
|
|
test:
|
2018-11-11 15:50:46 -08:00
|
|
|
assume ((entries in {x: 1}) == [{key: "x", value: 1}])
|
2018-07-30 15:05:41 -07:00
|
|
|
|
2018-11-11 15:50:46 -08:00
|
|
|
(entries in %dict) parses as [: for %k = %v in %dict: add {key: %k, value: %v}]
|
2018-07-20 20:27:15 -07:00
|
|
|
test:
|
2018-11-11 15:50:46 -08:00
|
|
|
assume ((keys in {x: 1}) == ["x"])
|
|
|
|
[keys in %dict, keys of %dict] all parse as [: for %k = %v in %dict: add %k]
|
2018-07-20 20:27:15 -07:00
|
|
|
test:
|
2018-11-11 15:50:46 -08:00
|
|
|
assume ((values in {x: 1}) == [1])
|
|
|
|
[values in %dict, values of %dict] all parse as [: for %k = %v in %dict: add %v]
|
2018-01-26 20:20:12 -08:00
|
|
|
|
2018-05-27 18:28:23 -07:00
|
|
|
# Metatable stuff
|
2018-07-17 23:08:13 -07:00
|
|
|
test:
|
2018-07-18 01:27:56 -07:00
|
|
|
%t = {}
|
2018-11-17 14:38:05 -08:00
|
|
|
set %t's metatable to {__tostring: % -> "XXX"}
|
2018-07-18 01:27:56 -07:00
|
|
|
assume ("\%t" == "XXX")
|
2018-10-30 23:42:04 -07:00
|
|
|
|
2018-11-11 15:50:46 -08:00
|
|
|
(set %dict's metatable to %metatable) compiles to "\
|
|
|
|
..setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
|
2018-06-18 15:44:29 -07:00
|
|
|
|
2018-11-11 15:50:46 -08:00
|
|
|
[%'s metatable, %'metatable] all compile to "getmetatable(\(% as lua expr))"
|
2018-07-20 20:27:15 -07:00
|
|
|
test:
|
|
|
|
assume (({} with fallback % -> (% + 1)).10 == 11)
|
2018-11-11 15:50:46 -08:00
|
|
|
|
2018-11-09 14:36:15 -08:00
|
|
|
(%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))"
|
2018-05-27 18:28:23 -07:00
|
|
|
|
2018-04-25 16:30:49 -07:00
|
|
|
# Sorting
|
2018-07-17 23:08:13 -07:00
|
|
|
test:
|
2018-07-18 01:27:56 -07:00
|
|
|
%x = [3, 1, 2]
|
2018-07-11 14:13:43 -07:00
|
|
|
sort %x
|
2018-07-18 01:27:56 -07:00
|
|
|
assume (%x == [1, 2, 3])
|
2018-07-17 23:08:13 -07:00
|
|
|
sort %x by % = (- %)
|
2018-07-18 01:27:56 -07:00
|
|
|
assume (%x == [3, 2, 1])
|
2018-11-11 15:50:46 -08:00
|
|
|
%keys = {1: 999, 2: 0, 3: 50}
|
2018-07-11 14:13:43 -07:00
|
|
|
sort %x by % = %keys.%
|
2018-07-18 01:27:56 -07:00
|
|
|
assume (%x == [2, 3, 1])
|
2018-11-09 14:36:15 -08:00
|
|
|
(sort %items) compiles to "table.sort(\(%items as lua expr));"
|
2018-11-11 15:50:46 -08:00
|
|
|
[sort %items by %item = %key_expr, sort %items by %item -> %key_expr] \
|
2018-10-30 23:42:04 -07:00
|
|
|
..all parse as (..)
|
2018-07-17 23:08:13 -07:00
|
|
|
do:
|
2018-07-18 01:27:56 -07:00
|
|
|
%keys = ({} with fallback %item -> %key_expr)
|
2018-06-18 15:44:29 -07:00
|
|
|
lua> "table.sort(\%items, function(x,y) return \%keys[x] < \%keys[y] end)"
|
|
|
|
|
2018-07-17 23:08:13 -07:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2018-06-18 15:44:29 -07:00
|
|
|
|
2018-07-20 20:27:15 -07:00
|
|
|
test:
|
|
|
|
assume ((sorted [3, 1, 2]) == [1, 2, 3])
|
2018-11-11 15:50:46 -08:00
|
|
|
|
2018-10-30 23:42:04 -07:00
|
|
|
externally [%items sorted, sorted %items] all mean:
|
2018-11-11 15:50:46 -08:00
|
|
|
%copy = [: for % in %items: add %]
|
2018-06-18 15:44:29 -07:00
|
|
|
sort %copy
|
|
|
|
return %copy
|
2018-07-17 23:08:13 -07:00
|
|
|
|
2018-10-30 23:42:04 -07:00
|
|
|
[%items sorted by %item = %key, %items sorted by %item -> %key] all parse as (..)
|
2018-07-17 23:08:13 -07:00
|
|
|
result of:
|
2018-11-11 15:50:46 -08:00
|
|
|
%copy = [: for % in %items: add %]
|
2018-06-23 00:57:31 -07:00
|
|
|
sort %copy by %item = %key
|
|
|
|
return %copy
|
2018-06-18 15:44:29 -07:00
|
|
|
|
2018-07-20 20:27:15 -07:00
|
|
|
test:
|
|
|
|
assume ((unique [1, 2, 1, 3, 2, 3]) == [1, 2, 3])
|
2018-11-11 15:50:46 -08:00
|
|
|
|
2018-10-30 23:42:04 -07:00
|
|
|
externally (unique %items) means:
|
2018-07-18 01:27:56 -07:00
|
|
|
%unique = []
|
|
|
|
%seen = {}
|
2018-07-20 20:27:15 -07:00
|
|
|
for % in %items:
|
|
|
|
unless %seen.%:
|
2018-08-29 15:59:30 -07:00
|
|
|
%unique::add %
|
2018-07-20 20:27:15 -07:00
|
|
|
%seen.% = (yes)
|
2018-07-22 15:01:05 -07:00
|
|
|
return %unique
|