passagemath-ecl 10.6.32__cp312-cp312-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-ecl might be problematic. Click here for more details.
- ecl/kenzo.fas +0 -0
- ecl/maxima.fas +0 -0
- passagemath_ecl-10.6.32.dist-info/METADATA +137 -0
- passagemath_ecl-10.6.32.dist-info/METADATA.bak +138 -0
- passagemath_ecl-10.6.32.dist-info/RECORD +221 -0
- passagemath_ecl-10.6.32.dist-info/WHEEL +5 -0
- passagemath_ecl-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_ecl.libs/libecl-393a3b39.so.24.5.10 +0 -0
- passagemath_ecl.libs/libffi-2cda18aa.so.8.1.4 +0 -0
- passagemath_ecl.libs/libgc-a95afae3.so.1.5.4 +0 -0
- passagemath_ecl.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- sage/all__sagemath_ecl.py +4 -0
- sage/interfaces/all__sagemath_ecl.py +1 -0
- sage/interfaces/lisp.py +576 -0
- sage/libs/all__sagemath_ecl.py +1 -0
- sage/libs/ecl.cpython-312-aarch64-linux-musl.so +0 -0
- sage/libs/ecl.pxd +170 -0
- sage/libs/ecl.pyx +1360 -0
- sage/libs/eclsig.h +110 -0
- sage_wheels/bin/ecl +0 -0
- sage_wheels/lib/ecl-24.5.10/COPYING +502 -0
- sage_wheels/lib/ecl-24.5.10/LICENSE +41 -0
- sage_wheels/lib/ecl-24.5.10/TAGS +0 -0
- sage_wheels/lib/ecl-24.5.10/asdf.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/build-stamp +7 -0
- sage_wheels/lib/ecl-24.5.10/cmp.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/cmp.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/deflate.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/deflate.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/defsystem.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/defsystem.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/dpp +0 -0
- sage_wheels/lib/ecl-24.5.10/ecl-cdb.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/ecl-cdb.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/ecl-curl.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/ecl-curl.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/ecl-help.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/ecl-help.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/ecl-quicklisp.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/ecl-quicklisp.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/ecl_min +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/arabic +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ascii +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/asmo-708 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/atarist.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp-856.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp819 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp850 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp862 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp866 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp932 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp936 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp949 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cp950 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/cyrillic +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp437.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp737.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp775.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp850.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp852.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp855.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp857.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp860.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp861.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp862.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp863.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp864.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp865.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp866.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp869.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/dos-cp874.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ecma-114 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ecma-118 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/greek +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/greek8 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/hebrew +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm437 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm819 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm850 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm852 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm855 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm857 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm860 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm861 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm862 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm863 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm864 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm865 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm866 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ibm869 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-2022-jp +55 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-2022-jp-1 +57 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-1.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-10.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-11.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-13.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-14.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-15.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-16.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-2.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-3.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-4.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-5.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-6.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-7.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-8.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-9.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-1 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-10 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-13 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-14 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-15 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-2 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-3 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-4 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-5 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-6 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-7 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-8 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/iso8859-9 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/jisx0201.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/jisx0208.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/jisx0212.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/koi8-r.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/koi8-u.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/koi8r +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-1 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-2 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-3 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-4 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-5 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-6 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-7 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-8 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin-9 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin2 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin3 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin4 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin5 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin6 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin7 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin8 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/latin9 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ms-ansi +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ms-arab +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ms-cyrl +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ms-ee +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ms-greek +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ms-hebr +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ms-turk +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/shift-jis.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/tools.lisp +202 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ucs2 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ucs2be +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ucs2le +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ucs4 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ucs4be +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/ucs4le +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/unicode +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf-16 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf-16be +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf-16le +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf-32 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf-32be +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf-32le +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf16 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf32 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/utf8 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/winbaltrim +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1250 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1251 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1252 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1253 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1254 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1255 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1256 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1257 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-1258 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-932 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-936 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-949 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-950 +1 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1250.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1251.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1252.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1253.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1254.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1255.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1256.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1257.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1258.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp932.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp936.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp949.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/encodings/windows-cp950.bin +0 -0
- sage_wheels/lib/ecl-24.5.10/help.doc +0 -0
- sage_wheels/lib/ecl-24.5.10/libasdf.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libcmp.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libdeflate.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libdefsystem.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libecl-cdb.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libecl-curl.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libecl-help.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libecl-quicklisp.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libpackage-locks.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libql-minitar.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libsb-bsd-sockets.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libserve-event.a +0 -0
- sage_wheels/lib/ecl-24.5.10/libsockets.a +0 -0
- sage_wheels/lib/ecl-24.5.10/package-locks.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/package-locks.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/prebuilt-asdf.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/ql-minitar.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/ql-minitar.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/sb-bsd-sockets.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/sb-bsd-sockets.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/serve-event.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/serve-event.fas +0 -0
- sage_wheels/lib/ecl-24.5.10/sockets.asd +5 -0
- sage_wheels/lib/ecl-24.5.10/sockets.fas +0 -0
- sage_wheels/lib/maxima/5.47.0/binary-ecl/maxima +0 -0
sage/libs/ecl.pyx
ADDED
|
@@ -0,0 +1,1360 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ecl
|
|
2
|
+
"""
|
|
3
|
+
Library interface to Embeddable Common Lisp (ECL)
|
|
4
|
+
"""
|
|
5
|
+
# ****************************************************************************
|
|
6
|
+
# Copyright (C) 2009 Nils Bruin <nbruin@sfu.ca>
|
|
7
|
+
#
|
|
8
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
9
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
10
|
+
# the License, or (at your option) any later version.
|
|
11
|
+
# https://www.gnu.org/licenses/
|
|
12
|
+
# ****************************************************************************
|
|
13
|
+
|
|
14
|
+
# This version of the library interface prefers to convert ECL integers and
|
|
15
|
+
# rationals to Sage types Integer and Rational. These parts could easily be
|
|
16
|
+
# adapted to work with pure Python types.
|
|
17
|
+
|
|
18
|
+
from libc.stdlib cimport abort
|
|
19
|
+
from libc.signal cimport SIGINT, SIGBUS, SIGFPE, SIGSEGV
|
|
20
|
+
from libc.signal cimport raise_ as signal_raise
|
|
21
|
+
from posix.signal cimport sigaction, sigaction_t
|
|
22
|
+
cimport cysignals.signals
|
|
23
|
+
|
|
24
|
+
from sage.libs.gmp.types cimport mpz_t
|
|
25
|
+
from sage.cpython.string cimport str_to_bytes, char_to_str
|
|
26
|
+
from sage.rings.integer cimport Integer
|
|
27
|
+
from sage.rings.rational cimport Rational
|
|
28
|
+
from cpython.object cimport Py_EQ, Py_NE
|
|
29
|
+
|
|
30
|
+
# it would be preferable to let bint_symbolp wrap an efficient macro
|
|
31
|
+
# but the macro provided in object.h doesn't seem to work
|
|
32
|
+
cdef bint bint_symbolp(cl_object obj) noexcept:
|
|
33
|
+
return not(cl_symbolp(obj) == ECL_NIL)
|
|
34
|
+
|
|
35
|
+
# these type predicates are only provided in "cl_*" form, so we wrap them
|
|
36
|
+
# with the proper type cast.
|
|
37
|
+
|
|
38
|
+
cdef bint bint_integerp(cl_object obj) noexcept:
|
|
39
|
+
return not(cl_integerp(obj) == ECL_NIL)
|
|
40
|
+
cdef bint bint_rationalp(cl_object obj) noexcept:
|
|
41
|
+
return not(cl_rationalp(obj) == ECL_NIL)
|
|
42
|
+
|
|
43
|
+
cdef bint bint_base_string_p(cl_object obj) noexcept:
|
|
44
|
+
return not(si_base_string_p(obj) == ECL_NIL)
|
|
45
|
+
|
|
46
|
+
cdef extern from "eclsig.h":
|
|
47
|
+
int ecl_sig_on() except 0
|
|
48
|
+
void ecl_sig_off()
|
|
49
|
+
cdef sigaction_t ecl_sigint_handler
|
|
50
|
+
cdef sigaction_t ecl_sigbus_handler
|
|
51
|
+
cdef sigaction_t ecl_sigfpe_handler
|
|
52
|
+
cdef sigaction_t ecl_sigsegv_handler
|
|
53
|
+
cdef mpz_t ecl_mpz_from_bignum(cl_object obj)
|
|
54
|
+
cdef cl_object ecl_bignum_from_mpz(mpz_t num)
|
|
55
|
+
cdef cl_object conditions_to_handle_clobj
|
|
56
|
+
void safe_cl_boot(int argc, char** argv)
|
|
57
|
+
cl_object safe_cl_funcall(cl_object *error, cl_object fun, cl_object arg)
|
|
58
|
+
cl_object safe_cl_apply(cl_object *error, cl_object fun, cl_object args)
|
|
59
|
+
cl_object safe_cl_eval(cl_object *error, cl_object form)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
cdef cl_object string_to_object(char * s) noexcept:
|
|
63
|
+
return ecl_read_from_cstring(s)
|
|
64
|
+
|
|
65
|
+
# We need to keep a list of objects bound to python, to protect them from being
|
|
66
|
+
# garbage collected. We want a list in which we can quickly add and remove
|
|
67
|
+
# elements. Lookup is not necessary. A doubly linked list seems
|
|
68
|
+
# most appropriate. A node looks like
|
|
69
|
+
# N = ( value next . prev)
|
|
70
|
+
# so that car(N)=value, cadr(N)=next, cddr(N)=prev.
|
|
71
|
+
# we write routines to insert a node after a given node
|
|
72
|
+
# and to delete a given node. This can all be done with modifying pointers.
|
|
73
|
+
# note that circular structures are unpleasant for most lisp routines.
|
|
74
|
+
# perhaps this even puts a strain on the garbage collector?
|
|
75
|
+
# an alternative data structure would be an array where the free nodes get
|
|
76
|
+
# chained in a "free list" for quick allocation (and if the free list is empty
|
|
77
|
+
# upon allocating a node, the array needs to be extended)
|
|
78
|
+
|
|
79
|
+
cdef cl_object insert_node_after(cl_object node, cl_object value) noexcept:
|
|
80
|
+
cdef cl_object next, newnode
|
|
81
|
+
|
|
82
|
+
next = cl_cadr(node)
|
|
83
|
+
newnode = cl_cons(value, cl_cons(next, node))
|
|
84
|
+
cl_rplaca(cl_cdr(node), newnode)
|
|
85
|
+
if next != ECL_NIL:
|
|
86
|
+
cl_rplacd(cl_cdr(next), newnode)
|
|
87
|
+
return newnode
|
|
88
|
+
|
|
89
|
+
cdef void remove_node(cl_object node) noexcept:
|
|
90
|
+
cdef cl_object next, prev
|
|
91
|
+
next = cl_cadr(node)
|
|
92
|
+
prev = cl_cddr(node)
|
|
93
|
+
if next != ECL_NIL:
|
|
94
|
+
cl_rplacd(cl_cdr(next), prev)
|
|
95
|
+
if prev != ECL_NIL:
|
|
96
|
+
cl_rplaca(cl_cdr(prev), next)
|
|
97
|
+
|
|
98
|
+
# our global list of pointers. This will be a pointer to a sentinel node,
|
|
99
|
+
# after which all new nodes can be inserted. list_of_object gets initialised
|
|
100
|
+
# by init_ecl() and bound to the global ECL variable *SAGE-LIST-OF-OBJECTS*
|
|
101
|
+
|
|
102
|
+
cdef cl_object list_of_objects
|
|
103
|
+
|
|
104
|
+
cdef cl_object read_from_string_clobj # our own error catching reader
|
|
105
|
+
cdef cl_object make_unicode_string_clobj
|
|
106
|
+
cdef cl_object unicode_string_codepoints_clobj
|
|
107
|
+
|
|
108
|
+
cdef bint ecl_has_booted = 0
|
|
109
|
+
|
|
110
|
+
cdef char *argv = "sage"
|
|
111
|
+
# we need a dummy argv for cl_boot (we just don't give any parameters)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
# ECL signal handling
|
|
115
|
+
|
|
116
|
+
def test_sigint_before_ecl_sig_on():
|
|
117
|
+
"""
|
|
118
|
+
TESTS:
|
|
119
|
+
|
|
120
|
+
If an interrupt arrives *before* ecl_sig_on(), we should get an
|
|
121
|
+
ordinary KeyboardInterrupt::
|
|
122
|
+
|
|
123
|
+
sage: from sage.libs.ecl import test_sigint_before_ecl_sig_on
|
|
124
|
+
sage: test_sigint_before_ecl_sig_on()
|
|
125
|
+
Traceback (most recent call last):
|
|
126
|
+
...
|
|
127
|
+
KeyboardInterrupt
|
|
128
|
+
"""
|
|
129
|
+
# Raise a SIGINT *now*. Since we are outside of sig_on() at this
|
|
130
|
+
# point, this SIGINT will not be seen yet.
|
|
131
|
+
signal_raise(SIGINT)
|
|
132
|
+
# An ordinary KeyboardInterrupt should be raised by ecl_sig_on()
|
|
133
|
+
# since ecl_sig_on() calls sig_on() before anything else. This
|
|
134
|
+
# will catch the pending SIGINT.
|
|
135
|
+
ecl_sig_on()
|
|
136
|
+
# We should never get here.
|
|
137
|
+
abort()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_ecl_options():
|
|
141
|
+
"""
|
|
142
|
+
Print an overview of the ECL options.
|
|
143
|
+
|
|
144
|
+
TESTS::
|
|
145
|
+
|
|
146
|
+
sage: from sage.libs.ecl import test_ecl_options
|
|
147
|
+
sage: test_ecl_options()
|
|
148
|
+
ECL_OPT_INCREMENTAL_GC = 0
|
|
149
|
+
ECL_OPT_TRAP_SIGSEGV = 1
|
|
150
|
+
ECL_OPT_TRAP_SIGFPE = 1
|
|
151
|
+
ECL_OPT_TRAP_SIGINT = 1
|
|
152
|
+
ECL_OPT_TRAP_SIGILL = 1
|
|
153
|
+
ECL_OPT_TRAP_SIGBUS = 1
|
|
154
|
+
ECL_OPT_TRAP_SIGPIPE = 1
|
|
155
|
+
ECL_OPT_TRAP_INTERRUPT_SIGNAL = 1
|
|
156
|
+
ECL_OPT_SIGNAL_HANDLING_THREAD = 0
|
|
157
|
+
ECL_OPT_SIGNAL_QUEUE_SIZE = 16
|
|
158
|
+
ECL_OPT_BOOTED = 1
|
|
159
|
+
ECL_OPT_BIND_STACK_SIZE = ...
|
|
160
|
+
ECL_OPT_BIND_STACK_SAFETY_AREA = ...
|
|
161
|
+
ECL_OPT_FRAME_STACK_SIZE = ...
|
|
162
|
+
ECL_OPT_FRAME_STACK_SAFETY_AREA = ...
|
|
163
|
+
ECL_OPT_LISP_STACK_SIZE = ...
|
|
164
|
+
ECL_OPT_LISP_STACK_SAFETY_AREA = ...
|
|
165
|
+
ECL_OPT_C_STACK_SIZE = ...
|
|
166
|
+
ECL_OPT_C_STACK_SAFETY_AREA = ...
|
|
167
|
+
ECL_OPT_HEAP_SIZE = ...
|
|
168
|
+
ECL_OPT_HEAP_SAFETY_AREA = ...
|
|
169
|
+
ECL_OPT_THREAD_INTERRUPT_SIGNAL = ...
|
|
170
|
+
ECL_OPT_SET_GMP_MEMORY_FUNCTIONS = 0
|
|
171
|
+
"""
|
|
172
|
+
print('ECL_OPT_INCREMENTAL_GC = {0}'.format(
|
|
173
|
+
ecl_get_option(ECL_OPT_INCREMENTAL_GC)))
|
|
174
|
+
print('ECL_OPT_TRAP_SIGSEGV = {0}'.format(
|
|
175
|
+
ecl_get_option(ECL_OPT_TRAP_SIGSEGV)))
|
|
176
|
+
print('ECL_OPT_TRAP_SIGFPE = {0}'.format(
|
|
177
|
+
ecl_get_option(ECL_OPT_TRAP_SIGFPE)))
|
|
178
|
+
print('ECL_OPT_TRAP_SIGINT = {0}'.format(
|
|
179
|
+
ecl_get_option(ECL_OPT_TRAP_SIGINT)))
|
|
180
|
+
print('ECL_OPT_TRAP_SIGILL = {0}'.format(
|
|
181
|
+
ecl_get_option(ECL_OPT_TRAP_SIGILL)))
|
|
182
|
+
print('ECL_OPT_TRAP_SIGBUS = {0}'.format(
|
|
183
|
+
ecl_get_option(ECL_OPT_TRAP_SIGBUS)))
|
|
184
|
+
print('ECL_OPT_TRAP_SIGPIPE = {0}'.format(
|
|
185
|
+
ecl_get_option(ECL_OPT_TRAP_SIGPIPE)))
|
|
186
|
+
print('ECL_OPT_TRAP_INTERRUPT_SIGNAL = {0}'.format(
|
|
187
|
+
ecl_get_option(ECL_OPT_TRAP_INTERRUPT_SIGNAL)))
|
|
188
|
+
print('ECL_OPT_SIGNAL_HANDLING_THREAD = {0}'.format(
|
|
189
|
+
ecl_get_option(ECL_OPT_SIGNAL_HANDLING_THREAD)))
|
|
190
|
+
print('ECL_OPT_SIGNAL_QUEUE_SIZE = {0}'.format(
|
|
191
|
+
ecl_get_option(ECL_OPT_SIGNAL_QUEUE_SIZE)))
|
|
192
|
+
print('ECL_OPT_BOOTED = {0}'.format(
|
|
193
|
+
ecl_get_option(ECL_OPT_BOOTED)))
|
|
194
|
+
print('ECL_OPT_BIND_STACK_SIZE = {0}'.format(
|
|
195
|
+
ecl_get_option(ECL_OPT_BIND_STACK_SIZE)))
|
|
196
|
+
print('ECL_OPT_BIND_STACK_SAFETY_AREA = {0}'.format(
|
|
197
|
+
ecl_get_option(ECL_OPT_BIND_STACK_SAFETY_AREA)))
|
|
198
|
+
print('ECL_OPT_FRAME_STACK_SIZE = {0}'.format(
|
|
199
|
+
ecl_get_option(ECL_OPT_FRAME_STACK_SIZE)))
|
|
200
|
+
print('ECL_OPT_FRAME_STACK_SAFETY_AREA = {0}'.format(
|
|
201
|
+
ecl_get_option(ECL_OPT_FRAME_STACK_SAFETY_AREA)))
|
|
202
|
+
print('ECL_OPT_LISP_STACK_SIZE = {0}'.format(
|
|
203
|
+
ecl_get_option(ECL_OPT_LISP_STACK_SIZE)))
|
|
204
|
+
print('ECL_OPT_LISP_STACK_SAFETY_AREA = {0}'.format(
|
|
205
|
+
ecl_get_option(ECL_OPT_LISP_STACK_SAFETY_AREA)))
|
|
206
|
+
print('ECL_OPT_C_STACK_SIZE = {0}'.format(
|
|
207
|
+
ecl_get_option(ECL_OPT_C_STACK_SIZE)))
|
|
208
|
+
print('ECL_OPT_C_STACK_SAFETY_AREA = {0}'.format(
|
|
209
|
+
ecl_get_option(ECL_OPT_C_STACK_SAFETY_AREA)))
|
|
210
|
+
print('ECL_OPT_HEAP_SIZE = {0}'.format(
|
|
211
|
+
ecl_get_option(ECL_OPT_HEAP_SIZE)))
|
|
212
|
+
print('ECL_OPT_HEAP_SAFETY_AREA = {0}'.format(
|
|
213
|
+
ecl_get_option(ECL_OPT_HEAP_SAFETY_AREA)))
|
|
214
|
+
print('ECL_OPT_THREAD_INTERRUPT_SIGNAL = {0}'.format(
|
|
215
|
+
ecl_get_option(ECL_OPT_THREAD_INTERRUPT_SIGNAL)))
|
|
216
|
+
print('ECL_OPT_SET_GMP_MEMORY_FUNCTIONS = {0}'.format(
|
|
217
|
+
ecl_get_option(ECL_OPT_SET_GMP_MEMORY_FUNCTIONS)))
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def init_ecl():
|
|
221
|
+
r"""
|
|
222
|
+
Internal function to initialize ecl. Do not call.
|
|
223
|
+
|
|
224
|
+
This function initializes the ECL library for use within Python.
|
|
225
|
+
This routine should only be called once and importing the ecl library
|
|
226
|
+
interface already does that, so do not call this yourself.
|
|
227
|
+
|
|
228
|
+
EXAMPLES::
|
|
229
|
+
|
|
230
|
+
sage: from sage.libs.ecl import *
|
|
231
|
+
|
|
232
|
+
At this point, init_ecl() has run. Explicitly executing it
|
|
233
|
+
gives an error::
|
|
234
|
+
|
|
235
|
+
sage: init_ecl()
|
|
236
|
+
Traceback (most recent call last):
|
|
237
|
+
...
|
|
238
|
+
RuntimeError: ECL is already initialized
|
|
239
|
+
"""
|
|
240
|
+
global list_of_objects
|
|
241
|
+
global read_from_string_clobj
|
|
242
|
+
global conditions_to_handle_clobj
|
|
243
|
+
global ecl_has_booted
|
|
244
|
+
global argv
|
|
245
|
+
cdef sigaction_t sage_action[32]
|
|
246
|
+
cdef int i
|
|
247
|
+
|
|
248
|
+
if ecl_has_booted:
|
|
249
|
+
raise RuntimeError("ECL is already initialized")
|
|
250
|
+
|
|
251
|
+
# we keep our own GMP memory functions. ECL should not claim them
|
|
252
|
+
ecl_set_option(ECL_OPT_SET_GMP_MEMORY_FUNCTIONS, 0)
|
|
253
|
+
|
|
254
|
+
# get all the signal handlers before initializing Sage so we can
|
|
255
|
+
# put them back afterwards.
|
|
256
|
+
for i in range(1, 32):
|
|
257
|
+
sigaction(i, NULL, &sage_action[i])
|
|
258
|
+
|
|
259
|
+
# initialize ECL
|
|
260
|
+
ecl_set_option(ECL_OPT_SIGNAL_HANDLING_THREAD, 0)
|
|
261
|
+
safe_cl_boot(1, &argv)
|
|
262
|
+
|
|
263
|
+
# save signal handler from ECL
|
|
264
|
+
sigaction(SIGINT, NULL, &ecl_sigint_handler)
|
|
265
|
+
sigaction(SIGBUS, NULL, &ecl_sigbus_handler)
|
|
266
|
+
sigaction(SIGFPE, NULL, &ecl_sigfpe_handler)
|
|
267
|
+
sigaction(SIGSEGV, NULL, &ecl_sigsegv_handler)
|
|
268
|
+
|
|
269
|
+
# and put the Sage signal handlers back
|
|
270
|
+
for i in range(1, 32):
|
|
271
|
+
sigaction(i, &sage_action[i], NULL)
|
|
272
|
+
|
|
273
|
+
# initialise list of objects and bind to global variable
|
|
274
|
+
# *SAGE-LIST-OF-OBJECTS* to make it rooted in the reachable tree for the GC
|
|
275
|
+
list_of_objects=cl_cons(ECL_NIL, cl_cons(ECL_NIL, ECL_NIL))
|
|
276
|
+
cl_set(string_to_object(b"*SAGE-LIST-OF-OBJECTS*"), list_of_objects)
|
|
277
|
+
|
|
278
|
+
# We define our own error catching eval, apply and funcall/
|
|
279
|
+
# Presently these routines are only converted to byte-code. If they
|
|
280
|
+
# ever turn out to be a bottle neck, it should be easy to properly
|
|
281
|
+
# compile them.
|
|
282
|
+
|
|
283
|
+
read_from_string_clobj = cl_eval(string_to_object(b"(symbol-function 'read-from-string)"))
|
|
284
|
+
|
|
285
|
+
conditions_to_handle_clobj = ecl_list1(ecl_make_symbol(b"SERIOUS-CONDITION", b"COMMON-LISP"))
|
|
286
|
+
insert_node_after(list_of_objects, conditions_to_handle_clobj)
|
|
287
|
+
|
|
288
|
+
ecl_has_booted = 1
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
cdef ecl_string_to_python(cl_object s):
|
|
292
|
+
if bint_base_string_p(s):
|
|
293
|
+
return char_to_str(ecl_base_string_pointer_safe(s))
|
|
294
|
+
else:
|
|
295
|
+
return ''.join(chr(ecl_char(s, i)) for i in range(ecl_length(s)))
|
|
296
|
+
|
|
297
|
+
cdef cl_object ecl_safe_eval(cl_object form) except NULL:
|
|
298
|
+
"""
|
|
299
|
+
TESTS:
|
|
300
|
+
|
|
301
|
+
Test interrupts::
|
|
302
|
+
|
|
303
|
+
sage: from sage.libs.ecl import *
|
|
304
|
+
sage: from cysignals.tests import interrupt_after_delay
|
|
305
|
+
sage: ecl_eval("(setf i 0)")
|
|
306
|
+
<ECL: 0>
|
|
307
|
+
sage: inf_loop = ecl_eval("(defun infinite() (loop (incf i)))")
|
|
308
|
+
sage: interrupt_after_delay(1000)
|
|
309
|
+
sage: inf_loop()
|
|
310
|
+
Traceback (most recent call last):
|
|
311
|
+
...
|
|
312
|
+
KeyboardInterrupt: ECL says: Console interrupt.
|
|
313
|
+
"""
|
|
314
|
+
cdef cl_object ret, error = NULL
|
|
315
|
+
|
|
316
|
+
ecl_sig_on()
|
|
317
|
+
ret = safe_cl_eval(&error, form)
|
|
318
|
+
ecl_sig_off()
|
|
319
|
+
|
|
320
|
+
if error != NULL:
|
|
321
|
+
message = ecl_string_to_python(error)
|
|
322
|
+
if "Console interrupt" in message:
|
|
323
|
+
raise KeyboardInterrupt("ECL says: {}".format(message))
|
|
324
|
+
else:
|
|
325
|
+
raise RuntimeError("ECL says: {}".format(message))
|
|
326
|
+
else:
|
|
327
|
+
return ret
|
|
328
|
+
|
|
329
|
+
cdef cl_object ecl_safe_funcall(cl_object func, cl_object arg) except NULL:
|
|
330
|
+
cdef cl_object ret, error = NULL
|
|
331
|
+
|
|
332
|
+
ecl_sig_on()
|
|
333
|
+
ret = safe_cl_funcall(&error, func, arg)
|
|
334
|
+
ecl_sig_off()
|
|
335
|
+
|
|
336
|
+
if error != NULL:
|
|
337
|
+
message = ecl_string_to_python(error)
|
|
338
|
+
if "Console interrupt" in message:
|
|
339
|
+
raise KeyboardInterrupt("ECL says: {}".format(message))
|
|
340
|
+
else:
|
|
341
|
+
raise RuntimeError("ECL says: {}".format(message))
|
|
342
|
+
else:
|
|
343
|
+
return ret
|
|
344
|
+
|
|
345
|
+
cdef cl_object ecl_safe_apply(cl_object func, cl_object args) except NULL:
|
|
346
|
+
cdef cl_object ret, error = NULL
|
|
347
|
+
|
|
348
|
+
ecl_sig_on()
|
|
349
|
+
ret = safe_cl_apply(&error, func, args)
|
|
350
|
+
ecl_sig_off()
|
|
351
|
+
|
|
352
|
+
if error != NULL:
|
|
353
|
+
message = ecl_string_to_python(error)
|
|
354
|
+
if "Console interrupt" in message:
|
|
355
|
+
raise KeyboardInterrupt("ECL says: {}".format(message))
|
|
356
|
+
else:
|
|
357
|
+
raise RuntimeError("ECL says: {}".format(message))
|
|
358
|
+
else:
|
|
359
|
+
return ret
|
|
360
|
+
|
|
361
|
+
cdef cl_object ecl_safe_read_string(char * s) except NULL:
|
|
362
|
+
cdef cl_object o
|
|
363
|
+
o = ecl_cstring_to_base_string_or_nil(s)
|
|
364
|
+
o = ecl_safe_funcall(read_from_string_clobj, o)
|
|
365
|
+
return o
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def shutdown_ecl():
|
|
369
|
+
r"""
|
|
370
|
+
Shut down ecl. Do not call.
|
|
371
|
+
|
|
372
|
+
Given the way that ECL is used from python, it is very difficult to ensure
|
|
373
|
+
that no ECL objects exist at a particular time. Hence, destroying ECL is a
|
|
374
|
+
risky proposition.
|
|
375
|
+
|
|
376
|
+
EXAMPLES::
|
|
377
|
+
|
|
378
|
+
sage: from sage.libs.ecl import *
|
|
379
|
+
sage: shutdown_ecl()
|
|
380
|
+
"""
|
|
381
|
+
cl_shutdown()
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
# this prints the objects that sage wants the GC to keep track of.
|
|
385
|
+
# these should be all non-immediate EclObject wrapped objects
|
|
386
|
+
def print_objects():
|
|
387
|
+
r"""
|
|
388
|
+
Print GC-protection list.
|
|
389
|
+
|
|
390
|
+
Diagnostic function. ECL objects that are bound to Python objects need to
|
|
391
|
+
be protected from being garbage collected. We do this by including them
|
|
392
|
+
in a doubly linked list bound to the global ECL symbol
|
|
393
|
+
*SAGE-LIST-OF-OBJECTS*. Only non-immediate values get included, so
|
|
394
|
+
small integers do not get linked in. This routine prints the values
|
|
395
|
+
currently stored.
|
|
396
|
+
|
|
397
|
+
EXAMPLES::
|
|
398
|
+
|
|
399
|
+
sage: from sage.libs.ecl import *
|
|
400
|
+
sage: a=EclObject("hello")
|
|
401
|
+
sage: b=EclObject(10)
|
|
402
|
+
sage: c=EclObject("world")
|
|
403
|
+
sage: print_objects() #random because previous test runs can have left objects
|
|
404
|
+
NIL
|
|
405
|
+
WORLD
|
|
406
|
+
HELLO
|
|
407
|
+
"""
|
|
408
|
+
|
|
409
|
+
cdef cl_object c, s
|
|
410
|
+
c = list_of_objects
|
|
411
|
+
while True:
|
|
412
|
+
|
|
413
|
+
s = cl_write_to_string(1, cl_car(c))
|
|
414
|
+
print(ecl_string_to_python(s))
|
|
415
|
+
|
|
416
|
+
c = cl_cadr(c)
|
|
417
|
+
if c == ECL_NIL:
|
|
418
|
+
break
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
cdef cl_object python_to_ecl(pyobj, bint read_strings) except NULL:
|
|
422
|
+
# conversion of a python object into an ecl object
|
|
423
|
+
# most conversions are straightforward. Noteworthy are:
|
|
424
|
+
# python lists -> lisp (NIL terminated) lists
|
|
425
|
+
# tuples -> dotted lists
|
|
426
|
+
# strings -> if read_strings is true, parsed by lisp reader
|
|
427
|
+
# otherwise creates a simple-string
|
|
428
|
+
|
|
429
|
+
cdef bytes s
|
|
430
|
+
cdef cl_object L, o
|
|
431
|
+
|
|
432
|
+
if isinstance(pyobj, bool):
|
|
433
|
+
if pyobj:
|
|
434
|
+
return ECL_T
|
|
435
|
+
else:
|
|
436
|
+
return ECL_NIL
|
|
437
|
+
elif pyobj is None:
|
|
438
|
+
return ECL_NIL
|
|
439
|
+
elif isinstance(pyobj, int):
|
|
440
|
+
if MOST_NEGATIVE_FIXNUM <= pyobj <= MOST_POSITIVE_FIXNUM:
|
|
441
|
+
return ecl_make_integer(pyobj)
|
|
442
|
+
else:
|
|
443
|
+
return python_to_ecl(Integer(pyobj), read_strings)
|
|
444
|
+
elif isinstance(pyobj, float):
|
|
445
|
+
return ecl_make_doublefloat(pyobj)
|
|
446
|
+
elif isinstance(pyobj, unicode):
|
|
447
|
+
try:
|
|
448
|
+
s = str_to_bytes(pyobj, 'ascii')
|
|
449
|
+
except UnicodeEncodeError:
|
|
450
|
+
o = cl_make_string(1, ecl_make_fixnum(len(pyobj)))
|
|
451
|
+
for i in range(len(pyobj)):
|
|
452
|
+
ecl_char_set(o, i, ord(pyobj[i]))
|
|
453
|
+
else:
|
|
454
|
+
o = ecl_cstring_to_base_string_or_nil(s)
|
|
455
|
+
|
|
456
|
+
if read_strings:
|
|
457
|
+
return ecl_safe_funcall(read_from_string_clobj, o)
|
|
458
|
+
else:
|
|
459
|
+
return o
|
|
460
|
+
elif isinstance(pyobj, bytes):
|
|
461
|
+
s = <bytes>pyobj
|
|
462
|
+
if read_strings:
|
|
463
|
+
return ecl_safe_read_string(s)
|
|
464
|
+
else:
|
|
465
|
+
return ecl_cstring_to_base_string_or_nil(s)
|
|
466
|
+
elif isinstance(pyobj, Integer):
|
|
467
|
+
if pyobj >= MOST_NEGATIVE_FIXNUM and pyobj <= MOST_POSITIVE_FIXNUM:
|
|
468
|
+
return ecl_make_integer(pyobj)
|
|
469
|
+
else:
|
|
470
|
+
return ecl_bignum_from_mpz((<Integer>pyobj).value)
|
|
471
|
+
elif isinstance(pyobj, Rational):
|
|
472
|
+
return ecl_make_ratio(
|
|
473
|
+
python_to_ecl((<Rational>pyobj).numerator(), read_strings),
|
|
474
|
+
python_to_ecl((<Rational>pyobj).denominator(), read_strings))
|
|
475
|
+
elif isinstance(pyobj, EclObject):
|
|
476
|
+
return (<EclObject>pyobj).obj
|
|
477
|
+
elif isinstance(pyobj, list):
|
|
478
|
+
L = ECL_NIL
|
|
479
|
+
for i in range(len(pyobj) - 1, -1, -1):
|
|
480
|
+
L = cl_cons(python_to_ecl(pyobj[i], read_strings), L)
|
|
481
|
+
return L
|
|
482
|
+
elif isinstance(pyobj, tuple):
|
|
483
|
+
if not pyobj:
|
|
484
|
+
return ECL_NIL
|
|
485
|
+
else:
|
|
486
|
+
L = python_to_ecl(pyobj[-1], read_strings)
|
|
487
|
+
for i in range(len(pyobj) - 2, -1, -1):
|
|
488
|
+
L = cl_cons(python_to_ecl(pyobj[i], read_strings), L)
|
|
489
|
+
return L
|
|
490
|
+
else:
|
|
491
|
+
raise TypeError("Unimplemented type for python_to_ecl")
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
cdef ecl_to_python(cl_object o):
|
|
495
|
+
cdef cl_object s
|
|
496
|
+
cdef Integer N
|
|
497
|
+
# conversions from an ecl object to a python object.
|
|
498
|
+
|
|
499
|
+
if o == ECL_NIL:
|
|
500
|
+
return None
|
|
501
|
+
elif bint_fixnump(o):
|
|
502
|
+
# Sage specific conversion
|
|
503
|
+
# return ecl_fixint(o)
|
|
504
|
+
return Integer(ecl_fixint(o))
|
|
505
|
+
elif bint_integerp(o):
|
|
506
|
+
# Sage specific conversion
|
|
507
|
+
N = Integer.__new__(Integer)
|
|
508
|
+
N.set_from_mpz(ecl_mpz_from_bignum(o))
|
|
509
|
+
return N
|
|
510
|
+
elif bint_rationalp(o):
|
|
511
|
+
# Sage specific conversion
|
|
512
|
+
# vanilla python does not have a class to represent rational numbers
|
|
513
|
+
return Rational((ecl_to_python(cl_numerator(o)),
|
|
514
|
+
ecl_to_python(cl_denominator(o))))
|
|
515
|
+
elif bint_floatp(o):
|
|
516
|
+
# Python conversion
|
|
517
|
+
# Since Sage mainly uses mpfr, perhaps "double is not an appropriate return type
|
|
518
|
+
return ecl_to_double(o)
|
|
519
|
+
elif o == ECL_T:
|
|
520
|
+
return True
|
|
521
|
+
elif bint_consp(o):
|
|
522
|
+
L=[]
|
|
523
|
+
while o != ECL_NIL:
|
|
524
|
+
L.append(ecl_to_python(cl_car(o)))
|
|
525
|
+
o = cl_cdr(o)
|
|
526
|
+
if not(bint_listp(o)):
|
|
527
|
+
L.append(ecl_to_python(o))
|
|
528
|
+
return tuple(L)
|
|
529
|
+
return L
|
|
530
|
+
else:
|
|
531
|
+
s = cl_write_to_string(1, o)
|
|
532
|
+
return ecl_string_to_python(s)
|
|
533
|
+
|
|
534
|
+
# Maxima's BFLOAT multiprecision float type can be read with:
|
|
535
|
+
# def bfloat_to_python(e):
|
|
536
|
+
# prec=Integer(str(e.car().cddr().car()))
|
|
537
|
+
# mant=Integer(str(e.cdr().car()))
|
|
538
|
+
# exp=Integer(str(e.cddr().car()))
|
|
539
|
+
# return 2^(exp-prec)*mant
|
|
540
|
+
|
|
541
|
+
cdef class EclObject:
|
|
542
|
+
r"""
|
|
543
|
+
Python wrapper of ECL objects
|
|
544
|
+
|
|
545
|
+
The ``EclObject`` forms a wrapper around ECL objects. The wrapper ensures
|
|
546
|
+
that the data structure pointed to is protected from garbage collection in
|
|
547
|
+
ECL by installing a pointer to it from a global data structure within the
|
|
548
|
+
scope of the ECL garbage collector. This pointer is destroyed upon
|
|
549
|
+
destruction of the EclObject.
|
|
550
|
+
|
|
551
|
+
EclObject() takes a Python object and tries to find a representation of it
|
|
552
|
+
in Lisp.
|
|
553
|
+
|
|
554
|
+
EXAMPLES:
|
|
555
|
+
|
|
556
|
+
Python lists get mapped to LISP lists. None and Boolean values to
|
|
557
|
+
appropriate values in LISP::
|
|
558
|
+
|
|
559
|
+
sage: from sage.libs.ecl import *
|
|
560
|
+
sage: EclObject([None,true,false])
|
|
561
|
+
<ECL: (NIL T NIL)>
|
|
562
|
+
|
|
563
|
+
Numerical values are translated to the appropriate type in LISP::
|
|
564
|
+
|
|
565
|
+
sage: EclObject(1)
|
|
566
|
+
<ECL: 1>
|
|
567
|
+
sage: EclObject(10**40)
|
|
568
|
+
<ECL: 10000000000000000000000000000000000000000>
|
|
569
|
+
|
|
570
|
+
Floats in Python are IEEE double, which LISP has as well. However,
|
|
571
|
+
the printing of floating point types in LISP depends on settings::
|
|
572
|
+
|
|
573
|
+
sage: a = EclObject(float(1.234e40))
|
|
574
|
+
sage: ecl_eval("(setf *read-default-float-format* 'single-float)")
|
|
575
|
+
<ECL: SINGLE-FLOAT>
|
|
576
|
+
sage: a
|
|
577
|
+
<ECL: 1.234d40>
|
|
578
|
+
sage: ecl_eval("(setf *read-default-float-format* 'double-float)")
|
|
579
|
+
<ECL: DOUBLE-FLOAT>
|
|
580
|
+
sage: a
|
|
581
|
+
<ECL: 1.234e40>
|
|
582
|
+
|
|
583
|
+
Tuples are translated to dotted lists::
|
|
584
|
+
|
|
585
|
+
sage: EclObject( (false, true))
|
|
586
|
+
<ECL: (NIL . T)>
|
|
587
|
+
sage: EclObject( (1, 2, 3) )
|
|
588
|
+
<ECL: (1 2 . 3)>
|
|
589
|
+
|
|
590
|
+
Strings are fed to the reader, so a string normally results in a symbol::
|
|
591
|
+
|
|
592
|
+
sage: EclObject("Symbol")
|
|
593
|
+
<ECL: SYMBOL>
|
|
594
|
+
|
|
595
|
+
But with proper quotation one can construct a lisp string object too::
|
|
596
|
+
|
|
597
|
+
sage: EclObject('"Symbol"')
|
|
598
|
+
<ECL: "Symbol">
|
|
599
|
+
|
|
600
|
+
Or any other object that the Lisp reader can construct::
|
|
601
|
+
|
|
602
|
+
sage: EclObject('#("I" am "just" a "simple" vector)')
|
|
603
|
+
<ECL: #("I" AM "just" A "simple" VECTOR)>
|
|
604
|
+
|
|
605
|
+
By means of Lisp reader macros, you can include arbitrary objects::
|
|
606
|
+
|
|
607
|
+
sage: EclObject([ 1, 2, '''#.(make-hash-table :test #'equal)''', 4])
|
|
608
|
+
<ECL: (1 2 #<hash-table ...> 4)>
|
|
609
|
+
|
|
610
|
+
Using an optional argument, you can control how strings are handled::
|
|
611
|
+
|
|
612
|
+
sage: EclObject("String", False)
|
|
613
|
+
<ECL: "String">
|
|
614
|
+
sage: EclObject('#(I may look like a vector but I am a string)', False)
|
|
615
|
+
<ECL: "#(I may look like a vector but I am a string)">
|
|
616
|
+
|
|
617
|
+
This also affects strings within nested lists and tuples ::
|
|
618
|
+
|
|
619
|
+
sage: EclObject([1, 2, "String", 4], False)
|
|
620
|
+
<ECL: (1 2 "String" 4)>
|
|
621
|
+
|
|
622
|
+
EclObjects translate to themselves, so one can mix::
|
|
623
|
+
|
|
624
|
+
sage: EclObject([1,2, EclObject([3])])
|
|
625
|
+
<ECL: (1 2 (3))>
|
|
626
|
+
|
|
627
|
+
Calling an EclObject translates into the appropriate LISP ``apply``,
|
|
628
|
+
where the argument is transformed into an EclObject itself, so one can
|
|
629
|
+
flexibly apply LISP functions::
|
|
630
|
+
|
|
631
|
+
sage: car = EclObject("car")
|
|
632
|
+
sage: cdr = EclObject("cdr")
|
|
633
|
+
sage: car(cdr([1,2,3]))
|
|
634
|
+
<ECL: 2>
|
|
635
|
+
|
|
636
|
+
and even construct and evaluate arbitrary S-expressions::
|
|
637
|
+
|
|
638
|
+
sage: eval=EclObject("eval")
|
|
639
|
+
sage: quote=EclObject("quote")
|
|
640
|
+
sage: eval([car, [cdr, [quote,[1,2,3]]]])
|
|
641
|
+
<ECL: 2>
|
|
642
|
+
|
|
643
|
+
TESTS:
|
|
644
|
+
|
|
645
|
+
We check that multiprecision integers are converted correctly::
|
|
646
|
+
|
|
647
|
+
sage: i = 10 ^ (10 ^ 5)
|
|
648
|
+
sage: EclObject(i) == EclObject(str(i))
|
|
649
|
+
True
|
|
650
|
+
sage: EclObject(-i) == EclObject(str(-i))
|
|
651
|
+
True
|
|
652
|
+
sage: EclObject(i).python() == i
|
|
653
|
+
True
|
|
654
|
+
sage: EclObject(-i).python() == -i
|
|
655
|
+
True
|
|
656
|
+
|
|
657
|
+
We check that symbols with Unicode names are converted correctly::
|
|
658
|
+
|
|
659
|
+
sage: EclObject('λ')
|
|
660
|
+
<ECL: Λ>
|
|
661
|
+
sage: EclObject('|λ|')
|
|
662
|
+
<ECL: |λ|>
|
|
663
|
+
|
|
664
|
+
We check that Unicode strings are converted correctly::
|
|
665
|
+
|
|
666
|
+
sage: EclObject('"Mαξιμα"')
|
|
667
|
+
<ECL: "Mαξιμα">
|
|
668
|
+
"""
|
|
669
|
+
cdef cl_object obj # the wrapped object
|
|
670
|
+
cdef cl_object node # linked list pointer: car(node) == obj
|
|
671
|
+
|
|
672
|
+
cdef void set_obj(EclObject self, cl_object o) noexcept:
|
|
673
|
+
if self.node:
|
|
674
|
+
remove_node(self.node)
|
|
675
|
+
self.node = NULL
|
|
676
|
+
self.obj = o
|
|
677
|
+
if not(bint_fixnump(o) or bint_characterp(o) or bint_nullp(o)):
|
|
678
|
+
self.node=insert_node_after(list_of_objects, o)
|
|
679
|
+
|
|
680
|
+
def __init__(self, *args):
|
|
681
|
+
r"""
|
|
682
|
+
Create an EclObject.
|
|
683
|
+
|
|
684
|
+
See EclObject for full documentation.
|
|
685
|
+
|
|
686
|
+
EXAMPLES::
|
|
687
|
+
|
|
688
|
+
sage: from sage.libs.ecl import *
|
|
689
|
+
sage: EclObject([None,true,false])
|
|
690
|
+
<ECL: (NIL T NIL)>
|
|
691
|
+
"""
|
|
692
|
+
if not args:
|
|
693
|
+
return
|
|
694
|
+
elif len(args) == 1:
|
|
695
|
+
self.set_obj(python_to_ecl(args[0], True))
|
|
696
|
+
elif len(args) == 2:
|
|
697
|
+
self.set_obj(python_to_ecl(args[0], args[1]))
|
|
698
|
+
else:
|
|
699
|
+
raise TypeError('EclObject.__init__ received a wrong number of arguments')
|
|
700
|
+
|
|
701
|
+
def __reduce__(self):
|
|
702
|
+
r"""
|
|
703
|
+
This is used for pickling. Not implemented.
|
|
704
|
+
|
|
705
|
+
Ecl does not natively support serialization of its objects, so the
|
|
706
|
+
python wrapper class EclObject does not support pickling. There are
|
|
707
|
+
independent efforts for developing serialization for Common Lisp, such as
|
|
708
|
+
CL-STORE. Look at those if you need serialization of ECL objects.
|
|
709
|
+
|
|
710
|
+
EXAMPLES::
|
|
711
|
+
|
|
712
|
+
sage: from sage.libs.ecl import *
|
|
713
|
+
sage: s=EclObject([1,2,3])
|
|
714
|
+
sage: s.__reduce__()
|
|
715
|
+
Traceback (most recent call last):
|
|
716
|
+
...
|
|
717
|
+
NotImplementedError: EclObjects do not have a pickling method
|
|
718
|
+
sage: s==loads(dumps(s))
|
|
719
|
+
Traceback (most recent call last):
|
|
720
|
+
...
|
|
721
|
+
NotImplementedError: EclObjects do not have a pickling method
|
|
722
|
+
"""
|
|
723
|
+
raise NotImplementedError("EclObjects do not have a pickling method")
|
|
724
|
+
|
|
725
|
+
def python(self):
|
|
726
|
+
r"""
|
|
727
|
+
Convert an EclObject to a python object.
|
|
728
|
+
|
|
729
|
+
EXAMPLES::
|
|
730
|
+
|
|
731
|
+
sage: from sage.libs.ecl import *
|
|
732
|
+
sage: L = EclObject([1,2,("three",'"four"')])
|
|
733
|
+
sage: L.python()
|
|
734
|
+
[1, 2, ('THREE', '"four"')]
|
|
735
|
+
"""
|
|
736
|
+
return ecl_to_python(self.obj)
|
|
737
|
+
|
|
738
|
+
def __dealloc__(self):
|
|
739
|
+
r"""
|
|
740
|
+
Deallocate EclObject.
|
|
741
|
+
|
|
742
|
+
It is important to remove the GC preventing reference to the object upon
|
|
743
|
+
deletion of the wrapper.
|
|
744
|
+
|
|
745
|
+
EXAMPLES::
|
|
746
|
+
|
|
747
|
+
sage: from sage.libs.ecl import *
|
|
748
|
+
sage: L=EclObject("symbol")
|
|
749
|
+
sage: del L
|
|
750
|
+
"""
|
|
751
|
+
if self.node:
|
|
752
|
+
remove_node(self.node)
|
|
753
|
+
|
|
754
|
+
def __repr__(self):
|
|
755
|
+
r"""
|
|
756
|
+
Produce a string representation suitable for interactive printing.
|
|
757
|
+
|
|
758
|
+
Converts the wrapped LISP object to a string, decorated in such a way that
|
|
759
|
+
it can be recognised as a LISP object.
|
|
760
|
+
|
|
761
|
+
EXAMPLES::
|
|
762
|
+
|
|
763
|
+
sage: from sage.libs.ecl import *
|
|
764
|
+
sage: L=EclObject("symbol")
|
|
765
|
+
sage: repr(L)
|
|
766
|
+
'<ECL: SYMBOL>'
|
|
767
|
+
"""
|
|
768
|
+
return "<ECL: " + str(self) + ">"
|
|
769
|
+
|
|
770
|
+
def __str__(self):
|
|
771
|
+
r"""
|
|
772
|
+
Produce a string representation.
|
|
773
|
+
|
|
774
|
+
Converts the wrapped LISP object to a string and returns that as a Python
|
|
775
|
+
string.
|
|
776
|
+
|
|
777
|
+
EXAMPLES::
|
|
778
|
+
|
|
779
|
+
sage: from sage.libs.ecl import *
|
|
780
|
+
sage: L=EclObject("symbol")
|
|
781
|
+
sage: str(L)
|
|
782
|
+
'SYMBOL'
|
|
783
|
+
"""
|
|
784
|
+
cdef cl_object s
|
|
785
|
+
s = cl_write_to_string(1, self.obj)
|
|
786
|
+
return ecl_string_to_python(s)
|
|
787
|
+
|
|
788
|
+
def __hash__(self):
|
|
789
|
+
r"""
|
|
790
|
+
Return a hash value of the object.
|
|
791
|
+
|
|
792
|
+
Returns the hash value returned by SXHASH, which is a routine that is
|
|
793
|
+
specified in Common Lisp. According to the specification, lisp objects that
|
|
794
|
+
are EQUAL have the same SXHASH value. Since two EclObjects are equal if
|
|
795
|
+
their wrapped objects are EQUAL according to lisp, this is compatible with
|
|
796
|
+
Python's concept of hash values.
|
|
797
|
+
|
|
798
|
+
It is not possible to enforce immutability of lisp objects, so care should
|
|
799
|
+
be taken in using EclObjects as dictionary keys.
|
|
800
|
+
|
|
801
|
+
EXAMPLES::
|
|
802
|
+
|
|
803
|
+
sage: from sage.libs.ecl import *
|
|
804
|
+
sage: L=EclObject([1,2])
|
|
805
|
+
sage: L
|
|
806
|
+
<ECL: (1 2)>
|
|
807
|
+
sage: hash(L) #random
|
|
808
|
+
463816586
|
|
809
|
+
sage: L.rplacd(EclObject(3))
|
|
810
|
+
sage: L
|
|
811
|
+
<ECL: (1 . 3)>
|
|
812
|
+
sage: hash(L) #random
|
|
813
|
+
140404060
|
|
814
|
+
"""
|
|
815
|
+
return ecl_fixint(cl_sxhash(self.obj))
|
|
816
|
+
|
|
817
|
+
def __call__(self, *args):
|
|
818
|
+
r"""
|
|
819
|
+
Apply ``self`` to arguments.
|
|
820
|
+
|
|
821
|
+
EXAMPLES::
|
|
822
|
+
|
|
823
|
+
sage: from sage.libs.ecl import *
|
|
824
|
+
sage: sqr=EclObject("(lambda (x) (* x x))").eval()
|
|
825
|
+
sage: sqr(10)
|
|
826
|
+
<ECL: 100>
|
|
827
|
+
"""
|
|
828
|
+
lispargs = EclObject(list(args))
|
|
829
|
+
return ecl_wrap(ecl_safe_apply(self.obj, (<EclObject>lispargs).obj))
|
|
830
|
+
|
|
831
|
+
def __richcmp__(left, right, int op):
|
|
832
|
+
r"""
|
|
833
|
+
Comparison test.
|
|
834
|
+
|
|
835
|
+
An EclObject is not equal to any non-EclObject. Two EclObjects
|
|
836
|
+
are equal if their wrapped lisp objects are EQUAL. Since LISP
|
|
837
|
+
has no universal ordering, less than and greater than tests
|
|
838
|
+
are not implemented for EclObjects.
|
|
839
|
+
|
|
840
|
+
EXAMPLES::
|
|
841
|
+
|
|
842
|
+
sage: from sage.libs.ecl import *
|
|
843
|
+
sage: a=EclObject(1)
|
|
844
|
+
sage: b=EclObject(2)
|
|
845
|
+
sage: a==b
|
|
846
|
+
False
|
|
847
|
+
sage: a<b
|
|
848
|
+
Traceback (most recent call last):
|
|
849
|
+
...
|
|
850
|
+
NotImplementedError: EclObjects can only be compared for equality
|
|
851
|
+
sage: EclObject("<")(a,b)
|
|
852
|
+
<ECL: T>
|
|
853
|
+
"""
|
|
854
|
+
if op == Py_EQ:
|
|
855
|
+
if not(isinstance(left, EclObject) and isinstance(right, EclObject)):
|
|
856
|
+
return False
|
|
857
|
+
else:
|
|
858
|
+
return bint_equal((<EclObject>left).obj, (<EclObject>right).obj)
|
|
859
|
+
elif op == Py_NE:
|
|
860
|
+
if not(isinstance(left, EclObject) and isinstance(right, EclObject)):
|
|
861
|
+
return True
|
|
862
|
+
else:
|
|
863
|
+
return not(bint_equal((<EclObject>left).obj, (<EclObject>right).obj))
|
|
864
|
+
|
|
865
|
+
# Common lisp only seems to be able to compare numeric and string types
|
|
866
|
+
# and does not have generic routines for doing that.
|
|
867
|
+
# we could dispatch based on type here, but that seems
|
|
868
|
+
# inappropriate for an *interface*.
|
|
869
|
+
raise NotImplementedError("EclObjects can only be compared for equality")
|
|
870
|
+
|
|
871
|
+
def __iter__(self):
|
|
872
|
+
r"""
|
|
873
|
+
Implement the iterator protocol for EclObject.
|
|
874
|
+
|
|
875
|
+
EclObject implements the iterator protocol for lists. This means
|
|
876
|
+
one can use an EclObject in the context where an iterator is
|
|
877
|
+
expected (for instance, in a list comprehension or in a for loop).
|
|
878
|
+
The iterator produces EclObjects wrapping the members of the list that
|
|
879
|
+
the original EclObject wraps.
|
|
880
|
+
|
|
881
|
+
The wrappers returned are all newly constructed but refer to the
|
|
882
|
+
original members of the list iterated over. This is usually what is
|
|
883
|
+
intended but, just as in Python, can cause surprises if the original
|
|
884
|
+
object is changed between calls to the iterator.
|
|
885
|
+
|
|
886
|
+
Since EclObject translates Python Lists into LISP lists and Python
|
|
887
|
+
tuples into LISP "dotted" lists (lists for which the final CDR is not
|
|
888
|
+
necessarily NIL), and both these python structures are iterable, the
|
|
889
|
+
corresponding EclObjects are iterable as well.
|
|
890
|
+
|
|
891
|
+
EclObjects that are not lists are not iterable.
|
|
892
|
+
|
|
893
|
+
EXAMPLES::
|
|
894
|
+
|
|
895
|
+
sage: from sage.libs.ecl import *
|
|
896
|
+
sage: [i for i in EclObject("(1 2 3)")]
|
|
897
|
+
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
|
|
898
|
+
sage: [i for i in EclObject("(1 2 . 3)")]
|
|
899
|
+
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
|
|
900
|
+
sage: [i for i in EclObject("NIL")]
|
|
901
|
+
[]
|
|
902
|
+
|
|
903
|
+
TESTS:
|
|
904
|
+
|
|
905
|
+
These show that Python lists and tuples behave as
|
|
906
|
+
described above::
|
|
907
|
+
|
|
908
|
+
sage: [i for i in EclObject([1,2,3])]
|
|
909
|
+
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
|
|
910
|
+
sage: [i for i in EclObject((1,2,3))]
|
|
911
|
+
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
|
|
912
|
+
|
|
913
|
+
This tests that we cannot iterate EclObjects we shouldn't,
|
|
914
|
+
as described above::
|
|
915
|
+
|
|
916
|
+
sage: [i for i in EclObject("T")]
|
|
917
|
+
Traceback (most recent call last):
|
|
918
|
+
...
|
|
919
|
+
TypeError: ECL object is not iterable
|
|
920
|
+
"""
|
|
921
|
+
return EclListIterator(self)
|
|
922
|
+
|
|
923
|
+
def eval(self):
|
|
924
|
+
r"""
|
|
925
|
+
Evaluate object as an S-Expression.
|
|
926
|
+
|
|
927
|
+
EXAMPLES::
|
|
928
|
+
|
|
929
|
+
sage: from sage.libs.ecl import *
|
|
930
|
+
sage: S=EclObject("(+ 1 2)")
|
|
931
|
+
sage: S
|
|
932
|
+
<ECL: (+ 1 2)>
|
|
933
|
+
sage: S.eval()
|
|
934
|
+
<ECL: 3>
|
|
935
|
+
"""
|
|
936
|
+
cdef cl_object o
|
|
937
|
+
o=ecl_safe_eval(self.obj)
|
|
938
|
+
if o == NULL:
|
|
939
|
+
raise RuntimeError("ECL runtime error")
|
|
940
|
+
return ecl_wrap(o)
|
|
941
|
+
|
|
942
|
+
def cons(self, EclObject d):
|
|
943
|
+
r"""
|
|
944
|
+
Apply cons to ``self`` and argument and return the result.
|
|
945
|
+
|
|
946
|
+
EXAMPLES::
|
|
947
|
+
|
|
948
|
+
sage: from sage.libs.ecl import *
|
|
949
|
+
sage: a=EclObject(1)
|
|
950
|
+
sage: b=EclObject(2)
|
|
951
|
+
sage: a.cons(b)
|
|
952
|
+
<ECL: (1 . 2)>
|
|
953
|
+
"""
|
|
954
|
+
return ecl_wrap(cl_cons(self.obj, d.obj))
|
|
955
|
+
|
|
956
|
+
def rplaca(self, EclObject d):
|
|
957
|
+
r"""
|
|
958
|
+
Destructively replace car(self) with d.
|
|
959
|
+
|
|
960
|
+
EXAMPLES::
|
|
961
|
+
|
|
962
|
+
sage: from sage.libs.ecl import *
|
|
963
|
+
sage: L=EclObject((1,2))
|
|
964
|
+
sage: L
|
|
965
|
+
<ECL: (1 . 2)>
|
|
966
|
+
sage: a=EclObject(3)
|
|
967
|
+
sage: L.rplaca(a)
|
|
968
|
+
sage: L
|
|
969
|
+
<ECL: (3 . 2)>
|
|
970
|
+
"""
|
|
971
|
+
if not(bint_consp(self.obj)):
|
|
972
|
+
raise TypeError("rplaca can only be applied to a cons")
|
|
973
|
+
cl_rplaca(self.obj, d.obj)
|
|
974
|
+
|
|
975
|
+
def rplacd(self, EclObject d):
|
|
976
|
+
r"""
|
|
977
|
+
Destructively replace cdr(self) with d.
|
|
978
|
+
|
|
979
|
+
EXAMPLES::
|
|
980
|
+
|
|
981
|
+
sage: from sage.libs.ecl import *
|
|
982
|
+
sage: L=EclObject((1,2))
|
|
983
|
+
sage: L
|
|
984
|
+
<ECL: (1 . 2)>
|
|
985
|
+
sage: a=EclObject(3)
|
|
986
|
+
sage: L.rplacd(a)
|
|
987
|
+
sage: L
|
|
988
|
+
<ECL: (1 . 3)>
|
|
989
|
+
"""
|
|
990
|
+
if not(bint_consp(self.obj)):
|
|
991
|
+
raise TypeError("rplacd can only be applied to a cons")
|
|
992
|
+
cl_rplacd(self.obj, d.obj)
|
|
993
|
+
|
|
994
|
+
def car(self):
|
|
995
|
+
r"""
|
|
996
|
+
Return the car of ``self``.
|
|
997
|
+
|
|
998
|
+
EXAMPLES::
|
|
999
|
+
|
|
1000
|
+
sage: from sage.libs.ecl import *
|
|
1001
|
+
sage: L=EclObject([[1,2],[3,4]])
|
|
1002
|
+
sage: L.car()
|
|
1003
|
+
<ECL: (1 2)>
|
|
1004
|
+
sage: L.cdr()
|
|
1005
|
+
<ECL: ((3 4))>
|
|
1006
|
+
sage: L.caar()
|
|
1007
|
+
<ECL: 1>
|
|
1008
|
+
sage: L.cadr()
|
|
1009
|
+
<ECL: (3 4)>
|
|
1010
|
+
sage: L.cdar()
|
|
1011
|
+
<ECL: (2)>
|
|
1012
|
+
sage: L.cddr()
|
|
1013
|
+
<ECL: NIL>
|
|
1014
|
+
"""
|
|
1015
|
+
if not(bint_consp(self.obj)):
|
|
1016
|
+
raise TypeError("car can only be applied to a cons")
|
|
1017
|
+
return ecl_wrap(cl_car(self.obj))
|
|
1018
|
+
|
|
1019
|
+
def cdr(self):
|
|
1020
|
+
r"""
|
|
1021
|
+
Return the cdr of ``self``.
|
|
1022
|
+
|
|
1023
|
+
EXAMPLES::
|
|
1024
|
+
|
|
1025
|
+
sage: from sage.libs.ecl import *
|
|
1026
|
+
sage: L=EclObject([[1,2],[3,4]])
|
|
1027
|
+
sage: L.car()
|
|
1028
|
+
<ECL: (1 2)>
|
|
1029
|
+
sage: L.cdr()
|
|
1030
|
+
<ECL: ((3 4))>
|
|
1031
|
+
sage: L.caar()
|
|
1032
|
+
<ECL: 1>
|
|
1033
|
+
sage: L.cadr()
|
|
1034
|
+
<ECL: (3 4)>
|
|
1035
|
+
sage: L.cdar()
|
|
1036
|
+
<ECL: (2)>
|
|
1037
|
+
sage: L.cddr()
|
|
1038
|
+
<ECL: NIL>
|
|
1039
|
+
"""
|
|
1040
|
+
if not(bint_consp(self.obj)):
|
|
1041
|
+
raise TypeError("cdr can only be applied to a cons")
|
|
1042
|
+
return ecl_wrap(cl_cdr(self.obj))
|
|
1043
|
+
|
|
1044
|
+
def caar(self):
|
|
1045
|
+
r"""
|
|
1046
|
+
Return the caar of ``self``.
|
|
1047
|
+
|
|
1048
|
+
EXAMPLES::
|
|
1049
|
+
|
|
1050
|
+
sage: from sage.libs.ecl import *
|
|
1051
|
+
sage: L=EclObject([[1,2],[3,4]])
|
|
1052
|
+
sage: L.car()
|
|
1053
|
+
<ECL: (1 2)>
|
|
1054
|
+
sage: L.cdr()
|
|
1055
|
+
<ECL: ((3 4))>
|
|
1056
|
+
sage: L.caar()
|
|
1057
|
+
<ECL: 1>
|
|
1058
|
+
sage: L.cadr()
|
|
1059
|
+
<ECL: (3 4)>
|
|
1060
|
+
sage: L.cdar()
|
|
1061
|
+
<ECL: (2)>
|
|
1062
|
+
sage: L.cddr()
|
|
1063
|
+
<ECL: NIL>
|
|
1064
|
+
"""
|
|
1065
|
+
if not(bint_consp(self.obj) and bint_consp(cl_car(self.obj))):
|
|
1066
|
+
raise TypeError("caar can only be applied to a cons")
|
|
1067
|
+
return ecl_wrap(cl_caar(self.obj))
|
|
1068
|
+
|
|
1069
|
+
def cadr(self):
|
|
1070
|
+
r"""
|
|
1071
|
+
Return the cadr of ``self``.
|
|
1072
|
+
|
|
1073
|
+
EXAMPLES::
|
|
1074
|
+
|
|
1075
|
+
sage: from sage.libs.ecl import *
|
|
1076
|
+
sage: L=EclObject([[1,2],[3,4]])
|
|
1077
|
+
sage: L.car()
|
|
1078
|
+
<ECL: (1 2)>
|
|
1079
|
+
sage: L.cdr()
|
|
1080
|
+
<ECL: ((3 4))>
|
|
1081
|
+
sage: L.caar()
|
|
1082
|
+
<ECL: 1>
|
|
1083
|
+
sage: L.cadr()
|
|
1084
|
+
<ECL: (3 4)>
|
|
1085
|
+
sage: L.cdar()
|
|
1086
|
+
<ECL: (2)>
|
|
1087
|
+
sage: L.cddr()
|
|
1088
|
+
<ECL: NIL>
|
|
1089
|
+
"""
|
|
1090
|
+
if not(bint_consp(self.obj) and bint_consp(cl_cdr(self.obj))):
|
|
1091
|
+
raise TypeError("cadr can only be applied to a cons")
|
|
1092
|
+
return ecl_wrap(cl_cadr(self.obj))
|
|
1093
|
+
|
|
1094
|
+
def cdar(self):
|
|
1095
|
+
r"""
|
|
1096
|
+
Return the cdar of ``self``.
|
|
1097
|
+
|
|
1098
|
+
EXAMPLES::
|
|
1099
|
+
|
|
1100
|
+
sage: from sage.libs.ecl import *
|
|
1101
|
+
sage: L=EclObject([[1,2],[3,4]])
|
|
1102
|
+
sage: L.car()
|
|
1103
|
+
<ECL: (1 2)>
|
|
1104
|
+
sage: L.cdr()
|
|
1105
|
+
<ECL: ((3 4))>
|
|
1106
|
+
sage: L.caar()
|
|
1107
|
+
<ECL: 1>
|
|
1108
|
+
sage: L.cadr()
|
|
1109
|
+
<ECL: (3 4)>
|
|
1110
|
+
sage: L.cdar()
|
|
1111
|
+
<ECL: (2)>
|
|
1112
|
+
sage: L.cddr()
|
|
1113
|
+
<ECL: NIL>
|
|
1114
|
+
"""
|
|
1115
|
+
if not(bint_consp(self.obj) and bint_consp(cl_car(self.obj))):
|
|
1116
|
+
raise TypeError("cdar can only be applied to a cons")
|
|
1117
|
+
return ecl_wrap(cl_cdar(self.obj))
|
|
1118
|
+
|
|
1119
|
+
def cddr(self):
|
|
1120
|
+
r"""
|
|
1121
|
+
Return the cddr of ``self``.
|
|
1122
|
+
|
|
1123
|
+
EXAMPLES::
|
|
1124
|
+
|
|
1125
|
+
sage: from sage.libs.ecl import *
|
|
1126
|
+
sage: L=EclObject([[1,2],[3,4]])
|
|
1127
|
+
sage: L.car()
|
|
1128
|
+
<ECL: (1 2)>
|
|
1129
|
+
sage: L.cdr()
|
|
1130
|
+
<ECL: ((3 4))>
|
|
1131
|
+
sage: L.caar()
|
|
1132
|
+
<ECL: 1>
|
|
1133
|
+
sage: L.cadr()
|
|
1134
|
+
<ECL: (3 4)>
|
|
1135
|
+
sage: L.cdar()
|
|
1136
|
+
<ECL: (2)>
|
|
1137
|
+
sage: L.cddr()
|
|
1138
|
+
<ECL: NIL>
|
|
1139
|
+
"""
|
|
1140
|
+
if not(bint_consp(self.obj) and bint_consp(cl_cdr(self.obj))):
|
|
1141
|
+
raise TypeError("cddr can only be applied to a cons")
|
|
1142
|
+
return ecl_wrap(cl_cddr(self.obj))
|
|
1143
|
+
|
|
1144
|
+
def fixnump(self):
|
|
1145
|
+
r"""
|
|
1146
|
+
Return ``True`` if ``self`` is a fixnum, ``False`` otherwise.
|
|
1147
|
+
|
|
1148
|
+
EXAMPLES::
|
|
1149
|
+
|
|
1150
|
+
sage: from sage.libs.ecl import *
|
|
1151
|
+
sage: EclObject(2**3).fixnump()
|
|
1152
|
+
True
|
|
1153
|
+
sage: EclObject(2**200).fixnump()
|
|
1154
|
+
False
|
|
1155
|
+
"""
|
|
1156
|
+
return bint_fixnump(self.obj)
|
|
1157
|
+
|
|
1158
|
+
def characterp(self):
|
|
1159
|
+
r"""
|
|
1160
|
+
Return ``True`` if ``self`` is a character, ``False`` otherwise.
|
|
1161
|
+
|
|
1162
|
+
Strings are not characters
|
|
1163
|
+
|
|
1164
|
+
EXAMPLES::
|
|
1165
|
+
|
|
1166
|
+
sage: from sage.libs.ecl import *
|
|
1167
|
+
sage: EclObject('"a"').characterp()
|
|
1168
|
+
False
|
|
1169
|
+
"""
|
|
1170
|
+
return bint_characterp(self.obj)
|
|
1171
|
+
|
|
1172
|
+
def nullp(self):
|
|
1173
|
+
r"""
|
|
1174
|
+
Return ``True`` if ``self`` is NIL, ``False`` otherwise.
|
|
1175
|
+
|
|
1176
|
+
EXAMPLES::
|
|
1177
|
+
|
|
1178
|
+
sage: from sage.libs.ecl import *
|
|
1179
|
+
sage: EclObject([]).nullp()
|
|
1180
|
+
True
|
|
1181
|
+
sage: EclObject([[]]).nullp()
|
|
1182
|
+
False
|
|
1183
|
+
"""
|
|
1184
|
+
return bint_nullp(self.obj)
|
|
1185
|
+
|
|
1186
|
+
def listp(self):
|
|
1187
|
+
r"""
|
|
1188
|
+
Return ``True`` if ``self`` is a list, ``False`` otherwise. NIL is a list.
|
|
1189
|
+
|
|
1190
|
+
EXAMPLES::
|
|
1191
|
+
|
|
1192
|
+
sage: from sage.libs.ecl import *
|
|
1193
|
+
sage: EclObject([]).listp()
|
|
1194
|
+
True
|
|
1195
|
+
sage: EclObject([[]]).listp()
|
|
1196
|
+
True
|
|
1197
|
+
"""
|
|
1198
|
+
return bint_listp(self.obj)
|
|
1199
|
+
|
|
1200
|
+
def consp(self):
|
|
1201
|
+
r"""
|
|
1202
|
+
Return ``True`` if ``self`` is a cons, ``False`` otherwise. NIL is not a cons.
|
|
1203
|
+
|
|
1204
|
+
EXAMPLES::
|
|
1205
|
+
|
|
1206
|
+
sage: from sage.libs.ecl import *
|
|
1207
|
+
sage: EclObject([]).consp()
|
|
1208
|
+
False
|
|
1209
|
+
sage: EclObject([[]]).consp()
|
|
1210
|
+
True
|
|
1211
|
+
"""
|
|
1212
|
+
return bint_consp(self.obj)
|
|
1213
|
+
|
|
1214
|
+
def atomp(self):
|
|
1215
|
+
r"""
|
|
1216
|
+
Return ``True`` if ``self`` is atomic, ``False`` otherwise.
|
|
1217
|
+
|
|
1218
|
+
EXAMPLES::
|
|
1219
|
+
|
|
1220
|
+
sage: from sage.libs.ecl import *
|
|
1221
|
+
sage: EclObject([]).atomp()
|
|
1222
|
+
True
|
|
1223
|
+
sage: EclObject([[]]).atomp()
|
|
1224
|
+
False
|
|
1225
|
+
"""
|
|
1226
|
+
return bint_atomp(self.obj)
|
|
1227
|
+
|
|
1228
|
+
def symbolp(self):
|
|
1229
|
+
r"""
|
|
1230
|
+
Return ``True`` if ``self`` is a symbol, ``False`` otherwise.
|
|
1231
|
+
|
|
1232
|
+
EXAMPLES::
|
|
1233
|
+
|
|
1234
|
+
sage: from sage.libs.ecl import *
|
|
1235
|
+
sage: EclObject([]).symbolp()
|
|
1236
|
+
True
|
|
1237
|
+
sage: EclObject([[]]).symbolp()
|
|
1238
|
+
False
|
|
1239
|
+
"""
|
|
1240
|
+
return bint_symbolp(self.obj)
|
|
1241
|
+
|
|
1242
|
+
cdef class EclListIterator:
|
|
1243
|
+
r"""
|
|
1244
|
+
Iterator object for an ECL list
|
|
1245
|
+
|
|
1246
|
+
This class is used to implement the iterator protocol for EclObject.
|
|
1247
|
+
Do not instantiate this class directly but use the iterator method
|
|
1248
|
+
on an EclObject instead. It is an error if the EclObject is not a list.
|
|
1249
|
+
|
|
1250
|
+
EXAMPLES::
|
|
1251
|
+
|
|
1252
|
+
sage: from sage.libs.ecl import *
|
|
1253
|
+
sage: I=EclListIterator(EclObject("(1 2 3)"))
|
|
1254
|
+
sage: type(I)
|
|
1255
|
+
<class 'sage.libs.ecl.EclListIterator'>
|
|
1256
|
+
sage: [i for i in I]
|
|
1257
|
+
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
|
|
1258
|
+
sage: [i for i in EclObject("(1 2 3)")]
|
|
1259
|
+
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
|
|
1260
|
+
sage: EclListIterator(EclObject("1"))
|
|
1261
|
+
Traceback (most recent call last):
|
|
1262
|
+
...
|
|
1263
|
+
TypeError: ECL object is not iterable
|
|
1264
|
+
"""
|
|
1265
|
+
cdef EclObject current
|
|
1266
|
+
|
|
1267
|
+
def __init__(EclListIterator self, EclObject o):
|
|
1268
|
+
r"""
|
|
1269
|
+
Initialize EclListIterator.
|
|
1270
|
+
|
|
1271
|
+
EXAMPLES::
|
|
1272
|
+
|
|
1273
|
+
sage: from sage.libs.ecl import *
|
|
1274
|
+
sage: I=EclListIterator(EclObject("(1 2 3)"))
|
|
1275
|
+
sage: type(I)
|
|
1276
|
+
<class 'sage.libs.ecl.EclListIterator'>
|
|
1277
|
+
"""
|
|
1278
|
+
if not o.listp():
|
|
1279
|
+
raise TypeError("ECL object is not iterable")
|
|
1280
|
+
self.current = ecl_wrap(o.obj)
|
|
1281
|
+
|
|
1282
|
+
def __iter__(EclListIterator self):
|
|
1283
|
+
r"""
|
|
1284
|
+
Return ``self``.
|
|
1285
|
+
|
|
1286
|
+
It seems standard that iterators return themselves if asked to produce
|
|
1287
|
+
an iterator.
|
|
1288
|
+
|
|
1289
|
+
EXAMPLES::
|
|
1290
|
+
|
|
1291
|
+
sage: from sage.libs.ecl import *
|
|
1292
|
+
sage: I=EclListIterator(EclObject("(1 2 3)"))
|
|
1293
|
+
sage: id(I) == id(I.__iter__())
|
|
1294
|
+
True
|
|
1295
|
+
"""
|
|
1296
|
+
return self
|
|
1297
|
+
|
|
1298
|
+
def __next__(EclListIterator self):
|
|
1299
|
+
r"""
|
|
1300
|
+
Get next element from iterator.
|
|
1301
|
+
|
|
1302
|
+
EXAMPLES::
|
|
1303
|
+
|
|
1304
|
+
sage: from sage.libs.ecl import *
|
|
1305
|
+
sage: I=EclListIterator(EclObject("(1 2 3)"))
|
|
1306
|
+
sage: next(I)
|
|
1307
|
+
<ECL: 1>
|
|
1308
|
+
sage: next(I)
|
|
1309
|
+
<ECL: 2>
|
|
1310
|
+
sage: next(I)
|
|
1311
|
+
<ECL: 3>
|
|
1312
|
+
sage: next(I)
|
|
1313
|
+
Traceback (most recent call last):
|
|
1314
|
+
...
|
|
1315
|
+
StopIteration
|
|
1316
|
+
"""
|
|
1317
|
+
|
|
1318
|
+
if self.current.nullp():
|
|
1319
|
+
raise StopIteration
|
|
1320
|
+
elif self.current.consp():
|
|
1321
|
+
r = self.current.car()
|
|
1322
|
+
self.current = self.current.cdr()
|
|
1323
|
+
else:
|
|
1324
|
+
r = self.current
|
|
1325
|
+
self.current = ecl_wrap(ECL_NIL)
|
|
1326
|
+
return r
|
|
1327
|
+
|
|
1328
|
+
# input: a cl-object. Output: EclObject wrapping that.
|
|
1329
|
+
cdef EclObject ecl_wrap(cl_object o):
|
|
1330
|
+
cdef EclObject obj = EclObject.__new__(EclObject)
|
|
1331
|
+
obj.set_obj(o)
|
|
1332
|
+
return obj
|
|
1333
|
+
|
|
1334
|
+
# convenience routine to more easily evaluate strings
|
|
1335
|
+
cpdef EclObject ecl_eval(str s):
|
|
1336
|
+
r"""
|
|
1337
|
+
Read and evaluate string in Lisp and return the result.
|
|
1338
|
+
|
|
1339
|
+
EXAMPLES::
|
|
1340
|
+
|
|
1341
|
+
sage: from sage.libs.ecl import *
|
|
1342
|
+
sage: ecl_eval("(defun fibo (n)(cond((= n 0) 0)((= n 1) 1)(T (+ (fibo (- n 1)) (fibo (- n 2))))))")
|
|
1343
|
+
<ECL: FIBO>
|
|
1344
|
+
sage: ecl_eval("(mapcar 'fibo '(1 2 3 4 5 6 7))")
|
|
1345
|
+
<ECL: (1 1 2 3 5 8 13)>
|
|
1346
|
+
|
|
1347
|
+
TESTS:
|
|
1348
|
+
|
|
1349
|
+
We check that Unicode is handled correctly::
|
|
1350
|
+
|
|
1351
|
+
sage: ecl_eval('''(defun double-struck-number (n) (map 'string #'(lambda (c) (code-char (+ (char-code #\𝟘) (- (char-code c) (char-code #\\0))))) (format nil "~A" n)))''')
|
|
1352
|
+
<ECL: DOUBLE-STRUCK-NUMBER>
|
|
1353
|
+
sage: _(4711)
|
|
1354
|
+
<ECL: "𝟜𝟟𝟙𝟙">
|
|
1355
|
+
"""
|
|
1356
|
+
cdef cl_object o
|
|
1357
|
+
o = ecl_safe_eval(python_to_ecl(s, True))
|
|
1358
|
+
return ecl_wrap(o)
|
|
1359
|
+
|
|
1360
|
+
init_ecl()
|