[m-dev.] for review: EDCGs - intro

Peter Nicholas MALKIN pnmalk at cat.cs.mu.OZ.AU
Fri Dec 24 14:09:34 AEDT 1999


Hi,

Estimated Hours Taken: >100

The EDCG syntax as described below is implemented. The transformation from code
with EDCGs to code without, is done when items are placed into the HLDS. The
main data structure for EDCGs is hidden_info, and the main data structure within
hidden_info is state_info (both defined in edcg.m). Each hidden variable has an
entry in state_info which is a map from hidden variables to their states.  The
state of a hidden variable mainly consists of whether it is alive or dead
(within scope or not within scope respectively) and a variable (prog_var) which
it currently represents (if it is alive). 

There is a copy of the diff at ~pnmalk/MERCURY/DIFF. The diff is also posted in
subsequent emails.

Peter

Description of Extended Definite Clause Grammars (EDCGs).
=========================================================

EDCGs are as their name implies are similar to DCGs, except more variation is
allowed in the usage of implicit arguments (referred to here as hidden
arguments). Like DCGs, EDCGs do not change the semantics of the language. They
are similar to DCGs, in that the compiler performs a source to source
transformation of the EDCG code. 

EDCGs are a way of implicitly using variables (through hidden variables) that
can be used within the body of a clause without explicitly listing the variable
in the head argument list or in any predicate call argument list within the body
of the clause. A hidden variable represents a single variable at a time, but not
necessarily always the same variable. Each hidden variable has associated with
it a name (hidden variables are module qualified) that must be distinct from all
other hidden variable names. A hidden variable can be only be used in specific
places where it is in scope. 


EDCG Declarations
=================

Type Declarations
-----------------
Each hidden variable must be declared using an `htype' declaration. Each hidden
variable has a type associated with it, the type of the variable it represents.

The htype declaration is of the following form:

:- htype(HiddenName, Type).

Where Type is a Mercury type, the type associated with HiddenName.


Predicate Declarations
----------------------
If a hidden variable is to be used implicitly within the clause head of a 
predicate then it must be declared within the `pred' declaration for that 
predicate. Each hidden variable can only be declared once within a predicate 
declaration. Predicate declarations are extended with an optional hidden part:

:- pred PredName(VisableArgs)[+hidden(HiddenVars)].

Where `+' and `hidden' are required syntactic elements and HiddenVars is a
comma-separated enumeration of HiddenVar's. A HiddenVar can be one of
two forms: 

	changed(HiddenName)
	passed(HiddenName)

where HiddenName is the name of a hidden variable declared in an `htype'
declaration. The same hidden variable can be used in different forms in
different predicates.

For each HiddenVar the predicate declaration is extended with two (changed) or
one (passed) additional argument, in the order the hidden variables are listed.
The additional argument(s) have the Mercury type, as specified in the
corresponding htype declaration for HiddenName. A predicate can be called
with its hidden variables listed explicitly (only used for backwards
compatability with DCGs, a warning message will be given if used).

Two different predicates are not allowed to be defined with the same functor 
and the same "visual" arity (the number of arguments not including hidden 
arguments). Two different predicates are not allowed to be defined with the same
functor and the same "total" arity (hidden plus visual arity). There is no
overloading allowed for predicates with hidden variables.

Every clause that uses hidden variables must have the functor '-->>' instead 
of ':-', to symbolise that the order of the goals in the body of the clause 
is significant.


Mode Declarations
-----------------
Each hidden variable must have an `hmode' declaration specifying the mode(s)
of the hidden variable. Only here can the mode of a hidden variable be 
specified.

The hmode declaration is of the following form:

:- hmode(HiddenName, [changed(Mode, Mode),] [passed(Mode)]) 

Where HiddenName is the name of a hidden variable declared in an `htype'
declaration and Mode is a Mercury mode.

A single mode is associated with the form passed and two modes with the form
changed. The mode declarations for the different hidden forms do not need to
appear in the above order. A form only needs a mode declaration if the hidden
argument is called in that form, otherwise it can be left out. Only one mode
declaration can be given for each form of a hidden variable (this is not
necessary and can be extended). Only one hmode declaration is allowed for any
particular hidden variable.

Hidden argument modes cannot be declared in normal predicate mode 
declarations. When a predicate has a hidden variable then its mode
declaration will be expanded to include the mode(s) of the hidden 
argument's form in which it is called (in the order they are listed in the 
pred declaration).

NB: The form of the hidden variable is in no way related to its mode. There is
no restriction upon which mode(s) can be assigned to which form.


EDCG Manipulations
==================

EDCG Operators
--------------
There are two primitive operators to manipulate hidden variables. The operators
can be used in predicate calls or unifications. 

(i) accessing:	`$HiddenName' -> `Var'
Where HiddenName is a hidden variable and Var is the variable that HiddenName
currently represents. The hidden variable continues to represent the same
variable. This can be used with hidden variables that are in either
form (passed or changed).

(ii) changing: `$=HiddenName' -> `NewVar'
Where HiddenName is a hidden variable and NewVar is a new variable that
HiddenName now represents (the previous variable is now inaccessable).
This can be used only with hidden variables that are in changed form.

For these operators the order of processing can make a difference.
For example: `$=hidden = [X | $hidden]' can mean two different things if
processed left to right as opposed to right to left.
All arguements of terms are processed in a left to right manner unless the
functor is `=' (it is a unification) in which case the right is processed before
the left (but the individual arguments of the unification will be processed in a
left to right manner).

EDCG Predicate Calls (not higher order)
---------------------------------------
Predicate([, Arg1 [, Arg2 ...]])+hidden(HiddenVars)

Where HiddenVars is a comma separated enumeration of either:

(i) HiddenName(Var): 
	HiddenName was declared as passed for the specified predicate. Var will
	be added to predicate's argument list in the appropriate place.
or

(ii) HiddenName(Var1, Var2):
	HiddenName was declared as changed for the specified predicate. Var1 and
	Var2 will be added to predicate's argument list in the appropriate
	places.  

The elements in the enumeration can occur in any order. The list may be
incomplete; i.e. if a predicate receives two hidden arguments, zero, one or two
hidden arguments may be listed, as long as the hidden arguments received by the
predicate that are not listed are currently in scope.

This may be used inside or outside of an edcg clause (functor is "-->>").


EDCG Goals
----------
An edcg goal may be written as:

(edcg(HiddenVars) -->> Goal)

This goal may be used any where within the body of a clause where any other
goal may be used.

Where HiddenVars is a comma separated enumeration of either:

(i) HiddenName(Var):
	HiddenName has the form passed for the goal. HiddenName represents Var
	during the goal.
or

(ii) HiddenName(Var1, Var2):
	HiddenName has the form changed for the goal. HiddenName initially
	represents Var1 for the goal. The variable HiddenName represents at the
	conclusion of the goal is unified with Var2.

The elements in the enumeration can occur in any order.

This may be used inside or outside of an edcg clause.


EDCG Scope
==========
The scope of an edcg variable is either:

(i) The entire clause of any predicate which the hidden variable was listed in
the hidden argument part of the predicate's pred declaration.

(ii) The entire goal of an EDCG-goal within any clause. If the same hidden
variable exists in the scope of the enclosing clause of the goal then the local
definition is used.


--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list