passagemath-ecl 10.6.33__cp312-cp312-macosx_13_0_arm64.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.

Files changed (221) hide show
  1. ecl/kenzo.fas +0 -0
  2. ecl/maxima.fas +0 -0
  3. passagemath_ecl-10.6.33.dist-info/METADATA +137 -0
  4. passagemath_ecl-10.6.33.dist-info/METADATA.bak +138 -0
  5. passagemath_ecl-10.6.33.dist-info/RECORD +221 -0
  6. passagemath_ecl-10.6.33.dist-info/WHEEL +6 -0
  7. passagemath_ecl-10.6.33.dist-info/top_level.txt +2 -0
  8. passagemath_ecl.dylibs/libecl.24.5.10.dylib +0 -0
  9. passagemath_ecl.dylibs/libffi.8.dylib +0 -0
  10. passagemath_ecl.dylibs/libgc.1.dylib +0 -0
  11. passagemath_ecl.dylibs/libgmp.10.dylib +0 -0
  12. sage/all__sagemath_ecl.py +4 -0
  13. sage/interfaces/all__sagemath_ecl.py +1 -0
  14. sage/interfaces/lisp.py +576 -0
  15. sage/libs/all__sagemath_ecl.py +1 -0
  16. sage/libs/ecl.cpython-312-darwin.so +0 -0
  17. sage/libs/ecl.pxd +170 -0
  18. sage/libs/ecl.pyx +1360 -0
  19. sage/libs/eclsig.h +110 -0
  20. sage_wheels/bin/ecl +0 -0
  21. sage_wheels/lib/ecl-24.5.10/COPYING +502 -0
  22. sage_wheels/lib/ecl-24.5.10/LICENSE +41 -0
  23. sage_wheels/lib/ecl-24.5.10/TAGS +0 -0
  24. sage_wheels/lib/ecl-24.5.10/asdf.fas +0 -0
  25. sage_wheels/lib/ecl-24.5.10/build-stamp +7 -0
  26. sage_wheels/lib/ecl-24.5.10/cmp.asd +5 -0
  27. sage_wheels/lib/ecl-24.5.10/cmp.fas +0 -0
  28. sage_wheels/lib/ecl-24.5.10/deflate.asd +5 -0
  29. sage_wheels/lib/ecl-24.5.10/deflate.fas +0 -0
  30. sage_wheels/lib/ecl-24.5.10/defsystem.asd +5 -0
  31. sage_wheels/lib/ecl-24.5.10/defsystem.fas +0 -0
  32. sage_wheels/lib/ecl-24.5.10/dpp +0 -0
  33. sage_wheels/lib/ecl-24.5.10/ecl-cdb.asd +5 -0
  34. sage_wheels/lib/ecl-24.5.10/ecl-cdb.fas +0 -0
  35. sage_wheels/lib/ecl-24.5.10/ecl-curl.asd +5 -0
  36. sage_wheels/lib/ecl-24.5.10/ecl-curl.fas +0 -0
  37. sage_wheels/lib/ecl-24.5.10/ecl-help.asd +5 -0
  38. sage_wheels/lib/ecl-24.5.10/ecl-help.fas +0 -0
  39. sage_wheels/lib/ecl-24.5.10/ecl-quicklisp.asd +5 -0
  40. sage_wheels/lib/ecl-24.5.10/ecl-quicklisp.fas +0 -0
  41. sage_wheels/lib/ecl-24.5.10/ecl_min +0 -0
  42. sage_wheels/lib/ecl-24.5.10/encodings/arabic +1 -0
  43. sage_wheels/lib/ecl-24.5.10/encodings/ascii +1 -0
  44. sage_wheels/lib/ecl-24.5.10/encodings/asmo-708 +1 -0
  45. sage_wheels/lib/ecl-24.5.10/encodings/atarist.bin +0 -0
  46. sage_wheels/lib/ecl-24.5.10/encodings/cp-856.bin +0 -0
  47. sage_wheels/lib/ecl-24.5.10/encodings/cp819 +1 -0
  48. sage_wheels/lib/ecl-24.5.10/encodings/cp850 +1 -0
  49. sage_wheels/lib/ecl-24.5.10/encodings/cp862 +1 -0
  50. sage_wheels/lib/ecl-24.5.10/encodings/cp866 +1 -0
  51. sage_wheels/lib/ecl-24.5.10/encodings/cp932 +1 -0
  52. sage_wheels/lib/ecl-24.5.10/encodings/cp936 +1 -0
  53. sage_wheels/lib/ecl-24.5.10/encodings/cp949 +1 -0
  54. sage_wheels/lib/ecl-24.5.10/encodings/cp950 +1 -0
  55. sage_wheels/lib/ecl-24.5.10/encodings/cyrillic +1 -0
  56. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp437.bin +0 -0
  57. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp737.bin +0 -0
  58. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp775.bin +0 -0
  59. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp850.bin +0 -0
  60. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp852.bin +0 -0
  61. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp855.bin +0 -0
  62. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp857.bin +0 -0
  63. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp860.bin +0 -0
  64. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp861.bin +0 -0
  65. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp862.bin +0 -0
  66. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp863.bin +0 -0
  67. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp864.bin +0 -0
  68. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp865.bin +0 -0
  69. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp866.bin +0 -0
  70. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp869.bin +0 -0
  71. sage_wheels/lib/ecl-24.5.10/encodings/dos-cp874.bin +0 -0
  72. sage_wheels/lib/ecl-24.5.10/encodings/ecma-114 +1 -0
  73. sage_wheels/lib/ecl-24.5.10/encodings/ecma-118 +1 -0
  74. sage_wheels/lib/ecl-24.5.10/encodings/greek +1 -0
  75. sage_wheels/lib/ecl-24.5.10/encodings/greek8 +1 -0
  76. sage_wheels/lib/ecl-24.5.10/encodings/hebrew +1 -0
  77. sage_wheels/lib/ecl-24.5.10/encodings/ibm437 +1 -0
  78. sage_wheels/lib/ecl-24.5.10/encodings/ibm819 +1 -0
  79. sage_wheels/lib/ecl-24.5.10/encodings/ibm850 +1 -0
  80. sage_wheels/lib/ecl-24.5.10/encodings/ibm852 +1 -0
  81. sage_wheels/lib/ecl-24.5.10/encodings/ibm855 +1 -0
  82. sage_wheels/lib/ecl-24.5.10/encodings/ibm857 +1 -0
  83. sage_wheels/lib/ecl-24.5.10/encodings/ibm860 +1 -0
  84. sage_wheels/lib/ecl-24.5.10/encodings/ibm861 +1 -0
  85. sage_wheels/lib/ecl-24.5.10/encodings/ibm862 +1 -0
  86. sage_wheels/lib/ecl-24.5.10/encodings/ibm863 +1 -0
  87. sage_wheels/lib/ecl-24.5.10/encodings/ibm864 +1 -0
  88. sage_wheels/lib/ecl-24.5.10/encodings/ibm865 +1 -0
  89. sage_wheels/lib/ecl-24.5.10/encodings/ibm866 +1 -0
  90. sage_wheels/lib/ecl-24.5.10/encodings/ibm869 +1 -0
  91. sage_wheels/lib/ecl-24.5.10/encodings/iso-2022-jp +55 -0
  92. sage_wheels/lib/ecl-24.5.10/encodings/iso-2022-jp-1 +57 -0
  93. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-1.bin +0 -0
  94. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-10.bin +0 -0
  95. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-11.bin +0 -0
  96. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-13.bin +0 -0
  97. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-14.bin +0 -0
  98. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-15.bin +0 -0
  99. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-16.bin +0 -0
  100. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-2.bin +0 -0
  101. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-3.bin +0 -0
  102. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-4.bin +0 -0
  103. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-5.bin +0 -0
  104. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-6.bin +0 -0
  105. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-7.bin +0 -0
  106. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-8.bin +0 -0
  107. sage_wheels/lib/ecl-24.5.10/encodings/iso-8859-9.bin +0 -0
  108. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-1 +1 -0
  109. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-10 +1 -0
  110. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-13 +1 -0
  111. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-14 +1 -0
  112. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-15 +1 -0
  113. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-2 +1 -0
  114. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-3 +1 -0
  115. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-4 +1 -0
  116. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-5 +1 -0
  117. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-6 +1 -0
  118. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-7 +1 -0
  119. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-8 +1 -0
  120. sage_wheels/lib/ecl-24.5.10/encodings/iso8859-9 +1 -0
  121. sage_wheels/lib/ecl-24.5.10/encodings/jisx0201.bin +0 -0
  122. sage_wheels/lib/ecl-24.5.10/encodings/jisx0208.bin +0 -0
  123. sage_wheels/lib/ecl-24.5.10/encodings/jisx0212.bin +0 -0
  124. sage_wheels/lib/ecl-24.5.10/encodings/koi8-r.bin +0 -0
  125. sage_wheels/lib/ecl-24.5.10/encodings/koi8-u.bin +0 -0
  126. sage_wheels/lib/ecl-24.5.10/encodings/koi8r +1 -0
  127. sage_wheels/lib/ecl-24.5.10/encodings/latin-1 +1 -0
  128. sage_wheels/lib/ecl-24.5.10/encodings/latin-2 +1 -0
  129. sage_wheels/lib/ecl-24.5.10/encodings/latin-3 +1 -0
  130. sage_wheels/lib/ecl-24.5.10/encodings/latin-4 +1 -0
  131. sage_wheels/lib/ecl-24.5.10/encodings/latin-5 +1 -0
  132. sage_wheels/lib/ecl-24.5.10/encodings/latin-6 +1 -0
  133. sage_wheels/lib/ecl-24.5.10/encodings/latin-7 +1 -0
  134. sage_wheels/lib/ecl-24.5.10/encodings/latin-8 +1 -0
  135. sage_wheels/lib/ecl-24.5.10/encodings/latin-9 +1 -0
  136. sage_wheels/lib/ecl-24.5.10/encodings/latin2 +1 -0
  137. sage_wheels/lib/ecl-24.5.10/encodings/latin3 +1 -0
  138. sage_wheels/lib/ecl-24.5.10/encodings/latin4 +1 -0
  139. sage_wheels/lib/ecl-24.5.10/encodings/latin5 +1 -0
  140. sage_wheels/lib/ecl-24.5.10/encodings/latin6 +1 -0
  141. sage_wheels/lib/ecl-24.5.10/encodings/latin7 +1 -0
  142. sage_wheels/lib/ecl-24.5.10/encodings/latin8 +1 -0
  143. sage_wheels/lib/ecl-24.5.10/encodings/latin9 +1 -0
  144. sage_wheels/lib/ecl-24.5.10/encodings/ms-ansi +1 -0
  145. sage_wheels/lib/ecl-24.5.10/encodings/ms-arab +1 -0
  146. sage_wheels/lib/ecl-24.5.10/encodings/ms-cyrl +1 -0
  147. sage_wheels/lib/ecl-24.5.10/encodings/ms-ee +1 -0
  148. sage_wheels/lib/ecl-24.5.10/encodings/ms-greek +1 -0
  149. sage_wheels/lib/ecl-24.5.10/encodings/ms-hebr +1 -0
  150. sage_wheels/lib/ecl-24.5.10/encodings/ms-turk +1 -0
  151. sage_wheels/lib/ecl-24.5.10/encodings/shift-jis.bin +0 -0
  152. sage_wheels/lib/ecl-24.5.10/encodings/tools.lisp +202 -0
  153. sage_wheels/lib/ecl-24.5.10/encodings/ucs2 +1 -0
  154. sage_wheels/lib/ecl-24.5.10/encodings/ucs2be +1 -0
  155. sage_wheels/lib/ecl-24.5.10/encodings/ucs2le +1 -0
  156. sage_wheels/lib/ecl-24.5.10/encodings/ucs4 +1 -0
  157. sage_wheels/lib/ecl-24.5.10/encodings/ucs4be +1 -0
  158. sage_wheels/lib/ecl-24.5.10/encodings/ucs4le +1 -0
  159. sage_wheels/lib/ecl-24.5.10/encodings/unicode +1 -0
  160. sage_wheels/lib/ecl-24.5.10/encodings/utf-16 +1 -0
  161. sage_wheels/lib/ecl-24.5.10/encodings/utf-16be +1 -0
  162. sage_wheels/lib/ecl-24.5.10/encodings/utf-16le +1 -0
  163. sage_wheels/lib/ecl-24.5.10/encodings/utf-32 +1 -0
  164. sage_wheels/lib/ecl-24.5.10/encodings/utf-32be +1 -0
  165. sage_wheels/lib/ecl-24.5.10/encodings/utf-32le +1 -0
  166. sage_wheels/lib/ecl-24.5.10/encodings/utf16 +1 -0
  167. sage_wheels/lib/ecl-24.5.10/encodings/utf32 +1 -0
  168. sage_wheels/lib/ecl-24.5.10/encodings/utf8 +1 -0
  169. sage_wheels/lib/ecl-24.5.10/encodings/winbaltrim +1 -0
  170. sage_wheels/lib/ecl-24.5.10/encodings/windows-1250 +1 -0
  171. sage_wheels/lib/ecl-24.5.10/encodings/windows-1251 +1 -0
  172. sage_wheels/lib/ecl-24.5.10/encodings/windows-1252 +1 -0
  173. sage_wheels/lib/ecl-24.5.10/encodings/windows-1253 +1 -0
  174. sage_wheels/lib/ecl-24.5.10/encodings/windows-1254 +1 -0
  175. sage_wheels/lib/ecl-24.5.10/encodings/windows-1255 +1 -0
  176. sage_wheels/lib/ecl-24.5.10/encodings/windows-1256 +1 -0
  177. sage_wheels/lib/ecl-24.5.10/encodings/windows-1257 +1 -0
  178. sage_wheels/lib/ecl-24.5.10/encodings/windows-1258 +1 -0
  179. sage_wheels/lib/ecl-24.5.10/encodings/windows-932 +1 -0
  180. sage_wheels/lib/ecl-24.5.10/encodings/windows-936 +1 -0
  181. sage_wheels/lib/ecl-24.5.10/encodings/windows-949 +1 -0
  182. sage_wheels/lib/ecl-24.5.10/encodings/windows-950 +1 -0
  183. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1250.bin +0 -0
  184. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1251.bin +0 -0
  185. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1252.bin +0 -0
  186. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1253.bin +0 -0
  187. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1254.bin +0 -0
  188. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1255.bin +0 -0
  189. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1256.bin +0 -0
  190. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1257.bin +0 -0
  191. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp1258.bin +0 -0
  192. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp932.bin +0 -0
  193. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp936.bin +0 -0
  194. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp949.bin +0 -0
  195. sage_wheels/lib/ecl-24.5.10/encodings/windows-cp950.bin +0 -0
  196. sage_wheels/lib/ecl-24.5.10/help.doc +0 -0
  197. sage_wheels/lib/ecl-24.5.10/libasdf.a +0 -0
  198. sage_wheels/lib/ecl-24.5.10/libcmp.a +0 -0
  199. sage_wheels/lib/ecl-24.5.10/libdeflate.a +0 -0
  200. sage_wheels/lib/ecl-24.5.10/libdefsystem.a +0 -0
  201. sage_wheels/lib/ecl-24.5.10/libecl-cdb.a +0 -0
  202. sage_wheels/lib/ecl-24.5.10/libecl-curl.a +0 -0
  203. sage_wheels/lib/ecl-24.5.10/libecl-help.a +0 -0
  204. sage_wheels/lib/ecl-24.5.10/libecl-quicklisp.a +0 -0
  205. sage_wheels/lib/ecl-24.5.10/libpackage-locks.a +0 -0
  206. sage_wheels/lib/ecl-24.5.10/libql-minitar.a +0 -0
  207. sage_wheels/lib/ecl-24.5.10/libsb-bsd-sockets.a +0 -0
  208. sage_wheels/lib/ecl-24.5.10/libserve-event.a +0 -0
  209. sage_wheels/lib/ecl-24.5.10/libsockets.a +0 -0
  210. sage_wheels/lib/ecl-24.5.10/package-locks.asd +5 -0
  211. sage_wheels/lib/ecl-24.5.10/package-locks.fas +0 -0
  212. sage_wheels/lib/ecl-24.5.10/prebuilt-asdf.asd +5 -0
  213. sage_wheels/lib/ecl-24.5.10/ql-minitar.asd +5 -0
  214. sage_wheels/lib/ecl-24.5.10/ql-minitar.fas +0 -0
  215. sage_wheels/lib/ecl-24.5.10/sb-bsd-sockets.asd +5 -0
  216. sage_wheels/lib/ecl-24.5.10/sb-bsd-sockets.fas +0 -0
  217. sage_wheels/lib/ecl-24.5.10/serve-event.asd +5 -0
  218. sage_wheels/lib/ecl-24.5.10/serve-event.fas +0 -0
  219. sage_wheels/lib/ecl-24.5.10/sockets.asd +5 -0
  220. sage_wheels/lib/ecl-24.5.10/sockets.fas +0 -0
  221. 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()