Created
October 22, 2016 16:52
-
-
Save marcoonroad/aabc5f0c05ed9690615af76a36e44588 to your computer and use it in GitHub Desktop.
Cloning optimized with clone families.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local export = { } | |
local weakkey = { __mode = 'k' } | |
local updated = setmetatable ({ }, weakkey) | |
local clones = setmetatable ({ }, weakkey) | |
local prototype = setmetatable ({ }, weakkey) | |
local proxy = setmetatable ({ }, weakkey) | |
local metatable = { } | |
-- we use the `prototype` relation for indexing -- | |
-- propagation while the `clones` relation -- | |
-- is used for propagation by mutation/writes -- | |
function metatable: __index (selector) | |
local value = proxy[ self ][ selector ] | |
if not rawequal (value, nil) then | |
return value | |
elseif rawequal (prototype[ self ], nil) then | |
return nil | |
elseif updated[ self ][ selector ] then | |
-- when it already have passed by here, -- | |
-- nil is the result value despite -- | |
-- non-nil mutations on prototype-side... -- | |
return nil | |
else | |
-- transitive propagation by access. -- | |
-- result value can be nil, though -- | |
local value = prototype[ self ][ selector ] | |
-- intransitive propagation by mutation -- | |
updated[ self ][ selector ] = true | |
proxy[ self ][ selector ] = value | |
-- we have chosen to not propagate down with -- | |
-- mutation, 'cause it will generate too much -- | |
-- overhead as an expensive computation. also, -- | |
-- transitive propagation by mutation is -- | |
-- useless here, 'cause we already have -- | |
-- transivity by indexing on prototype-side... -- | |
return value | |
end | |
end | |
function metatable: __newindex (selector, value) | |
-- transitive propagation by indexing -- | |
local previous = self[ selector ] | |
for child in pairs (clones[ self ]) do | |
if not updated[ child ][ selector ] then | |
-- intransitive propagation by mutation -- | |
updated[ child ][ selector ] = true | |
proxy[ child ][ selector ] = previous | |
end | |
end | |
updated[ self ][ selector ] = true | |
proxy[ self ][ selector ] = value | |
return | |
end | |
function export.create (structure) | |
local alias = { } | |
proxy[ alias ] = structure | |
updated[ alias ] = { } | |
clones[ alias ] = setmetatable ({ }, weakkey) | |
setmetatable (alias, metatable) | |
return alias | |
end | |
function export.copy (structure) | |
local copy = export.create { } | |
prototype[ copy ] = structure | |
clones[ structure ][ copy ] = true | |
return copy | |
end | |
return export |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment