using DeepcopyModules
module M; x = 1; f() = (global x += 1); end
M2 = deepcopy_module(M)
The package is on github. However, this code crashes. Is there any other way?
The error is:
main at /buildworker/worker/package_linux64/build/cli/loader_exe.c:42unknown function (ip: 0x7efc98030d8f)__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)Process julia aborted (core dumped) at Mon Jul 11 10:36:15 2022
X-post from here
I almost managed to deepcopy a module without going into the C internals. The only link that remains is that a change of a function definition in the initial module affects the copy. Any ideas how to get rid of that?
function getmodulename(x::Module)
## extracts name of passed module
nn = quote
$x
end
n_with_parent = nn.args[2] |> string
## Works for nested modules
parent = parentmodule(x)
m_maybe = match(Regex("(?<=$(parent)\\.).*"), n_with_parent)
return Symbol(m_maybe.match)
end
function copy_module(m::Module, new::Module)
mname = getmodulename(m)
unused_names = [mname, Symbol("#eval"), Symbol("#include"), :eval, :include]
mnames = names(m; all = true)
filter!(x-> x ∉ unused_names && !startswith(string(x), '#'), mnames)
properties = [getproperty(m, n) for n in mnames]
ismodule = isa.(properties, Ref(Module))
## Modules get copied recursively
modules = properties[ismodule]
for _m in modules
_mname = getmodulename(_m)
_new = new.Core.eval(new, :(module $_mname end))
copy_module(_m, _new)
end
## Functions cannot be copied but are defined such that
## a change in `new` does not affect `m`
## without a change in `new` the function will refer to
## whatever is currently in `m` (incl. changes)
isfunction = isa.(properties, Ref(Function))
functions = properties[isfunction]
for (_n, _f) in zip(mnames[isfunction], functions)
new.Core.eval(new, :($(_n)(x) = (y->$(_f)(y))(x)))
end
## Values are assigned with deepcopy
assignments = [:($nn = deepcopy($pp)) for (nn,pp) in zip(mnames[.!(ismodule) .&& .!(isfunction)], properties[.!(ismodule).&& .!(isfunction)])]
[new.Core.eval(new, i) for i in assignments]
return new
end
module A
x = 1
y = [1,3,4]
f(x) = println(x)
module C
z = [1,2,3]
end
end
module B end
copy_module(A, B)
A.f("HI")
B.f("HI")
A.f(x) = x^2 # modifies A.f AND B.f
A.f("HI")
B.f("HI")
B.f(x) = lowercase(x) # modifies ONLY B.f
A.f("HI")
B.f("HI")
A.x
B.x
A.Core.eval(A, :(x = 2)) # modifies ONLY A.x
A.x
B.x
B.Core.eval(B, :(x = "HI")) # modifies ONLY B.x
A.x
B.x
B.C.z .= [4,5,6] # modifies ONLY B.C.z
A.C.z
B.C.z
A.y !== B.y ## not same memory
A.C.z !== B.C.z ## not same memory