Introduction

\label{des/intro} \phrase{- The activity of the intuition consists in making spontaneous judgements which are not the results of conscious trains of reasoning ... -} {A. Turing, from Andrew Hodges, The Enigma of Intelligence} \nop{ The introduction of object oriented technology in the practice of software engineering has been of significant influence on the software life cycle. } \nop{ Traditionally, the software life cycle is subdivided in an analysis phase in which the requirements for a system are laid down, a design phase in which a conceptual architecture for a system meeting the requirements put forward in the analysis phase is proposed, an implementation phase in which the conceptual structure resulting from the design phase is embodied in actual software and an operational phase that includes installing and maintenance of the system. The transition from one phase to the next usually involves a significant effort of translating the results into the formalism appropriate to that phase. } The use of object oriented techniques in the design and implementation phases of software development projects has resulted in a shift of emphasis in favor of the design phase since the effort of implementing a system in an object oriented programming language on the basis of an object oriented design may be regarded as a process of refining the decisions laid down in the design. The use of object oriented techniques has thus effectively reduced the gap between the concept-oriented world of design and the technology-oriented world of implementation. C.f.  [WWW90] and  [Meyer88]. This development may be taken a step further by proposing a logic-based object oriented language that allows to employ an abstract specification of an object oriented system as a prototype.\ftn{ In this context I may remark that, independent of the introduction of object oriented technology, the need for prototyping has arisen in software engineering practice to accommodate the difficulty of eliciting the proper requirements in the analysis phase. It is generally acknowledged that prototyping is well supported by object oriented programming languages. } We will introduce a distributed logic programming language DLP that allows to specify an object oriented system in a highly abstract way. The language proposed extends logic programming with features specifically geared towards the specification of object oriented systems and thus corrects what has been commonly felt to be one of the major drawbacks of logic programming: the lack of support for specifying large systems in a structured way. In addition to object oriented features, the language DLP supports parallelism, by allowing objects to have activity of their own. For many problem areas, concurrency or parallelism is a very natural phenomenon. Parallism and distribution fit in well with the object oriented paradigm since the actual (possibly concurrent) behavior or location of an object may remain hidden for the clients of an object. An important application of DLP lies in the area of distributed knowledge based systems. We feel that the object oriented modeling approach may support a proper distribution of the various reasoning tasks that are involved, by taking the natural activity of the actors in a domain as the guideline in developing an intelligent system.

Principles of object oriented modeling

The philosophy of design underlying object oriented software development centers around abstraction and information hiding. Objects, encapsulating state and behavior, support these notions. Moreover, objects provide a natural means to model a problem since the objects in a system may bear a close correspondence to the entities encountered in reality. As phrased in  [Booch86], each module in the system denotes an object or a class of objects from the problem space. As a design method, the approaches treated in  [Booch91] and  [WWW90] have in common an emphasis on the identification of the objects that play a role in the system and on delineating the functionality of these objects, that is to assess what services are provided and how the objects interact in order to provide these services.\id{ As an heuristic guideline for finding the proper objects, often a 'linguistic' analysis of the documents stating the requirements is proposed. Nouns may suggest objects and verbs may suggest operations that are to be performed by objects. } \nop{ Clearly, of a design method, as opposed to a programming language, we require to be able to characterize objects and their possible interactions with other objects in an abstract way, ignoring implementation dependent details. However, since objects are the major organizing principle both in object oriented programming and design, the distinction between design and implementation lies in the degree that abstraction and conceptual clarity is supported. For developing a design method, the central question is what we consider to be objects and what means must (minimally) be provided to characterize the functionality of objects and their interactions with other objects. }

Objects

 [Booch86] characterizes objects as (clearly identifiable) entities that suffer and require actions. Operationally, an object may be defined as to comprise a state and behavior. The actions an object suffers may be requests to give information on its state or may demand to change the state of the object. To provide a service an object may need to issue such requests to other objects. In an object oriented system, computation amounts to sending messages between objects. Objects provide the means to encapsulate data and procedures and to hide the details of the implementation from the clients by specifying an external method interface. Apart from contributing to the modular structure of a program the encapsulation mechanism allows local changes to objects and thus enhances the maintenance of an object oriented system. Objects may play a variety of roles, that is an object may be merely a passive server, awaiting requests to execute a message, or objects may autonomously control (parts of) a computation. The most usual case, however, is for an object to figure in both roles, and to collaborate with other objects in order to provide a service.

