1% ----------------------------------------------------------------------
2% BEGIN LICENSE BLOCK
3% Version: CMPL 1.1
4%
5% The contents of this file are subject to the Cisco-style Mozilla Public
6% License Version 1.1 (the "License"); you may not use this file except
7% in compliance with the License.  You may obtain a copy of the License
8% at www.eclipse-clp.org/license.
9%
10% Software distributed under the License is distributed on an "AS IS"
11% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
12% the License for the specific language governing rights and limitations
13% under the License.
14%
15% The Original Code is  The ECLiPSe Constraint Logic Programming System.
16% The Initial Developer of the Original Code is  Cisco Systems, Inc.
17% Portions created by the Initial Developer are
18% Copyright (C) 1989-2006 Cisco Systems, Inc.  All Rights Reserved.
19%
20% Contributor(s): ECRC GmbH
21% Contributor(s): IC-Parc, Imperal College London
22%
23% END LICENSE BLOCK
24%
25% System:	ECLiPSe Constraint Logic Programming System
26% Version:	$Id: cprolog.pl,v 1.10 2013/06/16 02:21:27 jschimpf Exp $
27% ----------------------------------------------------------------------
28
29/*
30 * SEPIA PROLOG SOURCE MODULE
31 */
32
33/*
34 * IDENTIFICATION:	cprolog.pl
35 *
36 * DESCRIPTION: 	C-Prolog compatibility package.
37 *			This is also the basis for the
38 *			Quintus and SICStus packages.
39 *
40 * CONTENTS:
41 *
42 */
43
44:- module(cprolog).
45
46:- comment(categories, ["Compatibility"]).
47:- comment(summary, 'C-Prolog compatibility package').
48:- comment(author, 'Various, ECRC Munich').
49:- comment(copyright, 'Cisco Systems, Inc').
50:- comment(date, '$Date: 2013/06/16 02:21:27 $').
51:- comment(desc, html('
52    One of the requirements during the development of ECLiPSe has been the
53    aim of minimising the work required to port traditional Prolog
54    programs to ECLiPSe.  A de-facto standard for many years was the
55    C-Prolog dialect, often referred to as Edinburgh Prolog.  Therefore,
56    many of the non standard predicates in C-Prolog have also been
57    included in ECLiPSe.  It is of course impossible to achieve total
58    compatibility between the two systems.  To assist in making the
59    changes necessary to run a C-Prolog program on the current version of
60    ECLiPSe, we describve here the predicates available in the
61    C-Prolog compatibility library and summarise the principal
62    differences between ECLiPSe Prolog and C-Prolog.
63    <P>
64    Most of the C-Prolog predicates are also ECLiPSe built-in predicates
65    and so they can be always accessed.
66    <P>
67    Please note that this text does not detail the functionality of
68    C-Prolog, refer to the C-Prolog documentation for this information.
69    <P>
70    The effect of the compatibility library is local to the module where
71    it is loaded. For maximum compatibility, a C-Prolog program should
72    be wrapped in a separate module starting with a directive like
73    <PRE>
74    :- module(mymodule, [], cprolog).
75    </PRE>
76    In this case, Eclipse-specific language constructs will not be available.
77    <P>
78    If the compatibility package is loaded into a standard module, e.g. like
79    <PRE>
80    :- module(mymixedmdule).
81    :- use_module(library(cprolog)).
82    </PRE>
83    then C-Prolog and Eclipse language features can be used together.
84    However, ambiguities must be resolved explicitly and confusion may
85    arise from the different meaning of quotes in Eclipse vs C-Prolog.
86    <P>
87    Note that the C-Prolog compatibility package includes the <EM>cio</EM>
88    library (for see/1, seeing/1, seen/0, skip/1, tab/1, tell/1, telling/1,
89    told/0).
90    <P>
91    The following C-Prolog predicates are not available in ECLiPSe, or
92    the corresponding predicates have a different semantics:
93    <DL>
94    <DT>assert/2, asserta/2, assertz/2, clause/3
95	<DD>ECLiPSe does not support database references for clauses.
96    <DT>expand_term/2
97	<DD>This is not supported.  ECLiPSe provides the macro facility
98	    for transforming input terms (see chapter 13).
99    <DT>&#39;LC&#39;/0, &#39;NOLC&#39;/0
100	<DD>These are not supported in ECLiPSe.
101    </DL>
102    <P>
103    The following differences remain even with the compatibility package:
104    <DL>
105    <DT>Database References
106	<DD>ECLiPSe provides database references only for terms in the indexed database, not for program clauses.
107    <DT>Numbers
108	<DD>C-Prolog has a tendency to "prefer" integers over real
109	numbers.  For instance, under C-Prolog when the call X is
110	4.0/2.0 is made, X is instantiated to an integer.  This
111	behaviour does not occur in ECLiPSe.  The order of integers
112	and reals in the standard order is different.
113    <DT>Operators
114	<DD>In C-Prolog there is a bug regarding the operator not -- it
115	binds closer than its precedence declaration.
116    <DT>Strings
117	<DD>Strings are simulated in C-Prolog by lists.  Under C-Prolog
118	mode, ECLiPSe provides this functionality -- double-quoted
119	strings are parsed as lists of integers.  This can cause
120	confusion when pure ECLiPSe predicates are used in C-Prolog
121	mode, e.g.  substring/3 will not accept double-quoted items,
122	since they are lists, not ECLiPSe strings.  The built-in
123	string_list/2 converts between both representations.
124    <DT>consult/1, reconsult/1
125	<DD>These are implemented by simply calling the ECLiPSe predicate
126	compile/1.  By default all compiled procedures are static.
127	Procedures on which assert/1 etc.  will be applied, have to be
128	declared as dynamic using dynamic/1.  The notation [-File] for
129	reconsult/1 is not supported.
130    <DT>get/1
131	<DD>This is similar to the ECLiPSe predicate get/1, but
132	control characters and blank spaces are skipped.
133    <DT>put/1
134	<DD>This is similar to the ECLiPSe predicate put/1, but it
135	first applies arithmetic evaluation to its argument.
136    <DT>heapused/1
137	<DD>Needed for evaluating heapused in arithmetic expressions.
138	It returns the sum of code heap and general heap usage.
139    <DT>instance/2
140	<DD>Note that this compatibility predicate redefines the
141	ECLiPSe builtin of the same name but different meaning (which
142	is no longer available in C-Prolog mode).  It is implemented
143	using the ECLiPSe predicate referenced_record/2.
144    <DT>log/2, log10/2
145	<DD>These are not predicates in C-Prolog (arithmetic
146	functors), but in ECLiPSe they are needed for evaluating log/1
147	and log10/1 in arithmetic expressions.
148    <DT>ttyput/1
149    	<DD>corresponds to the DEC-10 Prolog predicate
150    </DL>
151    The list below describes the syntax differences between ECLiPSe
152    and C-Prolog.  The following C-Prolog properties are simulated by
153    the compatibility package:
154    <UL>
155	<LI>single (resp. double) quote must be doubled between single (resp. double) quotes.
156	<LI>$ is a normal character.
157	<LI>the symbol | is not an atom.
158    </UL>
159    The following properties of original C-Prolog are not simulated by
160    the compatibility package:
161    <UL>
162	<LI>a clause can not be ended by end of file.
163	<LI>based integers are not accepted.
164	<LI>comments are not a delimiter (just ignored).
165	<LI>{} is not an atom.
166	<LI>[] can not be a functor.
167    </UL>
168    ')).
169:- comment(see_also, [library(cio),library(quintus)]).
170
171
172:- reexport cio.
173
174% suppress deprecation warnings for reexported builtins
175:- pragma(deprecated_warnings(not_reexports)).
176
177:- reexport eclipse_language except
178
179	get/1,				% redefined predicates
180	put/1,
181	instance/2,
182	(abolish)/1,
183	arg/3,
184
185%	op(_,   xfx, (of)),		% don't provide these
186%	op(_,   xfx, (with)),
187%	op(_,   xfy, (do)),
188%	op(_,   xfx, (@)),
189%	op(_,   fx, (-?->)),
190%	macro((with)/2, _, _),
191%	macro((of)/2, _, _),
192
193	macro((if)/2,_,_).
194
195:- export			% temporary, while op/macros still global
196	op(0,   xfx, (of)),
197	op(0,   xfx, (with)),
198	op(0,   xfy, (do)),
199	op(0,   xfx, (@)),
200	op(0,   fx, (-?->)),
201	macro((with)/2, (=)/2, []),
202	macro((of)/2, (=)/2, []).
203
204:- local
205	op(1100,  xfy, (do)),
206	op(650,   xfx, (@)).
207
208:- export
209	syntax_option(nl_in_quotes),
210	syntax_option(no_blanks),
211        syntax_option(no_array_subscripts),
212	syntax_option(limit_arg_precedence),
213	syntax_option(doubled_quote_is_quote),
214	syntax_option(bar_is_no_atom),
215	syntax_option(bar_is_semicolon),
216	syntax_option(no_attributes),
217	syntax_option(no_curly_arguments),
218	syntax_option(blanks_after_sign),
219
220	chtab(0'$, lower_case),
221	chtab(0'\, symbol),		% disable escape sequences
222	chtab(128, string_quote),	% there must be some string_quote
223	chtab(0'", list_quote),
224
225	op(300, xfx, mod),
226	op(500, fx, (+)),
227	op(500, fx, (-)),
228	op(900, fy, (spy)),
229	op(900, fy, (nospy)).
230
231:- export
232	(.)/3,		% to evaluate lists in arithmetic expressions
233	(abolish)/2,
234	arg/3,
235	consult/1,
236	current_functor/2,
237	current_predicate/2,
238	db_reference/1,
239	erased/1,
240	fileerrors/0,
241	get/1,
242	get0/1,
243	heapused/1,
244	instance/2,
245	leash/1,
246	log10/2,
247	log/2,
248	nofileerrors/0,
249	primitive/1,
250	prompt/2,
251	put/1,
252	reconsult/1,
253	sh/0.
254
255:- skipped
256	(abolish)/2,
257	consult/1,
258	current_functor/2,
259	erased/1,
260	fileerrors/0,
261	get/1,
262	get0/1,
263	instance/2,
264	log10/2,
265	nofileerrors/0,
266	primitive/1,
267	prompt/2,
268	put/1,
269	reconsult/1.
270
271:- import
272	current_predicate_body / 2,
273	error_handler / 2,
274	get_flag_body/4,
275	set_default_error_handler/2,
276	system_error_handler / 4,
277	undef_dynamic_handler / 3
278    from sepia_kernel.
279
280:- system.		% compiler directive to add the SYSTEM flag
281
282
283/*
284 * OTHER DIRECTIVES
285 */
286
287
288:-  tool((abolish)/2, abolish_body/3),
289    tool(consult/1, consult_/2),
290    tool(reconsult/1, reconsult_/2),
291    tool(current_predicate/2, current_predicate_body/3).
292
293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294%
295%	EVENT HANDLERS
296%
297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298
299% This simulates Quintus' behaviour
300cp_undef_dynamic_handler(_, retract_all(_), _) :- !.
301cp_undef_dynamic_handler(_, retractall(_), _) :- !.
302cp_undef_dynamic_handler(_, listing(_), _) :- !.
303cp_undef_dynamic_handler(_, retract(_), _) :- !, fail.
304cp_undef_dynamic_handler(_, clause(_), _) :- !, fail.
305cp_undef_dynamic_handler(_, clause(_, _), _) :- !, fail.
306cp_undef_dynamic_handler(E, G, M) :-
307	undef_dynamic_handler(E, G, M).
308
309cp_access_undefined(_, abolish(_)) :-
310	!.
311cp_access_undefined(X,Y) :-
312	error_handler(X,Y).
313
314nofileerrors_handler(_, open(_, _, _), _, _) :- !, fail.
315nofileerrors_handler(N, Goal, CM, LM) :-
316	system_error_handler(N, Goal, CM, LM).
317
318fileerrors :-
319	set_default_error_handler(170, system_error_handler/4),
320	set_default_error_handler(171, error_handler/2),
321	reset_event_handler(170),
322	reset_event_handler(171).
323
324nofileerrors :-
325	set_default_error_handler(170, nofileerrors_handler/4),
326	set_default_error_handler(171, fail/0),
327	reset_event_handler(170),
328	reset_event_handler(171).
329
330:-
331	% we may change the default handlers, because we can't switch back
332	set_default_error_handler(60, cp_access_undefined/2),
333	reset_event_handler(60),
334	set_default_error_handler(70, cp_undef_dynamic_handler/3),
335	reset_event_handler(70),
336	set_default_error_handler(100, cp_undef_dynamic_handler/3),
337	reset_event_handler(100).
338
339
340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341%
342%	NEW PREDICATES
343%
344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345
346sh :-
347	getenv('SHELL', X),
348	sh(X).
349
350primitive(X) :- atom(X), !, fail.
351primitive(X) :- atomic(X).
352
353db_reference(X) :- type_of(X, handle).
354
355get0(X):- get(input, X).
356
357leash(Ports) :-
358	set_leash(_, print),
359	set_leash(Ports, stop).
360
361
362heapused(X) :- X is statistics(general_heap_used) + statistics(code_heap_used).
363
364prompt(Old, New) :-
365	get_stream_info(input, prompt, Old),
366	set_stream_property(input, prompt, New).
367
368ttyput(Char) :-
369	N is Char,
370	put(stdout, N).
371
372current_functor(F, T) :-
373	current_functor(F/A),
374	functor(T, F, A).
375
376abolish_body(N, A, M) :-
377	sepia_kernel:abolish(N/A)@M.
378
379consult_(File, Module) :-
380	compile(File)@Module.
381
382reconsult_(File, Module) :-
383	compile(File)@Module.
384
385erased(Ref) :-
386	\+referenced_record(Ref, _).
387
388%  ARITHMETIC
389
390log10(Y,X):- X is ln(Y)/ln(10.0).
391
392log(Y,X) :- X is ln(Y).
393
394.(X,_,X).
395
396% allow expressions built at runtime without an eval wrapper to be evaluated
397
398:- set_event_handler(24, eval_expr/2).
399
400eval_expr(N, ArithGoal) :-
401        functor(ArithGoal, Op, A),
402        NewA is A - 1,
403        functor(Expr, Op, NewA),
404	( sepia_kernel:arith_builtin(Expr) ->
405	    ( foreacharg(X,Expr,I), param(ArithGoal) do
406		eclipse_language:arg(I, ArithGoal, X)
407	    ),
408	    eclipse_language:arg(A, ArithGoal, Res),
409	    Res is Expr
410	;
411	    error(default(N), ArithGoal)
412	).
413
414
415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416%
417%	REDEFINED PREDICATES
418%
419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420
421get(X):- repeat, get(input, X), X > 32, X < 127, !.
422
423put(X):- N is X, put(output,N).
424
425instance(Ref, Term) :-
426	referenced_record(Ref, Term).
427
428current_predicate_body(F, T, M) :-
429	current_predicate_body(F/A, M),
430	functor(T, F, A),
431	get_flag_body(F/A, definition_module, M, M).
432
433arg(N, S, X) :-
434	nonvar(S),
435	integer(N),
436	1 =< N, N =< arity(S),
437	eclipse_language:arg(N, S, X).
438
439