Files
mercury/extras/references/reference.m
Warwick Harvey 9cbccbd5dc This change adds a new extras directory, "references".
Estimated hours taken: 70 (plus whatever pets spent when he wrote the
original version of this)

This change adds a new extras directory, "references".  This directory
contains two impure reference type modules and a module that allows scoped
non-backtrackable update, along with examples of using them and tests.
These modules are intended to be useful when HAL is retargetted to Mercury,
for implementing global variables (backtracking and non-backtracking), and
may also be useful for the debugger.

In order to implement these features, a new memory zone "global heap" was
added to the runtime system, for a heap which is not reclaimed on failure,
along with a pair of functions for copying terms to this heap.

runtime/mercury_deep_copy.c:
runtime/mercury_deep_copy.h:
	Added two functions, MR_make_permanent() and
	MR_make_partially_permanent(), which essentially do a deep copy of a
	term to the global heap.
	(In conservative GC grades, these functions actually do nothing).

runtime/mercury_engine.c:
runtime/mercury_engine.h:
	Added fields global_heap_zone and e_global_hp (for the global heap
	and its heap pointer) to the MR_mercury_engine_struct, along with
	appropriate initialisation, etc.
	Defined MR_heap_zone, MR_solutions_heap_zone, and
	MR_global_heap_zone for convenient access to the corresponding field
	of the relevant Mercury engine.

runtime/mercury_memory.c:
	Added code for handling the size and zone size of the global heap.

runtime/mercury_regorder.h:
runtime/mercury_regs.h:
	Defined MR_global_hp (the global heap pointer for general use),
	along with corresponding other changes.

runtime/mercury_wrapper.c:
runtime/mercury_wrapper.h:
	Added declarations and initialisation of the size and zone_size of
	the global_heap.
	Added an entry for MR_GLOBAL_HP_RN to print_register_usage_counts()
	(plus missing entries for MR_SOL_HP_RN, MR_MIN_HP_REC and
	MR_MIN_SOL_HP_REC).

New files:

extras/references/Mmakefile:
	Mmakefile for building and testing these modules.

extras/references/README:
	Description of contents of this directory.

extras/references/global.m:
	A wrapper module for building a library containing the nb_reference,
	reference and scoped_update modules.

extras/references/nb_reference.m:
	Implements references which are not backtracked on failure.

extras/references/reference.m:
	Implements references which *are* backtracked on failure.

extras/references/scoped_update.m:
	Allows nested scoping of non-backtracking references.

extras/references/samples/Mmakefile:
extras/references/samples/max_of.m:
extras/references/samples/max_test.exp:
extras/references/samples/max_test.m:
	An example of using a non-backtracking reference (to find the
	maximum of the solutions generated by a predicate), with tests.

extras/references/tests/Mmakefile:
extras/references/tests/ref_test.exp:
extras/references/tests/ref_test.m:
	Some tests of references (backtracking and non-backtracking) and
	scoping.
1998-06-18 04:30:48 +00:00

84 lines
3.1 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1998 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.
%-----------------------------------------------------------------------------%
%
% File : reference.m
% Authors : pets (Peter Schachte)
% Stability : low
% Purpose : A backtrackably modifiable storage type
%
% This module defines a type which is, in essence, a ``box'' into which you
% can put any term, and later destructively replace the contents with
% something else. The store module in the standard library provides a clean
% way to do exactly the same thing; the difference is that the reference
% module allows you to do it without threading a store through your code. The
% price for this convenience is that you must mark all predicates that create
% or modify a reference, and all the predicates that call them, and so on, as
% impure. This is probably more inconvenient than just threading the store
% through your code, so this module should probably only be used in
% exceptional circumstances.
%
% This module is implemented using the trailing features described in the
% "Trailing" subsection of the "C interface" section of the "Pragmas" chapter
% of the Mercury Language Reference Manual. This means that in order to use
% this module, you *must* compile with the --use-trail switch. The easiest
% way to do this is to include the line
%
% GRADEFLAGS=--use-trail
%
% in your Mmakefile.
:- module reference.
:- interface.
% A backtrackably destructively modifiable reference type.
:- type reference(T).
% Create a new reference given a term for it to (initially) refer to.
:- impure pred new_reference(T::in, reference(T)::out) is det.
% Get the value currently referred to by a reference.
:- semipure pred value(reference(T)::in, T::out) is det.
% (backtrackably) modify a reference to refer to a new object.
:- impure pred update(reference(T)::in, T::in) is det.
:- implementation.
% This type is implemented in C.
:- type reference(T) ---> reference(c_pointer).
:- pragma c_header_code("#include ""mercury_trail.h""").
:- pragma c_header_code("
typedef struct {
void *value;
MR_ChoicepointId id;
} ME_Reference;
").
:- pragma inline(new_reference/2).
:- pragma c_code(new_reference(X::in, Ref::out), will_not_call_mercury, "
incr_hp(Ref, (sizeof(ME_Reference) + sizeof(Word) - 1) / sizeof(Word));
((ME_Reference *) Ref)->value = (void *) X;
((ME_Reference *) Ref)->id = MR_current_choicepoint_id();
").
:- pragma inline(value/2).
:- pragma c_code(value(Ref::in, X::out), will_not_call_mercury, "
X = (Word) ((ME_Reference *) Ref)->value;
").
:- pragma inline(update/2).
:- pragma c_code(update(Ref::in, X::in), will_not_call_mercury, "
ME_Reference *ref = (ME_Reference *) Ref;
if (ref->id != MR_current_choicepoint_id()) {
MR_trail_current_value((Word *) (&ref->value));
MR_trail_current_value((Word *) (&ref->id));
ref->id = MR_current_choicepoint_id();
}
ref->value = (void *) X;
").