diff options
Diffstat (limited to 'ipl/procs/allof.icn')
-rw-r--r-- | ipl/procs/allof.icn | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/ipl/procs/allof.icn b/ipl/procs/allof.icn new file mode 100644 index 0000000..1a2003c --- /dev/null +++ b/ipl/procs/allof.icn @@ -0,0 +1,112 @@ +############################################################################ +# +# 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 |