[m-dev.] for review: Aditi update documentation round 2
Simon Taylor
stayl at cs.mu.OZ.AU
Fri Jul 2 16:58:47 AEST 1999
--- reference_manual.texi 1999/06/29 02:22:21 1.5
+++ reference_manual.texi 1999/07/02 06:53:39
@@ -5121,31 +5121,53 @@
@subsubsection Aditi update syntax
The Melbourne Mercury compiler provides special syntax to specify updates
-of Aditi base relations. For a predicate @samp{p/3}, the following update
-procedures are defined. Variables named @samp{DB at var{N}} are
- at samp{aditi__state} variables. When occuring as a pair at the end
-of an argument list, they have mode @samp{aditi_di, aditi_uo}.
+of Aditi base relations.
+
+Note: Only error checking is implemented for Aditi updates --- no code is
+generated yet.
+
+ at c XXX texinfo doesn't have subsubsubsection.
+ at ignore
+ at menu
+* Aditi update notes::
+* Insertion::
+* Deletion::
+* Bulk insertion::
+* Bulk deletion::
+* Modification::
+ at end menu
+ at end ignore
+
+ at c @node Aditi update notes::
+ at subsubheading Aditi update notes
+
+There must be a @w{@samp{:- pragma base_relation}} declaration for
+any relation to be updated.
It is currently up to the application to ensure that any modifications
do not change the determinism of a base relation. Updates of relations
-with unique B-tree indexes are checked to ensure that a key is not given
-multiple values. The transaction will abort if this occurs.
-
-Note: The implementation of Aditi updates is not yet complete.
+with unique B-tree indexes are checked to ensure that a key is not
+given multiple values. The transaction will abort if this occurs.
The examples make use of the following declarations.
@example
:- pred p(aditi__state::aditi_ui, int::out, int::out) is nondet.
:- pragma base_relation(p/3).
-:- func q(aditi__state::aditi_ui, int::out) = (int::out) is nondet.
-:- pragma base_relation(q/2).
+:- func f(aditi__state::aditi_ui, int::out) = (int::out) is nondet.
+:- pragma base_relation(f/2).
:- pred ancestor(aditi__state::aditi_ui, int::out, int::out) is nondet.
:- pragma aditi(ancestor/3).
@end example
- at c XXX texinfo doesn't have subsubsubsection.
+Variables named @samp{DB at var{N}} are
+ at samp{aditi__state} variables. When occuring as a pair at the end
+of an argument list, they have mode @w{@samp{aditi_di, aditi_uo}}.
+
+Predicate and function names in Aditi update goals may be module qualified.
+
+ at c @node Insertion
@subsubheading Insertion
@example
@@ -5158,8 +5180,6 @@
must have the same type signature as the relation. All the arguments
of the tuple have mode @samp{in}, except the @samp{aditi__state} argument
which has mode @samp{unused}.
-There must be a @w{@samp{:- pragma base_relation}} declaration for
- at w{@samp{@var{Name}/@var{Arity}}}.
Note that @w{@samp{@var{PredName}(@var{Var1}, @var{Var2}, @dots{})}}
in a call to @samp{aditi_insert} is not a higher-order term.
@@ -5168,17 +5188,20 @@
Examples:
@example
+insert_example_1(DB0, DB) :-
aditi_insert(p(_, 1, 2), DB0, DB).
- aditi_insert(q(_, 1) = 2, DB0, DB).
+insert_example_2(DB0, DB) :-
+ aditi_insert(f(_, 1) = 2, DB0, DB).
@end example
+ at c @node Deletion
@subsubheading Deletion
@example
-aditi_delete(@var{PredName}(@var{Var1}, @var{Var2}, @dots{}) :- @var{Goal}, @var{DB0}, @var{DB}).
+aditi_delete((@var{PredName}(@var{Var1}, @var{Var2}, @dots{}) :- @var{Goal}), @var{DB0}, @var{DB}).
-aditi_delete(@var{FuncName}(@var{Var1}, @var{Var2}, @dots{}) = @var{RetVar} :- @var{Goal}, @var{DB0}, @var{DB}).
+aditi_delete((@var{FuncName}(@var{Var1}, @var{Var2}, @dots{}) = @var{RetVar} :- @var{Goal}), @var{DB0}, @var{DB}).
aditi_delete(@var{PredOrFunc} @var{Name}/@var{Arity}, @var{Closure}, @var{DB0}, @var{DB}).
@end example
@@ -5186,19 +5209,16 @@
Delete all tuples for which @samp{@var{Goal}} or @samp{@var{Closure}}
succeeds from the named base relation.
-There must be a @w{@samp{:- pragma base_relation}} declaration for
- at w{@samp{@var{PredOrFunc} @var{Name}/@var{Arity}}}.
-
For the third alternative @samp{@var{PredOrFunc}} must be either
@samp{pred} or @samp{func}.
-When updating a predicate with type declaration
+When deleting from a predicate with type declaration
@w{@samp{:- pred p(aditi__state, @var{Type1}, @dots{})}},
@samp{@var{Closure}} must have type
@w{@samp{aditi_top_down pred(aditi__state, @var{Type1}, @dots{})}},
and inst @w{@samp{pred(unused, in, @dots{}) is semidet}}.
-When updating a function with type declaration
+When deleting from a function with type declaration
@w{@samp{:- func p(aditi__state, @var{Type1}, @dots{}) = @var{Type2}}},
@samp{@var{Closure}} must have type
@w{@samp{aditi_top_down func(aditi__state, @var{Type1}, @dots{}) = @var{Type2}}},
@@ -5209,7 +5229,7 @@
Aditi database using the normal Mercury execution algorithm.
The @samp{aditi__state} argument of @samp{@var{Closure}} must have
-mode @samp{unused} -- it is not possible to call an Aditi
+mode @samp{unused} --- it is not possible to call an Aditi
relation from the deletion condition. All other arguments of
@samp{@var{Closure}} must have mode @samp{in}.
@@ -5219,28 +5239,44 @@
Examples:
@example
+delete_example_1(DB0, DB) :-
aditi_delete((p(_, X, Y) :- X + Y = 2), DB0, DB).
- aditi_delete(q(_, 2) = Y, DB0, DB).
+delete_example_2(DB0, DB) :-
+ aditi_delete(f(_, 2) = _Y, DB0, DB).
+delete_example_3(DB0, DB) :-
DeleteP = (aditi_top_down
pred(_::unused, X::in, Y::in) is semidet :-
X = 2
),
aditi_delete(pred p/3, DeleteP, DB0, DB).
+delete_example_4(DB0, DB) :-
DeleteQ = (aditi_top_down
func(_::unused, X::in) = (Y::in) is semidet :-
X = 2
),
- aditi_delete(func q/2, DeleteQ, DB0, DB).
+ aditi_delete(func f/2, DeleteQ, DB0, DB).
+
+delete_example_5 -->
+ aditi_delete((p(_, X, Y) :- X = 2, Y = 2)).
+
@end example
-The type of @samp{Pred} is
+The type of @samp{DeleteP} is
@w{@samp{aditi_top_down pred(aditi__state, int, int)}}.
Its inst is @w{@samp{pred(unused, in, in) is nondet}}, as for a normal
lambda expression.
+Note that in @samp{delete_example_5} the extra set of parentheses around
+the goal are needed, otherwise the second goal in the conjunction
+in the deletion goal is parsed as an argument of the `aditi_delete' call.
+This behaviour is inconsistent with ISO Prolog syntax. An ISO Prolog
+implementation would report a syntax error without the extra set of
+parentheses.
+
+ at c @node Bulk insertion
@subsubheading Bulk insertion
@example
@@ -5249,10 +5285,8 @@
Insert all solutions of @samp{@var{Closure}} into the named relation.
@samp{@var{PredOrFunc}} must be either @samp{pred} or @samp{func}.
-There must be a @w{@samp{:- pragma base_relation}} declaration for
- at w{@samp{@var{Name}/@var{Arity}}}.
-The closure to produce the tuples to insert must have the same
+The closure for producing the tuples to insert must have the same
type signature as the base relation, with all arguments except
the @samp{aditi__state} output. It must also be evaluable bottom-up
by the Aditi system. This means the predicate passed must have a
@@ -5262,14 +5296,17 @@
Examples:
@example
+bulk_insert_example_1(DB0, DB) :-
aditi_bulk_insert(pred p/3, ancestor, DB0, DB).
+bulk_insert_example_2(DB0, DB) :-
InsertP = (aditi_bottom_up
pred(DB1::aditi_ui, X::out, Y::out) is nondet :-
ancestor(DB1, X, Y)
),
aditi_bulk_insert(pred p/3, InsertP, DB0, DB).
+bulk_insert_example_3(DB0, DB) :-
InsertQ = (aditi_bottom_up
func(DB1::aditi_ui, X::out) = (Y::out) is nondet :-
ancestor(DB1, X, Y)
@@ -5277,11 +5314,12 @@
aditi_bulk_insert(pred p/3, InsertQ, DB0, DB).
@end example
-The type of @samp{Pred} is
+The type of @samp{InsertP} is
@w{@samp{aditi_bottom_up pred(aditi__state, int, int)}}.
Its inst is @w{@samp{pred(aditi_ui, out, out) is nondet}},
as for a normal lambda expression.
+ at c @node Bulk deletion
@subsubheading Bulk deletion
@example
@@ -5290,25 +5328,24 @@
Delete all solutions of @samp{@var{Closure}} from the named relation.
@samp{@var{PredOrFunc}} must be either @samp{pred} or @samp{func}.
-There must be a @w{@samp{:- pragma base_relation}} declaration for
- at w{@samp{@var{Name}/@var{Arity}}}.
-The restrictions on the closure term passed to @samp{aditi_bulk_insert} also
+The restrictions on the closure passed to @samp{aditi_bulk_insert} also
apply to @samp{aditi_bulk_delete}.
+ at c @node Modification
@subsubheading Modification
@example
aditi_modify(
(@var{PredName}(@var{Var1}, @var{Var2}, @dots{}) ==> @var{Predname}(@var{Var3}, @var{Var4}, @dots{}) :-
- @var{Goal},
+ @var{Goal}
),
@var{DB0}, @var{DB}).
aditi_modify(
((@var{FuncName}(@var{Var1}, @var{Var2}, @dots{}) = @var{RetVar0}) ==>
- ((@var{Predname}(@var{Var3}, @var{Var4}, @dots{}) = @var{RetVar})) :-
- @var{Goal},
+ (@var{Predname}(@var{Var3}, @var{Var4}, @dots{}) = @var{RetVar}) :-
+ @var{Goal}
),
@var{DB0}, @var{DB}).
@@ -5316,23 +5353,21 @@
@end example
-Modify tuples for which @samp{@var{Goal}} or @samp{@var{Closure}}.
+Modify tuples for which @samp{@var{Goal}} or @samp{@var{Closure}} succeeds.
Tuples for which the modification goal fails are left unchanged.
-There must be a @w{@samp{:- pragma base_relation}} declaration for
- at w{@samp{@var{PredOrFunc} @var{Name}/@var{Arity}}}.
The original tuple is given by the first set of arguments, the
updated tuple is given by the second set.
For the third alternative @samp{@var{PredOrFunc}} must be either @samp{pred}
or @samp{func}.
-When updating a predicate with type declaration
+When modifying a predicate with type declaration
@w{@samp{:- pred p(aditi__state, @var{Type1}, @dots{})}}, @samp{@var{Closure}}
must have type
@samp{aditi_top_down pred(aditi__state, @var{Type1}, @dots{}, aditi__state, @var{Type1}, @dots{})},
and inst @w{@samp{pred(unused, in, @dots{}, unused, out, @dots{}) is semidet}}.
-When updating a function with type declaration
+When modifying a function with type declaration
@w{@samp{:- func p(aditi__state, @var{Type1}, @dots{}) = @var{Type2}}},
@samp{@var{Closure}} must have type
@samp{aditi_top_down pred(aditi__state, @var{Type1}, @dots{}, @var{Type2}, aditi__state, @var{Type1}, @dots{}, @var{Type2})},
@@ -5340,7 +5375,7 @@
@w{@samp{pred(unused, in, @dots{}, in, unused, out, @dots{}, out) is semidet}}.
The @samp{aditi__state} arguments of @samp{@var{Closure}} must have
-mode @samp{unused} -- it is not possible to call an Aditi
+mode @samp{unused} --- it is not possible to call an Aditi
relation from the modification goal.
If the construction of the lambda expression is in the same conjunction
@@ -5349,28 +5384,45 @@
Examples:
@example
+modify_example_1(DB0, DB) :-
aditi_modify(
(p(_DB0, X, Y0) ==> p(_DB, X, Y) :-
X > 2, X < 5, Y = Y0 + 1
), DB0, DB).
+modify_example_2(DB0, DB) :-
aditi_modify(
- ((q(_DB0, X) = Y0) ==> (q(_DB, X) = Y) :-
+ ((f(_DB0, X) = Y0) ==> (f(_DB, X) = Y) :-
X > 2, X < 5, Y = Y0 + 1
), DB0, DB).
+modify_example_3(DB0, DB) :-
ModifyP = (aditi_top_down pred(_::unused, X::in, Y0::in,
_::unused, X::out, Y::out) is semidet :-
X > 2, X < 5, Y = Y0 + 1
),
aditi_modify(pred p/3, ModifyP, DB0, DB).
+modify_example_4(DB0, DB) :-
ModifyQ = (aditi_top_down pred(_::unused, X::in, Y0::in,
_::unused, X::out, Y::out) is semidet :-
X > 2, X < 5, Y = Y0 + 1
),
- aditi_modify(func q/2, ModifyQ, DB0, DB).
+ aditi_modify(func f/2, ModifyQ, DB0, DB).
+
+modify_example_5 -->
+ aditi_modify(
+ (p(_DB0, X, Y0) ==> p(_DB, X, Y) :-
+ X > 2, X < 5, Y = Y0 + 1
+ )).
@end example
+
+Note that in @samp{modify_example_5} the extra set of parentheses around
+the goal are needed, otherwise the second and third goals in
+the conjunction in the modification goal are parsed as arguments
+of the `aditi_modify' call. This behaviour is inconsistent with
+ISO Prolog syntax. An ISO Prolog implementation would report a
+syntax error without the extra set of parentheses.
@node Aditi glossary
@subsubsection Aditi glossary
--------------------------------------------------------------------------
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