Scholarly article on topic 'Correct and Complete (Positive) Strategy Annotations for OBJ'

Correct and Complete (Positive) Strategy Annotations for OBJ Academic research paper on "Computer and information sciences"

CC BY-NC-ND
0
0
Share paper
Keywords
{"Declarative programming" / OBJ / "strategy annotations"}

Abstract of research paper on Computer and information sciences, author of scientific article — María Alpuente, Santiago Escobar, Salvador Lucas

Abstract Strategy annotations are used in several rewriting-based programming languages to introduce replacement restrictions aimed at improving efficiency and/or reducing the risk of nontermination. Unfortunately, rewriting restrictions can have a negative impact on the ability to compute normal forms. In this paper, we first ascertain/clarify the conditions ensuring correctness and completeness (regarding normalization) of computing with strategy annotations. Then, we define a program transformation methodology for (correct and) complete evaluations which applies to OBJ-like languages.

Academic research paper on topic "Correct and Complete (Positive) Strategy Annotations for OBJ"

URL: http://www.elsevier.nl/locate/entcs/volume71.html 20 pages

Correct and Complete (Positive) Strategy Annotations for OBJ *

Maria Alpuente1, Santiago Escobar 2, and Salvador Lucas 3

DSIC, Universidad Politécnica de Valencia, Spain.

Abstract

Strategy annotations are used in several rewriting-based programming languages to introduce replacement restrictions aimed at improving efficiency and/or reducing the risk of nontermination. Unfortunately, rewriting restrictions can have a negative impact on the ability to compute normal forms. In this paper, we first ascertain/clarify the conditions ensuring correctness and completeness (regarding normalization) of computing with strategy annotations. Then, we define a program transformation methodology for (correct and) complete evaluations which applies to OBJ-like languages.

Key words: Declarative programming, OBJ, strategy annotations.

1 Introduction

Strategy annotations are used in the OBJ family of languages4 (OBJ2 [6], OBJ3 [8], CafeOBJ [7], and Maude [3]) to avoid nontermination ([8], Section 2.4.4).

Example 1.1 The following OBJ program:

obj EXAMPLE is sorts Nat LNat . op 0 : -> Nat . op s : Nat -> Nat [strat (1)] .

op nil : -> LNat .

op cons : Nat LNat -> LNat [strat (1)] .

* Work partially supported by CICYT TIC2001-2705-C03-01, Acciones Integradas HI 20000161, HA 2001-0059, HU 2001-0019, and Generalitat Valenciana GV01-424.

1 Email: alpuente@dsic.upv.es

2 Email: sescobar@dsic.upv.es

3 Email: slucas@dsic.upv.es

4 As in [8], by OBJ we mean OBJ2, OBJ3, CafeOBJ, or Maude.

©2003 Published by Elsevier Science B. V.

op from : Nat -> LNat [strat (10)] . op sel : Nat LNat -> Nat [strat (12 0)] . op first : Nat LNat -> LNat [strat (1 2 0)] . vars X Y : Nat . var Z : LNat .

eq sel(s(X),cons(Y,Z)) = sel(X,Z) . eq sel(0,cons(X,Z)) = X . eq first(0,Z) = nil .

eq first(s(X),cons(Y,Z)) = cons(Y,first(X,Z)) . eq from(X) = cons(X,from(s(X))) .

specifies an explicit strategy annotation for the list constructor cons which disables replacements on the second argument. In this way, we can ensure that computations with this program are terminating (see Example 4.4 below for a formal justification of this claim).

Termination of rewriting under strategy annotations has been studied in a number of papers [5,13,14]. Unfortunately, using rewriting restrictions may cause incompleteness, i.e., normal forms of input expressions could be unreachable by restricted computation. For instance, using the program in Example 1.1 we are not able to compute the list of integers that corresponds to the evaluation of first(s(0),from(0)). As we show below, the evaluation of this expression stops yielding the term cons(0,first(0,from(s(0)))). On the other hand, from the user's point of view, this must be thought of as a kind of incorrect evaluation, when normal forms are expected as the result of a computation.

We show that these problems can be solved by using a program transformation while we are still able to preserve termination of computations.

2 Preliminaries

Given a set A, P(A) denotes the set of all subsets of A. Let R C A x A be a binary relation on a set A. We denote the reflexive closure of R by R=, its transitive closure by R+, and its reflexive and transitive closure by R*. An element a G A is an R-normal form, if there exists no b such that a R b; NF# is the set of R-normal forms [1]. We say that b is an R-normal form of a (written a R! b), if b is an R-normal form and a R*b. We say that R is terminating iff there is no infinite sequence a1 R a2 R a3 •••. Throughout the paper, X denotes a countable set of variables and F denotes a set of function symbols {f, g,...}, each having a fixed arity given by a function ar : F ^ N. We denote the set of terms built from F and X by T(F, X). A context C [] is a term from T(F U {□}, X), where □ is a new constant symbol. A term is said to be linear if it has no multiple occurrences of a single variable. Terms are viewed as labelled trees in the usual way. Positions p,q,... are represented by

chains of positive natural numbers used to address subterms of t. By A, we denote the empty chain (referring to the root of the term). Given positions p, q, we denote its concatenation by p.q. If p is a position, and Q is a set of positions, p.Q is the set {p.q | q E Q}. By Pos(t), we denote the set of positions of a term t. Positions of non-variable symbols in t are denoted as PosF(t) and PosX(t) are the variable occurrences. The subterm at position p of t is denoted as tlP and t[s]p is the term t with the subterm at position p replaced by s. The symbol labelling the root of t is denoted as root(t) and root(t,p) is root(t|p). A substitution is a mapping a : X — T(F, X) which homomorphically extends to a mapping a : T(F, X) — T(F, X).

A rewrite rule is an ordered pair (l, r), written l — r, with l,r E T(F, X), l E X and Var(r) C Var(l). The left-hand side (lhs) of the rule is l and the right-hand side (rhs) is r. A TRS is a pair R = (F, R) where R is a set of rewrite rules. L(R) denotes the set of lhs's of R. R is left-linear if L(R) is a set of linear terms. Given R = (F, R), we consider F as the disjoint union F = C ^V of symbols c EC, called constructors, and symbols f EV, called defined functions, where V = {f | f (l\,. ..,lk) — r E R} and C = F — V. Then, T(C, X) is the set of constructor terms. Let PosD(t) (resp. PosC(t)) be the set of positions of defined (resp. constructor) symbols of term t. An instance a(l) of a lhs l E L(R) is a redex. A term t E T(F, X) rewrites to s (at position p), written t —R s (or just t — s), if tlp = a(l) and s = t[a(r)]p, for some l — r E R, p E Pos(t) and substitution a. A term is a normal form if it is a —-normal form. Let NFR be the set of normal forms of R. A term t is a head-normal form if it cannot be rewritten to a redex. Let HNFR be the set of head-normal forms of R. A TRS is terminating if — is terminating.

