Macros don't preserve an array's identity when they are evaluated. Instead, any arrays in the macro's return list are invisibly copied before being used. It is therefore impossible to use SETITEM in a macro as it ends up modifying a copy of the array that is inaccessible to the programmer, instead of the array the programmer specified.
This bug is also reproducible in UCBLogo 6.2.5.
How Reproducible:
Every Time
Steps to Reproduce:
MAKE "array {1}
RUN (LIST "SETITEM 1 :array 2)
SHOW :array
What Happens:
SHOW prints {1}.
Expected Result:
SHOW prints {2}. This is the same as if SETITEM 1 :array 2 had been run.
Impact:
This prevents anyone from using SETITEM in a macro, including macroized primitives like RUN.
Notes:
I suspect that this is due to the logic to copy the array when it's evaluated as a literal in eval.cpp
case ARRAY:
// array must be copied
{
assign(val, make_array(getarrdim(exp)));
setarrorg(val, getarrorg(exp));
NODE ** p = getarrptr(exp);
NODE ** q = getarrptr(val);
for (int i = 0; i < getarrdim(exp); i++)
{
*q++ = vref(*p);
p++;
}
}
goto fetch_cont;
The above logic makes sense for array literals, as it would be bad if SETITEM modified the definition a procedure that returned the array instead of just the array. However, in a macro evaluation, it makes sense to use the original array's reference.