% ----------------------------------------------------------------------
% BEGIN LICENSE BLOCK
% Version: CMPL 1.1
%
% The contents of this file are subject to the Cisco-style Mozilla Public
% License Version 1.1 (the "License"); you may not use this file except
% in compliance with the License. You may obtain a copy of the License
% at www.eclipse-clp.org/license.
%
% Software distributed under the License is distributed on an "AS IS"
% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
% the License for the specific language governing rights and limitations
% under the License.
%
% The Original Code is The ECLiPSe Constraint Logic Programming System.
% The Initial Developer of the Original Code is Cisco Systems, Inc.
% Portions created by the Initial Developer are
% Copyright (C) 1989-2006 Cisco Systems, Inc. All Rights Reserved.
%
% Contributor(s): ECRC GmbH
% Contributor(s): IC-Parc, Imperal College London
%
% END LICENSE BLOCK
%
% System: ECLiPSe Constraint Logic Programming System
% Version: $Id: cprolog.pl,v 1.10 2013/06/16 02:21:27 jschimpf Exp $
% ----------------------------------------------------------------------
/*
* SEPIA PROLOG SOURCE MODULE
*/
/*
* IDENTIFICATION: cprolog.pl
*
* DESCRIPTION: C-Prolog compatibility package.
* This is also the basis for the
* Quintus and SICStus packages.
*
* CONTENTS:
*
*/
:- module(cprolog).
:- comment(categories, ["Compatibility"]).
:- comment(summary, 'C-Prolog compatibility package').
:- comment(author, 'Various, ECRC Munich').
:- comment(copyright, 'Cisco Systems, Inc').
:- comment(date, '$Date: 2013/06/16 02:21:27 $').
:- comment(desc, html('
One of the requirements during the development of ECLiPSe has been the
aim of minimising the work required to port traditional Prolog
programs to ECLiPSe. A de-facto standard for many years was the
C-Prolog dialect, often referred to as Edinburgh Prolog. Therefore,
many of the non standard predicates in C-Prolog have also been
included in ECLiPSe. It is of course impossible to achieve total
compatibility between the two systems. To assist in making the
changes necessary to run a C-Prolog program on the current version of
ECLiPSe, we describve here the predicates available in the
C-Prolog compatibility library and summarise the principal
differences between ECLiPSe Prolog and C-Prolog.
Most of the C-Prolog predicates are also ECLiPSe built-in predicates
and so they can be always accessed.
Please note that this text does not detail the functionality of
C-Prolog, refer to the C-Prolog documentation for this information.
The effect of the compatibility library is local to the module where
it is loaded. For maximum compatibility, a C-Prolog program should
be wrapped in a separate module starting with a directive like
:- module(mymodule, [], cprolog).
In this case, Eclipse-specific language constructs will not be available.
If the compatibility package is loaded into a standard module, e.g. like
:- module(mymixedmdule).
:- use_module(library(cprolog)).
then C-Prolog and Eclipse language features can be used together.
However, ambiguities must be resolved explicitly and confusion may
arise from the different meaning of quotes in Eclipse vs C-Prolog.
Note that the C-Prolog compatibility package includes the cio
library (for see/1, seeing/1, seen/0, skip/1, tab/1, tell/1, telling/1,
told/0).
The following C-Prolog predicates are not available in ECLiPSe, or
the corresponding predicates have a different semantics:
- assert/2, asserta/2, assertz/2, clause/3
- ECLiPSe does not support database references for clauses.
- expand_term/2
- This is not supported. ECLiPSe provides the macro facility
for transforming input terms (see chapter 13).
- 'LC'/0, 'NOLC'/0
- These are not supported in ECLiPSe.
The following differences remain even with the compatibility package:
- Database References
- ECLiPSe provides database references only for terms in the indexed database, not for program clauses.
- Numbers
- C-Prolog has a tendency to "prefer" integers over real
numbers. For instance, under C-Prolog when the call X is
4.0/2.0 is made, X is instantiated to an integer. This
behaviour does not occur in ECLiPSe. The order of integers
and reals in the standard order is different.
- Operators
- In C-Prolog there is a bug regarding the operator not -- it
binds closer than its precedence declaration.
- Strings
- Strings are simulated in C-Prolog by lists. Under C-Prolog
mode, ECLiPSe provides this functionality -- double-quoted
strings are parsed as lists of integers. This can cause
confusion when pure ECLiPSe predicates are used in C-Prolog
mode, e.g. substring/3 will not accept double-quoted items,
since they are lists, not ECLiPSe strings. The built-in
string_list/2 converts between both representations.
- consult/1, reconsult/1
- These are implemented by simply calling the ECLiPSe predicate
compile/1. By default all compiled procedures are static.
Procedures on which assert/1 etc. will be applied, have to be
declared as dynamic using dynamic/1. The notation [-File] for
reconsult/1 is not supported.
- get/1
- This is similar to the ECLiPSe predicate get/1, but
control characters and blank spaces are skipped.
- put/1
- This is similar to the ECLiPSe predicate put/1, but it
first applies arithmetic evaluation to its argument.
- heapused/1
- Needed for evaluating heapused in arithmetic expressions.
It returns the sum of code heap and general heap usage.
- instance/2
- Note that this compatibility predicate redefines the
ECLiPSe builtin of the same name but different meaning (which
is no longer available in C-Prolog mode). It is implemented
using the ECLiPSe predicate referenced_record/2.
- log/2, log10/2
- These are not predicates in C-Prolog (arithmetic
functors), but in ECLiPSe they are needed for evaluating log/1
and log10/1 in arithmetic expressions.
- ttyput/1
- corresponds to the DEC-10 Prolog predicate
The list below describes the syntax differences between ECLiPSe
and C-Prolog. The following C-Prolog properties are simulated by
the compatibility package:
- single (resp. double) quote must be doubled between single (resp. double) quotes.
- $ is a normal character.
- the symbol | is not an atom.
The following properties of original C-Prolog are not simulated by
the compatibility package:
- a clause can not be ended by end of file.
- based integers are not accepted.
- comments are not a delimiter (just ignored).
- {} is not an atom.
- [] can not be a functor.
')).
:- comment(see_also, [library(cio),library(quintus)]).
:- reexport cio.
% suppress deprecation warnings for reexported builtins
:- pragma(deprecated_warnings(not_reexports)).
:- reexport eclipse_language except
get/1, % redefined predicates
put/1,
instance/2,
(abolish)/1,
arg/3,
% op(_, xfx, (of)), % don't provide these
% op(_, xfx, (with)),
% op(_, xfy, (do)),
% op(_, xfx, (@)),
% op(_, fx, (-?->)),
% macro((with)/2, _, _),
% macro((of)/2, _, _),
macro((if)/2,_,_).
:- export % temporary, while op/macros still global
op(0, xfx, (of)),
op(0, xfx, (with)),
op(0, xfy, (do)),
op(0, xfx, (@)),
op(0, fx, (-?->)),
macro((with)/2, (=)/2, []),
macro((of)/2, (=)/2, []).
:- local
op(1100, xfy, (do)),
op(650, xfx, (@)).
:- export
syntax_option(nl_in_quotes),
syntax_option(no_blanks),
syntax_option(no_array_subscripts),
syntax_option(limit_arg_precedence),
syntax_option(doubled_quote_is_quote),
syntax_option(bar_is_no_atom),
syntax_option(bar_is_semicolon),
syntax_option(no_attributes),
syntax_option(no_curly_arguments),
syntax_option(blanks_after_sign),
chtab(0'$, lower_case),
chtab(0'\, symbol), % disable escape sequences
chtab(128, string_quote), % there must be some string_quote
chtab(0'", list_quote),
op(300, xfx, mod),
op(500, fx, (+)),
op(500, fx, (-)),
op(900, fy, (spy)),
op(900, fy, (nospy)).
:- export
(.)/3, % to evaluate lists in arithmetic expressions
(abolish)/2,
arg/3,
consult/1,
current_functor/2,
current_predicate/2,
db_reference/1,
erased/1,
fileerrors/0,
get/1,
get0/1,
heapused/1,
instance/2,
leash/1,
log10/2,
log/2,
nofileerrors/0,
primitive/1,
prompt/2,
put/1,
reconsult/1,
sh/0.
:- skipped
(abolish)/2,
consult/1,
current_functor/2,
erased/1,
fileerrors/0,
get/1,
get0/1,
instance/2,
log10/2,
nofileerrors/0,
primitive/1,
prompt/2,
put/1,
reconsult/1.
:- import
current_predicate_body / 2,
error_handler / 2,
get_flag_body/4,
set_default_error_handler/2,
system_error_handler / 4,
undef_dynamic_handler / 3
from sepia_kernel.
:- system. % compiler directive to add the SYSTEM flag
/*
* OTHER DIRECTIVES
*/
:- tool((abolish)/2, abolish_body/3),
tool(consult/1, consult_/2),
tool(reconsult/1, reconsult_/2),
tool(current_predicate/2, current_predicate_body/3).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% EVENT HANDLERS
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This simulates Quintus' behaviour
cp_undef_dynamic_handler(_, retract_all(_), _) :- !.
cp_undef_dynamic_handler(_, retractall(_), _) :- !.
cp_undef_dynamic_handler(_, listing(_), _) :- !.
cp_undef_dynamic_handler(_, retract(_), _) :- !, fail.
cp_undef_dynamic_handler(_, clause(_), _) :- !, fail.
cp_undef_dynamic_handler(_, clause(_, _), _) :- !, fail.
cp_undef_dynamic_handler(E, G, M) :-
undef_dynamic_handler(E, G, M).
cp_access_undefined(_, abolish(_)) :-
!.
cp_access_undefined(X,Y) :-
error_handler(X,Y).
nofileerrors_handler(_, open(_, _, _), _, _) :- !, fail.
nofileerrors_handler(N, Goal, CM, LM) :-
system_error_handler(N, Goal, CM, LM).
fileerrors :-
set_default_error_handler(170, system_error_handler/4),
set_default_error_handler(171, error_handler/2),
reset_event_handler(170),
reset_event_handler(171).
nofileerrors :-
set_default_error_handler(170, nofileerrors_handler/4),
set_default_error_handler(171, fail/0),
reset_event_handler(170),
reset_event_handler(171).
:-
% we may change the default handlers, because we can't switch back
set_default_error_handler(60, cp_access_undefined/2),
reset_event_handler(60),
set_default_error_handler(70, cp_undef_dynamic_handler/3),
reset_event_handler(70),
set_default_error_handler(100, cp_undef_dynamic_handler/3),
reset_event_handler(100).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NEW PREDICATES
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sh :-
getenv('SHELL', X),
sh(X).
primitive(X) :- atom(X), !, fail.
primitive(X) :- atomic(X).
db_reference(X) :- type_of(X, handle).
get0(X):- get(input, X).
leash(Ports) :-
set_leash(_, print),
set_leash(Ports, stop).
heapused(X) :- X is statistics(general_heap_used) + statistics(code_heap_used).
prompt(Old, New) :-
get_stream_info(input, prompt, Old),
set_stream_property(input, prompt, New).
ttyput(Char) :-
N is Char,
put(stdout, N).
current_functor(F, T) :-
current_functor(F/A),
functor(T, F, A).
abolish_body(N, A, M) :-
sepia_kernel:abolish(N/A)@M.
consult_(File, Module) :-
compile(File)@Module.
reconsult_(File, Module) :-
compile(File)@Module.
erased(Ref) :-
\+referenced_record(Ref, _).
% ARITHMETIC
log10(Y,X):- X is ln(Y)/ln(10.0).
log(Y,X) :- X is ln(Y).
.(X,_,X).
% allow expressions built at runtime without an eval wrapper to be evaluated
:- set_event_handler(24, eval_expr/2).
eval_expr(N, ArithGoal) :-
functor(ArithGoal, Op, A),
NewA is A - 1,
functor(Expr, Op, NewA),
( sepia_kernel:arith_builtin(Expr) ->
( foreacharg(X,Expr,I), param(ArithGoal) do
eclipse_language:arg(I, ArithGoal, X)
),
eclipse_language:arg(A, ArithGoal, Res),
Res is Expr
;
error(default(N), ArithGoal)
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% REDEFINED PREDICATES
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get(X):- repeat, get(input, X), X > 32, X < 127, !.
put(X):- N is X, put(output,N).
instance(Ref, Term) :-
referenced_record(Ref, Term).
current_predicate_body(F, T, M) :-
current_predicate_body(F/A, M),
functor(T, F, A),
get_flag_body(F/A, definition_module, M, M).
arg(N, S, X) :-
nonvar(S),
integer(N),
1 =< N, N =< arity(S),
eclipse_language:arg(N, S, X).