for review: EDCG syntax: READ ME INSTEAD OF PREVIOUS EDCG EMAIL

Peter Nicholas MALKIN pnmalk at students.cs.mu.OZ.AU
Tue Jan 27 16:30:41 AEDT 1998


I designed this notation with an aim to keep it simple and use a
syntax style as close to the current mercury style as possible.

HIDDEN TYPE DECLARATIONS:
If a variable is to be hidden it must be declared as a new type with an
'htype' declaration.

The 'htype' declaration is the same as the standard 'type' declaration,
except that it declares the type to refer to a hidden argument.

Syntax;

:- htype hidden_type    --->    body.

:- htype hidden_type    ==      type.

:- htype hidden_type.

The hidden_type functor can have an arity of zero inferring a monomorphic
type or one or more arguments inferring a polymorphic type.

For example:

:- htype hidden(T) ---> hidden(list(T)).

Non hidden types can be declared using hidden type declarations in the
body of the declaration but will not be considered as hidden. Similarly
hidden types can be declared using other hidden types but are considered
to be hidden.

PREDICATE DECLARATIONS INVOLVING HIDDEN ARGUMENTS:
Hidden arguments are declared the same manner as other types with one
restriction; Hidden types must be declared after (or to the right of)
all non hidden types. This is not necessary but it promotes readability.

Declaring hidden types in a ':- pred' declaration means that the hidden
arguments are passed through the body to the goals of any clause which has
the declared predicate as a head. However no restriction is placed on the
recieving of hidden arguments, any predicate can recieve hidden arguments
even if it has not declared the arguments to be hidden. (See the DCG
equivalent example below).

HIDDEN ARGUMENT MODES:
The modes of the hidden arguments can be expressed either in a ':- pred '
or ':- mode ' declaration. The hidden modes can be written in standard 
fashion. For example;

:- htype hidden == int.
:- pred something(int::in, hidden::out) is det.

OR

:- htype hidden == int.
:- pred something(int, hidden).
:- mode something(in, out) is det.

The hidden mode does not have to be declared in a pred or mode
declaration and can also be expressed in an ':- hmode ' declaration.

Syntax:
:-  hmode hidden_type(mode, mode, ...).

Each one of the modes represents a possible default mode for the hidden
argument. All ':- pred " declarations with modes and ':- mode '
declarations involving a hidden argument without a mode declaration will
be expanded to incorporate each possible mode of the hidden argument.

Hidden arguments have one added mode feature, which is that they can be
declared with a 'ch' (short for changed) mode. A 'ch' mode allows the
recycling of the hidden argument. A hidden argument with a 'ch' mode
really represents two arguments. One argument with an initial
instantiation other than free, and the other with an initial instantiation
of free, and a final instantiation the same as the initial of the first
argument. An argument can be given to 'ch' which specifies the mode of the
first argument and implies the mode of the second. The default mode is
ch(in), or ch(ground -> ground), meaning the first argument has a mode of
'in', and the second 'out', or free -> ground. The second argument will
always begin with an instantiation of free and go to the initial
instantiation of the first argument. This allows the hidden argument to be
assigned to a new value of the same instantiation as it was previously.

For example (a DCG equivalent);

:- htype world_state == io__state.

:- pred main(world_state::ch(di)) is det.
main -->>
        io__write_string("\nHi!  I'm Eliza. \
                                Please tell me your problem.\n"),
        eliza__initial_state(State),
        eliza__main_loop([], State),
        io__write_string("\nGoodbye.\n").

Note that io__write_string does not have the hidden argument word_state
declared but it still recieves the hidden argument.

If in a ':- mode' or an ':- pred' declaration not all of the hidden 
arguments are given modes then an identifier needs to be used to signify
to which hidden argument a particular mode refers. The identifier is just
the hidden_type with the mode as an argument.

For example:
:- htype hidden1 == int.
:- htype hidden2 == int.
:- hmode hidden1(in).

:- pred something(int, hidden1, hidden2).
:- mode something(in, hidden2(out)) is det.

EDCG CLAUSES:
Whenever a hidden argument is passed between goals within a clause the
clause head must be '-->>' which signifies that the order of the goals
within the clause is important.

REFERENCING HIDDEN ARGUMENTS:
Hidden arguments can be referenced in the head or body of a clause of a
predicate. They can appear anywhere within the list of arguments of a
clause in any order, as long as they are listed after all nonhidden
arguments. Since hidden arguments can be listed in any order all of the
hidden arguments must have each have a unique identifier.

The identifier used is the hidden_type name. To unify a term with the
current value of the hidden argument the hidden_type name is written with
the term as an argument.

If the hidden argument has a 'ch' mode then, if the hidden_type name has
one argument then the argument term is unified with the current value of
the hidden argument, if it has two arguments then the first unifies with
the current value of the hidden argument and the second becomes the new
value of the hidden argument.

The functional equivalent which better represents what is going on will
also be allowed.

For example;
:- htype list_acc(T) == list(T).
:- hmode list_acc(ch).
:- pred append(list(T)::in, list_acc(T)) is det.
append([]).
append([X|Xs], list_acc([X|Ys], Ys)).

HIDDEN ARGUMENT SCOPE RULES:
One extra point to address is the scope of hidden argument. To make a
hidden become live it needs to be included in the head of a clause, or
using hidden_type notation to reference the hidden argument.

A hidden variable appearing in the head of a clause has scope only within
that clause. A hidden variable using the hidden_type notation has scope of
its present location until the end of the body of the clause it appears
in or it is ended by the programmer. To end the scope of a hidden variable
prematurely the notation is simply;

hidden_type             % with no arguments

Any scope violations should be picked up as either mode or determinism
errors because a hidden variable has been unduely passed on, or predicate
errors where the wrong number of arguments is given because a hidden
variable has not been passed on.

RESOLVING AMBIGUITIES:
There is a potential for confusion when calling predicates, since
predicates can have the same name and a different number and or types of
arguments and be different predicates. Most of the time it will be clear
which which predicate is appropriate. When it is not, some extra notation
is required. The hidden_type name can be placed in the argument list of
the predicate call to indicate that it is passed on. The curly bracket
notation used for DCGs can be used to indicate no more hidden arguments to
be passed on. These two notations can be combined.

EDCG COMPATABILITY:
I will allow non EDCG sytax to be used instead of or amongst EDCG syntax.
For instance with mode declarations as mentioned before you can list the
hidden argument's mode in a  mode declaration as usual. I will also allow 
predicates to be called in the  usual fashion without using hidden_type
identifiers, as long as all hidden arguments are included in the
argument list.

OTHER SUGGESTIONS:
Instead of using the hidden_type predicate notation (which means that no
functions or predicates can have the same name, arity), a type specifier
could be used ':' which is what it is proposed to be in the future I
believe. Also the DCG syntax of '=(term)' could be used.
For example:

main -->>
	some_predicate(hidden(Term)),
	hidden(Term).

BECOMES

main  -->>
	some_predicate(hidden:Term),
	=hidden:Term.

Also, the 'ch' mode declaration could quite easily be replaced
with two mode declarations, but I thought it nice to condense it to one
mode because the hidden argument of mode 'ch' acts like a single argument.

EXAMPLES:
For examples look at the file ~pnmalk/edcg/examples which has an example
written in the EDCG syntax proposed by mission critical converted to my
syntax.

Peter Malkin




More information about the developers mailing list