%Simuliert eine URM-Berechnung bis zu einem gewissen Zeitpunkt.
%Eingabe Programm: [[1,[z,3]],[2,[j,4,5,2]],[3,[t,2,4]]]:
%[Zeilennummer, [Befehlstyp, Registerliste]]
%Repräsentation Zustand: [3,[[1,4],[2,5],[3,0]]]:
%[Aktive Zeile, [[Registerindex,Inhalt],...]]
%Sieht brauchbar aus.

%leeres programm
next_state(X,[],X).

%auf stopp folgt stopp...
next_state(stop,_,stop).

%nachfolger
next_state([X1,Reg1],P,[X2,Reg2]):-
	member([X1,Com],P),
	Com=[s,I],
	member([I,Cont],Reg1),
	X2 is X1+1,
	delete(Reg1,[I,Cont],Regzw),
	ContNeu is Cont+1,
	Reg2=[[I,ContNeu]|Regzw].

%nullbefehl
next_state([X1,Reg1],P,[X2,Reg2]):-
	member([X1,Com],P),
	Com=[z,I],
	member([I,Cont],Reg1),
	X2 is X1+1,
	delete(Reg1,[I,Cont],Regzw),
	Reg2=[[I,0]|Regzw].

%sprung, falls bedingung erfüllt
next_state([X1,Reg1],P,[Z,Reg1]):-
	member([X1,Com],P),
	Com=[j,R1,R2,Z],
	member([R1,Cont1],Reg1),
	member([R2,Cont1],Reg1).

%sprung, falls bedingung nicht erfüllt
next_state([X1,Reg1],P,[X2,Reg1]):-
	member([X1,Com],P),
	Com=[j|_],
	X2 is X1+1.

%transferbefehl
next_state([X1,Reg1],P,[X2,Reg2]):-
	X2 is X1+1,
	member([X1,Com],P),
	Com=[t,Source,Target],
	member([Source,Cont1],Reg1),
	member([Target,Cont2],Reg1),
	delete(Reg1,[Target,Cont2],Regzw),
	Reg2=[[Target,Cont1]|Regzw].

% falls nichts funktioniert, gibt es keinen befehl mit dem
% entsprechenden index, in diesem fall stoppe.
next_state(_,_,stop).


% execute(P,Anf,Time,Ber) führt Programm P mit Anfangszustand Anf für
% Time viele Schritte aus und nennt die Berechnung Ber.

execute(_,Anf,0,[Anf]):-nl,write(timeout),nl,nl.
execute(P,Anf,Time,[Anf|Rest]):-
	not(Time=inf),
	T is Time-1,
	next_state(Anf,P,NextState),
	Anf=[I,Cont],
	sort(Cont,SortCont),
	nl,
	write([I,SortCont]),
	execute(P,NextState,T,Rest).
execute(_,_,_,_):-nl,write(stop),nl,nl.

% mit Zeitlimit "inf" läuft die Maschine bis zum Stoppzustand, falls der
% eintritt, sonst bis der Speicher überfließt.

execute(P,Anf,inf,J,[Anf|Rest]):-
	JNeu is J+1,
	next_state(Anf,P,NextState),
	Anf=[I,Cont],
	sort(Cont,SortCont),
	nl,
	write([I,SortCont]),
	execute(P,NextState,inf,JNeu,Rest).
execute(_,_,_,L,_):-nl,write(stop),nl,write('Laufzeit:'),write(L),nl,nl.




% endresult(P,Anf,Time,Ber) gibt den Zustand nach Time vielen Schritten
% aus. (Wenn die Berechnung vorher stoppt, dann den letzten Zustand vor
% dem Stopp.)

endresult(P,Anf,Time,[Z,End],stop):-
	execute(P,Anf,Time,Ber),
	last_act(Ber,[Z,Endzw]),
	sort(Endzw,End).

endresult(P,Anf,Time,[Z,End],nostop):-
	execute(P,Anf,Time,Ber),
	reverse(Ber,[[Z,Endzw]|_]),
	sort(Endzw,End).


%last_act sucht den letzten nicht-stop-zustand
last_act([X],X):-not(X=stop).
last_act([X|[stop|_]],X).
last_act([_|Rest],Y):-last_act(Rest,Y).







