[m-dev.] for review: Aditi updates [3]

Simon Taylor stayl at cs.mu.OZ.AU
Wed Apr 12 18:26:06 AEST 2000


Index: extras/aditi/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/aditi/Mmakefile,v
retrieving revision 1.2
diff -u -u -r1.2 Mmakefile
--- extras/aditi/Mmakefile	1999/09/16 04:46:22	1.2
+++ extras/aditi/Mmakefile	2000/04/12 02:53:37
@@ -1,36 +1,63 @@
 #-----------------------------------------------------------------------------#
-# Copyright (C) 1998-1999 The University of Melbourne.
+# Copyright (C) 1998-2000 The University of Melbourne.
 # This file may only be copied under the terms of the GNU Library General
 # Public License - see the file COPYING.LIB in the Mercury distribution.
 #-----------------------------------------------------------------------------#
-
-MAIN_TARGET = all
-
-MCFLAGS = --no-infer-all
+# Mmakefile for the Mercury->Aditi interface.
+# 
+# Environment variables (must be set externally):
+# MADITI_INSTALL_PREFIX - directory where the interface should be installed.
+# MAKEFILE_ADITI - makefile containing variables used when compiling
+# 		a program for Aditi.
+#				
+#-----------------------------------------------------------------------------#
+#
+# Defines ADITI_API_EXTRA_CFLAGS, ADITI_API_EXTRA_LIBS and
+# ADITI_API_EXTRA_LDFLAGS
+include $(MAKEFILE_ADITI)
+
+INSTALL_PREFIX = $(MADITI_INSTALL_PREFIX)
+
+# The Aditi interface only works with conservative garbage collection.
+# This is equivalent to
+# LIBGRADES-aditi = $(filter %.gc%,$(LIBGRADES))
+# but gmake patterns can't include multiple wildcards.
+LIBGRADES-aditi = $(shell echo $(LIBGRADES) | tr ' ' '\n' | grep '.gc')
 
-ADITI_API_DIR = /aditi4/stayl/aditi2/src/api
+#----------------------------------------------------------------------------#
 
 # The --Wno-strict-prototypes is to shut up warnings about prototypes
 # without argument types in a header file generated by rpcgen.
-MGNUCFLAGS=-I$(ADITI_API_DIR) -Wno-strict-prototypes
+CFLAGS = $(ADITI_API_EXTRA_CFLAGS) -Wno-strict-prototypes
 
-# Link in the Aditi API library.
-MLFLAGS += -R$(ADITI_API_DIR) -L$(ADITI_API_DIR) $(EXTRA_MLFLAGS) -lapi
-C2INITFLAGS = --aditi aditi.init
+MLFLAGS = --use-thread-libs $(ADITI_API_EXTRA_LDFLAGS) $(EXTRA_MLFLAGS)
+MLLIBS = $(ADITI_API_EXTRA_LIBS)
 
-#-----------------------------------------------------------------------------#
+MCFLAGS = --no-infer-all --aditi
 
-DEPENDS =	aditi.depend
+C2INITFLAGS = --aditi
 
-#-----------------------------------------------------------------------------#
+#-----------------------------------------------------------------------------%
+
+MAIN_TARGET = libaditi
 
 .PHONY: depend
-depend: $(DEPENDS)
+depend: aditi.depend
+	cd tests && mmake $(MMAKEFLAGS) depend
 
-.PHONY: all
-all: aditi.o
+.PHONY: clean
+clean:
+	cd tests && mmake $(MMAKEFLAGS) clean
+
+.PHONY: realclean
+realclean:
+	cd tests && mmake $(MMAKEFLAGS) realclean
+
+.PHONY: tests
+tests:
+	cd tests && mmake $(MMAKEFLAGS)
 
-clean_local:
-	rm -f *.out *.res
+.PHONY: install
+install: libaditi.install
 
 #-----------------------------------------------------------------------------#
Index: extras/aditi/aditi.m
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/aditi/aditi.m,v
retrieving revision 1.5
diff -u -u -r1.5 aditi.m
--- extras/aditi/aditi.m	2000/02/08 02:07:58	1.5
+++ extras/aditi/aditi.m	2000/04/12 07:58:54
@@ -14,6 +14,25 @@
 % (XXX this section in the manual is commented out, since Aditi is not yet
 % publicly available.)
 %
