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