############################################################################ # # File: allof.icn # # Subject: Procedure for conjunction control operation # # Author: Robert J. Alexander # # Date: April 28, 1990 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # allof{expr1,expr2} -- Control operation that performs iterative # conjunction. # # Iterative conjunction permits a conjunction expression to be built # at run time which supports full backtracking among the created terms # of the expression. The computed expression can be of arbitrary # length, and is built via an iterative loop in which one term is # appended to the expression (as if connected with a "&" operator) per # iteration. # # Expr1 works like the control expression of "every-do"; it controls # iteration by being resumed to produce all of its possible results. # The allof{} expression produces the outcome of conjunction of all of # the resulting instances of expr2. # # For example: # # global c # ... # pattern := "ab*" # "abcdef" ? { # allof { c := !pattern , # if c == "*" then move(0 to *&subject - &pos + 1) else =c # } & pos(0) # } # # This example will perform a wild card match on "abcdef" against # pattern "ab*", where "*" in a pattern matches 0 or more characters. # Since pos(0) will fail the first time it is evaluated, the allof{} # expression will be resumed just as a conjunction expression would, # and backtracking will propagate through all of the instances of # expr2; the expression will ultimately succeed (as its conjunctive # equivalent would). # # Note that, due to the scope of variables in co-expressions, # variables shared between expr1 and expr2 must have global scope, # hence c in the above example must be global. # # The allof{} procedure models Icon's expression evaluation # mechanism in that it explicitly performs backtracking. The author of # this procedure knows of no way to invoke Icon's built-in goal # directed evaluation to perform conjunction of a arbitrary number of # computed expressions (suggestions welcome). # ############################################################################ # # Requires: co-expressions # ############################################################################ procedure allof(expr) local elist,i,x,v # # Initialize # elist := [] # expression list i := 1 # expression list index # # Loop until backtracking over all expr[2]s has failed. # while i > 0 do { if not (x := elist[i]) then # # If we're at the end of the list of expressions, attempt an # iteration to produce another expression. # if @expr[1] then put(elist,x := ^expr[2]) else { # # If no further iterations, suspend a result. # suspend v # # We've been backed into -- reset to last expr[2]. # i -:= 1 } # # Evaluate the expression. # if v := @\x then { # # If success, move on to the refreshed next expression. # i +:= 1 elist[i] := ^elist[i] } else # # If failure, back up. # i -:= 1 } end