Files
mercury/tests/structure_reuse/interpret.m
Zoltan Somogyi c03b11ca48 Update the style of more test cases.
And updated expected outputs for changed line numbers.
2021-07-27 19:29:21 +10:00

104 lines
2.8 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%
% A regression test.
% This tests a case where the compiler marked cells as being compile time
% garbage collectable, where references to that cell existed in other
% data structures.
%---------------------------------------------------------------------------%
:- module interpret.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module exception.
:- import_module list.
:- import_module map.
:- import_module float.
:- import_module int.
:- import_module require.
:- type element
---> float(float)
; int(int).
:- type operation
---> addf
; addi
; float(float)
; lookup
; pop.
:- type stack == list(element).
:- type env == map(int, element).
main(!IO) :-
Env = map.set(map.init, 1, int(5)),
Stack0 = [int(1)],
Ops = [lookup, float(3.14)],
interpret(Ops, Env, Stack0, Stack1),
% This list must be of at least length two to as the first cell
% is correctly marked as not being cgc'able.
( if Stack1 = [float(_), int(X0)] then
X = X0
else
error("incorrect stack")
),
% XXX If int(X0) is incorrectly being marked as cgc'able,
% then P will reuse it's memory and hence the later map.lookup
% will return int(3) instead of int(5).
P = int(3),
io.write_line(P, !IO),
map.lookup(Env, 1, Q),
( if Q = int(X) then
io.write_string("Element of map hasn't changed.\n", !IO)
else
io.write_string("BEEP! BEEP! Map changed!!!.\n", !IO)
).
:- pred interpret(list(operation)::in, env::in, stack::in, stack::out) is det.
interpret([], _, Stack, Stack).
interpret([Op | Ops], Env, Stack0, Stack) :-
do_op(Op, Env, Stack0, Stack1),
interpret(Ops, Env, Stack1, Stack).
:- pred do_op(operation::in, env::in, stack::in, stack::out) is det.
do_op(float(F), _Env, Stack, [float(F) | Stack]).
do_op(addi, _Env, Stack0, Stack) :-
( if Stack0 = [int(A), int(B) | Stack1] then
Stack = [int(A+B) | Stack1]
else
throw(Stack0)
).
do_op(addf, _Env, Stack0, Stack) :-
( if Stack0 = [float(A), float(B) | Stack1] then
Stack = [float(A+B) | Stack1]
else
error("addi: wrong arguments")
).
do_op(lookup, Env, Stack0, Stack) :-
( if Stack0 = [int(Loc) | Stack1] then
% Here we create an alias between the Env variable,
% and the elements in the stack.
map.lookup(Env, Loc, Element),
Stack = [Element | Stack1]
else
error("lookup: wrong arguments")
).
do_op(pop, _Env, Stack0, Stack) :-
( if Stack0 = [_ | Stack1] then
Stack = Stack1
else
error("pop: no arguments on the stack")
).