mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-25 14:24:11 +00:00
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.
84 lines
3.1 KiB
Mathematica
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;
|
|
").
|