New implementations of IFMATCH and FILL
I have finally got round to implementing the proposed new implementations
for IFMATCH and FILL in WSL.
The old versions had two serious problems:
- There was an ambiguity in IFMATCH: does ~?foo mean "match an item
and store the result in foo" or "match against the current value of foo".
Currently, IFMATCH takes the former interpretation if the variable is
the empty sequence < >. For global variables, the result of an IFMATCH
depends on whether the variable is bound or not in some procedure further
up the (dynamic) call path. In practice, this means that if you want
to match against any binary IF statement, for example, then you
need to surround the IFMATCH by a local variable structure:
VAR < B := < >, S1 ;= < >, S2 := < > >:
IFMATCH Statement IF ~?B THEN ~*S1 ELSE ~*S2 FI
ELSE... ENDMATCH ENDVAR
- There used to be no way to interpolate the value of an expression
(eg @I^2) in a FILL: the value must be stored in a variable first.
The new syntax is as follows:
- New types for interpolation: ~?(expn), ~*(expn), ~?=var and ~*=var.
The first two have a single component of type T_Expression.
The expression is evaluated *before* the match or fill begins
and is then interpolated into the item. The ~?=var and ~*=var matches
can only appear *after* a corresponding ~?var, ~*var or ~+var.
They match against the previously matched value: they can *only*
appear in an IFMATCH, not in a FILL.
@One_Pattern_Type?, @Many_Pattern_Type?, @Any_Pattern_Type?,
@One_Int_Type?, @Any_Int_Type?, @One_Var_Type?, @Any_Var_Type?
S := FILL Statement v := ~?(e) ENDFILL
Names for the types are T_Cond_Int_One and T_Cond_Val_One
plus T_Name_Int_One and T_Name_Val_One
- Thanks to the new interpolation syntax, within an IFMATCH
the patterns ~?name, ~*name and ~+name will *always*
match against any current item (or list of items) and store
the resulting match in a new local variable. Any global
value of the variable is ignored. Also, there can be only one
occurrence of ~?name, ~*name or ~+name for each name:
any "backreference" to something previously matched
in the pattern should use the new syntax ~?=name or ~*=name.
IFMATCH Statement DO ~*S; ~*=S OD
will match against any DO loop whose body consists of a duplicated
sequence of statements, eg:
DO x := x + 1;
IF x > 3 THEN EXIT(1) FI;
x := x + 1;
IF x > 3 THEN EXIT(1) FI OD
- The interpolation types are used in IFMATCH to match
against the value of an expression. The variables in the expression
are always global variables, for example:
IFMATCH Statement IF ~?B THEN ~*S ELSE ~*(S) FI
ELSE ... ENDMATCH
will match any binary IF statement whose ELSE body is given
in the global variable S, while:
IFMATCH Statement IF ~?B THEN ~*S ELSE ~*=S FI
ELSE ... ENDMATCH
will match any IF statement whose ELSE body is the same
as the THEN body.
Note: matches are "loose" with respect to Lvalues and Expressions,
so that we can match an Lvalue against an Expression etc.
For example: IFMATCH Statement ~?v := ~?=v THEN ... ENDMATCH
will match when the current statement is an assign or assignment statement
whose LHS and RHS are the same.
Back to my home page.
Last modified: 23rd July 2009
De Montfort University, Leicester.