3 Rewriting with syntactic replacement restrictions

A mapping f : F — P(N) is a replacement map (or F-map) if f(f) C {1,... ,ar(f)} for all f E F [9]. The inclusion ordering C on P(N) extends to an ordering □ on MF, the set of all F-maps: f □ f if for all f E F, f(f) C i'(f). In this way, fi □ f means that f considers less positions than f for reduction. We also say that f is more restrictive than (or equally restrictive to) f. Given a TRS R = (F,R), we write MR rather than MF. The set of f-replacing positions Pos^(t) of t E T(F, X) is: Pos^(t) = {A} if t E X, and P os^(t) = {A} U Ui^(root(t)) i.P os"(t\i) if t EX. In context-sensitive rewriting (CSR [9]), we (only) rewrite replacing redexes: t f-rewrites to s (written t s) if t — R s and p E Pos^ (t). The —^-normal forms are called f-normal forms. NF^ is the set of f-normal forms of R. The f-normal forms include all normal forms of R (but not viceversa). A TRS R is f-terminating if is terminating. The canonical replacement map fCz"1 is the most restrictive replacement map which ensures that the non-variable subterms of the left-hand sides of the rules of R are replacing. Note that fCzn

is easily obtained from R: for all f eT and i E {1,..., ar(f)},

i E /T(f) iff E L(R),p E Posf(l), (root(l,p) = f Ap.i E Posf(l))

Let CMr = {/ E Mr | /i^" □ /} be the set of replacement maps which are less restrictive than or equally restrictive to /R".

4 ^-strategies

A (positive) local strategy (or ¿"-strategy) for a k-ary symbol f eT is a sequence p(f) of integers taken from {0,1,...,k} which are given in parentheses (see Example 1.1). A mapping p that associates a local strategy p(f) to every f E T is called an E-strategy map [19]. Algebraic languages such as OBJ2, OBJ3, CafeOBJ and Maude admit the specification of E-strategies. Symbols without an explicit local strategy are given a default strategy whose concrete shape depends on the language considered5. Given an OBJ program P, we (separately) consider the corresponding TRS R which consists of the set of rewriting rules in P and the E-strategy map p that corresponds to its strategy annotations. Semantics of OBJ programs under a given E-strategy map p is given by means of a mapping evalv : T(T, X) ^ P(T(T, X)) (from terms to their sets of 'computed values'). Following [17,19] we describe evalv by using a reduction relation on pairs of labelled terms and positions.

Let L be the set of all lists consisting of natural numbers. By Ln, we denote the set of all lists of natural numbers not exceding n E N. We use the signature TL = {fL I f eTAL e Car(f)} and labelled variables XL = {xnil | x E X}. An E-strategy map p for T is extended to a (labelling) mapping from T(T, X) to T(TL, XL) as follows:

I Xnil if t = x EX

P(t) = <

I Uf )(p(tl),..., p(tk)) if t = f {tu ...,tk)

The mapping erase : T(TL, XL) ^ T(T, X) removes labellings from symbols in the obvious way. Given a TRS R = (T, R) and an E-strategy map p for T, the binary relation on T(TL, XL) x N+ (i.e., pairs (t,p) of labelled terms t and positions p) is [17,19]: (t,p) (s, q) if and only if p E Pos(t) and either

(i) root(t,p) = fnil, s = t and p = q.i for some i; or

(ii) tip = fi:L (t\, ...,tk) with i> 0, s = tfL(ti,.. .,tk )]p and q = p.i; or

(iii) tip = fo:L (ti,.. .,tk), erase(tip) is not a redex, s = t[fL (ti,... ,tk )]p, q = p; or

(iv) tip = fo:L(ti,...,tk) = a(l'), erase(l') = l, s = t[a(p(r))]p for some l ^ r E R and substitution a, q = p.

We let eval^(t) = {erase(s) E T(T, X) | (p(t), A) ^ (s, A)} [17,19]. A TRS

5 For instance, in Maude, the default local strategy associated to a k-ary symbol f, is (12 • • • k 0), see [4].

R is ^-terminating if, for all t E T(F, X), there is no infinite —^-rewrite sequence starting from (p(t), A). An OBJ program P is terminating if the corresponding TRS R is ^-terminating [13].

4.1 E-strategies and context-sensitive rewriting

Rewriting with strategy annotations is closely related to CSR. Given an E-strategy map p for F, we define E MF as follows: jf(f) = {i E p(f) | i = 0} for all f E F, where e E L means that item e appears somewhere within the list L. We will drop superscript p from if no confusion arises. Moreover, we also write p E CMR meaning that E CMR.

Example 4.1 The TRS R:

sel(0,cons(x,z)) — x

sel(s(x),cons(y,z)) — sel(x,z)

first(0,z) — nil

first(s(x),cons(y,z)) — cons(y,first(x,z))

from(x) — cons(x,from(s(x)))

together with the replacement map

j(s) = j(cons) = j(from) = {1} and j(sel) = j(first) = {1, 2}

correspond to the OBJ program in Example 1.1.

Every -reduction step issued on (t,p) correspond to a -rewriting step on the unlabelled version erase(t) of t (or erase(t) just remains unchanged).

Theorem 4.2 [13] Let R be a TRS and p be an E-strategy map. Let t E T(Fl, Xl), and p E Pos^(erase(t)) be s.t. root(t,p) = fL for some suffix L of p(f). If (t,p) (s,q), then q E Pos^(erase(s)) and erase(t) erase(s).

Termination of OBJ programs and termination of CSR are also related.

Theorem 4.3 [13] An OBJ program P with E-strategy map p is terminating if the corresponding TRS R is -terminating.

Termination of CSR has been studied in a number of papers, see [12] for an overview of the different methods for proving termination of CSR.