Inheritance

There is some debate whether inheritance is to be considered an integral part of an object oriented development method. C.f.  [Booch86]. I share the view expressed in e.g.  [HOB87] that inheritance is of major importance in the design and implementation of object oriented systems as a mechanism to suppress the complexity of a large collection of object descriptions by means of a hierarchical organization according to their functionality. Moreover, inheritance is of essential importance for the effective reuse of software. C.f.  [Meyer88] and  [WWW90]. In object oriented design, inheritance comes down to sharing specifications of behavioral properties of objects.\id{ In object oriented programming languages inheritance by code sharing has proven to be a very powerful mechanism. }

Object oriented design

The principal guideline in object oriented design is to find some meaningful decomposition, that allows to regard each of the components as an object providing certain services, reflecting the structure of the problem domain. Describing objects and characterizing their structural relations by means of inheritance are the two major components of an object oriented design methodology. Objects provide a mechanism to abstract from the details of how a service is provided. To make use of a service, it suffices to know what services an object offers and what messages must be sent to request for that service. Inheritance provides a means to create a hierarchy of objects and to separate the stable conceptual issues from more specific volatile details.

The concept of distributed logic programming

Distributed logic programming (DLP) may be characterized by the pseudo-equation [] DLP = LP + OO + || stating that distributed logic programming combines logic programming (LP), object oriented programming (OO) and parallelism ( || ). \nop{ The nature of the features supported by DLP will be introduced in the next section and further explained in chapter \ref{des/ext}. Here a brief characterization will be given of the distinct paradigms of computing that form the foundation of DLP. }

Logic Programming

has originally been used only in the context of Artificial Intelligence. Its most popular representative is Prolog. Because of its logical basis it allows to solve problems in a declarative way, that is by providing a logical description of the problem to be solved. See  [Ko79],  [Bratko]. However, usually such specifications must be refined to become efficiently executable. C.f.  [Ho87]. Prolog is a very suitable language for prototyping small systems. In software engineering practice, logic programming and in particular Prolog has been recognized as a potential aid in requirements engineering and design specification. See  [Webster].

Object Oriented Programming

has rapidly grown into a popular paradigm for developing complex systems. Objects integrate data and methods that operate on these data in a protected way. This allows to organize a program as a collection of objects, representing the conceptual structure of the problem. Part of the popularity of object oriented languages is due to the facilities for code sharing as offered by the inheritance mechanism. See  [We87]. Object oriented programming allows to model problems in a very natural way. Its major promise for software engineering practice is in my opinion that it offers the opportunity of a close link between the various phases of the software life cycle, the engineering of requirements in the analysis phase and the design and implementation phases. C.f.  [WWW90],  [Meyer88].

Parallelism

is somehow of independent interest. Most of the developments in parallel logic programming are based on exploiting the parallelism inherent in the computation model of logic programming languages. Parallelism in DLP is achieved by extending the notion of object to that of a process, in a similar fashion as the approach taken for POOL  [Am87]. DLP, however, also supports multi-threaded objects, that have autonomous activity and may simultaneously evaluate method calls. As  [Booch86] observes, objects provide a natural way to introduce concurrency, by associating (possibly multiple) processes with objects. Despite the fact that parallelism is often inherently part of the problem domain, not many design specification formalisms support concurrency. See  [Webster]. A design goal in developing DLP was to provide a syntactically elegant language with a clear semantics that allows to express the conceptual structure of a program in a straightforward way and that may serve as a vehicle for prototyping. The next section summarizes the main ingredients of the language DLP. Readers not familiar with the language Prolog may wish to consult section \ref{des:lp} first.

The language DLP

The language DLP may be regarded as an extension of Prolog with object declarations and statements for the dynamic creation of objects, communication between objects and the assignment of values to non-logical instance variables of objects.

Object declarations

Object declarations in DLP have the form \dlpindex{object} \oprog{object}{
  object name {
  var variables.
  clauses
  }
  
} Both object and var are keywords. The variables declared by var are non-logical variables that may be assigned values by a special statement. Objects act as prototypes in that new copies may be made by so-called new statements. Such copies are called instances. Each instance has its private copy of the non-logical variables of the declared object. In other words, non-logical variables act as instance variables. Dynamically, a distinction is made between active objects and passive objects. Active objects must explicitly be created by a new statement. Syntactically, the distinction between active and passive objects is reflected in the occurrence of so-called constructor clauses in the declaration for active objects. Constructor clauses are clauses of which the head has a predicate name identical to the name of the object in which they occur. Constructor clauses specify an object's own activity. The other clauses occurring in an object declaration may be regarded as method clauses, specifying how a request to the object is handled. Passive objects only have method clauses.

Statements

DLP extends Prolog with a number of statements for dealing with non-logical variables, the creation of objects and the communication between objects. These statements may occur as atoms in a goal.

Non-logical variables

For assigning a term t to a non-logical variable x the statement \dlpindex{\assignexpr} <>- x := t is provided. Before the assignment takes place, the term t is simplified. The non-logical variables occurring in t are replaced by their current values. In fact, such simplification takes place for each goal atom. DLP also supports arithmetical simplification. \nop{ For accessing the value of a non-logical variable x of some object O a term of the form [] O@x is used. This term is simplified to the value of that non-logical variable when the atom in which it occurs is evaluated. }

New expressions

For dynamically creating instances of objects the statement \dlpindex{\newpassiveexpr} <>- O = new(c) is provided, where c is the name of a declared object. When evaluated as an atom, a reference to the newly created object will become bound to the logical variable O. For creating active objects the statement \dlpindex{\newactiveexpr} <>- O = new(c(t1,...,t_n)) must be used. The activity of the newly created object consists of evaluating the constructor goal c(t1,...,t_n), where c is the object name and t1,...,t_n denote the actual parameters. The constructor goal will be evaluated by using the constructor clauses. Actually, the expressions new(c) and new(c(t1,...,t_n)) will be simplified to a reference to an object when they occur as a term in a goal. Both the statements introduced above may be regarded as special cases, in which the new expressions occur in a unification goal.

Method calls

A method call is the evaluation of a goal by an object. To call the method m of an object O with actual parameters t1,...,t_n the statement \dlpindex{\methodcallexpr} <>- O!m(t1,...,t_n) must be used. It is assumed that O is a logical variable referring to the object to which the request is addressed. When such an atom is encountered, the object O is asked to evaluate the goal m(t1,...,t_n). If the object to which the call is addressed is willing to accept the request then the result of evaluating m(t1,...,t_n) will be sent back to the caller. After sending the first result, subsequent results will be delivered whenever the caller tries to backtrack over the method call. If no alternative solutions can be produced the call fails. Active objects must explicitly interrupt their own activity and state their willingness to accept a method call by a statement of the form \dlpindex{\acceptexpr} <>- accept(m1,...,m_n) which indicates that any request for one of the methods m1,...,m_n will be accepted.

The computation model of DLP

The computation model of DLP combines the computation model underlying Prolog and the model underlying a parallel object oriented language. Parallel object oriented processing must support objects, processes and communication between objects.

Objects

contain non-logical data, persisting during the life time of the object, and clauses defining the functionality of the object.\nop{ The clauses are identical to ordinary Prolog clauses, except for the possible occurrence of special atoms for creating new objects or for communicating with other objects. } Objects may be active or passive. The activity of an object is defined by so-called constructor clauses that describe the own activity of an object. Apart from constructor clauses, active objects may also contain so-called method clauses that are used when the object receives a method call. A method call is simply the request to evaluate a goal.

Processes

are created when creating a new active object and for the evaluation of a method call. The process executing the own activity of an active object is called the constructor process. For each method call a process is created to enable backtracking over the results of a method call. Passive objects have no activity but answering to method calls. Active objects must explicitly interrupt their own activity to indicate the willingness to answer a method call.

Communication

with another object takes place by engaging in a (synchronous) rendez-vous. In order to achieve compatibility with the ordinary Prolog goal evaluation, DLP supports global backtracking over the results of a rendez-vous. With respect to backtracking, it is transparent whether a goal is evaluated remotely, by another object or locally, provided the necessary clauses are defined. This transparency holds for both passive and active objects. Below is pictured what happens when a process issues a method call to an active object. Here we assume that accept statements may occur only in the constructor process associated with an (active) object. .so sv As soon as both the process calling the method and the constructor process of the object to which the call is addressed have synchronized, the activity of the constructor is interrupted and a process is created to evaluate the goal m(t1,...,t_n). The constructor is interrupted for safety reasons, in order to guarantee that no other method call will be accepted. The calling process waits for an answer. As soon as the caller has received a result, both the calling process and the constructor process resume their activity. On backtracking, the calling process may ask for alternative solutions. Passive objects allow unlimited internal concurrency: in other words, an indefinite number of method calls may be active simultaneously. For active objects, mutual exclusion is provided to the extent that when a particular method call is accepted no other method call will be accepted until the first answer for that call is delivered. This protocol of mutual exclusion seemed more natural than either locking out the object until all answers have been delivered or providing no mutual exclusion at all.

