Search                        Top                                  Index
REF SECTIONS                                        John Gibson Oct 1992

     COPYRIGHT University of Sussex 1992. All Rights Reserved.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<                             >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<          SECTIONS           >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<                             >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

This REF file provides the why and  the how behind the use of  sections.
i.e.   creating   and    manipulating   sections,    importing/exporting
identifiers, miscellaneous procedures etc. The mechanics of sections are
illustrated by some examples at the end.

         CONTENTS - (Use <ENTER> g to access required sections)

  1   Introduction

  2   Pathnames

  3   The section Construct

  4   Global Identifiers

  5   Section Procedures

  6   Predicates on Sections

  7   Creating/Manipulating Sections

  8   Standard Sections

  9   Importing/Exporting Identifiers

 10   Miscellaneous

 11   Examples



---------------
1  Introduction
---------------

As described  in  REF * IDENT,  a declaration  of  a  permanent  program
identifier (i.e. a variable or a constant) results in the attachment  of
a identifier record to the  corresponding word, this record  maintaining
the idval (or valof) and  identprops of the program identifier.  Program
sections provide  a  means whereby  this  attachment can  be  made  on a
localised basis, i.e.  the same  word can be  associated with  different
permanent identifiers in different sections of a program. (Note that the
section mechanism does NOT  apply to lexically-scoped identifiers,  i.e.
those declared with lvars or  lconstant. From here on 'identifier'  will
always mean 'permanent identifier'.)

    The motivation for  sections is that  in writing a  part of a  large
program (or in writing  a library program or  system which other  people
are going to use), it may be convenient to use particular words to  name
private identifiers on the  basis of mnemonic  significance. But at  the
same time these  private identifiers  should not  conflict or  interfere
with identifiers of the same name either in other parts of the  program,
or that users of the  library program/system will employ. (This  applies
particularly to frequently used variable names, e.g. "x".) For  example,
the mere use  of a  variable name in  a library  routine will  prevent a
warning message being issued for that  variable when employed by a  user
who has forgotten to declare it as local to a procedure (assuming he has
the library routine loaded).

    Another useful aspect  of sections  is that they  can be  cancelled.
Cancelling  a   section  simultaneously   cancels  all   the   permanent
identifiers local  to that  section,  implying that  the words  used  to
reference them (if not used elsewhere) will be garbage collected.

    Pop-11 sections are  analagous to directories  in a  tree-structured
file system, where the identifiers play the role of files. Just as files
in different  directories may  have  the same  name, so  identifiers  in
different  sections   may   also;   just   as   directories   may   have
sub-directories, so sections may have sub-sections. Just as there is the
concept of  'current directory',  so there  is the  concept of  'current
section', and the user may make any node in the section tree the current
section at any time -- changing sections in this way involves the system
in manipulating the identifier fields  in all word records currently  in
the dictionary.

    The ability to import and export identifiers provides a facility not
(usually) found in file systems. Importing an identifier named X  into a
sub-section B of a section  A means that references to  X in B refer  to
the  identifier  associated  with  X  in  A;  similarily,  exporting  an
identifier Y from B upto A means that references to Y in A refer to  the
identifier as  declared  in B.  Thus  the former  allows  references  to
identifiers already declared  in sections above  the current one,  while
the latter allows mew identifiers to  be declared in such sections  from
within the current.

    The construction of the section tree is in terms of section records,
each section record containing  information about the identifiers  local
to that section, as well as  a list of section records for  sub-sections
of that section. The root node of this tree is the section record in the
constant pop_section,  which  represents  the  'top-level'  of  the  POP
system, and all other sections can be reached by working downwards  from
this. Procedures are  provided to  enable the  user to  effect this  and
other manipulations on sections and identifiers at run-time (see below),
as well as syntactic constructs for use at compile-time.




------------
2  Pathnames
------------

As with  directories,  sections are  identified  by name;  a  'pathname'
syntax is provided  to enable reference  to identifiers within  sections
(in a manner similar to UNIX file  pathnames). The word "$-" is used  to
separate parts of the pathname (rather than "/" as in UNIX), so that for
example

                $-tom$-dick$-harry