Example 4.4 Consider R and j as in Example 4.1. The ¡-termination of (a superset of) R is demonstrated in Example 7 of [2]. Hence, by Theorem 4.3, the OBJ program in Example 1.1 is terminating.

5 Correctness and completeness

A rewriting semantics for a TRS R = (F, R) is a mapping S : T(F, X) — P(T(F, X)) such that, for all t E T(F, X) and s e S(t), t —R s [15]. Note that, given a TRS R and an E-strategy map p, evalf is a rewriting semantics for R. A semantics S is deterministic (resp. defined) if Wt E T(F, X), |S(t)| < 1

(resp. |S(t)| > 1). In general, evalv is not deterministic or defined. Note that p-termination of R implies definedness of evalv.

The semantics which is most commonly considered in functional programming is the set of constructor terms that R is able to produce in a finite number of rewriting steps (eval(t) = {s E T(C, X) | t s}). Other kinds of semantics often considered for R are, e.g., the set of all possible reducts of a term which are head-normal forms (hnf(t) = {s E HNFR | t ^^ s}), or normal forms (nf(t) = hnf(t) fl NFR). Thus, given a semantics S for R (e.g., S E {eval, hnf, nf}), a different rewriting semantics for R (e.g., evalv) is:

correct (w.r.t. S) if evalv(t) C S(t) for all t E T(T, X), and

complete (w.r.t. S) if, S(t) C evalv(t) for all t E T(T, X).

Computations with OBJ programs produce expresions (by means of evalv) called E-normal forms (ENFs). Such terms are not generally normal forms (i.e., terms without redexes). Therefore, evalv is not guaranteed to be either correct or complete w.r.t. nf. In fact, we have the following:

Theorem 5.1 [13] Let R = (C W D, R) be a TRS and p be a E-strategy map such that for all f ED, p(f) ends in 0. If s E eval^(t), then s is a /-normal form of t.

Requiring that p(f) ends in 0 for all f eD is essential in our development (see also [4] for a thorough analysis of the relevance of this requirement). Thus, we say that a E-strategy map p is regular 6 if this condition holds.

If the strategy annotations are 'compatible' with the canonical replacement map, we can ensure that the E-strategy is correct w.r.t. hnf.

Theorem 5.2 [13] Let R = (CWD, R) be a left-linear TRS and p be a regular E-strategy map such that p E CMR. If s E eval^(t), then s is a head-normal form.

If we restrict the attention to the computation of values (i.e., constructor terms), then CSR is powerful enough to compute them. Given TRS R = (T, r) = (CWD, R) and BCC, we let /R to be /R(c) = {1,..., ar(c)} for all c EB and /R(f) = /icRl"{f) if f ET-B. Note that /R E CMr.

Theorem 5.3 [9] Let R = (T, R) = (C W D, R) be a left-linear TRS, BCC and / E MF be such that /R □ /. Let t E T(T, X), and 5 E T(B, X). Then, t 5 iff t^l 5.

Theorem 5.3 is very easy to use in sorted signatures (as in OBJ programs), since, given a term t (of sort t), we are able to establish the set of constructors BCC which should be considered (namely, the constructor symbols of sort t). Unfortunately, Theorem 5.3 does not directly apply to OBJ computations, as they must obey the order of evaluation expressed by the strategy annotations. However, we have the following.

This terminology is used in [20], with a slightly different meaning.

Theorem 5.4 Let R = (F,R) = (C^V,R) be a left-linear, confluent TRS and BC C. Let p be a regular E-strategy map such that R is p-terminating. Let t E T(F, X) and 8 E T(B, X). If jR Q then t —! 8 iff 8 E evalf(t).

For instance, p can be used to compute the value of every expression of the sort Nat in the OBJ program in Example 1.1 (since Q ). This is

not true for expressions of the sort LNat as the following example shows.

Example 5.5 The evaluation of expression t = first(s(0),from(0)) of sort LNat using the program in Example 1.1 yields (we use the version 1.0.5 of the Maude interpreter 7 but other interpreters behave likewise8 ):

Maude> reduce first(s(0),from(0)) .

reduce in EXAMPLE : first(s(0), from(0)) .

rewrites: 2 in -10ms cpu (0ms real) (~ rewrites/second)

result LNat: cons(0, first(0, from(s(0))))

Note that cons(0,first(0,from(s(0)))) is not a normal form. However, t —* cons(0,nil) E T(C, X), i.e., cons(0,nil) is a value of t which cannot be obtained by using the Maude interpreter.

Correctness of OBJ computations w.r.t. nf can also be achieved:

(i) Nagaya shows that if p(f) contains all indices 0,1,...,ar(f) for each symbol f eF, and p(f) ends in 0 for defined symbols f EV, then evalf is correct w.r.t. nf (Theorem 6.1.12 in [17]).

(ii) Nakamura and Ogata show that given a strategy map p, if evalf is correct w.r.t. hnf, then evalf is correct w.r.t. nf for any p' given by p'(f) = p(f )++(ii ••• in) for all symbol f eF (where '++' appends two lists, and {i1, ...,in} = {1,..., ar(f)} — jf(f)) (Theorem 3.2 in [19]).

For instance, p as given in Example 1.1 is correct w.r.t. hnf (use Theorem 5.2). Moreover, since the OBJ program in Example 1.1 is p-terminating, evalf is defined. Thus, the evaluation of every term t yields a head-normal form of t (i.e., p can be thought of as being head-normalizing). Unfortunately evalf is not defined anymore: the head-normalizing behavior of p gets lost.

Example 5.6 Consider the program in Example 1.1 with p'(cons) = (1 2) and p'(f) = p(f) for every other symbol f (rename the program to EXAMPLE-INF). Consider again the evaluation of t = first(s(0),from(0)):

Maude> reduce first(s(0),from(0)) .

reduce in EXAMPLE-INF : first(s(0), from(0)) .

Segment violation

7 Available at http://maude.csl.sri.com/system/.

