-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement GAP's ShallowCopy and StructuralCopy resp. Julia' copy and deepcopy; and, closely related, handle (GAP's) mutability #197
Comments
We might actually want to enable the HPC-GAP variant for object copying in our Julia version of GAP, too. Possibly with some modifications -- we could modify However, the code in |
While a full fix for this is difficult, we might be able to at least handle the case where deepcopy if called on "basic" GAP inputs which do not refer to Julia objects: basically by installing kernel functions for That should help with many basic needs, e.g. when one needs a deepcopy of a GAP group (I think @GDeFranceschi may have need for this) |
@fingolfin I do not understand the example of a deepcopy of a GAP group. Both What did I misunderstand? |
I think part of the problem here is that it is not 100% clear what
As an aside, that does not necessarily mean that
Anyway: From a top level, this matches quite well what GAP does: there,
For GAP, there is indeed no standard way to "clone" a group. (Likewise, there is no good way to serialize and deserialize them in general (an issue we need to address at some point, but I digress), which the I see two options:
To decide which we want, we have to determine what we need. For the uses in Oscarjl so, far, I think option 1 might be fine -- perhaps @GDeFranceschi can comment on this, though? |
The issue came out when I tried to compute
This is not possible since |
The example shows that a |
I do not see problems with the definition that Things become more complicated when the mutable GAP object A stores a Julia object B as a subobject. My proposal would be that |
Implementing Hence my suggestion that to get started, we just provide a I know in principle how to handle the general case (again, see the top post of this issue), but it's one of these tasks which are too big for one afternoon, so I think I'd really need another coding workshop to address this (similar for a many other issues with GAP.jl sigh). |
O.k., I can create a pull request for this partial solution ( Would it --from the viewpoint of GAP-- be attractive to change the |
This is the "easy" first step for issue oscar-system#197.
This is the "easy" first step for issue #197.
Right now, on the GAP side, all T_JULIA wrappers are marked as immutable. This allows us to provide trivial copying operations for those objects. But of course this unsatisfying, and has immediate undesirable side effects; e.g. we can't implement
julia_list[idx] := val;
on the GAP level, as the kernel helpfully prints a common error message for assigning to immutable objects.So, we need something better, but there are pitfalls... In a first iteration, we could switch to the opposite, and mark all T_JULIA objects, and leave it to Julia to figure out the details. (A more clever implementation is difficult, as the concept of "mutability" differs between GAP an Julia: In GAP, it is recursively defined, in Julia, it is not).
Anyway, for copying, here are some relevant links: https://docs.julialang.org/en/v1/base/base/#Base.copy and https://docs.julialang.org/en/v1/base/base/#Base.deepcopy for the Julia side (there is also an undocumented
copymutable
). Source code: https://github.com/JuliaLang/julia/blob/master/base/deepcopy.jlOn the GAP side, we need to provide (resp. improve) our own implementations for handlers in these function arrays:
IsMutableObjFuncs
(could set toAlwaysYes
for now)MakeImmutableObjFuncs
, but probably pointless / not possible)IsCopyableObjFuncs
ShallowCopyObjFuncs
CopyObjFuncs
CleanObjFuncs
The Julia
copy
anddeepcopy
method forGAP.FFE
just can be the identity (and since this is a primitive data type, am guessing that Julia already provides them for us).I imagine that ShallowCopy of T_JULIA wrappers on the GAP side is pretty easy: we use Julia's
copy
to shallow copy the wrapped object. If the result is identical, we also don't make a copy of the wrapper (so justreturn self;
). Otherwise, wrap the copied Julia object into a newT_JULIA
wrapper.For deep / structural copies, more work is needed: On the Julia side,
deepcopy
keeps track of already copied objects via anIdDict
(similar to what our copying code for HPC-GAP does), while GAP does so by temporarily modifying the object being copied to store a forwarding pointer. We need to bridge these two concepts.A first iteration without modifying the GAP kernel could look like this: On the Julia side, we provide a
deepcopy_internal
method for MPtr (and for FFE, but that one can just return the input). This function stores thestackdict::IdDict
passed to it in a global (resp. thread local) variableXYZ
for later reference. Then, we call GAP'sCopyObj
kernel function (asCopyObj(obj, 1)
as usual. The globalXYZ
comes into play in theCopyObjFuncs
forT_JULIA
objects, which needs to calldeepcopy_internal(wrapped, XYZ)
on the wrapped object. Of course ifXYZ
is not yet set, it needs to be set to an emptyIdDict
first.One iffy issue with this is when to clear the XYZ variable. I am actually not quite sure how to solve that right now.
An alternative approach, is to modify the GAP copying functions in the kernel to take
stackdict::IdDict
as an extra argument (and then they could use it instead of the forwarding pointers, too, somewhat similar to what we do in HPC-GAP). But this cannot reasonably be implemented in our package, it really needs modifications to the GAP kernel.The text was updated successfully, but these errors were encountered: