nomsu/core/collections.nom
2018-04-25 16:31:09 -07:00

205 lines
8.0 KiB
Plaintext

#..
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?