8 We have reproduced all our experiments using the OBJ3 interpreter v. 2.0 (available at http://www.kindsoftware.com/products/opensource/obj3/OBJ3/) and the CafeOBJ interpreter v. 1.3.1 (available at http://www.ipa.go.jp/STC/CafeP/cafe.html).

The problem is that the evaluation of t, i.e., the evaluation of

p'(t) = first(i 2 0) (s(i)(0nii ),from(i o)(0nii))

using —p does not terminate (we underline the contracted redexes):

(first(i 2 o) (s(i) (0nii),from(i o)(0nii)), A)

(first(2 o)(s(i) (0nii ),from(i 0) (0nil)), 1) (first(2 0)(snil (0nil ),from(i o)(0nil)), 1-1) (first(2 o)(snil(0nil),from(i o)(0nil)), 1) (first(2 o)(snil(0nil),from(i o)(0nil)),A) (first(o) (snii(0nii),from(i o) (0nii)), 2) (first(o) (snii(0nii),from(o) (0nii)), 2.1) (first(o) (snii(0nii),from(o) (0nii)), 2)

(first(o) (snii(0nii),cons(i 2) (0nil,from(i o) (s(i) (0nil)))), 2) (first(o) (snii(0nii),cons(2) (0nii ,from(i o) (s(i) (0nii)))), 2) (first(o) (snil (0nil) ,consnil (0nil ,from(i o) (s(i) (0nil)))) , 2-2) (first(o) (snil (0nil) ,consnii(0nii,from(o) (snil (0nil)))), 2.2)

The Maude interpreter 'shows' this infinite sequence as a 'segment violation'.

Thus, the p-termination of R (see Example 4.4) does not ensure defined-ness of evalp' as the previous results by Nagaya, and Nakamura-Ogata may suggest. Moreover, evalp was able to obtain head-normal forms that evalp' does not obtain (compare the evaluation of t in Examples 5.5 and 5.6). Example 5.6 also shows that requiring p-termination in Theorem 5.4 is essential for ensuring correct and complete evaluations (note that R and p' in Example 5.6 fulfill all requirements in Theorem 5.4, except for p'-termination).

In the following section, we propose a solution to (partially) overcome this problem which is based on program transformation.

6 Program transformations for complete evaluations

The discussion and examples in the previous section suggest to isolate the replacement restrictions which are needed to achieve the head-evaluation of a term t (which, at least, requires /RR", see Theorem 5.2) from the restrictions which are needed to get them within a constructor context C[ ] E T(BU {□}, X) for some B C C (which, at least, requires /R, see Theorem 5.4). In practice, we only need (and want) to fix the sort t of input expressions we want to evaluate in order to fix the 'interesting' constructor terms. Assume that symbols f E T are sorted by: f : t1 x • • • x Tk — t'. The (output) sort of f is sort(f) = t'. Variables x EX also have a sort, sort(x). We also assume that all terms are well sorted everywhere. The sort of a term t is the sort of its outermost symbol. Given a sort t, let C* C C be the set of constructor symbols that can be found in constructor terms of sort t . For instance, CNat = {0, s} and C£Nat = {0, s, nil, cons}. We introduce a set

C of fresh constructor symbols: they are renamed versions C of the original constructors c EC* that evaluate all the arguments.

The renaming of constructor symbols c EC* into new constructor symbols C E C is performed by the rules

quoteT, (c(xi,.. . ,Xk)) — c'(quoteTi (xi),.. . ,quoteTfc (xk))

where c,c' : t1 x ••• x Tk — t'. Let Quote be the set containing all these symbols: Quote = {quoteT, | 3c EC**, sort(c) = t'}. The evaluation of a term t would proceed by reducing quotescrt(t)(t). The obtained value is built by using symbols in C' only. After the evaluation, new symbols unquoteT, : t' — t ' are used to reverse the renamings. For each constant b EC*, we add a rule

unquotescrt(6) (b') — b

For each c EC* such that c : t1 Tk — t', k > 0, and (c) = {1,..., k},

we add a rule

unquoteT,(c'(xi,. . . ,Xk)) — c(unquoteTi(xi),. . . ,unquoteTfc(xk))

Finally, for each c EC* such that c : ti x ••• x Tk — t ', k > 0, and (c) = {1,...,k}, we consider a new symbol fc : ti Tk — t'; we add two rules

unquoteT, (cl(xi,. . . ,xk)) — fc(unquoteTi (xi),. . . ,unquoteTfc (xk))

fc(xi,. ..,xk) — c(xi, ...,xk)

We collect these new symbols together in a new set Unquote. Denote the TRS obtained from joining these rules together with those of R as ET(R). The transformed TRS ET (R) includes the rules of the original TRS R. The added rules manage the appropriate quoting and unquoting of constructor symbols: quoted constructors enable the evaluation of all their arguments; after evaluating them, symbol unquote restores the original constructor c. Therefore, we also extend the (original) E-strategy p: let p' = EmapT(p) as follows: p'(f) = p(f) if f EF, p'(c') = (1 ••• ar(c')) if c' E C, p'(quoteT,) = p' (unquoteT,) = (1 0) for all sort t' , and p(fc) = (1 ••• ar(c) 0) for each c EC* such that jf(c) = {1,... ,ar(c)}. In the following results, evalf, uses p' and ET(R) to evaluate terms (evalf uses p and R, as above). Our transformation is correct9 in a very general setting.

Theorem 6.1 Let R = (F,R) = (C W V,R) be a TRS. Let p be a regular E-strategy map. Let t E T(F, X) be such that sort(t) = t and 8 E T(C). Let R' = ET(R) and p' = EmapT(p). If 8 E evalf,(unquoteT(quoteT(t))), then

t —*R 8.

Thus, no 'unexpected' value can be obtained when evaluating t E T(F, X) of sort t as unquoteT(quoteT(t)). Moreover, no constructor term (of sort t) obtained by using p and R gets lost when EmapT (p) and ET (R) are used instead.

9 In this section we do not use 'corrrect' and 'complete' in the technical sense defined in Section 5 because we need to consider two rewrite systems rather than only one.

Theorem 6.2 Let R = (F, R) = (C W D, R) be a TRS. Let p be a regular E-strategy map. Let t E T(F, X) be .such that sort(t) = t and 8 E T(C). Let R' = Er(R) and p' = EmapT(p). If 8 E evalp(t), then 8 E evalp (unquoteT (quoteT (t))).

Completeness of the transformation (regarding the computation of constructor terms) requires some additional conditions.

Theorem 6.3 Let R = (F, R) = (C W D, R) be a left-linear, confluent TRS. Let p be a regular E-strategy map such that p E CMR, and R is p-terminating. Let t E T(F, X) be such that sort(t) = t and 8 E T(C). Let R' = ET(R) and p' = EmapT(p). If t —R 8, then 8 E evalp(unquoteT(quoteT(t))).

Note that, in contrast to Theorem 5.4, we can now start with any E-strategy map p E CMR:

Example 6.4 The following OBJ program:

obj EXAMPLE-STR is sorts Nat LNat . ops 0 0' : -> Nat . ops s s' : Nat -> Nat [strat (1)] . ops nil nil' : -> LNat . op cons : Nat LNat -> LNat [strat (1)] . op cons' : Nat LNat -> LNat [strat (12)] . op fcons : Nat LNat -> LNat [strat (12 0)] . op from : Nat -> LNat [strat (10)] . op sel : Nat LNat -> Nat [strat (12 0)] . op first : Nat LNat -> LNat [strat (1 2 0)] . ops quote unquote : Nat -> Nat [strat (10)] . ops quote' unquote' : LNat -> LNat [strat (10)] . vars X Y : Nat . var Z : LNat .

eq sel(s(X),cons(Y,Z)) = sel(X,Z) . eq sel(0,cons(X,Z)) = X . eq first(0,Z) = nil .

eq first(s(X),cons(Y,Z)) = cons(Y,first(X,Z)) . eq from(X) = cons(X,from(s(X))) . eq quote(0) =0' .

eq quote'(cons(X,Z)) = cons'(quote(X),quote'(Z)) .

eq quote'(nil) = nil' .

eq quote(s(X)) = s'(quote(X)) .

eq unquote(0') = 0 .

eq unquote(s'(X)) = s(unquote(X)) .

eq unquote'(nil') = nil .

eq unquote'(cons'(X,Z)) = fcons(unquote(X),unquote'(Z)) . eq fcons(X,Z) = cons(X,Z) .

is the transformed version of the OBJ program in Example 1.1. Now, the evaluation of term unquote'(quote'(first(s(0),from(0)))) yields:

Maude> reduce unquote'(quote'(first(s(0), from(0)))) . reduce in EXAMPLE-STR : unquote'(quote'(first(s(0), from(0)))) . rewrites: 11 in -10ms cpu (0ms real) (~ rewrites/second) result LNat: cons(0, nil)

Note the difference between 'unquoting' rules for symbols s' and cons'. The unquoting of cons' is indirect; the obvious short-cut:

unquote(cons'(X,Z)) = cons(unquote(X),unquote'(Z))

in the program in Example 6.4 does not work: the reason is that after applying this rule, the second argument of cons remains non-replacing. For instance, by using such a rule (instead of the last two rules of the program in Example 6.4) the evaluation of unquote'(quote'(first(s(0),from(0)))) would yield

cons(0,unquote'(nil'))

This is solved by introducing the intermediate defined symbol fcons which first evaluates its arguments (thus performing the renaming) and then reduces to cons. In this sense, the explicit annotation (1 2 0) is also crucial for symbol fcons; otherwise, the interpreter could associate a default strategy which does not permit the renamings (for instance, OBJ3 associates the strategy (0 12 0) to fcons; with this default annotation, we would also obtain cons(0,unquote'(nil')) instead of the desired value).

Unfortunately, the previous transformation does not preserve termination of the original program (proved in Example 4.4).

Example 6.5 The evaluation of t = quote'(from(0)) yields:

Maude> reduce quote'(from(0)) .

reduce in EXAMPLE-STR : quote'(from(0)) .

ADVISORY: closing open files. Debug(1)> Bye.

where we were forced to abort the non-terminating execution. Again, the problem is that the evaluation of t, i.e., the evaluation of

p(t) = quote'(i o) (from(i o)(0nii))

does not terminate:

(quote'(i o)(from(i o) (0nil)), A)

— (quote'(o) (from(i o)(0nil)), 1)

— (quote'(o) (from(o) (0nii)), 1.1)

— (quote'(o) (from(o) (0nii)), 1)

— (quote'(o) (cons(i) (0nii,from(i o)(s(i o)(0nil))), 1)

— (quote'(o) (consnii (0nii ,from(i o) (s(i o)(0nil))), 1.1)

—p (quote'(o) (consnil (0"il ,from(i o) (s(i o)(0nil))), 1) —p (quote'(o) (consnil (0nil ,from(i o) (s(i o)(0nil))), A) —p (cons' (i 2) (quote(i o) (0nil ),quote'(i o) (from(i o) (s(i o) (0nil)))), A)

—+ (cons'(2) (0'nil,quote'(i o) (from(i o) (s(i o) (0nil)))), 2)

6.1 Preserving completeness and termination

Example 6.5 shows that the annotation p'(quoteT) = (10) may cause non-termination. We can try to avoid this problem by restricting the E-strategy for quoteT to (0). In this case, however, we need to add new rules to enable the evaluation in some alternative way. In [16], we have introduced a program transformation which is able to achieve a similar effect. In the following, by an outermost (occurrence of a) defined symbol in a term t, we mean a defined symbol which only has constructor symbols above it in t. The new constructors are now introduced in computations by the contraction of redexes of outermost defined symbols f. Thus, we add both new defined symbols f', which will show up when these outermost defined f symbols emerge, and new rules for defining these symbols. The new rules f'(l1,. ..,lk) — r' come from the original ones f (l1,. ..,lk) — r as follows: occurrences of outermost defined symbols g in r are renamed in r' as g'; occurrences of constructor symbols c above those g in r are renamed in r' as c'; occurrences of variables x in r which only have constructor symbols above them are marked as quotesori(^)(x) in r'. Now (in contrast to the previous transformation) symbols quoteT are also intended to rename outermost defined symbols f (of sort t) as their alias f' (of the same sort). In order to simplify the transformation, it is tempting not to take into account the number of extra rules which are added to the transformed TRS and introduce new rules f'(l1,...,lk) — r' for each defined symbol f. Unfortunately, this may unnecessarily cause non-termination.

Example 6.6 Consider the rule

from(x) — cons(x,from(s(x)))

of our running example. We then introduce the rule:

from'(x) — cons'(quote(x),from'(s(x)))

For example, in the evaluation of t = first(s(0),from(0)) in Example 5.5, the symbol from does not emerge as outermost: roughly speaking, the only possibility is that either the right-hand side of a rule defining first contains a variable of sort LNat having only constructor symbols above, or that from is outermost in some right-hand side. This does not happen in our example. Thus, we do not need the rule which would introduce non-termination since reductions are allowed on both arguments of cons'. For this reason, we perform a more accurate analysis of the required additional rules by carefully identifying the outermost defined symbols that can emerge during the evaluation of a given expression.

The following notations are auxiliary [16]: Given f : t1 x ... x Tk — t, the

sorts of arguments of f are gathered in the setio sortarg(f) = {t1,..., Tk}.

Given a term t E T(F, X),

• CVar(t) = {x E Var(t) | 3p E Pos(t), tip = x AV q < p, q E Posc(t)} is the set of constructor variables of t, i.e., variables of t having a maximal proper prefix which only points to constructor symbols. We also use CT = {c E C i sort(c) = t}.

• The set of possible sorts for symbols arising by instantiation of a constructor variable x is CVSort(sort(x)) where, given a sort t,

CVSort(T) = {t}U U CVSort(T')

t' E sortarg(c)

• Vouter(t) = (Jxecvar(t){f E D i sort(f) E CVSort(sort(x))} are the defined symbols which can root the subterms introduced in t by instantiation of constructor variables of t (that is, which emerge as outermost in t after instantiation).

Example 6.7 Consider the term t = cons(y,first(x,z)), where sort(y) =

Nat and first : Nat x LNat — LNat. Then,

• CVar(t) = {y}; note that sort(y) = Nat.

• CVSort(Nat) = {Nat} and

CVSort(LNat) = {LNat} U U CVSort(T')

c E {nil,cons}

t' E sortarg(c)

= {LNat} U CVSort(Nat) U CVSort(LNat)

= {LNat, Nat}

• Vouter(t) = {f ED i sort(f) E CVSort(sort(y))} = {f eD | sort(f) E {Nat}} = {sel}.

Given a TRS R = (F, R) = (C W D, R) and f eD,

• outrhsR(f) C D contains the outermost defined symbols in rhs's of the f-rules: outrhsn(f) = Uf(i1 ,,„,ik)^reR{root(r,p) | p E Vosv(r) AV q < p. q E Posc(r)}.

• VrhsR(f) CD is the set of outermost defined symbols which can appear by instantiation of constructor variables in rhs's of the f-rules: VrhsR(f) = Uf (ii„„iik )^reRVouter(r).

• newouterR(f) = outrhsR(f) U VrhsR(f).

10 Here, we disregard from the ordering of the argument sorts (i.e., we do not use a list of sorts) since it is not important for our purposes.

Example 6.8 Consider the TRS R in Example 4.1 (assume the sorts as given in the signature of the original OBJ program in Example 1.1). We have:

• outrhsR(sel) = {sel} and outrhsR(first) = {first}. Let us develop the first one: the rules defining sel are

sel(0,cons(x,z)) — x and sel(s(x),cons(y,z)) — sel(x,z).

The rhs of the first rule is a variable; hence it does not contribute to outrhsR(sel). On the other hand, the only outermost defined symbol of the second rhs is sel; hence, outrhsR(sel) = {sel}.

• VrhsR(sel) = Vouter(x) U Vouter(sel(x,z)) = Vouter(x) = {sel} (note that sort(x) = Nat) and, according to Example 6.7:

VrhsR(first) = Vouter(nil) U Vouter(cons(y,first(x,z))) = Vouter(cons(y,first(x,z))) = {sel}

• Finally, newouterR(sel) = outrhsR(sel) U VrhsR(sel) = {sel} and newouterR(first) = outrhsR(first) U VrhsR(first) = {first, sel}.

In contrast to transformation ET, here we are mainly interested in evaluating term f (t1, ...,tk) for a given defined symbol f E D. Given R = (F,R) = (C W D, R) and f eD, we let Dfn CD be:

DR = {f }U |J D

gtnewoutern(f)

Df contains the outermost defined symbols which arise when a (well sorted) f-rooted term f (t1, ...,tk) is arbitrarily rewritten. In practice, since the definition of Df is mutually recursive, we must consider all possible equations

DR = {fi} U UgeneMjoutern(h) DR

DR = {fn} U UgenewouterR(fn) DR

(where f1 = f and f2 ,...,fn are all the defined symbols successively occurring in newouterR(f1) U • • • U newouterR(fn)) and compute the (least) solutions Df,... ,Df by using fixpoint techniques (see [11,16]).

Example 6.9 (Continuing Example 6.8) Since newouterR(sel) = {sel} and newouterR(first) = {first, sel}, we have the system:

VRirst = {first} U VRel U DRirst

DR-1 = {sel} U DR-1

which has a simple solution: Dfirst = {first, sel} and D-^f1 = {sel}. Note that from E DRrst and from E DR1

The set evf (F, X) of terms is given as follows: (1) X C evf (F, X), (2) g(t) E evf (F, X) if g E DR, and (3) c(ti, ...,tk) E evf (F, X) if c E C*sort(f) and ti,...,tk E evf (F, X). If we do not require (1) (and change the inductive case (3) to be c(ti,. ..,tk) E gevf (F, X) if c E C*sort(f) and ti,...,tk E gevf (F, X)), then we are defining the set gevf (F, X). Roughly speaking, if we rewrite on a term t = g(t) for some g E Df, then every possible reduct of t belongs to evf (F, X). If t is ground, then we only need to consider gevf (F, X).

We now define the program transformation. First, we give the new signature. Note that the transformation is parametric w.r.t. a TRS R = (F,R) = (C WD, R) and a defined symbol f eD.

Definition 6.10 Given a TRS R = (F ,R) = (CWD,R) and f eD, we let Ff = FWC' WD' W Quote W Unquote, where: d EC' & c E C*sort{f) A ar(c') =

ar(c) and g' E D' & g EDfn A ar(g') = ar(g). Quote and Unquote are as above.

The transformation introduces rules to deal with the different symbols that we consider, according to the informal description above.

Definition 6.11 [Transformation V] Let R = (F, R) = (C W D, R) be a TRS and f ED. We let Vf (R) = (Ff ,R U S U Q U U), where:

• S = {g'(7) — Kf (r) | g(l) — r E R A g E DR}, where

Kf (x) = qu^^o^x)^ for x E X, Kf (g(t)) = g'(t) if g E DR, and

Kf (c(t)) = c'(Kf (t)) if c EC.

• Rules in Q define symbols quoteT in order to rename external constructors c eCS (where t = sort(f)) to constructors c' E C where c,c' : t1 x • • • XTk — t', and outermost application of g E Df to outermost applications of the corresponding g' eD'.

Q = {quoteT,(c(xi,... ,xk)) — c'(quoteTi(xi),... , quoteTk(xk)) | c EC%}

U{quotesort(g)(g(x1,...,xk)) — g'(x1,...,xk) | g EDR} • Rules in U define symbols in Unquote exactly as in the previous transformation ET.

Given an ^-strategy map p, we define the new ¿"-strategy map p'; we let p' = Emapf (p) as follows: p'(g) = p(f) if g E D, p'(g') = p(g) if g E Df, p'(c) = p(c) if c E C, and p(c') = (1 • • • ar(c')) if c' E C', p(quoteT) = (0) and p(unquoteT) = (1 0) for all sort t; and p(fc) = (1 • • • ar(c) 0) for each c E CScrt(f) such that ^(c) = {1,...,ar(c)}.

For the new transformation, we have similar results as for the simpler one.

Theorem 6.12 Let R = (F, R) = (CWD, R) be a TRS. Let p be a regular E-strategy map. Let f ED, t E evf (F, X), and 5 eT(C ). Let R' = Vf (r) and p' = Emapf (p). If 5 E evalv, (unquotesort(t)(qUOtesOrt(t)(t))), then t —R 5.

Theorem 6.13 Let R = (F, R) = (CWD, R) be a TRS. Let p be a regular E-strategy map. Let f eD, t E evf (F, X), and 8 eT(C). Let R' = Vf (R) and p' = Emapf (p). If 8 E evalv(t), then 8 E evalp(unquotesort(t)(quotesort(t)(t))).

Theorem 6.14 Let R = (F,R) = (CWD,R) be a left-linear, confluent TRS. Let p be a regular E-strategy map such that p E CMR and R is p-terminating. Let f E D, t E evf (F, X), and 8 E T(C). Let R' = Vf (R) and p' = Emapf (p). If t —R 8, then 8 E evalp(unquotesort(t)(quotesoH(t)(t))).

Example 6.15 The following OBJ3 program:

obj EXAMPLE-TR is sorts Nat LNat . ops 0 0' : -> Nat . ops s s' : Nat -> Nat [strat (1)] . ops nil nil' : -> LNat . op cons : Nat LNat -> LNat [strat (1)] . op cons' : Nat LNat -> LNat [strat (12)] . op fcons : Nat LNat -> LNat [strat (12 0)] . op from : Nat -> LNat [strat (10)] . ops sel sel' : Nat LNat -> Nat [strat (12 0)] . ops first first' : Nat LNat -> LNat [strat (12 0)] . op quote : Nat -> Nat [strat (0)] . op unquote : Nat -> Nat [strat (10)] . op quote' : LNat -> LNat [strat (0)] . op unquote' : LNat -> LNat [strat (10)] . vars X Y : Nat . var Z : LNat .

eq se1(s(X),cons(Y,Z)) = se1(X,Z) . eq se1(0,cons(X,Z)) = X . eq first(0,Z) = nil .

eq first(s(X),cons(Y,Z)) = cons(Y,first(X,Z)) . eq from(X) = cons(X,from(s(X))) . eq sel'(s(X),cons(Y,Z)) = sel'(X,Z) . eq sel'(0,cons(X,Z)) = quote(X) . eq first'(0,Z) = nil' .

eq first'(s(X),cons(Y,Z)) = cons'(quote(Y),first'(X,Z)) . eq quote(0) =0' .

eq quote'(cons(X,Z)) = cons'(quote(X),quote'(Z)) . eq quote'(nil) = nil' . eq quote(s(X)) = s'(quote(X)) . eq quote(sel(X,Z)) = sel'(X,Z) . eq quote'(first(X,Z)) = first'(X,Z) . eq unquote(0') = 0 . eq unquote(s'(X)) = s(unquote(X)) . eq unquote'(nil') = nil .

eq unquote'(cons'(X,Z)) = fcons(unquote(X),unquote'(Z)) . eq fcons(X,Z) = cons(X,Z) . endo

is the new transformed version of the OBJ program in Example 1.1. Now, the evaluation of unquote'(quote'(first(s(0),from(0)))) yields:

Maude> reduce unquote'(quote'(first(s(0), from(0)))) . reduce in EXAMPLE-TR : unquote'(quote'(first(s(0), from(0)))) . rewrites: 10 in -10ms cpu (0ms real) (~ rewrites/second) result LNat: cons(0, nil)

By using the context-sensitive recursive path ordering (CSRPO) of [2] we can even prove termination of the program in Example 6.15.

Example 6.16 Consider again the evaluation of the non-terminating expression from(0) using the program in Example 6.15. Now, we obtain:

Maude> reduce unquote'(quote'(from(0))) . reduce in EXAMPLE-TR : unquote'(quote'(from(0))) . rewrites: 0 in -10ms cpu (0ms real) (~ rewrites/second) result LNat: unquote'(quote'(from(0)))

General conditions under which this second transformation preserves termination of the original program should be further investigated.

7 Conclusions and Related work

We summarize the contributions of this paper as follows:

• We first clarify our notion of correct and complete computations with (positive) strategy annotations. As there is no standard, commonly accepted terminology, current definitions are rather misleading and we think this may cause an erroneous understanding (e.g., compare the mix of different concepts for the notion of correctness/completeness in [18,19,21]).

• We demonstrate that previously known approaches for computing normal forms with (non-terminating) OBJ programs using positive strategy annotations (e.g., Nakamura and Ogata's technique of 'completing' head-normalizing E-strategy maps p for obtaining a normalizing one p') are not completely satisfactory in practice: they do ensure correctness (that is, that computed E-normal forms are normal forms) but the desired definedness do not.

• We ascertain the conditions (on p) ensuring that OBJ programs using (positive) strategy annotations do compute the value of any given expression (Theorem 5.4). As shown in Example 5.6, termination of the program (under p) is essential for achieving correct (and complete) computations.

• Theorem 5.4 requires that all arguments of constructor symbols be replac-

ing. This may incur in unnecessary nontermination. Thus, we have formalized a transformation which can achieve (correct and) complete computations without worsening the termination behavior. Our technique differs from Nakamura and Ogata's (or Nagaya's) approach: we only relax the replacement restrictions associated to the (constructor) symbols after a thorough analysis of their role in the computation.

The only work addressing completeness of the E-strategy (w.r.t. normalization) is Nagaya's thesis (although completeness is called 'normalizability' in Nagaya's terminology). Nagaya establishes conditions (on the TRS and the E-strategy p) ensuring that p is normalizing, i.e., it is able to compute a normal form of a term whenever it exists [17]. However, these results only apply to a rather restricted subclass of orthogonal TRSs. In this paper, we have focused on the functional evaluation semantics, i.e., computations leading to constructor terms or values. We are able to deal with more general programs (represented by left-linear and confluent TRSs); as a counterpart, the termination of the program must be proved either before or after transforming it to ensure correctness and completeness (regarding functional evaluation). In CSR, normal forms of a term t can be obtained by successively computing its ¡-normal forms s, and continuing the evaluation of t by (recursively) normalizing the maximal non-replacing subterms of s (normalization via ¡-normalization [10,12]). In OBJ programs, we could proceed in a similar way provided that E-normal forms are ¡-normal forms. Unfortunately, we would need a 'meta-operation' that uses evalv to obtain partially evaluated results (i.e., E-normal forms) and then 'jumps' into the non-replacing parts of them in order to obtain normal forms. Of course, this procedure is not directly available in current OBJ implementations. The possibility of achieving a similar effect by using program transformation is a subject of future work.

Acknowledgements.

We would like to thank Cristina Borralleras for providing a proof of termination of the TRS that correspond to the program of Example 6.15 using CSRPO. We also thank the anonymous referees for their helpful remarks.

References

[1] F. Baader and T. Nipkow. Term Rewriting and All That. Cambridge University Press, 1998.

[2] C. Borralleras, S. Lucas, and A. Rubio. Recursive Path Orderings can be Context-Sensitive. In A. Voronkov, editor, Proc. of 18th International Conference on Automated Deduction, CADE'02, LNAI 2392:314-331, SpringerVerlag, Berlin, 2002.

[3] M. Clavel, S. Eker, P. Lincoln, and J. Meseguer. Principles of Maude. Electronic Notes in Theoretical Computer Science, volume 4, Elsevier Sciences, 1996.

[4] S. Eker. Term Rewriting with Operator Evaluation Strategies. Electronic Notes in Theoretical Computer Science, volume 15, Elsevier Sciences, 1998.

[5] O. Fissore, I. Gnaedig, and H. Kirchner. Induction for termination with local strategies. Electronic Notes in Theoretical Computer Science, volume 58(2), Elsevier Sciences, 2001.

[6] K. Futatsugi, J. Goguen, J.-P. Jouannaud, and J. Meseguer. Principles of OBJ2. In Conference Record of the 12th Annual ACM Symposium on Principles of Programming Languages, POPL'85, pages 52-66, ACM Press, 1985.

[7] K. Futatsugi and A. Nakagawa. An Overview of CAFE Specification Environment - An algebraic approach for creating, verifying, and maintaining formal specification over networks -. In Proc. of 1st International Conference on Formal Engineering Methods, 1997.

[8] J.A. Goguen, T. Winkler, J. Meseguer, K. Futatsugi, and J.-P. Jouannaud. Introducing OBJ. In J. Goguen and G. Malcolm, editors, Software Engineering with OBJ: algebraic specification in action, Kluwer, 2000.

[9] S. Lucas. Context-sensitive computations in functional and functional logic programs. Journal of Functional and Logic Programming, 1998(1):1-61, The MIT Press, 1998.

[10] S.Lucas. Context-sensitive rewriting strategies. Information and Computation, Academic Press, to appear.

[11] S. Lucas. Rewriting with replacement restrictions. PhD Thesis, DSIC, Universidad Politecnica de Valencia, in spanish, October 1998.

[12] S. Lucas. Termination of (Canonical) Context-Sensitive Rewriting. In Sophie Tison, editor, Proc. 13th International Conference on Rewriting Techniques and Applications (RTA'02), LNCS 2378:296-310, Springer-Verlag, Berlin, 2002.

[13] S. Lucas. Termination of on-demand rewriting and termination of OBJ programs. In Proc. of 3rd International Conference on Principles and Practice of Declarative Programming, PPDP'01, pages 82-93, ACM Press, 2001.

[14] S. Lucas. Termination of Rewriting With Strategy Annotations. In R. Nieuwenhuis and A. Voronkov, editors, Proc. of 8th International Conference on Logic for Programming, Artificial Intelligence and Reasoning, LPAR'01, LNAI 2250:669-684, Springer-Verlag, Berlin, 2001.

[15] S. Lucas. Transfinite Rewriting Semantics for Term Rewriting Systems. In A. Middeldorp, editor, Proc. of 12th International Conference on Rewriting Techniques and Applications, RTA'01, LNCS 2051:216-230. Springer-Verlag, Berlin, 2001.

[16] S. Lucas. Transformations for Efficient Evaluations in Functional Programming. In H. Glaser and P. Hartel, editors, Proc of 9th International Symposium on Programming Languages, Implementations, Logics and Programs, PLILP'97, LNCS 1292:127-141, Springer-Verlag, Berlin, 1997.

[17] T. Nagaya. Reduction Strategies for Term Rewriting Systems. PhD Thesis, School of Information Science, Japan Advanced Institute of Science and Technology, March 1999.

[18] M. Nakamura and K. Futatsugi. Completeness and strictness analysis for the evaluation strategy. In Y. Toyama, editor, Proc. of 1th International Workshop on Rewriting y Proof and Computation, RPC'01, pages 80-89, RIEC, Tohoku University, 2001.

[19] M. Nakamura and K. Ogata. The evaluation strategy for head normal form with and without on-demand flags. Electronic Notes in Theoretical Computer Science, volume 36, Elsevier Sciences, 2001.

[20] K. Ogata and K. Futatsugi. Implementation of Term Rewritings with the Evaluation Strategy. In H. Glaser and P. Hartel, editors, Proc of 9th International Symposium on Programming Languages, Implementations, Logics and Programs, PLILP'97, LNCS 1292:225-239, Springer-Verlag, Berlin, 1997.

[21] J. van de Pol. Just-in-time: on Strategy Annotations. Electronic Notes in Theoretical Computer Science, volume 57, Elsevier Sciences, 2001.