27
145 Implementing contexts in logic programming E. Denti, E. Lamma, P. Mello, A. Natali, A. Omicini DEIS, University of Bologna Viale Risorgimento 2 - 40136 Bologna - Italy Premise The concept of context and contextual programming has been recently introduced [MP89,LMN89,MNR89] in the logic programming field in order to enrich logic languages with general purpose concepts and mechanisms to structure programs, to support quick prototyping techniques and to promote the design and development of open, extensible software components. The key-idea of contextual logic programming is to allow programmers to introduce the software components they need not only in a static way, but also dynamically, by composition of primitive, unalterable objects, called units, which are collections of clauses. The main goal is to give a uniform language support to fundamental concepts in knowledge-based applications, such as inheritance, viewpoints, evolving knowledge, etc., as discussed in [BLM90a]. A context is intended here as an abstraction that can be interpreted in two ways: at programming-level, it can be viewed as a dynamically configured software component; at implementation-level, it works like a structured environment, supporting a number of different binding mechanisms, each related to a specific high-level component architecture. In particular, according to the terminology reported in [MNR89], the eager binding mechanism allows users to define software components according to conservative architectures, while lazy binding supports evolving, open architectures. Contexts have been deeply studied in the last years both from the semantic (see [MP89,BLM90a]) and the implementative side [LMN89,LMN]. In the following two related works, we describe our main results concerning the implementation of the context abstraction as an extension of Prolog. In particular, three main approaches have been considered, which can be summarized as follows: 1) Prolog-based approach: it exploits two well known techniques for implementing extensions of logic programming: - translating contextual programs into standard Prolog; - meta-intepretation; 2) WAM-based approach: it consists of extending the standard Warren Abstract Machine with a minimal set of features to support contexts; 3) Program representation-based approach: it exploits the program representation and the predicate addressing mechanism of a modular Prolog programming system, in order to implement contexts in the same way ordinary modules are. The main goal of the first work is to discuss and compare the first two approaches by considering both methodological and performance aspects.

Implementing contexts in logic programming

  • Upload
    unibo

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

145

Implementing contexts in logic programming

E. Denti, E. Lamma, P. Mello, A. Natali, A. Omicini

DEIS, University of Bologna

Viale Risorgimento 2 - 40136 Bologna - Italy

Premise

The concept of context and contextual programming has been recently introduced[MP89,LMN89,MNR89] in the logic programming field in order to enrich logiclanguages with general purpose concepts and mechanisms to structure programs, tosupport quick prototyping techniques and to promote the design and development ofopen, extensible software components.

The key-idea of contextual logic programming is to allow programmers to introducethe software components they need not only in a static way, but also dynamically, bycomposition of primitive, unalterable objects, called units, which are collections ofclauses. The main goal is to give a uniform language support to fundamental conceptsin knowledge-based applications, such as inheritance, viewpoints, evolvingknowledge, etc., as discussed in [BLM90a].

A context is intended here as an abstraction that can be interpreted in two ways: atprogramming-level, it can be viewed as a dynamically configured software component;at implementation-level, it works like a structured environment, supporting a number ofdifferent binding mechanisms, each related to a specific high-level componentarchitecture. In particular, according to the terminology reported in [MNR89], the eagerbinding mechanism allows users to define software components according toconservative architectures, while lazy binding supports evolving, open architectures.

Contexts have been deeply studied in the last years both from the semantic (see[MP89,BLM90a]) and the implementative side [LMN89,LMN].

In the following two related works, we describe our main results concerning theimplementation of the context abstraction as an extension of Prolog. In particular, threemain approaches have been considered, which can be summarized as follows:

1) Prolog-based approach: it exploits two well known techniques forimplementing extensions of logic programming:

- translating contextual programs into standard Prolog;- meta-intepretation;

2) WAM-based approach: it consists of extending the standard Warren AbstractMachine with a minimal set of features to support contexts;

3) Program representation-based approach: it exploits the programrepresentation and the predicate addressing mechanism of a modular Prologprogramming system, in order to implement contexts in the same way ordinarymodules are.

The main goal of the first work is to discuss and compare the first two approaches byconsidering both methodological and performance aspects.

146

In order to achieve comparable performance results, a simulator of the VLSI Prologcoprocessor described in [CIV89] has been used. Two versions of such a simulatorhave been employed, the first supporting standard Prolog (i.e. implementing thestandard WAM), the second supporting the S-WAM described in [LMN89, LMN].Since both machines share the same set of micro-coded instruction, this set has beenused as unit of measure. Reliable measures of computational costs can also beachieved, since the execution time of each micro-instruction is known.

The work shows, as it can be expected, that the WAM-based approach gives thebetter performance results. However, these results are considerably different (in favourof the Prolog-based approach) in the case of partial evaluation of completely configuredcontextual goals.

The main goal of the second work is to describe the third implementation approach,assuming as host environment the SICStus Prolog system [SICS91]. This approach(called CSM, i.e. Contexts as SICStus Modules) allowed us to achieve the followingimportant results:1) contexts are now supported by an efficient, widely used and well-supported Prolog

system;2) the implementation of contexts does introduce neither semantic distortion nor

computational overhead with respect to standard (SICStus) Prolog programs;3) both eager and late binding policies are implemented with the same (very low)

computational cost. The main computational cost is now related to the contextcreation operation, which is however rather limited, since context creation isalways obtained in an incremental way, without restarting from scratch.

Since CSM is based on a completely different predicate addressing scheme andoperating environment, no quantitative performance comparison is immediatelypossible with the previous approaches. In any case, it is worth to note that the lastsolution can be considered as complementary with respect to the S-WAM design. Inparticular, while the stack-based S-WAM context representation provides automaticmemory management in case of context deallocation, the CSM approach delegates sucha problem to the user, by allowing, on the other side, the system programmer to exploitcontext memoization techniques.

In conclusion, far from stating the ultimate word in a field still open to significativeimprovements, our work shows that contextual logic programming paradigm can beeffectively used also in industrial environments to face several of the most criticalproblems of modern software engineering.

References

See the works.

147

147

Implementing contexts in logic programming:

WAM extensions vs. translation and meta-interpretation

Evelina Lamma, Paola Mello, Antonio Natali, Andrea Omicini

DEIS, Università di BolognaViale Risorgimento, 240136 Bologna - Italy

email: {evelina, paola, natali, andrea}@deis33.cineca.it

1. INTRODUCTION

The intensive use of logic programming languages, and Prolog in particular, impliesin some frequent and significant cases the introduction of linguistic extensions to thebasic logic programming paradigm to enhance its expressive power. For instance,artificial intelligence applications frequently demand for the knowledge base to bestructured into different theories that can be statically or dynamically combined, in orderto represent inheritance relationships, viewpoints and evolving knowledge ([Bow85,Mil86, BLM90]).

Once linguistic extensions have been defined, the problem to be faced is how toimplement them. In particular, three well-known techniques for implementingextensions of logic programming are:

1) Meta-programming and, in particular, meta-interpretation.In this case, an extended meta-interpreter ([StS86]) is defined, which reproduces atmeta-level the Prolog interpretation cycle, enhanced with the new linguisticextensions. This approach, frequently adopted in the logic programmingcommunity, is elegant and easy to follow, and allows us to quickly build a firstprototype supporting the extensions introduced. The main problem is that, due tothe added interpretation level, this approach is sometimes too inefficient to beadopted for real applications.

2) Translation into standard Prolog.This implementation technique is based on a “naive” translation of extended logicprograms into standard Prolog ones and does not require any modification to theexecution model of Prolog that is based on the Warren Abstract Machine (WAM[War83]). This approach is less natural and easy to follow than meta-interpretation,but it is more efficient, and does not require the development of more complex,specialized execution models and environments.

148

148

3) Compilation into an extended Prolog abstract machine.The standard Prolog abstract machine (WAM) is extended with a minimal set of newinstructions and new data structures to directly support the extensions introduced(see [Bac87, LMN89]). This technique is the most efficient but also the mostcomplex in practice, since it implies the building of an “ad hoc” environment for thenew language with a new compiler and a new emulator for the extended abstractmachine.

These approaches represent a different trade-off between easy and fast implementation(at the first stage of the development) and efficiency (when real applications are built).The paper discusses the implementation of an extension of logic programming based oncontexts ([MP89]) by considering the approaches mentioned above and comparing themfrom the point of view of both the methodology and the efficiency. In contextual logicprogramming ([MP89, MNR89, BLM90a]) a logic program can be structured intoseparate units that can be statically or dynamically combined into contexts.

In the paper a simple logic programming language that extends Prolog with contexts isimplemented through meta-interpretation, translation and compilation into an extendedWAM, to compare these approaches.

Comparative performance results are given on the basis of a common emulationenvironment grounded on a dedicated VLSI microcoded architecture [Civ90]. For thesake of completeness, in the last part of the paper we consider also the application ofpartial evaluation techniques [Kom81] to reduce the overhead of all the consideredimplementation techniques.

2. CONTEXTUAL LOGIC PROGRAMMING AS A CASE STUDY

The contextual logic programming paradigm is firstly introduced in [MP89]. While inpure Prolog only a flat set of clauses is available, the key idea in contextual logicprogramming is that a logic program can be conceived as a collection of independentcomponents called units. A unit is simply identified by the set of clauses it defines andby a unique, atomic name used to denote it. Units can be (possibly dynamically)connected into contexts and contexts, in turn, provide the set of definitions for theevaluation of goals. Contexts are represented as ordered lists of unit names of the form[u N,…,u i ,…,u 1] , and denote the union of the sets of clauses of the composing units.

Contexts are dynamically built by using a suitable extension operator, here denoted by>>. In particular, the execution of uN+1>>G, where uN+1 is a unit name and G a goalformula with respect to the current context C=[u N,…,u i ,…,u 1] , causes the proof of Gto be executed in a new context C1=[u N+1,u N,…,u i ,…,u 1] , obtained by pushinguN+1 on top of C. In other words, a context represents the ordered, dynamic nesting ofextension operators.

unit(u1): unit(u2): unit(u3):a(X):- b(X). b(1). c(X):- a(X).

Figure 2.1: A sample contextual logic program.

149

149

Consider the program of figure 2.1. The top goal u1>>u2>>u3>>c(X) is provedwith answer substitution {X/1} . In particular, c(X) is proved in the context[u3,u2,u1] , which virtually corresponds to the set of clauses:

c(X):- a(X).b(1).a(X):- b(X).

As a further example, let us consider two units (see figure 2.2), the first one (list )defining the predicates member/2 , permutation/2 and del/3 , and the secondone (eq) defining the predicate equal/2 which implements an equality relation in thecase of lists by using the permutation/2 predicate. Notice the different ways inwhich a predicate that is not locally defined is called. The unit list calls the predicateequal/2 by explicitly naming the unit eq in which it is defined, while the “external”call of the predicate permutation/2 in the unit eq does not specify any unit name.

Which definition of permutation/2 has to be considered depends on the currentcontext and can be changed at run-time without changing the code of equal/2 . If thetop-level goal is

:- list>>member([a,b],[e,d,[f,g],h,[b,a]]) ,when permutation/2 is called in eq the current context is [eq,list] , so that

the definition of permutation/2 present in list will be used. Notice that, if thecurrent context is changed, a different definition will be used, thus giving to the unit eqa high degree of reusability.

unit(list).member(X,[Y|_]):- eq>>equal(X,Y).member(X,[_|Z]):- member(X,Z).

permutation([],[]).permutation([X|Y],Z):- del(X,Z,W),

permutation(Y,W).

del(X,[X|Z],Z).del(X,[Y|Z],[Y|W]):- del(X,Z,W).

unit(eq).equal(X,X).equal([X|Y],[Z|W]):- permutation([X|Y],[Z|W]).

Figure 2.2: Another contextual logic program

Of course, different policies can be adopted when defining a real contextual logicprogramming language [MNR89, BLM90a].

Informally, given a context C=[u N,…,u i ,…,u 1] , we refer to a conservative policywhen, in order to solve goals (predicate calls) of the unit ui in C, only predicatedefinitions present in the subcontext [u i ,…,u 1] of C are taken into account. We referto an evolving policy, instead, when all predicate definitions present in C are taken intoaccount for solving goals of the unit ui independently of its position in C.

150

150

In practice, if a conservative policy is adopted, new extensions nested within theextension involving ui cannot give any contribution to the proof of goals of u i , whilethis may happen if an evolving policy is adopted.

Let us consider the program in figure 2.2, and a new unit del where a differentdefinition for the del/3 predicate is given.

If we call the goal:- list>>del>>member([a,b],[e,d,[f,g],h,[b,a]])

and an evolving policy is adopted, the definition of del/3 used in list will be thenew one, defined in the unit del . If a conservative policy is adopted, the definition ofdel/3 in unit list will be used and we will have the same result of the program infigure 2.2, independently of the unit del that is present in the current context.

While in the previous examples units are dynamically composed in contexts by usingthe extension operator, in some cases it could be useful to define a more static way ofcomposing units. In particular, a fixed context can be associated with each unit (thuscalled static), so that at unit definition time a “closed environment” can be set, whosebehaviour does not depend on the dynamic computational environment.

Blocks, modules and inheritance-based systems can be easily implemented asstatically configured hierarchies of units, whereas dynamic configurations provide anatural support for artificial intelligence techniques such as viewpoints and hypotheticalreasoning (see [BLM90a]).

Here, we consider only the most dynamic case: i.e. an evolving policy for bindingpredicate calls to predicate definitions, and a dynamic configuration of units. Choosingthe most dynamic case is mainly due to two different reasons:

1) It is the most frequent in the case of artificial intelligence applications, where Prologis widely used;

2) In the dynamic case, it is less evident the advantage, in terms of efficiency, ofcompilation techniques with respect to (meta-)interpretation, thus performanceresults are more significant.

3. THE META-INTERPRETATION APPROACH

Meta-programming is a technique which treats other programs as data. Meta-programsanalyze, transform, and simulate other programs [BK82].

In particular, writing meta-interpreters is a common technique to add functionalities tothe basic Prolog machine (see [SaS86, StS86, LMN91]). In general, meta-interpretersuse direct access to the program internal representation through the built-in predicateclause/2 whose arguments are the clause head and body, and reproduce theinterpretation cycle at Prolog level. Since we consider programs which have beenpartitioned into units, we suppose that the representation of program clauses is given bymeans of a rule/3 predicate, where the first argument represents the unit name towhich the clause belongs, and the second and third arguments represent the clause headand body respectively. The program reported in figure 2.2 is therefore represented asshown in figure 3.1.

151

151

rule(list,member(X,[Y|_]),eq>>equal(X,Y)).rule(list,member(X,[_|Z]),member(X,Z)).

rule(list,permutation([],[]),true).rule(list,permutation([X|Y],W), (del1(X,W,Z),permutation(Y,Z))).

rule(list,del1(X,[X|Z],Z),true).rule(list,del1(X,[Y|W],[Y|Z]),del1(X,W,Z)).

rule(eq,equal(X,X),true).rule(eq,equal([X|Y],[W|Z]),permutation([X|Y],[W|Z])).

Figure 3.1: Program representation

As concerns the meta-interpreter code (see figure 3.2), subgoal selection andreduction is described by the clauses C1, C2 and C4. Clause C4 implements the bindingmechanism, non-deterministically selecting a unit U of context Ctx ; a subgoal G isproved by finding in U some clause whose head unifies with G, and subsequentlysolving the clause body. Moreover, through a suited member/2 definition, itimplements the predicate extension policy, by exploring through backtracking all Ctxunits in which a definition for G can be found.

Clause C3 extends the language with the new operator “>>” which dynamicallyexpands the current set of clauses. In order to solve a goal of the kind U>>G, themeta-interpreter simply adds unit U on the top of the current context Ctx and thensolves G.

solve(_,true):- !. %C1solve(Ctx,(G1,G2)):- !, solve(Ctx,G1), solve(Ctx,G2). %C2solve(Ctx,U>>G):- !, solve([U|Ctx],G). %C3solve(Ctx,G):- member(U,Ctx), %C4

rule(U,G,Body),solve(Ctx,Body).

member(X,[X|_]). %C5member(X,[_|Z]):- member(X,Z). %C6

Figure 3.2: Meta-interpreter code

4. THE TRANSLATION APPROACH

Besides meta-interpretation, another common approach for supporting linguisticextensions is to translate the extended code into Prolog one. This is usually obtained byadding extra-arguments to Prolog clauses. The resulting code can be therefore executedon a standard Prolog machine.

In the case of contextual logic programming, we have to maintain a new data structure(i.e. a Prolog list) for recording the context. The major overhead of this solution is dueto the fact that, in the most general case, we perform more unifications, since we addextra-arguments to each predicate definition and predicate call.

152

152

In figure 4.1 the translated code for the program of figure 2.2 is reported. We add twoarguments to each clause head and subgoal. The second argument represents the globalset of clauses which constitute the context (global context), while the first onerepresents the subcontext (partial context) we are considering for finding some clauseto apply. Moreover, additional clauses (C9-C13) are added for each predicatedefinition, in order to consider not only one unit, but the overall context, whensearching for predicate definitions in the case of predicate extension.

member([list|_],Ctx,X,[Y|_]):-equal([eq|Ctx],[eq|Ctx],X,Y). %C1

member([list|_],Ctx,X,[_|Z]):- member(Ctx,Ctx,X,Z). %C2permutation([list|_],Ctx,[],[]). %C3permutation([list|_],Ctx,[X|Y],Z):-

del1(Ctx,Ctx,X,Z,W), %C4permutation(Ctx,Ctx,Y,W).

del1([list|_],Ctx,X,[X|Z],Z). %C5del1([list|_],Ctx,X,[Y|Z],[Y|W]):- %C6

del1(Ctx,Ctx,X,Z,W).equal([eq|_],Ctx,X,X). %C7equal([eq|_],Ctx,[X|Y],[Z|W]):- %C8

permutation(Ctx,Ctx,[X|Y],[Z|W]).member([H|T],Ctx,X,Y):- member(T,Ctx,X,Y). %C9permutation([H|T],Ctx,X,Y):- permutation(T,Ctx,X,Y). %C10del1([H|T],Ctx,X,Y,Z):- del1(T,Ctx,X,Y,Z). %C11dummy([H|T],Ctx,X):- dummy(T,Ctx,X). %C12equal([H|T],Ctx,X,Y):- equal(T,Ctx,X,Y). %C13

Figure 4.1: The translated code

5. THE WAM EXTENSION APPROACH

The third approach supports extensions to the Prolog language by directly extendingthe basic abstract machine defined by D.H.D. Warren (WAM, [War83]). WAMextensions are more complex and difficult to achieve, but they are generally moreefficient.

In the following, we briefly sketch the extensions needed to support contextual logicprograms. The resulting abstract machine (called S-WAM) is better described in[LMN89, LMN]. The basic difference of this approach with respect to themeta-interpretation and the automatic translation one is that in S-WAM contexts are notexplicitly represented as extra-arguments, but are maintained in an internal data structure(i.e. the context stack) implicitly handled by the machine.

In particular, in S-WAM the current context is represented by a new stack (the contextstack), which can be viewed as the binding environment for predicate calls. The contextstack grows whenever an extension of the kind U>>G occurs and shrinks when G isdeterministically solved or definitely fails.

Each object on the context stack is a frame (called instance environment) associatedwith a specific unit U and allocated on the context stack whenever U is involved in a

153

153

context extension (allocate_ctx U instruction), and logically deallocated when G issolved (deallocate_ctx instruction). New registers refer to the context stack, andnew instructions are also added to the WAM instruction set in order to expand andshrink this data area. Moreover, the structure of both WAM choice-points andenvironments have been expanded to consistently handle new registers and someoptimizations have been also considered, in order to limit the overhead in the case ofexecution of standard Prolog programs (see [LMN89, LMN] for details).

6. COMPARISONS AND PERFORMANCE RESULTS

In order to compare the computational cost of the three approaches discussed so far,we consider the program reported in figure 2.2, together with the following unitdummy:

unit(dummy).dummy(0).

For performance tests we consider goals of the kind::- list>> {dummy>>}member([a,b],[e,d,[f,g],h,[b,a]]).

with the bracketed part repeated 0,1,…,5 times, to emphasize the cost of searchingpredicate definitions through growing contexts. For instance, the permutation/3call in the second clause of eq/2 produces a search of the corresponding predicatedefinition in the current context starting from the top unit (eq) to the bottom unit(list ) through a variable number of dummy units.

To compare the three implementation approaches we need a common unit of measure;in fact, while meta-interpreted and translated solution can run on standard Prologmachines, this is no more true when considering WAM extensions.

We solve this problem by using a prototype [Civ90] providing a set of micro-codedinstructions (called WAM0) which is a common ground for both WAM and S-WAMinstructions. We choose to use the number of WAM0 instructions as the mostsignificant parameter for performance comparisons; since the number of executedWAM0 instructions is directly related to execution time, we can obtain also a reliablemeasure of computational costs.

In figure 6.1, 6.2, 6.3 we report the results in the case of meta-interpretation,translation and WAM extension respectively, in terms of Logical Inferences, WAM andWAM0 instructions.

L.I. 108 147 186 225 264 303

W.I. 2008 2640 3272 3904 4536 5168

WAM0 50160 70017 89784 109551 129318 149085

dummy units 0 1 2 3 4 5

Figure 6.1: Results for Meta-interpretation

154

154

L.I. 42 61 80 99 118 137

W.I. 617 851 1085 1319 1553 1787

WAM0 13569 20411 27253 34095 4 0 9 3 7 47779

dummy units 0 1 2 3 4 5

Figure 6.2: Results for Translation

L.I. 20 20 20 20 20 20

W.I. 225 228 231 234 237 240

WAM0 8 2 0 6 9 0 5 3 9 9 0 0 10746 11593 12439

dummy units 0 1 2 3 4 5

Figure 6.3: Results for WAM extension

In figure 6.4, we compare all the results of the tests in terms of WAM0 instructions.

0

20000

40000

60000

80000

100000

120000

140000

160000

0 1 2 3 4 5

WAM Extension

Meta-interpretation

Translation

number of WAM0 instructions

number of dummy units

Figure 6.4: Performance comparisons

The WAM-extension solution is, of course, the most efficient and has an increment ofabout 10% (with respect to the 0-dummy test) for each dummy unit added. This ismainly due to the fact that now units and contexts are part of the low-level machine anddirectly manipulated by WAM instructions, while in the case of translation andmeta-interpretation they are Prolog structures accessed by unification at each predicatecall. Moreover, it has been shown in [LMN89, LMN] that adopting a conservative

155

155

policy - instead of the evolving one here considered – makes the efficiency gain evenbetter, in the case of WAM extensions.

7. APPLYING PARTIAL EVALUATION

The fundamental idea of partial evaluation is to evaluate parts of the program whichhave enough input data for that purpose to produce a specialised version of theprogram, possibly more efficient.

In logic programming terms, partial evaluation can be described as follows [LS87]:given a program P and a goal G, partial evaluation produces a new program P’ , whichis P specialized for goal G. In other words, G and all its instances should have the sameanswers with respect to P and P’ . The basic technique for obtaining P’ from P is toconstruct partial search trees for G with respect to P and then extract P’ from thedefinitions associated with the leaves of these trees.

The use of partial evaluation enhances program execution and it also has a greatrelevance with respect to meta-level programming techniques. The application of partialevaluation to meta-programming has already helped extensively, for example, indefining the various layers of the Logix virtual machine [SaS86] and in the design of alogic programming system that supports separate Prolog theories [CFL88]. In all thesesystems, the partial evaluator is applied to a meta-interpreter with respect to the goal ofan object program.

The result is a specialization of the meta-interpreter plus the user program that can beseen as a “compiled” version of the program incorporating all the additional featuresprovided by the meta-interpreter. Since this “compiled” version can be executed directlyby the basic interpreter, it is much more efficient.

Thus, we cannot ignore the application of partial evaluation and in the following weinvestigate its impact on the different implementation techniques discussed above.

The solutions based on meta-interpretation and translation in standard Prolog havebeen optimized by using Mixtus [Sah90], a Prolog partial evaluator written in Prolog.In the case of S-WAM, we should directly partially evaluate the contextual logicprogramming language. To this purpose, we have applied the partial evaluation schemedefined in [BLM] where a definition of partial evaluation which extends that given in[LS87] to capture the notions of unit and unit composition is introduced. The initial goalspecifies an initial context and an atomic formula. The result of the transformation is anew program in which some of (possibly all) the units occurring in the initial context arereplaced by their specialized versions.

The specialized transformed program is still a structured logic program running onS-WAM and taking advantage from structuring mechanisms, thus maintaining theoriginal readability and avoiding code replication whenever possible.

We expect efficiency to increase when partial evaluation is applied. Figure 7.2 andcomparison of values between figure 6.4 and figure 7.1 confirm this belief.

156

156

WAM ext. 5558 5688 5818 5948 6079 6209

translation 3876 3946 4016 4086 4156 4226

meta-int. 3575 3679 3819 3941 4063 4185

dummy units 0 1 2 3 4 5

Figure 7.1: Partial evaluation performance comparisons (WAM0 instr.)

0

10000

20000

30000

40000

50000

P.Ev.Meta-int. P.Ev. Transl. P.Ev. Ext. WAM Ext. Transl. Meta-int.

number of WAM0 instructions

Figure 7.2: Global comparison (0-dummy unit tests)

The meta-interpretation solution has been partially evaluated with respect to theprograms of figure 3.1 and 3.2 and the goal

:- solve([],list>> {dummy>>}member(X,Y)).The solution based on translation has been partially evaluated with respect to the

program of figure 4.1 and the goal:- member([ {dummy,}list], [ {dummy,}list], X, Y) .Finally, the solution based on WAM extension, has been partially evaluated with

respect to the program of figure 2.2 and the goal:- list>>{dummy>>}member(X,Y) .Performance results are shown in figure 7.1 in the case of a growing context, while

the performance increasing with respect to the non-partially evaluated cases (figure 6.4)is depicted in figure 7.2 in the case of 0-dummy unit in the context.

The application of partial evaluation makes the three implementation techniques – herediscussed – comparable. The overhead paid by the S-WAM solution is due to theextensions introduced in the WAM data structures which imply an higher number ofmemory accesses even if contexts are not used. Of course these results are subject to beconfirmed on most significant examples.

Acknowledgements

157

157

This work has been partially supported by the C.N.R. “Progetto Finalizzato SistemiInformatici e Calcolo Parallelo”, under grant nº 890004269.

REFERENCES

[Bac87] BACHA, H., Meta-level Programming: a Compiled Approach, in J-L.Lassez (ed.), Proceedings 4th International Conference on LogicProgramming, The MIT Press, Cambridge (USA), 1987.

[BK82] BOWEN, K., KOWALSKI, R., Amalgamating language and metalanguage inlogic programming, in Logic Programming, K.L. Clark and S-A. Tarnlundeds., Academic Press, London (UK), pp. 153-172, 1982.

[BLM] BUGLIESI, M., LAMMA , E., MELLO, P., Partial Deduction for StructuredLogic Programming, to appear in Journal of Logic Programming, SpecialIssue on Partial Deduction and Partial Evaluation, J. Komorowski ed.,North-Holland, 1992.

[BLM90] BROGI, A., LAMMA , E., MELLO P., Inheritance and HypotheticalReasoning in Logic Programming, in L. Carlucci Aiello (ed.), Proceedingsof 9th European Conference on Artificial Intelligence ECAI-90, PitmanPublishing, London (UK), 1990.

[BLM90a] BROGI, A., LAMMA , E., MELLO P., A General Framework for StructuringLogic Programs, C.N.R. Technical Report “Progetto Finalizzato SistemiInformatici e Calcolo Parallelo”, N. 4/1, May 1990, submitted forpubblication.

[Bow85] BOWEN, K., Meta-level Programming and Knowledge Representation,New Generation Computing, Vol. 3, no. 4, OHMSHA LDT. andSpringer-Verlag, Tokyo (J), pp. 359-383, 1985.

[CFL88] COSCIA, G. P., FRANCESCHI, P., LEVI, G., SARDU, G., TORRE, L.,Meta-Level Definition and Compilation of Inference Engines in the EpsilonLogic Programming Environment, Proceedings of the 5th InternationalConference on Logic Programming, R.A. Kowalski and K.A.Bowen eds.,Seattle (USA), The MIT Press, Cambridge, Massachusetts, pp. 359-373,1988.

[Civ90] CIVERA, P. L., LAMMA , E., MELLO, P., NATALI , N., PICCININI , G.,ZAMBONI, M., Implementing Structured Logic Programs on a DedicatedVLSI Coprocessor, in Proceedings Workshop on VLSI for ArtificialIntelligence and Neural Networks, Oxford University, September 1990.

[Kom81] KOMOROWSKI, H. J., A specification of an abstract Prolog machine and itsapplication to Partial Evaluation, Linkoping University, Dissertation, 1981.

[LMN89] LAMMA , E., MELLO, P., NATALI , A., The Design of an Abstract Machinefor Efficient Implementation of Contexts in Logic Programming, in G. Leviand M. Martelli (eds.), Proceedings 6th International Conference and

158

158

Symposium on Logic Programming, The MIT Press, Cambridge (USA),1989.

[LMN] LAMMA , E., MELLO, P., NATALI A., An Extended Warren AbstractMachine for the Execution of Structured Logic Programs, to appear inJournal of Logic Programming, North-Holland, 1992.

[LMN91] LAMMA , E., MELLO, P., NATALI A., Reflection Mechanisms forCombining Prolog Databases, in Software, Practice and Experience, Vol.21, No. 6, John Wiley and Sons, June 1991.

[LS87] LLOYD, J. W., SHEPHERDSON, J. C., Partial Evaluation in LogicProgramming, Technical Report CS-87-09, University of Bristol, December1987 (also to appear in Journal of Logic Programming).

[Mil86] MILLER, D., A Theory of Modules for logic Programming, Proceedings1986 International Symposium on Logic Programming, 106-114; 1986.

[MNR89] MELLO, P., NATALI , A., RUGGIERI, C., Logic Programming in a SoftwareEngineering Perspective, in E. L. Lusk and R. A. Overbeek (eds.),Proceedings of the North American Conference on Logic ProgrammingNACLP89, The MIT Press, Cambridge (USA), 1989.

[MP989] MONTEIRO, L., PORTO, A., Contextual Logic Programming, in G. Leviand M. Martelli (eds.), Proceedings 6th International Conference andSymposium on Logic Programming, The MIT Press, Cambridge (USA),1989.

[Sah90] SAHLIN , D., The Mixtus Approach for Hierarchies of Logic Theories, inProc. NACLP’90, S. Debray and M. Hermenegildo eds., The MIT Press,1990.

[SaS86] SAFRA, S., SHAPIRO, E., Meta-interpreters for Real, InformationProcessing 86, H.G.Kugler ed., Elsevier Science Publisher, pp. 271-278,1986.

[StS86] STERLING, L., SHAPIRO, E., The Art of Prolog, The MIT Press, 1986.

[War83] WARREN, D. H. D., An Abstract Prolog Instruction Set, SRI TechnicalNote 309, SRI International, October 1983.

159

159

Contexts as first-class objects in SICStus Prolog

Enrico Denti(1), Antonio Natali(1), Andrea Omicini(2)

(1) - Dipartimento di Elettronica, Informatica e SistemisticaUniversità di Bologna, viale Risorgimento, 2 — 40136 Bologna - Italy

tel +39-51-6443021, fax +39-51-6443073E-mail: [email protected]

(2) - DS Logicsviale Silvani,1 — 40100 Bologna - Italy

tel +39-51-521285

Introduction

Among the open problems of the logic programming field, one of the most criticalconcerns the extension of the logic paradigm with concepts and mechanisms tosupport the design, development and maintenaince of large software systems.

All industrial Prolog systems (e.g. Quintus, SICStus, etc.) provide predicates topartition the single Prolog data-base into a collection of modules, together withspecific visibility and import/export rules. However, since the concept of module isbasically unrelated to the notion of logic theory and satisfiability, different conceptsand mechanisms have been proposed in the literature to define structured logiclanguages more coherent with the logic paradigm. These proposals cover a widespace, ranging from the conventional notion of scope-rule and block-basedprogramming [GMR88], to the integration into the logic framework of Object-Oriented ideas [BR91,B91].

In this wide research space, the concept of contextual programming - first proposedin [MP89] and later refined in [MNR89] and implemented in [LMN89] - does assumea rather intermediate position. In fact, contextual languages do not force a specificprogram structuring model: rather, since the notion of context is intrinsecally relatedto the notion of scoping and binding environment, contextual languages provide a setof mechanisms that can be exploited to explicitly define different kinds of structuredcomponents, including structured logic theories.

The basic idea of contextual programming is to allow programmers to dynamicallybuild the software components they need, by composition of primitive objects, calledunits. Three forms of binding (local, eager and late) allow users to define componentsstructured according to both conservative and evolving architectures, as described in[LMN].

At the moment, however, since they are not conceived as data abstractions, contextscannot be used in programs as first class objects. A context is simply reduced to aparticular state (or binding environment) of the underlying machine that can be

160

160

modified only by predefined extension operators. Thus, software components definedas contexts have to be dynamically rebuilt any time the program needs them.

In this work we present an implementation of the context abstraction that allows usto remove such a limit from contextual programming and to achieve a remarkable setof properties:

- contexts can be used at language level as first-class objects which can bereferred to by logic variables;

- contexts are memoized in the internal system knowledge base and reused whenneeded;

- since contexts are completely configured at creation time, there is no need toperform dynamic searching of predicate definitions at run time.

These properties can be achieved, in theory, also by following the implementationproposed in [LMN] - called S-WAM - based on an extension of the Warren AbstractMachine (WAM). And, in fact, the implementation presented here - called CSM(Contexts as SICStus Modules) - still maintains a strong correspondence with theS-WAM architecture. The main difference is that the data structures needed toimplement context abstraction are immediately and naturally obtained through asuitable mapping into the structures provided by a real system used in industrialapplication: the SICStus Prolog system.[SICS89]

