Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/interfaces/lisp.py
4045 views
1
r"""
2
Lisp Interface
3
4
EXAMPLES:
5
sage: lisp.eval('(* 4 5)')
6
'20'
7
sage: a = lisp(3); b = lisp(5)
8
sage: a + b
9
8
10
sage: a * b
11
15
12
sage: a / b
13
3/5
14
sage: a - b
15
-2
16
sage: a.sin()
17
0.14112
18
sage: b.cos()
19
0.2836622
20
sage: a.exp()
21
20.085537
22
sage: lisp.eval('(+ %s %s)'%(a.name(), b.name()))
23
'8'
24
25
One can define functions and the interface supports object-oriented
26
notation for calling them:
27
sage: lisp.eval('(defun factorial (n) (if (= n 1) 1 (* n (factorial (- n 1)))))')
28
'FACTORIAL'
29
sage: lisp('(factorial 10)')
30
3628800
31
sage: lisp(10).factorial()
32
3628800
33
sage: a = lisp(17)
34
sage: a.factorial()
35
355687428096000
36
37
AUTHORS:
38
-- William Stein (first version)
39
-- William Stein (2007-06-20): significant improvements.
40
"""
41
42
##########################################################################
43
#
44
# Copyright (C) 2006 William Stein <[email protected]>
45
#
46
# Distributed under the terms of the GNU General Public License (GPL)
47
#
48
# http://www.gnu.org/licenses/
49
#
50
##########################################################################
51
52
from __future__ import with_statement
53
54
import random
55
56
from expect import Expect, ExpectElement, ExpectFunction, FunctionElement, gc_disabled
57
from sage.structure.element import RingElement
58
59
class Lisp(Expect):
60
def __init__(self,
61
maxread=100000, script_subdirectory=None,
62
logfile=None,
63
server=None,
64
server_tmpdir=None):
65
"""
66
EXAMPLES:
67
sage: lisp == loads(dumps(lisp))
68
True
69
"""
70
Expect.__init__(self,
71
72
# The capitalized version of this is used for printing.
73
name = 'Lisp',
74
75
# This is regexp of the input prompt. If you can change
76
# it to be very obfuscated that would be better. Even
77
# better is to use sequence numbers.
78
prompt = '> ',
79
80
# This is the command that starts up your program
81
command = "ecl",
82
83
maxread = maxread,
84
server=server,
85
server_tmpdir=server_tmpdir,
86
script_subdirectory = script_subdirectory,
87
88
# If this is true, then whenever the user presses Control-C to
89
# interrupt a calculation, the whole interface is restarted.
90
restart_on_ctrlc = False,
91
92
# If true, print out a message when starting
93
# up the command when you first send a command
94
# to this interface.
95
verbose_start = False,
96
97
logfile=logfile,
98
99
# If an input is longer than this number of characters, then
100
# try to switch to outputting to a file.
101
eval_using_file_cutoff=1024)
102
103
self.__seq = 0
104
self.__in_seq = 1
105
106
def eval(self, code, strip=True, **kwds):
107
"""
108
EXAMPLES:
109
sage: lisp.eval('(+ 2 2)')
110
'4'
111
112
TEST:
113
# Verify that it works when input == output
114
sage: lisp.eval('2')
115
'2'
116
"""
117
with gc_disabled():
118
self._synchronize()
119
code = str(code)
120
code = code.strip()
121
code = code.replace('\n',' ')
122
x = []
123
for L in code.split('\n'):
124
if L != '':
125
try:
126
s = self.__in_seq + 1
127
M = self._eval_line(L, wait_for_prompt=self._prompt)
128
if M.startswith(L + "\n"):
129
M = M[len(L):] # skip L in case it was echoed
130
x.append(M.strip())
131
self.__in_seq = s
132
except KeyboardInterrupt:
133
# DO NOT CATCH KeyboardInterrupt, as it is being caught
134
# by _eval_line
135
# In particular, do NOT call self._keyboard_interrupt()
136
raise
137
except TypeError, s:
138
return 'error evaluating "%s":\n%s'%(code,s)
139
return '\n'.join(x)
140
141
def _an_element_impl(self):
142
"""
143
EXAMPLES:
144
sage: lisp._an_element_impl()
145
0
146
"""
147
return self(0)
148
149
def set(self, var, value):
150
"""
151
Set the variable var to the given value.
152
153
EXAMPLES:
154
sage: lisp.set('x', '2')
155
sage: lisp.get('x')
156
'2'
157
158
TEST:
159
# it must also be possible to eval the variable by name
160
sage: lisp.eval('x')
161
'2'
162
"""
163
cmd = '(setq %s %s)'%(var, value)
164
out = self.eval(cmd)
165
if '***' in out:
166
raise TypeError, "Error executing code in Sage\nCODE:\n\t%s\nSAGE ERROR:\n\t%s"%(cmd, out)
167
168
def get(self, var):
169
"""
170
EXAMPLES:
171
sage: lisp.set('x', '2')
172
sage: lisp.get('x')
173
'2'
174
"""
175
out = self.eval(var)
176
return out
177
178
def _start(self, *args, **kwds):
179
"""
180
EXAMPLES:
181
sage: l = Lisp()
182
sage: l.is_running()
183
False
184
sage: l._start()
185
sage: l.is_running()
186
True
187
"""
188
Expect._start(self, *args, **kwds)
189
self.__in_seq = 1
190
191
def _synchronize(self):
192
E = self._expect
193
if E is None:
194
self._start()
195
E = self._expect
196
r = random.randrange(2147483647)
197
s = str(r+1)
198
cmd = "(+ 1 %s)\n"%r
199
E.sendline(cmd)
200
E.expect(s)
201
E.expect(self._prompt)
202
203
def _repr_(self):
204
"""
205
EXAMPLES:
206
sage: lisp
207
Lisp Interpreter
208
"""
209
return 'Lisp Interpreter'
210
211
def __reduce__(self):
212
"""
213
EXAMPLES:
214
sage: lisp.__reduce__()
215
(<function reduce_load_Lisp at 0x...>, ())
216
217
"""
218
return reduce_load_Lisp, tuple([])
219
220
def _function_class(self):
221
"""
222
EXAMPLES:
223
sage: lisp._function_class()
224
<class 'sage.interfaces.lisp.LispFunction'>
225
"""
226
return LispFunction
227
228
def _quit_string(self):
229
"""
230
EXAMPLES:
231
sage: lisp._quit_string()
232
'(quit);'
233
234
sage: l = Lisp()
235
sage: l._start()
236
sage: l.quit()
237
sage: l.is_running()
238
False
239
"""
240
return '(quit);'
241
242
def _read_in_file_command(self, filename):
243
"""
244
EXAMPLES:
245
sage: lisp._read_in_file_command(tmp_filename())
246
Traceback (most recent call last):
247
...
248
NotImplementedError
249
"""
250
raise NotImplementedError
251
252
def trait_names(self):
253
"""
254
EXAMPLES:
255
sage: lisp.trait_names()
256
Traceback (most recent call last):
257
...
258
NotImplementedError
259
260
"""
261
raise NotImplementedError
262
263
def kill(self, var):
264
"""
265
EXAMPLES:
266
sage: lisp.kill('x')
267
Traceback (most recent call last):
268
...
269
NotImplementedError
270
"""
271
raise NotImplementedError
272
273
def console(self):
274
"""
275
Spawn a new Lisp command-line session.
276
277
EXAMPLES:
278
sage: lisp.console() #not tested
279
ECL (Embeddable Common-Lisp) ...
280
Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
281
Copyright (C) 1993 Giuseppe Attardi
282
Copyright (C) 2000 Juan J. Garcia-Ripoll
283
ECL is free software, and you are welcome to redistribute it
284
under certain conditions; see file 'Copyright' for details.
285
Type :h for Help. Top level.
286
...
287
"""
288
lisp_console()
289
290
291
def version(self):
292
"""
293
Returns the version of Lisp being used.
294
295
EXAMPLES:
296
sage: lisp.version()
297
'Version information is given by lisp.console().'
298
299
"""
300
# import subprocess
301
# p = subprocess.Popen('ecl --version', shell=True, stdin=subprocess.PIPE,
302
# stdout = subprocess.PIPE, stderr=subprocess.PIPE)
303
# return AsciiArtString(p.stdout.read())
304
return "Version information is given by lisp.console()."
305
306
def _object_class(self):
307
"""
308
EXAMPLES:
309
sage: lisp._object_class()
310
<class 'sage.interfaces.lisp.LispElement'>
311
312
"""
313
return LispElement
314
315
def _function_class(self):
316
"""
317
EXAMPLES:
318
sage: lisp._function_class()
319
<class 'sage.interfaces.lisp.LispFunction'>
320
"""
321
return LispFunction
322
323
def _function_element_class(self):
324
"""
325
EXAMPLES:
326
sage: lisp._function_element_class()
327
<class 'sage.interfaces.lisp.LispFunctionElement'>
328
"""
329
return LispFunctionElement
330
331
def _true_symbol(self):
332
"""
333
EXAMPLES:
334
sage: lisp._true_symbol()
335
'T'
336
"""
337
return 'T'
338
339
def _false_symbol(self):
340
"""
341
EXAMPLES:
342
sage: lisp._false_symbol()
343
'NIL'
344
"""
345
return 'NIL'
346
347
def _equality_symbol(self):
348
"""
349
We raise a NotImplementedError when _equality_symbol is called since
350
equality testing in Lisp does not use infix notation and cannot be
351
done the same way as in the other interfaces.
352
353
EXAMPLES:
354
sage: lisp._equality_symbol()
355
Traceback (most recent call last):
356
...
357
NotImplementedError: ...
358
"""
359
raise NotImplementedError, ("We should never reach here in the Lisp interface. " +
360
"Please report this as a bug.")
361
362
def help(self, command):
363
"""
364
EXAMPLES:
365
sage: lisp.help('setq')
366
Traceback (most recent call last):
367
...
368
NotImplementedError
369
"""
370
raise NotImplementedError
371
372
def function_call(self, function, args=None, kwds=None):
373
"""
374
Calls the Lisp function with given args and kwds.
375
For Lisp functions, the kwds are ignored.
376
377
EXAMPLES:
378
sage: lisp.function_call('sin', ['2'])
379
0.9092974
380
sage: lisp.sin(2)
381
0.9092974
382
"""
383
args, kwds = self._convert_args_kwds(args, kwds)
384
self._check_valid_function_name(function)
385
return self.new("(%s %s)"%(function, ",".join([s.name() for s in args])))
386
387
class LispElement(ExpectElement):
388
def __cmp__(self, other):
389
"""
390
EXAMPLES:
391
sage: one = lisp(1); two = lisp(2)
392
sage: one == one
393
True
394
sage: one != two
395
True
396
sage: one < two
397
True
398
sage: two > one
399
True
400
sage: one < 1
401
False
402
sage: two == 2
403
True
404
405
"""
406
P = self._check_valid()
407
if not hasattr(other, 'parent') or P is not other.parent():
408
other = P(other)
409
410
if P.eval('(= %s %s)'%(self.name(), other.name())) == P._true_symbol():
411
return 0
412
elif P.eval('(< %s %s)'%(self.name(), other.name())) == P._true_symbol():
413
return -1
414
else:
415
return 1
416
417
def bool(self):
418
"""
419
EXAMPLES:
420
sage: lisp(2).bool()
421
True
422
sage: lisp(0).bool()
423
False
424
sage: bool(lisp(2))
425
True
426
"""
427
return self != 0
428
429
def _add_(self, right):
430
"""
431
EXAMPLES:
432
sage: a = lisp(1); b = lisp(2)
433
sage: a + b
434
3
435
"""
436
P = self._check_valid()
437
return P.new('(+ %s %s)'%(self._name, right._name))
438
439
def _sub_(self, right):
440
"""
441
EXAMPLES:
442
sage: a = lisp(1); b = lisp(2)
443
sage: a - b
444
-1
445
"""
446
P = self._check_valid()
447
return P.new('(- %s %s)'%(self._name, right._name))
448
449
def _mul_(self, right):
450
"""
451
EXAMPLES:
452
sage: a = lisp(1); b = lisp(2)
453
sage: a * b
454
2
455
"""
456
P = self._check_valid()
457
return P.new('(* %s %s)'%(self._name, right._name))
458
459
def _div_(self, right):
460
"""
461
EXAMPLES:
462
sage: a = lisp(1); b = lisp(2)
463
sage: a / b
464
1/2
465
"""
466
P = self._check_valid()
467
return P.new('(/ %s %s)'%(self._name, right._name))
468
469
def __pow__(self, n):
470
"""
471
EXAMPLES:
472
sage: a = lisp(3)
473
sage: a^3
474
27
475
"""
476
return RingElement.__pow__(self, n)
477
478
class LispFunctionElement(FunctionElement):
479
def _sage_doc_(self):
480
"""
481
EXAMPLES:
482
sage: two = lisp(2)
483
sage: two.sin._sage_doc_()
484
Traceback (most recent call last):
485
...
486
NotImplementedError
487
"""
488
M = self._obj.parent()
489
return M.help(self._name)
490
491
492
class LispFunction(ExpectFunction):
493
def _sage_doc_(self):
494
"""
495
EXAMPLES:
496
sage: lisp.sin._sage_doc_()
497
Traceback (most recent call last):
498
...
499
NotImplementedError
500
"""
501
M = self._parent
502
return M.help(self._name)
503
504
505
506
def is_LispElement(x):
507
"""
508
EXAMPLES:
509
sage: from sage.interfaces.lisp import is_LispElement
510
sage: is_LispElement(lisp(2))
511
True
512
sage: is_LispElement(2)
513
False
514
"""
515
return isinstance(x, LispElement)
516
517
# An instance
518
lisp = Lisp()
519
520
def reduce_load_Lisp():
521
"""
522
EXAMPLES:
523
sage: from sage.interfaces.lisp import reduce_load_Lisp
524
sage: reduce_load_Lisp()
525
Lisp Interpreter
526
"""
527
return lisp
528
529
import os
530
def lisp_console():
531
"""
532
Spawn a new Lisp command-line session.
533
534
EXAMPLES:
535
sage: lisp.console() #not tested
536
ECL (Embeddable Common-Lisp) ...
537
Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
538
Copyright (C) 1993 Giuseppe Attardi
539
Copyright (C) 2000 Juan J. Garcia-Ripoll
540
ECL is free software, and you are welcome to redistribute it
541
under certain conditions; see file 'Copyright' for details.
542
Type :h for Help. Top level.
543
...
544
"""
545
os.system('ecl')
546
547
548
549