Here are some thoughts of a country bumpkin :-)
In order to get the following behaviour I think we need to change our (my)
ideas about the stack.
1.
: [a],[%hd()%] =>
** [ a ]
2.
: [a],{%hd()%} =>
** {a}
The first case fails because the call to "hd" takes a popstackmark as
argument. The second case fails because the change in stacklength is
used to determine the size of the vector and "hd" does not change
the stacklength.
The traditional stack can be thought of as a list where a push is
equivalent to cons-ing an item on to the stack and a pop is equivalent
to dest-ing the stack
ie
PUSH item item :: STACK -> STACK
POP dest(STACK) -> STACK
Now consider the stack to be a list of lists. A push is then equivalent to
cons-ing an item on to the first list in the stack and a pop is equivalent
to dest-ing the first non-empty list in the stack.
ie
PUSH item item :: (hd(STACK)) -> hd(STACK);
POP for i from 1 to length(STACK) do
unless STACK(i) == [] then
dest(STACK(i)) -> STACK(i);
quitloop;
endunless;
endfor
(check for stack underflow)
The opener% is then equivalent to cons-ing an empty list onto the stack
and %closer takes the first list from the stack and creates the appropriate
structure.
opener% [] :: STACK -> STACK;
%closer destlist(dest(STACK) -> STACK).consXXX
This gives a clear way of thinking about an open stack which can
achieve the desired result. The problem then is how to implement this
in an efficient manner. Any ideas?
Anthony.Worrall@Reading.ac.uk
|