In SICStus Prolog, the compiled code is no more represented as a sequence ofWAM instructions, but as a tree data-structure. Among the several reasons that, alltogether, lead to this quite radical change, we stress here the following ones:

- support for a more efficient indexing scheme;- support for modularity;- incremental loading of clauses;- providing coexistence of both compiled and interpreted predicate-code.

Since the code is represented as a tree, the basic SICStus WAM (SICS-WAM)binding mechanism takes place in an indirect way (via hash-tables). This basic featureof the SICS-WAM is exploited in CSM implementation by using the SICStus moduleas concrete representation of the context abstract data type. The result is a systemwhich:

- does not introduce any semantic distortion to conventional Prolog programs;- still maintains all the features of the SICStus Prolog programming system;- does not introduce any computational overhead respect to Prolog programs. In

fact, there is no need to modify the SICS-WAM.

These properties, together with those mentioned before, help making contextualprogramming an effective tool for structuring logic programs according to specificapplication needs. By limiting the computational overhead to context (first-time)creation phase, CSM provides a run-time support whose organization and efficiencyis comparable with that of the run-time support of languages based on staticstructuring mechanisms only, such as class-based object-oriented languages. In fact,

161

161

what CSM does is to allow users to delay (until context creation time) the creation ofthose descriptors usually built at compile-time by static languages.

The work is organized as follows. In section 1, contexts are defined as new (Prolog)data-structures by conceiving a context as an abstract data type. The relation with theprevious approach to context definition is also briefly discussed. Section 2 is devotedto the presentation of the main characteristics of CSM implementation, stressing thoseelements of the SICS-WAM organization and architecture which are fundamental forit, in particular the predicate addressing scheme. Conclusions and final considerationsare reported in section 3.

1 Contexts as structured binding environments

Binding in standard Prolog is a matter of associating predicate names to codeaddresses. A Prolog program P implicitly configures a set Pd of all the predicatesdefined in P, which represents the binding environment of its predicate calls: thus, acall to p/n in a P clause is statically bound to the definition code, if p/n belongs toPd, otherwise it fails (as required by CWA).

In a modular Prolog, a program P basically defines a set Pm of modules and a set Pdof couples (M,p/n), where M belongs to Pm and p/n is a predicate such that adefinition for it can be found in M, providing a static form of program structuring.

Contextual programming provides further mechanisms in order to dynamicallystructure new addressing spaces from basic elements called units .

Like modules, units are constituted by a list of Prolog clauses, and can be used tostatically decompose a program into a set of components. In the following we denoteas:

- Ud, the set of predicates explicitly defined within unit U (local predicates);- Uv, the set (subset of Ud) of predicates explicitly declared as visible in U;

We define local call the policy that binds the predicate p/n, called within a unit U,by using Ud as binding environment, and that solves it there under CWA.

A context is defined here as a new data-object, representing a structured bindingenvironment, conceptually constituted by a list of frames. Context objects are builtrecursively by the constructor

createCtx(U,C1,C)

which binds the variable C (initially unbound) to the context obtained by extendingthe context referred to by C1 with the set of bindings represented by the frame Fudefined as follows:

Fu = {(U,p/n) | (p/n∈Uv)}

The atom emptyCtx is used to denote the empty context. The context C1 is calledfirst-subcontext of C. Given the context C, the predicates topUnit(C,U) and

162

162

sub1Ctx(C,C1) can be used as selectors. Thus, sub1Ctx(C1,C2) unifies C2with the second subcontext of C and so on.

If we denote as Ctxd the binding environment associated to the generic contextCtx, Cd is then defined as the union (modulo predicate overriding) of Uv and C1d.More formally:

Cd = {(M,p/n) | (M=U ∧ p/n∈Uv) ∨ ((M,p/n)∈C1d ∧ p/n∉Uv)}

i.e. Cd is the union of Fu and the frames obtained from C1d ones excluding the pairswhose functor is already present in a Fu pair. Of course, emptyCtxd = ∅.1

We define context call (of predicate p/n to context C), the policy that binds thepredicate p/n by using Cd as binding environment, and that solves it there underCWA. A binding for p/n is found in C if there exists a pair (U1,p/n)∈Cd: in sucha case, the call is solved as a local call in U1. The first subcontext C1 of C such that

(U1,p/n) ∈ topUnit(C1)is called bindcontext of predicate p/n with respect to context C

In order to support the binding policies defined in [LMN89], CSM keeps track (asin the S-WAM) of both the current context and the current bindcontext and providesthe following primitive operators:

- curCtx(C) that binds C to the current working context (elsewhere calledglobal context)

- curBindCtx(C) that binds C to the current bindcontext (elsewhere calledpartial context).

CSM allows users to exploit both context and local calls, according to the syntaxrules below:

- a goal P called within a unit U of a context C is always solved as a local call,ignoring every information about the contexts

- if curCtx(C), a goal ##P is solved as a context call to C. This goal performsthe lazy binding policy defined in [LMN89], so we will refer to it also as lazycall (of P)

- if curBindCtx(C), a goal ::P is solved as a context call to C. This goalperforms the eager binding policy defined in [LMN89]), so we will refer to italso as eager call (of P)

The predicate C♦P is interpreted as a context call of P to C. It implements a form ofcontext switch which represents CSM own primitive mechanism for context calls: thecurrent context is set to C and the current bindcontext is set to the bindcontext of Cw.r.t. P, then P is solved as a local call to the bindcontext top unit.

The S-WAM context-extension operators (for cactus and linear extension) areperformed respectively by CSM primitive predicates >:>/2 and >#>/2, whichconceptually work as follows:- U >#> G :- curCtx(C1), createCtx(U,C1,C), C♦G.

1 Even if conceptually true, this is not rigorously exact, because of the builtin predicates.

163

163

- U >:> G :- curBindCtx(C1), createCtx(U,C1,C), C♦G.

Note that these operators were the only ones provided by S-WAM for contextcreation, which could be consequently performed only implicitly. In CSM instead,contexts can be interpreted as first-class objects which can be referred to by logicvariables. The unification of variables C1 and C2, each referencing a context,succeeds only if C1 and C2 are bound to the same context (i.e. C1==C2), sincecontexts are completely configured data-structures (i.e. they do not include unboundvariables).

The following example illustrates the main features defined above and the mainadvantage gained from the new approach.

A robot system is designed as a collection of action-modules that will bedynamically configured according to external events. At a certain time t2, the robotconfiguration is represented by the context Ct2, incrementally built from units u0,

u1, u2. Unit u0 implements the set of robot basic actions (movements), while unitu1 implements a set of higher-level actions. Unit u2 implements the current strategyof the robot in order to achieve its initial goal (target goal).

