+
+ -----------------------------------------------------------------------------
+ -- nest_points are places where a table appears within itself, directly or not.
+ -- for instance, all of these chunks create nest points in table x:
+ -- "x = { }; x[x] = 1", "x = { }; x[1] = x", "x = { }; x[1] = { y = { x } }".
+ -- To handle those, two tables are created by mark_nest_point:
+ -- * nest_points [parent] associates all keys and values in table parent which
+ -- create a nest_point with boolean `true'
+ -- * nest_patches contain a list of { parent, key, value } tuples creating
+ -- a nest point. They're all dumped after all the other table operations
+ -- have been performed.
+ --
+ -- mark_nest_point (p, k, v) fills tables nest_points and nest_patches with
+ -- informations required to remember that key/value (k,v) create a nest point
+ -- in table parent. It also marks `parent' as occuring multiple times, since
+ -- several references to it will be required in order to patch the nest
+ -- points.
+ -----------------------------------------------------------------------------
+ local function mark_nest_point (parent, k, v)
+ local nk, nv = nested[k], nested[v]
+ assert (not nk or seen_once[k] or multiple[k])
+ assert (not nv or seen_once[v] or multiple[v])
+ local mode = (nk and nv and "kv") or (nk and "k") or ("v")
+ local parent_np = nest_points [parent]
+ local pair = { k, v }
+ if not parent_np then parent_np = { }; nest_points [parent] = parent_np end
+ parent_np [k], parent_np [v] = nk, nv
+ table.insert (nest_patches, { parent, k, v })
+ seen_once [parent], multiple [parent] = nil, true
+ end
+