[Date Prev] [Date Next] [Thread Prev] [Thread Next] Date Index Thread Index Search archive:
Date:Mon Jan 4 03:02:02 2002 
Subject:More on use of stack in Pop-11 (Was: Have I hit a bug already?) 
From:Aaron Sloman See text for reply address 
Volume-ID:1020104.01 

[To reply replace "Aaron.Sloman.XX" with "A.Sloman"]

Here's another example of pop-11 programming style using the stack.

pete@jwgibbs.cchem.Berkeley.EDU (Pete Goodeve) writes:

> Date: Sat, 29 Dec 2001 03:01:47 +0000 (UTC)
> Organization: University of California, Berkeley
>
> In article <3C2B27F7.6009@ed.ac.uk>,
> Stephen Isard  <S.IsardDeleteThis@ed.ac.uk> wrote:
> ....
> >...You could call stacklength() on entry to the function and then
> >take just the new items off the stack at the end.  It would save you
> >making repeated calls to consstring.
>
> Having done quite a bit more experimentation and program-construction
> since, one of the things that strikes me about a lot of Pop-11 is its
> -- shall we say? -- cavalier use of the stack...

This is a source of both very elegant and efficient constructs and
obscure bugs.

One way to minimise the risk of bugs, as indicated in a
previous message is to use good syntactic constructs, like the
#| ... |# brackets, and also [% ,,, %] for making lists and
{% ... %} for making vectors.

However, this is not enough. So in a lot of my code which is
intended to be used by other people who may inadvertently write
programs that remove more than they should from the stack or leave
junk on the stack, I have found it essential to include stack
checking code which produces helpful error messages if appropriate.

Otherwise users get obscure results at a later stage which can be
impossible to debug.

General rule: if you provide constructs that can run procedures that
are provided by other programmers, and you know the stack should be
unchanged afterwards, insert stack checks.

For instance, there is stack checking code in several places in
poprulebase

http://www.cs.bham.ac.uk/research/poplog/newkit/prb/help/poprulebase

and in sim_agent
http://www.cs.bham.ac.uk/research/poplog/newkit/sim/help/sim_agent

and in rclib
http://www.cs.bham.ac.uk/research/poplog/rclib/help/rclib

The technique in all cases is to use stacklength() to record the
length at the beginning of a block of text, then to check at some
later point whether it has changed and if so to produce an error
message.

I keep meaning to produce some nice syntax to mark the beginning and
the end of such blocks, but so far have not done it. e.g. i could
use two macros or syntax words STACK and ENDSTACK

    STACK

        ....

    ENDSTACK (<string>, <expression>);

STACK would merely save the result of stacklength().

ENDSTACK would check whether stacklength has changed and if so
produce a message using a format something like this:

    sys_raise_exception(
        <string> >< N >< ' items removed from stack',
        [%<expression>%],
        `E` );

(or ' items added to stack', if appropriate).

(Note that 'sys_raise_exception' supersedes 'mishap', which is
defined in terms of it.)

It would be simple to add STACK and ENDSTACK, but I have never
bothered.

It would be possible to define the two syntax words so that their
effect could be turned off at compile time for efficiency in trusted
code.


> There seem to be a number of functions that dump arbitrary numbers of
> things on the stack, without giving any direct indication of how many
> there might be. (On the other hand, 'deststring' for example does it
> "right" -- putting the number of items on top.)
>
> 'explode' for instance just dumps whatever its given, although here
> I suppose you usually know how big the thing you're exploding is.

Often you don't care, because you are exploding several things and
it is simpler just to use the total change in stack length.

My previous example of a program to concatenate several strings in a
list without constructing intermediate strings is an example:

    define join(strings) -> newstring;

        consstring(#| applist(strings, explode) |#) -> newstring;

    enddefine;

    join(['abcd' 'efgh' 'ijklmn']) =>
    ** abcdefghijklmn

Another example occurs when you are doing a recursive search over a
complex data-structure (a graph or a tree) and want to make a vector
of all items found which satisfy some condition. You can do

    {% findall(tree, test_predicate) %} -> found;

> Worse is the procedure I came across while looking for a way to split
> strings.  I needed to break a string into segments at "=" characters,
> and at first sight 'sys_parse_string(string, sepchar)'  looked ideal.
> However, it puts the resulting segments on the stack, so in the general
> case you'd *have* to use your stacklength checking mechanism, which seems
> inelegant at least!
>
> There is a variant 'sysparse_string" which makes a list -- just what
> I want! -- but it *only* splits at space characters!  Very strange.

What you want is easily expressed thus;

    [% sys_parse_string(string, `=`) %]

e.g. this makes a list of strings:

    ;;; show string quotes in printout
    true -> pop_pr_quotes;
    [% sys_parse_string('the=cat=sat=on=the=mat', `=`) %] =>
    ** ['the' 'cat' 'sat' 'on' 'the' 'mat']

It's just a matter of getting used to all the stack idioms in
Pop-11.

Often when a procedure is not defined it is because users could
easily do it themselves.

Actually it would be very easy to generalise the definition of
sysparse_string so as to include an optional character argument
as in sys_parse_string. I don't know why that was not done.

The current version of sysparse_string is defined in terms of
sys_parse_string. However the latter was introduced at a later
stage than sysparse_string, which was originally defined in terms of
more primitive mechanisms, and did not allow an arbitrary separation
character.

See the revision notes at the end of
    $usepop/pop/lib/auto/sysparse_string.p

> I ended up doing it with 'locchar' and a couple of 'substring's, but
> I hoped there was a ready-made solution.

See above.

See also the new version of TEACH STACK
    http://www.cs.bham.ac.uk/research/poplog/teach/stack

and Chapter 3 of the pop-11 primer.

Aaron
====
Aaron Sloman, ( http://www.cs.bham.ac.uk/~axs/ )
School of Computer Science, The University of Birmingham, B15 2TT, UK
EMAIL A.Sloman AT cs.bham.ac.uk   (ReadATas@please !)
PAPERS: http://www.cs.bham.ac.uk/research/cogaff/ (And free book on Philosophy of AI)
FREE TOOLS: http://www.cs.bham.ac.uk/research/poplog/freepoplog.html