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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
#..
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/dict functions:
# Indexing
immediately:
compile [..]
%index st to last in %list, %index nd to last in %list, %index rd to last in %list
%index th to last in %list
..to: Lua value "utils.nth_to_last(\(%list as lua expr), \(%index as lua expr))"
immediately:
parse [first in %list, first %list] as: 1 st in %list
parse [last in %list, last %list] as: 1 st to last in %list
# Membership testing
immediately:
action [%item is in %list, %list contains %item, %list has %item]
for %key = %value in %list
if (%key is %item): return (yes)
return (no)
action [..]
%item isn't in %list, %item is not in %list
%list doesn't contain %item, %list does not contain %item
%list doesn't have %item, %list does not have %item
..:
for %key = %value in %list
if (%key is %item): return (no)
return (yes)
immediately:
# Note: it's important to have the space after "[" to prevent confusion if %index is a string
compile [%list has key %index, %list has index %index] to
Lua value ".."
((\(%list as lua expr))[ \(%index as lua expr)] ~= nil)
# Note: it's important to have the space after "[" to prevent confusion if %index is a string
compile [..]
%list doesn't have key %index, %list does not have key %index
%list doesn't have index %index, %list does not have index %index
..to: Lua value "((\(%list as lua expr))[ \(%index as lua expr)] == nil)"
compile [number of keys in %list] to:
Lua value "utils.size(\(%list as lua expr))"
compile [append %item to %list, add %item to %list, to %list add %item, to %list append %item] to:
Lua "table.insert(\(%list as lua expr), \(%item as lua expr))"
compile [pop from %list, remove last from %list] to:
Lua "table.remove(\(%list as lua expr))"
compile [remove index %index from %list] to:
Lua "table.remove(\(%list as lua expr), \(%index as lua expr))"
# List Comprehension
immediately:
compile [%expression for %item in %iterable] to:
assume (%item.type is "Var") or barf ".."
List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item.type)
return
Lua value ".."
(function()
local comprehension = {};
for i,\(%item as lua expr) in ipairs(\(%iterable as lua expr)) do
comprehension[i] = \(%expression as lua expr);
end
return comprehension;
end)()
parse [%expression for all %iterable] as: %expression for % in %iterable
compile [..]
%expression for %index from %start to %stop via %step
%expression for %index from %start to %stop by %step
..to:
assume (%index.type is "Var") or barf ".."
List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%index.type)
return
Lua value ".."
(function()
local comprehension = {};
for \(%index as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(%step as lua expr) do
comprehension[#comprehension+1] = \(%expression as lua expr);
end
return comprehension;
end)()
parse [%expression for all ] as: %expression for % in %iterable
parse [%expression for %var from %start to %stop] as: %expression for %var from %start to %stop via 1
parse [..]
%expression for all %start to %stop by %step
%expression for all %start to %stop via %step
..as: %expression for % from %start to %stop via %step
parse [%expression for all %start to %stop] as: %expression for all %start to %stop via 1
compile [%expression for %key = %value in %iterable] to:
assume (%key.type is "Var") or barf ".."
List comprehension has the wrong type for the key loop variable. Expected Var, but got: \(%key.type)
assume (%value.type is "Var") or barf ".."
List comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%value.type)
return
Lua value ".."
(function()
local comprehension = {};
for \(%key as lua expr), \(%value as lua expr) in pairs(\(%iterable as lua expr)) do
table.insert(comprehension, \(%expression as lua expr));
end
return comprehension;
end)()
# Dict comprehensions
immediately:
compile [%key = %value for %item in %iterable] to:
assume (%item.type is "Var") or barf ".."
Dict comprehension has the wrong type for the loop variable. Expected Var, but got: \(%item.type)
# Note: it's important to have the space after "[" to prevent confusion if %key is a string
return
Lua value ".."
(function()
local comprehension = {};
for i,\(%item as lua expr) in ipairs(\(%iterable as lua expr)) do
comprehension[ \(%key as lua expr)] = \(%value as lua expr)
end
return comprehension;
end)()
parse [%key = %value for all %iterable] as: %key = %value for % in %iterable
compile [%key = %value for %src_key = %src_value in %iterable] to:
assume (%src_key.type is "Var") or barf ".."
Dict comprehension has the wrong type for the key loop variable. Expected Var, but got: \(%src_key.type)
assume (%src_value.type is "Var") or barf ".."
Dict comprehension has the wrong type for the value loop variable. Expected Var, but got: \(%src_value.type)
# Note: it's important to have the space after "[" to prevent confusion if %key is a string
return
Lua value ".."
(function()
local comprehension = {};
for \(%src_key as lua expr), \(%src_value as lua expr) in pairs(\(%iterable as lua expr)) do
comprehension[ \(%key as lua expr)] = \(%value as lua expr);
end
return comprehension;
end)()
immediately:
action [%lists flattened]:
%flat <- []
for %list in %lists:
for %item in %list:
add %item to %flat
return %flat
parse [entries in %dict] as: {key:%k, value:%v} for %k = %v in %dict
parse [keys in %dict] as: %k for %k = %v in %dict
parse [values in %dict] as: %v for %k = %v in %dict
# Sorting:
immediately:
compile [sort %items] to: Lua "table.sort(\(%items as lua expr));"
compile [sort %items by %key_expr] to
Lua ".."
utils.sort(\(%items as lua expr), function(_)
return \(%key_expr as lua expr);
end);
immediately:
action [%items sorted, sorted %items]:
%copy <- (% for all %items)
sort %copy
return %copy
action [%items sorted by %key]:
%copy <- (% for all %items)
sort %copy by %key
return %copy
action [unique %items]:
%unique <- []
%seen <- {}
for all %items:
unless: % in %seen
add % to %unique
(% in %seen) <- (yes)
return %unique
immediately:
# Metatable stuff
compile [set %dict's metatable to %metatable] to
Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
compile [new counter] to: Lua value "setmetatable({}, {__index=function() return 0; end})"
compile [new default dict] to
Lua value ".."
setmetatable({}, {__index=function(self, key)
t = {};
self[key] = t;
return t;
end})
# TODO: maybe make a generator/coroutine?
|