Implementation of a REPL in Common Lisp
The most basic REPL implementation is just what it says:
NOTE: the code presented here lacks flushing (call to finish-output). It'll have to be updated
Given the order of evaluation imposed by the parentheses, READ is evaluated first, then EVAL, then PRINT, then LOOP. Hence REPL.
cl-user> (Loop (Print (Eval (Read)))) (+ 2 3) 5 (list 1 'apple 2 'orange) (1 apple 2 orange) ; Evaluation aborted on #<com.informatimago.signal:user-interrupt #x302004E56F0D>. cl-user>
A more sophisticated REPL (conforming to the ANSI Common Lisp specification) could be:
It provides the standard REPL variables, -, +, ++, +++, *, **, ***, /, // and ///, and handle errors reporting a message. In CL implementations, the debugger would be invoked upon errors.
cl-user> (repl) COMMON-LISP-USER[1]> (* 3 4) --> 12 COMMON-LISP-USER[2]> (/ 1 0) division-by-zero: #<division-by-zero #x302004F8497D> COMMON-LISP-USER[3]> (quit) nil cl-user>
Examples and Comparison of REPL
Here are two examples of REPL interaction.
The first is with an ANSI Common Lisp implementation; all Common Lisp implementations have similar REPL, but they differ in the set of command they offer in the debugger. slime covers the differences with a common layer.
The second is with an ANSI C implementation. C implementations don't often provide a REPL, having an heritage of batch processing much more than interactive development, but there are a few C implementations that provide more or less limited REPL.
Langage: ANSI Common Lisp; Implementation: clisp
[pjb@kuiper :0 ~]$ clisp -ansi -norc
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Welcome to GNU CLISP 2.49+ (2010-07-17) <http://clisp.org/>
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2010
Type :h and hit Enter for context help.
[1]> (defun f (x) (if (< x 1) 1 (* x (f (1- x)))))
F
[2]> (f 5)
120
[3]> (defparameter *s* 0)
*S*
[4]> (loop for i from 0 to 5 do (incf *s* (f i)))
NIL
[5]> *s*
154
[6]> (loop for i from 0 to 5 do (incf *s* (f (/ i))))
*** - /: division by zero
The following restarts are available:
ABORT :R1 Abort main loop
Break 1 [7]> :bt 4 1
<1/246> #<SYSTEM-FUNCTION SHOW-STACK> 3
<2/239> #<COMPILED-FUNCTION SYSTEM::PRINT-BACKTRACE>
<3/233> #<COMPILED-FUNCTION SYSTEM::DEBUG-BACKTRACE>
<4/224> #<SYSTEM-FUNCTION SYSTEM::READ-EVAL-PRINT> 2
<5/221> #<COMPILED-FUNCTION SYSTEM::BREAK-LOOP-2-3>
<6/217> #<SYSTEM-FUNCTION SYSTEM::SAME-ENV-AS> 2
<7/203> #<COMPILED-FUNCTION SYSTEM::BREAK-LOOP-2>
<8/201> #<SYSTEM-FUNCTION SYSTEM::DRIVER>
<9/161> #<COMPILED-FUNCTION SYSTEM::BREAK-LOOP>
<10/158> #<SYSTEM-FUNCTION INVOKE-DEBUGGER> 1
<11/147> #<SYSTEM-FUNCTION /> 1
[146] EVAL frame for form (/ I)
Printed 11 frames
Break 1 [7]> i
0
Break 1 [7]> :q
[8]> (loop for i from 0 to 5 do (incf *s* (f (/ (1+ i)))))
NIL
[9]> *s*
160
[10]> (setf *s* 0)
0
[11]> (loop for i from 0 to 5 do (incf *s* (f (/ (1+ i)))))
NIL
[12]> *s*
6
[13]> (f (/ 1 5))
1
[14]> (f 30)
265252859812191058636308480000000
[15]> (quit)
Bye.
[pjb@kuiper :0 ~]$
Langage: ANSI C; Implementation: ch
[pjb@kuiper :0 ~]$ ch
Ch (64-bit)
Standard edition, version 7.0.0.15151
Copyright (C) SoftIntegration, Inc. 2001-2011
http://www.softintegration.com
/home/pjb> int f(int x){ return x<1?1:x*f(x-1); }
int f(int x){ return x<1?1:x*f(x-1); }
/home/pjb> f(5)
f(5)
120
/home/pjb> int s=0;
int s=0;
/home/pjb> {int i; for(i=0;i<=5;i++){ s+=f(i); }}
{int i; for(i=0;i<=5;i++){ s+=f(i); }}
/home/pjb> s
s
154
/home/pjb> {int i; for(i=0;i<=5;i++){ s+=f(1/i); }}
{int i; for(i=0;i<=5;i++){ s+=f(1/i); }}
WARNING: integer divide by zero
Segmentation fault
[pjb@kuiper :0 ~]$