An example

As an example, consider the object declaration for a travel agency. \lprog{agency}{ .ds agency.pl } A travel agency may be asked for a destination. The destinations an agency offers are contained in a list of cities. The non-logical variable cities storing this list is initialized to contain as possible destinations amsterdam, paris and london. Creating a new agency, and subsequently asking it for a destination, is done as in the following goal.
  	?-
  		O = new(agency()),
  		O!destination(Y),
  		...
  
When evaluating the first component of this goal the logical variable O will become bound to the newly created agency that offers as destinations amsterdam, paris and london. Immediately thereafter the method call O!destination(Y) will be evaluated, but the call will not be accepted until the accept statement expressing the willingness to accept a call is reached. The evaluation of the method call will result in binding Y to amsterdam and when backtracking occurs, subsequently to paris and london. Then the call will fail. Backtracking over a new statement is not possible. This call will simply fail. \nop{

And parallelism

As an additional primitive DLP offers an and-parallel operator. The goal ?- O!destination(tokyo) & O!add(tokyo) will result in concurrently requesting the object O to check for the destination tokyo and to add tokyo as a destination. Due to the mutual exclusion between method calls, since an agency is an active object, one of the calls will be accepted first and exclude the other until it has produced a result. So the goal above may either fail or succeed, depending on whether the request for adding a destination is granted first. }

Inheritance

An essential feature of the object oriented approach is the use of inheritance to define the relations between objects. C.f.  [We87],  [WZ88],  [HOB87]. Inheritance may be conveniently used to factor out the code common to a number of objects. For an untyped language, as DLP, inheritance is a facility to share code. The declaration for an object inheriting from an object base is \dlpindex{inheritance} \oprog{inheritance}{
    object name : base {
    var variables.
    clauses
    }
  
} This declaration will result in adding the non-logical variables and clauses declared for the object base to those of the declared object. Any non-logical variables of the base object that occur also in the declared object will be overwritten by the non-logical variable of the declared object. This will be of significance only when at least one of the non-logical variables has an initializing declaration. Such overwriting does not take place for clauses. When the declared object contains clauses similar to clauses in the base object, concerning the same predicate, then these will be treated as alternative choices for evaluating an atom. As an example, consider the relation between a researcher and a professor, stated in the declaration below. \lprog{researcher}{
   object researcher {
   var field.
  
   knowsof(X):- member(X,field).
   }
  
   object professor : researcher {
  
   knowsof(X):- committee(Conference,X).
  
   }
  
} The intended meaning here is that a professor knows of the topics of the conferences for which he has been a member of the program committee, in addition to what he knows of as a researcher.

Relation to other work

The inspiration for this work comes from three directions: design representation technology, multiple-paradigm languages and distributed problem solving.

Design representation technology

The idea of employing distributed logic programming as a tool for supporting the design of (object oriented) software systems is inspired by the survey of design representation techniques given in  [Webster]. \nop{ Design representation technologies are classified in  [Webster] along the axes of formality and conceptual complexity. With regard to formality distributed logic programming (as embodied in DLP) lies, in my estimate of this classification, between Prolog and knowledge representation formalisms such as KEE and ART. It is not as formal though as ordinary first order (mathematical) logic or algebraic specification formalisms such as OBJ. This lack of formality is primarily due to the facilities offered for parallelism and the distribution of processes. The expression of conceptual complexity is definitely enhanced by the introduction of object oriented features that allow to structure a system in semi-independent entities, and a fair estimate is that distributed logic programming is comparable in this respect to frame-based languages such as KL-ONE and the methods commonly employed in object oriented design. Distributed logic programming shares with the knowledge representations formalisms mentioned that its specifications are executable. In contrast to these formalisms, I wish to stress that the proposed approach is logic-based, thus allowing for a declarative interpretation of its components, insofar these are implemented in a pure logic programming style. } Because of its declarative nature, the language DLP may be used to specify an object oriented system in an abstract way. Due to the fact that DLP is a high level programming language, this specification may be used as a prototype embodying the behavior of the system.

Multiple-paradigm languages

