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