/* Rule 2: If the PC is not zero, then simulating the current state can be performed by simulating the current instruction and then simulating the new state that results from that instruction. The result of simulating the new state is the result for simulating the current state. */ simulate( state(PC, CurrentMemory, Program),Memory ) :- integer(PC), simulate_one_instruction( state(PC, CurrentMemory , Program), state( NewPC , NewMemory, Program) ), simulate( state(NewPC, NewMemory, Program), Memory), not PC=0. /* Rule 5: Performing an add X Y instruction means adding the value stored at location X to the value stored at location Y and putting the result in location Y. The program counter is incremented by 1. */ perform_instruction(instruction(add, X, Y), PC, CurrentMemory, NewPC, NewMemory) :- integer(PC), integer(X), integer(Y), plus(PC, 1, NewPC), extract_memory(X, CurrentMemory, ContentsAtX), extract_memory(Y, CurrentMemory, ContentsAtY), integer(ContentsAtX), integer(ContentsAtY), plus(ContentsAtX,ContentsAtY,NewValue), change_memory(Y, CurrentMemory, NewValue, NewMemory). /* Rule 9: Performing a jump_on_zero X Y instruction means that if the contents of location Y are zero, then the program counter is changed to X. */ perform_instruction(instruction(jump_on_zero, X, Y), PC, CurrentMemory, NewPC, CurrentMemory) :- integer(X), integer(Y), integer(PC), extract_memory(Y,CurrentMemory,ContentsAtY), ContentsAtY = 0, plus(X,0,NewPC). /* Rule 10: Performing a jump_on_zero X Y instruction means that if the contents of location Y are not zero, then the program counter is incremented. */ perform_instruction(instruction(jump_on_zero, X, Y), PC, CurrentMemory, NewPC, CurrentMemory) :- integer(X), integer(Y), integer(PC), extract_memory(Y,CurrentMemory,ContentsAtY), not ContentsAtY = 0, plus(PC,1,NewPC). /* Rule 13: If the memory location is 1, then the first memory cell is the sought after memory cell. */ extract_memory(1, CurrentCell:RestOfMemory, CurrentCell) :- . /* Rule 17: If we want to change a memory location that is not 1 in a memory list that has only one cell and the new value is to be 0, then the memory is left unchanged. */ change_memory(Location, CurrentCell:nil, 0, CurrentCell:nil) :- integer(Location), not Location = 1. /* Rule 18: If we want to change a memory location that is not 1 in a memory list that has only one cell and the new value is not 0, then we want to handle the current memory list as if it had an extra 0 at its end. We do this by looking at the result of adding into a memory list containing just one 0 at a location that is one less than the current memory location. When we see the memory list that results from this change, we then append to it the one cell in the original memory list. */ change_memory(Location, CurrentCell:nil, NewValue, CurrentCell:NewMemory) :- integer(Location), integer(NewValue), not Location = 1, not NewValue = 0, plus(NewLocation,1,Location), change_memory(NewLocation, 0:nil, NewValue, NewMemory). /* Rule 19: If we want to change a memory location that is not 1 in a memory list that has more than one cell, then we do this by decreasing the current memory location by 1 and removing the first element from the memory list. Once we find the result of changing the new location in the new memory list, we append the first cell from the original memory list to that result to get the new memory list that represents this change in the original list. */ change_memory(Location, CurrentCell:RestOfMemory, NewValue, CurrentCell:NewMemory ) :- integer(Location), integer(NewValue), not Location = 1, not RestOfMemory = nil, plus(NewLocation,1,Location), change_memory(NewLocation, RestOfMemory, NewValue, NewMemory).