This boils down to keeping track of unassigned (free) symbols in ginsh in addition to the assigned signals which we already track, and to also track in which assigned symbol every free symbol occurs in.
An assigned symbol can always be freed by unassign('x').
And a free symbol can be assigned by e.g. y=42*x and at this moment we subs(y==42*x) in all assigned symbols where y occurs in and tell the free symbol x that it now occurs in all assigned symbols where previously y was in. Effectively, all free symbols in y (x in our example) become free symbols in the assigned symbols where we just substituted.
That is a little bit tedious but straightforward and should fix your performance problems, I guess.
A slightly more complete implementation would verify, after the substitution, whether the free symbols just introduced in the assigned symbol *really* occurs in the assigned symbols expression, using .has(), constructing a symbols_map, or similar. After all, the symbol might have cancelled in the substitution! Doing this would descend into the expression and be a rather expensive operation. Is that worth it? Not sure. It might be better to lazily omit this extra verification. What would be the cost? At most an possible extra substitution later because ginsh doesn't know that the symbol it is substituting hasn't cancelled from the assigned symbol. (The result expression would be the same.) I tried implementing this on a new branch named ginsh-performance. It
Hi Vitaly, On 4/9/26 11:02 AM, Richard B. Kreckel wrote: [...] passes the new ginsh test suite. \o/ Please do try with your applications! (Not sure if it is free of bugs and worth the effort.) -richy. -- Richard B. Kreckel <https://in.terlu.de/~kreckel/>