logo
TurboProlog / Документация / TOM_2

Реализация трассировки

Если, читая все это, вы заглянули в действительный исходный код, то

вы заметили, что там, где мы беседовали о call, исходный код имел имя

trace_call. Мы можем узнать об этом несколько больше, хотя и немного.

В интерпретаторе есть опция, выполняемая во время компилирования,

для определения, должна ли она включать возможность трассировки:

ifdef implement_trace

predicates

showtrace(STRING,STRING,aTermList)

nondeterm trace_call(STRING,aTermList)

nondeterm report_redo(STRING,aTermList)

clauses

trace_call(PID,ATermList):-

not(traceflag),!,

call(PID,ATermList).

trace_call(PID,ATermList):-

showtrace("CALL: ",PID,ATermList),

call(PID,ATermList),

report_redo(PID,ATermList),

showtrace("RETURN: ",PID,ATermList).

trace_call(PID,ATermList):-

showtrace("FAIL: ",PID,ATermList),

fail.

report_redo(_,_).

report_redo(PID,ATermList):-

showtrace("REDO: ",PID,ATermList),

fail.

showtrace(STR,PID,ATermList):-

shiftwindow(OLD),shiftwindow(3),

attribute(15),write(STR),attribute(7),

wterm("write",cmp(PID,ATermList)),nl,

shiftwindow(OLD).

elsedef % call the predicate "call" directly

constants

trace_call = call

enddef

Если трассировка не включена, то то исходная текстовая строка

"trace_call" заменяется на на "call". Многих пользователей привлекает

способность трассировки, имеющаяся в традиционном Прологе, но как мы ви-

дим, включить ее несложно. Задача заключается во вставке какого-нибудь

печатающего терма между unify_body и call. Это также послужило причиной

нашего совета использовать данные предикаты раздельно.

Если включен traceflag, вызов trace_call введет второе предложение

предиката. Появится знакомый CALL: сообщение и вызовет имющийся в вопросе

предикат.

Если не выполняется это второе предложение, то третье предложение

trace_call отразит невыполнение с помощью обычного FAIL:сообщения, а за-

тем прекратит работу. В противном случае первый вызов report_redo будет

выполнен, и перед возвратом к unify_body появится RETURN:сообщение.

Если не выполнено неотсечение в каком-либо месте, подчиненном данно-

му, то возврат задействует второе предложение report_redo, которое выве-

дет знакомое REDO:сообщение, а затем не выполнится, вызвав таким образом

call.

Единственный недостаток этого решения заключается в том, что в про-

цессе трассировки не будет выведен assert. Трассировку assert можно вклю-

чить, заменив вызов handle_assert на трассирующий фрагмент, но это пока-

зывает, насколько плохо отделять assert от теории, используемой в Проло-

ге. asert требует специального управления, которое, в свою очередь, тре-

бует дальнейшего специального управления и т.д. и т.д. до бесконечности.