aboutsummaryrefslogtreecommitdiff
path: root/core/collections.nom
blob: 18b1af6581f45f09cf55625e51121d4a7ae6a4c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env nomsu -V6.14
#
    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 $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