I propose the following alternate guidelines.
First, the code would look something like this:
STRING * concat (STRING* a, STRING* b, STRING* c) {
PARROT_start();
PARROT_str_params_3(a, b, c);
PARROT_str_local_2(d, e);
d = string_concat(a, b);
e = string_concat(d, c);
PARROT_return(e);
}
Then, the rules would be:
(1) start your functions with PARROT_start
(2) register all parameters of type STRING * with PARROT_str_params
(2') register all parameters of type PMC * with PARROT_pmc_params
(3) declare the local variables of type STRING * with PARROT_str_local
(3') declare the local variables of type PMC * with PARROT_pmc_local
(4) use PARROT_return to exit the function
(5) do not nest function calls
(for instance, "e = string_concat (string_concat(a, b), c);"
would be forbidden)
The idea is to explicitly manage a stack of parrot objects, which can
be traversed by the GC.
This rules let a lot of freedom to the garbage collector:
- it can garbage collect anything which is not rooted;
- it can move objects (strings and PMCs) around;
- objects do not need any additional field/flag;
- exception can be implemented using longjmp; if an exception is
raised, temporary allocated objects will be properly freed by the GC.
Do you think that these rules would be too error-prone, or too
cumbersome?
-- Jerome