Code: Select all
1 begin
2 begin
3 begin
3 failI also tried the eight queens demo in 32 bit. That however worked well.
Code: Select all
1 begin
2 begin
3 begin
3 failCode: Select all
delegate
interface array2M{@ItemType} to ar2MCode: Select all
getBackTrackTop = "?GetBackTrackTop@Kernel@VIP@@YAQAVTBackTrackBlock@12@XZ".Code: Select all
getBackTrackTop = "?GetBackTrackTop@Kernel@VIP@@YAQAVTBackTrackBlock@12@XZ".Code: Select all
class btReversion
open core
predicates
addUndoAction : (predicate Undo).
predicates
undoOnFailure_mt : () multi.
end class btReversion
%---
implement btReversion
open core
domains
trailEntry = trailEntry(programControl::stackMark StackMark, predicate Undo).
class facts
trailTree : redBlackTree::tree{multiThread_native::threadID ThreadID, varM{trailEntry*} TrailM} := redBlackTree::emptyUnique().
class predicates
getTrailM : () -> varM{trailEntry*} TrailM.
clauses
getTrailM() = TrailM :-
ThreadId = multiThread_native::getCurrentThreadId(),
if TrailM = redBlackTree::tryLookUp(trailTree, ThreadId) then
else
TrailM = varM::new([]),
trailTree := redBlackTree::insert(trailTree, ThreadId, TrailM)
end if.
clauses
undoOnFailure_mt().
undoOnFailure_mt() :-
TrailM = getTrailM(),
undoOnFailure_fl(TrailM).
class predicates
undoOnFailure_fl : (varM{trailEntry*} TrailM) failure.
clauses
undoOnFailure_fl(TrailM) :-
[trailEntry(StackMark, Undo) | RestTrail] = TrailM:value,
StackMark <= programControl::getBackTrack(),
TrailM:value := RestTrail,
try
Undo()
finally
undoOnFailure_fl(TrailM)
end try.
clauses
addUndoAction(Undo) :-
TrailM = getTrailM(),
StackMark = programControl::getBackTrack(),
TrailM:value := [trailEntry(StackMark, Undo) | TrailM:value].
end implement btReversion
%===
interface array2B{@ItemType} supports array2M{@ItemType}
end interface array2B
%---
class array2B{@ItemType} : array2B{@ItemType}
open core
constructors
new : (positive SizeX, positive SizeY).
constructors
newInitialize : (positive SizeX, positive SizeY, @ItemType InitValue).
constructors
newPointer : (pointer Data, positive SizeX, positive SizeY).
end class array2B
%---
implement array2B{@ItemType}
open core, btReversion
delegate
interface array2M{@ItemType} to ar2M
facts
ar2M : array2M{@ItemType}.
clauses
new(SizeX, SizeY) :-
ar2M := array2M::new(SizeX, SizeY).
clauses
newInitialize(SizeX, SizeY, Init) :-
ar2M := array2M::newInitialize(SizeX, SizeY, Init).
clauses
newPointer(Buffer, SizeX, SizeY) :-
ar2M := array2M::newPointer(Buffer, SizeX, SizeY).
clauses
set(X, Y, Value) :-
OldValue = ar2M:get(X, Y),
ar2M:set(X, Y, Value),
addUndoAction({ :- ar2M:set(X, Y, OldValue) }).
clauses
set(tuple(X, Y), Value) :-
set(X, Y, Value).
clauses
set_optional(tuple(X, Y), some(Value)) :-
set(X, Y, Value).
set_optional(XY, none) :-
ar2M:set_optional(XY, none). %raises exception
clauses
insert(tuple(XY, Value)) :-
set(XY, Value).
clauses
insertList(TupleList) :-
OldAr2M = ar2M:createCopy(),
ar2M:insertList(TupleList),
addUndoAction({ :- ar2M := OldAr2M }).
clauses
insertCollection(TupleCollection) :-
OldAr2M = ar2M:createCopy(),
ar2M:insertCollection(TupleCollection),
addUndoAction({ :- ar2M := OldAr2M }).
clauses
insertEnumerator(TupleEnum_nd) :-
OldAr2M = ar2M:createCopy(),
ar2M:insertEnumerator(TupleEnum_nd),
addUndoAction({ :- ar2M := OldAr2M }).
end implement array2B
%===
implement main
open core
constants
boardSize : positive = 8.
class facts
boardB : array2B{unsigned8} := array2B::new(boardSize, boardSize).
solutionCount : positive := 0.
clauses
run() :-
stdIO::nl(),
solve_nd(0, 0),
fail.
run() :-
stdIO::writeF("Total solutions for a %ux%u board: %u.\n", boardSize, boardSize, solutionCount).
class predicates
show : ().
clauses
show() :-
stdIO::writeF("Solution %u:\n", solutionCount),
foreach Y = std::downTo(boardSize - 1, 0) do
stdIO::writeF("%2u", Y + 1),
foreach X = std::fromTo(0, boardSize - 1) do
Field = if boardB:get(X, Y) = 0 then '.' else 'Q' end if,
stdIO::write(Field)
end foreach,
stdIO::nl()
end foreach,
stdIO::write(' '),
foreach X = std::fromTo(0, boardSize - 1) do
stdIO::write(string::getCharFromValue(string::getCharValue('a') + X))
end foreach,
stdIO::nl(),
stdIO::nl().
class predicates
solve_nd : (positive QueenX, positive QueenY) nondeterm.
clauses
solve_nd(QueenX, QueenY) :-
btReversion::undoOnFailure_mt(), %internally insert a call to undoOnFailure_mt at each backtrack point
boardB:set(QueenX, QueenY, 1),
not(canCaptureHorizontal(0, QueenX, QueenY)),
not(canCaptureDiagonal1(0, QueenX, QueenY)),
not(canCaptureDiagonal2(0, QueenX, QueenY)),
if QueenX = boardSize - 1 then
solutionCount := solutionCount + 1,
show()
else
solve_nd(QueenX + 1, 0)
end if.
solve_nd(QueenX, QueenY) :-
QueenY < boardSize - 1,
solve_nd(QueenX, QueenY + 1).
class predicates
canCaptureHorizontal : (positive N, positive QueenX, positive QueenY) determ.
clauses
canCaptureHorizontal(N, QueenX, QueenY) :-
N < QueenX,
if boardB:get(N, QueenY) = 0 then
canCaptureHorizontal(N + 1, QueenX, QueenY)
end if.
class predicates
canCaptureDiagonal1 : (positive N, positive QueenX, positive QueenY) determ.
clauses
canCaptureDiagonal1(N, QueenX, QueenY) :-
N < QueenX,
N < QueenY,
N1 = N + 1,
if boardB:get(QueenX - N1, QueenY - N1) = 0 then
canCaptureDiagonal1(N1, QueenX, QueenY)
end if.
class predicates
canCaptureDiagonal2 : (positive N, positive QueenX, positive QueenY) determ.
clauses
canCaptureDiagonal2(N, QueenX, QueenY) :-
N < QueenX,
N1 = N + 1,
N1 < boardSize - QueenY,
if boardB:get(QueenX - N1, QueenY + N1) = 0 then
canCaptureDiagonal2(N1, QueenX, QueenY)
end if.
end implement mainCode: Select all
class reversal
open core
predicates
addUndoAction : (predicate UndoAction).
predicates
undo : ().
end class reversal
%------
implement reversal
open core
domains
backtrackEntry = backtrackEntry(bTop Next, tTopP LastTTop, returnAddress ReturnAddress, handle EBP).
bTop = pointer.
tTopP = pointer.
returnAddress = pointer.
domains
undoElement = undoElement(bTop BtEntryP, predicate UndoAction).
%---
class predicates
getBackTrackTop : () -> bTop BTop language c as linknames_vipKernel::getBackTrackTop.
resolve
getBackTrackTop externally
%---
class facts
undoStack : undoElement* := [].
%--
class predicates
setMark : (tTopP LastTTop) -> tTopP MarkedLastTTop.
clauses
setMark(LastTTop) = uncheckedConvert(tTopP, uncheckedConvert(unsignedNative, LastTTop) ++ 1).
%--
class predicates
isMarkNotSet : (tTopP LastTTop) determ.
clauses
isMarkNotSet(LastTTop) :-
uncheckedConvert(unsignedNative, LastTTop) ** 1 = 0.
%---
clauses
addUndoAction(UndoAction) :-
TopBtEntryP = getBackTrackTop(),
undo_walkDown(TopBtEntryP),
undoStack := [undoElement(TopBtEntryP, UndoAction) | undoStack],
if not(memory::isNull(TopBtEntryP)) then
TopBtEntry = uncheckedConvert(backtrackEntry, TopBtEntryP),
backtrackEntry(:LastTTop = LastTTop | _) == TopBtEntry,
MarkedLastTTop = setMark(LastTTop),
memory::copyTo(TopBtEntry, backtrackEntry(:LastTTop = MarkedLastTTop | TopBtEntry))
end if.
%---
clauses
undo() :-
TopBtEntryP = getBackTrackTop(),
undo_walkDown(TopBtEntryP).
class predicates
undo_walkDown : (bTop WalkerBtEntryP).
clauses
undo_walkDown(WalkerBtEntryP) :-
if memory::isNull(WalkerBtEntryP) then
undo_all()
else
backtrackEntry(:Next = NextBtEntryP, :LastTTop = LastTTop | _) == uncheckedConvert(backtrackEntry, WalkerBtEntryP),
if isMarkNotSet(LastTTop) then
undo_allAbove(WalkerBtEntryP),
undo_walkDown(NextBtEntryP)
end if
end if.
class predicates
undo_allAbove : (bTop WalkerBtEntryP).
clauses
undo_allAbove(WalkerBtEntryP) :-
if [undoElement(UndoEntryP, UndoAction) | RestUndoStack] = undoStack and UndoEntryP <= WalkerBtEntryP then
try
UndoAction()
catch TraceID do
continueUndoException(TraceID)
end try,
undoStack := RestUndoStack,
undo_allAbove(WalkerBtEntryP)
end if.
class predicates
undo_all : ().
clauses
undo_all() :-
if [undoElement(_UndoEntryP, UndoAction) | RestUndoStack] = undoStack then
try
UndoAction()
catch TraceID do
continueUndoException(TraceID)
end try,
undoStack := RestUndoStack,
undo_all()
end if.
class predicates
continueUndoException : (exception::traceId TraceID) erroneous.
clauses
continueUndoException(TraceID) :-
exception::continue_unknown(TraceID, "Undo action raised exception").
end implement reversal
%======
implement main
class facts
myFact : string := "original".
class predicates
show : (string Mark).
clauses
show(Mark) :-
reversal::undo(),
stdio::writef("(%s) BackTrackPoints=%, myFact=%p\n", Mark, programControl::getBackTrackPoints(), myFact).
clauses
run() :-
show("1"),
OldMyFact = myFact,
myFact := "changed",
reversal::addUndoAction({ :- myFact := OldMyFact }),
show("2"),
fail.
/*
run() :-
show("3"),
fail.
*/
run() :-
show("4").
end implement main
goal
console::runUtf8(main::run).Code: Select all
... and UndoEntryP <= WalkerBtEntryP then