[m-dev.] for review: EDCG syntax

Peter Nicholas MALKIN pnmalk at students.cs.mu.OZ.AU
Mon Jan 26 20:26:32 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. Each hidden variable must have an 'htype'
declaration.

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

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.

HIDDEN ARGUMENT MODES:
The modes of the hidden arguments are expressed in the usual fashion.
Either in a ':- pred ' or ':- mode ' declaration. They 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 with
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").


EDCG CLAUSES:
Whenever an argument is passed 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.

For example;
:- htype hidden.
:- hmode hidden(ch).

:- pred predicate(int::out, int::in, hidden) is det.
predicate(Old, New) -->>
        hidden(Old, New).

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.

Peter Malkin




More information about the developers mailing list