+%
+% Compilation grade notes (see the section "Compilation model options"
+% in the Mercury User's Guide for more information):
+%
+%	This module requires a compilation grade with conservative garbage 
+%	collection. Any grade containing `.gc' in its name, such as
+%	`asm_fast.gc' or `asm_fast.gc.tr', will do.
+%
+% 	When trailing is not being used (the compilation grade does not
+% 	contain `.tr'), resources will sometimes not be cleaned up until
+%	the end of a transaction.
+%	If there is a commit across a nondet database call, or an exception
+%	is thrown, or a database call is retried in the debugger, the output
+%	relation from the call and its cursor will not be cleaned up until the
+%	transaction ends.
+%	It is up to the programmer to decide whether imposing the overhead
+%	of trailing on the rest of the program is worthwhile.
+%
+%
 % The transaction interface used here is described in
 %	Kemp, Conway, Harris, Henderson, Ramamohanarao and Somogyi,
 % 	"Database transactions in a purely declarative 
@@ -84,16 +103,35 @@
 		io__state, io__state).
 :- mode aditi__disconnect(in, out, di, uo) is det.
 
+:- type aditi__transaction(T) == pred(T, aditi__state, aditi__state).
+:- inst aditi__transaction = (pred(out, aditi_di, aditi_uo) is det).
+
+	% aditi__transaction(Connection, Transaction, Result).
+	%
+	% Start a transaction with the Aditi database referred to by
+	% Connection, call Transaction, returning ok(Result) if the
+	% transaction is not aborted, or error(Error, Msg) if
+	% the transaction fails.
+	%
+	% If Transaction throws an exception, the transaction will
+	% be aborted and the exception will be rethrown to the caller.
+	%
+	% Predicates with `:- pragma aditi' or `:- pragma base_relation'
+	% markers can only be called from within a transaction -- there
+	% is no other way to get an `aditi__state' to pass to them.
+:- pred aditi__transaction(aditi__connection, aditi__transaction(T),
+		aditi__result(T), io__state, io__state).
+:- mode aditi__transaction(in, in(aditi__transaction), out, di, uo) is det.
+
 	% aditi__aggregate_compute_initial(Closure, UpdateAcc, 
 	% 		ComputeInitial, Results)
 	%
 	% When called, the query Closure returns the relation to be 
 	% aggregated over. This relation must have two attributes,
-	% the first being the attribute to group by. The relation is
-	% sorted and duplicates are removed before the aggregate is applied.
-	% The closure ComputeInitial computes an initial accumulator
-	% for each group given the first tuple in the group.
-	% The closure UpdateAcc is called for each tuple in each group to 
+	% the first being the attribute to group by. The closure 
+	% ComputeInitial computes an initial accumulator for each 
+	% group given the first tuple in the group. The closure
+	% UpdateAcc is called for each tuple in each group to 
 	% update the accumulator. The outputs are the group-by element
 	% and final accumulator for each group.
 	%
@@ -136,18 +174,11 @@
 		in, out, out) is nondet.
 */
 
-:- type aditi__transaction(T) == pred(T, aditi__state, aditi__state).
-:- inst aditi__transaction = (pred(out, aditi_di, aditi_uo) is det).
-
-:- pred aditi__transaction(aditi__connection, aditi__transaction(T),
-		aditi__result(T), io__state, io__state).
-:- mode aditi__transaction(in, in(aditi__transaction), out, di, uo) is det.
-
 %---------------------------------------------------------------------------%
 
 :- implementation.
 
-:- import_module bool, char, list, require, std_util, string, std_util.
+:- import_module bool, char, exception, list, require, std_util, string.
 
 :- type aditi__connection == int.
 :- type aditi__state == unit.
@@ -159,10 +190,32 @@
 :- pragma c_header_code("
 
 #include ""mercury_wrapper.h""
+#include ""mercury_ho_call.h""
+
+/* aditi_api_config.h must be included before aditi_clnt.h */
+#include ""aditi_api_config.h""
 #include ""aditi_clnt.h""
 
+#define MADITI_check(status) MADITI_do_check(status, __LINE__);
 #define MADITI_throw MR_longjmp(&MADITI_jmp_buf);
 
+typedef enum { MADITI_INSERT_TUPLE, MADITI_DELETE_TUPLE } MADITI_insert_delete;
+typedef enum { MADITI_INSERT, MADITI_DELETE, MADITI_MODIFY } MADITI_bulk_op;
+
+#ifdef MR_USE_TRAIL
+
+/*
+** Information used to clean up a call result if there is a commit
+** or an exception across a database call.
+*/
+typedef struct {
+	ticket *output_rel;
+	ticket *output_cursor;
+	bool cleaned_up;
+} MADITI_trail_cleanup_data;
+
+#endif /* MR_USE_TRAIL */
+
 static ticket MADITI_ticket;		/* Current connection ticket. */
 static MR_jmp_buf MADITI_jmp_buf;	/* jmp_buf to longjmp() to when
 					** aborting the transaction.
@@ -171,10 +224,26 @@
 					** Aditi API call.
 					*/
 
-static void MADITI_do_call(void);
-static void MADITI_check(int);
+static void MADITI_do_nondet_call(void);
+static ticket * MADITI_run_procedure(String proc_name,
+		String input_schema, String input_tuple);
+static void MADITI_do_insert_delete_tuple(MADITI_insert_delete);
+static void MADITI_do_bulk_operation(MADITI_bulk_op operation);
+static void MADITI_do_bulk_insert_or_delete(MADITI_bulk_op operation,
+		String rel_name, ticket *call_result_ticket);
 static bool MADITI_get_output_tuple(int);
-static void MADITI_cleanup(void);
+static void MADITI_post_call_cleanup(void);
+static void MADITI_cleanup_call_output(ticket *output_rel, ticket *cursor);
+
+#ifdef MR_USE_TRAIL
+static void MADITI_trail_cleanup_call_output(void *cleanup_data,
+		MR_untrail_reason reason);
+#endif
+
+static String MADITI_construct_tuple(int num_input_args,
+		Word *input_typeinfos, Word *input_args);
+static void MADITI_do_check(int, int);
+static void MADITI_list_rel(ticket* rel);
 ").
 
 %-----------------------------------------------------------------------------%
@@ -208,11 +277,7 @@
 		*/
 		if ((Stat = ADITI_NAME(login)(User, Passwd)) == ADITI_OK) {
 
-			DEBUG(struct param_value pvalue);
-			DEBUG(pvalue.type = int_type);
-			DEBUG(pvalue.param_value_u.int_val = 1);
-			DEBUG(ADITI_NAME(setparam)(""debug"", &pvalue));
-			DEBUG(ADITI_NAME(disable_ping)());
+			DEBUG(ADITI_NAME(set_debug)());
 
 			DEBUG(printf(""logged in\\n""));
 			if ((Stat = MR_load_aditi_rl_code())
@@ -259,23 +324,29 @@
 
 aditi__transaction(_Connection, Transaction, TransResult, IO0, IO) :-
 	aditi__do_transaction(Transaction, Results,
-		Status, IO0, IO),
-	( Status = 0 ->
-		TransResult = ok(Results)
+		Status, GotException, Exception, IO0, IO),
+	( GotException = 0 ->
+		( Status = 0 ->
+			TransResult = ok(Results)
+		;
+			aditi__error_code(Status, Error, String),
+			TransResult = error(Error, String) 
+		)
 	;
-		aditi__error_code(Status, Error, String),
-		TransResult = error(Error, String) 
+		rethrow(exception(Exception))
 	).
 
 %-----------------------------------------------------------------------------%
 
 :- pred aditi__do_transaction(aditi__transaction(T),
-		T, int, io__state, io__state).
-:- mode aditi__do_transaction(in(aditi__transaction), out, out, di, uo) is det.
-:- pragma no_inline(aditi__do_transaction/5).	% contains labels
+		T, int, int, univ, io__state, io__state).
+:- mode aditi__do_transaction(in(aditi__transaction),
+		out, out, out, out, di, uo) is det.
+:- pragma no_inline(aditi__do_transaction/7).	% contains labels
 
 :- pragma c_code(aditi__do_transaction(Transaction::in(aditi__transaction), 
-		Results::out, Stat::out, IO0::di, IO::uo),
+		Results::out, Stat::out, GotException::out, Exception::out,
+		IO0::di, IO::uo),
 		may_call_mercury,
 "
 {
@@ -293,11 +364,18 @@
 	MR_setjmp(&MADITI_jmp_buf, transaction_error);
 
 	MADITI__call_transaction(TypeInfo_for_T,
-		Transaction, &Results, 0, &DB);
+		Transaction, &Results, &GotException,
+		&Exception, (Word)0, &DB);
 
-	DEBUG(printf(""committing transaction...""));
-	Stat = ADITI_NAME(trans_commit)(&MADITI_ticket);
-	DEBUG(printf(""done\\n""));
+	if (GotException == 0) {
+		DEBUG(printf(""committing transaction...""));
+		Stat = ADITI_NAME(trans_commit)(&MADITI_ticket);
+		DEBUG(printf(""done\\n""));
+	} else {
+		DEBUG(printf(""got exception - aborting transaction...""));
+		Stat = ADITI_NAME(trans_abort)(&MADITI_ticket);
+		DEBUG(printf(""done\\n""));
+	}
 	
 	goto transaction_done;
 
@@ -306,38 +384,60 @@
 	DEBUG(printf(""aborting transaction...""));
 	ADITI_NAME(trans_abort)(&MADITI_ticket);
 	DEBUG(printf(""done\\n""));
+	GotException = 0;
 	Stat = MADITI_status;
 
 transaction_done:
 }
 ").
 
-:- pred aditi__call_transaction(aditi__transaction(T), T,
+:- pred aditi__call_transaction(aditi__transaction(T), T, int, univ,
 		aditi__state, aditi__state).
-:- mode aditi__call_transaction(in(aditi__transaction), out,
-		aditi_di, aditi_uo) is det.
+:- mode aditi__call_transaction(in(aditi__transaction), out, out, out,
+		aditi_di, aditi_uo) is cc_multi.
 :- pragma export(
 		aditi__call_transaction(in(aditi__transaction), out,
-			aditi_di, aditi_uo),
+			out, out, aditi_di, aditi_uo),
 		"MADITI__call_transaction"
 	).
 
-aditi__call_transaction(Trans, Results) -->
-	call(Trans, Results).
+aditi__call_transaction(Trans, Results, GotException, Exception,
+		State0, State) :-
+	TryTransaction = 
+		(pred(Result - AditiState::out) is det :-
+			Trans(Result, State0, AditiState)
+		),
+	try(TryTransaction, ExceptionResult),
+	(
+		ExceptionResult = succeeded(Results - State),
+		GotException = 0,
+		make_dummy_value(Exception)
+	;
+		ExceptionResult = exception(Exception),
+		State = State0,
+		GotException = 1,
+		make_dummy_value(Results)
+	).	
+
+	% Pretend to bind a variable. The result must never be looked at.
+:- pred make_dummy_value(T::out) is det.
+:- pragma c_code(make_dummy_value(T::out),
+		[will_not_call_mercury, thread_safe],
+		"T = 0;").
 
 %-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
 
 :- pragma c_code("
 
 	/*
-	** We might allocate memory from may_call_mercury C code. XXX?
+	** We might allocate memory from may_call_mercury C code.
 	*/
 #ifndef CONSERVATIVE_GC
 #error The Aditi interface requires conservative garbage collection. \\
                 Use a compilation grade containing .gc.
 #endif /* ! CONSERVATIVE_GC */
 
+
 ").
 
 	% Hand coded C to call an Aditi procedure. This is needed
@@ -378,8 +478,8 @@
 #define MADITI_input_schema			r3
 #define MADITI_num_output_args			r4
 
-	/* Register containing the first input argument */
-#define MADITI_FIRST_INPUT 5
+	/* Register containing the typeinfo for the first input argument */
+#define MADITI_CALL_FIRST_INPUT 5
 
 /*
 ** Output arguments from do_call_aditi are the same as for
@@ -410,17 +510,37 @@
 Declare_label(do_nondet_aditi_call_i1);
 Define_extern_entry(do_semidet_aditi_call);
 Define_extern_entry(do_det_aditi_call);
+Define_extern_entry(do_aditi_insert);
+Define_extern_entry(do_aditi_delete);
+Define_extern_entry(do_aditi_bulk_insert);
+Define_extern_entry(do_aditi_bulk_delete);
+Define_extern_entry(do_aditi_bulk_modify);
 
 MR_MAKE_PROC_LAYOUT(do_nondet_aditi_call, MR_DETISM_NON,
-	MR_ENTRY_NO_SLOT_COUNT, MR_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
-	""private_builtin"", ""do_nondet_aditi_call"", 0, 0);
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_nondet_aditi_call"", 0, 0);
 MR_MAKE_INTERNAL_LAYOUT(do_nondet_aditi_call, 1);
 MR_MAKE_PROC_LAYOUT(do_semidet_aditi_call, MR_DETISM_NON,
-	MR_ENTRY_NO_SLOT_COUNT, MR_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
-	""private_builtin"", ""do_semidet_aditi_call"", 0, 0);
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_semidet_aditi_call"", 0, 0);
 MR_MAKE_PROC_LAYOUT(do_det_aditi_call, MR_DETISM_NON,
-	MR_ENTRY_NO_SLOT_COUNT, MR_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
-	""private_builtin"", ""do_semidet_aditi_call"", 0, 0);
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_det_aditi_call"", 0, 0);
+MR_MAKE_PROC_LAYOUT(do_aditi_insert, MR_DETISM_DET,
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_aditi_insert"", 0, 0);
+MR_MAKE_PROC_LAYOUT(do_aditi_delete, MR_DETISM_DET,
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_aditi_delete"", 0, 0);
+MR_MAKE_PROC_LAYOUT(do_aditi_bulk_insert, MR_DETISM_DET,
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_aditi_bulk_insert"", 0, 0);
+MR_MAKE_PROC_LAYOUT(do_aditi_bulk_delete, MR_DETISM_DET,
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_aditi_bulk_delete"", 0, 0);
+MR_MAKE_PROC_LAYOUT(do_aditi_bulk_modify, MR_DETISM_DET,
+	MR_ENTRY_NO_SLOT_COUNT, MR_LONG_LVAL_TYPE_UNKNOWN, MR_PREDICATE,
+	""aditi"", ""do_aditi_bulk_modify"", 0, 0);
 
 BEGIN_MODULE(do_aditi_call_module)
 	init_entry_sl(do_nondet_aditi_call);
@@ -430,16 +550,26 @@
 	MR_INIT_PROC_LAYOUT_ADDR(do_semidet_aditi_call);
 	init_entry_sl(do_det_aditi_call);
 	MR_INIT_PROC_LAYOUT_ADDR(do_det_aditi_call);
+	init_entry_sl(do_aditi_insert);
+	MR_INIT_PROC_LAYOUT_ADDR(do_aditi_insert);
+	init_entry_sl(do_aditi_delete);
+	MR_INIT_PROC_LAYOUT_ADDR(do_aditi_delete);
+	init_entry_sl(do_aditi_bulk_insert);
+	MR_INIT_PROC_LAYOUT_ADDR(do_aditi_bulk_insert);
+	init_entry_sl(do_aditi_bulk_delete);
+	MR_INIT_PROC_LAYOUT_ADDR(do_aditi_bulk_delete);
+	init_entry_sl(do_aditi_bulk_modify);
+	MR_INIT_PROC_LAYOUT_ADDR(do_aditi_bulk_modify);
 BEGIN_CODE
 
 Define_entry(do_nondet_aditi_call);
 {
-	mkframe(""do_nondet_aditi_call"",
+	MR_mkframe(""do_nondet_aditi_call"",
 		(MADITI_NUM_FRAME_VARS + MADITI_num_output_args),
 		LABEL(do_nondet_aditi_call_i1));
 
 	save_transient_registers();
-	MADITI_do_call();
+	MADITI_do_nondet_call();
 	restore_transient_registers();
 	GOTO(LABEL(do_nondet_aditi_call_i1));
 }
@@ -450,22 +580,22 @@
 	/* Unpack the output tuple into r1 and upwards. */
 	if (MADITI_get_output_tuple(1)) {
 		restore_transient_registers();
-		succeed();
+		MR_succeed();
 	} else {
-		MADITI_cleanup();
+		MADITI_post_call_cleanup();
 		restore_transient_registers();
-		fail();
+		MR_fail();
 	}
 }
 
 Define_entry(do_semidet_aditi_call);
 {
-	mkframe(""do_semidet_aditi_call"",
+	MR_mkframe(""do_semidet_aditi_call"",
 		(MADITI_NUM_FRAME_VARS + MADITI_num_output_args),
 		ENTRY(do_not_reached));
 
 	save_transient_registers();
-	MADITI_do_call();
+	MADITI_do_nondet_call();
 
 	/* Unpack the output tuple into r2 and upwards for semidet code. */
 	if (MADITI_get_output_tuple(2)) {
@@ -475,25 +605,25 @@
 		** We assume that any other solutions are duplicates
 		** of the one we just collected.
 		*/
-		MADITI_cleanup();
+		MADITI_post_call_cleanup();
 		restore_transient_registers();
 		r1 = 1;
 	} else {
-		MADITI_cleanup();
+		MADITI_post_call_cleanup();
 		restore_transient_registers();
 		r1 = 0;
 	}
-	succeed_discard();
+	MR_succeed_discard();
 }
 
 Define_entry(do_det_aditi_call);
 {
-	mkframe(""do_det_aditi_call"",
+	MR_mkframe(""do_det_aditi_call"",
 		(MADITI_NUM_FRAME_VARS + MADITI_num_output_args),
 		ENTRY(do_not_reached));
 
 	save_transient_registers();
-	MADITI_do_call();
+	MADITI_do_nondet_call();
 
 	/* Unpack the output tuple into r1 and upwards. */
 	if (!MADITI_get_output_tuple(1)) {
@@ -507,11 +637,76 @@
 	** of the one we just collected.
 	*/
 
-	MADITI_cleanup();
+	MADITI_post_call_cleanup();
 	restore_transient_registers();
 
-	succeed_discard();
+	MR_succeed_discard();
+}
+
+/*---------------------------------------------------------------------------*/
+/*
+** Insert or delete a single tuple into/from a relation.
+**
+** Input arguments:
+** r1 -> name of relation
+** r2 -> arity of relation
+** r3 -> name of the deletion procedure for the relation (aditi_delete only)
+** r4 -> schema of the relation (aditi_delete only)
+** r5 -> type_infos for arguments of tuple to insert
+**    -> arguments of tuple to insert
+**
+** There are no output arguments.
+*/
+Define_entry(do_aditi_insert);
+{
+	save_transient_registers();
+	DEBUG(printf(""do_aditi_insert\\n""));
+	MADITI_do_insert_delete_tuple(MADITI_INSERT_TUPLE);
+	restore_transient_registers();
+	proceed();	
+}
+Define_entry(do_aditi_delete);
+{
+	save_transient_registers();
+	DEBUG(printf(""do_aditi_delete\\n""));
+	MADITI_do_insert_delete_tuple(MADITI_DELETE_TUPLE);
+	restore_transient_registers();
+	proceed();	
+}
+
+
+/*
+** Insert/delete the tuples returned by the query argument
+** 
+** Input arguments:
+** r1 -> name of relation
+** r2 -> name of deletion or modification procedure
+** r3 -> closure
+*/
+Define_entry(do_aditi_bulk_insert);
+{
+	save_transient_registers();
+	DEBUG(printf(""do_aditi_bulk_insert\\n""));
+	MADITI_do_bulk_operation(MADITI_INSERT);
+	restore_transient_registers();
+	proceed();	
+}
+Define_entry(do_aditi_bulk_delete);
+{
+	save_transient_registers();
+	DEBUG(printf(""do_aditi_bulk_delete\\n""));
+	MADITI_do_bulk_operation(MADITI_DELETE);
+	restore_transient_registers();
+	proceed();	
 }
+Define_entry(do_aditi_bulk_modify);
+{
+	save_transient_registers();
+	DEBUG(printf(""do_aditi_bulk_modify\\n""));
+	MADITI_do_bulk_operation(MADITI_MODIFY);
+	restore_transient_registers();
+	proceed();	
+}
 
 END_MODULE
 void mercury_sys_init_aditi_call(void); /* suppress gcc warning */
@@ -520,6 +715,7 @@
 }
 
 /*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
 
 /*
 ** The functions below fiddle with the Mercury registers, so be sure
@@ -528,127 +724,439 @@
 
 /*
 ** Send the input tuple to the database then run the procedure.
+** Afterwards, setup for nondeterministic return of the output tuples.
 */
 static void
-MADITI_do_call(void)
-{ 
+MADITI_do_nondet_call(void)
+{
 	String proc_name;
 	int num_input_args;
+	Word *input_typeinfos;
+	Word *input_args;	
+
 	String input_schema;
+	String input_tuple = NULL;
+
 	int num_output_args;
 
-		/* Ticket identifying the input relation. */
-	ticket *input_ticket = NULL;
-		/* Ticket identifying the output relation. */
-	ticket *output_ticket = NULL;
-		/* Ticket identifying the cursor on the output relation. */
-	ticket *cursor = NULL;
-	
-		/* Used to hold the list of attributes of the input tuple
-		** as they are built up.
-		*/
-	Word tuple_list; 
-	Word new_tuple_list;
+	ticket *output_ticket = NULL;	/* ticket for the output relation */
+	ticket *cursor = NULL;		/* ticket for the output cursor */
 
-	char *tuple = NULL; /* The input tuple. */
+	int first_output_typeinfo;	/* register containing the first of the
+					** type-infos for the output arguments
+					*/
 	int i;
-		/* Register containing the first of the output type_infos. */
-	int first_output_typeinfo;
 
-		/* Memory used to hold copies of the input arguments. */
-	Word *input_save_area;
-	
 	restore_transient_registers();
 
 	proc_name = (String) MADITI_proc_name;
 	num_input_args = (int) MADITI_num_input_args;
 	input_schema = (String) MADITI_input_schema;
-	num_output_args = MADITI_num_output_args;
+
+	num_output_args = (int) MADITI_num_output_args;
 
 	/* save the number of output arguments */
 	MADITI_saved_num_output_args = num_output_args;
 
-	/* create temporary relation to hold the input tuple */
-	DEBUG(printf(""creating input temporary...""));
-	input_ticket = MR_NEW(ticket);
-	output_ticket = MR_NEW(ticket);
-	MADITI_check(ADITI_NAME(tmp_create)(&MADITI_ticket,
-		input_schema, input_ticket));
-	DEBUG(printf(""done\\n""));
 
-	/*
-	** Copy the input arguments and their type_infos out of the registers.
-	** This is done to avoid having to save/restore the
-	** registers around each call to MADITI__attr_to_string,
-	** which calls back into Mercury. 
-	*/
-	input_save_area = MR_GC_NEW_ARRAY(Word, num_input_args * 2);
+	DEBUG(printf(""Handling call to %s\\n"", proc_name));
+	DEBUG(printf(""%d input args; %d output args\\n"",
+		num_input_args, num_output_args));
+	DEBUG(printf(""input schema %s\\n"", input_schema));
+
+	/* extract the input arguments and their type-infos from registers */
+	input_args = MR_GC_NEW_ARRAY(Word, num_input_args);
+	input_typeinfos = MR_GC_NEW_ARRAY(Word, num_input_args);
 	save_registers();	
-	for (i = 0; i < num_input_args * 2; i++) {
-		input_save_area[i] = virtual_reg(MADITI_FIRST_INPUT + i);
+	for (i = 0; i < num_input_args; i++) {
+		input_typeinfos[i] = virtual_reg(MADITI_CALL_FIRST_INPUT + i);
+		input_args[i] =
+		    virtual_reg(MADITI_CALL_FIRST_INPUT + num_input_args + i);
 	}
 
 	/* store the output typeinfos in the nondet stack frame */
-	first_output_typeinfo = MADITI_FIRST_INPUT + num_input_args * 2;
+	first_output_typeinfo = MADITI_CALL_FIRST_INPUT + num_input_args * 2;
 	for (i = 0; i < num_output_args; i++) {
 		MADITI_OUTPUT_TYPEINFO(i) =
 			virtual_reg(first_output_typeinfo + i);
 	}
 
-	/*
-	** We're finished with the virtual_reg array.
-	** There's no need to restore the registers here since 
-	** we haven't altered any of the virtual_reg array entries.
-	*/
+	input_tuple = MADITI_construct_tuple(num_input_args,
+				input_typeinfos, input_args);
+	MR_GC_free(input_args);
+	MR_GC_free(input_typeinfos);
 
-	tuple_list = MR_list_empty();
-	DEBUG(printf(""building input tuple...""));
-	for (i = 0; i < num_input_args; i++) {
-		/* convert the argument to a string, adding it to the tuple */
-		MADITI__attr_to_string(input_save_area[i],
-			input_save_area[num_input_args + i],
-			tuple_list, &new_tuple_list);
-		tuple_list = new_tuple_list;
-	}
-	MADITI__reverse_append_string_list(tuple_list, &tuple);
+	output_ticket = MADITI_run_procedure(proc_name,
+				input_schema, input_tuple);
+
+	/* create cursor on the output relation */
+	DEBUG(printf(""opening output cursor...""));
+	/* XXX MR_GC_NEW_ATOMIC */
+	cursor = (ticket *) MR_GC_NEW(ticket);
+	MADITI_check(ADITI_NAME(rel_cursor_create)(output_ticket, cursor));
+	MADITI_check(ADITI_NAME(cursor_open)(cursor, CUR_FORWARD));
 	DEBUG(printf(""done\\n""));
 
+	MADITI_saved_output_rel = (Word) output_ticket;
+	MADITI_saved_cursor = (Word) cursor;
+
+#ifdef MR_USE_TRAIL
+	{
+		MADITI_trail_cleanup_data *cleanup_data;
+		cleanup_data = MR_GC_NEW(MADITI_trail_cleanup_data);
+		cleanup_data->output_rel = output_ticket;
+		cleanup_data->output_cursor = cursor;
+		cleanup_data->cleaned_up = FALSE;
+		MR_trail_function(MADITI_trail_cleanup_call_output,
+			(void *) cleanup_data);
+	}
+#endif /* MR_USE_TRAIL */
+
+	save_transient_registers();
+}
+
+#ifdef MR_USE_TRAIL
+static void
+MADITI_trail_cleanup_call_output(void *data, MR_untrail_reason reason)
+{
+	MADITI_trail_cleanup_data *cleanup_data;
+	switch (reason) {
+	    case MR_commit:
+	    case MR_exception:
+	    case MR_retry:
+		/*
+		** Cleanup the output relation.
+		*/
+		cleanup_data = (MADITI_trail_cleanup_data *) data;
+
+		if (cleanup_data->cleaned_up) {
+
+			/*
+			** This can happen if there is a commit followed
+			** by an exception -- the commit will not reset
+			** the trail.
+			*/
+			DEBUG(printf(
+	""MADITI_trail_cleanup_call_output: already cleaned up (%d)\n"",
+				reason));
+
+		} else {
+
+			DEBUG(printf(
+	""MADITI_trail_cleanup_call_output: cleaning up (%d)\n"",
+				reason));
+
+			MADITI_cleanup_call_output(cleanup_data->output_rel,
+				cleanup_data->output_cursor);
+			cleanup_data->cleaned_up = TRUE;
+		}
+		break;
+
+	    case MR_solve:
+	    case MR_undo:
+		/*
+		** Undo on backtracking will be handled by
+		** MADITI_post_call_cleanup, so that the 
+		** cleanup will happen even if trailing
+		** is not being used.
+		*/
+		break;
+
+	    case MR_gc:
+	    default:
+		fatal_error(""MADITI_trail_cleanup_call_output"");
+	}
+}
+#endif /* MR_USE_TRAIL */
+
+/* 
+** Given an RL procedure name, the schema of the input relation and a tuple
+** to insert into the input relation, run the procedure, returning a ticket
+** for the output relation.
+** MADITI_run_procedure does not look at the Mercury registers.
+*/
+static ticket *
+MADITI_run_procedure(String proc_name, String input_schema, String input_tuple)
+{
+		/* Ticket identifying the input relation. */
+	ticket input_ticket;
+		/* Ticket identifying the output relation. */
+	ticket *output_ticket = NULL;
+
 	/*
-	** We're done with the saved input arguments.
+	** Create a temporary relation to hold the input tuple.
 	*/
-	MR_GC_free(input_save_area);
+	DEBUG(printf(""creating input temporary (schema %s)..."",
+		input_schema));
+	MADITI_check(ADITI_NAME(tmp_create)(&MADITI_ticket,
+		input_schema, &input_ticket));
+	DEBUG(printf(""done\\n""));
 
-	/* insert the input tuple into the relation */
-	DEBUG(printf(""adding input tuple...%s"", tuple));
-	MADITI_check(ADITI_NAME(tmp_addtup)(input_ticket, tuple));
+	/*
+	** Insert the input tuple into the relation.
+	*/
+	DEBUG(printf(""adding input tuple...%s"", input_tuple));
+	MADITI_check(ADITI_NAME(tmp_addtup)(&input_ticket, input_tuple));
 	DEBUG(printf(""done\\n""));
 
-	/* run the procedure */
+	/*
+	** Run the procedure.
+	*/
 	DEBUG(printf(""running procedure... ""));
-	MADITI_check(ADITI_NAME(run2)(proc_name, 100000, &MADITI_ticket,
-		input_ticket, output_ticket));
+	/* XXX MR_GC_NEW_ATOMIC */
+	output_ticket = (ticket *) MR_GC_NEW(ticket);
+	MADITI_check(ADITI_NAME(run2_s)(proc_name, 100000, &MADITI_ticket,
+		&input_ticket, output_ticket));
 	DEBUG(printf(""done\\n""));
 
-	/* drop the input relation */
+	/*
+	** Drop the input relation.
+	*/
 	DEBUG(printf(""dropping input temporary...""));
-	MADITI_check(ADITI_NAME(tmp_destroy)(input_ticket));
-	MR_free(input_ticket);
+	MADITI_check(ADITI_NAME(tmp_destroy)(&input_ticket));
 	DEBUG(printf(""done\\n""));
 
-	/* create cursor on the output relation */
-	DEBUG(printf(""opening output cursor...""));
-	cursor = MR_NEW(ticket);
-	MADITI_check(ADITI_NAME(tmp_cursor_create)(output_ticket, cursor));
-	MADITI_check(ADITI_NAME(cursor_open)(cursor, CUR_FORWARD));
-	DEBUG(printf(""done\\n""));
+	DEBUG(printf(""output tuples\n""));
+	DEBUG(MADITI_list_rel(output_ticket));
+	DEBUG(printf(""\\n\\n""));
 
-	MADITI_saved_output_rel = (Word) output_ticket;
-	MADITI_saved_cursor = (Word) cursor;
+	return output_ticket;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+MADITI_do_insert_delete_tuple(MADITI_insert_delete op)
+{
+	String rel_name;
+	int rel_arity;
+	String tuple;
+	String delete_proc_name;
+	String delete_input_schema;
+	Word *input_typeinfos;
+	Word *input_args;
+	int first_input_reg = 5;
+	int i;
+	ticket *delete_output_rel = NULL;
+
+	restore_transient_registers();
+	rel_name = (String) r1;
+	rel_arity = r2;
+	delete_proc_name = (String) r3;
+	delete_input_schema = (String) r4;
+
+	DEBUG(
+		switch (op) {
+			case MADITI_INSERT_TUPLE:
+				printf(""aditi_insert(%s)\\n"",
+					rel_name);	
+				break;
+			case MADITI_DELETE_TUPLE:
+				printf(""aditi_delete(%s)\\n"",
+					rel_name);	
+				break;
+		}
+	)
+
+	/* extract the input arguments and their type-infos from registers */
+	input_args = MR_GC_NEW_ARRAY(Word, rel_arity);
+	input_typeinfos = MR_GC_NEW_ARRAY(Word, rel_arity);
+	save_registers();
+	for (i = 0; i < rel_arity; i++) {
+		input_typeinfos[i] = virtual_reg(first_input_reg + i);
+		input_args[i] = virtual_reg(first_input_reg + rel_arity + i);
+	}
+
+	tuple = MADITI_construct_tuple(rel_arity, input_typeinfos, input_args);
+
+	MR_GC_free(input_args);
+	MR_GC_free(input_typeinfos);
+
+	switch (op) {
+		case MADITI_INSERT_TUPLE:
+			DEBUG(printf(""inserting tuple %s\\n"", tuple));
+			MADITI_check(ADITI_NAME(addtup)(rel_name, tuple));
+			break;
+		case MADITI_DELETE_TUPLE:
+			DEBUG(printf(""deleting tuple %s\\n"", tuple));
+			delete_output_rel =
+				MADITI_run_procedure(delete_proc_name,
+					delete_input_schema, tuple);
+			MADITI_check(ADITI_NAME(rel_close)(
+				delete_output_rel));
+			MR_GC_free(delete_output_rel);
+			break;
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+MADITI_do_bulk_operation(MADITI_bulk_op operation)
+{
+	String rel_name;
+	int num_input_args;
+	Word *input_args;
+	Word *input_typeinfos;
+	MR_Closure *closure;
+	String called_proc_name;
+	String update_proc_name = NULL;
+	String input_schema;
+	String input_tuple;
+	ticket modified_rel_ticket;
+	ticket dummy_output_ticket;
+	ticket *call_result_ticket;
+
+	restore_transient_registers();
 
+	rel_name = (String) r1;
+	update_proc_name = (String) r2;
+	closure = (MR_Closure *) r3;
+
+	DEBUG(
+		switch (operation) {
+			case MADITI_INSERT:
+				printf(""aditi_bulk_insert(%s)\\n"",
+					rel_name);	
+				break;
+			case MADITI_DELETE:
+				printf(""aditi_bulk_delete(%s)\\n"",
+					rel_name);	
+				break;
+			case MADITI_MODIFY:
+				printf(""aditi_bulk_delete(%s)\\n"",
+					rel_name);	
+				break;
+		}
+	)
+
+	/*
+	** The 'code' passed to an aditi_bottom_up closure is
+	** actually a tuple containing the procedure name and
+	** the schema of the input relation.
+	*/
+	called_proc_name =
+		(String) MR_field(MR_mktag(0), closure->MR_closure_code, 0);
+	input_schema =
+		(String) MR_field(MR_mktag(0), closure->MR_closure_code, 1);
+
+	DEBUG(printf(""closure proc name %s\n"", called_proc_name));
+
+	num_input_args = closure->MR_closure_num_hidden_args;
+	input_args = (Word *) closure->MR_closure_hidden_args_0;
+	input_typeinfos =
+		(Word *) closure->MR_closure_layout->arg_pseudo_type_info;
+
+	input_tuple = MADITI_construct_tuple(num_input_args,
+				input_typeinfos, input_args);
+
+	call_result_ticket = MADITI_run_procedure(called_proc_name,
+				input_schema, input_tuple);
+
+	switch (operation) {
+		case MADITI_INSERT:
+			DEBUG(printf(""Inserting tuples into %s\\n"",
+				rel_name));	
+
+			MADITI_check(ADITI_NAME(perm_open)(&MADITI_ticket,
+					rel_name, &modified_rel_ticket));
+			MADITI_check(ADITI_NAME(add_tups_to)(
+					call_result_ticket,
+					&modified_rel_ticket));
+			MADITI_check(ADITI_NAME(perm_close)(
+					&modified_rel_ticket));
+			break;
+
+		case MADITI_DELETE:
+		case MADITI_MODIFY:
+			DEBUG(printf(""Doing delete/modify of %s\n"",
+				rel_name));
+			MADITI_check(ADITI_NAME(run2_s)(update_proc_name,
+				100000, &MADITI_ticket,
+				call_result_ticket, &dummy_output_ticket)
+			);
+			MADITI_check(
+				ADITI_NAME(rel_close)(&dummy_output_ticket)
+			);
+			break;
+	}
+
+
+	MADITI_check(ADITI_NAME(rel_close)(call_result_ticket));
+	MR_GC_free(call_result_ticket);
+
 	save_transient_registers();
 }
 
+static void 
+MADITI_list_rel(ticket* rel)
+{
+	size_t len;
+	char* ptr;
+	ticket cur;
+
+	MADITI_check(ADITI_NAME(tmp_cursor_create)(rel,&cur));
+	MADITI_check(ADITI_NAME(cursor_open)(&cur,CUR_FORWARD));
+	len = 0;
+	ptr = NULL;
+	fflush(stdout);
+	while (ADITI_NAME(cursor_next)(&cur,&len,&ptr) == ADITI_OK) {
+		fprintf(stdout,""tuple: [%.*s]\n"",(int)len,ptr);
+		free(ptr);
+		len = 0;
+		ptr = NULL;
+	}
+	MADITI_check(ADITI_NAME(cursor_close)(&cur));
+	MADITI_check(ADITI_NAME(cursor_destroy)(&cur));
+}
+
+/*---------------------------------------------------------------------------*/
+
 /*
+** Convert a list of arguments in registers into a string representation
+** suitable for sending to Aditi.
+** Starting at register `first_argument', there must be `num_input_args'
+** type_infos, followed by `num_input_args' data values.
+** save_transient_registers()/restore_transient_registers() must be done
+** around calls to this function.
+*/
+String MADITI_construct_tuple(int num_input_args,
+		Word *typeinfos, Word *input_args)
+{
+		/* Used to hold the list of attributes of the input tuple
+		** as they are built up.
+		*/
+	Word tuple_list; 
+	Word new_tuple_list;
+
+	String tuple;
+	int i;
+
+	restore_transient_registers();
+
+	/*
+	** This part calls back into Mercury to construct the tuple.
+	** The wrapper functions expect the registers to be saved,
+	** so do that here.
+	*/
+	save_registers();
+	tuple_list = MR_list_empty();
+	DEBUG(printf(""building input tuple...""));
+	for (i = 0; i < num_input_args; i++) {
+		/* convert the argument to a string, adding it to the tuple */
+		MADITI__attr_to_string(typeinfos[i], input_args[i],
+			tuple_list, &new_tuple_list);
+		tuple_list = new_tuple_list;
+	}
+	MADITI__reverse_append_string_list(tuple_list, &tuple);
+	DEBUG(printf(""done: tuple = %s\\n"", tuple));
+
+	return tuple;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
 ** Get an output tuple from the database, return an indication of success.
 ** Attributes from the tuple should be placed in consecutive registers
 ** starting with r(first_reg).
@@ -666,6 +1174,7 @@
 	String tuple_str_copy;
 	Word arg;
 	int found_result;
+	ticket *output_cursor;
 	int num_output_args;
 	int rc;
 		/* Somewhere to put the output arguments before copying them
@@ -675,16 +1184,18 @@
 
 	restore_transient_registers();
 	num_output_args = MADITI_saved_num_output_args;
+	output_cursor = (ticket *)MADITI_saved_cursor;
 
 	/* advance cursor, get tuple string */
-	rc = ADITI_NAME(cursor_next)((ticket *)MADITI_saved_cursor,
+	DEBUG(printf(""getting output tuple\\n""));
+	rc = ADITI_NAME(cursor_next)(output_cursor,
 		&tuple_str_len, &tuple_str);
-	DEBUG(printf(""handling tuple %s %ld %d\\n"",
-		tuple_str, tuple_str_len, num_output_args));
-
 	if (rc != ADITI_OK) {
+		DEBUG(printf(""no more output tuples\\n""));
 		found_result = FALSE;
 	} else {
+		DEBUG(printf(""handling tuple %s %ld %d\\n"",
+			tuple_str, tuple_str_len, num_output_args));
 
 		/*
 		** Found another output tuple.
@@ -692,6 +1203,7 @@
 	
 		/* Copy out the tuple string. */
 		make_aligned_string_copy(tuple_str_copy, tuple_str);
+		/* The tuple is on the C heap. */
 		free(tuple_str);
 
 		/*
@@ -700,6 +1212,13 @@
 		*/
 		output_save_area = MR_GC_NEW_ARRAY(Word, num_output_args);
 	
+		/*
+		** This part calls back into Mercury to parse the
+		** tuple terms from the string returned from Aditi.
+		** The wrapper functions generated expect the registers
+		** to be saved, so do that here.
+		*/
+		save_registers();
 		/* convert tuple, put output args in stack slots */
 		MADITI__init_posn(&pos);
 		for (i = 0; i < num_output_args; i++) {
@@ -716,7 +1235,6 @@
 		}
 
 		/* Move the output arguments to their registers. */
-		save_registers();
 		for (i = 0; i < num_output_args; i++) {
 			virtual_reg(first_reg + i) = output_save_area[i];
 		}
@@ -729,43 +1247,49 @@
 	return found_result;
 }
 
+/*---------------------------------------------------------------------------*/
+
 /*
 ** Free all resources used by a database call.
 */
 static void
-MADITI_cleanup()
+MADITI_post_call_cleanup(void)
 { 
 	restore_transient_registers();
+	MADITI_cleanup_call_output((ticket *) MADITI_saved_output_rel,
+		(ticket *) MADITI_saved_cursor);
+	save_transient_registers();
+}
 
+static void
+MADITI_cleanup_call_output(ticket *output_rel, ticket *cursor)
+{
 	/* close cursor */
-	MADITI_check(ADITI_NAME(cursor_close)(
-		(ticket *)MADITI_saved_cursor));
+	MADITI_check(ADITI_NAME(cursor_close)(cursor));
 
 	/* destroy cursor */
-	MADITI_check(ADITI_NAME(cursor_destroy)(
-		(ticket *)MADITI_saved_cursor));
-	MR_free((ticket *)MADITI_saved_cursor);
-
-	/* destroy output temporary */
-	MADITI_check(ADITI_NAME(tmp_destroy)(
-		(ticket *)MADITI_saved_output_rel));
-	MR_free((ticket *)MADITI_saved_output_rel);
+	MADITI_check(ADITI_NAME(cursor_destroy)(cursor));
+	MR_GC_free(cursor);
 
-	save_transient_registers();
+	/* close output temporary */
+	MADITI_check(ADITI_NAME(rel_close)(output_rel));
+	MR_GC_free(output_rel);
 }
 
+/*---------------------------------------------------------------------------*/
+
 /*
 ** If the status is not OK, abort the transaction.
 */
 static void
-MADITI_check(int status)
+MADITI_do_check(int status, int line)
 {
 	if (status != ADITI_OK) {
-		MADITI_status = status;
+		DEBUG(printf(""aditi.m:%d MADITI_check_failed, status %d\\n"",
+				line, status));
 		MR_longjmp(&MADITI_jmp_buf);
 	}
 }
-
 ").
 
 %-----------------------------------------------------------------------------%
@@ -848,12 +1372,11 @@
 :- pragma export(aditi__reverse_append_string_list(in, out),
 		"MADITI__reverse_append_string_list").
 
-	% Yes, the output of this is meant to have unbalanced parentheses.
 aditi__reverse_append_string_list(Strings0, String) :-
 	( Strings0 = [] ->
 		String = "()\n"
 	;
-		aditi__construct_attr_list(Strings0, yes, ["\n"], Strings1),
+		aditi__construct_attr_list(Strings0, yes, [")\n"], Strings1),
 		string__append_list(Strings1, String)
 	).
 
@@ -956,7 +1479,7 @@
 :- pragma c_code(aditi__error_message(Stat::in, Msg::out),
 		will_not_call_mercury,
 "
-	Msg = aditi_strerror(Stat);
+	Msg = aditi_strerror((int) Stat);
 ").
 
 %-----------------------------------------------------------------------------%
Index: tests/invalid/aditi_update_errors.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/aditi_update_errors.err_exp,v
retrieving revision 1.3
diff -u -u -r1.3 aditi_update_errors.err_exp
--- tests/invalid/aditi_update_errors.err_exp	2000/02/15 00:36:03	1.3
+++ tests/invalid/aditi_update_errors.err_exp	2000/04/04 02:24:48
@@ -1,57 +1,81 @@
-aditi_update_errors.m:091: Error: wrong number of arguments (5; should be 3 or 4)
-aditi_update_errors.m:091:   in `aditi_modify'.
-aditi_update_errors.m:090: Error: expected
-aditi_update_errors.m:090:   `aditi_modify(
-aditi_update_errors.m:090:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
-aditi_update_errors.m:090:     DB0, DB)'
-aditi_update_errors.m:090:   or `aditi_modify(PredOrFunc p/N, Closure, DB0, DB)'.
-aditi_update_errors.m:081: Error: wrong number of arguments (5; should be 3 or 4)
-aditi_update_errors.m:081:   in `aditi_modify'.
-aditi_update_errors.m:080: Error: expected
-aditi_update_errors.m:080:   `aditi_modify(
-aditi_update_errors.m:080:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
-aditi_update_errors.m:080:     DB0, DB)'
-aditi_update_errors.m:080:   or `aditi_modify(PredOrFunc p/N, Closure, DB0, DB)'.
-aditi_update_errors.m:071: Error: expected
-aditi_update_errors.m:071:   `aditi_modify(
-aditi_update_errors.m:071:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
-aditi_update_errors.m:071:     DB0, DB)'
-aditi_update_errors.m:071:   or `aditi_modify(PredOrFunc p/N, Closure, DB0, DB)'.
-aditi_update_errors.m:067: Error: wrong number of arguments (5; should be 4)
-aditi_update_errors.m:067:   in `aditi_bulk_delete'.
-aditi_update_errors.m:066: Error: expected `PredOrFunc Name/Arity' in `aditi_bulk_delete'.
-aditi_update_errors.m:057: Error: wrong number of arguments (5; should be 4)
-aditi_update_errors.m:057:   in `aditi_bulk_delete'.
-aditi_update_errors.m:056: Error: expected `PredOrFunc Name/Arity' in `aditi_bulk_insert'.
-aditi_update_errors.m:048: Error: expected `aditi_delete((p(<Args>) :- <Goal>), DB0, DB)'
-aditi_update_errors.m:048:   or `aditi_delete(PredOrFunc p/N, Closure, DB0, DB)'.
-aditi_update_errors.m:043: Error: expected `aditi_delete((p(<Args>) :- <Goal>), DB0, DB)'
-aditi_update_errors.m:043:   or `aditi_delete(PredOrFunc p/N, Closure, DB0, DB)'.
-aditi_update_errors.m:037: Error: expected `aditi_delete((p(<Args>) :- <Goal>), DB0, DB)'
-aditi_update_errors.m:037:   or `aditi_delete(PredOrFunc p/N, Closure, DB0, DB)'.
-aditi_update_errors.m:036: Error: expected `aditi_delete((p(<Args>) :- <Goal>), DB0, DB)'
-aditi_update_errors.m:036:   or `aditi_delete(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:090: Error: wrong number of arguments (5; should be 3 or 4)
+aditi_update_errors.m:090:   in `aditi_bulk_modify'.
+aditi_update_errors.m:089: Error: expected
+aditi_update_errors.m:089:   `aditi_bulk_modify(
+aditi_update_errors.m:089:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
+aditi_update_errors.m:089:     DB0, DB)'
+aditi_update_errors.m:089:   or `aditi_bulk_modify(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:079: Error: wrong number of arguments (5; should be 3 or 4)
+aditi_update_errors.m:079:   in `aditi_bulk_modify'.
+aditi_update_errors.m:078: Error: expected
+aditi_update_errors.m:078:   `aditi_bulk_modify(
+aditi_update_errors.m:078:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
+aditi_update_errors.m:078:     DB0, DB)'
+aditi_update_errors.m:078:   or `aditi_bulk_modify(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:068: Error: expected
+aditi_update_errors.m:068:   `aditi_bulk_modify(
+aditi_update_errors.m:068:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
+aditi_update_errors.m:068:     DB0, DB)'
+aditi_update_errors.m:068:   or `aditi_bulk_modify(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:067: Error: expected
+aditi_update_errors.m:067:   `aditi_bulk_modify(
+aditi_update_errors.m:067:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
+aditi_update_errors.m:067:     DB0, DB)'
+aditi_update_errors.m:067:   or `aditi_bulk_modify(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:066: Error: expected
+aditi_update_errors.m:066:   `aditi_bulk_modify(
+aditi_update_errors.m:066:     (p(<Args0>) ==> p(<Args>) :- <Goal>),
+aditi_update_errors.m:066:     DB0, DB)'
+aditi_update_errors.m:066:   or `aditi_bulk_modify(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:064: Error: wrong number of arguments (5; should be 3 or 4)
+aditi_update_errors.m:064:   in `aditi_bulk_delete'.
+aditi_update_errors.m:063: Error: expected `aditi_bulk_delete((p(<Args>) :- <Goal>), DB0, DB)'
+aditi_update_errors.m:063:   or `aditi_bulk_delete(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:046: Error: wrong number of arguments (5; should be 3 or 4)
+aditi_update_errors.m:046:   in `aditi_bulk_delete'.
+aditi_update_errors.m:045: Error: expected `aditi_bulk_insert((p(<Args>) :- <Goal>), DB0, DB)'
+aditi_update_errors.m:045:   or `aditi_bulk_insert(PredOrFunc p/N, Closure, DB0, DB)'.
+aditi_update_errors.m:037: Error: wrong number of arguments (4; should be 3)
+aditi_update_errors.m:037:   in `aditi_delete'.
+aditi_update_errors.m:036: Error: wrong number of arguments (4; should be 3)
+aditi_update_errors.m:036:   in `aditi_delete'.
 aditi_update_errors.m:034: Error: wrong number of arguments (4; should be 3)
 aditi_update_errors.m:034:   in `aditi_insert'.
 aditi_update_errors.m:033: Error: wrong number of arguments (4; should be 3)
 aditi_update_errors.m:033:   in `aditi_insert'.
 aditi_update_errors.m:031: Error: expected tuple to insert in `aditi_insert'.
-aditi_update_errors.m:073: In clause for predicate `aditi_update_errors:aditi_update_syntax/2':
-aditi_update_errors.m:073:   warning: variable `X' has overlapping scopes.
-aditi_update_errors.m:083: In clause for predicate `aditi_update_errors:aditi_update_syntax/2':
-aditi_update_errors.m:083:   warning: variable `X' has overlapping scopes.
+aditi_update_errors.m:048: In clause for predicate `aditi_update_errors:aditi_update_syntax/2':
+aditi_update_errors.m:048:   warning: variable `X' has overlapping scopes.
+aditi_update_errors.m:070: In clause for predicate `aditi_update_errors:aditi_update_syntax/2':
+aditi_update_errors.m:070:   warning: variable `X' has overlapping scopes.
+aditi_update_errors.m:081: In clause for predicate `aditi_update_errors:aditi_update_syntax/2':
+aditi_update_errors.m:081:   warning: variable `X' has overlapping scopes.
+aditi_update_errors.m:102: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:102:   warning: variable `_Y' occurs more than once in this scope.
+aditi_update_errors.m:102: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:102:   warning: variable `_Y' occurs more than once in this scope.
+aditi_update_errors.m:103: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:103:   warning: variable `_Y' occurs more than once in this scope.
+aditi_update_errors.m:103: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:103:   warning: variable `_Y' occurs more than once in this scope.
+aditi_update_errors.m:166: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:166:   warning: variable `DB' occurs only once in this scope.
 aditi_update_errors.m:007: Error: no clauses for
 aditi_update_errors.m:007:   predicate `aditi_update_errors:aditi_update_syntax/2'.
+aditi_update_errors.m:096: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:096:   error: wrong number of arguments (2; should be 3)
+aditi_update_errors.m:096:   in call to predicate `p'.
 aditi_update_errors.m:097: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:097:   error: wrong number of arguments (2; should be 3)
-aditi_update_errors.m:097:   in call to predicate `p'.
+aditi_update_errors.m:097:   error: undefined predicate `q/2'.
+aditi_update_errors.m:097:   (There is a *function* with that name, however.
+aditi_update_errors.m:097:   Perhaps you forgot to add ` = ...'?)
 aditi_update_errors.m:098: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:098:   error: undefined predicate `q/2'.
-aditi_update_errors.m:098:   (There is a *function* with that name, however.
-aditi_update_errors.m:098:   Perhaps you forgot to add ` = ...'?)
+aditi_update_errors.m:098:   error: wrong number of arguments (1; should be 2)
+aditi_update_errors.m:098:   in call to function `q'.
 aditi_update_errors.m:099: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:099:   error: wrong number of arguments (1; should be 2)
-aditi_update_errors.m:099:   in call to function `q'.
+aditi_update_errors.m:099:   in argument 2 of `aditi_insert' of predicate `p/3':
+aditi_update_errors.m:099:   type error: argument has type `int',
+aditi_update_errors.m:099:   expected type was `(aditi:state)'.
 aditi_update_errors.m:100: In clause for predicate `aditi_update_errors:aditi_update_types/2':
 aditi_update_errors.m:100:   in argument 2 of `aditi_insert' of predicate `p/3':
 aditi_update_errors.m:100:   type error: argument has type `int',
@@ -65,6 +89,9 @@
 aditi_update_errors.m:103:   type error: argument has type `float',
 aditi_update_errors.m:103:   expected type was `int'.
 aditi_update_errors.m:105: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:105:   error: wrong number of arguments (2; should be 3)
+aditi_update_errors.m:105:   in call to predicate `p'.
+aditi_update_errors.m:105: In clause for predicate `aditi_update_errors:aditi_update_types/2':
 aditi_update_errors.m:105:   in argument 2 of call to predicate `</2':
 aditi_update_errors.m:105:   type error: argument has type `float',
 aditi_update_errors.m:105:   expected type was `int'.
@@ -72,83 +99,86 @@
 aditi_update_errors.m:105:   error: wrong number of arguments (2; should be 3)
 aditi_update_errors.m:105:   in call to predicate `p'.
 aditi_update_errors.m:106: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:106:   in argument 1 of call to predicate `</2':
+aditi_update_errors.m:106:   type error: variable `Y' has type `((func int) = int)',
+aditi_update_errors.m:106:   expected type was `int'.
+aditi_update_errors.m:106: In clause for predicate `aditi_update_errors:aditi_update_types/2':
 aditi_update_errors.m:106:   error: wrong number of arguments (1; should be 2)
 aditi_update_errors.m:106:   in call to function `q'.
-aditi_update_errors.m:112: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:112:   in argument 2 of `aditi_delete' of predicate `p/3':
-aditi_update_errors.m:112:   type error: variable `DeleteP' has type `(aditi_top_down pred(V_10, int))',
-aditi_update_errors.m:112:   expected type was `(aditi_top_down pred((aditi:state), int, int))'.
-aditi_update_errors.m:113: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:113:   error: undefined predicate `q/2'.
-aditi_update_errors.m:113:   (There is a *function* with that name, however.
-aditi_update_errors.m:113:   Perhaps you forgot to add ` = ...'?)
-aditi_update_errors.m:118: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:118:   in argument 2 of `aditi_delete' of function `q/2':
-aditi_update_errors.m:118:   type error: variable `DeleteQ' has type `((aditi_top_down (func V_12)) = int)',
-aditi_update_errors.m:118:   expected type was `((aditi_top_down func((aditi:state), int)) = int)'.
-aditi_update_errors.m:119: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:119:   error: undefined function `p/3'.
-aditi_update_errors.m:119:   (There is a *predicate* with that name, however.)
-aditi_update_errors.m:124: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:124:   in argument 2 of `aditi_delete' of function `q/2':
-aditi_update_errors.m:124:   type error: variable `DeleteQ2' has type `((func V_14) = int)',
-aditi_update_errors.m:124:   expected type was `((aditi_top_down func((aditi:state), int)) = int)'.
-aditi_update_errors.m:132: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:132:   error: wrong number of arguments (4; should be 3)
-aditi_update_errors.m:132:   in call to predicate `p'.
-aditi_update_errors.m:133: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:133:   in argument 2 of `aditi_bulk_insert' of predicate `p/3':
-aditi_update_errors.m:133:   type error: variable `InsertP' has type `(aditi_bottom_up pred(V_16, int, float))',
-aditi_update_errors.m:133:   expected type was `(aditi_bottom_up pred((aditi:state), int, int))'.
-aditi_update_errors.m:134: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:134:   error: undefined predicate `q/2'.
-aditi_update_errors.m:134:   (There is a *function* with that name, however.
-aditi_update_errors.m:134:   Perhaps you forgot to add ` = ...'?)
-aditi_update_errors.m:142: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:142:   in argument 2 of `aditi_bulk_insert' of predicate `p/3':
-aditi_update_errors.m:142:   type error: variable `InsertP2' has type `pred(V_19, int, float)',
-aditi_update_errors.m:142:   expected type was `(aditi_bottom_up pred((aditi:state), int, int))'.
+aditi_update_errors.m:109: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:109:   in argument 2 of `aditi_bulk_delete' of predicate `p/3':
+aditi_update_errors.m:109:   type error: variable `DeleteP' has type `(aditi_bottom_up pred(V_11, int))',
+aditi_update_errors.m:109:   expected type was `(aditi_bottom_up pred((aditi:state), int, int))'.
+aditi_update_errors.m:110: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:110:   error: undefined predicate `q/2'.
+aditi_update_errors.m:110:   (There is a *function* with that name, however.
+aditi_update_errors.m:110:   Perhaps you forgot to add ` = ...'?)
+aditi_update_errors.m:115: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:115:   in argument 2 of `aditi_bulk_delete' of function `q/2':
+aditi_update_errors.m:115:   type error: variable `DeleteQ' has type `((aditi_bottom_up (func V_13)) = int)',
+aditi_update_errors.m:115:   expected type was `((aditi_bottom_up func((aditi:state), int)) = int)'.
+aditi_update_errors.m:116: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:116:   error: undefined function `p/3'.
+aditi_update_errors.m:116:   (There is a *predicate* with that name, however.)
+aditi_update_errors.m:121: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:121:   in argument 2 of `aditi_bulk_delete' of function `q/2':
+aditi_update_errors.m:121:   type error: variable `DeleteQ2' has type `((func V_15) = int)',
+aditi_update_errors.m:121:   expected type was `((aditi_bottom_up func((aditi:state), int)) = int)'.
+aditi_update_errors.m:129: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:129:   error: wrong number of arguments (4; should be 3)
+aditi_update_errors.m:129:   in call to predicate `p'.
+aditi_update_errors.m:130: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:130:   in argument 2 of `aditi_bulk_insert' of predicate `p/3':
+aditi_update_errors.m:130:   type error: variable `InsertP' has type `(aditi_bottom_up pred(V_17, int, float))',
+aditi_update_errors.m:130:   expected type was `(aditi_bottom_up pred((aditi:state), int, int))'.
+aditi_update_errors.m:131: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:131:   error: undefined predicate `q/2'.
+aditi_update_errors.m:131:   (There is a *function* with that name, however.
+aditi_update_errors.m:131:   Perhaps you forgot to add ` = ...'?)
+aditi_update_errors.m:139: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:139:   in argument 2 of `aditi_bulk_insert' of predicate `p/3':
+aditi_update_errors.m:139:   type error: variable `InsertP2' has type `pred(V_20, int, float)',
+aditi_update_errors.m:139:   expected type was `(aditi_bottom_up pred((aditi:state), int, int))'.
+aditi_update_errors.m:149: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:149:   error: undefined predicate `q/2'.
+aditi_update_errors.m:149:   (There is a *function* with that name, however.
+aditi_update_errors.m:149:   Perhaps you forgot to add ` = ...'?)
 aditi_update_errors.m:152: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:152:   error: undefined predicate `q/2'.
-aditi_update_errors.m:152:   (There is a *function* with that name, however.
-aditi_update_errors.m:152:   Perhaps you forgot to add ` = ...'?)
-aditi_update_errors.m:155: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:155:   in argument 1 of `aditi_modify' of predicate `p/3':
-aditi_update_errors.m:155:   type error: argument has type `(aditi_top_down pred(int, int, V_27, int, int, V_30))',
-aditi_update_errors.m:155:   expected type was `(aditi_top_down pred((aditi:state), int, int, (aditi:state), int, int))'.
-aditi_update_errors.m:156: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:156:   error: wrong number of arguments (1; should be 2)
-aditi_update_errors.m:156:   in call to function `q'.
-aditi_update_errors.m:157: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:157:   error: undefined predicate `q/3'.
-aditi_update_errors.m:157:   (There is a *function* with that name, however.
-aditi_update_errors.m:157:   Perhaps you forgot to add ` = ...'?)
-aditi_update_errors.m:163: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:163:   in unification of variable `X'
-aditi_update_errors.m:163:   and term `(X0 + Y0)':
-aditi_update_errors.m:163:   type error in argument(s) of functor `+/2'.
-aditi_update_errors.m:163:   Argument 1 (X0) has type `float',
-aditi_update_errors.m:163:   expected type was `int';
-aditi_update_errors.m:163:   argument 2 (Y0) has type `V_43',
-aditi_update_errors.m:163:   expected type was `int'.
-aditi_update_errors.m:164: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:164:   in unification of variable `Y'
-aditi_update_errors.m:164:   and term `(X0 - Y0)':
-aditi_update_errors.m:164:   type error in argument(s) of functor `-/2'.
-aditi_update_errors.m:164:   Argument 1 (X0) has type `float',
-aditi_update_errors.m:164:   expected type was `int';
-aditi_update_errors.m:164:   argument 2 (Y0) has type `V_43',
-aditi_update_errors.m:164:   expected type was `int'.
-aditi_update_errors.m:166: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:166:   in argument 2 of `aditi_modify' of predicate `p/3':
-aditi_update_errors.m:166:   type error: variable `ModifyP' has type `(aditi_top_down pred(V_41, float, V_43, V_44, V_45, V_46))',
-aditi_update_errors.m:166:   expected type was `(aditi_top_down pred((aditi:state), int, int, (aditi:state), int, int))'.
-aditi_update_errors.m:175: In clause for predicate `aditi_update_errors:aditi_update_types/2':
-aditi_update_errors.m:175:   in argument 2 of `aditi_modify' of function `q/2':
-aditi_update_errors.m:175:   type error: variable `ModifyQ' has type `((aditi_top_down func(V_47, int, int, V_50, int)) = int)',
-aditi_update_errors.m:175:   expected type was `(aditi_top_down pred((aditi:state), int, int, (aditi:state), int, int))'.
+aditi_update_errors.m:152:   in argument 4 of clause head:
+aditi_update_errors.m:152:   in unification of argument
+aditi_update_errors.m:152:   and term `(X0 + V_91)':
+aditi_update_errors.m:152:   type error in argument(s) of functor `+/2'.
+aditi_update_errors.m:152:   Argument 1 (X0) has type `(aditi:state)',
+aditi_update_errors.m:152:   expected type was `int'.
+aditi_update_errors.m:153: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:153:   in argument 4 of clause head:
+aditi_update_errors.m:153:   in unification of argument
+aditi_update_errors.m:153:   and term `(Y0 + V_87)':
+aditi_update_errors.m:153:   type error in argument(s) of functor `+/2'.
+aditi_update_errors.m:153:   Argument 1 (Y0) has type `((func int) = int)',
+aditi_update_errors.m:153:   expected type was `int'.
+aditi_update_errors.m:153: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:153:   error: wrong number of arguments (1; should be 2)
+aditi_update_errors.m:153:   in call to function `q'.
+aditi_update_errors.m:154: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:154:   error: undefined predicate `q/3'.
+aditi_update_errors.m:154:   (There is a *function* with that name, however.
+aditi_update_errors.m:154:   Perhaps you forgot to add ` = ...'?)
+aditi_update_errors.m:154: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:154:   error: undefined predicate `q/3'.
+aditi_update_errors.m:154:   (There is a *function* with that name, however.
+aditi_update_errors.m:154:   Perhaps you forgot to add ` = ...'?)
+aditi_update_errors.m:160: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:160:   type error in unification of variable `X0'
+aditi_update_errors.m:160:   and constant `1.00000000000000'.
+aditi_update_errors.m:160:   variable `X0' has type `int',
+aditi_update_errors.m:160:   constant `1.00000000000000' has type `float'.
+aditi_update_errors.m:173: In clause for predicate `aditi_update_errors:aditi_update_types/2':
+aditi_update_errors.m:173:   in argument 2 of `aditi_bulk_modify' of function `q/2':
+aditi_update_errors.m:173:   type error: variable `ModifyQ' has type `((aditi_bottom_up func(V_48, int, int, V_51, int)) = int)',
+aditi_update_errors.m:173:   expected type was `(aditi_bottom_up pred((aditi:state), int, int, (aditi:state), int, int))'.
 aditi_update_errors.m:026: Error: no clauses for
 aditi_update_errors.m:026:   predicate `aditi_update_errors:anc/3'.
-aditi_update_errors.m:094: In `aditi_insert' of predicate `anc/3':
-aditi_update_errors.m:094:   error: the modified predicate is not a base relation.
+aditi_update_errors.m:093: In `aditi_insert' of predicate `anc/3':
+aditi_update_errors.m:093:   error: the modified predicate is not a base relation.
 For more information, try recompiling with `-E'.
Index: tests/invalid/aditi_update_errors.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/aditi_update_errors.m,v
retrieving revision 1.1
diff -u -u -r1.1 aditi_update_errors.m
--- tests/invalid/aditi_update_errors.m	1999/07/13 08:55:06	1.1
+++ tests/invalid/aditi_update_errors.m	2000/04/04 02:24:29
@@ -33,20 +33,9 @@
 	aditi_insert(p(_, 1, 2), foo),
 	aditi_insert(q(_, 1) = 2, foo),
 
-	aditi_delete(p(_, X, _Y) :- X < 2, foo),
-	aditi_delete(q(_, X) = _Y :- X < 2, foo),
+	aditi_delete(p(_, X, _Y), _),
+	aditi_delete(q(_, X) = _Y, _),
 
-	{ DeleteP =
-		(aditi_top_down pred(_::unused, 1::in, 2::in) is semidet :-
-			true
-		) },
-	aditi_delete(p/3, DeleteP),
-
-	{ DeleteQ =
-		(aditi_top_down func(_::unused, 1::in) = (2::in) is semidet)
-	},
-	aditi_delete(q/2, DeleteQ),
-
 	{ InsertP =
 	    (aditi_bottom_up pred(_::aditi_ui, A1::out, A2::out) is nondet :-
 		( A1 = 1, A2 = 2
@@ -56,6 +45,14 @@
 	aditi_bulk_insert(p/3, InsertP),
 	aditi_bulk_delete(pred p/3, InsertP, foo),
 
+	aditi_bulk_insert(
+		(p(_, X, Y, Z) :-
+			( X = 1, Y = 2, Z = 2
+			; X = 2, Y = 3, Z = 4
+			)
+		)
+	),
+
 	{ InsertQ =
 	    (aditi_bottom_up func(_::aditi_ui, A1::out)
 	    		= (A2::out) is nondet :-
@@ -66,29 +63,31 @@
 	aditi_bulk_delete(q/2, InsertQ),
 	aditi_bulk_delete(func q/2, InsertQ, foo),
 
-	aditi_modify(p(_, X0, Y0) ==> p(_, X0 + 1, Y0 + 1)),
-	aditi_modify((q(_, X0) = Y0) ==> (q(_, X0 + 1) = (Y0 + 1))),
-	aditi_modify(q(_, _X0) ==> _Y0),
+	aditi_bulk_modify(p(_, X0, Y0, _) ==> p(_, X0 + 1, Y0 + 1)),
+	aditi_bulk_modify((q(_, X0, _) = Y0) ==> (q(_, X0 + 1) = (Y0 + 1))),
+	aditi_bulk_modify(q(_, _X0) ==> _Y0),
 
 	{ ModifyP =
-	    (aditi_top_down pred(_::unused, X0::in, Y0::in,
-			_::unused, X::out, Y::out) is semidet :-
+	    (aditi_bottom_up pred(DB::aditi_ui, X0::out, Y0::out,
+			_::unused, X::out, Y::out) is nondet :-
+		p(DB, X0, Y0),
 		X0 = 1,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(p/3, ModifyP),
-	aditi_modify(pred p/3, ModifyP, foo),
+	aditi_bulk_modify(p/3, ModifyP),
+	aditi_bulk_modify(pred p/3, ModifyP, foo),
 
 	{ ModifyQ =
-	    (aditi_top_down pred(_::unused, X0::in, Y0::in,
-			_::unused, X::out, Y::out) is semidet :-
+	    (aditi_bottom_up pred(DB::aditi_ui, X0::out, Y0::out,
+			_::unused, X::out, Y::out) is nondet :-
+		q(DB, X) = Y,
 		X0 = 1,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(q/2, ModifyQ),
-	aditi_modify(func q/2, ModifyQ, foo).
+	aditi_bulk_modify(q/2, ModifyQ),
+	aditi_bulk_modify(func q/2, ModifyQ, foo).
 
 aditi_update_derived_relation -->
 	aditi_insert(anc(_, 1, 2)).	
@@ -98,30 +97,28 @@
 	aditi_insert(q(_, 1)),
 	aditi_insert(q(_) = 2),
 	{ aditi_insert(p(_, 1, 2), 1, _) },
+	{ aditi_delete(p(_, 1, 2), 1, _) },
 
-	aditi_delete(p(_, X, _Y) :- X < 2.0),
-	aditi_delete(q(_, X) = _Y :- X < 2.0),
+	aditi_bulk_delete(p(_, X, _Y) :- X < 2.0),
+	aditi_bulk_delete(q(_, X) = _Y :- X < 2.0),
 
-	aditi_delete(p(_, X) :- X < 2.0),
-	aditi_delete(q(_) = Y :- Y < 2),
+	aditi_bulk_delete(p(_, X) :- X < 2.0),
+	aditi_bulk_delete(q(_) = Y :- Y < 2),
 
-	{ DeleteP =
-		(aditi_top_down pred(_::unused, 2::in) is semidet :-
-			true
-		) },
-	aditi_delete(pred p/3, DeleteP),
-	aditi_delete(pred q/2, DeleteP),
+	{ DeleteP = (aditi_bottom_up pred(_::aditi_ui, 2::out) is nondet) },
+	aditi_bulk_delete(pred p/3, DeleteP),
+	aditi_bulk_delete(pred q/2, DeleteP),
 
 	{ DeleteQ =
-		(aditi_top_down func(_::unused) = (2::in) is semidet)
+		(aditi_bottom_up func(_::unused) = (2::in) is nondet)
 	},
-	aditi_delete(func q/2, DeleteQ),
-	aditi_delete(func p/3, DeleteQ),
+	aditi_bulk_delete(func q/2, DeleteQ),
+	aditi_bulk_delete(func p/3, DeleteQ),
 
 	{ DeleteQ2 =
-		(func(_::unused) = (2::in) is semidet)
+		(func(_::aditi_ui) = (2::out) is nondet)
 	},
-	aditi_delete(func q/2, DeleteQ2),
+	aditi_bulk_delete(func q/2, DeleteQ2),
 
 	{ InsertP =
 	    (aditi_bottom_up pred(_::aditi_ui, A1::out, A2::out) is nondet :-
@@ -152,25 +149,26 @@
 	aditi_bulk_insert(pred q/2, InsertQ),
 	aditi_bulk_delete(func q/2, InsertQ),
 
-	aditi_modify(p(X0, Y0, _) ==> p(X0 + 1, Y0 + 1, _)),
-	aditi_modify((q(_) = Y0) ==> (q(_) = (Y0 + 1))),
-	aditi_modify(q(_, X0, Y0) ==> q(_, X0 + 1, Y0 + 1)),
+	aditi_bulk_modify(p(X0, Y0, _) ==> p(X0 + 1, Y0 + 1, _)),
+	aditi_bulk_modify((q(_) = Y0) ==> (q(_) = (Y0 + 1))),
+	aditi_bulk_modify(q(_, X0, Y0) ==> q(_, X0 + 1, Y0 + 1)),
 
 	{ ModifyP =
-	    (aditi_top_down pred(_::unused, X0::in, Y0::in,
-			_::unused, X::out, Y::out) is semidet :-
+	    (aditi_bottom_up pred(DB::aditi_ui, X0::out, Y0::out,
+			_::unused, X::out, Y::out) is nondet :-
+		p(DB, X0, Y0),
 		X0 = 1.0,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(pred p/3, ModifyP),
+	aditi_bulk_modify(pred p/3, ModifyP),
 
 	{ ModifyQ =
-	    (aditi_top_down func(_::unused, X0::in, Y0::in,
-			_::unused, X::out) = (Y::out) is semidet :-
+	    (aditi_bottom_up func(DB::aditi_ui, X0::out, Y0::out,
+			_::unused, X::out) = (Y::out) is nondet :-
 		X0 = 1,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(func q/2, ModifyQ).
+	aditi_bulk_modify(func q/2, ModifyQ).
 
Index: tests/invalid/aditi_update_mode_errors.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/aditi_update_mode_errors.err_exp,v
retrieving revision 1.2
diff -u -u -r1.2 aditi_update_mode_errors.err_exp
--- tests/invalid/aditi_update_mode_errors.err_exp	1999/07/14 07:03:38	1.2
+++ tests/invalid/aditi_update_mode_errors.err_exp	2000/04/04 02:24:58
@@ -1,10 +1,26 @@
 aditi_update_mode_errors.m:062: In clause for predicate `aditi_update_mode_errors:aditi_update_modes4/2':
+aditi_update_mode_errors.m:062:   warning: variables `_X, _Y' occur more than once in this scope.
+aditi_update_mode_errors.m:062: In clause for predicate `aditi_update_mode_errors:aditi_update_modes4/2':
+aditi_update_mode_errors.m:062:   warning: variables `_X, _Y' occur more than once in this scope.
+aditi_update_mode_errors.m:062: In clause for predicate `aditi_update_mode_errors:aditi_update_modes4/2':
 aditi_update_mode_errors.m:062:   warning: variable `X' occurs only once in this scope.
 aditi_update_mode_errors.m:065: In clause for predicate `aditi_update_mode_errors:aditi_update_modes5/2':
+aditi_update_mode_errors.m:065:   warning: variables `_X, _Y' occur more than once in this scope.
+aditi_update_mode_errors.m:065: In clause for predicate `aditi_update_mode_errors:aditi_update_modes5/2':
+aditi_update_mode_errors.m:065:   warning: variables `_X, _Y' occur more than once in this scope.
+aditi_update_mode_errors.m:065: In clause for predicate `aditi_update_mode_errors:aditi_update_modes5/2':
 aditi_update_mode_errors.m:065:   warning: variable `X' occurs only once in this scope.
 aditi_update_mode_errors.m:102: In clause for predicate `aditi_update_mode_errors:aditi_update_modes10/2':
+aditi_update_mode_errors.m:102:   warning: variable `_X0' occurs more than once in this scope.
+aditi_update_mode_errors.m:102: In clause for predicate `aditi_update_mode_errors:aditi_update_modes10/2':
+aditi_update_mode_errors.m:102:   warning: variable `_X0' occurs more than once in this scope.
+aditi_update_mode_errors.m:102: In clause for predicate `aditi_update_mode_errors:aditi_update_modes10/2':
 aditi_update_mode_errors.m:102:   warning: variable `X0' occurs only once in this scope.
 aditi_update_mode_errors.m:105: In clause for predicate `aditi_update_mode_errors:aditi_update_modes11/2':
+aditi_update_mode_errors.m:105:   warning: variable `_X0' occurs more than once in this scope.
+aditi_update_mode_errors.m:105: In clause for predicate `aditi_update_mode_errors:aditi_update_modes11/2':
+aditi_update_mode_errors.m:105:   warning: variable `_X0' occurs more than once in this scope.
+aditi_update_mode_errors.m:105: In clause for predicate `aditi_update_mode_errors:aditi_update_modes11/2':
 aditi_update_mode_errors.m:105:   warning: variable `X0' occurs only once in this scope.
 aditi_update_mode_errors.m:053: In clause for `aditi_update_modes1((aditi:aditi_di), (aditi:aditi_uo))':
 aditi_update_mode_errors.m:053:   in argument 2 of the inserted tuple of `aditi_insert' of predicate `p/3':
@@ -27,13 +43,13 @@
 aditi_update_mode_errors.m:065:   mode error: variable `X' has instantiatedness `free',
 aditi_update_mode_errors.m:065:   expected instantiatedness was `ground'.
 aditi_update_mode_errors.m:072: In clause for `aditi_update_modes6((aditi:aditi_di), (aditi:aditi_uo))':
-aditi_update_mode_errors.m:072:   in argument 2 of `aditi_delete' of predicate `p/3':
-aditi_update_mode_errors.m:072:   mode error: variable `DeleteP' has instantiatedness `/* unique */(pred((free -> free), (free -> ground), (ground -> ground)) is semidet)',
-aditi_update_mode_errors.m:072:   expected instantiatedness was `(pred(unused, in, in) is semidet)'.
+aditi_update_mode_errors.m:072:   in argument 2 of `aditi_bulk_delete' of predicate `p/3':
+aditi_update_mode_errors.m:072:   mode error: variable `DeleteP' has instantiatedness `/* unique */(pred((free -> free), (free -> ground), (ground -> ground)) is nondet)',
+aditi_update_mode_errors.m:072:   expected instantiatedness was `(pred(in, out, out) is nondet)'.
 aditi_update_mode_errors.m:078: In clause for `aditi_update_modes7((aditi:aditi_di), (aditi:aditi_uo))':
-aditi_update_mode_errors.m:078:   in argument 2 of `aditi_delete' of function `q/2':
-aditi_update_mode_errors.m:078:   mode error: variable `DeleteQ' has instantiatedness `/* unique */(func((free -> free), (free -> ground)) = (ground -> ground) is semidet)',
-aditi_update_mode_errors.m:078:   expected instantiatedness was `(func(unused, in) = in is semidet)'.
+aditi_update_mode_errors.m:078:   in argument 2 of `aditi_bulk_delete' of function `q/2':
+aditi_update_mode_errors.m:078:   mode error: variable `DeleteQ' has instantiatedness `/* unique */(func((free -> free), (free -> ground)) = (ground -> ground) is nondet)',
+aditi_update_mode_errors.m:078:   expected instantiatedness was `(func(in, out) = out is nondet)'.
 aditi_update_mode_errors.m:087: In clause for `aditi_update_modes8((aditi:aditi_di), (aditi:aditi_uo))':
 aditi_update_mode_errors.m:087:   in argument 2 of `aditi_bulk_insert' of predicate `p/3':
 aditi_update_mode_errors.m:087:   mode error: variable `InsertP' has instantiatedness `/* unique */(pred((ground -> ground), (ground -> ground), (free -> ground)) is nondet)',
@@ -53,13 +69,13 @@
 aditi_update_mode_errors.m:105:   have insts `free, unique(1), free',
 aditi_update_mode_errors.m:105:   which does not match any of the modes for function `int:+/2'.
 aditi_update_mode_errors.m:115: In clause for `aditi_update_modes12((aditi:aditi_di), (aditi:aditi_uo))':
-aditi_update_mode_errors.m:115:   in argument 2 of `aditi_modify' of predicate `p/3':
+aditi_update_mode_errors.m:115:   in argument 2 of `aditi_bulk_modify' of predicate `p/3':
 aditi_update_mode_errors.m:115:   mode error: variable `ModifyP' has instantiatedness `/* unique */(pred((free -> free), (free -> ground), (free -> ground), (free -> free), (ground -> ground), (ground -> ground)) is semidet)',
-aditi_update_mode_errors.m:115:   expected instantiatedness was `(pred(unused, in, in, unused, out, out) is semidet)'.
+aditi_update_mode_errors.m:115:   expected instantiatedness was `(pred(in, out, out, unused, out, out) is nondet)'.
 aditi_update_mode_errors.m:125: In clause for `aditi_update_modes13((aditi:aditi_di), (aditi:aditi_uo))':
-aditi_update_mode_errors.m:125:   in argument 2 of `aditi_modify' of function `q/2':
-aditi_update_mode_errors.m:125:   mode error: variable `ModifyQ' has instantiatedness `/* unique */(pred((free -> free), (ground -> ground), (ground -> ground), (free -> free), (ground -> ground), (ground -> ground)) is semidet)',
-aditi_update_mode_errors.m:125:   expected instantiatedness was `(pred(unused, in, in, unused, out, out) is semidet)'.
+aditi_update_mode_errors.m:125:   in argument 2 of `aditi_bulk_modify' of function `q/2':
+aditi_update_mode_errors.m:125:   mode error: variable `ModifyQ' has instantiatedness `/* unique */(pred((free -> free), (ground -> ground), (ground -> ground), (free -> free), (ground -> ground), (ground -> ground)) is nondet)',
+aditi_update_mode_errors.m:125:   expected instantiatedness was `(pred(in, out, out, unused, out, out) is nondet)'.
 aditi_update_mode_errors.m:047: In clause for `anc((aditi:aditi_ui), out, out)':
 aditi_update_mode_errors.m:047:   in argument 2 of clause head:
 aditi_update_mode_errors.m:047:   mode error in unification of `HeadVar__2' and `X'.
Index: tests/invalid/aditi_update_mode_errors.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/aditi_update_mode_errors.m,v
retrieving revision 1.1
diff -u -u -r1.1 aditi_update_mode_errors.m
--- tests/invalid/aditi_update_mode_errors.m	1999/07/13 08:55:07	1.1
+++ tests/invalid/aditi_update_mode_errors.m	2000/04/04 02:24:29
@@ -59,23 +59,23 @@
 	{ aditi_insert(p(_, 1, 2), _, _) }.
 
 aditi_update_modes4 -->
-	aditi_delete(p(_, _X, _Y) :- X < 2).
+	aditi_bulk_delete(p(_, _X, _Y) :- X < 2).
 
 aditi_update_modes5 -->
-	aditi_delete(q(_, _X) = _Y :- X < 2).
+	aditi_bulk_delete(q(_, _X) = _Y :- X < 2).
 
 aditi_update_modes6 -->
 	{ DeleteP =
-		(aditi_top_down pred(_::unused, 1::out, 2::in) is semidet :-
+		(aditi_bottom_up pred(_::unused, 1::out, 2::in) is nondet :-
 			true
 		) },
-	aditi_delete(pred p/3, DeleteP).
+	aditi_bulk_delete(pred p/3, DeleteP).
 
 aditi_update_modes7 -->
 	{ DeleteQ =
-		(aditi_top_down func(_::unused, 1::out) = (2::in) is semidet)
+		(aditi_bottom_up func(_::unused, 1::out) = (2::in) is nondet)
 	},
-	aditi_delete(func q/2, DeleteQ).
+	aditi_bulk_delete(func q/2, DeleteQ).
 
 aditi_update_modes8 -->
 	{ InsertP =
@@ -99,28 +99,28 @@
 	aditi_bulk_delete(func q/2, InsertQ).
 
 aditi_update_modes10 -->
-	aditi_modify(p(_, _X0, Y0) ==> p(_, X0 + 1, Y0 + 1)).
+	aditi_bulk_modify(p(_, _X0, Y0) ==> p(_, X0 + 1, Y0 + 1)).
 
 aditi_update_modes11 -->
-	aditi_modify((q(_, _X0) = Y0) ==> (q(_, X0 + 1) = (Y0 + 1))).
+	aditi_bulk_modify((q(_, _X0) = Y0) ==> (q(_, X0 + 1) = (Y0 + 1))).
 
 aditi_update_modes12 -->
 	{ ModifyP =
-	    (aditi_top_down pred(_::unused, X0::out, Y0::out,
+	    (aditi_bottom_up pred(_::unused, X0::out, Y0::out,
 			_::unused, X::in, Y::in) is semidet :-
 		X0 = 1,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(pred p/3, ModifyP).
+	aditi_bulk_modify(pred p/3, ModifyP).
 
 aditi_update_modes13 -->
 	{ ModifyQ =
-	    (aditi_top_down pred(_::unused, X0::in, Y0::in,
-			_::unused, X::in, Y::in) is semidet :-
+	    (aditi_bottom_up pred(_::unused, X0::in, Y0::in,
+			_::unused, X::in, Y::in) is nondet :-
 		X0 = 1,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(func q/2, ModifyQ).
+	aditi_bulk_modify(func q/2, ModifyQ).
 
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.60
diff -u -u -r1.60 Mmakefile
--- tests/valid/Mmakefile	2000/04/06 05:33:32	1.60
+++ tests/valid/Mmakefile	2000/04/11 05:52:03
@@ -27,6 +27,7 @@
 	instance_unconstrained_tvar.m
 
 OTHER_SOURCES= \
+	aditi_update.m \
 	base_relation.m \
 	base_relation2.m \
 	common_struct_bug.m \
@@ -135,10 +136,6 @@
 	vn_float.m \
 	zero_arity.m
 
-# Code generation is not yet implemented for Aditi updates,
-# so don't attempt to compile to C.
-#	aditi_update.m
-
 # The mode system can't handle the following test cases yet:
 #	assoc_list.m
 #	determinism.m
@@ -233,7 +230,7 @@
 intermod_nested_module2.date: intermod_nested_module2.date0
 intermod_user_equality_nested2.date: intermod_user_equality_nested2.date0
 
-check:	objs aditi_update.err
+check:	objs
 
 objs:	$(OBJS)
 
Index: tests/valid/aditi_update.m
===================================================================
RCS file: /home/mercury1/repository/tests/valid/aditi_update.m,v
retrieving revision 1.1
diff -u -u -r1.1 aditi_update.m
--- tests/valid/aditi_update.m	1999/07/13 08:55:28	1.1
+++ tests/valid/aditi_update.m	2000/03/22 00:42:21
@@ -19,19 +19,18 @@
 	aditi_insert(p(_, 1, 2)),
 	aditi_insert(q(_, 1) = 2),
 
-	aditi_delete(p(_, X, _Y) :- X < 2),
-	aditi_delete(q(_, X) = _Y :- X < 2),
+	aditi_delete(p(_, 1, 2)),
+	aditi_delete(q(_, 1) = 2),
 
-	{ DeleteP =
-		(aditi_top_down pred(_::unused, 1::in, 2::in) is semidet :-
-			true
-		) },
-	aditi_delete(pred p/3, DeleteP),
-
-	{ DeleteQ =
-		(aditi_top_down func(_::unused, 1::in) = (2::in) is semidet)
-	},
-	aditi_delete(func q/2, DeleteQ),
+	aditi_bulk_insert(
+		(p(_, X, Y) :-
+			( X = 1, Y = 2
+			; X = 2, Y = 3
+			)
+		)),
+
+	aditi_bulk_delete(p(_, X, _) :- X < 2),
+	aditi_bulk_delete(q(_, X) = _ :- X < 2),
 
 	{ InsertP =
 	    (aditi_bottom_up pred(_::aditi_ui, A1::out, A2::out) is nondet :-
@@ -42,6 +41,14 @@
 	aditi_bulk_insert(pred p/3, InsertP),
 	aditi_bulk_delete(pred p/3, InsertP),
 
+	aditi_bulk_insert(
+		(p(_, A1, A2) :-
+			( A1 = 1, A2 = 2
+			; A1 = 2, A2 = 3
+			)
+		)
+	),
+
 	{ InsertQ =
 	    (aditi_bottom_up func(_::aditi_ui, A1::out)
 	    		= (A2::out) is nondet :-
@@ -51,29 +58,39 @@
 	    ) },
 	aditi_bulk_insert(func q/2, InsertQ),
 	aditi_bulk_delete(func q/2, InsertQ),
+
+	aditi_bulk_insert(
+		(q(_, A1) = A2 :-
+			( A1 = 1, A2 = 2
+			; A1 = 2, A2 = 3
+			)
+		)
+	),
 
-	aditi_modify(p(_, X0, Y0) ==> p(_, X0 + 1, Y0 + 1)),
-	aditi_modify((p(_, X0, Y0) ==> p(_, X, Y) :-
+	aditi_bulk_modify(p(_, X0, Y0) ==> p(_, X0 + 1, Y0 + 1)),
+	aditi_bulk_modify((p(_, X0, Y0) ==> p(_, X, Y) :-
 			X = X0 + 1,
 			Y = Y0 + 1
 		)),
-	aditi_modify((q(_, X0) = Y0) ==> (q(_, X0 + 1) = (Y0 + 1))),
+	aditi_bulk_modify((q(_, X0) = Y0) ==> (q(_, X0 + 1) = (Y0 + 1))),
 
-	{ ModifyP =
-	    (aditi_top_down pred(_::unused, X0::in, Y0::in,
-			_::unused, X::out, Y::out) is semidet :-
+	{ ModifyP1 =
+	    (aditi_bottom_up pred(DB::aditi_ui, X0::out, Y0::out,
+			_::unused, X::out, Y::out) is nondet :-
+		p(DB, X0, Y0),
 		X0 = 1,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(pred p/3, ModifyP),
+	aditi_bulk_modify(pred p/3, ModifyP1),
 
 	{ ModifyQ =
-	    (aditi_top_down pred(_::unused, X0::in, Y0::in,
-			_::unused, X::out, Y::out) is semidet :-
+	    (aditi_bottom_up pred(DB::aditi_ui, X0::out, Y0::out,
+			_::unused, X::out, Y::out) is nondet :-
+		q(DB, X0) = Y0,
 		X0 = 1,
 		X = X0 + Y0,
 		Y = X0 - Y0
 	    ) },
-	aditi_modify(func q/2, ModifyQ).
+	aditi_bulk_modify(func q/2, ModifyQ).
 
--------------------------------------------------------------------------
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