As related approaches in combining logic programming, object oriented programming and parallelism, I wish to mention first of all Delta Prolog that also supports distributed backtracking, but in the context of a less powerful communication mechanism.  [PM85]. Delta Prolog does not, however, provide any modularization construct. Modularization in an object oriented style is offered by MultiLog, a multi-tasking object oriented Prolog developed to support prototyping embedded systems, that are (eventually) to be implemented in Ada.  [Ka88]. The distinguishing feature of DLP with respect to MultiLog however is that DLP supports backtracking over the answers of a method call by rendez-vous, whereas MultiLog proceeds from the assumption that such backtracking is not needed. Other efforts at extending logic programming with object oriented features are reported in  [ST83],  [Za84] and  [Da89]. \nop{ Also related is the work on distributing (medical) reasoning tasks reported in  [GC81]. A logical basis to this approach has been provided in  [KT90]. The DLP approach to the issue of defining generic reasoning tasks comes from a programming perspective. In this respect DLP may be compared to the proposal in  [HL89], exploring the use of the object oriented programming paradigm in a distributed problem solver. }

Distributed problem solving

Also related is the work on distributing (medical) reasoning tasks reported in  [GC81]. A logical basis to this approach has been provided in  [KT90]. The DLP approach to the issue of defining generic reasoning tasks comes from a programming perspective. In this respect DLP may be compared to the proposal in  [HL89], exploring the use of the object oriented programming paradigm in a distributed problem solver. A more extensive discussion of related approaches is given in section \ref{des/per/dlp}.

An overview of this book

\label{des/intro/ov} Our research covers the design, the semantics and the implementation of the language DLP.

Design

In part I we will introduce the language and present a number of examples that illustrate the use of the language. However, before this, an introduction will be given to the paradigms underlying distributed logic programming.

Logic programming

Since, undeniably, logic programming lies at the heart of our approach, an extensive introduction is given to logic programming, and the language Prolog. The notion of a logic program will be introduced and a thorough account will be given of the relation between the declarative, that is logical, interpretation and the procedural interpretation of a logic program, allowing logic programs to be used for computing. The nature of unification will be explained and the role of the logical variable therein. For readers not familiar with the language Prolog, a treatment will be given of the basic constructs of the language as well as its particular features. Examples will be presented that explain the use of these features. Further, two typical search problems will be discussed for which Prolog may conveniently be used.

Object oriented programming

To introduce object oriented programming, a brief account will be given of the developments that have contributed to the popularity of object oriented programming. Objects will be characterized as a device to encapsulate data and procedures that operate on these data. We will look at classes, as templates for creating objects. Then the notion of inheritance will be introduced, and the use of inheritance to factor out the functionality of a collection of objects or to create a specialization hierarchy will be explained. Further, we will discuss the role of object oriented modeling from the perspective of the requirements analysis and the design underlying a system. \nop{ Further, the relation between subclasses and subtypes will be discussed and the role of this distinction in an untyped setting. Finally, to conclude our introduction of object oriented programming, we will look at some object oriented languages and systems. }

Parallel/distributed programming

Next, a characterization will be given of the major features of distributed programming and the three models underlying parallel/distributed programming will be introduced: communicating sequential processes, object-based concurrency and concurrent logic programming. Communicating sequential processes provide a basic model to employ parallelism. Communication in this model may be characterized as synchronous transfer of values. Then it will be explained how objects may be combined with concurrency and we will take a closer look at the rendez-vous concept that is supported by Ada as a means to call remote procedures. The notion of active objects and method calls by rendez-vous will then be introduced. Lastly, we will discuss the computation model of concurrent logic programming and show how objects may be implemented using shared logical variables that act as channels between processes.

Software engineering

We will conclude the introduction of the paradigms underlying distributed logic programming by reviewing the contributions of each of these paradigms to the practice of software engineering and we will assess their shortcomings. Briefly, we will discuss how distributed logic programming might provide a remedy.

The language DLP