refers to the identifier  harry in subsection dick  of section tom  (tom
being a subsection of pop_section), while

                $-foo

refers to the  top-level identifier  foo. Again  analagously to  UNIX, a
pathname not beginning with '$-' is taken to be relative to the  current
section, e.g.

                bill$-ben

means the identifier ben in the subsection bill of the current section.




------------------------
3  The section Construct
------------------------

The section  construct  is the  principal  way of  using  sections  when
compiling programs. It has the form

        section <pathname> <imports> => <exports> ;

            <statement sequence>

        endsection

where both <imports> and <exports> are optional sequences of words,  the
"=>" being omitted if there are no exports.

    <pathname> is a pathname as described above, but in THIS context  it
refers to a section, not an identifier. So

        section $-tom$-dick$-harry; ... endsection

specifies subsection  harry  of subsection  dick  of subsection  tom  of
pop_section, etc. In addition,  the name of  pop_section is <blank>  (it
is!), so that omitting the pathname references the top-level, thus

        section; ... endsection

(there must be  no imports or  exports in this  case because they  don't
make sense at top-level).

    The effect of section is to save the current section, make the named
section the current,  and then  continue compiling  until endsection  is
encountered, at which  point the previous  current section is  restored.
After entering the named section, section_import is called on each  word
specified  by  <imports>,  and  section_export  on  each  specified   by
<exports>  --   see  under   'Section  Procedures'   below.  (In   fact,
section_import and section_export are  also called in each  intermediate
section in the specified path. This implies, e.g, that

        section $-tom$-dick$-harry xxx => yyy;
            ...
        endsection

will import xxx from top-level down through tom and dick into harry, and
export yyy from harry up through them to top-level.)




---------------------
4  Global Identifiers
---------------------

Most permanent identifiers are normally required to be accessible in all
sub-sections of the section in which  they are declared, and thus to  be
imported into  sub-sections without  any  explicit declaration  to  that
effect.

To this end, an  identifier can be declared  as global, meaning that  it
should be  considered  an automatic  import  into any  sub-section  of a
section where it is accessible. This can be done either at run-time with
sysGLOBAL (see REF * VMCODE), or at compile-time with a vars or constant
statement prefixed by global, e.g.

            global vars x, y, z;
            global constant a, b, c;

The keyword global can also appear in a define statement after the  word
"define" (but before any "vars" or "constant"). E.g.

            define global x(); ... enddefine;
            define global constant y(); ... enddefine;

However, to make the continual use of global unnecessary in Pop-11,  the
compile_mode option  :pop11  +global  may be  used;  this  automatically
defaults  all  permanent  identifiers  to  global.  Moreover  (since  in
practice non-global  identifiers  are  rarely needed),  this  option  is
included in the 'macro'  option :pop11 +strict used  by most system  and
library code.

If required, the :pop11 +global option can be overridden with nonglobal,
which may appear anywhere that global can, e.g.

            nonglobal vars x, y, z;
            define nonglobal x(); ... enddefine;




---------------------
5  Section Procedures
---------------------

These procedures allow  the manipulation  of sections by  the user  (the
syntactic constructs  described  above  being implemented  in  terms  of
these). At  system  startup  time  the current  (and  only)  section  is
pop_section,  which  represents  the  'normal'  top-level  of  POP.  New
sections are then created by use of section_subsect as described below.

    On  entering  a  section  (by  assigning  to  current_section),  all
non-imported words  have  their identifiers  set  to "undef",  with  the
following exceptions:

        # All system words.

        # All words having system identifiers associated with them.

        # All words having associated with them identifiers marked as
          global (this actually subsumes (2), since all system
          identifiers are so marked).

    After  this,  words   having  section-local   identifiers  are   set