unit(u0) unit(u1) unit(u2)move0(…):-… move1(…):-… explore(…):-…,##move0(…),…

When the robot executes the subgoal move0 of the clause explore in Ct2, CSM setsthe current bindcontext to Ct0 (composed by the single frame Fu0). Note that,

differently from the S-WAM, CSM does not perform any search in order to find thebindcontext, (since all the bindings are set at context creation time) notwithstandingthe lazy call to move0.

Now suppose that such a move is not immediately appliable in the currentconfiguration and that a recovery action must be immediately taken, involving thehigher-level movements defined by u1 . A way to achieve such an effect is to writethe following alternative for move0:

move0(…) :- u1 >:> recover(…) .

In S-WAM this extension implies the re-building of a data-structure (the contextdescriptor) which is instead already available in CSM. CSM automatically recognizesthat the new context already exists, and implements the extension by simply“switching” to such a context. The new dynamic extension is reduced to a reference toan object that the program had previously created, as if it were statically defined.With respect to a static language however, contextual programming does not force theuser to a-priori plan the set of all possible system configurations.

In conclusion, we can summarize CSM contexts properties as follows:- contexts can be used as first-class objects;- context data-structures are completely configured at creation time;- there is no dynamic searching for predicate definition, even in the case of lazy

calls;- context creation can take advantage from memoization techniques, to avoid

unnecessary rebuilding of contexts from scratch.

164

164

2 The CSM implementation

Viewing a context as an abstract data type means that the context-implementationpackage must provide:

- a suitable representation of the context abstraction;- the set of primitive operations (constructors, selectors, predicates).

While the S-WAM representation of a context is based on a dynamically createdchain of unit-instances supported by a new stack, the representation of a context inCSM is based on the consistent model for modular Prolog provided by the SICStussystem. A global view of the resulting architecture is reported in figure 2, whose maindesign concepts can be summarized as follows:

- a unit is a conventional SICStus module;- visible predicates of a unit are the public ones of the corresponding SICStus

module;- a context is represented as a SICStus module, not visible to the user, called

context-descriptor.

The context descriptor includes a reference to the descriptors of all the predicatesthat can be accessed within the context. The context constructorcreateCtx(U,C1,C) is implemented in two steps:

1) an internal knowledge base is consulted to know if the context C already exists;2) if the context does not already exist, a new descriptor is created for the new

context C, by updating a copy of C1 descriptor as follows:- new predicate descriptors for all the elements of Fu are created;- the references to these new predicates are added to C descriptor, overwriting

previous references in case of predicate redefinition.2

Thus, the main cost of the CSM context implementation is related to step 2 ofcontruction, in terms of both computation time and memory occupation.

The key-element, that allows us to properly map CSM data structures and operatorsinto SICStus ones, is the SICStus support for modular programming and in particularits addressing scheme, which are now briefly described.

The global architecture of the SICStus system is depicted in figure 1, where it hasbeen conceptually decomposed in a SICS-WAM part and a SICS-Cfg one. TheSICS-WAM is the SICS version of the Warren machine, which operates by using theprogram representation PR as input. The SICS-Cfg constitutes the programconfiguration part of the SICStus system, i.e. an abstract machine providing all theoperations required to incrementally extend or modify the program representation PR.

2 Thus, predicate overriding takes place. However, this does not preclude in any way the efficient

implementation of predicate extension, not discussed here for the sake of conciseness.

165

165

SICS-Cfg operations are typically executed when a new module is loaded/updated, ora predicate is asserted/retracted.

PR

SICS-WAM SICS-Cfg

heap

stack

trail

SIC

S-W

AM

dat

a st

ruct

ures

files

Figure 1 - Basic decomposition of the SICStus Prolog global architecture.(an arrow from block A to B means “B depends on A”)

The SICStus program representation has been designed so to ensure efficientpredicate addressing scheme, while providing at the same time adequate support forprogram updating operation. In particular, the program is no more a linear collectionof statement, but a tree data-structure (incrementally built up either at loading or atrun time), whose every leaf contains a clause code; coherently, SICStus compiler is asingle-clause compiler.

Thus, the addressing mechanism of the SICS-WAM is intrinsically dynamic andindirect. Indirect predicate addressing, while allowing both a more efficient way toaccess clauses and freely-mixed predicate code types, is well suited for expressingmodularity.

A SICStus module M is a list of clauses which implicitly defines a set Md of (local)predicates; a call to a predicate p/n belonging to Md is solved with respect to M clauselist (i.e. a local call policy is adopted).

Further predicates may be imported in M from other modules either implicitly orexplicitly:

- explicitly, by executing a loading directive or predicate (e.g. use_module/n);

- implicitly, by loading other modules when M is the current working module(type-in module).

Module M predicate space Mt is given by the union of both its local (Md) andimported predicates (Mi): that is, Mt = Md ≈ Mi, where Md ↔ Mi = ∅. A call toa predicate p/n (where p/n belongs to Mi and is imported from module M’ ) in a Mclause is solved as a local call to p/n in module M’ . Thus, the implicit environmentfor a predicate call in a module M is Mt; to explicitly set a different environment, thecall must be expanded by prefixing the predicate name with the name of the newmodule: e.g. M”:p/n . This call is solved in M” predicate space (M”t) according tothe above semantics.

166

166

vp vp

user_modules root

emptyCtxu0 u1 C0 C1

module descriptors

predicate descriptors

code

hash tables

prolog

p/0

u0

q/0

u0

r/0

u0

q/0

u0

vphp vp p/0

u0

C0

q/0

u0

C0

r/0

u1

C1

q/0

u1

C1

hp

vp

prolog module hidden-predicate descriptors

prolog module visible-predicate descriptors

u0:p/0

code

u0:q/0

code

u1:r/0

code

u1:q/0

code

prolog module predicates

codes

Figure 2 - Snapshot of SICStus indexing tree after the creation of contexts C0 and C1.(See text) Note: the presence (or the absence) of the prolog module visible predicates (the so-called builtin predicates) in the various CSM modules (units, contexts, the empty context); the q/0 overriding in C1; the code sharing between predicate descriptors; the sharing of predicate descriptors between context descriptors (e.g. u0:p/0).

bindcontext

167

167

The SICStus module implementation is based on a top tree structure having codetrees as subtrees (see figure 2). A SICS-WAM global variable points to the tree root(implemented by a hash table collecting all module names) whose child nodes are themodule descriptors (one for each module), recording the module name and the globalpredicate space Mt by using a hash table. Every module predicate space is againimplemented through a hash table, which keeps track of all proper predicate names,each one pointing to the respective predicate descriptor: here the system mantainsinformation about predicate name, arity, code and properties, and qualifies predicatesas imported or local, hereby implementing the distinction between the Mi and the Mdsets.

CSM exploits the SICStus module system architecture to implement the structuredaddressing space represented by a context. In particular, a context C is implementedas a SICStus module M, where:

Mt = Mi = Cd

