210 lines
6.2 KiB
Plaintext
210 lines
6.2 KiB
Plaintext
#!/usr/bin/env nomsu -V3.7.5.6
|
|
#
|
|
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:yes, 2:yes, 3:yes, 4:yes, 5:yes})
|
|
%visited = {}
|
|
for %x in %list:
|
|
%visited.%x = (yes)
|
|
assume (%visited == {1:yes, 2:yes, 3:yes, 4:yes, 5:yes})
|
|
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)
|
|
|
|
# Dict functionality
|
|
test:
|
|
%dict = {x:1, y:2, z:3}
|
|
assume ((size of %dict) == 3)
|
|
assume ((% for % in {x:1}) == [{key:"x", value:1}])
|
|
assume (({key:%k, value:%v} for %k = %v in {x:1}) == [{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})
|
|
|
|
# List Comprehension
|
|
test:
|
|
assume (((% * %) for % in [1, 2, 3]) == [1, 4, 9])
|
|
parse [%expression for %item in %iterable] as (..)
|
|
result of:
|
|
%comprehension = []
|
|
for %item in %iterable:
|
|
%comprehension::add %expression
|
|
return %comprehension
|
|
|
|
parse [..]
|
|
%expression for %index in %start to %stop via %step
|
|
%expression for %index in %start to %stop by %step
|
|
..as (..)
|
|
result of:
|
|
%comprehension = []
|
|
for %index in %start to %stop via %step:
|
|
%comprehension::add %expression
|
|
return %comprehension
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
test:
|
|
assume (((% * %) for % in 1 to 3) == [1, 4, 9])
|
|
parse [%expression for %var in %start to %stop] as (..)
|
|
%expression for %var in %start to %stop via 1
|
|
|
|
test:
|
|
assume (("\%k,\%v" for %k = %v in {x:1}) == ["x,1"])
|
|
parse [..]
|
|
%expression for %key = %value in %iterable
|
|
%expression for %key %value in %iterable
|
|
..as (..)
|
|
result of:
|
|
%comprehension = []
|
|
for %key = %value in %iterable:
|
|
%comprehension::add %expression
|
|
return %comprehension
|
|
|
|
# Dict comprehensions
|
|
test:
|
|
assume (((% * %) = % for % in [1, 2, 3]) == {1:1, 4:2, 9:3})
|
|
parse [%key = %value for %item in %iterable, %key %value for %item in %iterable] as
|
|
..(..)
|
|
result of:
|
|
%comprehension = {}
|
|
for %item in %iterable:
|
|
%comprehension.%key = %value
|
|
return %comprehension
|
|
|
|
test:
|
|
assume ((%k = (%v * %v) for %k = %v in {x:1, y:2, z:3}) == {x:1, y:4, z:9})
|
|
parse [..]
|
|
%key = %value for %src_key = %src_value in %iterable
|
|
%key %value for %src_key %src_value in %iterable
|
|
..as (..)
|
|
result of:
|
|
%comprehension = {}
|
|
for %src_key = %src_value in %iterable:
|
|
%comprehension.%key = %value
|
|
return %comprehension
|
|
|
|
parse [..]
|
|
%key = %value for %item in %start to %stop via %step
|
|
%key %value for %item in %start to %stop via %step
|
|
..as (..)
|
|
result of:
|
|
%comprehension = {}
|
|
for %item in %start to %stop via %step:
|
|
%comprehension.%key = %value
|
|
return %comprehension
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
test:
|
|
assume (((% * %) = % for % in 1 to 3) == {1:1, 4:2, 9:3})
|
|
parse [..]
|
|
%key = %value for %item in %start to %stop
|
|
%key %value for %item in %start to %stop
|
|
..as (%key = %value for %item in %start to %stop via 1)
|
|
|
|
test:
|
|
assume (([[1, 2], [3, 4]] flattened) == [1, 2, 3, 4])
|
|
action [%lists flattened]:
|
|
%flat = []
|
|
for %list in %lists:
|
|
for %item in %list: %flat::add %item
|
|
return %flat
|
|
|
|
test:
|
|
assume ((entries in {x:1}) == [{key:"x", value:1}])
|
|
parse [entries in %dict] as ({key:%k, value:%v} for %k = %v in %dict)
|
|
|
|
test:
|
|
assume ((keys in {x:1}) == ["x"])
|
|
parse [keys in %dict, keys of %dict] as (%k for %k = %v in %dict)
|
|
|
|
test:
|
|
assume ((values in {x:1}) == [1])
|
|
parse [values in %dict, values of %dict] as (%v for %k = %v in %dict)
|
|
|
|
# Metatable stuff
|
|
test:
|
|
%t = {}
|
|
set %t 's metatable to {__tostring:[%] -> "XXX"}
|
|
assume ("\%t" == "XXX")
|
|
compile [set %dict 's metatable to %metatable] to (..)
|
|
Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
|
|
|
|
test:
|
|
assume (({} with fallback % -> (% + 1)).10 == 11)
|
|
compile [%dict with fallback %key -> %value] to (..)
|
|
Lua value ".."
|
|
(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])
|
|
compile [sort %items] to (Lua "table.sort(\(%items as lua expr));")
|
|
parse [sort %items by %item = %key_expr, sort %items by %item -> %key_expr] 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])
|
|
action [%items sorted, sorted %items]:
|
|
%copy = (% for % in %items)
|
|
sort %copy
|
|
return %copy
|
|
|
|
parse [%items sorted by %item = %key, %items sorted by %item -> %key] as (..)
|
|
result of:
|
|
%copy = (% for % in %items)
|
|
sort %copy by %item = %key
|
|
return %copy
|
|
|
|
test:
|
|
assume ((unique [1, 2, 1, 3, 2, 3]) == [1, 2, 3])
|
|
action [unique %items]:
|
|
%unique = []
|
|
%seen = {}
|
|
for % in %items:
|
|
unless %seen.%:
|
|
%unique::add %
|
|
%seen.% = (yes)
|
|
|
|
return %unique
|