appropriately. The  process  of  entering a  section  actually  involves
'unwinding' all  sections  up to  the  lowest common  ancestor  of  that
section and the current one, and then recursively entering all  sections
from there down to the given one (although the user need not be aware of
this).

    Whenever a  new identifier  is declared  (i.e. with  vars,  constant
etc), this identifier is made local  to the current section, unless  the
identifier name has been  declared as an export  (see below). By use  of
word_identifier (described below), new identifiers can be created in any
section regardless  of the  current section  context. Redeclarations  of
existing identifiers  merely  alter  the  information  in  the  existing
identifier record, and so do not change their section status in any way.




-------------------------
6  Predicates on Sections
-------------------------

issection(item) -> bool                                      [procedure]
        Returns <true> if item is a section, <false> otherwise.




---------------------------------
7  Creating/Manipulating Sections
---------------------------------

section_subsect(name, sect, create) -> sub_sect              [procedure]
section_subsect(sect) -> sub_sect_list
        In the first form of the call, given a section sect, returns the
        subsection called name  of sect  (name is  a word).  If no  such
        subsection currently exists, then

            (a) If create is true, a new subsection of sect called
            name is created and returned;

            (b) If create is <false>, the mishap NONEXISTENT SECTION
            occurs.

        In the second form, given a section sect, returns a list of  all
        subsections of sect.


section_supersect(sect) -> super_sect                        [procedure]
        Given a section  sect, returns the  section super_sect of  which
        sect is  a  subsection, or  <false>  if sect  is  the  top-level
        section pop_section.


section_cancel(sect)                                         [procedure]
section_cancel(sect, zap_pdprops)
        Cancels the section sect, i.e. breaks the link to sect from  its
        supersection (sect must not be top-level, although it's quite OK
        for sect to be the CURRENT section).

        If the  optional  boolean  argument  zap_pdprops  is  true,  the
        pdprops of all procedures held in local identifiers of sect  are
        set to <false>  (providing that they  are user procedures  whose
        current pdprops  is  the  word  with  which  the  identifier  is
        associated -- if not the pdprops are left untouched).

        section_cancel also recursively  applies itself  (with the  same
        value for zap_pdprops)  to any subsections  of sect,  cancelling
        them too.


section_name(sect) -> word                                   [procedure]
        This procedure returns the name of  sect, or <false> if sect  is
        pop_section (note  that  the  name does  not  include  the  full
        pathname of sect).


section_pathname(sect) -> string                             [procedure]
        Returns the full pathname of sect, as a string (blank if sect is
        pop_section).




--------------------
8  Standard Sections
--------------------

pop_section -> sect                                           [constant]
        The value of this constant is the top-level section record,  the
        root node of the section tree.


pop_default_section -> sect                                   [variable]
sect -> pop_default_section
        This variable holds the default section to return to on  doing a
        setpop (or when vederror is called inside VED). In other  words,
        they both do the assignment

            pop_default_section -> current_section;

        The initial value of this variable is pop_section.


current_section -> sect                                       [variable]
sect -> current_section
        This (active) variable  holds the current  section; its  initial
        value is pop_section.




----------------------------------
9  Importing/Exporting Identifiers
----------------------------------

section_export(word)                                         [procedure]
        Declares the word word  to be an export  of the current  section
        (which must not  be top-level),  meaning that  whenever word  is
        subsequently declared,  the identifier  attached to  it is  made
        local to the section above (or  the section above that if it  is
        exported from there ,  etc). At the same  time, word is made  an
        import to  the current  section;  thus the  identifier  actually
        'rises' to the highest  level section it  is NOT exported  from,
        while at the same time 'sinking' down from there to the  current
        section through all intermediate sections.

        If word currently  has a  local identifier  associated with  it,
        this 'rises' as described  above and ceases to  be local; if  it
        has an  associated imported  identifier, then  exporting has  no
        effect unless word  is cancelled and  redeclared, in which  case
        the redeclaration is exported.


section_import(word)                                         [procedure]
        Declares the word word  to be an import  of the current  section
        (which  must  not  be  top-level),  thus  making  available  the
        identifier associated with word in the super-section of SECT. If
        word already has a local identifier associated with it, this  is
        CANCELLED. word is automatically  declared in the  super-section
        if it is undefined there.




