vermaseren / form

The FORM project for symbolic manipulation of very big expressions
GNU General Public License v3.0
982 stars 118 forks source link

Wrong implicit symbol declaration in "autodeclare index" #324

Closed mgerlach-phys closed 2 years ago

mgerlach-phys commented 4 years ago

The following, short program does not behave as expected:

`*symbol n; autodeclare index randomIndex=n; local A = n;

print +s; .end`

Without declaring "n" the expected behavior would be to declare it implicitly as a symbol with a warning (as it is the case for the program without the "autodeclare" statement).

Funnily, the program runs without complains and returns i_.

tueda commented 4 years ago

Thank you for your report! It seems that this issue and #325 are caused by the fact that n (in the following example) is considered as a different object from the usual one when implicitly used via autodeclare index (20 vs. 0):

I x = n;
L F = n;
P "%r";
.end
test.frm Line 1 --> Warning: Implicit declaration of n as a symbol
8  1  4  20  1  1  1  3
Auto I x = n;
L F = n;
P "%r";
.end
8  1  4  0  1  1  1  3

The reason why you may get i_, pi_, coeff_, num_, den_, ... is because they are built-in objects defined in this order: https://github.com/vermaseren/form/blob/0b3ab5d87b7aa61408f57bcd041707f43cc8961b/sources/startup.c#L1029-L1037

benruijl commented 2 years ago

The problem is caused by a rather error-prone way that auto-declared statements are processed. The entry point is:

    AC.Symbols = &(AC.AutoSymbolList);
...
    retval = CompileStatement(inp);

    AC.Symbols = &(AC.SymbolList);
...

So the AC.Symbols is overwritten. This array is used by AddSymbol to add symbols, and I believe AddSymbol expects that this array is always AC.SymbolList. For example, the function GetAutoName uses AddSymbol to register a new symbol when the auto-symbol wasn't used before.

What happens in a situation like:

Auto S n1;
Auto I mu = n1;

is that when n1 is used in the second auto-declare, it gets created and added to AC.AutoSymbolList and not AC.SymbolList. Since AC.AutoSymbolList is empty, we see a 0 popping up in the P "%r". Similarly, if we leave out Auto S n1, it creates the symbol in the wrong array.

To fix it, in DoDimension, I switch out the symbol list at the start:

AC.Symbols = &(AC.SymbolList);

and set it back to the original value at the end. This fixes this problem, and hopefully doesn't have side-effects. Basically any place where auto-declared variables is used for the first time in another auto-declared statement, this problem occurs. I believe DoDimension is the only place where this happens, but I haven't checked this thorougly.