that is to say, M has no own predicates (Md = ∅). Thus, all goes as every predicaterecorded in the context descriptor (module M descriptor) were imported, i.e eachpredicate still belongs to its original unit.

As an example of CSM behavior, let us consider the units:

unit(u0, [p/0, q/0]). unit(u1, [r/0, q/0])./* p/0,q/0 visible */ /* r/0, q/0 visible */

p :- ##q. r :- ::p.q. q.

A CSM unit is implemented as a SICStus module, whose public list is interpreted asthe CSM visible list.

The goal u0>:>u1>:>r forces CSM to perform the following steps:

1) initially, since curBindCtx(emptyCtx) is true, the goalcreateCtx(u0,emptyCtx,C0) is called and CSM produces thecorresponding C0 data structures, as reported in figure 2.

2) next, createCtx(u1,C0,C1) is called, and CSM builds the new datastructures reported in figure 2 (corresponding to C1), performing the actionsbelow:- the C1 context descriptor is created, by using SICStus system operations;- the C1d predicate space is created, by copying the C0d one, i.e. duplicatingC0 hash table;

- the u1 module descriptor is used to include each pair of the frame Fu1 in theC1d space. More precisely, a new descriptor is first created for each u1vpredicate (r/0 and q/0); then, a reference to the r/0 descriptor is added toC1d hashtable, while the reference to the new q/0 descriptor replaces theone inherited from C0d.

3) the goal C1♦r (a context switch) is called. This goal is solved as a normalSICStus explicit module call, enveloped in suited CSM state handling

168

168

operations; conceptually, CSM works according to the following high-levelspecification:

C♦G :- curCtxs(CC,BC),bindCtx(G,C,B),setCtxs(C,B),C:G,setCtxs(CC,BC).

The predicate curCtxs/2 returns the current CSM contexts, whilesetCtxs/2 performs the context switch. The predicate bindCtx/3 returnsin B the bindcontext of the goal G with respect to the context C by directlyretrieving it from the G predicate descriptor (see figure 2).Then the subgoal ::p of r (an eager call) is called in C1. CSM implements theeager call operator as a context call to the current binding context:

::G :- curBindCtx(C),C♦G.Finally, predicate p/0 in u0 produces a lazy call to q/0, which is consequentlysolved as a context call to the current (lazy) context:

##G :- curCtx(C),C♦G.Therefore, no dynamic search is performed for binding purposes.

Context memoization

When a context is created, a CSM internal knowledge-base is consulted (andupdated) in order to record the context structure. Such a knowledge-base could berepresented as a collection of high-level Prolog facts. However, for efficiencypurposes, it has been implemented as a new CSM data structure, by extending thedata structures of figure 2 with other ones like those reported in figure 3.

C1

SICStus data structures

CSM Knowledge Base data structures

u1C0u0

top unit info

top unit info <nil>

context structure descriptors

context & unit (module) descriptors

top unit sub1 ctx

top unit sub1 ctx

context context

Figure 3 - Context structure descriptors in CSM Knowledge Base

3 Conclusions

Among the proposals for extending logic languages with program structuringmechanisms, contextual programming distinguishes itself by providing tools forbuilding structured software components in a dynamic way according to applicationneeds.

169

169

In this work, we have provided a new view of contexts, by defining them as newprimitive data types whose instances can be interpreted in two ways: as structuredbinding environments to resolve predicate references (calls) and as first-class objects.

The main advantage of this proposal consists in the chance to use contexts to define(prototypes of) software components that can be further specialized in an incrementalway without restarting from scratch. To obtain such a goal, we have presented animplementation whose main cost is related to the context creation operation. In fact,contexts are built (by exploiting memoization techniques) as completely configureddata-structures that keep track of all the predicates accessible in it. The cost of contextcreation is widely balanced by the fact that no run time overhead arises for bindingpurposes, even in the case of late binding policies.

Context data-structures however, have not been defined in an ad-hoc manner.Rather, they have been defined starting from the data-structures provided by acommercial and efficient Prolog system (the SICStus Prolog) in order to supportmodularity.

Since the SICS-WAM is intrinsically based on an indirect addressing scheme viamodule descriptors, each context instance has been implemented as a hidden module(the context descriptor) properly configured at context creation time. Our contextualmachine (CSM) has been developed starting from SICStus Prolog version 2.0 andmaintains full compatibility with such a system, without introducing any overhead inthe case of conventional Prolog programs, since the SICS-WAM remains unchanged.

In order to support the same general-purpose binding policies discussed in [LMN],CSM implements both lazy/eager binding policies and cactus/linear contextextensions, by keeping track of two contexts into low-level registers (as in theS-WAM, whose architecture has a strong correspondence with the CSM one).

However, while S-WAM represents and handles contexts by adding a new stackwithin the WAM, CSM leaves the SICS-WAM unchanged, by implementing contextsin the program representation space. As a result, the S-WAM provides automaticmechanisms for context deallocation, while CSM does not.

The price paid by the S-WAM approach is the need to re-create a context each timeit is required, while the CSM approach needs explicit control at program level forcontext deletion operations.

With respect to the concept of context supported by the S-WAM however, thechance offered by the CSM to use contexts as first-class objects opens newperspectives from both a practical and a theoretical point of view. In the future, weintend to explore such new perspectives, with particular respect to the definition ofcontext-based supports for the definition of objects with state and object-orientedlogic programming languages.

Acknowledgements

This work has been partially supported by the “Progetto Finalizzato Sistemi

Informatici e Calcolo Parallelo”, of CNR under grant nº 890004269.

170

170

171

171

REFERENCES

[BR91] M. BUGLIESI, C. RUGGIERI, A Prolog Object-Oriented System: anExercise in Contextual Logic Programming, in Proceedings of theSixth Conference on Logic Programming, Pisa, Italy, June 1991.

[B91] M. BUGLIESI, A declarative view of inheritance in LogicProgramming, Computer Sciences, Purdue University,November 1991.

[LMN] E. LAMMA, P. MELLO, A. NATALI, An Extended Warren AbstractMachine for the Execution of Structured Logic Programs, to appearin Journal of Logic Programming, North-Holland, 1992.

[LMN89] E. LAMMA, P. MELLO, A. NATALI, The design of an abstractmachine for efficient implementation of contexts in LogicProgramming, in Proceedings of the Sixth International Conferenceof Logic Programming, Lisboa, Portugal, MIT Press, June 1989.

[MP89] L. MONTEIRO, A. PORTO, Contextual Logic Programming, inProceedings of the Sixth International Conference of LogicProgramming, Lisboa, Portugal, June 1989.

[GMR88] L. GIORDANO, A. MARTELLI, G.F.ROSSI, Local definitions withstatic scope-rules in Logic Languages, in Proceedings of the FGCSInternational Conference, pp. 389-396, Tokyo,Japan, 1988.

[SICS91] SWEDISH INSTITUTE OF COMPUTER SCIENCE, SICStus PrologUser’s Manual, Kista, Sweden, 1991.