After introducing the paradigms out of which distributed logic programming originated, we will introduce the constructs of the language DLP by exploring how the language Prolog may be extended to support parallel object oriented programming. Objects will be introduced as a modularization construct that may contain non-logical (instance) variables, and it will be described how processes are created to evaluate method calls and to execute the own activity of (active) objects. We will explore the use of synchronous bi-unification accross channels as a mechanism to communicate between objects. Then method calls by rendez-vous will be introduced that allow synchronization by explicit acceptance statements and that support distributed backtracking over the results of a call. An extension of accept statements will be introduced that allows acceptance to depend on the parameters of the call. Then, it will be shown how the communication primitives implementing the synchronous rendez-vous may be used for engaging in an asynchronous rendez-vous and how this mechanism allows the user to define (restricted) and-parallelism. We will further explain how the language supports the distribution of objects and processes over processors. Finally, after summarizing the constructs by which DLP extends Prolog, we will distinguish three subsets of DLP of increasing complexity that will serve as a basis for our semantic study of DLP in part II.

Object oriented modeling

To illustrate how DLP may be applied in developing actual systems it will be shown how inheritance and delegation may be used to factor out control in searching a state space. Also, an object oriented solution to the N-queens problem is presented that illustrates how to connect a number of active objects. The use of inheritance for knowledge representation will be investigated and we will discuss the way that inheritance may be of influence on backtracking. To demonstrate the role of object oriented modeling in developing systems for distributed problem solving we will describe the specification and implementation of a distributed medical expert system. The example shows how control may be distributed according to the hierarchic organization of the knowledge.

Design perspectives

Having introduced the language DLP we will take a step back and reflect on the motivations underlying our approach to distributed logic programming. We will discuss the notion of distributed knowledge processing and our contribution to this area. We will then pay attention to related work aiming at the integration of logic programming, object oriented programming and parallel/distributed programming. A distinction will be made between these approaches according to their point of departure, that is whether they strive for an integration starting from a combination of logic programming and object oriented programming, logic programming and parallelism, or object oriented programming and parallelism. The design choices made for DLP will be motivated during this discussion.

Semantics

In part II, we will study the semantics of DLP. To characterize the behavior of programs, we will employ the technique of structured operational semantics introduced in  [Plo83]. In order to show that these semantics are well-defined in a mathematical sense, we will also provide a compositional denotational semantics. The mathematical framework in which this semantic study takes place is the metric approach originally developed in  [BZ82]. Chapter 6 provides a thorough introduction to the metric approach and its application to concurrency semantics. In order to manage the complexity of our task, we have distinguished three subsets of the language DLP that allow us to study the various behavioral phenomena of distributed logic programming in a more isolated way. The simplest subset is a language that supports backtracking. We will extend this language with features for dynamic object creation and synchronous communication between objects with local backtracking that takes place within the confines of an object. Finally, our last subset represents a language that supports dynamic object creation and method calls by rendez-vous, allowing distributed backtracking over the results of a rendez-vous. Before giving the semantics of (these subsets of) DLP, we will study the semantics of what we call uniform abstractions of these subsets, in which we will pay no attention to assignments to non-logical variables and the unification of logical variables. The results of this preliminary study carry over to our semantic study of DLP in a surprisingly smooth way. It must be remarked that the semantics given are of a behavioral nature, that is characterizing the flow of control within objects and the communication between objects. These behavioral semantics must be regarded as complementary to a declarative semantics that clarifies the meaning of a program in terms of a logical model. It seems unlikely that such a declarative semantics is possible at all, without taking recourse to dynamic logic or possible worlds semantics. In chapter 12 some recommendations will be given of how to approach the problem of providing a declarative semantics for DLP.

Implementation

In part III, a detailed description is given of the implementation model employed in the prototype implementation of DLP. Our solution to integrating the computation models of logic programming and object oriented programming in a parallel/distributed setting has been to extend an imperative parallel object oriented language with logic programming capabilities. Since our language DLP supports backtracking over the results of a rendez-vous, we had to make an explicit distinction between objects and processes. An interesting feature of our solution is the way the results of a method call are communicated to the calling process by means of so-called resumptions, which are goals that must be executed by the caller in order to effect the bindings resulting from the call. In developing the prototype implementation of DLP, the code for the Prolog interpreter was derived from a formal continuation semantics of Prolog. Employing such a technique for implementing a protoype of an experimental language may be fruitful, since the resulting code will in general be rather compact. For an efficient implementation, however, an abstract machine approach such as the WAM for Prolog is an absolute necessity. See  [Wa83]. A detailed description is given of the implementation of the prototype of DLP, including the way terms are handled, the implementation of objects and the communication protocols governing the communication between objects. We will then comment on the current status of the language and its implementation. Further, some recommendations will be given for improving the efficiency of the DLP system and we will explore the possibility of providing a declarative semantics for a distributed logic programming language such as DLP.