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