ianr@cogs.susx.ac.uk (Ian Rogers) writes:
> Date: 27 Nov 1995 16:10:32 GMT
> Organization: University of Sussex
>
> A.Sloman@uk.ac.bham.cs wrote:
> ....
> > It's even worse to make the change and then leave lots of libraries and
> > documentation that are then broken.
>
> Absolutely. It wouldn't have been hard to search all the libraries and put
>
> compile_mode :pop11 +oldvar;
>
> at the head of each file that used the matcher.
Unfortunately that would not fix all the teaching documentation. I
think I'd have to search through about 3 Megabytes of stuff and I am
far too busy with other things. Besides which there are printed
versions....
> The correct solution is to fix the matcher to recognise lvars.
Here's a first simple shot at that. This works with the ordinary
Pop-11 matcher, but only in V15.0 because of the extension to valof.
Ignore the references to doesmatch. You can simply compile the
following and then try out the examples given.
===================================================================
/* --- The University of Birmingham 1995. --------------------------------
> File: $poplocal/local/lib/readpattern.p
> Purpose: Read in a pattern, changing variables to idents
> Define new syntax word "!" for this purpose
> Author: Aaron Sloman, Nov 26 1995 (see revisions)
> Documentation: See HELP * DOESMATCH
> Related Files: LIB * DOESMATCH, LIB * FMATCHES,
*/
/*
![ .... ]
creates a new type of pattern structure for use with lvars, etc.
![?x ison ??y]
creates a list in which the words "x" and "y" are replaced
by the corresponding current identifiers.
The syntactic operator "!" defined below can ONLY be followed by list
expressions, and it reads them in and replaces occurrences of variable
names after "?" or "??" with identifiers. The resulting list can be used
as a pattern to be given to either the standard pattern matcher (in
Poplog Version 15.0 onwards) or the more general matcher doesmatch,
defined in LIB * DOESMATCH (available from Birmingham).
A pattern read in after "!" works with lexical variables as they are
treated like dynamic variables.
I think it is more efficient to use dlvars than lvars, but am not sure.
Here is an example, which can be tried after compiling this file.
define list_between(item1, item2, list) -> found;
;;; Here found is automatically declared as lvars, as are the
;;; input variables in Poplog version 15, but just to make
;;; the point we declare it
lvars found;
unless list matches ![== ^item1 ??found ^item2 ==] then
false -> found;
endunless;
enddefine;
;;; Now test the procedure
vars words = [a b c d e f g];
list_between("a", "g", words) =>
** [b c d e f]
list_between("d", "e", words) =>
** []
list_between("e", "c", words) =>
** <false>
It works also with restriction elements (See HELP * MATCHES).
;;; Mark and load the next two lines together.
lvars x;
[[a b c]] matches ![[== ??x:2]], x =>
** <true> [b c]
;;; Try that without "!"
;;; Or a procedure restriction
lvars n;
[a b c 3 4 d 4 5 e] matches ![== ?n == ?n:isinteger ==], n=>
** <true> 4
;;; Some test cases, showing that in vector expressions the "?" and "??"
;;; are ignored.
vars v1,v2,v3;
! [v1 ?v1 {v2 ?v2 [?v2]} [v3 ?v3]] =>
** [v1 ? <ident <undef v1>> {v2 ? v2 [? v2]} [v3 ? <ident <undef v3>>]]
lvars lv1, lv2, lv3;
! [lv1 ?lv1 {lv2 ?lv2 [?lv2]} [lv3 ?lv3]] =>
** [lv1 ? <ident <undef>> {lv2 ? lv2 [? lv2]} [lv3 ? <ident <undef>>]]
Note: if procedures using patterns created with "!" are traced, then
identifiers will show up in patterns with their current values, not the
names of the identifiers, as here:
lvars lv4 = 99, lv5 = "cat" ;
![lv4 ?lv4 lv5 ?lv5] =>
** [lv4 ? <ident 99> lv5 ? <ident cat>]
WARNING:
Patterns should NOT contain evaluated sub-expressions quoting
"?" or "??", e.g.
![== [?x b] == [?x h ^(consword("?" >< 'foo')] ==], x =>
Finally note that patterns containing lexically scoped variables
cannot be compiled as constants. (See LIB * COMPILE_MODE)
*/
compile_mode: pop11 +strict;
#_INCLUDE '$usepop/pop/lib/include/pop11_flags.ph'
#_INCLUDE '$usepop/pop/lib/include/vm_flags.ph'
section;
applist([! where readpattern sysPUSHQ], sysunprotect);
lvars procedure oldPUSHQ;
define lconstant Readpattern();
;;; Read in a list or vector expression minus the closing bracket,
;;; replacing words following "?", "??", and ":" with the corresponding
;;; identifier, in nested lists, but not inside nested vectors.
dlvars
was_query = false,
in_vector = iscaller(nonsyntax {);
;;; It would be nice to make patterns constants where possible,
dlocal pop_pop11_flags = pop_pop11_flags || POP11_CONSTRUCTOR_CONSTS;
;;; Discount lexical idents pushed in patterns. I.e. don't treat as type 3
;;; See REF * VMCODE, and REF * pop_vm_flags
;;; IS THIS SAFE ???? A.S. Nov 1995
dlocal pop_vm_flags = pop_vm_flags || VM_DISCOUNT_LEX_PROC_PUSHES;
dlocal oldPUSHQ;
if isundef(oldPUSHQ) then sysPUSHQ -> oldPUSHQ endif;
define dlocal sysPUSHQ(item);
lvars idprops item;
lvars invec, inlist, inpat;
if was_query then
if isword(item) then
identprops(item) -> idprops;
if idprops == undef or isinteger(idprops) then
sysIDENT(item)
else
mishap(item, 1, 'UNSUITABLE ITEM AFTER ' sys_>< was_query)
endif
elseif was_query == ":" and isinteger(item) then
oldPUSHQ(item)
elseif isident(item) then
oldPUSHQ(item)
else
mishap(item, 1, 'NON-WORD AFTER ' sys_>< was_query)
endif;
false -> was_query
else
oldPUSHQ(item);
;;;; Removed the colon. A.S. 29Nov95
;;;; if lmember(item, #_< [? ?? :] >_#) then
if lmember(item, #_< [? ?? ] >_#) then
;;; could the next item be a query variable? Or a restriction
if lmember(nextreaditem(), #_<[% "]", "}", "%", "^", """ %]>_# ) then
;;; end of expression
false;
elseif in_vector then
;;; make sure "{" is higher in calling chain than Readpattern
;;; and that current context is a list expression lower down
lvars
invec = iscaller(nonsyntax {),
inlist = iscaller(nonsyntax [),
inpat = iscaller(Readpattern);
(inpat < invec) and (inlist < inpat) and item
elseif iscaller(nonsyntax {) then
;;; in an embedded vector
false
else
item
endif
else
false
endif -> was_query
endif
enddefine;
;;; Read in the list expression, planting special code
apply(nonsyntax [)
enddefine;
;;; Prepare for expressions of the form
;;; ![ ....] where <exp>
;;; to be compiled as if written
;;; (![ ....], procedure; <exp> endprocedure)
global constant syntax where = pop_undef;
define constant readpattern(trywhere);
;;; Check that a list expression follows on proglist
;;; Read in its items using Readpattern to replace variable
;;; names with identifiers.
lvars item, trywhere;
readitem() -> item;
if item /== "[" then
mishap(item, 1, 'LIST EXPECTED AFTER "!"')
endif;
;;; Now read in the list, replacing pattern variables with
;;; identifiers
Readpattern();
;;; Check if a "where <test> " expression follows. If so compile it as
;;; procedure; <test> endprocedure; and push the procedure. This is for
;;; matchers which accept a third argument which is a boolean procedure
;;; to determine whether a match is successful.
if trywhere then
if pop11_try_nextreaditem("where") then
sysPROCEDURE("where",0);
;;; Read expression with precedence 11. (It's debatable whether it
;;; makes syntactic sense to grab operators of higher precedence
;;; than "!" itself, but it needs to be left this way for backward
;;; compatibility and allows and/or expresions to be included in the where
;;; expression.)
pop11_comp_prec_expr(221,false) ->;
sysPUSHQ(sysENDPROCEDURE())
endif
else
if nextitem() == "where" then
mishap('"where" FOUND WHERE NOT PERMITTED', [])
endif
endif;
enddefine;
define global syntax 7 ! = readpattern(%true%)
;;; The precedence must be less than that of doesmatch
enddefine;
applist([! readpattern where sysPUSHQ], sysprotect);
endsection;
===================================================================
Aaron
--
Aaron Sloman, ( http://www.cs.bham.ac.uk/~axs )
School of Computer Science, The University of Birmingham, B15 2TT, England
EMAIL A.Sloman@cs.bham.ac.uk
Phone: +44-121-414-4775 (Sec 3711) Fax: +44-121-414-4281
|