Thanks for your idea about push/pop. There are, however, several
rather important issues with it.
As you mention, it allows pushing onto non-list arguments, e.g. ll:
x+y$ push(3,ll) => x+y+3. This is probably not a good idea, since most
non-list operators do not preserve order, thus they cannot have
push/pop semantics. In fact, they don't even preserve non-atomicity.
Consider the sequence: ll:a+1$ push(-1,ll)$ pop(ll) => oops.
If you still think this is a good idea, then it is an error to push
back on a SIMP marker, because the result will in fact not be
simplified but will still be marked as simplified: ll:x+1$ push(3,ll)
=> x+1+3 ((mplus simp) 3 1 $x).
Your code will also create malformed expressions in some cases:
ll:x^y$ push(3,ll) => 3^x ((mexpt simp) 3 $x $y). But mexpt takes
exactly 2 arguments.
It is an error to use Lisp's push function to modify a Maxima
variable. In particular, this means you can't push onto a subscripted
variable: zz[1]:[]$ push(3,zz[1]) => error.
> I think I should use (symbol-value ms) instead of (meval ms) to get the list attached to the symbol, right?
Absolutely not. As a general matter, you shouldn't "short-circuit"
other functions unless you have a very good reason. In this
particular case, see above for array arguments.
I hope my comments help you understand how Maxima works internally better.
-s