picolisp

Unnamed repository; edit this file to name it for gitweb.
git clone https://logand.com/git/picolisp.git/
Log | Files | Refs | README | LICENSE

commit 3db5895b3ea5d3cfaa0a8aa1a2b00d4150525276
parent aaf01d10c2e626c218881906fab7fa43b5565e35
Author: Commit-Bot <unknown>
Date:   Mon,  8 Nov 2010 11:42:28 +0000

Automatic commit from picoLisp.tgz, From: Mon, 08 Nov 2010 11:42:28 GMT
Diffstat:
Mdoc/faq.html | 2+-
Mdoc/tut.html | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mersatz/PicoLisp.java | 34+++++++++++++++++++++-------------
Mersatz/fun.src | 10++++++----
Mersatz/picolisp.jar | 0
Mersatz/sys.src | 27+++++++++++++++++----------
6 files changed, 106 insertions(+), 55 deletions(-)

diff --git a/doc/faq.html b/doc/faq.html @@ -581,7 +581,7 @@ cell holds the symbol's value in its CDR, and the tail in its CAR. If the string is not longer than 7 bytes, it fits (on the 64-bit version) completely into the tail, and a single cell suffices. Up to 15 bytes take up two cells, 23 bytes three etc., so that long strings are not very efficient (needing twice the -memory on the avarage), but this disadvantage is made up by simplicity and +memory on the average), but this disadvantage is made up by simplicity and uniformity. And lots of extremely long strings are not the common case, as they are split up anyway during processing, and stored as plain byte sequences in external files and databases. diff --git a/doc/tut.html b/doc/tut.html @@ -53,10 +53,10 @@ front-end to the PicoLisp console. This is not recommended, because the PicoLisp debugging environment will set the console (tty) to raw mode by itself and do the special handling seen above during character input. -<p>If you feel that you absolutely have to use an input front-end, please remove -the entry "@lib/led.l" from "dbg.l". Note that in this case, however, you will -not have the TAB symbol completion feature available during command line -editing. +<p>If you feel that you absolutely have to use an IDE, <code>rlwrap</code> or ++another input front-end, please remove the entry "@lib/led.l" from "dbg.l". +Note that in this case, however, you will not have the TAB symbol completion +feature available during command line editing. <h3>Table of content</h3> @@ -200,8 +200,8 @@ an application server during debugging). <li><code>Ctrl-X</code> discards all input, abandons further processing, and returns to the interpreter's top level (equivalent to invoking <code><a href="refQ.html#quit">quit</a></code>). This is also useful when the program -stopped at a breakpoint, or after program execution was interrupted with -<code>Ctrl-C</code>. +stopped at a breakpoint (see single-stepping <a href="#dbg">Debugging</a>), or +after program execution was interrupted with <code>Ctrl-C</code>. </ul> @@ -748,6 +748,16 @@ function, using <code><a href="refP.html#pass">pass</a></code>: <p>There are two major ways to debug functions (and methods) at runtime: <i>Tracing</i> and <i>single-stepping</i>. +In this section we will use the REPL to explore the debugging facilities, but in +the <a href="#script">Scripting</a> section, you will learn how to launch +PicoLisp scripts with some selected functions debugged: + +<pre><code> +$ ./dbg app/file1.l -"trace 'foo" -main -"debug 'bar" app/file2.l +</code></pre> + +<h3>Tracing</h3> + <p><i>Tracing</i> means letting functions of interest print their name and arguments when they are entered, and their name again and the return value when they are exited. @@ -760,7 +770,7 @@ href="fun.l">doc/fun.l</a></code>"): (de fact (N) (if (=0 N) 1 - (* N (fact (- N 1))) ) ) + (* N (fact (dec N))) ) ) </code></pre> <p>With <code><a href="refT.html#trace">trace</a></code> we can put it in trace @@ -791,10 +801,10 @@ space. Upon function entry, the name is separated from the arguments with a colon (<code>:</code>), and upon function exit with an equals sign (<code>=</code>) from the return value. -<p>Trace works by modifying the function body, so generally only for functions -defined as lists (lambda expressions, see <a href="ref.html#ev">Evaluation</a>). -Tracing a C-function is possible, however, when it is a function that evaluates -all its arguments. +<p><code>trace</code> works by modifying the function body, so generally it +works only for functions defined as lists (lambda expressions, see <a +href="ref.html#ev">Evaluation</a>). Tracing a C-function is possible, however, +when it is a function that evaluates all its arguments. <p>So let's trace the functions <code><a href="ref_.html#=0">=0</a></code> and <code><a href="ref_.html#*">*</a></code>: @@ -836,7 +846,7 @@ all its arguments. </code></pre> <p>To reset a function to its untraced state, call <code><a -href="refU.html#untrace">untrace</a></code> +href="refU.html#untrace">untrace</a></code>: <pre><code> : (untrace 'fact) @@ -847,13 +857,15 @@ href="refU.html#untrace">untrace</a></code> -> * </code></pre> -<p>or simply +<p>or simply use <code><a href="refM.html#mapc">mapc</a></code>: <pre><code> : (mapc untrace '(fact =0 *)) -> * </code></pre> +<h3>Single-stepping</h3> + <p><i>Single-stepping</i> means to execute a function step by step, giving the programmer an opportunity to look more closely at what is happening. The function <code><a href="refD.html#debug">debug</a></code> inserts a breakpoint @@ -869,13 +881,13 @@ then functions <li>execute <code>(<a href="refD.html#d">d</a>)</code> to recursively debug the -next expression +next expression (looping through subexpressions of this expression) <li>execute <code>(<a href="refE.html#e">e</a>)</code> to evaluate the next expression, to see what will happen without actually advancing on -<li>type ENTER (: enter an empty line) to leave the read-eval loop and continue -with the next expression +<li>type ENTER (that is, enter an empty line) to leave the read-eval loop and +continue with the next expression </ul> @@ -883,7 +895,25 @@ with the next expression repeatedly to step through the function. <p>To try it out, let's look at the <code><a -href="refS.html#stamp">stamp</a></code> system function. +href="refS.html#stamp">stamp</a></code> system function. You may need to have a +look at + +<ul> +<li><code><a href="ref_.html#=T">=T</a></code> (T test),</li> + +<li><code><a href="refD.html#date">date</a></code> and <code><a +href="refT.html#time">time</a></code> (grab system date and time) + +<li><code><a href="refD.html#default">default</a></code> (conditional assignmen + +<li><code><a href="refP.html#pack">pack</a></code> (kind of concatenation), and + +<li><code><a href="refD.html#dat$">dat$</a></code> and <code><a +href="refT.html#tim$">tim$</a></code> (date and time formats)</li> + +</ul> + +to understand this definition. <pre><code> : (pp 'stamp) @@ -950,7 +980,8 @@ pretty-print it: -> stamp </code></pre> -<p>To reset the function to its normal state, call +<p>To reset the function to its normal state, calll <code><a +href="refU.html#unbug">unbug</a></code>: <pre><code> : (unbug 'stamp) @@ -987,7 +1018,7 @@ automatically skipped by <code>read</code>: <pre><code> : (in "doc/fun.l" (read)) --> (de fact (N) (if (=0 N) 1 (* N (fact (- N 1))))) +-> (de fact (N) (if (=0 N) 1 (* N (fact (dec N))))) </code></pre> <p>The <code><a href="refS.html#skip">skip</a></code> function can also be used @@ -1005,8 +1036,9 @@ stream for given patterns. Typically, this is not done with Lisp source files immediately following <code>fact</code> in the file, <pre><code> -: (in "doc/fun.l" (make (while (from "fact ") (link (read))))) --> ((N) (- N 1)) +: (in "doc/fun.l" (while (from "fact ") (println (read)))) +(N) +(dec N) </code></pre> <p>or the word following "(de " with <code><a @@ -1019,7 +1051,9 @@ href="refT.html#till">till</a></code>: <p>With <code><a href="refL.html#line">line</a></code>, a line of characters is -read, either into a single transient symbol, +read, either into a single transient <a +href="ref.html#transient-io">transient</a> symbol (the type used by PicoLisp for +strings), <pre><code> : (in "doc/tut.html" (line T)) @@ -1049,7 +1083,7 @@ fields. A typical way to import the contents of such a file is: ... use 'getStr', 'getNum' etc ... # process them </code></pre> -<p>Some more examples: +<p>Some more examples with <code><a href="refE.html#echo">echo</a></code>: <pre><code> (in "a" # Copy the first 40 Bytes @@ -1266,11 +1300,11 @@ site, and prints it to standard output: <p>We recommend that you have a terminal window open, and try the examples by yourself. You may either type them in, directly to the PicoLisp interpreter, or -edit a separate source file (e.g. <code>"test.l"</code>) in a second terminal +edit a separate source file (e.g. <code>"doc/fun.l"</code>) in a second terminal window and load it into PicoLisp with <pre><code> -: (load "test.l") +: (load "doc/fun.l") </code></pre> <p>each time you have modified and saved it. @@ -1281,11 +1315,11 @@ window and load it into PicoLisp with that function with <pre><code> -: (vi 'foo) +: (vi 'fact) </code></pre> <p>The function 'vi' opens the appropriate source file, and jumps to the right -line where 'foo' is defined. When you modify it, you can simply call 'ld' to +line where 'fact' is defined. When you modify it, you can simply call 'ld' to (re)load that source file <pre><code> diff --git a/ersatz/PicoLisp.java b/ersatz/PicoLisp.java @@ -1,4 +1,4 @@ -// 05nov10abu +// 08nov10abu // (c) Software Lab. Alexander Burger import java.util.*; @@ -431,7 +431,10 @@ public class PicoLisp { sel = Selector.open(); int t = ms >= 0? ms : Integer.MAX_VALUE; if (fd >= 0 && InFiles[fd] != null) - InFiles[fd].register(sel); + if (InFiles[fd].Stream != null && InFiles[fd].Stream.available() > 0) + t = 0; + else + InFiles[fd].register(sel); for (Any x = Env.Task = Run.Car; x instanceof Cell; x = x.Cdr) { if (memq(x.Car, task) == null) { if ((i = ((Number)x.Car.Car).Cnt) < 0) { @@ -440,7 +443,10 @@ public class PicoLisp { } else if (i != fd) { if (i < InFiles.length && InFiles[i] != null) - InFiles[i].register(sel); + if (InFiles[i].Stream != null && InFiles[i].Stream.available() > 0) + t = 0; + else + InFiles[i].register(sel); } } } @@ -1550,16 +1556,16 @@ public class PicoLisp { } final static class PicoLispReader { - LineNumberReader Rd; + Reader Rd; String Name; char Eof1, Eof2; int Fd, Chr, Src, Ops; + InputStream Stream; SelectableChannel Chan; SelectionKey Key; PicoLispReader(Reader rd, String nm, int fd, SelectableChannel chan, int ops) { - if (rd != null) - Rd = new LineNumberReader(rd); + Rd = rd; Name = nm; InFiles[Fd = fd] = this; Chan = chan; @@ -1568,10 +1574,11 @@ public class PicoLisp { PicoLispReader(InputStream in, int fd, SelectableChannel chan, int ops) { this(in == null? null : new InputStreamReader(in), null, fd, chan, ops); + Stream = in; } PicoLispReader(String s, char eof1, char eof2) { - Rd = new LineNumberReader(new StringReader(s)); + Rd = new StringReader(s); Eof1 = eof1; Eof2 = eof2; } @@ -1783,8 +1790,8 @@ public class PicoLisp { return Nil; eofErr(); } - if (top && InFile != null) - InFile.Src = InFile.Rd.getLineNumber() + 1; + if (top && InFile != null && InFile.Rd instanceof LineNumberReader) + InFile.Src = ((LineNumberReader)InFile.Rd).getLineNumber() + 1; if (Chr == '(') { x = rdList(); if (top && Chr == ']') @@ -2802,9 +2809,10 @@ public class PicoLisp { } final static Any do9(Any ex) { // double: - Number num; - num = (Number)((ex = ex.Cdr).Car.eval()); - return new Symbol(new Double(num.toString(evInt(ex.Cdr), '.', '\0'))); + Any x; + if ((x = (ex = ex.Cdr).Car.eval()) instanceof Number) + return new Symbol(new Double(((Number)x).toString(evInt(ex.Cdr), '.', '\0'))); + return new Symbol(new Double(x.name())); } final static Any do10(Any ex) { // big: @@ -6631,7 +6639,7 @@ public class PicoLisp { String nm = path(name()); if (nm.charAt(0) == '+') nm = nm.substring(1); // No file reader with "rw" mode - return new InFrame(new PicoLispReader(new FileReader(nm), nm, allocFd(), null, 0), 1); + return new InFrame(new PicoLispReader(new LineNumberReader(new FileReader(nm)), nm, allocFd(), null, 0), 1); } catch (IOException e) { err(ex, this, "Read open error"); diff --git a/ersatz/fun.src b/ersatz/fun.src @@ -1,4 +1,4 @@ -# 05nov10abu +# 06nov10abu # (c) Software Lab. Alexander Burger # Ersatz PicoLisp Functions @@ -121,10 +121,12 @@ int: () long: () return new Symbol(new Long(evLong(ex.Cdr))); +# (double: 'str 'cnt) -> obj # (double: 'num 'cnt) -> obj -double: (num) - num = (Number)((ex = ex.Cdr).Car.eval()); - return new Symbol(new Double(num.toString(evInt(ex.Cdr), '.', '\0'))); +double: (x) + if ((x = (ex = ex.Cdr).Car.eval()) instanceof Number) + return new Symbol(new Double(((Number)x).toString(evInt(ex.Cdr), '.', '\0'))); + return new Symbol(new Double(x.name())); # (big: 'num) -> obj big: (num) diff --git a/ersatz/picolisp.jar b/ersatz/picolisp.jar Binary files differ. diff --git a/ersatz/sys.src b/ersatz/sys.src @@ -1,4 +1,4 @@ -// 05nov10abu +// 08nov10abu // (c) Software Lab. Alexander Burger import java.util.*; @@ -138,7 +138,10 @@ public class PicoLisp { sel = Selector.open(); int t = ms >= 0? ms : Integer.MAX_VALUE; if (fd >= 0 && InFiles[fd] != null) - InFiles[fd].register(sel); + if (InFiles[fd].Stream != null && InFiles[fd].Stream.available() > 0) + t = 0; + else + InFiles[fd].register(sel); for (Any x = Env.Task = Run.Car; x instanceof Cell; x = x.Cdr) { if (memq(x.Car, task) == null) { if ((i = ((Number)x.Car.Car).Cnt) < 0) { @@ -147,7 +150,10 @@ public class PicoLisp { } else if (i != fd) { if (i < InFiles.length && InFiles[i] != null) - InFiles[i].register(sel); + if (InFiles[i].Stream != null && InFiles[i].Stream.available() > 0) + t = 0; + else + InFiles[i].register(sel); } } } @@ -1257,16 +1263,16 @@ public class PicoLisp { } final static class PicoLispReader { - LineNumberReader Rd; + Reader Rd; String Name; char Eof1, Eof2; int Fd, Chr, Src, Ops; + InputStream Stream; SelectableChannel Chan; SelectionKey Key; PicoLispReader(Reader rd, String nm, int fd, SelectableChannel chan, int ops) { - if (rd != null) - Rd = new LineNumberReader(rd); + Rd = rd; Name = nm; InFiles[Fd = fd] = this; Chan = chan; @@ -1275,10 +1281,11 @@ public class PicoLisp { PicoLispReader(InputStream in, int fd, SelectableChannel chan, int ops) { this(in == null? null : new InputStreamReader(in), null, fd, chan, ops); + Stream = in; } PicoLispReader(String s, char eof1, char eof2) { - Rd = new LineNumberReader(new StringReader(s)); + Rd = new StringReader(s); Eof1 = eof1; Eof2 = eof2; } @@ -1490,8 +1497,8 @@ public class PicoLisp { return Nil; eofErr(); } - if (top && InFile != null) - InFile.Src = InFile.Rd.getLineNumber() + 1; + if (top && InFile != null && InFile.Rd instanceof LineNumberReader) + InFile.Src = ((LineNumberReader)InFile.Rd).getLineNumber() + 1; if (Chr == '(') { x = rdList(); if (top && Chr == ']') @@ -2268,7 +2275,7 @@ public class PicoLisp { String nm = path(name()); if (nm.charAt(0) == '+') nm = nm.substring(1); // No file reader with "rw" mode - return new InFrame(new PicoLispReader(new FileReader(nm), nm, allocFd(), null, 0), 1); + return new InFrame(new PicoLispReader(new LineNumberReader(new FileReader(nm)), nm, allocFd(), null, 0), 1); } catch (IOException e) { err(ex, this, "Read open error");