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 ~]$