-----------------
10  Miscellaneous
-----------------

sys_read_path(first_item, use_itemread, needsect) -> result  [procedure]
        Reads a  section/identifier  pathname  from  the  current  input
        stream (i.e. from proglist).

        If needsect is <false>, the pathname is interpreted as referring
        to an identifier,  and the  appropriate word_identifier  (called
        with CONTEXT argument "undef" -- see below) is the result.

        If needsect has a true  value, the pathname is interpreted  as a
        section name  (all sections  referenced  being created  if  they
        don't exist).  For any  true  value of  needsect other  than  []
        (nil), the  section  record for  the  target section  is  simply
        returned; however, for  needsect =  [] the  result is  instead a
        list of  all  section records  in  the pathname,  starting  with
        pop_section if the pathname is absolute (i.e. begins with "$-").

        It  is  assumed  that  the  pathname  begins  with  (the   word)
        first_item,  which  has   already  been   read  from   proglist;
        successive items of the pathname are then read with itemread  if
        use_itemread is true, or readitem otherwise. (If the first  item
        has not  been  read  then  the  first_item  argument  should  be
        readitem() or itemread(), etc.)


word_identifier(word, sect, context) -> word_id              [procedure]
        This procedure enables sectioned  identifiers to be  represented
        by unique word records.

        Given a dictionary word  word and a  section sect, it  returns a
        unique word word_id which has associated with it the  identifier
        associated with word in  the section sect.  The word word_id  is
        not entered in the  dictionary, and so  does not participate  in
        the section mechanism; thus the identifier associated with it is
        always guaranteed to be  that associated with  word in sect  (in
        other words  word_id  is  a 'symbolic'  representation  of  that
        particular identifier record).

        What is meant by 'the  identifier associated with word in  sect'
        further depends on the value of the context argument, which  can
        take the following values:

            false
                Only identifiers strictly local  to sect are  considered
                (i.e. not  including imports,  either explicit  ones  or
                implicit "global" ones); <false> is returned if there is
                no currently associated identifier.

            the word "undef"
                Same as  false,  but  if there  is  currently  no  local
                identifier associated  with word,  an 'undeclared'  word
                identifier is returned (see below).

            anything else
                Imported identifiers are  taken into  account, i.e.  the
                state of word as  it would be if  sect were the  current
                section is considered; false is returned if there is  no
                currently associated identifier.

        In all cases, the  characters of the word  word_id are the  full
        section  pathname  of  its  identifier,  except  that  top-level
        identifiers are not prefixed by '$-'.

        The case of the "undef"  context argument is different from  the
        other two in  that it  returns an  'undeclared' word  identifier
        when there is no current local identifier. This word  identifier
        will act as a vehicle for  declaring word in sect, in the  sense
        that any later attachment of an identifier to word_id (e.g. with
        ident_declare or  sysSYNTAX,  or  by a  direct  assignment  with
        identof, etc),  will simultaneously  attach that  identifier  to
        word in section sect. Conversely, a later declaration of word in
        sect will cause the new identifier to become attached to word_id
        also.

        [Note that in all cases, cancelling word_id with syscancel  will
        cancel word in sect. It  does not, however, actually remove  the
        identifier from word_id, since word_id is supposed to  represent
        that identifier uniquely. What it does do is to remove the  link
        between word_id and word in sect, so that from the point of view
        of  any   further   operations  it   becomes   a   'stand-alone'
        identifier.]

        If the word argument to word_identifier is not a dictionary word
        (i.e. it is itself  a word identifier, or  a copied word),  then
        word is just returned unchanged.

        Note that  in  Pop-11,  any ident  expression  for  a  permanent
        identifier  may  be  surrounded  by  word  quotes  to  get   the
        corresponding quoted word identifier, e.g.

            "ident $-mysect$-xxxx" -> word_id;

        In addition, "nonactive" may be used in place of "ident":

            "nonactive $-ved_current_file" -> pair;

        This returns  the  word  identifier inside  a  'nonactive  pair'
        suitable for giving to (e.g.) sys_current_val. Either "ident" or
        "nonactive" may be followed by "weakref" to return the word in a
        'weakref pair':

            "ident weakref $-mysect$-xxxx" -> pair;

        See REF * VMCODE.


fast_app_sect_idents(sect, p)                                [procedure]
        Applies the procedure p to all identifiers local to the  section
        sect.  That  is,  for  each  word  having  a  local   identifier
        associated with  it in  sect,  p is  called  with the  word  and
        identifier record as arguments, i.e.

                p(WORD, IDENT)

        If sect is pop_section, then p is called for all words having an
        associated top-level identifier.

        If the  procedure  p create  new  words in  the  dictionary,  or
        deletes existing  ones, or  declares or  cancels identifiers  in
        sect, exactly what p is applied to is undefined; in this case it
        is advisable to use a 'non-fast' version such as the following:

               define app_sect_idents(sect, p);
                    lvars sect, procedure p, n, v;
                    {% fast_app_sect_idents(sect, identfn) %} -> v;
                    for n from 1 by 2 to datalength(v) do
                        p(subscrv(n,v), subscrv(n+1,v))
                    endfor
                enddefine;

        etc.


section_key -> key                                            [constant]
        This  constant  holds  the  key  structure  for  sections   (see
        REF * KEYS).




------------
11  Examples
------------

We will  now illustrate  the  mechanics of  sections by  some  examples.
Suppose we declare list as a constant:

        constant list = [this is a list of words];

Normally, the  following procedure  definition  will produce  a  mishap,
because list has already been declared as a constant (and so cannot be a
procedure local):

        define count(list);
            if list == [] then
                0
            else
                hd(list) + count(tl(list))
            endif;
        enddefine;

However, if we put this definition  inside a section called various  (if
we want to make sure  it's a subsection of  top-level we should call  it
$-various)

        section various;

        define count(list);
            if list == [] then
                0
            else
                hd(list) + count(tl(list))
            endif;
        enddefine;

        endsection;

this is  OK, because  the local  variable  list used  in count  now  has
nothing whatever  to  do  with  the previous  definition  of  list  as a
constant -- the  word "list"  is associated  with different  identifiers
inside and  outside of  section various.  Outside of  this section,  the
identifier which  is the  local of  count is  inaccessible by  the  name
'list' (but could be accessed as 'various$-list').

    On the other hand, this applies  also the identifier count, i.e.  it
cannot be accessed outside of various, and this is probably not what  we
want. So if count is required to be used outside of various, we can make
it an export of the section:

        section various => count;
        define count(list); ... enddefine;
        endsection;

Thus the definition of count  is treated as if  it were made outside  of
various, while at the same time list remains internal to the section.

    Now on entering a section, it  is NOT the case that any  identifiers
defined outside are automatically  accessible inside. This is  generally
what we want, i.e  that these external  identifiers should not  conflict
with ones which are  internal to the section.  So in the example  above,
the constant  list is  not available  inside various,  and so  does  not
conflict with the local  of count. If we  have another constant,  vector
say, and  we  try  to access  it  inside  section various,  it  will  be
undefined:

        constant vector = {1 2 3 4 5 6 7 8 9};
        section various;
        vector=>
        ;;; DECLARING VARIABLE vector
        ** <undef vector>
        endsection;

However, we can either make vector an explicit import of section various

        section various vector;
        vector=>
        ** {1 2 3 4 5 6 7 8 9}
        endsection;

or, if we know that we are going to want to import it into any  section,
we could have declared it as global in the first place:

        global constant vector = {1 2 3 4 5 6 7 8 9};
        section various;
        vector=>
        ** {1 2 3 4 5 6 7 8 9}
        endsection;

(Note that, in the definition of  count above, the system procedures  +,
==, hd and tl were accessible inside various by virtue of being declared
global, as all system identifiers are.)




--- C.all/ref/sections
--- Copyright University of Sussex 1992. All rights reserved.