PageRenderTime 57ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/pl-6.0.2/packages/pldoc/doc_modes.pl

#
Perl | 469 lines | 393 code | 76 blank | 0 comment | 14 complexity | a862008bbcdb26d9e0c8212bc5ac728f MD5 | raw file
Possible License(s): AGPL-3.0, LGPL-2.1, GPL-2.0, LGPL-2.0, BSD-3-Clause
  1. /* $Id$
  2. Part of SWI-Prolog
  3. Author: Jan Wielemaker
  4. E-mail: wielemak@science.uva.nl
  5. WWW: http://www.swi-prolog.org
  6. Copyright (C): 1985-2006, University of Amsterdam
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public
  16. License along with this library; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. As a special exception, if you link this library with other files,
  19. compiled with a Free Software compiler, to produce an executable, this
  20. library does not by itself cause the resulting executable to be covered
  21. by the GNU General Public License. This exception does not however
  22. invalidate any other reasons why the executable file might be covered by
  23. the GNU General Public License.
  24. */
  25. :- module(pldoc_modes,
  26. [ process_modes/6, % +Lines, +M, +FP, -Modes, -Av, -RLines
  27. store_modes/2, % +Modes, +SourcePos
  28. mode/2, % ?:Head, -Det
  29. is_mode/1, % @Mode
  30. mode_indicator/1, % ?Atom
  31. modes_to_predicate_indicators/2, % +Modes, -PIs
  32. compile_clause/2 % +Term, +File:Line
  33. ]).
  34. :- use_module(library(lists)).
  35. :- use_module(library(memfile)).
  36. :- use_module(library(operators)).
  37. :- use_module(library(error)).
  38. /** <module> Analyse PlDoc mode declarations
  39. This module analyzes the formal part of the documentation of a
  40. predicate. The formal part is processed by read_term/3 using the
  41. operator declarations in this module.
  42. @author Jan Wielemaker
  43. @license GPL
  44. */
  45. :- op(750, xf, ...). % Repeated argument: Arg...
  46. :- op(650, fx, +). % allow +Arg
  47. :- op(650, fx, -). % allow -Arg
  48. :- op(650, fx, ?). % allow ?Arg
  49. :- op(650, fx, :). % allow :Arg
  50. :- op(650, fx, @). % allow @Arg
  51. :- op(650, fx, !). % allow !Arg
  52. :- op(200, xf, //). % allow for Head// is det.
  53. /*******************************
  54. * MODES *
  55. *******************************/
  56. %% process_modes(+Lines:lines, +Module, +FilePos,
  57. %% -Modes:list, -Args:list(atom),
  58. %% -RestLines:lines) is det.
  59. %
  60. % Process the formal header lines (upto the first blank line),
  61. % returning the remaining lines and the names of the arguments
  62. % used in the various header lines.
  63. %
  64. % @param FilePos Term File:Line with the position of comment
  65. % @param Modes List if mode(Head, Bindings) terms
  66. % @param Args List of argument-names appearing in modes
  67. process_modes(Lines, Module, FilePos, ModeDecls, Vars, RestLines) :-
  68. mode_lines(Lines, ModeText, [], RestLines),
  69. modes(ModeText, Module, FilePos, ModeDecls),
  70. extract_varnames(ModeDecls, Vars0, []),
  71. sort(Vars0, Vars).
  72. %% mode_lines(+Lines, -ModeText:codes, ?ModeTail:codes, -Lines) is det.
  73. %
  74. % Extract the formal header. For %% comments these are all lines
  75. % starting with %%. For /** comments, first skip empty lines and
  76. % then take all lines upto the first blank line. Skipping empty
  77. % lines allows for comments using this style:
  78. %
  79. % ==
  80. % /**
  81. % * predicate(+arg1:type1, ?arg2:type2) is det
  82. % ...
  83. % ==
  84. mode_lines(Lines0, ModeText, ModeTail, Lines) :-
  85. percent_mode_line(Lines0, ModeText, ModeTail0, Lines1), !,
  86. percent_mode_lines(Lines1, ModeTail0, ModeTail, Lines).
  87. mode_lines(Lines0, ModeText, ModeTail, Lines) :-
  88. empty_lines(Lines0, Lines1),
  89. non_empty_lines(Lines1, ModeText, ModeTail, Lines).
  90. percent_mode_line([1-[0'%|L]|Lines], ModeText, ModeTail, Lines) :- %'
  91. append(L, [10|ModeTail], ModeText).
  92. percent_mode_lines(Lines0, ModeText, ModeTail, Lines) :-
  93. percent_mode_line(Lines0, ModeText, ModeTail1, Lines1), !,
  94. percent_mode_lines(Lines1, ModeTail1, ModeTail, Lines).
  95. percent_mode_lines(Lines, Mode, Mode, Lines).
  96. empty_lines([_-[]|Lines0], Lines) :- !,
  97. empty_lines(Lines0, Lines).
  98. empty_lines(Lines, Lines).
  99. non_empty_lines([], ModeTail, ModeTail, []).
  100. non_empty_lines([_-[]|Lines], ModeTail, ModeTail, Lines) :- !.
  101. non_empty_lines([_-L|Lines0], ModeText, ModeTail, Lines) :-
  102. append(L, [10|ModeTail0], ModeText),
  103. non_empty_lines(Lines0, ModeTail0, ModeTail, Lines).
  104. %% modes(+Text:codes, +Module, +FilePos, -ModeDecls) is det.
  105. %
  106. % Read mode declaration. This consists of a number of Prolog terms
  107. % which may or may not be closed by a Prolog full-stop.
  108. %
  109. % @param Text Input text as list of codes.
  110. % @param Module Module the comment comes from
  111. % @param ModeDecls List of mode(Term, Bindings)
  112. modes(Text, Module, FilePos, Decls) :-
  113. prepare_module_operators(Module),
  114. modes(Text, FilePos, Decls).
  115. modes(Text, FilePos, Decls) :-
  116. catch(read_mode_terms(Text, FilePos, '', Decls), E, true),
  117. ( var(E)
  118. -> !
  119. ; E = error(syntax_error(end_of_file), _)
  120. -> fail
  121. ; !, mode_syntax_error(E),
  122. Decls = []
  123. ).
  124. modes(Text, FilePos, Decls) :-
  125. catch(read_mode_terms(Text, FilePos, ' . ', Decls), E, true),
  126. ( var(E)
  127. -> !
  128. ; mode_syntax_error(E),
  129. fail
  130. ).
  131. modes(_, _, []).
  132. %% mode_syntax_error(+ErrorTerm) is det.
  133. %
  134. % Print syntax errors in mode declarations. Currently, this is
  135. % suppressed unless the flag =pldoc_errors= is specified.
  136. mode_syntax_error(E) :-
  137. current_prolog_flag(pldoc_errors, true), !,
  138. print_message(warning, E).
  139. mode_syntax_error(_).
  140. read_mode_terms(Text, File:Line, End, Terms) :-
  141. new_memory_file(MemFile),
  142. open_memory_file(MemFile, write, Out),
  143. format(Out, '~s~w', [Text, End]),
  144. close(Out),
  145. open_memory_file(MemFile, read, In),
  146. set_stream(In, file_name(File)),
  147. stream_property(In, position(Pos0)),
  148. set_line(Pos0, Line, Pos),
  149. set_stream_position(In, Pos),
  150. call_cleanup(read_modes(In, Terms),
  151. ( close(In),
  152. free_memory_file(MemFile))).
  153. set_line('$stream_position'(CharC, _, LinePos, ByteC),
  154. Line,
  155. '$stream_position'(CharC, Line, LinePos, ByteC)).
  156. read_modes(In, Terms) :-
  157. read_mode_term(In, Term0),
  158. read_modes(Term0, In, Terms).
  159. read_modes(mode(end_of_file,[]), _, []) :- !.
  160. read_modes(T0, In, [T0|Rest]) :-
  161. read_mode_term(In, T1),
  162. read_modes(T1, In, Rest).
  163. read_mode_term(In, mode(Term, Bindings)) :-
  164. read_term(In, Term,
  165. [ variable_names(Bindings),
  166. module(pldoc_modes)
  167. ]).
  168. %% prepare_module_operators is det.
  169. %
  170. % Import operators from current source module.
  171. :- dynamic
  172. prepared_module/2.
  173. prepare_module_operators(Module) :-
  174. ( prepared_module(Module, _)
  175. -> true
  176. ; unprepare_module_operators,
  177. public_operators(Module, Ops),
  178. ( Ops \== []
  179. -> push_operators(Ops, Undo),
  180. asserta(prepared_module(Module, Undo))
  181. ; true
  182. )
  183. ).
  184. unprepare_module_operators :-
  185. forall(retract(prepared_module(_, Undo)),
  186. pop_operators(Undo)).
  187. %% public_operators(+Module, -List:list(op(Pri,Assoc,Name))) is det.
  188. %
  189. % List is the list of operators exported from Module through its
  190. % module header.
  191. public_operators(Module, List) :-
  192. module_property(Module, exported_operators(List)), !.
  193. public_operators(_, []).
  194. %% extract_varnames(+Bindings, -VarNames, ?VarTail) is det.
  195. %
  196. % Extract the variables names.
  197. %
  198. % @param Bindings Nested list of Name=Var
  199. % @param VarNames List of variable names
  200. % @param VarTail Tail of VarNames
  201. extract_varnames([], VN, VN) :- !.
  202. extract_varnames([H|T], VN0, VN) :- !,
  203. extract_varnames(H, VN0, VN1),
  204. extract_varnames(T, VN1, VN).
  205. extract_varnames(mode(_, Bindings), VN0, VN) :- !,
  206. extract_varnames(Bindings, VN0, VN).
  207. extract_varnames(Name=_, [Name|VN], VN).
  208. %% store_modes(+Modes, +SourcePos) is det.
  209. %
  210. % Assert modes into the database with the given position.
  211. %
  212. % @param Modes List if mode-terms. See process_modes/6.
  213. % @param SourcePos Term File:Line
  214. store_modes([], _).
  215. store_modes([mode(Mode, _Bindings)|T], Pos) :-
  216. store_mode(Mode, Pos),
  217. store_modes(T, Pos).
  218. store_mode(Var, _) :-
  219. var(Var), !,
  220. throw(error(instantiation_error,
  221. context(_, 'PlDoc: Mode declaration expected'))).
  222. store_mode(Head0 is Det, Pos) :- !,
  223. dcg_expand(Head0, Head),
  224. compile_clause('$mode'(Head, Det), Pos).
  225. store_mode(Head0, Pos) :-
  226. dcg_expand(Head0, Head),
  227. compile_clause('$mode'(Head, unknown), Pos).
  228. dcg_expand(M:Head0, M:Head) :-
  229. atom(M), !,
  230. dcg_expand(Head0, Head).
  231. dcg_expand(//(Head0), Head) :- !,
  232. Head0 =.. [Name|List0],
  233. maplist(remove_argname, List0, List1),
  234. append(List1, [?list, ?list], List2),
  235. Head =.. [Name|List2].
  236. dcg_expand(Head0, Head) :-
  237. remove_argnames(Head0, Head).
  238. remove_argnames(Var, _) :-
  239. var(Var), !,
  240. instantiation_error(Var).
  241. remove_argnames(M:Head0, M:Head) :- !,
  242. must_be(atom, M),
  243. remove_argnames(Head0, Head).
  244. remove_argnames(Head0, Head) :-
  245. functor(Head0, Name, Arity),
  246. functor(Head, Name, Arity),
  247. remove_argnames(0, Arity, Head0, Head).
  248. remove_argnames(Arity, Arity, _, _) :- !.
  249. remove_argnames(I0, Arity, H0, H) :-
  250. I is I0 + 1,
  251. arg(I, H0, A0),
  252. remove_argname(A0, A),
  253. arg(I, H, A),
  254. remove_argnames(I, Arity, H0, H).
  255. remove_argname(T, ?(any)) :-
  256. var(T), !.
  257. remove_argname(T0..., T...) :- !,
  258. remove_argname(T0, T).
  259. remove_argname(A0, A) :-
  260. mode_ind(A0, M, A1), !,
  261. remove_aname(A1, A2),
  262. mode_ind(A, M, A2).
  263. remove_argname(A0, ?A) :-
  264. remove_aname(A0, A).
  265. remove_aname(Var, any) :-
  266. var(Var), !.
  267. remove_aname(_:Type, Type) :- !.
  268. %% mode(:Head, ?Det) is nondet.
  269. %
  270. % True if there is a mode-declaration for Head with Det.
  271. %
  272. % @param Head Callable term. Arguments are a mode-indicator
  273. % followed by a type.
  274. % @param Det One of =unknown=, =det=, =semidet=, or =nondet=.
  275. :- module_transparent
  276. mode/2.
  277. mode(Head, Det) :-
  278. var(Head), !,
  279. current_module(M),
  280. '$c_current_predicate'(_, M:'$mode'(_,_)),
  281. M:'$mode'(H,Det),
  282. qualify(M,H,Head).
  283. mode(M:Head, Det) :-
  284. current_module(M),
  285. '$c_current_predicate'(_, M:'$mode'(_,_)),
  286. M:'$mode'(Head,Det).
  287. qualify(system, H, H) :- !.
  288. qualify(user, H, H) :- !.
  289. qualify(M, H, M:H).
  290. %% is_mode(@Head) is semidet.
  291. %
  292. % True if Head is a valid mode-term.
  293. is_mode(Var) :-
  294. var(Var), !, fail.
  295. is_mode(Head is Det) :-
  296. is_det(Det),
  297. is_head(Head).
  298. is_det(Var) :-
  299. var(Var), !, fail.
  300. is_det(det).
  301. is_det(semidet).
  302. is_det(nondet).
  303. is_det(multi).
  304. is_head(Var) :-
  305. var(Var), !, fail.
  306. is_head(Head//) :- !,
  307. is_head(Head).
  308. is_head(Head) :-
  309. callable(Head),
  310. functor(Head, _Name, Arity),
  311. is_head_args(0, Arity, Head).
  312. is_head_args(A, A, _) :- !.
  313. is_head_args(I0, Arity, Head) :-
  314. I is I0 + 1,
  315. arg(I, Head, Arg),
  316. is_head_arg(Arg),
  317. is_head_args(I, Arity, Head).
  318. is_head_arg(Arg) :-
  319. var(Arg), !.
  320. is_head_arg(Arg) :-
  321. Arg =.. [Ind,Arg1],
  322. mode_indicator(Ind),
  323. is_head_arg(Arg1).
  324. is_head_arg(Arg:Type) :-
  325. var(Arg),
  326. is_type(Type).
  327. is_type(Type) :-
  328. callable(Type).
  329. %% mode_indicator(?Ind:atom) is nondet.
  330. %
  331. % Our defined argument-mode indicators
  332. mode_indicator(+). % Instantiated to type
  333. mode_indicator(-). % Unbound
  334. mode_indicator(?). % Partially instantiated to type
  335. mode_indicator(:). % Meta-argument (implies +)
  336. mode_indicator(@). % Not instantiated by pred
  337. mode_indicator(!). % Mutable term
  338. mode_ind(+(X), +, X).
  339. mode_ind(-(X), -, X).
  340. mode_ind(?(X), ?, X).
  341. mode_ind(:(X), :, X).
  342. mode_ind(@(X), @, X).
  343. mode_ind(!(X), !, X).
  344. %% modes_to_predicate_indicators(+Modes:list, -PI:list) is det.
  345. %
  346. % Create a list of predicate indicators represented by Modes. Each
  347. % predicate indicator is of the form atom/integer for normal
  348. % predicates or atom//integer for DCG rules.
  349. %
  350. % @param Modes Mode-list as produced by process_modes/5
  351. % @param PI List of Name/Arity or Name//Arity without duplicates
  352. modes_to_predicate_indicators(Modes, PIs) :-
  353. modes_to_predicate_indicators2(Modes, PIs0),
  354. list_to_set(PIs0, PIs).
  355. modes_to_predicate_indicators2([], []).
  356. modes_to_predicate_indicators2([mode(H,_B)|T0], [PI|T]) :-
  357. mode_to_pi(H, PI),
  358. modes_to_predicate_indicators2(T0, T).
  359. mode_to_pi(Head is _Det, PI) :- !,
  360. head_to_pi(Head, PI).
  361. mode_to_pi(Head, PI) :-
  362. head_to_pi(Head, PI).
  363. head_to_pi(M:Head, M:PI) :-
  364. atom(M), !,
  365. head_to_pi(Head, PI).
  366. head_to_pi(//(Head), Name//Arity) :- !,
  367. functor(Head, Name, Arity).
  368. head_to_pi(Head, Name/Arity) :-
  369. functor(Head, Name, Arity).
  370. %% compile_clause(:Term, +FilePos) is det.
  371. %
  372. % Add a clause to the compiled program. Unlike assert/1, this
  373. % associates the clause with the given source-location, makes it
  374. % static code and removes the clause if the file is reloaded.
  375. % Finally, as we create clauses one-by-one, we define our
  376. % predicates as discontiguous.
  377. %
  378. % @param Term Clause-term
  379. % @param FilePos Term of the form File:Line, where File is a
  380. % canonical filename.
  381. compile_clause(Term, File:Line) :-
  382. '$set_source_module'(SM, SM),
  383. strip_module(SM:Term, M, Plain),
  384. clause_head(Plain, Head),
  385. functor(Head, Name, Arity),
  386. multifile(M:(Name/Arity)),
  387. ( M == SM
  388. -> Clause = Term
  389. ; Clause = M:Term
  390. ),
  391. '$store_clause'('$source_location'(File, Line):Clause, File).
  392. clause_head((Head :- _Body), Head) :- !.
  393. clause_head(Head, Head).