如何确定Prolog是否执行尾部调用优化
使用SWI Prolog(Win x64)的开发版本, 我为a编写了一个DCG谓词(因此所有外部谓词都没有选择点):如何确定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
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