如何确定Prolog是否执行尾部调用优化

如何确定Prolog是否执行尾部调用优化,prolog,tail-recursion,dcg,tail-call-optimization,Prolog,Tail Recursion,Dcg,Tail Call Optimization,使用SWI Prolog(Win x64)的开发版本, 我为a编写了一个DCG谓词(因此所有外部谓词都没有选择点): read_标记(解析器(语法、表), lexer(dfa DFAIndex,last_accept-lastapt,chars-Chars0), 令牌)--> ([输入], { dfa:当前(表格、DFAIndex、dfa), 字符和代码(输入、字符、代码), dfa:查找边(表、dfa、代码、TargetIndex) } ->{表:项(dfa_表,表,TargetIndex,T

使用SWI Prolog(Win x64)的开发版本, 我为a编写了一个DCG谓词(因此所有外部谓词都没有选择点):

read_标记(解析器(语法、表),
lexer(dfa DFAIndex,last_accept-lastapt,chars-Chars0),
令牌)-->
([输入],
{
dfa:当前(表格、DFAIndex、dfa),
字符和代码(输入、字符、代码),
dfa:查找边(表、dfa、代码、TargetIndex)
}
->{表:项(dfa_表,表,TargetIndex,TargetDFA),
dfa:接受(TargetDFA,接受),
原子浓度(Chars0,Char,Chars),
NewState=lexer(dfa TargetIndex,
最后的接受,
字符(字符)
},
read_标记(解析器(语法、表)、NewState、标记)
;   {
(LastAccept\=无
->令牌=lastapt-Chars0
;(接地(输入)
->一次(符号:按\类型\名称(表、错误、索引等)),
尝试恢复输入(输入、失败输入、输入),
输入=[FailedInput | InputR],
格式(atom(错误),“~w”,[FailedInput]),
令牌=索引错误
;一次(符号:按_类型_名称(表、eof、索引等)),
令牌=索引-“”
)
)
}
).
现在大量使用
(;)
->
,我想知道SWI-Prolog是否可以使用尾部调用优化来优化递归
读取令牌(解析器(语法、表)、新闻状态、令牌)
, 或者如果我必须手动将谓词拆分为几个子句。
我只是不知道如何找出解释器的作用,尤其是知道在运行调试器时禁用了TCO。

为了回答您的问题,我首先寻找可能会阻止最后一次调用优化的“琐碎”目标。如果找到一些:

; ( ground(Input) -> once(symbol:by_type_name(Tables, error, Index, _)), try_restore_input(Input, FailedInput, InputR), Input = [FailedInput | InputR], format(atom(Error), '~w', [FailedInput]), Token = Index-Error ; once(symbol:by_type_name(Tables, eof, Index, _)), Token = Index-'' ) ad 1)这是您最可能正在寻找的递归案例。在这里,一切似乎都很好

广告2,3)上面已经讨论过,也许你想交换目标

ad 4)这是DCGs中处理
{}//1
的精确、稳定方式的一种效果。作为经验法则:实施者更喜欢坚定,而不是争取LCO的稳定性。请参阅:

还请注意,这不仅仅是调用框架的简单重用。有很多与垃圾收集的交互。为了克服SWI中的所有这些问题,需要额外的GC相

有关更多信息,请参阅中的微小基准测试

所以最后回答你的问题:你的规则可能会被优化;假设在递归目标之前没有剩余的选择点


还有一种真正的低层次方法。我从不将此用于代码开发:
vm\u list
。清单最终显示了SWI是否考虑LCO(没有提供选择点)。
i\u call
i\u callm
将永远不会执行LCO。只有
i_depart
可以。在:
142 i_出发(读取令牌/5)

?-vm_列表(读取_令牌)。 ======================================================================== 读取令牌/5 ======================================================================== 0 s_virgin 1 i_出口 ---------------------------------------- 第1条((0x1cc4710)): ---------------------------------------- 0 h_函子(解析器/2) 2 h_firstvar(5) 4 h_firstvar(6) 6小时流行音乐 7 h_函子(lexer/3) 9 h_函子((-)/2) 11 h_const(dfa) 13 h_firstvar(7) 15小时流行音乐 16 h_函子((-)/2) 18小时常数(最后一次接受) 20 h_firstvar(8) 22小时流行音乐 23 h_函数((-)/2) 25小时常数(chars) 27 h_firstvar(9) 29小时流行音乐 30我进去 31 c_ifthenelse(26118) 34 b_统一_变量(3) 36小时名单(10,11) 39 b_统一_出口 40 b_var(6) 42 b_var(7) 44 b_firstvar(12) 46 i_callm(dfa,dfa:current/3) 49 b_var(10) 51 b_firstvar(13) 53 b_firstvar(14) 55 i_呼叫(字符和代码/3) 57 b_var(6) 59 b_var(12) 61 b_var(14) 63 b_firstvar(15) 65 i_callm(dfa,dfa:find_edge/4) 68 b_统一fv(16,11) 71 c_切口(26) 73 b_常数(dfa_表) 75 b_var(6) 77 b_var(15) 79 b_firstvar(17) 81 i_callm(表,表:项目/4) 84 b_var(17) 86 b_firstvar(18) 88 i_callm(dfa,dfa:accept/2) 91 b_var(9) 93 b_var(13) 95 b_firstvar(19) 97 i_呼叫(atom_concat/3) 99 b_unified_firstvar(20) 101 b_函子(lexer/3) 103 b_函子((-)/2) 105 b_const(dfa) 107 b_argvar(15) 109 b_pop 110 b_函子((-)/2) 112 b_const(最后接受) 114 b_argvar(18) 116 b_pop 117 b_函数((-)/2) 119 b_const(chars) 121 b_argvar(19) 123 b_pop 124 b_统一_出口 125 b___fv(21,16) 128 b_函子(解析器/2) 130 b_argvar(5) 132 b_argvar(6) 134 b_pop 135 b_var(20) 137 b_var2 138 b_var(21) 140 b_变量(4) 142 i_出发(读取令牌/5) 144 c_var_n(22,2) 147 c_var_n(24,2) 150 c_jmp(152) 152 c_ifthenelse(27,28) 155 b_var(8) 157 b_const(无) 159 i_呼叫(\=)/2) 161 c_切口(27) 163 b_统一变量(2) 165 h_函子((-)/2) 167 h_var(8) 169 h_变量(9) 171 h_pop 172 b_统一_出口 173 c_变量(10) 175 c_var_n(22,2) 178 c_var_n(24,2) 181 c_jmp(101) 183 c_ifthenelse(28,65) 186 b_firstvar(10) 188 i_呼叫(地面/1) 190 c_切口(28) 192 b_函子((:)/2) 194 b_const(符号) 196 b_rfunctor(按类型和名称/4) 198 b_argvar(6) 200 b_常数(错误) 202 b_argfirstvar(22) 204 b_void 205 b_pop 206 i_呼叫(一次/1) 208 b_var(10) 210 b_firstvar(23) 212 b_firstvar(24) 214 i_呼叫(尝试恢复输入/3) 216 b_统一_变量(10) 218 h_列表 219 h_变量(23) 221 h_var(24) 223小时流行音乐 224 b_统一_出口 225 b_函子(原子/1) 227 b_argfirstvar(25) 229波普 230 b_常数(“~w”) 232 b_列表 233 b_argvar(23) 235 b_nil 236B_pop 237 i_呼叫(格式/3) 239 b_变量(2) 241 h_函子((-)/2) 243 h_变量(22) 245 h_var(25) 247小时流行音乐 248 b_统一_出口 249 c_jmp(33) 251 b_函子((:)/2) 253立方英尺(符号) 255 b函数(按类型\名称/4) 257 b_argvar(6) 259 b_常数(eof) 261 b_argfirstvar(22) 263 b_void 264 b_pop 265 i_呼叫(一次/1) 267 b_unified_var(2) 269胡芬 ?- listing(read_token). read_token(parser(O, B), lexer(dfa-C, last_accept-T, chars-J), Q, A, S) :- ( A=[D|G], dfa:current(B, C, E), char_and_code(D, K, F), dfa:find_edge(B, E, F, H), N=G -> table:item(dfa_table, B, H, I), dfa:accept(I, L), atom_concat(J, K, M), P=lexer(dfa-H, last_accept-L, chars-M), R=N, read_token(parser(O, B), P, Q, R, S) % 1: looks nice! ; ( T\=none -> Q=T-J ; ground(D) -> once(symbol:by_type_name(B, error, W, _)), try_restore_input(D, U, V), D=[U|V], format(atom(X), '~w', [U]), Q=W-X % 2: prevents LCO ; once(symbol:by_type_name(B, eof, W, _)), Q=W-'' % 3: prevents LCO ), S=A % 4: prevents LCO ). ?- vm_list(read_token). ======================================================================== read_token/5 ======================================================================== 0 s_virgin 1 i_exit ---------------------------------------- clause 1 ((0x1cc4710)): ---------------------------------------- 0 h_functor(parser/2) 2 h_firstvar(5) 4 h_firstvar(6) 6 h_pop 7 h_functor(lexer/3) 9 h_functor((-)/2) 11 h_const(dfa) 13 h_firstvar(7) 15 h_pop 16 h_functor((-)/2) 18 h_const(last_accept) 20 h_firstvar(8) 22 h_pop 23 h_rfunctor((-)/2) 25 h_const(chars) 27 h_firstvar(9) 29 h_pop 30 i_enter 31 c_ifthenelse(26,118) 34 b_unify_var(3) 36 h_list_ff(10,11) 39 b_unify_exit 40 b_var(6) 42 b_var(7) 44 b_firstvar(12) 46 i_callm(dfa,dfa:current/3) 49 b_var(10) 51 b_firstvar(13) 53 b_firstvar(14) 55 i_call(char_and_code/3) 57 b_var(6) 59 b_var(12) 61 b_var(14) 63 b_firstvar(15) 65 i_callm(dfa,dfa:find_edge/4) 68 b_unify_fv(16,11) 71 c_cut(26) 73 b_const(dfa_table) 75 b_var(6) 77 b_var(15) 79 b_firstvar(17) 81 i_callm(table,table:item/4) 84 b_var(17) 86 b_firstvar(18) 88 i_callm(dfa,dfa:accept/2) 91 b_var(9) 93 b_var(13) 95 b_firstvar(19) 97 i_call(atom_concat/3) 99 b_unify_firstvar(20) 101 b_functor(lexer/3) 103 b_functor((-)/2) 105 b_const(dfa) 107 b_argvar(15) 109 b_pop 110 b_functor((-)/2) 112 b_const(last_accept) 114 b_argvar(18) 116 b_pop 117 b_rfunctor((-)/2) 119 b_const(chars) 121 b_argvar(19) 123 b_pop 124 b_unify_exit 125 b_unify_fv(21,16) 128 b_functor(parser/2) 130 b_argvar(5) 132 b_argvar(6) 134 b_pop 135 b_var(20) 137 b_var2 138 b_var(21) 140 b_var(4) 142 i_depart(read_token/5) 144 c_var_n(22,2) 147 c_var_n(24,2) 150 c_jmp(152) 152 c_ifthenelse(27,28) 155 b_var(8) 157 b_const(none) 159 i_call((\=)/2) 161 c_cut(27) 163 b_unify_var(2) 165 h_functor((-)/2) 167 h_var(8) 169 h_var(9) 171 h_pop 172 b_unify_exit 173 c_var(10) 175 c_var_n(22,2) 178 c_var_n(24,2) 181 c_jmp(101) 183 c_ifthenelse(28,65) 186 b_firstvar(10) 188 i_call(ground/1) 190 c_cut(28) 192 b_functor((:)/2) 194 b_const(symbol) 196 b_rfunctor(by_type_name/4) 198 b_argvar(6) 200 b_const(error) 202 b_argfirstvar(22) 204 b_void 205 b_pop 206 i_call(once/1) 208 b_var(10) 210 b_firstvar(23) 212 b_firstvar(24) 214 i_call(try_restore_input/3) 216 b_unify_var(10) 218 h_list 219 h_var(23) 221 h_var(24) 223 h_pop 224 b_unify_exit 225 b_functor(atom/1) 227 b_argfirstvar(25) 229 b_pop 230 b_const('~w') 232 b_list 233 b_argvar(23) 235 b_nil 236 b_pop 237 i_call(format/3) 239 b_unify_var(2) 241 h_functor((-)/2) 243 h_var(22) 245 h_var(25) 247 h_pop 248 b_unify_exit 249 c_jmp(33) 251 b_functor((:)/2) 253 b_const(symbol) 255 b_rfunctor(by_type_name/4) 257 b_argvar(6) 259 b_const(eof) 261 b_argfirstvar(22) 263 b_void 264 b_pop 265 i_call(once/1) 267 b_unify_var(2) 269 h_functor((-)/2) 271 h_var(22) 273 h_const('') 275 h_pop 276 b_unify_exit 277 c_var(10) 279 c_var_n(23,2) 282 c_var(25) 284 b_unify_vv(4,3) 287 c_var_n(11,2) 290 c_var_n(13,2) 293 c_var_n(15,2) 296 c_var_n(17,2) 299 c_var_n(19,2) 302 c_var(21) 304 i_exit