mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 15:26:31 +00:00
Estimated hours taken: 0.5 Branches: main Wrap the definitions of the standard library's stack/1 and bag/1 types in notag wrappers. This prevents problems with overlapping instances when they are used in type class instance definitions and in the case of bag/1 makes it usable in such definitions (the current definitions does not conform to what is allowed in instance heads under the current system.) This change does mean that the source code for these modules is a little more verbose, but this is outweighed by the fact that the behaviour with instances is much less surprising than it was. library/bag.m: library/stack.m: Define these types using notag wrappers rather than equivalence types.
160 lines
4.6 KiB
Mathematica
160 lines
4.6 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1994-1995, 1997-1999, 2005-2006 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.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: stack.m.
|
|
% Main author: fjh.
|
|
% Stability: high.
|
|
%
|
|
% This file contains a `stack' ADT.
|
|
% Stacks are implemented here using lists.
|
|
%
|
|
%--------------------------------------------------------------------------%
|
|
|
|
:- module stack.
|
|
:- interface.
|
|
:- import_module list.
|
|
|
|
%--------------------------------------------------------------------------%
|
|
|
|
:- type stack(T).
|
|
|
|
% `stack.init(Stack)' is true iff `Stack' is an empty stack.
|
|
%
|
|
:- pred stack.init(stack(T)::out) is det.
|
|
:- func stack.init = stack(T).
|
|
|
|
% `stack.is_empty(Stack)' is true iff `Stack' is an empty stack.
|
|
%
|
|
:- pred stack.is_empty(stack(T)::in) is semidet.
|
|
|
|
% `stack.is_full(Stack)' is intended to be true iff `Stack'
|
|
% is a stack whose capacity is exhausted. This implementation
|
|
% allows arbitrary-sized stacks, so stack.is_full always fails.
|
|
%
|
|
:- pred stack.is_full(stack(T)::in) is semidet.
|
|
|
|
% `stack.push(Stack0, Elem, Stack)' is true iff `Stack' is
|
|
% the stack which results from pushing `Elem' onto the top
|
|
% of `Stack0'.
|
|
%
|
|
:- pred stack.push(stack(T)::in, T::in, stack(T)::out) is det.
|
|
:- func stack.push(stack(T), T) = stack(T).
|
|
|
|
% `stack.push_list(Stack0, Elems, Stack)' is true iff `Stack'
|
|
% is the stack which results from pushing the elements of the
|
|
% list `Elems' onto the top of `Stack0'.
|
|
%
|
|
:- pred stack.push_list(stack(T)::in, list(T)::in, stack(T)::out) is det.
|
|
:- func stack.push_list(stack(T), list(T)) = stack(T).
|
|
|
|
% `stack.top(Stack, Elem)' is true iff `Stack' is a non-empty
|
|
% stack whose top element is `Elem'.
|
|
%
|
|
:- pred stack.top(stack(T)::in, T::out) is semidet.
|
|
|
|
% `stack.top_det' is like `stack.top' except that it will
|
|
% call error/1 rather than failing if given an empty stack.
|
|
%
|
|
:- pred stack.top_det(stack(T)::in, T::out) is det.
|
|
:- func stack.top_det(stack(T)) = T.
|
|
:- func stack.det_top(stack(T)) = T.
|
|
|
|
% `stack.pop(Stack0, Elem, Stack)' is true iff `Stack0' is
|
|
% a non-empty stack whose top element is `Elem', and `Stack'
|
|
% the stack which results from popping `Elem' off `Stack0'.
|
|
%
|
|
:- pred stack.pop(stack(T)::in, T::out, stack(T)::out) is semidet.
|
|
|
|
% `stack.pop_det' is like `stack.pop' except that it will
|
|
% call error/1 rather than failing if given an empty stack.
|
|
%
|
|
:- pred stack.pop_det(stack(T)::in, T::out, stack(T)::out) is det.
|
|
:- pred stack.det_pop(stack(T)::in, T::out, stack(T)::out) is det.
|
|
|
|
% `stack.depth(Stack, Depth)' is true iff `Stack' is a stack
|
|
% containing `Depth' elements.
|
|
%
|
|
:- pred stack.depth(stack(T)::in, int::out) is det.
|
|
:- func stack.depth(stack(T)) = int.
|
|
|
|
%--------------------------------------------------------------------------%
|
|
%--------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module require.
|
|
|
|
%--------------------------------------------------------------------------%
|
|
|
|
:- type stack(T)
|
|
---> stack(list(T)).
|
|
|
|
stack.init(stack([])).
|
|
|
|
stack.is_empty(stack([])).
|
|
|
|
stack.is_full(_) :-
|
|
semidet_fail.
|
|
|
|
stack.push(stack(Elems), Elem, stack([Elem | Elems])).
|
|
|
|
stack.push_list(Stack, [], Stack).
|
|
stack.push_list(Stack0, [Elem | Elems], Stack1) :-
|
|
stack.push(Stack0, Elem, Stack2),
|
|
stack.push_list(Stack2, Elems, Stack1).
|
|
|
|
stack.top(stack([Elem | _]), Elem).
|
|
|
|
stack.top_det(Stack, Elem) :-
|
|
(
|
|
Stack = stack([Elem | _])
|
|
;
|
|
Stack = stack([]),
|
|
error("stack.top_det: top of empty stack")
|
|
).
|
|
|
|
stack.pop(stack([Elem | Elems]), Elem, stack(Elems)).
|
|
|
|
stack.pop_det(Stack0, Elem, Stack) :-
|
|
(
|
|
Stack0 = stack([Elem | Elems]),
|
|
Stack = stack(Elems)
|
|
;
|
|
Stack0 = stack([]),
|
|
error("stack.pop_det: pop from empty stack")
|
|
).
|
|
|
|
stack.det_pop(Stack0, Elem, Stack) :-
|
|
stack.pop_det(Stack0, Elem, Stack).
|
|
|
|
stack.depth(stack(Elems), Depth) :-
|
|
list.length(Elems, Depth).
|
|
|
|
%--------------------------------------------------------------------------%
|
|
%--------------------------------------------------------------------------%
|
|
% Ralph Becket <rwab1@cl.cam.ac.uk> 29/04/99
|
|
% Function forms added.
|
|
|
|
stack.init = S :-
|
|
stack.init(S).
|
|
|
|
stack.push(S1, X) = S2 :-
|
|
stack.push(S1, X, S2).
|
|
|
|
stack.push_list(S1, Xs) = S2 :-
|
|
stack.push_list(S1, Xs, S2).
|
|
|
|
stack.top_det(S) = X :-
|
|
stack.top_det(S, X).
|
|
|
|
stack.det_top(S) = X :-
|
|
stack.top_det(S, X).
|
|
|
|
stack.depth(S) = N :-
|
|
stack.depth(S, N).
|