Showing preview only (6,944K chars total). Download the full file or copy to clipboard to get everything.
Repository: picolisp/pil21
Branch: master
Commit: 5cf52c58c7dd
Files: 202
Total size: 6.6 MB
Directory structure:
gitextract_pc6i5ihr/
├── COPYING
├── INSTALL
├── README
├── bin/
│ ├── pil
│ ├── psh
│ ├── pty
│ ├── vip
│ └── watchdog
├── doc/
│ ├── ChangeLog
│ ├── Tracks
│ ├── des.html
│ ├── doc.css
│ ├── faq.html
│ ├── httpGate.html
│ ├── man.html
│ ├── microTemplates
│ ├── native.html
│ ├── rc.sample
│ ├── ref.html
│ ├── refA.html
│ ├── refB.html
│ ├── refC.html
│ ├── refD.html
│ ├── refE.html
│ ├── refF.html
│ ├── refG.html
│ ├── refH.html
│ ├── refI.html
│ ├── refJ.html
│ ├── refK.html
│ ├── refL.html
│ ├── refM.html
│ ├── refN.html
│ ├── refO.html
│ ├── refP.html
│ ├── refQ.html
│ ├── refR.html
│ ├── refS.html
│ ├── refT.html
│ ├── refU.html
│ ├── refV.html
│ ├── refW.html
│ ├── refX.html
│ ├── refY.html
│ ├── refZ.html
│ ├── ref_.html
│ ├── search
│ ├── search.html
│ ├── select.html
│ ├── structures
│ ├── tut.html
│ └── viprc.sample
├── ext.l
├── lib/
│ ├── adm.l
│ ├── app.l
│ ├── bash_completion
│ ├── btree.l
│ ├── canvas.js
│ ├── canvas.l
│ ├── clang.l
│ ├── complete.l
│ ├── db.l
│ ├── dbgc.l
│ ├── debug.l
│ ├── form.js
│ ├── form.l
│ ├── frac.l
│ ├── gis.js
│ ├── gis.l
│ ├── heartbeat.l
│ ├── http.l
│ ├── json.l
│ ├── lint.l
│ ├── map
│ ├── math.l
│ ├── misc.l
│ ├── net.l
│ ├── pilog.l
│ ├── plio.js
│ ├── replica.l
│ ├── role.l
│ ├── select.l
│ ├── simul.l
│ ├── sq.l
│ ├── svg.l
│ ├── term.l
│ ├── test.l
│ ├── too.l
│ ├── ulimit.l
│ ├── user.l
│ ├── vip/
│ │ ├── cal.rc.l
│ │ ├── draw.l
│ │ ├── html.l
│ │ └── load.l
│ ├── vip.l
│ ├── xhtml/
│ │ ├── area
│ │ ├── field
│ │ ├── grid
│ │ ├── html
│ │ ├── input
│ │ ├── layout
│ │ ├── menu
│ │ ├── select
│ │ ├── submit
│ │ ├── tab
│ │ └── table
│ ├── xhtml.l
│ ├── xm.l
│ └── xxhash.l
├── lib.css
├── lib.l
├── loc/
│ ├── AE.l
│ ├── AR.l
│ ├── CH.l
│ ├── CKB.l
│ ├── CN.l
│ ├── DE.l
│ ├── ES.l
│ ├── FR.l
│ ├── GB.l
│ ├── GR.l
│ ├── HR.l
│ ├── IT.l
│ ├── JP.l
│ ├── NIL.l
│ ├── NO.l
│ ├── RU.l
│ ├── SE.l
│ ├── TR.l
│ ├── UA.l
│ ├── US.l
│ ├── ar
│ ├── ca
│ ├── ch
│ ├── ckb
│ ├── cn
│ ├── de
│ ├── el
│ ├── es
│ ├── fr
│ ├── hr
│ ├── it
│ ├── ja
│ ├── no
│ ├── ru
│ ├── sv
│ ├── tr
│ └── uk
├── man/
│ └── man1/
│ ├── picolisp.1
│ └── pil.1
├── misc/
│ ├── bigtest
│ └── stress.l
├── pil
├── soTest.c
├── src/
│ ├── Makefile
│ ├── Makefile.macos
│ ├── Makefile.openbsd
│ ├── apply.l
│ ├── balance.c
│ ├── base.ll
│ ├── big.l
│ ├── db.l
│ ├── dec.l
│ ├── defs.l
│ ├── ext.l
│ ├── ext.ll
│ ├── flow.l
│ ├── gc.l
│ ├── glob.l
│ ├── ht.l
│ ├── ht.ll
│ ├── httpGate.c
│ ├── io.l
│ ├── lib/
│ │ ├── ex.l
│ │ ├── llvm.l
│ │ └── so.l
│ ├── lib.c
│ ├── lib.so.c
│ ├── main.l
│ ├── pico.h
│ ├── ssl.c
│ ├── subr.l
│ ├── sym.l
│ ├── sysdefs.c
│ └── vers.l
├── test/
│ ├── lib/
│ │ ├── db.l
│ │ ├── lint.l
│ │ ├── math.l
│ │ └── misc.l
│ ├── lib.l
│ └── src/
│ ├── apply.l
│ ├── big.l
│ ├── db.l
│ ├── ext.l
│ ├── flow.l
│ ├── ht.l
│ ├── io.l
│ ├── main.l
│ ├── net.l
│ ├── subr.l
│ └── sym.l
└── vip
================================================
FILE CONTENTS
================================================
================================================
FILE: COPYING
================================================
PicoLisp Copyright (c) Software Lab. Alexander Burger
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: INSTALL
================================================
# 23jan26 Software Lab. Alexander Burger
PicoLisp Installation
=====================
PicoLisp needs a POSIX compatible system and the LLVM infrastructure. It
supports two installation strategies: Local and Global.
For a global installation, allowing system-wide access to the executable
and library/documentation files, you can either install it from a
ready-made distribution, or set some symbolic links to one of the local
installation directories as described below.
Note that you are still free to have local installations along with a
global installation, and invoke them explicitly as desired.
Local Installation
------------------
The following instructions work on Debian Linux. They should be similar
on other systems (for e.g. MacOS see src/Makefile.macos).
1. Install required packages
$ sudo apt install binutils make clang llvm libreadline-dev libffi-dev libssl-dev pkg-config
2. Unpack the tarball
$ wget https://software-lab.de/pil21.tgz
$ tar xfz pil21.tgz
3. Change the directory
$ cd pil21
4. Compile the PicoLisp interpreter
$ (cd src; make)
Global Installation
-------------------
The recommended way for a global installation is to use a picolisp
package from the OS distribution.
If that is not available, you can (as root) create symbolic links from
/usr/lib and /usr/bin to a local installation directory:
# ln -s /<path>/pil21 /usr/lib/picolisp
# ln -s /usr/lib/picolisp/bin/picolisp /usr/bin
# ln -s /usr/lib/picolisp/bin/pil /usr/bin
For additional access to the man pages, utilities and bash completion:
# ln -s /<path>/pil21/man/man1/picolisp.1 /usr/share/man/man1
# ln -s /<path>/pil21/man/man1/pil.1 /usr/share/man/man1
# ln -s /<path>/pil21 /usr/share/picolisp
# ln -s /<path>/pil21/lib/bash_completion /usr/share/bash-completion/completions/pil
Invocation
----------
In a global installation, the 'pil' command should be used. You can
either start in plain or in debug mode. The difference is that for debug
mode the command is followed by single plus ('+') sign. The '+' must be
the very last argument on the command line.
$ pil # Plain mode
:
$ pil + # Debug mode
:
In both cases, the colon ':' is PicoLisp's prompt. You may enter some
Lisp expression,
: (+ 1 2 3)
-> 6
To exit the interpreter, enter
: (bye)
or just type Ctrl-D.
For a local invocation, specify a path name, e.g.
$ ./pil # Plain mode
:
$ ./pil + # Debug mode
:
or
$ /home/app/pil # Invoking a local installation from some other directory
Note that 'pil' can also serve as a template for your own stand-alone
scripts.
Documentation
-------------
For further information, please look at "doc/index.html". There you find
the PicoLisp Reference Manual ("doc/ref.html"), the PicoLisp tutorial
("doc/tut.html"), and the frequently asked questions ("doc/faq.html").
As always, the most accurate and complete documentation is the source
code ;-)
Any feedback is welcome!
Hope you enjoy :-)
--------------------------------------------------------------------------------
Alexander Burger
Software Lab. / 7fach GmbH
Bahnhofstr. 24a, D-86462 Langweid
abu@software-lab.de, https://www.software-lab.de, +49 8230 5060
================================================
FILE: README
================================================
# 05nov25 Software Lab. Alexander Burger
Perfection is attained
not when there is nothing left to add
but when there is nothing left to take away
(Antoine de Saint-Exupery)
The PicoLisp System
===================
_PI_co Lisp is not _CO_mmon Lisp
PicoLisp can be viewed from two different aspects: As a general purpose
programming language, and a dedicated application server framework.
(1) As a programming language, PicoLisp provides a 1-to-1 mapping of a
clean and powerful Lisp derivate, to a simple and efficient virtual
machine. It supports persistent objects as a first class data type,
resulting in a database system of Entity/Relation classes and a
Prolog-like query language tightly integrated into the system.
The virtual machine was designed to be
Simple
The internal data structure should be as simple as possible. Only
one single data structure is used to build all higher level
constructs.
Unlimited
There are no limits imposed upon the language due to limitations
of the virtual machine architecture. That is, there is no upper
bound in symbol name length, number digit counts, or data
structure and buffer sizes, except for the total memory size of
the host machine.
Dynamic
Behavior should be as dynamic as possible ("run"-time vs.
"compile"-time). All decisions are delayed till runtime where
possible. This involves matters like memory management, dynamic
symbol binding, and late method binding.
Practical
PicoLisp is not just a toy of theoretical value. PicoLisp is used
since 1988 in actual application development, research and
production.
The language inherits the major advantages of classical Lisp systems
like
* Dynamic data types and structures
* Formal equivalence of code and data
* Functional programming style
* An interactive environment
PicoLisp is very different from any other Lisp dialect. This is partly
due to the above design principles, and partly due to its long
development history since 1984.
You can download the latest release version at
https://software-lab.de/pil21.tgz
(2) As an application server framework, PicoLisp provides for
NoSQL Database Management
Index trees
Object local indexes
Entity/Relation classes
Pilog (PicoLisp Prolog) queries
Multi-user synchronization
DB Garbage collection
Journaling, Replication
User Interface
Browser GUI
(X)HTML/CSS
XMLHttpRequest/JavaScript
Application Server
Process management
Process family communication
XML I/O
Import/export
User administration
Internationalization
Security
Object linkage
Postscript/Printing
PicoLisp is not an IDE. All program development in Software Lab. is done
using the console, bash, vip (vi-style editor) and the Lisp interpreter.
The only type of GUI supported for applications is through a browser via
HTML. This makes the client side completely platform independent. The
GUI is created dynamically. Though it uses JavaScript and XMLHttpRequest
for speed improvements, it is fully functional also without JavaScript
or CSS.
The GUI is deeply integrated with - and generated dynamically from - the
application's data model. Because the application logic runs on the
server, multiple users can view and modify the same database object
without conflicts, everyone seeing changes done by other users on her
screen immediately due to the internal process and database
synchronization.
PicoLisp is free software, and you are welcome to use and redistribute
it under the conditions of the MIT/X11 License (see "COPYING").
It is based on LLVM and compiles and runs on any 64-bit POSIX system.
--------------------------------------------------------------------------------
Alexander Burger
Software Lab. / 7fach GmbH
Bahnhofstr. 24a, D-86462 Langweid
abu@software-lab.de, http://www.software-lab.de
================================================
FILE: bin/pil
================================================
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
(load "@lib/net.l" "@lib/misc.l" "@lib/btree.l" "@lib/db.l" "@lib/pilog.l")
`*Dbg
(docs "@doc/")
================================================
FILE: bin/psh
================================================
#!/usr/bin/pil
# 06aug24 Software Lab. Alexander Burger
(load "@lib/net.l" "@lib/misc.l" "@lib/http.l")
(let Arg (opt)
(client "localhost"
(or
(format Arg)
(client "localhost" 80 (pack Arg "/!psh") (read)) )
(pack (opt) "!psh?"
(pw) "&"
(in '("tty") (line T)) "&"
(sys "TERM") )
(ctty (read))
(line)
(line) ) )
(bye)
================================================
FILE: bin/pty
================================================
#!/usr/bin/pil
# 05jul24abu
# Pseudo Terminal (PilBox)
# pty [host] [flg]
(load "@lib/term.l")
(setq
*Host (or (opt) "localhost")
*Port 8081 ) # Sync with ~/Port in PilBox
(unless (setq *Sock (connect *Host (inc *Port)))
(bye) )
(out *Sock
(in "~/.pty" (echo)) # Sync with ~/.pty in PilBox
(prinl) )
(in *Sock (rd 2)) # Skip "\r\n"
(finish (prinl))
(de sendCmd @
(udp *Host `(inc *Port)
(cons (in "~/.pty" (line T)) (rest)) ) )
(unless (opt)
(task (port (+ *Port 2))
(let? S (accept @)
(catch '(NIL)
(in S
(when (= (rd) (in "~/.pty" (line T)))
(let Z (tmp "pty.zip")
(casq (rd)
(+
(apply call (rd) "zip" "-r" Z)
(in Z (out S (echo))) )
(-
(out Z (echo))
(call "unzip" "-o" Z) ) ) ) ) )
(off *Msg) )
(close S)
(and *Msg (prinl @)) ) ) )
(when (getTerm)
(sendCmd
(cons 'setTerm (sys "TERM") @)
'(off *Err) )
(de *Winch
(sendCmd (cons 'setTerm (sys "TERM") (getTerm))) ) )
(raw T)
(call "stty" "intr" NIL)
(task *Sock
(in @
(ifn (rd 1)
(bye)
(wr @)
(flush) ) ) )
(loop
(and (key) (out *Sock (prin @))) )
================================================
FILE: bin/vip
================================================
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
# 30apr26abu
(unless *Dbg
(load "@lib/vip.l") )
(stack 1024)
(bye
(if
(vip~vi ## [+<pat> | +[<num>]] <file1> [+[<num>]] <file2> ..
(make
(while (opt)
(let (S @ L (chop S))
(cond
((pre? "+" S)
(link
(cond
((format S) (cons @ (opt)))
((= "+" S) (cons T (opt)))
((get (any (cdr L)) '*Dbg 1)
(symbols (cddr @))
(cons (car @) (cadr @)) )
(T (cons (cdr L) (opt))) ) ) )
((pre? "-" S) (load S))
(T (link S)) ) ) ) ) )
0
1 ) )
================================================
FILE: bin/watchdog
================================================
#!/usr/bin/pil
# 13apr23 Software Lab. Alexander Burger
# Use: bin/watchdog <host> <port> <from> <to1> <to2> ..
(load "@lib/misc.l")
# *MailHost *MailPort *MailFrom *MailTo *Watch
(argv *MailHost *MailPort *MailFrom . *MailTo)
(setq *MailPort (format *MailPort))
(unless (call 'test "-p" "fifo/beat")
(call 'mkdir "-p" "fifo")
(call 'rm "-f" "fifo/beat")
(call 'mkfifo "fifo/beat") )
(finish (call 'rm "fifo/beat"))
(de *Err
(prin (stamp))
(space)
(println *Watch) )
(task (open "fifo/beat")
(in @
(let X (rd)
(cond
((not X) (bye))
((num? X)
(let? W (assoc X *Watch)
(when (caddr W)
(msg (car W) " " (stamp) " bye") )
(del W '*Watch) ) )
((atom X) # bin/picolisp -"out 'fifo/beat (pr '$(tty))" -bye
(let D (+ (* 86400 (date T)) (time T))
(out X
(for W *Watch
(prinl
(align 7 (car W))
" "
(- (cadr W) D)
" "
(or (caddr W) "o")
" "
(cdddr W) ) ) ) ) )
((assoc (car X) *Watch) # X = (Pid Tim . Any)
(let W @ # W = (Pid Tim Flg . Any)
(when (caddr W)
(msg (car W) " " (stamp) " resumed") )
(set (cdr W) (cadr X))
(set (cddr W))
(con (cddr W) (or (cddr X) (cdddr W))) ) )
(T (push '*Watch (list (car X) (cadr X) NIL (cddr X)))) ) ) ) )
(task -54321 54321
(let D (+ (* 86400 (date T)) (time T))
(for W *Watch
(cond
((>= (cadr W) D))
((caddr W)
(msg (car W) " " (stamp)
(if (kill (car W) 15) " killed" " gone") )
(del W '*Watch) )
(T
(inc (cdr W) 3600)
(set (cddr W) T)
(let Sub (pack "Timeout " (car W) " " (cdddr W))
(msg (car W) " " (stamp))
(unless (mail *MailHost *MailPort *MailFrom *MailTo Sub)
(msg (cons Sub *MailTo) " mail failed " (stamp)) ) ) ) ) ) ) )
(wait)
================================================
FILE: doc/ChangeLog
================================================
26.4.30
Re-introduce 'any' (for '+<ns~sym>' arguments)
bin/vip
26.4.24
Check 'format' before 'get' (Bruno)
bin/vip
26.4.12
Bug in 'aux' for hooks (Andreas Rüegger)
lib/db.l
26.4.5
Use level 2 in 'not' rule
lib/pilog.l
26.4.4
ESC terminates '?'
doc/ref.html
26.3.31
Call 'dbFetch' also in 'prove'
src/subr.l
26.3.29
Minor comma
doc/refP.html
####### 26.3 #######
26.3.26
Remove "." after content and show whole week
lib/vip/cal.rc.l
26.3.21
'for' takes 'cnt', not 'num'
doc/refF.html
26.3.17
Use separate '$InChar' and '$OutChar' instead of '$IoChar'
src/glob.l
src/io.l
26.3.13
Force 'touch *.ll' if bootstrapping
src/Makefile
26.2.28
Show terminating "." after content
lib/vip/cal.rc.l
26.2.20
Remove '+Init' from radio button in 'bagBag'
lib/form.l
26.1.23
Fix MacOS build (Mike Pechkin, Andreas Hauser)
INSTALL
src/Makefile.macos
26.1.19
Restore "Constant Data" section from 22.5.29
doc/native.html
26.1.13
'iter>' for '+List' to set '*Iter+'
lib/db.l
Remove "lib/android.l" from distribution (is kept in PilBox)
26.1.12
Define PROT_READ, PROT_WRITE, MAP_SHARED and MAP_FAILED
Define "domainSock" (AF_UNIX domain sockets)
src/sysdefs.c
26.1.3
GET and POST restriction was removed jul23
doc/httpGate.html
26.1.2
Fix alphabetic order
doc/refC.html
26.1.1
Bug in 'dirname' for "/"
lib/misc.l
test/lib/misc.l
####### 25.12 #######
25.12.21
Vip ":cal" (calendar) command
doc/viprc.sample
New file
lib/vip/cal.rc.l
25.12.14
Namespace specification "ap~" not needed
doc/search.html
25.12.11
'scratch' returns buffer
lib/vip.l
25.12.9
Rename 'shift' to 'shiftN'
Refactor 'patMatch' to (search> . +Buffer)
lib/vip.l
'this' function
src/glob.l
src/flow.l
doc/ref.html
doc/refT.html
doc/refW.html
lib/sq.l
lib/vip.l
lib/simul.l
'keys' function
lib/vip.l
25.12.8
Support initial key sequence in "# VIP " header
lib/vip.l
25.12.7
Check for buffer-local command mappings
lib/vip.l
25.12.6
Inherit window methods when split
'status>' continued
'drawin' function
lib/vip.l
25.12.5
Fix 'any1' and 'any2' for 'init', 'iter' and 'scan'
doc/refI.html
doc/refS.html
'status>' method for '+Window'
lib/vip.l
25.12.4
'delBuf' function
lib/vip.l
25.12.3
Check for buffer-local key mappings
lib/vip.l
25.12.1
Revert res_init() from 25.11.29
src/ssl.c
25.11.30
Decode "%21", and handle multple header values (Mansur Mamkin)
lib/http.l
25.11.29
Reinitialize resolver before getaddrinfo()
src/ssl.c
25.11.26
Pointer casts for bufFloat() and bufDouble()
src/main.l
25.11.22
Typo
loc/RU.l
25.11.21
Add (val> . +Swap/R)
lib/form.l
25.11.20
Handle swap symbol replacement in '+Swap'
lib/db.l
(val> . +Swp) not needed
lib/form.l
25.11.14
"%" also matches braces "{" and "}"
lib/vip.l
25.11.10
Pointer casts for bufFloat() and bufDouble()
src/dec.l
src/lib.c
25.11.6
Optionally start 'lsn' listennig processes
src/httpGate.c
25.11.5
Remove phone number
README
Restore 'pkg-config --cflags libffi'
src/Makefile
Avoid stale 'CliSock' if fork() fails
src/httpGate.c
Add 'stat' output to 'proc'
lib/debug.l
25.11.2
New file
lib/xxhash.l
25.10.12
Set initial alarm to 2 seconds
lib/http.l
25.10.10
Extend example for 'yield' with 'env' arg
doc/refY.html
25.10.8
Optional 'prg' argument to 'yield'
src/flow.l
doc/refY.html
25.10.5
Bug in 'U' unsigned integer suppport
src/main.l
'i64u' type cast
src/lib/llvm.l
25.10.1
Use just CONTEXT in 'permit'
lib/android.l
####### 25.9 #######
25.9.28
Import 'U'
lib/reflect.l
25.9.27
Support 'U' unsigned integer result specification
src/glob.l
src/main.l
src/pico.h
doc/refN.html
25.9.26
Default scale 6
lib/reflect.l
25.9.25
'xCnt64' function
src/main.l
src/io.l
25.9.20
Recurse on nested structures
Remove '*Reflect'
lib/reflect.l
25.9.19
Use 'def' instead of 'set'
lib/reflect.l
25.9.17
Fix comment for linked libraries
soTest.c
25.9.16
New file
lib/reflect.l
25.9.15
Re-arrange evaluation in 'picolisp' to preserve stdout
src/main.l
Recommend (load) for "full" library
src/lib/so.l
25.9.13
Shared library continued
src/Makefile
src/main.l
soTest.c
25.9.9
reflect() function
src/lib/ex.l
src/lib/so.l
src/glob.l
src/main.l
doc/ref.html
doc/refR.html
evExe() function
src/main.l
src/io.l
src/apply.l
25.9.7
Add comment for "full" library
src/lib/so.l
Use 'parse' in 'picolisp'
src/main.l
25.9.6
Add interactive line input
soTest.c
Clean up
src/Makefile
src/dec.l
src/main.l
src/lib.so.c
25.9.2
New files
src/lib.so.c
soTest.c
'patch' function
src/lib/llvm.l
src/lib/so.l
'exclude' continued
src/Makefile
src/lib/llvm.l
src/lib/ex.l
src/lib/so.l
src/main.l
src/pico.h
src/big.l
src/subr.l
25.8.28
'$StkLimit' related to stack size
src/glob.l
src/main.l
src/flow.l
Call ulimStk() to set '$SysStkLimit'
src/lib.c
lib/ulimit.l
Quiche mode
src/lib/llvm.l
src/gc.l
src/sym.l
src/db.l
src/apply.l
'export' never worked!
lib.l
doc/refE.html
25.8.22
'dlfun' instruction
src/lib/llvm.l
src/main.l
25.8.21
'exclude' function
src/lib/llvm.l
src/lib/ex.l
src/lib/so.l
25.8.20
'!!' function
src/glob.l
src/flow.l
doc/ref.html
doc/ref_.html
25.8.15
Save position mark on every move
lib/vip.l
25.8.13
'stoplisp' function
src/main.l
25.8.12
Optionally build as shared library
src/Makefile
src/lib/llvm.l
src/dec.l
src/main.l
src/lib.c
src/io.l
New files
src/lib/ex.l
src/lib/so.l
25.7.29
Pass 'exe' instead of 'prg' to 'event' and 'wake'
lib/simul.l
doc/des.html
25.7.28
Handle circular lists in 'less'
lib.l
25.7.27
'sq' function
src/glob.l
src/big.l
test/src/big.l
doc/ref.html
doc/refS.html
doc/ref_.html
25.7.22
Use 'tco' in 'gcd'
lib/frac.l
25.7.19
Remove 'saveCoIO'
src/flow.l
25.7.15
Allow to stop main coroutine with (co T)
src/flow.l
doc/refS.html
25.7.5
'allowed' must be called before any GUI libs and/or 'allow' calls
doc/refA.html
####### 25.6 #######
25.6.27
'recur' signature analog to 'tco'
doc/refR.html
Return cons pair with hard limit
lib/ulimit.l
25.6.26
New file
lib/ulimit.l
Define RLIMIT_STACK, RLIMIT_NOFILE and RLIMIT_NPROC
src/sysdefs.c
25.6.17
Increase '$GcCount' in 'gc' dynamically
src/gc.l
25.6.7
Skip comments
lib/xm.l
25.6.4
Optional 'sub?' start byte position
src/dec.l
src/main.l
src/sym.l
test/src/sym.l
doc/refS.html
'flg' argument to 'group' for pre-grouped lists
src/subr.l
doc/refG.html
25.5.30
New file
lib/select.l
Deprecate 'db/x' and 'select/3' Pilog predicates, and move to "lib/select.l"
lib/pilog.l
doc/refB.html
doc/refD.html
doc/refF.html
doc/refH.html
doc/refI.html
doc/refP.html
doc/refR.html
doc/refS.html
doc/refT.html
doc/refV.html
doc/select.html
Deprecate Pilog GUI functions, and move to "lib/select.l"
lib/form.l
25.5.25
'idx' in 'search' also for 'relQs'
lib/db.l
25.5.23
Optional index argument to 'accu'
lib.l
test/lib.l
doc/refA.html
Minor tuning in 'cache' and 'once'
lib.l
25.5.22
Keep all command lines non-unique but longer than 3 in TAB-completion
lib/vip.l
Optionally return reversed key-value pairs from 'enum'
src/sym.l
doc/refE.html
test/src/sym.l
25.5.21
'min' and 'max' also accept a single list argument
src/subr.l
test/src/subr.l
doc/refM.html
25.5.17
Mention '@@' in the 'forall' reference
doc/refF.html
25.5.16
'sub?' stores substrig byte position in '@@'
src/dec.l
src/main.l
src/sym.l
test/src/sym.l
doc/refS.html
25.5.11
Auto-init in 'inc' and 'dec'
src/lib/llvm.l
src/big.l
Revert to 20 instead of 21 bits from 'hash'
src/big.l
test/src/big.l
doc/refH.html
25.5.10
Print times in 'bench' also as [hh:mm]
lib/debug.l
doc/refB.html
25.5.9
Bug in 'attr'
lib/xm.l
25.5.8
'version' can also check for a required version
src/main.l
doc/refV.html
Optimize 'idx' in 'search' for (+Ref +Link) and '+Joint'
lib/db.l
25.5.5
New files
src/Makefile.openbsd
src/Makefile.macos
25.4.24
'forall' also accepts an 'init' step structure
lib/db.l
doc/refF.html
25.4.20
Return 21 instead of 20 bits from 'hash'
src/big.l
test/src/big.l
doc/refH.html
'idx' in 'search' *after* filtering
lib/db.l
25.4.19
Bug in 'initSeed' for external symbols
src/big.l
25.4.18
'X' and 'Prg' in 'forall' private
lib/db.l
25.4.17
Simplify 'body' and 'attr'
lib/xm.l
25.4.14
'forall' also accepts a 'search' query structure
lib/db.l
doc/refF.html
'idx' in 'search' only if necessary
lib/db.l
25.4.13
Avoid catch/throw in 'step'
lib/btree.l
25.4.9
Add 'rt' to 'pretty'
lib.l
Return 20 instead of 16 bits from 'hash'
src/big.l
test/src/big.l
doc/refH.html
Hash 'idx' in 'search'
lib/db.l
25.4.7
Support 'prune' also in 'scan' and 'iter'
lib/btree.l
doc/refP.html
Make 'for' on lists more gc-conservative
src/flow.l
####### 25.3 #######
25.3.24
Don't skip empty value in 'create' for updates
More 'create' tuning
lib/db.l
25.3.20
'stdEval' must preserve '$At2'
src/io.l
'rt' function
src/glob.l
src/main.l
doc/ref.html
doc/refR.html
25.3.19
Remove parallelization with 'later' from 'create'
lib/db.l
25.3.13
KeyEvent 'keyCode' and 'charCode' are deprecated
lib/form.js
25.3.11
"onkeypress" is deprecated
lib/xhtml.l
25.3.9
Fix description of 'peek' (does not block, but returns only the next byte)
doc/refP.html
25.3.8
Scroll page on horizontal touch movements in tables
lib/form.js
Cosmetics
src/io.l
lib/form.l
25.3.7
Move 'pagehide' handling (back/forward cache) from 'html' to 'form'
lib/xhtml.l
lib/form.l
25.3.6
Remove @lib/tinymce.l from distribution
25.3.2
Change type of '$NsLink' from 'i64*' to 'any'
src/glob.l
25.2.27
Export namespace list from 'repl' via 'T' argument to 'symbols'
src/glob.l
src/sym.l
src/io.l
doc/refS.html
25.2.26
Typo
doc/refI.html
doc/refN.html
Use 'any' instead of 'intern' for '+<pat>' arguments
bin/vip
25.2.21
Move cursor left in final left scroll
lib/vip.l
25.2.17
Scroll two steps with horizontal arrow keys
lib/vip.l
25.2.13
'tco' continued
lib/lint.l
25.2.9
'tco' continued
src/flow.l
lib.l
test/src/flow.l
25.2.8
'tco' and 'tc' tail call optimization functions
src/glob.l
src/flow.l
doc/ref.html
doc/refR.html
doc/refT.html
25.2.5
'if@@' function
src/glob.l
src/flow.l
test/src/flow.l
doc/ref.html
doc/refC.html
doc/refI.html
25.2.1
Missing 'F' argument to 'packJson'
lib/json.l
25.1.22
Change 'permute' to use a callback function
lib/simul.l
25.1.21
Postpone first move event for better double-click detection
lib/canvas.js
25.1.9
Re-introduce "array" feature
lib/json.l
25.1.5
Handle "^?"
lib/vip.l
Read and print decimal unicode in symbol names
src/io.l
lib.l
25.1.4
Wrong examples for 'eval' and 'run' offset
doc/refE.html
doc/refR.html
Fix 'remark'
lib.l
####### 24.12 #######
24.12.30
Remove '*SesAdr' check
lib/http.l
lib/adm.l
24.12.23
Automatic lib configuration (Mike Pechkin)
src/Makefile
Reset form on 'pagehide' event to disable back/forward cache
lib/xhtml.l
24.12.22
Reduce Cache-Control to 'no-store'
lib/http.l
24.12.17
'remark' continued
lib.l
lib/vip.l
Typo
doc/refT.html
24.12.16
'remark' function to generalize REPL-comments
src/glob.l
src/io.l
lib.l
lib/vip.l
doc/refR.html
'complete' reference
doc/refC.html
24.12.14
Print namespace of symbols in REPL-comments
src/io.l
lib/vip.l
24.12.13
Cyan attribute for REPL-comments
src/io.l
'markup' also in 'scratch'
Print numbers as fixnum-comments also in Vip REPL
lib/vip.l
24.12.10
New file
lib/vip/load.l
24.12.5
Add ":wq" as alias for ":x"
lib/vip.l
24.12.2
Add section about namespaces
doc/ref.html
doc/refE.html
doc/refI.html
doc/refL.html
doc/refN.html
doc/refP.html
doc/refS.html
24.11.23
Example for catching errors
doc/refC.html
24.11.21
Intern mark names into 'vip'
lib/vip.l
24.11.20
Generalize 'llvm~fmtNum'
Print numbers as fixnum-comments in REPL
src/big.l
src/io.l
src/subr.l
doc/rc.sample
doc/refR.html
doc/refS.html
doc/ref_.html
24.11.7
Remove obsolete C-level 'lisp' descriptions
doc/refN.html
doc/native.html
24.10.16
Support also HOME and END keys
lib/vip.l
####### 24.9 #######
24.9.7
'0' for empty name in minimal symbol diagram
doc/ref.html
24.8.19
Stop 'gps' via 'Flg' argument
lib/android.l
24.8.16
'pil' is obsolete
doc/refT.html
24.8.7
Add 'L' and 'S' to private symbols
lib/vip.l
24.8.6
Pass TERM environment variable to 'psh'
lib/http.l
bin/psh
24.8.4
'wake' returns 'isHeld'
lib/android.l
24.8.3
Fix 'gps' with two Location Listeners
lib/android.l
24.7.30
Typo
doc/refN.html
24.7.23
Call 'restart' as a UI thread (avoid 'java' reentrancy)
lib/android.l
24.7.15
Cosmetics
src/io.l
src/ht.l
24.7.10
'volatile' access to '$Signal'
src/lib/llvm.l
src/dec.l
24.7.9
'Exe' argument to 'xName' not used
src/main.l
src/sym.l
src/io.l
src/db.l
src/flow.l
src/ext.l
'prompt' function
src/glob.l
src/main.l
doc/ref.html
doc/refP.html
Typo
doc/structures
24.7.7
Check for stale I/O frames in 'unwind'
src/main.l
24.7.5
Change pbPut/pbGet to Zip transfers
bin/pty
Bug in 'erVar'
lib/form.l
Typo
doc/refD.html
24.7.4
Mention '~' in the 'pico' reference
doc/refP.html
24.7.3
Check for SDK_INT >= 31 in 'alarm?'
lib/android.l
24.7.2
Adjust 'alarm' for changed numeric arguments
lib/android.l
####### 24.6 #######
24.6.27
Minimal delay time 1 ms in 'des'
lib/simul.l
Force frame buffer register through runCo()
src/flow.l
Re-arrange structures for alignment
src/glob.l
src/dec.l
24.6.26
'otg' in coroutine structure missing
doc/structures
24.6.23
Show terminated originator in 'yield' error
src/flow.l
24.6.22
'prv' in coroutine structure is obsolete
doc/structures
Fix 'This' upon coroutine termination
Bug in coroutines with non-symbolic tags
src/flow.l
24.6.21
Change 'opt' from "-O3" to "-O2"
src/Makefile
Generalize 'all*'
lib.l
dirString() function
src/main.l
Bug in coroutine free-list management
src/flow.l
24.6.20
Generalize output in 'tty'
src/main.l
src/gc.l
Check for terminated originator in 'yield'
src/flow.l
24.6.18
Clear 'at' in coroutine 'unwind'
src/main.l
'putCrtEnv' clean up
src/dec.l
src/flow.l
24.6.17
Reentrant 'co' checks
src/flow.l
24.6.16
Thread exceptions revisited
lib/android.l
24.6.14
'alarm?' function
lib/android.l
24.6.13
Call fcntlSetFl() in 'accept' if OpenBSD or FreeBSD
lib/net.l
24.6.12
Disallow reentrant 'co' calls
src/flow.l
doc/ref.html
doc/refC.html
24.6.9
Default format 72 columns
lib/vip.l
COPYING
README
INSTALL
doc/microTemplates
24.6.5
Handle thread exceptions in 'java1'
lib/android.l
24.6.2
Make 'dirname' and 'basename' non-destructive
lib/misc.l
24.5.30
'catch' stores throw/error-flag in '@@'
src/flow.l
test/src/flow.l
doc/refC.html
lib/vip.l
lib/form.l
24.5.24
'iter' returns 'NIL'
doc/refI.html
24.5.23
Typo
doc/search.html
24.5.8
Minor mismatch
doc/faq.html
24.4.4
TAB-completion also for search commands
lib/vip.l
24.4.3
No 'flushAll' in child process 'bye'
src/main.l
src/lib.c
24.4.1
'for' instead of 'while' in 'des'
lib/simul.l
24.3.31
Change 'sendCmd' protocol to UDP -> background task
bin/pty
####### 24.3 #######
24.3.29
Include lib/sysdefs in "clean2"
src/Makefile
24.3.28
Ignore ESC in command mode
lib/vip.l
24.3.11
Call (raw T) at start and (raw NIL) when done
lib/vip.l
24.3.10
'scale' function
lib/svg.l
24.3.5
Bug in "words"
doc/viprc.sample
24.2.3
Fix 'stack' reference
doc/refS.html
24.1.29
Runtime relations via 'erVar' function
lib/form.l
24.1.21
Add "apk" to '*Mimes'
lib/http.l
23.12.29
Minor comment
lib/simul.l
####### 23.12 #######
23.12.18
requestAnimationFrame() not helpful
lib/canvas.js
23.12.13
'P' instead of 'N' in native call (malloc() returns pointer)
test/src/main.l
'*DB' is 'NIL' while no database is open
src/glob.l
src/main.l
src/gc.l
src/db.l
doc/refD.html
23.12.12
'server' single-shot (non-forking) mode with 'Flg' argument
lib/http.l
23.12.9
ZERO-cache also for 'co' stopping
src/flow.l
23.12.8
ZERO-cache and free-list for 'co' speedup
src/glob.l
src/dec.l
src/main.l
src/flow.l
doc/ref.html
23.12.6
'co' crashes when gc() runs in put()
src/flow.l
23.12.5
Return 1 from ulimStk() for minimal stack address
src/lib.c
23.12.4
Use 'key' instead of 'line' (because of GNU readline behaviour change)
in 'more' and 'bt'
lib/debug.l
doc/refM.html
doc/refB.html
in 'select'
lib/sq.l
doc/refS.html
and in 'query' (and thus also '?')
lib/pilog.l
doc/refQ.html
doc/ref_.html
23.12.3
Global '$StkBrk' not needed
src/glob.l
src/main.l
23.12.1
Change transient "U" in 'bench' to private
lib/debug.l
23.11.30
Typo
doc/refN.html
23.11.29
Default '*Rt' off
lib/simul.l
doc/des.html
Check for empty 'lst' in renderCanvas()
lib/canvas.js
23.11.28
Transient "U" in 'bench'
lib/debug.l
23.11.27
Resume all coroutines waiting for the same point in time
lib/simul.l
doc/des.html
23.11.26
Use '*@@' instead of '@@'
lib/vip.l
'make' stores linkage cell in '@@'
src/subr.l
doc/refM.html
23.11.22
Simplify key loop in 'des'
lib/simul.l
23.11.19
Fix 'help' for new reference format
lib/debug.l
doc/refH.html
23.11.18
Handle optional count in ":bd"
lib/vip.l
Explicit symbol argument to 'new'
src/flow.l
doc/refN.html
23.11.17
'sext' constexprs are deprecated (Mike Pechkin)
src/lib/llvm.l
23.11.12
Use 'push1' instead of 'push' in 'finish'
lib.l
Mark end of layout in 'tracks' also with "#"
lib/simul.l
Remove @lib/compat.l from distribution
23.11.7
Fix 'cancel' call in 'alarm'
Checks for SDK_INT >= 26 are obsolete
lib/android.l
23.11.3
Search also for inherited indexes in 'select'
Clean up
lib/sq.l
doc/refS.html
23.10.31
Handle external symbols in 'xName'
src/main.l
'flg' argument to 'ext?' to check physical existence
src/db.l
lib/debug.l
lib/vip.l
23.10.30
More general matching in 'search'
lib/db.l
Skip duplicates in 'hintQ'
lib/form.l
23.10.29
Load @lib/sq.l at the end of @lib/db.l
lib/db.l
lib/pilog.l
Keep relative file position
lib/vip/html.l
23.10.28
Change 'hintQ' to use 'match>'
lib/form.l
Return 'Val' from 'match>' methods
lib/db.l
23.10.27
Minor comment
lib/svg.l
Change 'dump' to use 'search'
lib/too.l
23.10.26
Insert "# VIP " headers
Fix <pre> markups
*.html
23.10.25
Typo
doc/search.html
Minor comments
src/subr.l
doc/refC.html
23.10.24
Typo
doc/search.html
23.10.23
Continued
doc/search.html
Add "search.html"
doc/toc.html
Comments
lib/db.l
23.10.22
Style for <pre> tags
doc/doc.css
23.10.21
Documentation continued
doc/refS.html
doc/search.html
23.10.20
New file
doc/search.html
Use (sys "BROWSER") if set
lib/vip.l
23.10.19
Cosmetics
lib/vip/draw.l
New file
lib/vip/html.l
Check for "# VIP " in the first three lines
lib/vip.l
23.10.18
Use inherited tree
lib/db.l
23.10.17
Optional extract-function argument to 'search'
lib/db.l
doc/refS.html
23.10.16
Bug in 'iter>' for '+Sn'
lib/db.l
23.10.15
Change 'select' to use 'search'
lib/sq.l
'+DbChart' and 'hintQ' functions
lib/form.l
'search' function with 'iter>' and 'match>' methods
lib/db.l
doc/ref.html
doc/refC.html
doc/refS.html
New file
doc/search
23.10.5
Check 'status != 200' in 'onload'
lib/form.js
####### 23.9 #######
23.9.27
Add namespace "-ap~main"
doc/select.html
23.9.26
Cosmetics
lib/form.l
23.9.23
Use '*Evt' mechanism instead of 'Busy'
lib/form.l
lib/form.js
Remove 'vf'
lib/vip.l
23.9.20
Change global 'FormReq' to local
lib/form.js
23.9.19
Optionally cache image in 'csDrawImage'
lib/canvas.l
lib/canvas.js
23.9.17
Missing semicolon
lib/canvas.js
23.9.13
Remove 'Queue' global
lib/form.js
23.9.9
Remove "form.html" and "app.html", add "des.html"
doc/toc.html
23.9.8
Don't fall back to stdin/stdout for closed files
src/io.l
Load also @lib/lint.l in 'psh'
lib/http.l
23.9.7
Realtime mode 'off' in "dining" demo
doc/des.html
23.9.6
Preserve initial 'This' in coroutines
src/flow.l
doc/ref.html
23.9.5
Adjust LLVM version check (Mike Pechkin)
src/Makefile
23.9.4
Mark 'tag' and 'prg' also in non-running coroutines
src/gc.l
23.9.3
Allow reentrancy in coroutines
src/flow.l
doc/ref.html
23.8.31
Tag checks in 'co' and 'yield'
src/dec.l
src/flow.l
Cosmetics
doc/des.html
23.8.29
'noLint' for 'RED'
lib/term.l
23.8.28
Homogenize 'input' and' 'output'
src/glob.l
src/dec.l
src/main.l
src/gc.l
src/io.l
src/flow.l
'null' instead of '@null' in 'table'
src/lib/llvm.l
23.8.27
Set namespace for '+<pat>' argument in debug mode
bin/vip
23.8.26
Handle $ErrFrames and $CtlFrames in coroutines
src/flow.l
src/dec.l
'yield' bug revisited
src/flow.l
23.8.25
Release reference to Java object (Todd Coram)
lib/android.l
23.8.22
Bug in 'yield' for nested coroutines
src/flow.l
23.8.21
Move 'getSize' to lib/term.l
lib/term.l
lib/vip.l
'clear' function
lib/term.l
23.8.20
Generalize 'attr'
lib/term.l
23.8.15
Note about coroutine environments
doc/ref.html
23.8.13
Clarify 'stack' reference
doc/refN.html
23.8.12
Avoid 'read' in 'download'
lib/misc.l
23.8.8
Search first 'priv' in 'nsp'
src/sym.l
doc/refP.html
Rename lisp-level functions '_xxx' to '_Xxx'
src/glob.l
src/main.l
src/gc.l
src/big.l
src/sym.l
src/io.l
src/db.l
src/apply.l
src/flow.l
src/subr.l
23.8.7
'startForeground' with service type
lib/android.l
23.8.6
Set SSL_CERT_FILE only if on mobile device
lib/android.l
23.8.4
Check local variables for lower case in 'lint'
lib.l
lib/lint.l
lib/xhtml.l
lib/form.l
lib/svg.l
23.8.3
Defer advancing the list pointer in 'for'
src/flow.l
23.8.1
Fixes to 'native' description
doc/refN.html
doc/native.html
Target SDK 34 / androidx
lib/android.l
23.7.28
opaque-pointers for '18 > LLVM >= 15' (Mike Pechkin)
src/Makefile
23.7.24
Partially revert style simplification from 21.11.21
lib/form.l
lib/form.js
23.7.23
New Vip commands
- "gw" View Web page
- "gh" View HTTP code
- "gb" Invoke Browser (w3m)
Implicit writing to 'scratch' files
Extend 'map+', 'map+g' and 'map+q'
lib/vip.l
23.7.21
Minor clarification of @-result
doc/ref.html
23.7.20
Revisit 'allow'
lib/svg.l
23.7.19
Missing arg to "getnameinfo" in 'host'
lib/net.l
23.7.17
Generalize 'def' for 'any' keys
src/flow.l
doc/refD.html
Don't 'allow' temporary files by default any longer
lib/http.l
lib/xhtml.l
lib/svg.l
23.7.13
Bug in 'input' and 'output': Must preserve '@'
src/io.l
23.7.10
Revert change from 23.7.6
bin/vip
TAB-completion also from command history
lib/vip.l
23.7.8
Note about accessing symbol values in ':'
doc/ref_.html
23.7.7
'all*' function
doc/ref.html
Exponent notation in 'parseJson' and 'readJson'
lib/json.l
23.7.6
Use 'str' instead of direct 'intern' to handle namespaces
bin/vip
23.7.4
Generalize HTTP method support
src/httpGate.c
23.7.2
Deprecate 'zxing?' / 'queryIntentActivities'
lib/android.l
####### 23.6 #######
23.6.25
Print current coroutine in 'stkErr'
src/main.l
23.6.18
Minor comment
bin/pty
23.6.16
Minor elaboration on the 'sect' reference
doc/refS.html
23.6.6
Disallow append mode (via "+file") in 'in' and 'load'
src/io.l
doc/refI.html
doc/refO.html
23.6.4
'+<pat>' defaults to tag in debug mode
bin/vip
Accept 'any' in 'intern'
src/lib/llvm.l
src/sym.l
lib.l
test/src/sym.l
doc/refI.html
lib/form.l
lib/dbgc.l
23.5.27
Global '*AlwaysAsk'
lib/form.l
23.5.25
Track network functions
lib/simul.l
New file
doc/Tracks
Add more stack checks
src/main.l
src/flow.l
23.5.24
Change stack segment safety margin from 4096 to 1024
src/glob.l
src/flow.l
23.5.15
Remove 'Cpy' from getCrtEnv(), set 'env' and '$StkLimit' in loadCoEnv()
src/dec.l
src/main.l
src/flow.l
23.5.7
Show buffer and dirty status also for long path names
lib/vip.l
23.5.6
Deprecate "ta" abbreviation for "tag" command
lib/vip.l
23.5.5
Fix description of left/right fork signals
doc/des.html
23.4.28
Set 'home' property in '<drawCanvas>' to '*Top'
lib/canvas.l
23.4.25
Wait for multiple events in 'pause'
lib/simul.l
doc/des.html
23.4.24
Use 'idx' instead of 'rank' in '*Next'
lib/simul.l
doc/des.html
Bug in 'compare' for anonymous symbols
src/main.l
23.4.22
New file
doc/des.html
Return max and min from 'idx' for 'T' and 'NIL' key arguments
Randomize 'idx' if 'flg' is '0'
src/sym.l
src/io.l
doc/refI.html
chance() function
src/dec.l
src/lib.c
23.4.18
Needs 'symb?' instead of 'sym?' in 'repl'
src/io.l
Cache coroutines for 'yield' in ZERO-properties
src/main.l
src/flow.l
Clean up ZERO key handling in 'put' and 'get'
src/sym.l
src/flow.l
Bug in ffiPrep() for direct Lisp arguments
src/lib.c
23.4.16
'private' cosmetics
lib/net.l
23.4.13
'finish' function
lib.l
lib/app.l
lib/heartbeat.l
bin/pty
bin/watchdog
doc/ref.html
doc/refB.html
doc/refF.html
doc/refO.html
23.4.5
Evaluate list arguments in 'select'
lib/sq.l
doc/refS.html
23.4.3
Examples and test cases for 'ext:Base64' in 'input' and 'output'
test/src/ext.l
doc/refI.html
doc/refO.html
####### 23.3 #######
23.3.29
Make second port for pbPut/pbGet optional
bin/pty
23.3.28
Suppress duplicates in 'db/[345]'
lib/pilog.l
23.3.27
Fix escapes for special characters
lib/debug.l
doc/ref.html
doc/refB.html
doc/refD.html
doc/refE.html
doc/refN.html
doc/refM.html
doc/refP.html
doc/refR.html
doc/refU.html
doc/refX.html
doc/ref_.html
doc/tut.html
doc/native.html
23.3.26
Fix various markup issues
lib/debug.l
lib/form.l
ref.html
ref?.html
faq.html
tut.html
native.html
select.html
httpGate.html
Set download link to demoApp.tgz
doc/select.html
23.3.25
Undo tag argument restriction from 14feb23
src/flow.l
doc/refC.html
doc/refY.html
23.3.19
Allow one "-" in uppercase global constants
Handle 'default'
lib/lint.l
'noLint' for 'null'
lib/android.l
23.3.17
Repeat last shell command with ":$"
lib/vip.l
23.3.13
Support more attributes in 'serverSentEvent'
Force chunked transfer in 'serverSend'
lib/xhtml.l
23.3.5
Typo
lib/vip.l
Restrict 'words' command to 'delimNs'
doc/viprc.sample
23.2.27
Bug in 'js>' for '+Url'
lib/form.l
23.2.22
Default hasbangs to /usr/bin/pil
bin/pty
bin/psh
bin/watchdog
23.2.14
Tag argument to 'co' and 'yield' must be a symbol
src/flow.l
doc/refC.html
doc/refY.html
23.2.9
Add "mp4" to '*Mimes'
lib/http.l
####### 23.2 #######
23.2.8
Check for atomic argument in 'made'
src/subr.l
23.2.6
Undo cosmetics from 14jul22
lib/btree.l
23.2.5
Keep 'prg' argument to 'des' private
lib/simul.l
23.2.4
Allow numeric argument to 'repl'
src/io.l
Add BROWN and PURPLE
lib/term.l
23.2.1
Numeric '*Rt' as speedup factor
Optional 'prg' argument to 'des'
Change '*Key' to fifo structure '*Keys'
lib/simul.l
23.1.31
Optional 'var' argument to 'key'
src/io.l
doc/refK.html
23.1.27
Optional anchor for '<this>'
'<a>' anchor function
lib/xhtml.l
23.1.21
Init '*Key' in 'des'
Bug in 'wake'
lib/simul.l
23.1.15
Handle 'onOff'
lib/lint.l
23.1.14
Auto-quote 'null'
lib/android.l
23.1.13
'setCooked', 'setRaw' not needed in 'main' and 'brkLoad'
src/main.l
src/flow.l
Call rl_deprep_terminal() in 'setCooked'
src/lib.c
23.1.9
Minor cosmetics
src/main.l
23.1.6
Add link to @lib/bash_completion
INSTALL
23.1.2
Separate buffer for each "$" (shell) command call
lib/vip.l
23.1.1
Clear *Complete upon backspace
lib/vip.l
22.12.30
Handle destructuring function parameters
lib/lint.l
22.12.28
Move 'less' to @lib.l
lib.l
lib/debug.l
doc/refL.html
####### 22.12 #######
22.12.21
Use 'less' in 'show'
lib.l
doc/refB.html
doc/refM.html
doc/tut.html
Minor fix indentation
lib/debug.l
'circ' for atomic mapping arguments no longer needed
lib/http.l
22.12.20
Global '*Key'
lib/simul.l
22.12.18
Add GREEN and BLUE
lib/term.l
22.12.15
Handle destructuring function parameters in 'funq'
src/main.l
22.12.12
Fix 'tword' to go to the last space
lib/vip.l
22.12.11
Clear 'last' for deleted buffer
lib/vip.l
Directly call 'symbols' in 'tag'
lib/vip.l
22.12.2
Add percentage display to '<progress>'
lib/xhtml.l
Commented example for LEFT and RIGHT
doc/viprc.sample
22.12.1
Check for ":" delimiter in TAB-completion
lib/vip.l
22.11.22
'boss' is obsolete
lib/android.l
TAB-completion also for colon-commands
lib/vip.l
22.11.20
Minor privates
lib/vip.l
22.11.19
Fix 'unwind'ing coroutines
src/dec.l
src/main.l
src/flow.l
Reset screen and namespaces upon error
lib/vip.l
bin/vip
22.11.18
'namespaces' function
lib/debug.l
doc/refN.html
doc/refS.html
Exchange also 'last', 'mark' and 'sc' in ":bx"
lib/vip.l
22.11.15
'shadows' function
lib/debug.l
doc/refS.html
Allow also new namespace for '-symbols'
lib.l
22.11.14
Wrong 'save' / 'safe' in 'rdList'
src/io.l
Private 'queue'
lib/simul.l
22.11.12
'tabs' command to replace tabs with spaces
'words' command to toggle between Lisp an C
doc/viprc.sample
Generalize delimiter checking
lib/vip.l
22.11.11
Store 'symbols' source info after the change
src/sym.l
22.11.10
'info' returns local time instead of UTC if the flag argument is zero
src/dec.l
src/main.l
src/lib.c
doc/refI.html
lib/vip.l
22.11.9
Set blob symlinks in mirror destination directories
src/ssl.c
22.11.2
Clear references to deleted buffer in ":bd"
lib/vip.l
22.10.30
Don't clear '@' and '@@' before (gc)
src/gc.l
doc/refG.html
22.10.26
Passing zero to 'tell' refers to the parent process
src/io.l
src/db.l
doc/refT.html
Remove "lib/boss.l" from distribution
22.10.21
Use 'delete' instead of 'replace'
lib/dbgc.l
22.10.20
Minor cosmetics
src/main.l
src/subr.l
22.10.17
Decrement 'Ms' in 'waitFd' only if not 292MY
src/io.l
Include external declaration of ppoll()
src/lib.c
Fix reference of '*CPU'.
doc/refC.html
22.10.15
Avoid setting 'last' to current buffer
lib/vip.l
Call 'flush' in 'beep'
lib.l
22.10.6
'able' checks in 'val>' for '+ObjVal' and '+ObjVar'
lib/form.l
22.10.4
Add 'put' and 'get' to reference of '+Joint'
doc/refJ.html
####### 22.9 #######
22.9.29
Bitmask bug in <menu>
lib/xhtml.l
22.9.24
Use opaque-pointers in LLVM >= 15 (Mike Pechkin)
src/Makefile
22.9.16
Support partially circular lists in 'pretty' and 'view'
Print 'def' in 'pp' instead of 'de' for non-functions
lib.l
Simplify printing of circular lists
src/io.l
22.9.13
Move "ix.io" to @doc/viprc.sample, added "pb1n"
lib/vip.l
doc/viprc.sample
Bug in 'server' for non-numeric arguments
lib/net.l
22.9.9
Allow empty 'url' argument
src/ssl.c
22.9.6
Pass FLAG_IMMUTABLE to PendingIntent
lib/android.l
22.9.4
Avoid multiple auto timers
lib/canvas.js
22.9.3
Pass flag 'T' for mouse/touch events
lib/canvas.l
lib/canvas.js
22.9.1
Make 'all*' selective with 'T' or '0'
lib.l
doc/refA.html
lib/vip.l
22.8.31
Change 'http' abort time to 20 minutes
lib/http.l
22.8.30
'<progress>' function
lib/xhtml.l
Abort 'http' after 7 seconds
lib/http.l
22.8.29
Remove stale symbolic links
src/ssl.c
22.8.26
'cmd' function
lib/vip.l
22.8.22
Store debug source info in 'symbols'
src/dec.l
src/sym.l
lib/debug.l
doc/refD.html
doc/refS.html
22.8.21
Extend 'pool' tests
test/src/db.l
test/lib/db.l
22.8.20
'b8+' aligns stack buffers to 8 bytes
src/lib/llvm.l
src/main.l
src/io.l
src/db.l
src/flow.l
Pad 'dbFile' and 'child' to multiples of 8
src/dec.l
Add file
doc/viprc.sample
Improve use cases
doc/rc.sample
22.8.19
'gPrintf' returns void
src/dec.l
Size check in gPrintf()
src/lib.c
'save' before 'loop'
src/main.l
'$TickU' and '$TickS' are obsolete
src/glob.l
22.8.18
Declare 'Tio' and 'Fsign' as "char" instead of "int"
src/lib.c
Make insensitive to endianness
test/src/main.l
22.8.1
Add note on destructuring bind of function parameters
doc/ref.html
22.7.27
Bug in 'extra' assuming positive pointers
src/flow.l
Display applied functions in backtraces
lib/debug.l
lib/app.l
22.7.20
Bug in 'compare' for circular lists
src/main.l
test/src/subr.l
22.7.16
Call 'blob+' in (clone> . +Entity)
lib/db.l
22.7.15
Improve 'hex' argument verification
lib/misc.l
22.7.14
Use 'skip' instead of 'line' in 'here'
lib/misc.l
Minor cosmetics
lib/btree.l
22.7.13
'overview' function
lib/android.l
Go to last instead of previous buffer in ":bd"
lib/vip.l
22.7.12
Remove "Building httpGate"
doc/httpGate.html
'<drawCanvas>' function
lib/canvas.l
22.7.11
Go to previous instead of next buffer in ":bd"
lib/vip.l
22.7.9
Correct earth mean radius to 6371 km
lib/gis.l
22.7.8
'map+', 'map+g' and 'map+q' functions
lib/vip.l
22.7.3
Default values in 'print>' methods
lib/sq.l
22.7.2
Uncomment 'shift' import
src/lib/llvm.l
Let 'beep' return 'NIL'
lib.l
lib/vip.l
doc/refB.html
22.6.30
Show blank screen in 'restart'
lib/android.l
####### 22.6 #######
22.6.30
Bug in realpath() handling
lib/vip.l
22.6.26
Corrections (Christos Gitsis)
doc/ref.html
doc/refA.html
More fixes in local coroutine stacks
src/flow.l
22.6.25
realpath() directly if directory
lib/vip.l
22.6.24
Apply realpath() only to path of the file
lib/vip.l
More fixes in local coroutine stacks
src/flow.l
22.6.23
Set 'org' when resuming a coroutine in 'co'
src/flow.l
22.6.22
Silent exit if connect fails
src/ssl.c
22.6.17
Bugs in 'sort' with 'fun' argument
src/subr.l
22.6.15
Disable '*Run' in 'sync' calls
lib/form.l
22.6.13
Bug in printing symbols overshadowed in 'priv'
src/io.l
22.6.10
Don't lock remote symbols
lib/vip.l
22.6.9
Check empty name in '+SymField'
lib/form.l
22.6.7
Refined system clipboard copy
lib/vip.l
22.6.6
Missing "void *" in '*C-Defs'
src/lib/llvm.l
22.6.3
Disable form action for stale locks
lib/form.l
22.5.31
Remove 'visibilitychange' event handling
lib/xhtml.l
22.5.30
'h' function
lib/debug.l
doc/refH.html
22.5.29
String arguments do no longer cause strdup(3) calls
doc/native.html
22.5.26
Add 'binutils'
INSTALL
Use 'output' instead of 'pipe'
lib/misc.l
Replace control characters with backslash sequences
lib/misc.l
lib/db.l
lib/vip.l
lib/term.l
lib/http.l
lib/xhtml.l
lib/form.l
lib/canvas.l
lib/xm.l
lib/tinymce.l
test/src/io.l
test/src/sym.l
test/lib/misc.l
doc/tut.html
doc/refA.html
doc/refP.html
doc/form/refS.html
doc/app.html
misc/bigtest
22.5.25
Bug in 'untrace'
lib/debug.l
Multi-line data in 'serverSend'
lib/xhtml.l
'input' and 'output' functions
src/glob.l
src/dec.l
src/main.l
src/gc.l
src/io.l
test/src/io.l
doc/ref.html
doc/refI.html
doc/refO.html
22.5.18
Fix 'raw' example
doc/refR.html
Clear stdin 'tty' flag in 'pipe' child
src/io.l
22.5.15
Replace "%" also if in command window
lib/vip.l
22.5.13
Optional "dup" file descriptor argument to 'fd'
src/io.l
doc/refF.html
Use 'in' instead of 'pipe' for "ccrypt" call
lib/vip.l
22.5.12
Fix 'dbs' example
doc/refD.html
22.5.11
Use '*Uri' instead of '*Url' in 'post'
lib/form.l
22.5.10
Support also PUT, PATCH and DELETE
src/httpGate.c
22.5.6
Global '*Uri'
lib/http.l
Clean up '*Err'
lib/app.l
22.5.5
Call 'flush' in 'tty'
src/dec.l
src/main.l
src/ht.l
22.5.3
Use 'tty' in 'msg'
lib.l
Re-introduce 'visibilitychange' event handling
lib/xhtml.l
22.5.1
'fun' function
src/glob.l
src/apply.l
test/src/apply.l
doc/ref.html
doc/refF.html
22.4.30
Add "epub" mime type
lib/http.l
22.4.26
Outdated example for 'lisp'
doc/refL.html
22.4.24
Define PATH_MAX
src/sysdefs.c
lib/vip.l
22.4.22
Preserve 'errno' across readline(3) calls
src/dec.l
src/io.l
src/lib.c
Word search without 'match' support
lib/vip.l
22.4.20
'noLint' declarations
lib/xhtml.l
lib/svg.l
lib/canvas.l
22.4.17
Don't maintain ErrFrames and CtlFrames in coroutines
Fix file descriptor leak when stopping coroutines
src/dec.l
src/flow.l
22.4.11
'trail' check not needed
lib/app.l
22.4.9
Collect also C-tags into @lib/map
src/lib/llvm.l
src/main.l
src/pico.h
src/lib.c
22.4.8
Add "-o lib.bc"
Add "clean2" target
src/Makefile
22.4.6
Optional rounding in 'lat', 'lon' and 'fmt'
lib/gis.l
22.4.5
Check zero charCode in hint key events
lib/form.js
####### 22.3 #######
22.3.16
Pre-set 'home' property in 'form'
Conditionally unlock and enable in 'panel'
lib/form.l
22.3.14
Bug in 'ps'
lib/svg.l
Local and private declarations
lib/xm.l
Escape also backslashes in '<poi>'
lib/gis.l
22.3.13
Escape single quotes in '<poi>' text argument
lib/gis.l
Use 'get' instead of (cdr (asoq ..))
lib/xm.l
22.3.8
Revisit tcsetpgrp() calls
src/dec.l
src/flow.l
lib/debug.l
22.3.4
Plain searches without 'match' overhead
lib/vip.l
22.2.28
Issues with tcsetpgrp() calls
src/io.l
src/flow.l
22.2.26
Transient and private namespaces in catch and coroutine frames
src/glob.l
src/dec.l
src/main.l
src/gc.l
src/flow.l
22.2.24
Refactor 'repl' loops
src/io.l
22.2.23
Don't exit top-level REPL
src/main.l
src/io.l
22.2.22
Print error location in 'repl'
lib/form.l
Print error location in 'evCmd'
lib/vip.l
22.2.21
'height' function
Handle '0' and 'T' directly in 'ps'
lib/svg.l
22.2.19
Handle NILs in (has> . +List)
lib/db.l
Increase stack size
bin/vip
22.2.13
'move!>' method for '+Entity'
lib/too.l
22.2.11
Comment for 'fill'
src/subr.l
22.2.5
Remove 'dbs+'
lib/db.l
doc/ref.html
doc/refD.html
Pass '*Uuid' and arguments to RPC calls
lib/android.l
22.2.2
Revisit (rel> . +Dep)
lib/db.l
22.2.1
Add 'nth' to "see also" of 'get'
doc/refG.html
22.1.30
Additional arguments to 'fish'
src/apply.l
doc/refF.html
test/src/apply.l
lib/too.l
22.1.28
Optional third argument to 'fill'
src/subr.l
doc/refF.html
test/src/subr.l
22.1.27
'wrap' also converts string to list of strings
lib/misc.l
doc/refW.html
test/lib/misc.l
'badDep' function
lib/too.l
22.1.26
Bug in (rel> . +Dep)
lib/db.l
22.1.21
Optional database file for 'forall'
lib/db.l
doc/refF.html
Inherit tags from superclasses
lib/vip.l
Refactor screen handling
lib/term.l
lib/vip.l
22.1.20
'seq' instead of 'dbMap' in 'dangling'
'displaced' function
lib/too.l
22.1.18
Stack check in 'apply'
src/apply.l
Discrete-Event Simulation: 'des', 'pause', 'event' and 'wake' functions
lib/simul.l
22.1.15
'-debug' and '-trace' functions
lib/debug.l
doc/ref.html
doc/refD.html
doc/refT.html
22.1.13
Change "EMail" to "E-Mail"
doc/form/refM.html
22.1.11
Central Kurdish localization (Hunar Omar)
loc/CKB.l
loc/ckb
22.1.10
Variable '*Port'
bin/pty
22.1.8
Handle SIGWINCH
bin/pty
Reset readline in 'setTerm'
lib/term.l
Display namespace in 'repl'
lib/form.l
22.1.7
'refObj' searches also values
lib/too.l
22.1.6
Don't reset 'Busy' in ping()
lib/form.js
22.1.4
Bug in 'name' for external symbols
src/sym.l
####### 21.12 #######
22.1.3
Bugs in (del> . +Entity) and (has> . +List)
lib/db.l
test/lib/db.l
'assoc', 'rassoc', 'asoq' and 'rasoq' accept circular lists
src/subr.l
test/src/subr.l
21.12.30
Enable file transfers (via 'pbPut' and 'pbGet' in PilBox)
bin/pty
21.12.29
Fix touch scrolling in chart tables
lib/form.l
lib/form.js
lib/xhtml/table
21.12.27
'-symbols' function
lib.l
doc/ref.html
doc/refS.html
21.12.22
OpenBSD patch (Frithjof Schulze)
src/httpGate.c
21.12.20
Don't put single "." into readline history
21.12.14
Avoid 'resolveActivity' in 'startActivityForResult'
lib/android.l
21.12.13
Splice also atomic results in "~" read macros and 'fill'
src/io.l
src/subr.l
test/src/subr.l
doc/refF.html
21.12.12
Bug in 'format' (llvm~fmtNum)
src/big.l
Overflow float/double to bignum
src/dec.l
src/main.l
src/pico.h
src/lib.c
21.12.10
'native' and 'struct' not limited to C functions
doc/refN.html
doc/refS.html
'Str' not used in 'getWord'
lib/vip.l
21.12.8
Add 'adr' to "see also" of 'native'
doc/refN.html
21.12.5
Global '*Keys'
":map" command
lib/vip.l
21.12.4
Lock, sync and commit external symbols
lib/vip.l
21.11.30
'R' may be modified in 'evCmd'
lib/vip.l
21.11.29
Extend 'command' with '*CmdMap'
Continue direct editing only with "K" ("^]" always goes to source)
lib/vip.l
21.11.28
Remove '*Complete' filter
lib/vip.l
21.11.26
'all*' function
lib.l
doc/refA.html
Refactor TAB-completion
lib/vip.l
21.11.25
Search namespaces in TAB-completion
lib/vip.l
21.11.22
Minor cosmetics
lib.css
lib/canvas.js
lib/plio.js
lib/gis.js
loc/ar
loc/ch
loc/cn
loc/de
loc/hr
loc/it
loc/ja
loc/tr
21.11.21
Simplify style manipulations
lib/form.l
lib/form.js
21.11.18
Bug in 'bagBag'
lib/form.l
21.11.17
Minor cosmetics
lib/form.l
Inherit 'Dbf' in 'forall' from superclasses
lib/db.l
21.11.16
Re-introduce the '====' function
src/glob.l
src/sym.l
test/src/sym.l
doc/ref_.html
doc/diff
and use it in 'locale'
lib/misc.l
Preserve transients in comma read macro
src/io.l
21.11.15
Use 'fName' in 'vf'
lib/vip.l
21.11.12
'+ObjVar' prefix class
lib/form.l
21.11.11
Missing semicolon (Mia)
lib/form.js
21.11.9
Increase escape delay from 80 to 120
lib/vip.l
21.10.31
Mention Ctrl-D to terminate 'bt', 'query' and '?'
doc/ref.html
doc/refB.html
doc/refM.html
doc/refQ.html
doc/ref_.html
21.10.30
Generalize cut in 'prove'
src/subr.l
21.10.29
rl_initialize() not necessary
src/lib.c
21.10.28
Display namespace in 'status'
lib/vip.l
Minor optimization in '*Prompt'
lib/debug.l
21.10.27
'vf' (vi/find) function
lib/vip.l
Default '*Tab' to 1
lib/xhtml.l
21.10.25
'*KeyMap', '*KeyMap-g' and '*KeyMap-q' globals (Erik Gustafson)
More transients
lib/vip.l
21.10.18
Refactor (gui> . +User)
lib/adm.l
lib/user.l
21.10.15
Mention Ctrl-D to terminate 'more'
doc/refM.html
21.10.11
"CSV" -> "Export CSV" in 'csv'
lib/xhtml.l
21.10.9
'pico~cells' function
lib/vip/draw.l
Minor cosmetics
lib/vip.l
Fix 'arrow' for small distances
lib/vip/draw.l
21.10.2
Remove '+JsField'
lib/form.l
doc/app.html
doc/form/refJ.html
Import 'permute' from 'pico' namespace
lib/simul.l
21.9.29
'+hintObj' prefix class for '+Obj' and '+ObjVal'
lib/form.l
21.9.25
'rand' argument checks
src/big.l
doc/refR.html
21.9.24
Ignore SIGINT in 'ctty' parent process
src/main.l
Forward "^D"
bin/pty
21.9.23
Clear '*Err'
bin/pty
21.9.20
Initial '$StkBrk' and '$StkLimit'
src/glob.l
src/main.l
21.9.19
ulimStk() system call
src/dec.l
src/pico.h
src/lib.c
21.9.17
Clear 'history' after argument evaluation
src/main.l
21.9.16
Insert "^M" before "^J" in 'mail' body
lib/misc.l
'refObj' function
lib/too.l
21.9.13
Insert "^M" before "^J" in 'mail' body
lib/misc.l
'prBase64' optional "^M" argument
lib/misc.l
doc/refP.html
Explanations for reference syntax
doc/ref.html
21.9.10
"gg" uses *Count
lib/vip.l
21.9.3
'mis>' method for '+Swap'
lib/db.l
21.9.1
select() system calls are now poll()
doc/refK.html
doc/refL.html
doc/refR.html
doc/refS.html
doc/refW.html
21.8.30
Typo
doc/refR.html
21.8.28
Add note about 'native'
doc/faq.html
'rid' function
test/src/sym.l
21.8.27
'rid' function
src/glob.l
src/sym.l
test/src/sym.l
doc/ref.html
doc/refC.html
doc/refD.html
doc/refF.html
doc/refQ.html
doc/refR.html
21.8.26
Bug in 'place'
src/subr.l
test/src/subr.l
21.8.25
Division by zero did not throw an error
src/big.l
Private declarations
lib/xhtml.l
21.8.22
Default alert text color black
lib.css
21.8.20
Wrong 'tty' checks for stdin/stdout
src/main.l
src/flow.l
21.8.19
LLC and LINK variables
src/Makefile
21.8.18
Strip binaries
src/Makefile
'rasoq' function
src/glob.l
src/subr.l
test/src/subr.l
doc/ref.html
doc/refA.html
doc/refR.html
21.8.16
Add 'packJson'
lib/json.l
21.8.14
Sort TAB-completion
lib/vip.l
Host option
bin/pty
21.8.13
Check (sys "SHELL") for default shell
lib/vip.l
21.8.12
Some Pilog variables private again
lib/pilog.l
21.8.11
Default shell "bash" -> "sh"
lib/vip.l
Shell prefix "$ " -> "!" in 'repl'
lib/form.l
21.8.9
'go', 'up', 'down', 'left' and 'right functions
'block' function
lib/vip/draw.l
Preset terminal attributes in setRaw()
src/lib.c
21.8.8
Add files
lib/term.l
bin/pty
21.8.7
Clean up terminal handling
lib/vip.l
21.8.6
Define TIOCSWINSZ
src/sysdefs.c
Set standard I/O to a PTY with (ctty)
src/Makefile
src/dec.l
src/main.l
doc/refC.html
21.8.3
'tty' flag also in 'inFile'
src/dec.l
src/main.l
src/io.l
src/flow.l
21.7.27
Direct 'run' in auto-load with "# VIP (...)"
lib/vip.l
21.7.26
Bug in reading non-ASCII characters in internal symbols
src/io.l
21.7.25
'cnt' argument to 'unify'
src/subr.l
lib/pilog.l
doc/refU.html
21.7.24
Signal handler in 'prove'
src/subr.l
21.7.23
Pilog variables not private
lib/pilog.l
Revisit Pilog variables in Lisp expressions
src/subr.l
21.7.22
Revisit private symbols in properties
lib/vip.l
21.7.21
Global '*Rule' cleared in 'repl'
src/glob.l
src/io.l
doc/ref.html
doc/refB.html
doc/refC.html
doc/refR.html
Maintain source properties also in 'clause'
lib/pilog.l
Bind Pilog variables in Lisp expressions
src/subr.l
lib/pilog.l
test/src/subr.l
doc/ref.html
doc/refM.html
doc/refR.html
doc/refT.html
Intern private symbols also in properties
lib/vip.l
Bug in 'putSrc' for first property
src/flow.l
21.7.18
Minor cosmetics
src/subr.l
21.7.16
em120 and em150 styles
lib.css
21.7.13
'buf' function
doc/ref.html
doc/refB.html
21.7.10
Revisit (put> . +Swap)
lib/db.l
test/lib/db.l
21.7.5
Fix 'clone>' for '+Swap' in '+Bag'
lib/db.l
21.7.4
E/R unit tests
lib/test.l
test/src/sym.l
test/src/db.l
test/lib/db.l
Clean up 'has>' methods
lib/db.l
lib/tinymce.l
Revisit '+Bag' and '+Swap'
lib/db.l
21.7.3
Support methods as ":ta msg> +Cls"
lib/vip.l
Make 'bagBag' non-destructive
lib/form.l
21.7.2
'forall' function
doc/ref.html
Add file
doc/rc.sample
21.7.1
'forall' function
lib/db.l
doc/refF.html
####### 21.6 #######
21.6.30
'+Swp' prefix class
lib/form.l
Lazy external symbol creation in '+Swap'
lib/db.l
'has>' check in (rel> . +Joint)
lib/db.l
Keep application namespaces for background tasks in '*Ns'
lib/vip.l
21.6.29
Keep application namespaces for background tasks in '*Ns'
lib/vip.l
bin/vip
21.6.24
Minor addition
doc/microTemplates
21.6.23
Micro-templates for '<table>' and '<grid>'
doc/microTemplates
21.6.22
Micro-templates for '<table>' and '<grid>'
lib/xhtml.l
lib/xhtml/table
lib/xhtml/grid
Add <tr> and </tr>
lib/xhtml/tab
21.6.21
Minor fix in reference for 'all'
doc/refA.html
21.6.20
Micro-templates 2.0
lib/xhtml.l
lib/xhtml/
doc/microTemplates
21.6.19
Wrong 'Attr' output in 'html'
lib/xhtml.l
'pack' not needed
lib/vip.l
General argument to 'any'
src/io.l
doc/refA.html
21.6.18
Also 'flip'ped sort in 'sortButton'
lib/form.l
21.6.17
'sortButton' function
lib/form.l
21.6.16
Vip running in coroutine
Suspend with "qz", resume with (v)
lib/vip.l
doc/refV.html
21.6.15
Fix terminal after 'pipe', 'in' and 'out'
src/io.l
21.6.14
Minor fix indentation
src/flow.l
Restore private declarations
lib/xhtml.l
Missing '+Remote' methods
lib/db.l
21.6.13
Add '\e' to escape markups
src/io.l
doc/ref.html
21.6.11
Optional 'put' and 'get' function arguments for '+Joint'
lib/db.l
21.6.9
Revert confirm row deletion (01may21)
lib/form.l
21.6.4
'ctty' 'NIL' argument is obsolete
src/main.l
doc/refC.html
Minor renaming
src/flow.l
21.6.2
Push tag stack in "gf" command
lib/vip.l
Add A3 page sizes
lib/svg.l
Intern some globals for reload
lib/form.l
21.6.1
'class' clears old method and var definitions
'var' uses 'def' instead of 'put'
lib.l
test/lib.l
21.5.29
Set cooked terminal mode in 'repl'
src/io.l
21.5.27
Revisit TAB-completion
lib/vip.l
Use 'val' for '+Swap' relations in 'set>'
lib/db.l
21.5.25
Revisit TAB-completion from 'history'
lib/vip.l
Unary '+' is obsolete in '*Run' setup
lib.l
21.5.24
Nesting bug in 'cells'
lib/vip/draw.l
21.5.23
Maintain 'symbols' per buffer
lib/vip.l
21.5.21
TAB-complete from 'history' on ": "
":v" command
lib/vip.l
21.5.20
setCooked() only if necessary
src/lib.c
21.5.19
Add file
lib/clang.l
21.5.18
Fix 'struct' example
doc/refS.html
21.5.14
'<grid>' vertical-aligns to top
lib.css
Optional submenu CSS class index
lib/xhtml.l
lib/xhtml/menu
21.5.12
Add file
doc/microTemplates
Needs '*XhtmlField' in '<field>'
lib/xhtml.l
21.5.11
Don't set IPV6_V6ONLY for OpenBSD
lib/net.l
21.5.10
64-bit check not needed
lib/adm.l
21.5.6
Missing '+Remote' methods
lib/db.l
Missing 'mail' handshake (Mike Pechkin)
lib/misc.l
21.5.5
Fix catch/throw between coroutines
src/dec.l
src/main.l
src/flow.l
doc/structures
doc/ref.html
21.5.4
I/O save/restore bug in 'co' / 'yield'
src/main.l
src/flow.l
Minor cosmetics (collapse two 'let's)
src/flow.l
Fix docs and comments about coroutine tags
src/main.l
src/flow.l
doc/ref.html
doc/refC.html
doc/refS.html
doc/refY.html
21.5.3
(co) returns tag of current coroutine
src/flow.l
doc/refC.html
'shift' function
src/glob.l
src/sym.l
doc/ref.html
doc/refS.html
doc/refP.html
test/src/sym.l
21.5.1
Confirm row deletion also if repeated
lib/form.l
21.4.30
Add file
doc/app.html
21.4.29
Call 'loadCoEnv' in 'unwind'
src/main.l
src/flow.l
Remove coroutines from catch/throw environment
src/glob.l
21.4.22
Show thousands-separator in total counts in search dialogs
lib/form.l
21.4.21
File in first column of directory listings
lib/vip.l
21.4.20
Bug in 'till' reading UTF-8
src/io.l
21.4.19
Align SUBRs to 8 bytes
src/lib/llvm.l
21.4.18
's-expr' function, evaluate with "^E"
lib/vip.l
21.4.17
'stack' return value fix
src/main.l
doc/refS.html
Infinite timeout for values greater than 24 days in '*Run', 'wait' and 'key'
on non-Linux systems (using ppoll(2) on Linux)
src/lib.c
'stack' continued
src/main.l
21.4.16
Independent size of main stack segment
src/glob.l
src/main.l
src/flow.l
doc/refS.html
'stack' returns unused spaces
src/main.l
doc/refS.html
'llvm~cons2' function
src/dec.l
src/gc.l
Coroutine structure 'prv'
doc/structures
Optional alignment for 'memcpy' and 'memset'
src/lib/llvm.l
src/main.l
src/db.l
src/flow.l
21.4.15
Infinite timeout for values greater than 24 days in '*Run', 'wait' and 'key'
(only on systems with sizeof(int) == 4)
src/lib.c
21.4.14
Skip remote replication if 'key' is empty
src/ssl.c
21.4.13
Bug in '<table>': Header text not evaluated
lib/xhtml.l
ContextCompat 'permit' function
lib/android.l
'Str' in 'repl' private
lib/form.l
21.4.10
Minor fix indentation
lib/vip.l
21.4.9
Extensions to 'NIL' punning
doc/ref.html
21.4.8
Support '-fun' command line arguments
bin/vip
21.4.7
'enum?' function
src/glob.l
src/sym.l
doc/ref.html
doc/refE.html
doc/refL.html
test/src/sym.l
21.4.4
Wrong external declaration
src/ht.l
21.4.3
Bug in 'stem' (for -O2 or -O3)
src/subr.l
21.4.1
'enum' returns cell instead of value
src/sym.l
doc/refE.html
test/src/sym.l
doc/faq.html
Bug in '*Term' signal handling
src/main.l
21.3.31
'+Remote' entity class
lib/db.l
lib/too.l
21.3.30
Exit '*', '/*', '/' and '%' upon zero
src/big.l
21.3.29
Note about the default browser for 'doc' calls
man/man1/picolisp.1
doc/man.html
21.3.26
'enum' with single argument returns association list
src/sym.l
doc/refE.html
test/src/sym.l
21.3.25
Return 'NIL' from 'enum' if key <= 0
src/sym.l
Unit tests for 'enum'
test/src/sym.l
'*Term' signal handling (Constantine Bitensky)
src/glob.l
src/main.l
doc/ref.html
doc/refT.html
doc/refA.html
doc/refH.html
doc/refS.html
doc/refW.html
21.3.24
'enum' function
src/sym.l
21.3.23
'enum' function
src/glob.l
src/sym.l
doc/ref.html
doc/refE.html
doc/refH.html
doc/refI.html
'rev' function bit count argument
src/big.l
doc/refR.html
21.3.21
'rev' function
src/glob.l
src/big.l
doc/ref.html
doc/refR.html
doc/refH.html
doc/refI.html
doc/ref_.html
21.3.17
Still missing
lib/xm.l
Ukrainian and russian localization (Constantine Bitensky)
loc/RU.l
loc/uk
loc/ru
21.3.10
Renamed "UK.l" to "UA.l", restored "UK.l" and renamed to "GB.l"
Renamed "gr" to "el" and "jp" to "ja"
loc/UA.l
loc/GB.l
loc/uk
Symbolic links
UK.l -> GB.l
gr -> el
jp -> ja
21.3.8
Missing file
lib/xm.l
21.3.7
Ukrainian localization (Constantine Bitensky)
loc/UK.l
loc/uk
21.3.5
Subdirectory recursion buffer-local
Recurse when no trailing "/"
lib/vip.l
21.3.2
'*Bye' cleared in children
src/io.l
lib.l
lib/adm.l
lib/app.l
doc/diff
21.2.28
Missing check for 'NIL'
lib/vip.l
21.2.26
Remove Access-Control-Allow-Origin header
lib/http.l
21.2.20
Prefix "@" with "./" in directory listings
Recurse into subdirectories with ":E"
lib/vip.l
21.2.16
Case insensitive search with "~" prefix
Increase escape delay to 80 ms
lib/vip.l
21.2.12
Rename file to "area", add "field"
lib/xhtml.l
lib/xhtml/area
lib/xhtml/field
21.2.11
Elaborate '<area>'
lib/xhtml.l
lib/xhtml/textarea
21.2.9
Ignore SIGHUP for non-config calls
src/httpGate.c
21.2.8
Start task in first 'heartbeat' call
lib/heartbeat.l
Touch events not needed
lib/xhtml/tab
21.2.7
Variable titles in menu
Layout template line format
lib/xhtml.l
lib/xhtml/menu
lib/xhtml/layout
21.2.5
'plio' must preserve $Ptr and $End
src/io.l
Load @lib/too.l always in 'psh'
lib/http.l
21.2.3
Load @lib/sq.l in 'psh'
lib/http.l
21.2.2
Optional insert string in config keys
src/httpGate.c
doc/httpGate.html
21.2.1
Typo ".pil" -> "./pil"
doc/httpGate.html
21.1.28
Typo "none" -> "nond"
doc/tut.html
21.1.25
Remove 'evCmd' from custom function keys
lib/vip.l
21.1.23
'fish' function "skip" return value
src/apply.l
doc/refF.html
lib/vip.l
21.1.22
em80, em90 and em100 styles
lib.css
21.1.21
Stack check in 'fish'
src/apply.l
21.1.20
Comment
lib/tinymce.l
21.1.18
Bug in 'pack' of external symbol names
src/sym.l
21.1.17
'pil' backport
lib/compat.l
21.1.15
Micro-templates
lib/xhtml.l
lib/xhtml/
Bug in 'pass'
src/apply.l
Call 'bufString' instead of 'pathString' in 'token'
src/io.l
21.1.14
Bug in 'bit?'
src/big.l
21.1.8
Minor cosmetics
src/subr.l
Improved terminal reset
src/lib.c
21.1.5
Debian release
Dec20
Pil21 initial version
####### 21.0 #######
================================================
FILE: doc/Tracks
================================================
# VIP @lib/vip/draw.l
# 25may23 Software Lab. Alexander Burger
(label 1 1 "Connectors:")
(cells 7 6 '(| | | . |))
(go 1 3 "-")
(right 9 "+")
(down 2 "v")
(go 10 8 "+")
(down 8 "v")
(go 28 6 "+")
(up 3 "+")
(right 14 ">")
(go 46 6 "+")
(up 3 "+")
(right 30 ">")
(box 7 17 13 6 "Track"
(label 1 1 "- a")
(label 10 1 "b -")
(label 2 5 "x")
(label 11 5 "y") )
(go 7 18 "+")
(left 4 "+")
(up 11 "+")
(right 3 ">")
(go 20 18 "+")
(right 4 ">")
(cells 25 17 '(| | | . |))
(go 28 17 "+")
(up 3 "+")
(left 11 "+")
(down 2 "v")
(go 76 22 "-")
(left 48 "+")
(up 2 "\^")
(go 46 19 "+")
(down 6 "+")
(left 45 "<")
(go 64 19 "+")
(down 6 "+")
(left 14 "<")
(go 70 17 "+")
(up 6 "+")
(left 58 "+")
(up 2 "\^")
(go 52 8 "+")
(down 6 "+")
(left 22 "+")
(down 2 "v")
================================================
FILE: doc/des.html
================================================
<!--
# VIP @lib/vip/html.l
# 29jul25 Software Lab. Alexander Burger
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Discrete-Event Simulation</title>
<link rel="stylesheet" href="doc.css" type="text/css">
</head>
<body>
<a href="mailto:abu@software-lab.de">abu@software-lab.de</a>
<h1>Discrete-Event Simulation (DES)</h1>
<p style="text-align: right">(c) Software Lab. Alexander Burger
<p>PicoLisp has a <a
href="http://en.wikipedia.org/wiki/Discrete-event_simulation">Discrete-Event
Simulation</a> library in <code>"@lib/simul.l"</code>.
<p><ul>
<li><a href="#impl">Implementation</a>
<li><a href="#glob">Global Variables</a>
<li><a href="#fun">Functions</a>
<li><a href="#use">Usage</a>
<li><a href="#xmpl">An Example</a>
</ul>
<p><hr>
<h2><a id="impl">Implementation</a></h2>
<p>The simulated objects (often called "Agents") are implemented as separate <a
href="http://software-lab.de/doc/ref.html#coroutines">coroutines</a>. These are
created the normal way with <a
href="http://software-lab.de/doc/refC.html#co">co</a>, and the library functions
use <a href="http://software-lab.de/doc/refY.html#yield">yield</a> to transfer
control between them.
<p>Only one coroutine may be running at one point in time. All others are either
<p><ul>
<li>ready to run,
<li>waiting for the next scheduled point in time, and/or
<li>waiting for one or several specific signals (events).
</ul>
<p>A running coroutine can suspend itself, and cause another coroutine to
resume, by either
<p><ul>
<li>passing control to the next coroutine, or
<li>pausing for a given amount of time and/or waiting for signals.
</ul>
<p>The simulation can optionally run in realtime mode. In that case, it sleeps
between the scheduled points in time, and accepts key strokes for user
interaction.
<p>The library consists of five global variables and four functions.
<p><hr>
<h2><a id="glob">Global Variables</a></h2>
<dl>
<dt><code>*Time</code></dt>
<dd>Simulated system time since the start of the simulation. It can be in any
unit, but should be in milliseconds if in realtime mode.</dd>
<dt><code>*Ready</code></dt>
<dd>Queue of coroutines ready to run.</dd>
<dt><code>*Next</code></dt>
<dd><a href="http://software-lab.de/doc/refI.html#idx">idx</a> tree of
coroutines pausing for a given time.</dd>
<dt><code>*Rt</code></dt>
<dd>Realtime: Either <code>NIL</code> (default), or 1 for wall clock speed, 2
for double speed etc.</dd>
<dt><code>*Keys</code></dt>
<dd>Holds possibly queued key presses (only in realtime mode).</dd>
</dl>
<p><hr>
<h2><a id="fun">Functions</a></h2>
<dl>
<dt><code>(des [. prg])</code></dt>
<dd>Performs one discrete-event simulation step. It first runs all coroutines in
<code>*Ready</code> until that queue is empty. Then - if <code>*Next</code> is
not empty - advances the simulation to the next point in time, and resumes all
corresponding coroutines. In that case, if in realtime mode, it delays execution
as necessary, handles possible key presses, and runs <code>prg</code> after each
key.</dd>
<dt><code>(pause ['cnt|sym] ..) -> any</code></dt>
<dd>Waits for events (i.e. a time span elapsed or a signal arrived). For a
numeric argument, the current coroutine is scheduled in <code>*Next</code> for a
point in time after that number of time units. For symbolic arguments, the
current coroutine is queued into those symbol's event queues. In any case,
control is passed to the next coroutine.</dd>
<dt><code>(event 'sym 'exe)</code></dt>
<dd>Sends the signal <code>sym</code> to all coroutines waiting in that symbol's
event queue. As a result, these coroutines are removed from the queue and
appended to the <code>*Ready</code> queue, with the optional <code>exe</code> to
be evaluated when resumed. The current coroutine continues to run.</dd>
<dt><code>(wake 'sym 'exe)</code></dt>
<dd>Wakes up another coroutine <code>sym</code>, by appending it to the
<code>*Ready</code> queue with the optional 'exe' to be evaluated when resumed.
This means that if <code>sym</code> is currently waiting for a point in time in
<code>*Next</code>, it is removed from that index (i.e. the pause is aborted).
Also, if <code>sym</code> is waiting for signals, it is removed from those event
queues. The current coroutine continues to run.</dd>
</dl>
<p><hr>
<h2><a id="use">Usage</a></h2>
<p>A typical DES program will start some coroutines and let them perform their
initial work until they need to pause.
<p>That means, if a given operation in the simulation is supposed to take
<code>cnt</code> time units, this coroutine calls <code>pause</code> with that
number. Or, if it depends on some signals from another part of the program, it
may call <code>pause</code> with those symbols. In any case - as it has nothing
else to do - it goes to sleep.
<p>When all of them wait for a time or signal, control is returned to the main
program. All coroutines are now waiting in <code>*Next</code> or some signal
event queue (or in <code>*Ready</code> if they just gave up control with
<code>(pause)</code>).
<p>The main program may now check <code>*Next</code> and perhaps
<code>*Ready</code>. If both are empty, no further events can occur, and the
program may terminate.
<p>Otherwise, it calls <code>des</code> to continue with the next step(s).
<p>At any time, a coroutine or the main program may call <code>wake</code>, for
example to interrupt another coroutine and cause it to <a
href="http://software-lab.de/doc/refT.html#throw">throw</a> into some other
context, or have that coroutine's <code>pause</code> return a special value by
evaluating the <code>exe</code> argument.
<p><hr>
<h2><a id="xmpl">An Example</a></h2>
<p>Let's use DES to demonstrate the well-known <a
href="http://en.wikipedia.org/wiki/Dining_philosophers_problem">Dining
Philosophers Problem</a>.
<p> Put the following code into a file "dining.l".
<hr>
<pre>
# 07sep23 Software Lab. Alexander Burger
# Dining Philosophers
# pil dining.l -dining~main +
(load "@lib/simul.l")
(symbols 'dining 'simul 'pico)
(local) (*ForkA *ForkB *ForkC *ForkD *ForkE now think)
(de now (Str)
(prinl (tim$ (* 60 *Time)) " " (co) " " Str) )
(de think (Left Right)
(loop
(now "thinking")
(pause (rand 180 240)) # 3 to 4 hours
(now "hungry")
(while (or (val Left) (val Right))
(now "waiting")
(pause Left Right) )
(set Left (set Right (co)))
(now "eating")
(pause 20) # 20 minutes
(set Left (set Right NIL))
(event Left)
(event Right) ) )
(local) main
(de main ()
(symbols '(dining simul pico))
(co 'Aristotle
(think '*ForkA '*ForkB) )
(co 'Kant
(think '*ForkB '*ForkC) )
(co 'Spinoza
(think '*ForkC '*ForkD) )
(co 'Marx
(think '*ForkD '*ForkE) )
(co 'Russell
(think '*ForkE '*ForkA) ) )
</pre>
<hr>
<p>It uses five global variables <code>*ForkA</code> through <code>*ForkE</code>
and five coroutines <code>Aristotle</code>, <code>Kant</code>,
<code>Spinoza</code>, <code>Marx</code> and <code>Russell</code>. They all run
the same function <code>think</code>, with their neighboring forks as
<code>Left</code> and <code>Right</code> arguments.
<p>In <code>think</code>, each philospher is first "thinking" for a random time
between three and four hours. Then it gets "hungry", tries to pick up both
forks, and - if at least one of the forks is in use - starts "waiting" for a
left or right fork signal from another philosopher, and checks the forks again.
<p>Now both forks are free. The philosopher puts himself into both (it could put
in fact any non-<code>NIL</code> value), then is "eating" for 20 minutes,
releases both forks by setting them to <code>NIL</code>, and sends a left and a
right fork signal to the neighboring philosophers possibly waiting for the
forks.
<p>The simulation cannot deadlock, because both forks are picked up and released
atomically, and because coroutines waiting for fork signals are always queued
after the other waiting coroutines.
<h2>Sample Run</h2>
<pre>
$ ./pil misc/dining.l -dining~main +
00:00 Aristotle thinking
00:00 Kant thinking
00:00 Spinoza thinking
00:00 Marx thinking
00:00 Russell thinking
dining: (more (stack))
(Russell . 62)
(Marx . 62)
(Spinoza . 62)
(Kant . 62)
(Aristotle . 62)
(T . 155)
-> NIL
dining: *Ready
-> NIL
dining: (idx '*Next)
-> ((180 . Aristotle) (194 . Marx) (198 . Russell) (201 . Spinoza) (229 . Kant))
dining: (des)
03:00 Aristotle hungry
03:00 Aristotle eating
-> NIL
dining: (des)
03:14 Marx hungry
03:14 Marx eating
-> NIL
dining: (des)
03:18 Russell hungry
03:18 Russell waiting
-> NIL
dining: (do 10 (des))
03:20 Aristotle thinking
03:20 Russell waiting
03:21 Spinoza hungry
03:21 Spinoza waiting
03:34 Marx thinking
03:34 Spinoza eating
03:34 Russell eating
03:49 Kant hungry
03:49 Kant waiting
03:54 Russell thinking
03:54 Spinoza thinking
03:54 Kant eating
04:14 Kant thinking
06:27 Aristotle hungry
06:27 Aristotle eating
06:47 Aristotle thinking
06:47 Marx hungry
06:47 Marx eating
07:07 Marx thinking
07:40 Russell hungry
07:40 Russell eating
-> NIL
dining:
</pre>
</body>
</html>
================================================
FILE: doc/doc.css
================================================
/* 22oct23 Software Lab. Alexander Burger
* 06dec12jk
*/
html {
background-color: #ddd;
}
body {
margin: auto;
max-width: 50em;
border: 1px solid #bbb;
background-color: white;
padding: 2em 7% 4em 10%;
}
h5 {
font-size: 95%;
margin-bottom: 1em;
}
dt {
margin: 0.4em -2em 0 0;
font-weight: 600;
color: #444;
}
dd {
margin-top: 0.3em;
margin-bottom: 0.4em;
}
code, pre {
color: rgb(0%,40%,0%);
}
dt code {
word-spacing: -0.04em;
}
================================================
FILE: doc/faq.html
================================================
<!--
# VIP @lib/vip/html.l
# 08may24 Software Lab. Alexander Burger
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PicoLisp FAQ</title>
<link rel="stylesheet" href="doc.css" type="text/css">
</head>
<body>
<a href="mailto:abu@software-lab.de">abu@software-lab.de</a>
<p style="text-align: right">
<i>Monk: "If I have nothing in my mind, what shall I do?"</i><br>
<i>Joshu: "Throw it out."</i><br>
<i>Monk: "But if there is nothing, how can I throw it out?"</i><br>
<i>Joshu: "Well, then carry it out."</i><br>
<i>(Zen koan)</i><br>
<h1>PicoLisp Frequently Asked Questions</h1>
<p style="text-align: right">(c) Software Lab. Alexander Burger
<p><ul>
<li><a href="#yet">Why did you write yet another Lisp?</a>
<li><a href="#who">Who can use PicoLisp?</a>
<li><a href="#advantages">What are the advantages over other Lisp systems?</a>
<li><a href="#performance">How is the performance compared to other Lisp systems?</a>
<li><a href="#interpreted">What does "interpreted" mean?</a>
<li><a href="#compiler">Is there (or will be in the future) a compiler available?</a>
<li><a href="#portable">Is it portable?</a>
<li><a href="#webServer">Is PicoLisp a web server?</a>
<li><a href="#lambda">I cannot find the LAMBDA keyword in PicoLisp</a>
<li><a href="#dynamic">Why do you use dynamic variable binding?</a>
<li><a href="#problems">Are there no problems caused by dynamic binding?</a>
<li><a href="#closures">But with dynamic binding I cannot implement closures!</a>
<li><a href="#macros">Do you have macros?</a>
<li><a href="#threads">Can I run threads?</a>
<li><a href="#strings">Why are there no strings?</a>
<li><a href="#arrays">What about arrays?</a>
<li><a href="#floats">How to do floating point arithmetic?</a>
<li><a href="#bind">What happens when I locally bind a symbol which has a function definition?</a>
<li><a href="#hardware">Would it make sense to build PicoLisp in hardware?</a>
<li><a href="#segfault">I get a segfault if I ...</a>
<li><a href="#ask">Where can I ask questions?</a>
</ul>
<p><hr>
<h2><a id="yet">Why did you write yet another Lisp?</a></h2>
<p>Because other Lisps are not the way I'd like them to be. They concentrate on
efficient compilation, and lost the one-to-one relationship of language and
virtual machine of an interpreted system, gave up power and flexibility, and
impose unnecessary limitations on the freedom of the programmer. Other reasons
are the case-insensitivity and complexity of current Lisp systems.
<p><hr>
<h2><a id="who">Who can use PicoLisp?</a></h2>
<p>PicoLisp is for programmers who want to control their programming
environment, at all levels, from the application domain down to the bare metal,
who want to use a transparent and simple - yet universal - programming model,
and who want to know exactly what is going on.
<p>It does <i>not</i> pretend to be easy to learn. There are already plenty of
languages that do so. It is not for people who don't care what's under the hood,
who just want to get their application running. They are better served with some
standard, "safe" black-box, which may be easier to learn, and which allegedly
better protects them from their own mistakes.
<p><hr>
<h2><a id="advantages">What are the advantages over other Lisp systems?</a></h2>
<h3>Simplicity</h3>
<p>PicoLisp is easy to understand and adapt. There is no compiler enforcing
special rules, and the interpreter is simple and straightforward. There are only
three data types: Numbers, symbols and lists ("LISP" means "List-, Integer- and
Symbol Processing" after all ;-). The memory footprint is minimal, and the
tarball size of the whole system is just a few hundred kilobytes.
<h3>A Clear Model</h3>
<p>Most other systems define the language, and leave it up to the implementation
to follow the specifications. Therefore, language designers try to be as
abstract and general as possible, leaving many questions and ambiguities to the
users of the language.
<p>PicoLisp does the opposite. Initially, only the single-cell data structure
was defined, and then the structure of numbers, symbols and lists as they are
composed of these cells. Everything else in the whole system follows from these
axioms. This is documented in the chapter about <a href="ref.html#vm">The
PicoLisp Machine</a> in the reference manual.
<h3>Orthogonality</h3>
<p>There is only one symbolic data type, no distinction (confusion) between
symbols, strings, variables, special variables and identifiers.
<p>Most data-manipulation functions operate on the values of symbols as well as
the CARs of cons pairs:
<pre>
: (let (N 7 L (7 7 7)) (inc 'N) (inc (cdr L)) (cons N L))
-> (8 7 8 7)
</pre>
<p>There is only a single functional type, no "special forms". As there is no
compiler, functions can be used instead of macros. No special "syntax"
constructs are needed. This allows a completely orthogonal use of functions. For
example, most other Lisps do not allow calls like
<pre>
: (mapcar if '(T NIL T NIL) (1 2 3 4) (5 6 7 8))
-> (1 6 3 8)
</pre>
<p>PicoLisp has no such restrictions. It favors the principle of "Least
Astonishment".
<h3>Object System</h3>
<p>The OOP system is very powerful, because it is fully dynamic, yet extremely
simple:
<p><ul>
<li>In other systems you have to statically declare "slots". In PicoLisp,
classes and objects are completely dynamic, they are created and extended at
runtime. "Slots" don't even exist at creation time. They spring into existence
purely dynamically. You can add any new property or any new method to any single
object, at any time, regardless of its class.
<li>The multiple inheritance is such that not only classes can have several
superclasses, but each individual object can be of more than one class.
<li>Prefix classes can surgically change the inheritance tree for any class or
object. They behave like Mixins in this regard.
<li>Fine-control of inheritance in methods with <code><a
href="refS.html#super">super</a></code> and <code><a
href="refE.html#extra">extra</a></code>.
</ul>
<h3>Pragmatism</h3>
<p>PicoLisp has many practical features not found in other Lisp dialects. Among
them are:
<p><ul>
<li>Auto-quoting of lists when the CAR is a number. Instead of <code>'(1 2
3)</code> you can just write <code>(1 2 3)</code>. This is possible because a
number never makes sense as a function name, and has to be checked at runtime
anyway.
<li>The <code><a href="refQ.html#quote">quote</a></code> function returns all
unevaluated arguments, instead of just the first one. This is both faster
(<code>quote</code> does not have to take the CAR of its argument list) and
smaller (a single cell instead of two). For example, <code>'A</code> expands to
<code>(quote . A)</code> and <code>'(A B C)</code> expands to <code>(quote A B
C)</code>.
<li>The symbol <code><a href="ref.html#atres">@</a></code> is automatically
maintained as a local variable, and set implicitly in certain flow- and
logic-functions. This makes it often unnecessary to allocate and assign local
variables.
<li><a href="tut.html#funio">Functional I/O</a> is more convenient than
explicitly passing around file descriptors.
<li>A well-defined <a href="ref.html#cmp">ordinal relationship</a> between
arbitrary data types facilitates generalized comparing and sorting.
<li>Uniform handling of <code>var</code> locations (i.e. values of symbols and
CARs of cons pairs).
<li>The universality and usefulness of symbol properties is enforced and
extended with implicit and explicit bindings of the symbol <code><a
href="refT.html#This">This</a></code> in combination with the access functions
<code><a href="ref_.html#=:">=:</a></code>, <code><a
href="ref_.html#:">:</a></code> and <code><a href="ref_.html#::">::</a></code>.
<li>A very convenient list-building machinery, using the <code><a
href="refL.html#link">link</a></code>, <code><a
href="refY.html#yoke">yoke</a></code>, <code><a
href="refC.html#chain">chain</a></code> and <code><a
href="refM.html#made">made</a></code> functions in the <code><a
href="refM.html#make">make</a></code> environment.
<li>The syntax of often-used functions is kept non-verbose. For example, instead
of <code>(let ((A 1) (B 2) C 3) ..)</code> you write <code>(let (A 1 B 2 C 3)
..)</code>, or just <code>(let A 1 ..)</code> if there is only a single
variable.
<li>The use of the hash (<code>#</code>) as a comment character is more appropriate
today, and allows a clean hash-bang (<code>#!</code>) syntax for stand-alone
scripts.
<li>The interpreter is <a href="ref.html#invoc">invoked</a> with a simple and
flexible syntax, where command line arguments are either files to be interpreted
or functions to be directly executed. With that, many tasks can be performed
without writing a separate <a href="tut.html#script">script</a>.
<li>A sophisticated system of interprocess communication, file locking and
synchronization allows multi-user access to database applications.
<li>A general and dynamic interface for <a href="native.html">Native C Calls</a>
(FFI).
<li>A Prolog interpreter is tightly integrated into the language. Prolog
clauses can call Lisp expressions and vice versa, and a self-adjusting
depth-first search predicate <code>select</code> can be used in database
queries.
</ul>
<h3>Persistent Symbols</h3>
<p>Database objects ("external" symbols) are a primary data type in PicoLisp.
They look like normal symbols to the programmer, but are managed in the database
(fetched from, and stored to) automatically by the system. Symbol manipulation
functions like <code>set</code>, <code>put</code> or <code>get</code>, the
garbage collector, and other parts of the interpreter know about them.
<h3>Application Server</h3>
<p>It is a stand-alone system (it does not depend on external programs like
Apache or MySQL) and it provides a "live" user interface on the client side,
with an application server session for each connected client. The GUI layout and
behavior are described with S-expressions, generated dynamically at runtime, and
interact directly with the database structures.
<h3>Localization</h3>
<p>Internal exclusive and full use of UTF-8 encoding, and self-translating <a
href="ref.html#transient-io">transient symbols</a> (strings), make it easy to
write country- and language-independent applications.
<p><hr>
<h2><a id="performance">How is the performance compared to other Lisp systems?</a></h2>
<p>Despite the fact that PicoLisp is an interpreted-only system, the performance
is quite good. Typical Lisp programs operating on list data structures are
executed in (interpreted) PicoLisp at about the same speed as in (compiled)
CMUCL, and about two or three times faster than in CLisp or Scheme48.
<p>But in practice, speed was never a problem, even with the first versions of
PicoLisp in 1988 on a Mac II with a 12 MHz CPU. And certain things are cleaner
and easier to do in <code>C</code> (or other low-level languages) anyway. It is
very easy to write <code>C</code> functions in PicoLisp, either in the kernel,
as shared object libraries, or even inline in the Lisp code.
<p>PicoLisp is very space-efficient. Other Lisp systems reserve heap space twice
as much as needed, or use rather large internal structures to store cells and
symbols. Each cell or minimal symbol in PicoLisp consists of only two pointers.
No additional tags are stored, because they are implied in the pointer
encodings. No gaps remain in the heap during allocation, as there are only
objects of a single size. As a result, consing and garbage collection are very
fast, and overall performance benefits from a better cache efficiency. Heap and
stack grow automatically, and are limited only by hardware and operating system
constraints.
<p><hr>
<h2><a id="interpreted">What does "interpreted" mean?</a></h2>
<p>It means to directly execute Lisp data as program code. No transformation to
another representation of the code (e.g. compilation), and no structural
modifications of these data, takes place.
<p>Lisp data are the "real" things, like numbers, symbols and lists, which can
be directly handled by the system. They are <i>not</i> the textual
representation of these structures (which is outside the Lisp realm and taken
care of by the <code><a href="refR.html#read">read</a></code>ing and <code><a
href="refP.html#print">print</a></code>ing functions).
<p>The following example builds a function and immediately calls it with two
arguments:
<pre>
: ((list (list 'X 'Y) (list '* 'X 'Y)) 3 4)
-> 12
</pre>
<p>Note that no time is wasted to build up a lexical environment. Variable
bindings take place dynamically during interpretation.
<p>A PicoLisp function is able to inspect or modify itself while it is running
(though this is rarely done in application programming). The following function
modifies itself by incrementing the '0' in its body:
<pre>
(de incMe ()
(do 8
(printsp 0)
(inc (cdadr (cdadr incMe))) ) )
: (incMe)
0 1 2 3 4 5 6 7 -> 8
: (incMe)
8 9 10 11 12 13 14 15 -> 16
</pre>
<p>Only an interpreted Lisp can fully support such "Equivalence of Code and
Data". If executable pieces of data are used frequently, like in PicoLisp's
dynamically generated GUI, a fast interpreter is preferable over any compiler.
<p><hr>
<h2><a id="compiler">Is there (or will be in the future) a compiler available?</a></h2>
<p>No. That would contradict the idea of PicoLisp's simple virtual machine
structure. A compiler transforms it to another (physical) machine, with the
result that many assumptions about the machine's behavior won't hold any more.
Besides that, PicoLisp primitive functions evaluate their arguments
independently and are not suited for being called from compiled code. Finally,
the gain in execution speed would probably not be worth the effort. Typical
PicoLisp applications often use single-pass code which is loaded, executed and
thrown away; a process that would be considerably slowed down by compilation.
<p><hr>
<h2><a id="portable">Is it portable?</a></h2>
<p>Yes and No. Though we wrote and tested PicoLisp originally only on Linux, it
now also runs on many other POSIX systems. The first versions were even fully
portable between DOS, SCO-Unix and Macintosh systems. But today we have Linux.
Linux itself is very portable, and you can get access to a Linux system almost
everywhere. So why bother?
<p>The GUI is completely platform independent (Browser), and in the age of the
Internet an application <u>server</u> does not really need to be portable.
<p><hr>
<h2><a id="webServer">Is PicoLisp a web server?</a></h2>
<p>Not really, but it evolved a great deal into that direction.
<p>Historically it was the other way round: We had a plain X11 GUI for our
applications, and needed something platform independent. The solution was
obvious: Browsers are installed virtually everywhere. So we developed a protocol
which persuades a browser to function as a GUI front-end to our applications.
This is much simpler than to develop a full-blown web server.
<p><hr>
<h2><a id="lambda">I cannot find the LAMBDA keyword in PicoLisp</a></h2>
<p>Because it isn't there. The reason is that it is redundant; it is equivalent
to the <code>quote</code> function in any aspect, because there's no distinction
between code and data in PicoLisp, and <code>quote</code> returns the whole
(unevaluated) argument list. If you insist on it, you can define your own
<code>lambda</code>:
<pre>
: (def 'lambda quote)
-> lambda
: ((lambda (X Y) (+ X Y)) 3 4)
-> 7
: (mapcar (lambda (X) (+ 1 X)) (1 2 3 4 5))
-> (2 3 4 5 6)
</pre>
<p><hr>
<h2><a id="dynamic">Why do you use dynamic variable binding?</a></h2>
<p>Dynamic binding is very powerful, because there is only one single,
dynamically changing environment active all the time. This makes it possible
(e.g. for program snippets, interspersed with application data and/or passed
over the network) to access the whole application context, freely, yet in a
dynamically controlled manner. And (shallow) dynamic binding is the fastest
method for a Lisp interpreter.
<p>Lexical binding is more limited by definition, because each environment is
deliberately restricted to the visible (textual) static scope within its
establishing form. Therefore, most Lisps with lexical binding introduce "special
variables" to support dynamic binding as well, and constructs like
<code>labels</code> to extend the scope of variables beyond a single function.
<p>In PicoLisp, function definitions are normal symbol values. They can be
dynamically rebound like other variables. As a useful real-world example, take
this little gem:
<pre>
(de recur recurse
(run (cdr recurse)) )
</pre>
<p>It implements anonymous recursion, by defining <code>recur</code> statically
and <code>recurse</code> dynamically. Usually it is very cumbersome to think up
a name for a function (like the following one) which is used only in a single
place. But with <code>recur</code> and <code>recurse</code> you can simply
write:
<pre>
: (mapcar
'((N)
(recur (N)
(if (=0 N)
1
(* N (recurse (- N 1))) ) ) )
(1 2 3 4 5 6 7 8) )
-> (1 2 6 24 120 720 5040 40320)
</pre>
<p>Needless to say, the call to <code>recurse</code> does not have to reside in
the same function as the corresponding <code>recur</code>. Can you implement
anonymous recursion so elegantly with lexical binding?
<p><hr>
<h2><a id="problems">Are there no problems caused by dynamic binding?</a></h2>
<p>You mean the <i>funarg</i> problem, or problems that arise when a variable
might be bound to <i>itself</i>? For that reason we have a convention in
PicoLisp to use <a href="ref.html#transient-io">transient symbols</a> (instead
of internal symbols) or <a href="refP.html#private">private</a> internal symbols
<ol>
<li>for all parameters and locals, when functional arguments or executable lists
are passed through the current dynamic bindings
<li>for a parameter or local, when that symbol might possibly be (directly or
indirectly) bound to itself, and the bound symbol's value is accessed in the
dynamic context.
</ol>
<p>This is a form of lexical <i>scoping</i> - though we still have dynamic
<i>binding</i> - of symbols, similar to the <code>static</code> keyword in
<code>C</code>.
<p>In fact, these problems are a real threat, and may lead to mysterious bugs
(other Lisps have similar problems, e.g. with symbol capture in macros). They
can be avoided, however, when the above conventions are observed. As an example,
consider a function which doubles the value in a variable:
<pre>
(de double (Var)
(set Var (* 2 (val Var))) )
</pre>
<p>This works fine, as long as we call it as <code>(double 'X)</code>, but will
break if we call it as <code>(double 'Var)</code>. Therefore, the correct
implementation of <code>double</code> should be:
<pre>
(de double ("Var")
(set "Var" (* 2 (val "Var"))) )
</pre>
<p>If <code>double</code> is defined that way in a separate source file, then
the symbol <code><u>Var</u></code> is locked into a private lexical context and
cannot conflict with other symbols.
<p>Admittedly, there are two disadvantages with this solution:
<ol>
<li>The rules for when to use transient or private symbols are a bit
complicated. Though it is safe to use them even when not necessary, it will take
more space then and be more difficult to debug.
<li>The string-like syntax of transient symbols as variables may look strange to
alumni of other languages. With private symbols this is not an issue.
</ol>
Fortunately, these pitfalls do not occur so very often, and seem more likely in
utilities than in production code, so that they can be easily encapsulated.
<p><hr>
<h2><a id="closures">But with dynamic binding I cannot implement closures!</a></h2>
<p>This is not true. Closures are a matter of scope, not of binding.
<p>For a closure it is necessary to build and maintain a separate environment.
In a system with lexical bindings, this has to be done at <i>each</i> function
call, and for compiled code it is the most efficient strategy anyway, because it
is done once by the compiler, and can then be accessed as stack frames at
runtime.
<p>For an interpreter, however, this is quite an overhead. So it should not be
done automatically at each and every function invocation, but only if needed.
<p>You have several options in PicoLisp. For simple cases, you can take
advantage of the static scope of <a href="ref.html#transient-io">transient</a>
or <a href="refP.html#private">private</a> symbols. For the general case, PicoLisp has built-in functions like
<code><a href="refB.html#bind">bind</a></code> or <code><a
href="refJ.html#job">job</a></code>, which dynamically manage statically scoped
environments.
<p>Environments are first-class objects in PicoLisp, more flexible than
hard-coded closures, because they can be created and manipulated independently
from the code.
<p>As an example, consider a currying function:
<pre>
(de curry Args
(list (car Args)
(list 'list
(lit (cadr Args))
(list 'cons ''job
(list 'cons
(list 'lit (list 'env (lit (car Args))))
(lit (cddr Args)) ) ) ) ) )
</pre>
<p>When called, it returns a function-building function which may be applied to
some argument:
<pre>
: ((curry (X) (N) (* X N)) 3)
-> ((N) (job '((X . 3)) (* X N)))
</pre>
<p>or used as:
<pre>
: (((curry (X) (N) (* X N)) 3) 4)
-> 12
</pre>
<p>In other cases, you are free to choose a shorter and faster solution. If (as
in the example above) the curried argument is known to be immutable:
<pre>
(de curry Args
(list
(cadr Args)
(list 'fill
(lit (cons (car Args) (cddr Args)))
(lit (cadr Args)) ) ) )
</pre>
<p>Then the function built above will just be:
<pre>
: ((curry (X) (N) (* X N)) 3)
-> ((X) (* X 3))
</pre>
<p>In that case, the "environment build-up" is reduced by a simple (lexical)
constant substitution with zero runtime overhead.
<p>Note that the actual <code><a href="refC.html#curry">curry</a></code>
function is simpler and more pragmatic. It combines both strategies (to use
<code>job</code>, or to substitute), deciding at runtime what kind of function
to build.
<p><hr>
<h2><a id="macros">Do you have macros?</a></h2>
<p>Yes, there is a macro mechanism in PicoLisp, to build and immediately execute
a list of expressions. But it is seldom used. Macros are a kludge. Most things
where you need macros in other Lisps are directly expressible as functions in
PicoLisp, which (as opposed to macros) can be applied, passed around, and
debugged.
<p>For example, Common Lisp's <code>DO*</code> macro, written as a function:
<pre>
(de do* "Args"
(bind (mapcar car (car "Args"))
(for "A" (car "Args")
(set (car "A") (eval (cadr "A"))) )
(until (eval (caadr "Args"))
(run (cddr "Args"))
(for "A" (car "Args")
(and (cddr "A") (set (car "A") (run @))) ) )
(run (cdadr "Args")) ) )
</pre>
<p><hr>
<h2><a id="threads">Can I run threads?</a></h2>
<p>This is not possible. Threads share memory and other resources (as opposed to
processes, which are better isolated from each other). Each thread has its own
stack for private data, but PicoLisp uses dynamic binding, where the stack holds
the <i>saved</i> values instead of the <i>current</i> values of symbols. As a
result, each running thread would overwrite the symbol bindings of other
threads.
<p>Instead, PicoLisp uses separate processes - and interprocess communication -
for parallel execution, or <a href="ref.html#coroutines">coroutines</a> as a
kind of <i>cooperative</i> threads running a controlled way and doing all
necessary housekeeping.
<p>Another advantage of separate processes over threads: They can be distributed
across multiple machines, and therefore scale better.
<p><hr>
<h2><a id="strings">Why are there no strings?</a></h2>
<p>Because PicoLisp has something better: <a
href="ref.html#transient-io">Transient symbols</a>. They look and behave like
strings in any respect, but are nevertheless true symbols, with a value and a
property list.
<p>This leads to interesting opportunities. The value, for example, can point to
other data that represent the string's translation. This is used extensively for
localization. When a program calls
<pre>
(prinl "Good morning!")
</pre>
<p>then changing the value of the symbol <code>"Good morning!"</code> to its
translation will change the program's output at runtime.
<p>Transient symbols are also quite memory-conservative. As they are stored in
normal heap cells, no additional overhead for memory management is induced. The
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 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 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.
<p>Because transient symbols are temporarily interned (while <code><a
href="refL.html#load">load</a></code>ing the current source file), they are
shared within the same source and occupy that space only once, even if they
occur multiple times within the same file.
<p><hr>
<h2><a id="arrays">What about arrays?</a></h2>
<p>PicoLisp has no array or vector data type. Instead, lists must be used for
any type of sequentially arranged data.
<p>We believe that arrays are usually overrated. Textbook wisdom tells that they
have a constant access time O(1) when the index is known. Many other operations
like splits or insertions are expensive. Access with a known (numeric) index is
not typical for Lisp, and even then the advantage of an array is significant
only if it is relatively long. Holding lots of data in long arrays, however,
smells quite like a program design error, and we suspect that often more
structured representations like trees or interconnected objects would be better.
<p>In practice, most arrays are rather short, or the program can be designed in
such a way that long arrays (or at least an indexed access) are avoided.
<p>Using lists, on the other hand, has advantages. We have so many concerted
functions that uniformly operate on lists. There is no separate data type that
has to be handled by the interpreter, garbage collector, I/O, database and so
on. Lists can be made circular. And lists don't cause memory fragmentation.
<p>Still, if there is really a need to access large amounts of data with a
numeric index, <code><a href="refE.html#enum">enum</a></code> can be used. It
emulates a multidimensional - possibly sparse - array. It takes roughly 1.5 the
space a linear list would require, and is very fast.
<p><hr>
<h2><a id="floats">How to do floating point arithmetic?</a></h2>
<p>PicoLisp does not support real floating point numbers. You can do all kinds
of floating point calculations by calling existing library functions via
<code><a href="refN.html#native">native</a></code>, inline-C code, and/or by
loading the "@lib/math.l" library.
<p>But PicoLisp has something even (arguably) better: Scaled <a
href="ref.html#num-io">fixpoint numbers</a>, with unlimited precision.
<p>The reasons for this design decision are manifold. Floating point numbers
smack of imperfection, they don't give "exact" results, have limited precision
and range, and require an extra data type. It is hard to understand what really
goes on (How many digits of precision do we have today? Are perhaps 10-byte
floats used for intermediate results? How does rounding behave?).
<p>For fixpoint support, the system must handle just integer arithmetic, I/O and
string conversions. The rest is under programmer's control and responsibility
(the essence of PicoLisp).
<p>Carefully scaled fixpoint calculations can do anything floating point can do.
<p><hr>
<h2><a id="bind">What happens when I locally bind a symbol which has a function definition?</a></h2>
<p>That's not a good idea. The next time that function gets executed within the
dynamic context the program may crash. Therefore we have a convention to use an
upper case first letter for locally bound symbols:
<pre>
(de findCar (Car List)
(when (member Car (cdr List))
(list Car (car List)) ) )
</pre>
;-)
<p><hr>
<h2><a id="hardware">Would it make sense to build PicoLisp in hardware?</a></h2>
<p>At least it should be interesting. It would be a machine executing list
(tree) structures instead of linear instruction sequences. "Instruction
prefetch" would look down the CAR- and CDR-chains, and perhaps need only a
single cache for both data and instructions.
<p>Primitive functions like <code>set</code>, <code>val</code>, <code>if</code>
and <code>while</code>, which are written in <code>C</code> or assembly language
now, would be implemented in microcode. Plus a few I/O functions for hardware
access. <code>EVAL</code> itself would be a microcode subroutine.
<p>Only a single heap and a single stack is needed. They grow towards each
other, and cause garbage collection if they get too close. Heap compaction is
trivial due to the single cell size.
<p>There would be no assembly-language. The lowest level (above the hardware and
microcode levels) are s-expressions: The machine language is <i>Lisp</i>.
<p><hr>
<h2><a id="segfault">I get a segfault if I ...</a></h2>
<p>It is easy to produce a segfault in PicoLisp. Just set a symbol to a value
which is not a function, and call it:
<pre>
: (setq foo 1)
-> 1
: (foo)
Segmentation fault
</pre>
There is another <a href="ref.html#codePointer">example</a> in the <a
href="ref.html#ev">Evaluation</a> section of the reference manual.
<p>PicoLisp is a pragmatic language. It doesn't check at runtime for all
possible error conditions which won't occur during normal usage. Such errors are
usually detected quickly at the first test run, and checking for them after that
would just produce runtime overhead.
<p>Catching the segmentation violation and bus fault signals is also not a good
idea, because the Lisp heap is most probably be damaged afterwards, possibly
creating further havoc if execution continues.
<p>It is recommended to inspect the code periodically with <code><a
href="refL.html#lint">lint</a></code>. It will detect many potential errors.
And, most of these errors are avoided by following the PicoLisp <a
href="ref.html#conv">naming conventions</a>.
<p><hr>
<h2><a id="ask">Where can I ask questions?</a></h2>
<p>The best place is the <a
href="mailto:picolisp@software-lab.de?subject=Subscribe">PicoLisp Mailing
List</a> (see also <a
href="http://www.mail-archive.com/picolisp@software-lab.de/">The Mail
Archive</a>), or the IRC <a href="irc://irc.freenode.net/picolisp">#picolisp</a>
channel on FreeNode.net.
</body>
</html>
================================================
FILE: doc/httpGate.html
================================================
<!--
# VIP @lib/vip/html.l
# 03jan26 Software Lab. Alexander Burger
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>The 'httpGate' Proxy Server</title>
<link rel="stylesheet" href="doc.css" type="text/css">
</head>
<body>
<a href="mailto:mattias@inogu.se">mattias@inogu.se</a>
<h1>The 'httpGate' Proxy Server</h1>
<p style="text-align: right">(c) Software Lab. Mattias Sundblad
<p>This document describes the <code>httpGate</code> utility which is included
in the PicoLisp distribution.
<p>For basic information about the PicoLisp system please look at the <a
href="ref.html">PicoLisp Reference</a> and the <a href="tut.html">PicoLisp
Tutorial</a>.
<p><ul>
<li><a href="#purpose">Purpose</a>
<li><a href="#basic">Basic functionality</a>
<li><a href="#building">Building httpGate</a>
<li><a href="#running">Running httpGate</a>
<li><a href="#config">Configuring httpGate</a>
<ul>
<li><a href="#names">The "names" config file</a>
<li><a href="#balanced">Balanced "names" file</a>
<li><a href="#voidfile">The "void" file</a>
<li><a href="#reload">Reloading the configuration</a>
</ul>
<li><a href="#keepalive">Keep-alive and retirement</a>
</ul>
<p><hr>
<h2><a id="purpose">Purpose</a></h2>
<p><code>httpGate</code> is a central element of the PicoLisp application server
architecture. Its purpose is to perform the following tasks:
<p><ul>
<li>Provide a single application entry port (e.g. 80 or 443).
<li>Allow PicoLisp applications to run as non-root.
<li>Start application servers on demand.
<li>Handle HTTPS/SSL communication.
</ul>
<h2><a id="basic">Basic functionality</a></h2>
<p>A HTTP request to port 80, respectively 443, of the form
<pre>
http[s]://server.org/12345/path/file
</pre>
<p>is forwarded to a server on localhost listening on port 12345, to ask for the
resource "path/file".
<p>If httpGate was started with a config file, and that file contains an entry
for "app", then also the following request is accepted:
<pre>
http[s]://server.org/app/path/file
</pre>
<p>In that case, the "app" server process is started automatically (if it is not
already running) listening on port 12345, and the request is forwarded as above.
<p>Only requests to ports >= 1024 will be forwarded. The main httpGate
process then forks two child processes, one for each direction. These child
processes terminate automatically if the connection is idle for more than 7
minutes.
<h2><a id="running">Running httpGate</a></h2>
<p>The simplest way to run httpGate is to start it with an explicit port
argument:
<pre>
bin/httpGate 80 8080
bin/httpGate 443 8080 pem/www.domain.key,pem/domain.crt
</pre>
<p>When started in this way, httpGate forwards requests from port 80 and 443
respectively to a PicoLisp application on port 8080. This form has a drawback
though, since it only allows for a single application to be handled. Usually,
there are many PicoLisp applications running on the same machine, and we need
httpGate to forward requests to all of them.
<p>To handle several applications, start httpGate with a "names" config file:
<pre>
bin/httpGate 80 names
bin/httpGate 443 names pem/www.domain.key,pem/domain.crt
</pre>
<p>httpGate needs to be started as root, but application servers should run
under normal user accounts. The easiest way to start httpGate automatically is
to add lines like the ones above to '/etc/rc.local'.
<h2><a id="config">Configuring httpGate</a></h2>
<h3><a id="names">The "names" config file</a></h3>
<p>The "names" config file contains one line per application server. Each line
holds six whitespace separated tokens, for example:
<pre>
app 12345 tom /home/tom log/app ./pil app/main.l lib/app.l -main -go -wait
</pre>
<p><ol>
<li>"app" is the name of the application, and the key to this line.
<li>"12345" is the port where this server should listen at.
<li>"tom" is the user under whose ID the server should run.
<li>"/home/tom" is the working directory where the server should start.
<li>"log/app" is a log file to redirect stdout/stderr to.
<li>The rest of the line "./pil app/main.l ..." is the command to start the application.
</ol>
<p>Empty lines, and lines starting with a "#", are ignored. If the key in a
config file record is the special name "@", then it denotes the default
application for this machine. URLs without name will be forwarded to that port.
If the key contains a slash followed by a string (e.g. "app/foo") then this
string is inserted in front of URLs.
<p>Optional tokens (e.g. log files) or empty arguments to the commands must be
written as single caret (^) characters to denote empty strings. Double or single
quotes are not parsed.
<p>If the port is zero, then a single additional token is expected which should
denote an URL to redirect the request to:
<pre>
app 0 https://domain/foo/bar
</pre>
This will cause httpGate to respnd with "302 Found" and "Location:
https://domain/foo/bar".
<h3><a id="balanced">Balanced names file</a></h3>
<p>If the config file contains many (hundreds or thousands) entries, then it is
recommended to sort it with the 'balance' utility. This may greatly accelerate
name (key) lookup at runtime. For that, put the above config lines into a file
"config". The tool 'balance' can be built - together with httpGate - with
<pre>
(cd src; make tools gate)
</pre>
<p>The following command will create a balanced "names" file:
<pre>
cat config | bin/balance -sort > names
</pre>
<h3><a id="voidfile">The "void" file</a></h3>
<p>If the local application server cannot be connected on the requested port
(typically because a session timed out), and a file with the name "void" exists
in the current working directory (token 4 in the config line), then the contents
of that file (normally HTML) are sent as response to the client.
<h3><a id="reload">Reloading the configuration</a></h3>
<p>When the config file is modified, it can be reloaded by sending SIGHUP to all
running top-level httpGate processes:
<pre>
$ sudo pkill -HUP -P1 httpGate
</pre>
<p>Another possibility is to restart httpGate(s). This is not a problem, and can
be done also while the server is in production.
<p>Just kill the top level httpGate parent process. This is not harmful, because
existing user sessions are handled by pairs of child processes, which continue
to run (until they terminate normally) even if their parent is stopped. Note
that this is different from PicoLisp DB applications, where the parent should
*never* be hard-stopped (eg. with 'kill -9 <pid>') while child processes
are running ('kill <pid>' is OK though, because the parent takes care of
stopping the children).
<p>An example for stopping and restarting a running httpGate is:
<pre>
(let L
# Build list of all httpGate parents (i.e. on 80 and 443)
(make
(in '("sudo" "pgrep" "-P1" "httpGate")
(while (read)
(link @) ) ) )
# Stop them
(for P L
(call "sudo" "kill" P) )
# Wait until all are gone
(while (find '((P) (kill P 0)) L)
(wait 200) )
# Start new
(call "sudo" "bin/httpGate" 80 "names")
(call "sudo" "bin/httpGate" 443 "names" "pem/...") )
</pre>
<h2><a id="keepalive">Keep-alive and retirement</a></h2>
<p>Applications should call
<pre>
(retire 20)
</pre>
<p>before they call 'server'. This causes the parent server process to terminate
automatically 20 minutes after the last child process (user session) terminated.
It will be started by httpGate again on demand. User sessions in turn terminate
automatically after 5 minutes (if nobody logged in) or 1 hour (if a user is
logged in), unless JavaScript is enabled in the client browser and the
application calls
<pre>
(<ping> 7)
</pre>
<p>in its main 'action' function. In that case, the user session will not
terminate until the user closes the last window or tab to this application.
</body>
</html>
================================================
FILE: doc/man.html
================================================
Content-type: text/html; charset=UTF-8
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML><HEAD><TITLE>Man page of PICOLISP</TITLE>
</HEAD><BODY>
<H1>PICOLISP</H1>
Section: User Commands (1)<BR>Updated: <BR><A HREF="#index">Index</A>
<A HREF="http://home.picolisp.com">Return to Main Contents</A><HR>
<A NAME="lbAB"> </A>
<H2>NAME</H2>
pil, picolisp - a fast, lightweight Lisp interpreter
<A NAME="lbAC"> </A>
<H2>SYNOPSIS</H2>
<B>pil</B>
[arguments ...] [-] [arguments ...] [+]
<BR>
<B>picolisp</B>
[arguments ...] [-] [arguments ...] [+]
<A NAME="lbAD"> </A>
<H2>DESCRIPTION</H2>
<B>PicoLisp</B>
is a Lisp interpreter with a small memory footprint, yet relatively high
execution speed. It combines an elegant and powerful language with built-in
database functionality.
<P>
<B>pil</B>
is the startup front-end for the interpreter. It takes care of starting the
binary base system and loading a useful runtime environment.
<P>
<B>picolisp</B>
is just the bare interpreter binary. It is usually called in stand-alone
scripts, using the she-bang notation in the first line, passing the minimal
environment in
<I>lib.l</I>
and loading additional files as needed:
<P>
<DL COMPACT><DT><DD>
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
</DL>
<DL COMPACT><DT><DD>
(load "@ext.l" "myfiles/lib.l" "myfiles/foo.l")
</DL>
<DL COMPACT><DT><DD>
(do ... something ...)
</DL>
<DL COMPACT><DT><DD>
(bye)
</DL>
<A NAME="lbAE"> </A>
<H2>INVOCATION</H2>
<B>PicoLisp</B>
has no pre-defined command line flags; applications are free to define their
own. Any built-in or user-level Lisp function can be invoked from the command
line by prefixing it with a hyphen. Examples for built-in functions useful in
this context are
<B>version</B>
(print the version number) or
<B>bye</B>
(exit the interpreter). Therefore, a minimal call to print the version number
and then immediately exit the interpreter would be:
<P>
<DL COMPACT><DT><DD>
$ pil -version -bye
</DL>
<P>
Any other argument (not starting with a hyphen) should be the name of a file to
be loaded. If the first character of a path or file name is an at-mark, it
will be substituted with the path to the installation directory.
<P>
All arguments are evaluated from left to right, then an interactive
<I>read-eval-print</I>
loop is entered (with a colon as prompt).
<P>
A single hyphen stops the evaluation of the rest of the command line, so that
the remaining arguments may be processed under program control.
<P>
If the very last command line argument is a single plus character, debugging
mode is switched on at interpreter startup, before evaluating any of the command
line arguments. A minimal interactive session is started with:
<P>
<DL COMPACT><DT><DD>
$ pil +
</DL>
<P>
Here you can access the reference manual (expects the shell variable BROWSER to
be set, defaults to "w3m")
<P>
<DL COMPACT><DT><DD>
: (doc)
</DL>
<P>
and the online documentation for most functions,
<P>
<DL COMPACT><DT><DD>
: (doc 'vi)
</DL>
<P>
or directly inspect their sources:
<P>
<DL COMPACT><DT><DD>
: (vi 'doc)
</DL>
<P>
The interpreter can be terminated with
<P>
<DL COMPACT><DT><DD>
: (bye)
</DL>
<P>
or by typing Ctrl-D.
<A NAME="lbAF"> </A>
<H2>FILES</H2>
Runtime files are maintained in the ~/.pil directory:
<DL COMPACT>
<DT>~/.pil/tmp/<pid>/<DD>
Process-local temporary directories
<DT>~/.pil/rc<DD>
Loaded after interpreter startup
<DT>~/.pil/viprc<DD>
Loaded by the Vip editor
</DL>
<A NAME="lbAG"> </A>
<H2>BUGS</H2>
<B>PicoLisp</B>
doesn't try to protect you from every possible programming error ("You asked for
it, you got it").
<A NAME="lbAH"> </A>
<H2>AUTHOR</H2>
Alexander Burger <<A HREF="mailto:abu@software-lab.de">abu@software-lab.de</A>>
<A NAME="lbAI"> </A>
<H2>RESOURCES</H2>
<B>Home page:</B>
<A HREF="http://home.picolisp.com">http://home.picolisp.com</A>
<BR>
<B>Download:</B>
<A HREF="http://www.software-lab.de/down.html">http://www.software-lab.de/down.html</A>
<P>
<HR>
<A NAME="index"> </A><H2>Index</H2>
<DL>
<DT><A HREF="#lbAB">NAME</A><DD>
<DT><A HREF="#lbAC">SYNOPSIS</A><DD>
<DT><A HREF="#lbAD">DESCRIPTION</A><DD>
<DT><A HREF="#lbAE">INVOCATION</A><DD>
<DT><A HREF="#lbAF">FILES</A><DD>
<DT><A HREF="#lbAG">BUGS</A><DD>
<DT><A HREF="#lbAH">AUTHOR</A><DD>
<DT><A HREF="#lbAI">RESOURCES</A><DD>
</DL>
<HR>
This document was created by
<A HREF="http://home.picolisp.com">man2html</A>,
using the manual pages.<BR>
Time: 08:01:21 GMT, March 29, 2021
</BODY>
</HTML>
================================================
FILE: doc/microTemplates
================================================
Micro-Templates
* Each template file in the @lib/xhtml/ directory applies to one type of
component in the @lib/xhtml.l functions.
* The template files are line oriented. One micro-template per line.
* A micro-template can be continued on the following line(s) by
indenting these lines with space(s).
* Each line has a defined meaning. Except for indented lines, no lines
can be added or removed.
* A micro-template may contain either variables or expressions enclosed
by "¦" (broken bar character, hex "00A6").
* An empty line is denoted by "<>".
* "~" is replaced at runtime with the session ID.
* At program start, all templates from @lib/xhtml/ are loaded.
* The application may override one or more files in a local directory,
and call 'xhtml' with that path. Also more than once.
* Available templates:
html
1. DOCTYPE
2. HTML start
3. HEAD
4. BODY
5. HTML end
table
1. Table start
2. Caption
3. Header row start
4. Header row entry
5. Header row end
6. Data row start
7. Data row entry
8. Data row end
9. Table end
grid
1. Grid start
2. Grid row start
3. Grid row entry
4. Grid row end
5. Grid end
layout
Variable number of lines, one per code block
menu
1. Menu start
2. Submenu start
3. Plain HTML
4. Disabled link
5. Enabled link
6. Enabled active link
7. Closed submenu
8. Open submenu start
9. Open submenu end
10. Submenu end
11. Menu end
tab
1. TABLE start
2. Disabled entry
3. Enabled entry
4. TABLE end
input
1. (Non-text) Input element
field
1. Text input element
area
1. TEXTAREA start
2. TEXTAREA end
select
1. SELECT start
2. OPTION
3. SELECT end
submit
1. Submit input element
================================================
FILE: doc/native.html
================================================
<!--
# VIP @lib/vip/html.l
# 19jan26 Software Lab. Alexander Burger
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Native C Calls</title>
<link rel="stylesheet" href="doc.css" type="text/css">
</head>
<body>
<a href="mailto:abu@software-lab.de">abu@software-lab.de</a>
<h1>Native C Calls</h1>
<p style="text-align: right">(c) Software Lab. Alexander Burger
<p>This document describes how to call C functions in shared object files
(libraries) from PicoLisp, using the built-in <code><a
href="refN.html#native">native</a></code> function - possibly with the help of
the <code><a href="refS.html#struct">struct</a></code> and <code><a
href="refL.html#lisp">lisp</a></code> functions.
<p><ul>
<li><a href="#overview">Overview</a>
<li><a href="#syntax">Syntax</a>
<ul>
<li><a href="#libs">Libraries</a>
<li><a href="#funs">Functions</a>
<li><a href="#retval">Return Value</a>
<ul>
<li><a href="#primRet">Primitive Types</a>
<li><a href="#structRet">Arrays and Structures</a>
</ul>
<li><a href="#args">Arguments</a>
<ul>
<li><a href="#primArg">Primitive Types</a>
<li><a href="#structArg">Arrays and Structures</a>
</ul>
</ul>
<li><a href="#memory">Memory Management</a>
<ul>
<li><a href="#fftw">Fast Fourier Transform</a>
<li><a href="#const">Constant Data</a>
</ul>
<li><a href="#callbacks">Callbacks</a>
<ul>
<li><a href="#byName">Call by Name</a>
<li><a href="#funptr">Function Pointer</a>
</ul>
</ul>
<p><hr>
<h2><a id="overview">Overview</a></h2>
<p>
<code><a href="refN.html#native">native</a></code> calls a C function in a
shared library. It tries to
<p><ol>
<li>find a library by name
<li>find a function by name in the library
<li>convert the function's argument(s) from Lisp to C data structures
<li>call the function's C code
<li>convert the function's return value(s) from C to Lisp data structures
</ol>
<p>The direct return value of <code>native</code> is the Lisp representation of
the C function's return value. Further values, returned by reference from the C
function, are available in Lisp variables (symbol values).
<p><code><a href="refS.html#struct">struct</a></code> is a helper function,
which can be used to manipulate C data structures in memory. It may take a
scalar (a numeric representation of a C value) to convert it to a Lisp item, or
(more typically) a pointer to a memory area to build and extract data
structures. <code>lisp</code> allows you to install callback functions, callable
from C code, written in Lisp.
<p><code><a href="ref_.html#%25@">%@</a></code> is a convenience function,
simplifying the most common use case of <code>native</code>.
<p>In combination, these functions can interface PicoLisp to almost any C
function.
<p>The above steps are fully dynamic; <code>native</code> doesn't have (and
doesn't require) a priori knowledge about the library, the function or the
involved data. No need to write any glue code, interfaces or include files. All
functions can even be called interactively from the REPL.
<p><hr>
<h2><a id="syntax">Syntax</a></h2>
<p>The arguments to <code>native</code> are
<p><ol>
<li>a library
<li>a function
<li>a return value specification
<li>optional arguments
</ol>
<p>The simplest form is a call to a function without return value and without
arguments. If we assume a library "lib.so", containing a function with the
prototype
<pre>
void fun(void);
</pre>
<p>then we can call it as
<pre>
(native "lib.so" "fun")
</pre>
<p><hr>
<h3><a id="libs">Libraries</a></h3>
<p>The first argument to <code>native</code> specifies the library. It is either
the <i>name</i> of a library (a symbol), or the <i>handle</i> of a previously
found library (a number).
<p>As a special case, a transient symbol <code>"@"</code> can be passed for the
library name. It then refers to the current main program (instead of an external
library), and can be used for standard functions like <code>"malloc"</code> or
<code>"free"</code>.
Because this is needed so often,
<pre>
(%@ "fun" ...)
</pre>
<p>can be used instead of
<pre>
(native "@" "fun" ...)
</pre>
<p><code>native</code> uses <code>dlopen(3)</code> internally to find and open
the library, and to obtain the handle. If the name contains a slash ('/'), then
it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic
linker searches for the library according to the system's environment and
directories. See the man page of <code>dlopen(3)</code> for further details.
<p>If called with a symbolic argument, <code>native</code> automatically caches
the handle of the found library in the value of that symbol. The most natural
way is to pass the library name as a <a href="ref.html#transient">transient</a>
symbol (<code>"lib.so"</code> above): The initial value of a transient symbol is
that symbol itself, so that <code>native</code> receives the library name upon
the first call. After successfully finding and opening the library,
<code>native</code> stores the handle of that library in the value of the passed
symbol (<code>"lib.so"</code>). As <code>native</code> evaluates its arguments
in the normal way, subsequent calls within the same transient scope will receive
the numeric value (the handle), and don't need to open and search the library
again.
<p><hr>
<h3><a id="funs">Functions</a></h3>
<p>The same rules applies to the second argument, the function. When called with
a symbol, <code>native</code> stores the function handle in its value, so that
subsequent calls evaluate to that handle, and <code>native</code> can directly
jump to the function.
<p><code>native</code> uses <code>dlsym(3)</code> internally to obtain the
function pointer. See the man page of <code>dlsym(3)</code> for further details.
<p>In most cases a program will call more than one function from a given
library. If we keep the code within the same transient scope (i.e. in the same
source file), each library will be opened - and each function searched - only
once.
<pre>
(native "lib.so" "fun1")
(native "lib.so" "fun2")
(native "lib.so" "fun3")
</pre>
<p>After <code>"fun1"</code> was called, <code>"lib.so"</code> will be open, and
won't be re-opened for <code>"fun2"</code> and <code>"fun3"</code>. Consider
the definition of helper functions:
<pre>
(de fun1 ()
(native "lib.so" "fun1") )
(de fun2 ()
(native "lib.so" "fun2") )
(de fun3 ()
(native "lib.so" "fun3") )
</pre>
<p>After any one of <code>fun1</code>, <code>fun2</code> or <code>fun3</code>
was called, the symbol <code>"lib.so"</code> will hold the library handle. And
each function <code>"fun1"</code>, <code>"fun2"</code> and <code>"fun3"</code>
will be searched only when called the first time.
<p>Note that the function handle points to a structure in memory, which is
automatically allocated. This implies that a memory leak may occur if the
transient symbol holding the function handle goes out of scope (e.g. by repeated
(re)<code><a href="refL.html#load">load</a></code>ing the library after
executing its functions).
<p>Warning: It should be avoided to put more than one library into a single
transient scope if there is a chance that two different functions with the same
name will be called in two different libraries. Because of the function handle
caching, the second call would otherwise (wrongly) go to the first function.
<p><hr>
<h3><a id="retval">Return Value</a></h3>
<p>The (optional) third argument to <code>native</code> specifies the return
value. A C function can return many types of values, like integer or floating
point numbers, string pointers, or pointers to structures which in turn consist
of those types, and even other structures or pointers to structures.
<code>native</code> tries to cover most of them.
<p>As described in the <a href="refN.html#natResult">result specification</a>,
the third argument should consist of a pattern which tells <code>native</code>
how to extract the proper value.
<h4><a id="primRet">Primitive Types</a></h4>
<p>In the simplest case, the result specification is <code>NIL</code> like in
the examples so far. This means that either the C function returns
<code>void</code>, or that we are not interested in the value. The return value
of <code>native</code> will be <code>NIL</code> in that case.
<p>If the result specification is one of the symbols <code>B</code>,
<code>I</code> or <code>N</code>, an integer number is returned, by interpreting
the result as a <code>char</code> (8 bit unsigned byte), <code>int</code> (32
bit signed integer), or <code>long</code> number (64 bit signed integer),
respectively. Other (signed or unsigned numbers, and of different sizes) can be
produced from these types with logical and arithmetic operations if necessary.
<p>If the result specification is the symbol <code>C</code>, the result is
interpreted as a 16 bit number, and a single-char transient symbol (string) is
returned.
<p>A specification of <code>S</code> tells <code>native</code> to interpret the
result as a pointer to a C string (null terminated), and to return a transient
symbol (string).
<p>If the result specification is a number, it will be used as a scale to
convert a returned <code>double</code> (if the number is positive) or
<code>float</code> (if the number is negative) to a scaled fixpoint number.
<p>Examples for function calls, with their corresponding C prototypes:
<pre>
(native "lib.so" "fun" 'I) # int fun(void);
(native "lib.so" "fun" 'N) # long fun(void);
(native "lib.so" "fun" 'P) # void *fun(void);
(native "lib.so" "fun" 'S) # char *fun(void);
(native "lib.so" "fun" 1.0) # double fun(void);
</pre>
<h4><a id="structRet">Arrays and Structures</a></h4>
<p>If the result specification is a list, it means that the C function returned
a pointer to an array, or an arbitrary memory structure. The specification list
should then consist of either the above primitive specifications (symbols or
numbers), or of cons pairs of a primitive specification and a repeat count, to
denote arrays of the given type.
<p>Examples for function calls, with their corresponding pseudo C prototypes:
<pre>
(native "lib.so" "fun" '(I . 8)) # int *fun(void); // 8 integers
(native "lib.so" "fun" '(B . 16)) # unsigned char *fun(void); // 16 bytes
(native "lib.so" "fun" '(I I)) # struct {int i; int j;} *fun(void);
(native "lib.so" "fun" '(I . 4)) # struct {int i[4];} *fun(void);
(native "lib.so" "fun" '(I (B . 4))) # struct {
# int i;
# unsigned char c[4];
# } *fun(void);
(native "lib.so" "fun" # struct {
'(((B . 4) I) (S . 12) (N . 8)) ) # struct {unsigned char c[4]; int i;}
# char *names[12];
# long num[8];
# } *fun(void);
</pre>
<p>If a returned structure has an element which is a <i>pointer</i> to some
other structure (i.e. not an embedded structure like in the last example above),
this pointer must be first obtained with a <code>N</code> pattern, which can
then be passed to <code><a href="refS.html#struct">struct</a></code> for further
extraction.
<p><hr>
<h3><a id="args">Arguments</a></h3>
<p>The (optional) fourth and following arguments to <code>native</code> specify
the arguments to the C function.
<h4><a id="primArg">Primitive Types</a></h4>
<p>Integer arguments (up to 64 bits, signed or unsigned <code>char</code>,
<code>short</code>, <code>int</code> or <code>long</code>) can be passed as they
are: As numbers.
<pre>
(native "lib.so" "fun" NIL 123) # void fun(int);
(native "lib.so" "fun" NIL 1 2 3) # void fun(int, long, short);
</pre>
<p>String arguments can be specified as symbols. <code>native</code> allocates
memory for each string on the stack, passes the pointer to the C function, and
cleans up the stack when done.
<pre>
(native "lib.so" "fun" NIL "abc") # void fun(char*);
(native "lib.so" "fun" NIL 3 "def") # void fun(int, char*);
</pre>
<p>Note that the allocated string memory is released <i>after</i> the return
value is extracted. This allows a C function to return the argument string
pointer, perhaps after modifying the data in-place, and receive the new string
as the return value (with the <code>S</code> specification).
<pre>
(native "lib.so" "fun" 'S "abc") # char *fun(char*);
</pre>
<p>Also note that specifying <code>NIL</code> as an argument passes an empty
string ("", which also reads as <code>NIL</code> in PicoLisp) to the C function.
Physically, this is a pointer to a NULL-byte, and is <u>not</u> a NULL-pointer.
Be sure to pass <code>0</code> (the number zero) if a NULL-pointer is desired.
<p>Floating point arguments are specified as cons pairs, where the value is in
the CAR, and the CDR holds the fixpoint scale. If the scale is positive, the
number is passed as a <code>double</code>, otherwise as a <code>float</code>.
<pre>
(native "lib.so" "fun" NIL # void fun(double, float);
(12.3 . 1.0) (4.56 . -1.0) )
</pre>
<h4><a id="structArg">Arrays and Structures</a></h4>
<p>Composite arguments are specified as nested list structures.
<code>native</code> allocates memory for each array or structure (with
<code>malloc(3)</code>), passes the pointer to the C function, and releases the
memory (with <code>free(3)</code>) when done.
<p>This implies that such an argument can be both an input and an output value
to a C function (pass by reference).
<p>The CAR of the argument specification can be <code>NIL</code> (then it is an
input-only argument). Otherwise, it should be a variable which receives the
returned structure data.
<p>The CADR of the argument specification must be a cons pair with the total
size of the structure in its CAR. The CDR is ignored for input-only arguments,
and should contain a <a href="refN.html#natResult">result specification</a> for
the output value to be stored in the variable.
<p>For example, a minimal case is a function that takes an integer reference,
and stores the number '123' in that location:
<pre>
void fun(int *i) {
*i = 123;
}
</pre>
<p>We call <code>native</code> with a variable <code>X</code> in the CAR of the
argument specification, a size of 4 (i.e. <code>sizeof(int)</code>), and
<code>I</code> for the result specification. The stored value is then available
in the variable <code>X</code>:
<pre>
: (native "lib.so" "fun" NIL '(X (4 . I)))
-> NIL
: X
-> 123
</pre>
<p>The rest (CDDR) of the argument specification may contain initialization
data, if the C function expects input values in the structure. It should be a
list of <a href="refN.html#natItem">initialization items</a>, optionally with a
fill-byte value in the CDR of the last cell.
<p>If there are <i>no</i> initialization items and just the final fill-byte,
then the whole buffer is filled with that byte. For example, to pass a buffer of
20 bytes, initialized to zero:
<pre>
: (native "lib.so" "fun" NIL '(NIL (20) . 0))
</pre>
<p>A buffer of 20 bytes, with the first 4 bytes initialized to 1, 2, 3, and 4,
and the rest filled with zero:
<pre>
: (native "lib.so" "fun" NIL '(NIL (20) 1 2 3 4 . 0))
</pre>
<p>and the same, where the buffer contents are returned as a list of bytes in
the variable <code>X</code>:
<pre>
: (native "lib.so" "fun" NIL '(X (20 B . 20) 1 2 3 4 . 0))
</pre>
<p>For a more extensive example, let's use the following definitions:
<pre>
typedef struct value {
int x, y;
double a, b, c;
int z;
char nm[4];
} value;
void fun(value *val) {
printf("%d %d\n", val->x, val->y);
val->x = 3;
val->y = 4;
strcpy(val->nm, "OK");
}
</pre>
<p>We call this function with a structure of 40 bytes, requesting the returned
data in <code>V</code>, with two integers <code>(I . 2)</code>, three doubles
<code>(100 . 3)</code> with a scale of 2 (1.0 = 100), another integer
<code>I</code> and four characters <code>(C . 4)</code>. If the structure gets
initialized with two integers 7 and 6, three doubles 0.11, 0.22 and 0.33, and
another integer 5 while the rest of the 40 bytes is cleared to zero
<pre>
: (native "lib.so" "fun" NIL
'(V (40 (I . 2) (100 . 3) I (C . 4)) -7 -6 (100 11 22 33) -5 . 0) )
</pre>
<p>then it will print the integers 7 and 6, and <code>V</code> will contain the
returned list
<pre>
((3 4) (11 22 33) 5 ("O" "K" NIL NIL))
</pre>
<p>i.e. the original integer values 7 and 6 replaced with 3 and 4.
<p>Note that the allocated structure memory is released <i>after</i> the return
value is extracted. This allows a C function to return the argument structure
pointer, perhaps after modifying the data in-place, and receive the new
structure as the return value - instead of (or even in addition to) to the
direct return via the argument reference.
<p><hr>
<h2><a id="memory">Memory Management</a></h2>
<p>The preceding <a href="#args">Arguments</a> section mentions that
<code>native</code> implicitly allocates and releases memory for strings, arrays
and structures.
<p>Technically, this mimics <i>automatic variables</i> in C.
<p>For a simple example, let's assume that we want to call <code>read(2)</code>
directly, to fetch a 4-byte integer from a given file descriptor. This could be
done with the following C function:
<pre>
int read4bytes(int fd) {
char buf[4];
read(fd, buf, 4);
return *(int*)buf;
}
</pre>
<p><code>buf</code> is an automatic variable, allocated on the stack, which
disappears when the function returns. A corresponding <code>native</code> call
would be:
<pre>
(%@ "read" 'I Fd '(Buf (4 . I)) 4)
</pre>
<p>The structure argument <code>(Buf (4 . I))</code> says that a space of 4
bytes should be allocated and passed to <code>read</code>, then an integer
<code>I</code> returned in the variable <code>Buf</code> (the return value of
<code>native</code> itself is the integer returned by <code>read</code>). The
memory space is released after that.
<p>(Note that we can call <code>%@</code> here, as <code>read</code> resides in
the main program.)
<p>Instead of a single integer, we might want a list of four bytes to be
returned from <code>native</code>:
<pre>
(%@ "read" 'I Fd '(Buf (4 B . 4)) 4)
</pre>
<p>The difference is that we wrote <code>(B . 4)</code> (a list of 4 bytes)
instead of <code>I</code> (a single integer) for the <a
href="refN.html#natResult">result specification</a> (see the <a
href="#structArg">Arrays and Structures</a> section).
<p>Let's see what happens if we extend this example. We'll write the four bytes
to another file descriptor, after reading them from the first one:
<pre>
void copy4bytes(int fd1, int fd2) {
char buf[4];
read(fd1, buf, 4);
write(fd2, buf, 4);
}
</pre>
<p>Again, <code>buf</code> is an automatic variable. It is passed to both
<code>read</code> and <code>write</code>. A direct translation would be:
<pre>
(%@ "read" 'I Fd '(Buf (4 B . 4)) 4)
(%@ "write" 'I Fd2 (cons NIL (4) Buf) 4)
</pre>
<p>This works as expected. <code>read</code> returns a list of four bytes in
<code>Buf</code>. The call to <code>cons</code> builds the structure
<pre>
(NIL (4) 1 2 3 4)
</pre>
<p>i.e. no return variable, a four-byte memory area, filled with the four bytes
(assuming that <code>read</code> returned 1, 2, 3 and 4). Then this structure is
passed to <code>write</code>.
<p>But: This solution induces quite some overhead. The four-byte buffer is
allocated before the call to <code>read</code> and released after that, then
allocated and released again for <code>write</code>. Also, the bytes are
converted to a list to be stored in <code>Buf</code>, then that list is extended
for the structure argument to <code>write</code>, and converted again back to
the raw byte array. The data in the list itself are never used.
<p>If the above operation is to be used more than once, it is better to allocate
the buffer manually, use it for both reading and writing, and then release it.
This also avoids all intermediate list conversions.
<pre>
(let Buf (%@ "malloc" 'P 4) # Allocate memory
(%@ "read" 'I Fd Buf 4) # (Possibly repeat this several times)
(%@ "write" 'I Fd2 Buf 4)
(%@ "free" NIL Buf) ) # Release memory
</pre>
<p>To allocate such a buffer locally on the stack (just like a C function would
do), <code><a href="refB.html#buf">buf</a></code> can be used. Equivalent to the
above is:
<pre>
(buf Buf 4 # Allocate local memory
(%@ "read" 'I Fd Buf 4)
(%@ "write" 'I Fd2 Buf 4) )
</pre>
<h4><a id="fftw">Fast Fourier Transform</a></h4>
<p>For a more typical example, we might call the Fast Fourier Transform using
the library from the <a href="http://fftw.org">FFTW</a> package. With the
example code for calculating Complex One-Dimensional DFTs:
<pre>
#include <fftw3.h>
...
{
fftw_complex *in, *out;
fftw_plan p;
...
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
...
fftw_execute(p); /* repeat as needed */
...
fftw_destroy_plan(p);
fftw_free(in); fftw_free(out);
}
</pre>
<p>we can build the following equivalent:
<pre>
(load "@lib/math.l")
(de FFTW_FORWARD . -1)
(de FFTW_ESTIMATE . 64)
(de fft (Lst)
(let
(Len (length Lst)
In (native "libfftw3.so" "fftw_malloc" 'P (* Len 16))
Out (native "libfftw3.so" "fftw_malloc" 'P (* Len 16))
P (native "libfftw3.so" "fftw_plan_dft_1d" 'N
Len In Out FFTW_FORWARD FFTW_ESTIMATE ) )
(struct In NIL (cons 1.0 (apply append Lst)))
(native "libfftw3.so" "fftw_execute" NIL P)
(prog1
(struct Out (make (do Len (link (1.0 . 2)))))
(native "libfftw3.so" "fftw_destroy_plan" NIL P)
(native "libfftw3.so" "fftw_free" NIL Out)
(native "libfftw3.so" "fftw_free" NIL In) ) ) )
</pre>
<p>This assumes that the argument list <code>Lst</code> is passed as a list
of complex numbers, each as a list of two numbers for the real and imaginary
part, like
<pre>
(fft '((1.0 0) (1.0 0) (1.0 0) (1.0 0) (0 0) (0 0) (0 0) (0 0)))
</pre>
<p>The above translation to Lisp is quite straightforward. After the two buffers
are allocated, and a plan is created, <code><a
href="refS.html#struct">struct</a></code> is called to store the argument list
in the <code>In</code> structure as a list of double numbers (according to the
<code>1.0</code> <a href="refN.html#natItem">initialization item</a>). Then
<code>fftw_execute</code> is called, and <code>struct</code> is called again to
retrieve the result from <code>Out</code> and return it from <code>fft</code>
via the <code><a href="refP.html#prog1">prog1</a></code>. Finally, all memory is
released.
<h4><a id="const">Constant Data</a></h4>
<p>If such allocated data (strings, arrays or structures passed to
<code>native</code>) are constant during the lifetime of a program, it makes
sense to allocate them only once, before their first use. A typical candidate is
the format string of a <code>printf</code> call. Consider a function which
prints a floating point number in scientific notation:
<pre>
(load "@lib/math.l")
: (de prf (Flt)
(%@ "printf" NIL "%e\n" (cons Flt 1.0)) )
-> prf
: (prf (exp 12.3))
2.196960e+05
</pre>
<p>As we know that the format string <code>"%e\n"</code> will be converted from
a Lisp symbol to a C string on each call to <code>prf</code>, we might as well
perform a little optimization and delegate this conversion to the program load
time:
<pre>
: (de prf (Flt)
(%@ "printf" NIL `(%@ "strdup" 'P "%e\n") (cons Flt 1.0)) )
-> prf
: (prf (exp 12.3))
2.196960e+05
</pre>
<p>If we look at the <code>prf</code> function, we see that it now contains the
pointer to the allocated string memory:
<pre>
: (pp 'prf)
(de prf (Flt)
(%@ "printf" NIL 24662032 (cons Flt 1000000)) )
-> prf
</pre>
<p>This pointer will be used by <code>printf</code> directly, without any
further conversion or memory management.
<p><hr>
<h2><a id="callbacks">Callbacks</a></h2>
<p>Sometimes it is necessary to do the reverse: Call Lisp code from C code.
<p>This mechanism uses the Lisp-level function <code><a
href="refL.html#lisp">lisp</a></code>. No C source code access is
required.
<p><code>lisp</code> returns a function pointer, which can be passed to
C functions via <code>native</code>. When this function pointer is
dereferenced and called from the C code, the corresponding Lisp function
is invoked. Only five numeric arguments and a numeric return value can
be used, and other data types must be handled by the Lisp function with
<code><a href="refS.html#struct">struct</a></code> and memory management
operations.
<p>Callbacks are often used in user interface libraries, to handle key-, mouse-
and other events. Examples can be found in <code>"@lib/openGl.l"</code>. The
following function <code>mouseFunc</code> takes a Lisp function, installs it
under the tag <code>mouseFunc</code> (any other tag would be all right too) as a
callback, and passes the resulting function pointer to the OpenGL
<code>glutMouseFunc()</code> function, to set it as a callback for the current
window:
<pre>
(de mouseFunc (Fun)
(native `*GlutLib "glutMouseFunc" NIL (lisp 'mouseFunc Fun)) )
</pre>
<p>(The global <code>*GlutLib</code> holds the library
<code>"/usr/lib/libglut.so"</code>. The backquote (<code>`</code>) is important
here, so that the transient symbol with the library name (and not the global
<code>*GlutLib</code>) is evaluated by <code>native</code>, resulting in the
proper library handle at runtime).
<p>A program using OpenGL may then use <code>mouseFunc</code> to install a
function
<pre>
(mouseFunc
'((Btn State X Y)
(do-something-with Btn State X Y) ) )
</pre>
<p>so that future clicks into the window will pass the button, state and
coordinates to that function.
</body>
</html>
================================================
FILE: doc/rc.sample
================================================
# 20nov24 Software Lab. Alexander Burger
# Copy to ~/.pil/rc
(history
(make
(skip "#")
(while (line T) (link @)) # Global history
(while (read) (eval @)) # Initial commands
(when (info ".pilrc") # Local history and commands
(in @@
(skip "#")
(while (line T) (link @))
(while (read) (eval @)) ) ) ) )
# Initial history
(stack)
(gc 1200) (dbCheck)
(show (; *FormLst 1 2))
(vi (; *FormLst 1 2 *Dbg 1 -1))
(show (; *FormLst 1 2 obj))
# Initial commands
(de x ()
(load "x.l") )
================================================
FILE: doc/ref.html
================================================
<!--
# VIP @lib/vip/html.l
# 04apr26 Software Lab. Alexander Burger
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PicoLisp Reference</title>
<link rel="stylesheet" href="doc.css" type="text/css">
</head>
<body>
<a href="mailto:abu@software-lab.de">abu@software-lab.de</a>
<p style="text-align: right">
<i>Perfection is attained</i><br>
<i>not when there is nothing left to add</i><br>
<i>but when there is nothing left to take away.</i><br>
<i>(Antoine de Saint-Exupéry)</i><br>
<h1>The PicoLisp Reference</h1>
<p style="text-align: right">(c) Software Lab. Alexander Burger
<p>This document describes the concepts, data types, and kernel functions of the
<a href="http://software-lab.de/down.html">PicoLisp</a> system.
<p>This is <i>not</i> a Lisp tutorial. For an introduction to Lisp, a
traditional Lisp book like "Lisp" by Winston/Horn (Addison-Wesley 1981) is
recommended. Note, however, that there are significant differences between
PicoLisp and Maclisp (and even greater differences to Common Lisp).
<p>Please take a look at the <a href="tut.html">PicoLisp Tutorial</a> for an
explanation of some aspects of PicoLisp, and scan through the list of <a
href="faq.html">Frequently Asked Questions (FAQ)</a>.
<p><ul>
<li><a href="#intro">Introduction</a>
<li><a href="#vm">The PicoLisp Machine</a>
<ul>
<li><a href="#cell">The Cell</a>
<li><a href="#data">Data Types</a>
<ul>
<li><a href="#number">Numbers</a>
<li><a href="#symbol">Symbols</a>
<ul>
<li><a href="#nilSym">NIL</a>
<li><a href="#internal">Internal Symbols</a>
<li><a href="#transient">Transient Symbols</a>
<li><a href="#external">External Symbols</a>
</ul>
<li><a href="#lst">Lists</a>
</ul>
<li><a href="#mem">Memory Management</a>
</ul>
<li><a href="#penv">Programming Environment</a>
<ul>
<li><a href="#inst">Installation</a>
<li><a href="#invoc">Invocation</a>
<li><a href="#io">Input/Output</a>
<ul>
<li><a href="#num-io">Numbers</a>
<li><a href="#sym-io">Symbols</a>
<ul>
<li><a href="#nilSym-io">NIL</a>
<li><a href="#internal-io">Internal Symbols</a>
<li><a href="#transient-io">Transient Symbols</a>
<li><a href="#external-io">External Symbols</a>
</ul>
<li><a href="#lst-io">Lists</a>
<li><a href="#macro-io">Read-Macros</a>
</ul>
<li><a href="#namespaces">Namespaces</a>
<li><a href="#ev">Evaluation</a>
<li><a href="#libs">Shared Libraries</a>
<li><a href="#coroutines">Coroutines</a>
<li><a href="#int">Interrupt</a>
<li><a href="#errors">Error Handling</a>
<li><a href="#atres">@ Result</a>
<li><a href="#cmp">Comparing</a>
<li><a href="#oop">OO Concepts</a>
<li><a href="#dbase">Database</a>
<ul>
<li><a href="#trans">Transactions</a>
<li><a href="#er">Entities / Relations</a>
</ul>
<li><a href="#pilog">Pilog (PicoLisp Prolog)</a>
<li><a href="#conv">Naming Conventions</a>
<li><a href="#trad">Breaking Traditions</a>
</ul>
<li><a href="#fun">Function Reference</a>
<li><a href="#down">Download</a>
</ul>
<p><hr>
<h2><a id="intro">Introduction</a></h2>
<p>PicoLisp is the result of a language design study, trying to answer the
question "What is a minimal but useful architecture for a virtual machine?".
Because opinions differ about what is meant by "minimal" and "useful", there are
many answers to that question, and people might consider other solutions more
"minimal" or more "useful". But from a practical point of view, PicoLisp has
proven to be a valuable answer to that question.
<p>First of all, PicoLisp is a virtual machine architecture, and then a
programming language. It was designed in a "bottom up" way, and "bottom up" is
also the most natural way to understand and to use it: <i>Form Follows
Function</i>.
<p>PicoLisp has been used in several commercial and research programming
projects since 1988. Its internal structures are simple enough, allowing an
experienced programmer always to fully understand what's going on under the
hood, and its language features, efficiency and extensibility make it suitable
for almost any practical programming task.
<p>In a nutshell, emphasis was put on four design objectives. The PicoLisp
system should be
<p><dl>
<dt>Simple</dt>
<dd>The internal data structure should be as simple as possible. Only one single
data structure is used to build all higher level constructs.
</dd>
<dt>Unlimited</dt>
<dd>There are no limits imposed upon the language due to limitations of the
virtual machine architecture. That is, there is no upper bound in symbol name
length, number digit counts, stack depth, or data structure and buffer sizes,
except for the total memory size of the host machine.
</dd>
<dt>Dynamic</dt>
<dd>Behavior should be as dynamic as possible ("run"-time vs. "compile"-time).
All decisions are delayed until runtime where possible. This involves matters
like memory management, dynamic symbol binding, and late method binding.
</dd>
<dt>Practical</dt>
<dd>PicoLisp is not just a toy of theoretical value. It is in use since 1988 in
actual application development, research and production.
</dd>
</dl>
<p><hr>
<h2><a id="vm">The PicoLisp Machine</a></h2>
<p>An important point in the PicoLisp philosophy is the knowledge about the
architecture and data structures of the internal machinery. The high-level
constructs of the programming language directly map to that machinery, making
the whole system both understandable and predictable.
<p>This is similar to assembly language programming, where the programmer has
complete control over the machine.
<p><hr>
<h3><a id="cell">The Cell</a></h3>
<p>The PicoLisp virtual machine is both simpler and more powerful than most
current (hardware) processors. At the lowest level, it is constructed from a
single data structure called "cell":
<pre>
+-----+-----+
| CAR | CDR |
+-----+-----+
</pre>
<p>A cell is a pair of 64-bit machine words, which traditionally are called CAR
and CDR in the Lisp terminology. These words can represent either a numeric
value (scalar) or the address of another cell (pointer). All higher level data
structures are built out of cells.
<p>The type information of higher level data is contained in the pointers to
these data. Assuming the implementation on a byte-addressed physical machine,
and the pointer size being 8 bytes, each cell has a size of 16 bytes. Therefore,
the pointer to a cell must point to a 16-byte boundary (a number which is a
multiple of 16), and its bit-representation will look like:
<pre>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0000
</pre>
<p>(the '<code>x</code>' means "don't care"). For the individual data types, the
pointer is adjusted to point to other parts of a cell, in effect setting some of
the lower four bits to non-zero values. These bits are then used by the
interpreter to determine the data type.
<p>In any case, bit(0) - the least significant of these bits - is reserved as a
mark bit for garbage collection.
<p>Initially, all cells in the memory are unused (free), and linked together to
form a "free list". To create higher level data types at runtime, cells are
taken from that free list, and returned by the garbage collector when they are
no longer needed. All memory management is done via that free list; there are no
additional buffers, string spaces or special memory areas, with two exceptions:
<p><ul>
<li>A certain fixed area of memory is set aside to contain the executable code
and global variables of the interpreter itself, and
<li>a standard push down stack for return addresses and temporary storage. Both
are not directly accessible by the programmer.
</ul>
<p><hr>
<h3><a id="data">Data Types</a></h3>
<p>On the virtual machine level, PicoLisp supports
<p><ul>
<li>three base data types: Numbers, Symbols and Cons Pairs (Lists),
<li>the three scope variations of symbols: Internal, Transient and External, and
<li>the special symbol <code>NIL</code>.
</ul>
<p>They are all built from the single cell data structure, and all runtime data
cannot consist of any other types than these three.
<p>The following diagram shows the complete data type hierarchy, consisting of
the three base types and the symbol variations:
<pre>
cell
|
+-----------+-----------+
| | |
Number Symbol Pair
|
|
+--------+-----------+-----------+
| | | |
NIL Internal Transient External
</pre>
<p><hr>
<h4><a id="number">Numbers</a></h4>
<p>A number can represent a signed integral value of arbitrary size. Internally,
numeric values of up to 60 bits are stored in "short" numbers,
<pre>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxS010
</pre>
i.e. the value is directly represented in the pointer, and doesn't take any heap
space.
<p>Numbers larger than that are "big" numbers, stored in heap cells. The CARs of
one or more cells hold the number's "digits" (64 bits each), with the least
significant digit first, while the CDRs point to the remaining digits.
<pre>
Bignum
|
V
+-----+-----+
| DIG | | |
+-----+--+--+
|
V
+-----+-----+
| DIG | | |
+-----+--+--+
|
V
+-----+-----+
| DIG | CNT |
+-----+-----+
</pre>
The CDR of the final cell holds the remaining bits in a short number.
<p>The pointer to a big number points into the middle of the CAR, with an offset
of 4 from the cell's start address, and the sign bit in bit(3):
<pre>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxS100
</pre>
<p>Thus, a number is recognized by the interpreter when either bit(1) is
non-zero (a short number) or bit(2) is non-zero (a big number).
<p><hr>
<h4><a id="symbol">Symbols</a></h4>
<p>A symbol is more complex than a number. Each symbol has a value, and
optionally a name and an arbitrary number of properties. The CDR of a symbol
cell is also called VAL, and the CAR points to the symbol's tail. As a minimum,
a symbol consists of a single cell, and has no name or properties:
<pre>
Symbol
|
V
+-----+-----+
| '0' | VAL |
+-----+-----+
</pre>
<p>That is, the symbol's tail is empty (<code>ZERO</code>, as indicated by
'<code>0</code>').
<p>The pointer to a symbol points to the CDR of the cell, with an offset of 8
bytes from the cell's start address. Therefore, the bit pattern of a symbol will
be:
<pre>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1000
</pre>
<p>Thus, a symbol is recognized by the interpreter when bit(3) is non-zero. (It
should also be understood that both bit(2) and bit(1) must be zero, thus
avoiding confusion with the number types.)
<p>A property is a key-value pair, represented by a cons pair in the symbol's
tail. This is called a "property list". The property list may be terminated by a
number (short or big) representing the symbol's name. In the following example,
a symbol with the name <code>"abcdefghijklmno"</code> has three properties: A
KEY/VAL pair, a cell with only a KEY, and another KEY/VAL pair.
<pre>
Symbol
|
V
+-----+-----+ +----------+---------+
| | | VAL | |'hgfedcba'|'onmlkji'|
+--+--+-----+ +----------+---------+
| tail ^
| |
V | name
+-----+-----+ +-----+-----+ +-----+--+--+
| | | ---+---> | KEY | ---+---> | | | | |
+--+--+-----+ +-----+-----+ +--+--+-----+
| |
V V
+-----+-----+ +-----+-----+
| VAL | KEY | | VAL | KEY |
+-----+-----+ +-----+-----+
</pre>
<p>Each property in a symbol's tail is either a symbol (like the single KEY
above, then it represents the boolean value <code>T</code>) or a cons pair with
the property key in its CDR and the property value in its CAR. In both cases,
the key should be a symbol, because searches in the property list are performed
using pointer comparisons.
<p>The name of a symbol is stored as a number at the end of the tail. It
contains the characters of the name in UTF-8 encoding, using between one and
seven bytes in a short number, or eight bytes in a bignum cell. The first byte
of the first character, for example, is stored in the lowest 8 bits of the
number.
<p>All symbols have the above structure, but depending on scope and
accessibility there are actually four types of symbols: <code><a
href="#nilSym">NIL</a></code>, <a href="#internal">internal</a>, <a
href="#transient">transient</a> and <a href="#external">external</a> symbols.
<p><hr>
<h5><a id="nilSym">NIL</a></h5>
<p><code>NIL</code> is a special symbol which exists exactly once in the whole
system. It is used
<p><ul>
<li>as an end-of-list marker
<li>to represent the empty list
<li>to represent the boolean value "false"
<li>to represent a string of length zero
<li>to represent the absolute minimum
<li>to represent end of file
<li>to represent standard in/out
<li>to represent the value "Not a Number"
<li>as the root of all class hierarchies
<li>as volatile property key
<li>as "no value"
</ul>
<p>For that, <code>NIL</code> has a special structure:
<pre>
NIL: /
|
V
+-----+-----+-----+-----+
|'LIN'| / | / | / |
+-----+-----+-----+-----+
</pre>
<p>The reason for that structure is <code>NIL</code>'s dual nature both as a
symbol and as a list:
<p><ul>
<li>As a symbol, it should give <code>NIL</code> for its VAL, and be without
properties
<li>For the empty list, <code>NIL</code> should give <code>NIL</code> both for
its CAR and for its CDR
</ul>
<p>These requirements are fulfilled by the above structure.
<p><hr>
<h5><a id="internal">Internal Symbols</a></h5>
<p>Internal symbols are all those "normal" symbols, as they are used for
function definitions and variable names. They are "interned" into an index
structure, so that it is possible to find an internal symbol by searching for
its name.
<p>There cannot be two different symbols with the same name in the same
<a href="ref.html#namespaces">namespace</a>.
<p>Initially, a new internal symbol's VAL is <code>NIL</code>.
<p><hr>
<h5><a id="transient">Transient Symbols</a></h5>
<p>Transient symbols are only interned into an index structure for a certain
time (e.g. while reading the current source file), and are released after that.
That means, a transient symbol cannot be accessed then by its name, and there
may be several transient symbols in the system having the same name.
<p>Transient symbols are used
<p><ul>
<li>as text strings
<li>as identifiers with a limited access scope (like, for example,
<code>static</code> identifiers in the C language family)
<li>as anonymous, dynamically created objects (without a name)
</ul>
<p>Initially, a new transient symbol's VAL is that symbol itself.
<p>A transient symbol without a name can be created with the <code><a
href="refB.html#box">box</a></code> or <code><a
href="refN.html#new">new</a></code> functions.
<p><hr>
<h5><a id="external">External Symbols</a></h5>
<p>External symbols reside in a database file (or other resources, see <code><a
href="refE.html#*Ext">*Ext</a></code>), and are loaded into memory - and written
back to the file - dynamically as needed, and transparently to the programmer.
They are kept in memory ("cached") as long as they are accessible ("referred
to") from other parts of the program, or when they were modified but not yet
written to the database file (by <code><a
href="refC.html#commit">commit</a></code>).
<p>The interpreter recognizes external symbols internally by an additional tag
bit in the tail structure.
<p>There cannot be two different external symbols with the same name. External
symbols are maintained in index structures while they are loaded into memory,
and have their external location (disk file and block offset) directly coded
into their names (more details <a href="#external-io">here</a>).
<p>Initially, a new external symbol's VAL is <code>NIL</code>, unless otherwise
specified at creation time.
<p><hr>
<h4><a id="lst">Lists</a></h4>
<p>A list is a sequence of one or more cells (cons pairs), holding numbers,
symbols, or cons pairs.
<pre>
|
V
+-----+-----+
| any | | |
+-----+--+--+
|
V
+-----+-----+
| any | | |
+-----+--+--+
|
V
...
</pre>
<p>Lists are used in PicoLisp to implement composite data structures like
arrays, trees, stacks or queues.
<p>In contrast to lists, numbers and symbols are collectively called "Atoms".
<p>Typically, the CDR of each cell in a list points to the following cell,
except for the last cell which points to <code>NIL</code>. If, however, the CDR of
the last cell points to an atom, that cell is called a "dotted pair" (because of
its I/O syntax with a dot '<code>.</code>' between the two values).
<p><hr>
<h3><a id="mem">Memory Management</a></h3>
<p>The PicoLisp interpreter has complete knowledge of all data in the system,
due to the type information associated with every pointer. Therefore, an
efficient garbage collector mechanism can easily be implemented. PicoLisp
employs a simple but fast mark-and-sweep garbage collector.
<p>As the collection process is very fast (in the order of milliseconds per
megabyte), it was not necessary to develop more complicated, time-consuming and
error-prone garbage collection algorithms (e.g. incremental collection). A
compacting garbage collector is also not necessary, because the single cell data
type cannot cause heap fragmentation.
<p><hr>
<h2><a id="penv">Programming Environment</a></h2>
<p>Lisp was chosen as the programming language, because of its clear and simple
structure.
<p>In some previous versions, a Forth-like syntax was also implemented on top of
a similar virtual machine (Lifo). Though that language was more flexible and
expressive, the traditional Lisp syntax proved easier to handle, and the virtual
machine can be kept considerably simpler.
PicoLisp inherits the major advantages of classical Lisp systems like
<p><ul>
<li>Dynamic data types and structures
<li>Formal equivalence of code and data
<li>Functional programming style
<li>An interactive environment
</ul>
<p>In the following, some concepts and peculiarities of the PicoLisp language
and environment are described.
<p><hr>
<h3><a id="inst">Installation</a></h3>
<p>PicoLisp supports two installation strategies: Local and Global.
<p>Normally, if you didn't build PicoLisp yourself but installed it with your
operating system's package manager, you will have a global installation. This
allows system-wide access to the executable and library/documentation files.
<p>To get a local installation, you can directly download the PicoLisp tarball,
and follow the instructions in the INSTALL file.
<p>A local installation will not interfere in any way with the world outside its
directory. There is no need to touch any system locations, and you don't have to
be root to install it. Many different versions - or local modifications - of
PicoLisp can co-exist on a single machine.
<p>Note that you are still free to have local installations along with a global
installation, and invoke them explicitly as desired.
<p>Most examples in the following apply to a global installation.
<p><hr>
<h3><a id="invoc">Invocation</a></h3>
<p>When PicoLisp is invoked from the command line, an arbitrary number of
arguments may follow the command name.
<p>By default, each argument is the name of a file to be executed by the
interpreter. If, however, the argument's first character is a hyphen
'<code>-</code>', then the rest of that argument is taken as a Lisp function
call (without the surrounding parentheses), and a hyphen by itself as an
argument stops evaluation of the rest of the command line (it may be processed
later using the <code><a href="refA.html#argv">argv</a></code> and <code><a
href="refO.html#opt">opt</a></code> functions). This whole mechanism corresponds
to calling <code>(<a href="refL.html#load">load</a> T)</code>.
<p>A special case is if the last argument is a single '<code>+</code>'. This
will switch on debug mode (the <code><a href="refD.html#*Dbg">*Dbg</a></code>
global variable) and discard the '<code>+</code>'. In that case, a file
"~/.pil/rc" (if it exists) will be <code><a
href="refL.html#load">load</a></code>ed, which can contain arbitrary statements
and definitions (e.g. to initialize the <code>readline(3)</code> <code><a
href="refH.html#history">history</a></code>).
<p>As a convention, PicoLisp source files have the extension "<code>.l</code>".
<p>Note that the PicoLisp executable itself does not expect or accept any
command line flags or options (except the '<code>+</code>', see above). They are
reserved for application programs.
<p>The simplest and shortest invocation of PicoLisp does nothing, and exits
immediately by calling <code><a href="refB.html#bye">bye</a></code>:
<pre>
$ picolisp -bye
$
</pre>
<p>In interactive mode, the PicoLisp interpreter (see <code><a
href="refL.html#load">load</a></code>) will also exit when <code>Ctrl-D</code>
is entered:
<pre>
$ picolisp
: # Typed Ctrl-D
$
</pre>
<p>To start up the standard PicoLisp environment, several files should be
loaded. The most commonly used things are in "lib.l" and in a bunch of other
files, which are in turn loaded by "ext.l". Thus, a typical call would be:
<pre>
$ picolisp lib.l ext.l
</pre>
<p>The recommended way, however, is to call the "pil" shell script, which
includes "lib.l" and "ext.l". Given that your current project is loaded by some
file "myProject.l" and your startup function is <code>main</code>, your
invocation would look like:
<pre>
$ pil myProject.l -main
</pre>
<p>For interactive development it is recommended to enable debugging mode, to
get <code>readline(3)</code> line history, single-stepping, tracing and other
debugging utilities.
<pre>
$ pil myProject.l -main +
</pre>
<p>This is - in a local installation - equivalent to
<pre>
$ ./pil myProject.l -main +
</pre>
<p>In any case, the directory part of the first file name supplied (normally,
the path to "lib.l" as called by 'pil') is remembered internally as the
<i>PicoLisp Home Directory</i>. This path is later automatically substituted for
any leading "<code>@</code>" character in file name arguments to I/O functions
(see <code><a href="refP.html#path">path</a></code>).
<p><hr>
<h3><a id="io">Input/Output</a></h3>
<p>In Lisp, each internal data structure has a well-defined external
representation in human-readable format. All kinds of data can be written to a
file, and restored later to their original form by reading that file.
<p>For all input functions besides <code><a href="refW.html#wr">wr</a></code>,
<code><a href="refR.html#rd">rd</a></code> and <code><a
href="refE.html#echo">echo</a></code> the input is assumed to be valid UTF-8,
consisting only of characters allowed in picolisp symbol names.
<p>In normal operation, the PicoLisp interpreter continually executes an
infinite "read-eval-print loop". It reads one expression at a time, evaluates
it, and prints the result to the console. Any input into the system, like data
structures and function definitions, is done in a consistent way no matter
whether it is entered at the console or read from a file.
<p>Comments can be embedded in the input stream with the hash <code>#</code>
character. Everything up to the end of that line will be ignored by the reader.
<pre>
: (* 1 2 3) # This is a comment
-> 6
</pre>
<p>A comment spanning several lines (a block comment) may be enclosed between
<code>#{</code> and <code>}#</code>. Block comments may be nested.
<p>Here is the I/O syntax for the individual PicoLisp data types (numbers,
symbols and lists) and for read-macros:
<p><hr>
<h4><a id="num-io">Numbers</a></h4>
<p>A number consists of an arbitrary number of digits ('<code>0</code>' through
'<code>9</code>'), optionally preceded by a sign character ('<code>+</code>' or
'<code>-</code>'). Legal number input is:
<pre>
: 7
-> 7
: -12345678901245678901234567890
-> -12345678901245678901234567890
</pre>
<p>Fixpoint numbers can be input by embedding a decimal point '<code>.</code>',
and setting the global variable <code><a href="refS.html#*Scl">*Scl</a></code>
appropriately:
<pre>
: *Scl
-> 0
: 123.45
-> 123
: 456.78
-> 457
: (setq *Scl 3)
-> 3
: 123.45
-> 123450
: 456.78
-> 456780
</pre>
<p>Thus, fixpoint input simply scales the number to an integer value
corresponding to the number of digits in <code><a
href="refS.html#*Scl">*Scl</a></code>.
<p>Formatted output of scaled fixpoint values can be done with the <code><a
href="refF.html#format">format</a></code> and <code><a
href="refR.html#round">round</a></code> functions:
<pre>
: (format 1234567890 2)
-> "12345678.90"
: (format 1234567890 2 "." ",")
-> "12,345,678.90"
</pre>
<p><hr>
<h4><a id="sym-io">Symbols</a></h4>
<p>The reader is able to recognize the individual symbol types from their
syntactic form. A symbol name should - of course - not look like a legal number
(see above).
<p>In general, symbol names are case-sensitive. <code>car</code> is not the same
as <code>CAR</code>.
<p><hr>
<h5><a id="nilSym-io">NIL</a></h5>
<p>Besides the standard form, <code>NIL</code> is also recognized as
<code>()</code>, <code>[]</code> or <code>""</code>.
<pre>
: NIL
-> NIL
: ()
-> NIL
: ""
-> NIL
</pre>
<p>Output will always appear as <code>NIL</code>.
<p><hr>
<h5><a id="internal-io">Internal Symbols</a></h5>
<p>Internal symbol names can consist of any printable (non-whitespace)
character, except for the following meta characters:
<pre>
" ' ( ) , [ ] ` { } ~
</pre>
<p>It is possible, though, to include these special characters into symbol names
by escaping them with a backslash '<code>\</code>'.
<p>The dot '<code>.</code>' has a dual nature. It is a meta character when
standing alone, denoting a <a href="#dotted">dotted pair</a>, but can otherwise
be used in symbol names.
<p>As a rule, anything not recognized by the reader as another data type will be
returned as an internal symbol.
<p><hr>
<h5><a id="transient-io">Transient Symbols</a></h5>
<p>A transient symbol is anything surrounded by double quotes '<code>"</code>'.
With that, it looks like - and can be used as - a string constant in other
languages. However, it is a real symbol, and may be assigned a value or a
function definition, and properties.
<p>Initially, a transient symbol's value is that symbol itself, so that it does
not need to be quoted for evaluation:
<pre>
: "This is a string"
-> "This is a string"
</pre>
<p>However, care must be taken when assigning a value to a transient symbol.
This may cause unexpected behavior:
<pre>
: (setq "This is a string" 12345)
-> 12345
: "This is a string"
-> 12345
</pre>
<p>The name of a transient symbol can contain any character except the
null-byte. Control characters can be written with a preceding hat
'<code>^</code>' character. A hat or a double quote character can be escaped
with a backslash '<code>\</code>', and a backslash itself has to be escaped with
another backslash.
<pre>
: "We^Ird\\Str\"ing"
-> "We^Ird\\Str\"ing"
: (chop @)
-> ("W" "e" "^I" "r" "d" "\\" "S" "t" "r" "\"" "i" "n" "g")
</pre>
<p>The combination of a backslash followed by 'b', 'e', 'n', 'r' or 't' is
replaced with backspace ("^H"), escape ("^["), newline ("^J"), return ("^M") or
TAB ("^I"), respectively.
<pre>
: "abc\tdef\r"
-> "abc^Idef^M"
</pre>
<p>A decimal number between two backslashes can be used to specify any unicode
character directly.
<pre>
: "äöü\8364\xyz"
-> "äöü€xyz"
</pre>
<p>A backslash in a transient symbol name at the end of a line discards the
newline, and continues the name in the next line. In that case, all leading
spaces and tabs in that line are discarded, to allow proper source code
indentation.
<pre>
: "abc\
def"
-> "abcdef"
: "x \
y \
z"
-> "x y z"
</pre>
<p>The index for transient symbols is local when <code><a
href="refL.html#load">load</a></code>ing a source file. With that mechanism, it
is possible to create symbols with a local access scope, not accessible from
other parts of the program.
<p>A special case of transient symbols are <i>anonymous symbols</i>. These are
symbols without name (see <code><a href="refB.html#box">box</a></code>, <code><a
href="refB.html#box?">box?</a></code> or <code><a
href="refN.html#new">new</a></code>). They print as a dollar sign
(<code>$</code>) followed by a decimal digit string (actually their machine
address).
<p><hr>
<h5><a id="external-io">External Symbols</a></h5>
<p>External symbol names are surrounded by braces ('<code>{</code>' and
'<code>}</code>'). The characters of the symbol's name itself identify the
physical location of the external object. This is the number of the database
file minus 1 in <code><a href="refH.html#hax">hax</a></code> notation (i.e.
hexadecimal/alpha notation, where '<code>@</code>' is zero, '<code>A</code>' is
1 and '<code>O</code>' is 15 (from "alpha" to "omega")), immediately followed
(without a hyphen) the starting block in octal ('<code>0</code>' through
'<code>7</code>').
<p>The database file is omitted for the first (default) file.
<p><hr>
<h4><a id="lst-io">Lists</a></h4>
<p>Lists are surrounded by parentheses ('<code>(</code>' and '<code>)</code>').
<p><code>(A)</code> is a list consisting of a single cell, with the symbol
<code>A</code> in its CAR, and <code>NIL</code> in its CDR.
<p><code>(A B C)</code> is a list consisting of three cells, with the symbols
<code>A</code>, <code>B</code> and <code>C</code> respectively in their CAR, and
<code>NIL</code> in the last cell's CDR.
<p><a id="dotted"><code>(A . B)</code></a> is a "dotted pair", a list
consisting of a single cell, with the symbol <code>A</code> in its CAR, and
<code>B</code> in its CDR.
<p>PicoLisp has built-in support for reading and printing simple circular lists.
If the dot in a dotted-pair notation is immediately followed by a closing
parenthesis, it indicates that the CDR of the last cell points back to the
beginning of that list.
<pre>
: (let L '(a b c) (conc L L))
-> (a b c .)
: (cdr '(a b c .))
-> (b c a .)
: (cddddr '(a b c .))
-> (b c a .)
</pre>
<p>A similar result can be achieved with the function <code><a
href="refC.html#circ">circ</a></code>. Such lists must be used with care,
because many functions won't terminate or will crash when given such a list.
<p><hr>
<h4><a id="macro-io">Read-Macros</a></h4>
<p>Read-macros in PicoLisp are special forms that are recognized by the reader,
and modify its behavior. Note that they take effect immediately while <code><a
href="refR.html#read">read</a></code>ing an expression, and are not seen by the
<code>eval</code> in the main loop.
<p>The most prominent read-macro in Lisp is the single quote character
"<code>'</code>", which expands to a call of the <code><a
href="refQ.html#quote">quote</a></code> function. Note that the single quote
character is also printed instead of the full function name.
<pre>
: '(a b c)
-> (a b c)
: '(quote . a)
-> 'a
: (cons 'quote 'a) # (quote . a)
-> 'a
: (list 'quote 'a) # (quote a)
-> '(a)
</pre>
<p>A comma (<code>,</code>) will cause the reader to collect the following data
item into an <code><a href="refI.html#idx">idx</a></code> tree in the global
variable <code><a href="refU.html#*Uni">*Uni</a></code>, and to return a
previously inserted equal item if present. This makes it possible to create a
unique list of references to data which do normally not follow the rules of
pointer equality. If the value of <code>*Uni</code> is <code>T</code>, the
comma read macro mechanism is disabled.
<p>A single backquote character "<code>`</code>" will cause the reader to
evaluate the following expression, and return the result.
<pre>
: '(a `(+ 1 2 3) z)
-> (a 6 z)
</pre>
<p>A tilde character <code>~</code> inside a list will cause the reader to
evaluate the following expression, and (destructively) splice the result into
the list.
<pre>
: '(a b c ~(list 'd 'e 'f) g h i)
-> (a b c d e f g h i)
</pre>
<p>When a tilde character is used to separate two symbol names (without
surrounding whitespace), the first is taken as a namespace to look up the
second.
<pre>
: 'libA~foo # Look up 'foo' in namespace 'libA'
-> libA~foo # "foo" is not interned in the current namespace
</pre>
<p>Reading <code>libA~foo</code> is equivalent to switching the current
namespace search order to <code>libA</code> <i>only</i> (with <code><a
href="refS.html#symbols">symbols</a></code>), reading the symbol
<code>foo</code>, and then switching back to the original search order.
<p><code>%~foo</code> temporarily switches the search order to the
<code>CDR</code> of the current namespace list.
<p>Brackets ('<code>[</code>' and '<code>]</code>') can be used as super
parentheses. A closing bracket will match the innermost opening bracket, or all
currently open parentheses.
<pre>
: '(a (b (c (d]
-> (a (b (c (d))))
: '(a (b [c (d]))
-> (a (b (c (d))))
</pre>
<p>Finally, reading the sequence '<code>{}</code>' will result in a new
anonymous symbol with value <code>NIL</code>, equivalent to a call to <code><a
href="refB.html#box">box</a></code> without arguments.
<pre>
: '({} {} {})
-> ($177066763035351 $177066763035353 $177066763035355)
: (mapcar val @)
-> (NIL NIL NIL)
</pre>
<p><hr>
<h3><a id="namespaces">Namespaces</a></h3>
<p>When the reader encounters an atom that is not a number, it looks for
it in the current namespace search order. If a symbol with that name is
found, it is used; otherwise, a new symbol is created and interned in
the current namespace.
<p>In general, namespaces in PicoLisp have nothing to do with the values
or definitions of symbols, but only with their scope (visibility).
Several symbols with the same name may exist in different namespaces,
and a single symbol may exist in one or many (or none at all)
namespaces.
<p>At interpreter startup, only the internal <code><a
href="refP.html#pico">pico</a></code> namespace exists, along with the
three special built-in namespaces for <a
href="#transient-io">transient</a>, <a href="#external-io">external</a>,
and <code><a href="refP.html#private">private</a></code> symbols.
<p>For internal symbols, it may not always be clear which namespace(s)
they belong to. Depending on the search order, the same name in a given
code segment might refer to different physical symbols. To avoid
ambiguity, it is recommended to follow these namespace policies:
<p><dl>
<dt>Invariant namespace order</dt>
<dd>Across different parts of a program and all loaded libraries the
search order may be changed as needed, but the position of each
namespace relative to other namespaces should stay the same. That is,
namespace A should not overshadow namespace B in one context and be
overshadowed by B in another context.
</dd>
<dt>Scope declaration before first usage</dt>
<dd>Calls to <code><a href="refS.html#symbols">symbols</a></code>,
<code><a href="refP.html#private">private</a></code>, <code><a
href="refL.html#local">local</a></code> or <code><a
href="refI.html#import">import</a></code> should precede any appearance
(not just definition!) of all involved symbols, because merely reading a
symbol may already intern it in the wrong namespace. </dd>
</dl>
<p><hr>
<h3><a id="ev">Evaluation</a></h3>
<p>PicoLisp tries to evaluate any expression encountered in the read-eval-print
loop. Basically, it does so by applying the following three rules:
<p><ul>
<li>A number evaluates to itself.
<li>A symbol evaluates to its value (VAL).
<li>A list is evaluated as a function call, with the CAR as the function and the
CDR the arguments to that function. These arguments are in turn evaluated
according to these three rules.
</ul>
<pre>
: 1234
-> 1234 # Number evaluates to itself
: *Pid
-> 22972 # Symbol evaluates to its VAL
: (+ 1 2 3)
-> 6 # List is evaluated as a function call
</pre>
<p>For the third rule, however, things get a bit more involved. First - as a
special case - if the CAR of the list is a number, the whole list is returned as
it is:
<pre>
: (1 2 3 4 5 6)
-> (1 2 3 4 5 6)
</pre>
<p>This is not really a function call, but just a convenience to avoid having to
quote simple data lists. The interpreter needs to check it anyway, and returning
the list (instead of throwing an error) is a lot faster than calling the
<code>quote</code> function.
<p>Otherwise, if the CAR is a symbol or a list, PicoLisp tries to obtain an
executable function from that, by either using the symbol's value, or by
evaluating the list.
<p>What is an executable function? Or, said in another way, what can be applied
to a list of arguments, to result in a function call? A legal function in
PicoLisp is
<p><dl>
<dt>either</dt>
<dd>a <i>number</i>. When a number is used as a function, it is simply taken as
a pointer to executable code that will be called with the list of (unevaluated)
arguments as its single parameter. It is up to that code to evaluate the
arguments, or not. Some functions do not e
gitextract_pc6i5ihr/ ├── COPYING ├── INSTALL ├── README ├── bin/ │ ├── pil │ ├── psh │ ├── pty │ ├── vip │ └── watchdog ├── doc/ │ ├── ChangeLog │ ├── Tracks │ ├── des.html │ ├── doc.css │ ├── faq.html │ ├── httpGate.html │ ├── man.html │ ├── microTemplates │ ├── native.html │ ├── rc.sample │ ├── ref.html │ ├── refA.html │ ├── refB.html │ ├── refC.html │ ├── refD.html │ ├── refE.html │ ├── refF.html │ ├── refG.html │ ├── refH.html │ ├── refI.html │ ├── refJ.html │ ├── refK.html │ ├── refL.html │ ├── refM.html │ ├── refN.html │ ├── refO.html │ ├── refP.html │ ├── refQ.html │ ├── refR.html │ ├── refS.html │ ├── refT.html │ ├── refU.html │ ├── refV.html │ ├── refW.html │ ├── refX.html │ ├── refY.html │ ├── refZ.html │ ├── ref_.html │ ├── search │ ├── search.html │ ├── select.html │ ├── structures │ ├── tut.html │ └── viprc.sample ├── ext.l ├── lib/ │ ├── adm.l │ ├── app.l │ ├── bash_completion │ ├── btree.l │ ├── canvas.js │ ├── canvas.l │ ├── clang.l │ ├── complete.l │ ├── db.l │ ├── dbgc.l │ ├── debug.l │ ├── form.js │ ├── form.l │ ├── frac.l │ ├── gis.js │ ├── gis.l │ ├── heartbeat.l │ ├── http.l │ ├── json.l │ ├── lint.l │ ├── map │ ├── math.l │ ├── misc.l │ ├── net.l │ ├── pilog.l │ ├── plio.js │ ├── replica.l │ ├── role.l │ ├── select.l │ ├── simul.l │ ├── sq.l │ ├── svg.l │ ├── term.l │ ├── test.l │ ├── too.l │ ├── ulimit.l │ ├── user.l │ ├── vip/ │ │ ├── cal.rc.l │ │ ├── draw.l │ │ ├── html.l │ │ └── load.l │ ├── vip.l │ ├── xhtml/ │ │ ├── area │ │ ├── field │ │ ├── grid │ │ ├── html │ │ ├── input │ │ ├── layout │ │ ├── menu │ │ ├── select │ │ ├── submit │ │ ├── tab │ │ └── table │ ├── xhtml.l │ ├── xm.l │ └── xxhash.l ├── lib.css ├── lib.l ├── loc/ │ ├── AE.l │ ├── AR.l │ ├── CH.l │ ├── CKB.l │ ├── CN.l │ ├── DE.l │ ├── ES.l │ ├── FR.l │ ├── GB.l │ ├── GR.l │ ├── HR.l │ ├── IT.l │ ├── JP.l │ ├── NIL.l │ ├── NO.l │ ├── RU.l │ ├── SE.l │ ├── TR.l │ ├── UA.l │ ├── US.l │ ├── ar │ ├── ca │ ├── ch │ ├── ckb │ ├── cn │ ├── de │ ├── el │ ├── es │ ├── fr │ ├── hr │ ├── it │ ├── ja │ ├── no │ ├── ru │ ├── sv │ ├── tr │ └── uk ├── man/ │ └── man1/ │ ├── picolisp.1 │ └── pil.1 ├── misc/ │ ├── bigtest │ └── stress.l ├── pil ├── soTest.c ├── src/ │ ├── Makefile │ ├── Makefile.macos │ ├── Makefile.openbsd │ ├── apply.l │ ├── balance.c │ ├── base.ll │ ├── big.l │ ├── db.l │ ├── dec.l │ ├── defs.l │ ├── ext.l │ ├── ext.ll │ ├── flow.l │ ├── gc.l │ ├── glob.l │ ├── ht.l │ ├── ht.ll │ ├── httpGate.c │ ├── io.l │ ├── lib/ │ │ ├── ex.l │ │ ├── llvm.l │ │ └── so.l │ ├── lib.c │ ├── lib.so.c │ ├── main.l │ ├── pico.h │ ├── ssl.c │ ├── subr.l │ ├── sym.l │ ├── sysdefs.c │ └── vers.l ├── test/ │ ├── lib/ │ │ ├── db.l │ │ ├── lint.l │ │ ├── math.l │ │ └── misc.l │ ├── lib.l │ └── src/ │ ├── apply.l │ ├── big.l │ ├── db.l │ ├── ext.l │ ├── flow.l │ ├── ht.l │ ├── io.l │ ├── main.l │ ├── net.l │ ├── subr.l │ └── sym.l └── vip
SYMBOL INDEX (211 symbols across 12 files)
FILE: lib/canvas.js
function renderCanvas (line 3) | function renderCanvas(cvs, lst) {
function drawCanvas (line 182) | function drawCanvas(id, dly) {
function doCsDn (line 227) | function doCsDn(cvs, x, y) {
function csMouseDn (line 237) | function csMouseDn(cvs, event) {
function csTouchDn (line 241) | function csTouchDn(cvs, event) {
function doCsMv (line 245) | function doCsMv(cvs, x, y) {
function csMouseMv (line 266) | function csMouseMv(cvs, event) {
function csTouchMv (line 270) | function csTouchMv(cvs, event) {
function csMouseUp (line 278) | function csMouseUp(cvs) {
function csTouchEnd (line 296) | function csTouchEnd(cvs) {
function csLeave (line 303) | function csLeave(cvs) {
function csCursor (line 313) | function csCursor(cvs, x, y) {
FILE: lib/form.js
function inBtn (line 6) | function inBtn(btn,flg) {InBtn = flg;}
function formKey (line 8) | function formKey(event) {
function fldChg (line 27) | function fldChg(field) {
function doBtn (line 36) | function doBtn(btn) {
function doDrag (line 41) | function doDrag(event) {
function doDrop (line 46) | function doDrop(btn, event) {
function dropProgress (line 55) | function dropProgress(event) {
function dropLoad (line 61) | function dropLoad(event) {
function hasElement (line 65) | function hasElement(form, name) {
function setHref (line 72) | function setHref(fld, url) {
function idFocus (line 82) | function idFocus(fld) {
function setCheck (line 90) | function setCheck(fld, val) {
function doPost (line 99) | function doPost(form) {
function post (line 108) | function post(form, auto, exe, file) {
function doHint (line 352) | function doHint(field) {
function hintKey (line 381) | function hintKey(field, event, tok, coy) {
function addHint (line 469) | function addHint(i, field, str) {
function setHint (line 496) | function setHint(field, item) {
function hintOn (line 508) | function hintOn(i) {
function hintOff (line 514) | function hintOff(i) {
function tblTouch (line 523) | function tblTouch(event) {
function tblMove (line 531) | function tblMove(table, event) {
function lisp (line 553) | function lisp(form, fun) {
function lispVal (line 584) | function lispVal(x) {
function ping (line 592) | function ping(min) {
function ping1 (line 597) | function ping1(min) {
FILE: lib/gis.js
function osm (line 6) | function osm(id, lat, lon, zoom, click) {
function poi (line 59) | function poi(lat, lon, img, x, y, txt, dy, col, url, drag) {
function line (line 95) | function line(col, lat1, lon1, lat2, lon2) {
FILE: lib/plio.js
function plio (line 3) | function plio(lst) {
FILE: soTest.c
function main (line 13) | int main(int ac, char *av[]) {
FILE: src/balance.c
function giveup (line 16) | static void giveup(char *msg) {
function balance (line 39) | static void balance(char **data, int len) {
function main (line 52) | int main(int ac, char *av[]) {
FILE: src/httpGate.c
type name (line 26) | typedef struct name {
function giveup (line 53) | static void giveup(char *msg) {
function readNames (line 58) | static int readNames(void) {
function freeNames (line 127) | static void freeNames(name *np) {
function name (line 146) | static name *findName(char *p, char *q) {
function slow (line 165) | static int slow(SSL *ssl, int fd, char *p, int cnt) {
function rdLine (line 174) | static int rdLine(SSL *ssl, int fd, char *p, int cnt) {
function wrBytes (line 193) | static void wrBytes(int fd, char *p, int cnt) {
function sslWrite (line 204) | static void sslWrite(SSL *ssl, void *p, int cnt) {
function setDH (line 209) | static bool setDH(SSL_CTX *ctx) {
function gatePort (line 221) | static int gatePort(unsigned short port) {
function gateConnect (line 246) | static int gateConnect(int port, name *np) {
function doSigAlarm (line 314) | static void doSigAlarm(int n __attribute__((unused))) {
function doSigUsr1 (line 321) | static void doSigUsr1(int n __attribute__((unused))) {
function doSigHup (line 325) | static void doSigHup(int n __attribute__((unused))) {
function iSignal (line 329) | static void iSignal(int n, void (*foo)(int)) {
function main (line 338) | int main(int ac, char *av[]) {
FILE: src/lib.c
function gPrintf (line 16) | void gPrintf(char *buf, int32_t siz, char *fmt, char *arg) {
function openRd (line 25) | int32_t openRd(char *nm) {
function openWr (line 29) | int32_t openWr(char *nm) {
function openRdWr (line 33) | int32_t openRdWr(char *nm) {
function openRdWrExcl (line 37) | int32_t openRdWrExcl(char *nm) {
function openRdWrCreate (line 41) | int32_t openRdWrCreate(char *nm) {
function openRdWrAppend (line 45) | int32_t openRdWrAppend(char *nm) {
function openWrAppend (line 49) | int32_t openWrAppend(char *nm) {
function fseekOfs (line 53) | int fseekOfs(FILE *fp, int32_t ofs) {
function fseek0 (line 57) | int fseek0(FILE *fp) {
function seek0 (line 61) | int seek0(int32_t fd) {
function truncate0 (line 65) | int truncate0(int32_t fd) {
function socketPair (line 69) | int32_t socketPair(int32_t *sv) {
function fcntlCloExec (line 73) | int32_t fcntlCloExec(int32_t fd) {
function fcntlSetFl (line 77) | void fcntlSetFl(int32_t fd, int32_t flg) {
function nonBlocking (line 81) | int32_t nonBlocking(int32_t fd) {
function fcntlSetOwn (line 88) | void fcntlSetOwn(int32_t fd, int32_t pid) {
type dirent (line 95) | struct dirent
function initReadline (line 116) | void initReadline(void) {
function rlHide (line 136) | void rlHide(void) {
function rlShow (line 143) | void rlShow(void) {
function rlSigBeg (line 148) | void rlSigBeg(void) {
function rlSigEnd (line 156) | void rlSigEnd(void) {
function gSignal (line 179) | int32_t gSignal(int32_t n) {
function iSignal (line 200) | void iSignal(int32_t n, void (*fun)(int)) {
function sigUnblock (line 209) | void sigUnblock(int32_t sig) {
function sigChld (line 221) | void sigChld(int n __attribute__((unused))) {
function waitWuntraced (line 232) | int32_t waitWuntraced(int32_t pid, int32_t *res) {
function wifStopped (line 236) | int32_t wifStopped(int32_t *res) {
function nErrno (line 240) | int32_t nErrno(void) {
function gErrno (line 245) | int32_t gErrno(void) {
type termios (line 260) | struct termios
type termios (line 261) | struct termios
function tcSet (line 263) | static void tcSet(struct termios *p) {
function stopTerm (line 267) | void stopTerm(void) {
function setRaw (line 280) | void setRaw(void) {
function setCooked (line 292) | void setCooked(void) {
function reopenTty (line 299) | int reopenTty(char* tty) {
type timeval (line 307) | struct timeval
type tm (line 308) | struct tm
function getUsec (line 310) | int64_t getUsec(int flg) {
function getMsec (line 321) | int64_t getMsec(void) {
function getDate (line 329) | int64_t getDate(void) {
function getGmDate (line 336) | int64_t getGmDate(void) {
function getTime (line 343) | int64_t getTime(void) {
function getGmTime (line 352) | int64_t getGmTime(void) {
type rlimit (line 357) | struct rlimit
function fileInfo (line 367) | int64_t fileInfo(int lnk, int loc, char *nm, int64_t *siz) {
function pollIn (line 386) | void pollIn(int32_t fd, struct pollfd *p) {
function pollOut (line 391) | void pollOut(int32_t fd, struct pollfd *p) {
function pollIgn (line 396) | void pollIgn(struct pollfd *p) {
function gPoll (line 400) | int32_t gPoll(struct pollfd *fds, int32_t nfds, int64_t timeout) {
function readyIn (line 436) | int readyIn(struct pollfd *p) {
function readyOut (line 443) | int readyOut(struct pollfd *p) {
function rdLock (line 451) | int32_t rdLock(int32_t fd, off_t n, off_t len, int wait) {
function wrLock (line 461) | int32_t wrLock(int32_t fd, off_t n, off_t len, int wait) {
function unLock (line 471) | int32_t unLock(int32_t fd, off_t n, off_t len) {
function getLock (line 481) | int32_t getLock(int32_t fd, off_t n, off_t len) {
function any (line 499) | any name(any x) {
function any (line 505) | any number(any x) {
function any (line 510) | any length(any x) {
function any (line 518) | any box64(any x) {
function boxFloat (line 534) | uint64_t boxFloat(uint32_t value, int64_t scl) {
function boxFlt (line 552) | uint64_t boxFlt(void) {
function boxDouble (line 560) | uint64_t boxDouble(uint64_t value, int64_t scl) {
function boxDbl (line 578) | uint64_t boxDbl(void) {
function bufFloat (line 586) | void bufFloat(uint64_t value, int64_t scl, float *p) {
function bufDouble (line 602) | void bufDouble(uint64_t value, int64_t scl, double *p) {
type ffi (line 624) | typedef struct ffi {
function ffi (line 634) | ffi *ffiPrep(char *lib, char *fun, uint64_t lst) {
function ffiCall (line 679) | uint64_t ffiCall(ffi *p, uint64_t lst) {
function chance (line 745) | int chance(int64_t m) {
function charType (line 1277) | static inline int32_t charType(int32_t c) {return Data[Blocks[c>>5]+c & ...
function isLowc (line 1279) | int isLowc(int32_t c) {
function isUppc (line 1285) | int isUppc(int32_t c) {
function isLetterOrDigit (line 1291) | int isLetterOrDigit(int32_t c) {
function toUpperCase (line 1297) | int32_t toUpperCase(int32_t c) {
function toLowerCase (line 1303) | int32_t toLowerCase(int32_t c) {
FILE: src/lib.so.c
function gPrintf (line 16) | void gPrintf(char *buf, int32_t siz, char *fmt, char *arg) {
function openRd (line 25) | int32_t openRd(char *nm) {
function openWr (line 29) | int32_t openWr(char *nm) {
function openRdWr (line 33) | int32_t openRdWr(char *nm) {
function openRdWrExcl (line 37) | int32_t openRdWrExcl(char *nm) {
function openRdWrCreate (line 41) | int32_t openRdWrCreate(char *nm) {
function openRdWrAppend (line 45) | int32_t openRdWrAppend(char *nm) {
function openWrAppend (line 49) | int32_t openWrAppend(char *nm) {
function fseekOfs (line 53) | int fseekOfs(FILE *fp, int32_t ofs) {
function fseek0 (line 57) | int fseek0(FILE *fp) {
function seek0 (line 61) | int seek0(int32_t fd) {
function truncate0 (line 65) | int truncate0(int32_t fd) {
function socketPair (line 69) | int32_t socketPair(int32_t *sv) {
function fcntlCloExec (line 73) | int32_t fcntlCloExec(int32_t fd) {
function fcntlSetFl (line 77) | void fcntlSetFl(int32_t fd, int32_t flg) {
function nonBlocking (line 81) | int32_t nonBlocking(int32_t fd) {
function fcntlSetOwn (line 88) | void fcntlSetOwn(int32_t fd, int32_t pid) {
type dirent (line 95) | struct dirent
function waitWuntraced (line 114) | int32_t waitWuntraced(int32_t pid, int32_t *res) {
function wifStopped (line 118) | int32_t wifStopped(int32_t *res) {
function nErrno (line 122) | int32_t nErrno(void) {
function gErrno (line 127) | int32_t gErrno(void) {
type termios (line 142) | struct termios
type termios (line 143) | struct termios
function tcSet (line 145) | static void tcSet(struct termios *p) {
function stopTerm (line 149) | void stopTerm(void) {
function setRaw (line 160) | void setRaw(void) {
function setCooked (line 172) | void setCooked(void) {
function reopenTty (line 179) | int reopenTty(char* tty) {
type timeval (line 187) | struct timeval
type tm (line 188) | struct tm
function getUsec (line 190) | int64_t getUsec(int flg) {
function getMsec (line 201) | int64_t getMsec(void) {
function getDate (line 209) | int64_t getDate(void) {
function getGmDate (line 216) | int64_t getGmDate(void) {
function getTime (line 223) | int64_t getTime(void) {
function getGmTime (line 232) | int64_t getGmTime(void) {
type rlimit (line 237) | struct rlimit
function fileInfo (line 247) | int64_t fileInfo(int lnk, int loc, char *nm, int64_t *siz) {
function pollIn (line 266) | void pollIn(int32_t fd, struct pollfd *p) {
function pollOut (line 271) | void pollOut(int32_t fd, struct pollfd *p) {
function pollIgn (line 276) | void pollIgn(struct pollfd *p) {
function gPoll (line 280) | int32_t gPoll(struct pollfd *fds, int32_t nfds, int64_t timeout) {
function readyIn (line 316) | int readyIn(struct pollfd *p) {
function readyOut (line 323) | int readyOut(struct pollfd *p) {
function rdLock (line 331) | int32_t rdLock(int32_t fd, off_t n, off_t len, int wait) {
function wrLock (line 341) | int32_t wrLock(int32_t fd, off_t n, off_t len, int wait) {
function unLock (line 351) | int32_t unLock(int32_t fd, off_t n, off_t len) {
function getLock (line 361) | int32_t getLock(int32_t fd, off_t n, off_t len) {
function chance (line 387) | int chance(int64_t m) {
function charType (line 919) | static inline int32_t charType(int32_t c) {return Data[Blocks[c>>5]+c & ...
function isLowc (line 921) | int isLowc(int32_t c) {
function isUppc (line 927) | int isUppc(int32_t c) {
function isLetterOrDigit (line 933) | int isLetterOrDigit(int32_t c) {
function toUpperCase (line 939) | int32_t toUpperCase(int32_t c) {
function toLowerCase (line 945) | int32_t toLowerCase(int32_t c) {
FILE: src/pico.h
type any (line 28) | typedef uint64_t any;
FILE: src/ssl.c
function giveup (line 36) | static void giveup(char *msg) {
function sslConnect (line 42) | static int sslConnect(SSL *ssl, char *node, char *service) {
function sslClose (line 85) | static void sslClose(SSL *ssl, int sd) {
function sslFile (line 91) | static bool sslFile(SSL *ssl, char *file) {
function off_t (line 111) | static off_t lockFile(int fd) {
function doSigTerm (line 128) | static void doSigTerm(int n __attribute__((unused))) {
function iSigTerm (line 135) | static void iSigTerm(int n) {
function main (line 146) | int main(int ac, char *av[]) {
FILE: src/sysdefs.c
function ttl (line 29) | static void ttl(char *nm) {
function num (line 33) | static void num(char *sym, long val) {
function lit (line 37) | static void lit(char *sym, char *val) {
function str (line 41) | static void str(char *sym, char *val) {
function main (line 45) | int main(void) {
Condensed preview — 202 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,173K chars).
[
{
"path": "COPYING",
"chars": 1078,
"preview": "PicoLisp Copyright (c) Software Lab. Alexander Burger\n\nPermission is hereby granted, free of charge, to any person obtai"
},
{
"path": "INSTALL",
"chars": 3322,
"preview": "# 23jan26 Software Lab. Alexander Burger\n\n\n PicoLisp Installation\n =====================\n\n\nPicoLisp need"
},
{
"path": "README",
"chars": 4169,
"preview": "# 05nov25 Software Lab. Alexander Burger\n\n Perfection is attained\n "
},
{
"path": "bin/pil",
"chars": 142,
"preview": "#!/usr/bin/picolisp /usr/lib/picolisp/lib.l\n(load \"@lib/net.l\" \"@lib/misc.l\" \"@lib/btree.l\" \"@lib/db.l\" \"@lib/pilog.l\")\n"
},
{
"path": "bin/psh",
"chars": 397,
"preview": "#!/usr/bin/pil\n# 06aug24 Software Lab. Alexander Burger\n\n(load \"@lib/net.l\" \"@lib/misc.l\" \"@lib/http.l\")\n\n(let Arg (opt)"
},
{
"path": "bin/pty",
"chars": 1372,
"preview": "#!/usr/bin/pil\n# 05jul24abu\n# Pseudo Terminal (PilBox)\n# pty [host] [flg]\n\n(load \"@lib/term.l\")\n\n(setq\n *Host (or (opt"
},
{
"path": "bin/vip",
"chars": 847,
"preview": "#!/usr/bin/picolisp /usr/lib/picolisp/lib.l\n# 30apr26abu\n\n(unless *Dbg\n (load \"@lib/vip.l\") )\n\n(stack 1024)\n\n(bye\n ("
},
{
"path": "bin/watchdog",
"chars": 2341,
"preview": "#!/usr/bin/pil\n# 13apr23 Software Lab. Alexander Burger\n# Use: bin/watchdog <host> <port> <from> <to1> <to2> ..\n\n(load \""
},
{
"path": "doc/ChangeLog",
"chars": 63318,
"preview": "26.4.30\n Re-introduce 'any' (for '+<ns~sym>' arguments)\n bin/vip\n\n26.4.24\n Check 'format' before 'get' (Bruno)\n"
},
{
"path": "doc/Tracks",
"chars": 766,
"preview": "# VIP @lib/vip/draw.l\n# 25may23 Software Lab. Alexander Burger\n\n(label 1 1 \"Connectors:\")\n\n(cells 7 6 '(| | | . |))\n(go "
},
{
"path": "doc/des.html",
"chars": 9169,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 29jul25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/doc.css",
"chars": 483,
"preview": "/* 22oct23 Software Lab. Alexander Burger\n * 06dec12jk\n */\n\nhtml {\n background-color: #ddd;\n}\n\nbody {\n margin: auto;"
},
{
"path": "doc/faq.html",
"chars": 31048,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 08may24 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/httpGate.html",
"chars": 8014,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 03jan26 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/man.html",
"chars": 4597,
"preview": "Content-type: text/html; charset=UTF-8\n\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<HTML><HEAD><TIT"
},
{
"path": "doc/microTemplates",
"chars": 1928,
"preview": " Micro-Templates\n\n* Each template file in the @lib/xhtml/ directory applies to one type of\n component in the @l"
},
{
"path": "doc/native.html",
"chars": 26112,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 19jan26 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/rc.sample",
"chars": 554,
"preview": "# 20nov24 Software Lab. Alexander Burger\n# Copy to ~/.pil/rc\n\n(history\n (make\n (skip \"#\")\n (while (line T) ("
},
{
"path": "doc/ref.html",
"chars": 105623,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 04apr26 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refA.html",
"chars": 22718,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 05jul25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refB.html",
"chars": 16884,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 30may25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refC.html",
"chars": 31210,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 02jan26 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refD.html",
"chars": 30477,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 30may25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refE.html",
"chars": 20025,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 27aug25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refF.html",
"chars": 23824,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 21mar26 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refG.html",
"chars": 6762,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 04jun25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refH.html",
"chars": 10458,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 30may25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refI.html",
"chars": 19095,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 05dec25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refJ.html",
"chars": 2738,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 26oct23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refK.html",
"chars": 3050,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 26oct23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refL.html",
"chars": 21354,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 02dec24 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refM.html",
"chars": 23661,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 21may25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refN.html",
"chars": 16569,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 27sep25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refO.html",
"chars": 11297,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 26oct23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refP.html",
"chars": 34733,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 29mar26 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refQ.html",
"chars": 3064,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 04dec23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refR.html",
"chars": 30027,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 09sep25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refS.html",
"chars": 42370,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 05dec25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refT.html",
"chars": 25594,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 09dec25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refU.html",
"chars": 13602,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 26oct23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refV.html",
"chars": 5546,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 30may25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refW.html",
"chars": 7629,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 09dec25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refX.html",
"chars": 1300,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 26oct23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refY.html",
"chars": 2621,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 10oct25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/refZ.html",
"chars": 3166,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 26oct23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/ref_.html",
"chars": 19787,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 20aug25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/search",
"chars": 1567,
"preview": "Search criteria\n Numbers\n 3\n (3 . 4)\n Strings\n \"abc\"\n (\"a\" . \"z\")\n Objects\n {2}\n Symbol"
},
{
"path": "doc/search.html",
"chars": 13026,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 13dec25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/select.html",
"chars": 18270,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 30may25 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/structures",
"chars": 7429,
"preview": "# 09jul24 Software Lab. Alexander Burger\n\n ### Primary data types ###\n\n cnt xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"path": "doc/tut.html",
"chars": 34400,
"preview": "<!--\n# VIP @lib/vip/html.l\n# 26oct23 Software Lab. Alexander Burger\n-->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta h"
},
{
"path": "doc/viprc.sample",
"chars": 2430,
"preview": "# 21dec25 Software Lab. Alexander Burger\n# Copy to ~/.pil/viprc\n\n## Uncomment to enable the \":cal\" (calendar) command\n##"
},
{
"path": "ext.l",
"chars": 140,
"preview": "# 27oct20 Software Lab. Alexander Burger\n\n(load \"@lib/net.l\" \"@lib/misc.l\" \"@lib/btree.l\" \"@lib/db.l\" \"@lib/pilog.l\")\n\n`"
},
{
"path": "lib/adm.l",
"chars": 4091,
"preview": "# 30dec24 Software Lab. Alexander Burger\n\n# *Salt *Login *Users *Perms\n\n# crypt(3) algorithm, e.g. (setq *Salt (16 . \"$6"
},
{
"path": "lib/app.l",
"chars": 1291,
"preview": "# 13apr23 Software Lab. Alexander Burger\n\n# Exit on error\n(de *Err\n (prinl *Pid \" ! \" (stamp) \" [\" *Adr \" \" (host *Adr"
},
{
"path": "lib/bash_completion",
"chars": 476,
"preview": "# Bash completion for picolisp + pil\n# Alexander Burger <abu@software-lab.de>\n\n_pil()\n{\n local -a ARGS\n local IFS="
},
{
"path": "lib/btree.l",
"chars": 16376,
"preview": "# 13apr25 Software Lab. Alexander Burger\n\n# *Prune\n\n(private) (_store _put _splitBt _del)\n\n(de root (Tree)\n (cond\n "
},
{
"path": "lib/canvas.js",
"chars": 9831,
"preview": "/* 21jan25 Software Lab. Alexander Burger */\n\nfunction renderCanvas(cvs, lst) {\n var ctx = cvs.getContext(\"2d\");\n va"
},
{
"path": "lib/canvas.l",
"chars": 2559,
"preview": "# 19sep23 Software Lab. Alexander Burger\n\n(allow \"!jsDraw\" )\n(push1 '*JS (allow \"@lib/plio.js\") (allow \"@lib/canvas.js\")"
},
{
"path": "lib/clang.l",
"chars": 399,
"preview": "# 19may21 Software Lab. Alexander Burger\n\n(de clang (Nm L . Lst)\n (out (tmp Nm \".c\") (here \"/**/\"))\n (apply call L \""
},
{
"path": "lib/complete.l",
"chars": 922,
"preview": "# 29dec20 Software Lab. Alexander Burger\n\n(if (opt)\n (let \"Lst\" (chop @)\n (if (= \"-\" (car \"Lst\"))\n (let \""
},
{
"path": "lib/db.l",
"chars": 50877,
"preview": "# 12apr26 Software Lab. Alexander Burger\n\n# *Jnl *Blob\n\n### Tree Access ###\n(de tree (Var Cls Hook)\n (cons Var\n ("
},
{
"path": "lib/dbgc.l",
"chars": 1489,
"preview": "# 04jun23 Software Lab. Alexander Burger\n\n### DB Garbage Collection ###\n\n(private) (markData markExt)\n\n(de markExt (S)\n "
},
{
"path": "lib/debug.l",
"chars": 12045,
"preview": "# 05nov25 Software Lab. Alexander Burger\n\n# Prompt\n(de *Prompt\n (casq (car (symbols)) (pico) (T @)) )\n\n(private) (_who"
},
{
"path": "lib/form.js",
"chars": 17670,
"preview": "/* 13mar25 Software Lab. Alexander Burger */\n\nvar Btn = [];\nvar SesId, Key, InBtn, Auto, Chg, Post, Drop, Hint, Hints, I"
},
{
"path": "lib/form.l",
"chars": 62205,
"preview": "# 20feb26 Software Lab. Alexander Burger\n\n# *PRG *Top *Gui *Btn *Get *Got *Form *FormIx *FormLst *Evt\n# *Lock *Spans *Al"
},
{
"path": "lib/frac.l",
"chars": 1681,
"preview": "# 22jul25 Software Lab. Alexander Burger\n\n(symbols 'frac 'pico)\n\n(local) (gcd lcm f)\n\n(de gcd (A B)\n (tco (A B)\n "
},
{
"path": "lib/gis.js",
"chars": 3283,
"preview": "/* 22nov21 Software Lab. Alexander Burger */\n\nvar Map;\nvar Sources;\n\nfunction osm(id, lat, lon, zoom, click) {\n Map = "
},
{
"path": "lib/gis.l",
"chars": 3951,
"preview": "# 09jul22 Software Lab. Alexander Burger\n\n(symbols 'gis 'pico)\n\n(push1 '*JS (allow \"@lib/gis.js\"))\n\n(local) (lat lon fmt"
},
{
"path": "lib/heartbeat.l",
"chars": 442,
"preview": "# 13apr23 Software Lab. Alexander Burger\n\n(ifn (info \"fifo/beat\")\n (de heartbeat ())\n\n (de heartbeat @\n (unless"
},
{
"path": "lib/http.l",
"chars": 15547,
"preview": "# 30nov25 Software Lab. Alexander Burger\n\n# *HPorts *Home *Gate *Host *Port *Port1 *Port% *Http1 *Chunked\n# *Sock *Agent"
},
{
"path": "lib/json.l",
"chars": 3676,
"preview": "# 01feb25 Software Lab. Alexander Burger\n\n(de checkJson (X Item)\n (unless (= X Item)\n (quit \"Bad JSON\" Item) ) )\n"
},
{
"path": "lib/lint.l",
"chars": 8772,
"preview": "# 13feb25 Software Lab. Alexander Burger\n\n# *NoLint\n\n(private) (global? local? dlsym? lint1 lint2 lintVar lintDup lintLo"
},
{
"path": "lib/map",
"chars": 67419,
"preview": "llvm~$ (268 \"@src/lib/llvm.l\" llvm pico)\nllvm~$AV (6 \"@src/glob.l\" llvm pico)\nllvm~$AV0 (5 \"@src/glob.l\" llvm pico)\nllvm"
},
{
"path": "lib/math.l",
"chars": 901,
"preview": "# 14sep20 Software Lab. Alexander Burger\n\n(and (=0 *Scl) (scl 6)) # Default scale 6\n\n(setq "
},
{
"path": "lib/misc.l",
"chars": 15194,
"preview": "# 01jan26 Software Lab. Alexander Burger\n\n# *Allow\n\n(de *Day . (Mon Tue Wed Thu Fri Sat Sun .))\n(de *Mon . (Jan Feb Mar "
},
{
"path": "lib/net.l",
"chars": 6810,
"preview": "# 13jun24 Software Lab. Alexander Burger\n\n(sysdefs \"errno\")\n(sysdefs \"networking\")\n\n(private) (ipErr Var)\n\n(de ipErr (Ms"
},
{
"path": "lib/pilog.l",
"chars": 3901,
"preview": "# 05apr26 Software Lab. Alexander Burger\n\n(private) (CL Q R L Prg)\n\n(de be CL\n (clause CL) )\n\n(de clause (CL)\n (with"
},
{
"path": "lib/plio.js",
"chars": 1581,
"preview": "/* 22nov21 Software Lab. Alexander Burger */\n\nfunction plio(lst) {\n var NIX = 0;\n var BEG = 1;\n var DOT = 2;\n va"
},
{
"path": "lib/replica.l",
"chars": 1361,
"preview": "# 17oct20 Software Lab. Alexander Burger\n\n# <path>/bin/picolisp <path>/lib.l @lib/replica.l <port|num> <keyFile> <journa"
},
{
"path": "lib/role.l",
"chars": 802,
"preview": "# 18jul19 Software Lab. Alexander Burger\n\n(must \"Role Administration\" RoleAdmin)\n\n(menu ,\"Role Administration\"\n (idFor"
},
{
"path": "lib/select.l",
"chars": 12226,
"preview": "# 30may25 Software Lab. Alexander Burger\n\n# Deprecated Pilog DB Predicates\n# Use 'search' instead\n\n(de initQuery (Var Cl"
},
{
"path": "lib/simul.l",
"chars": 13151,
"preview": "# 09dec25 Software Lab. Alexander Burger\n\n(symbols 'simul 'pico)\n\n(local) (subsets shuffle samples)\n(import pico~permute"
},
{
"path": "lib/sq.l",
"chars": 2032,
"preview": "# 09dec25 Software Lab. Alexander Burger\n\n# (select [var ..] cls [hook] [var val ..])\n(de select Lst\n (let\n (Vars"
},
{
"path": "lib/svg.l",
"chars": 9869,
"preview": "# 10mar24 Software Lab. Alexander Burger\n\n(symbols 'svg 'pico)\n\n(local) (*A4-DX *A4-DY *StrokeWidth *FontSize *FontFamil"
},
{
"path": "lib/term.l",
"chars": 1826,
"preview": "# 29aug23 Software Lab. Alexander Burger\n\n(sysdefs \"terminal\")\n\n(local) (ULINE U-OFF REVERS)\n\n(de ULINE . \"4\")\n(de U-OFF"
},
{
"path": "lib/test.l",
"chars": 624,
"preview": "# 04jul21 Software Lab. Alexander Burger\n\n### Unit Tests ###\n# Local usage:\n# ./pil lib/test.l -bye +\n\n# Global usage:\n#"
},
{
"path": "lib/too.l",
"chars": 14795,
"preview": "# 27oct23 Software Lab. Alexander Burger\n\n(private) (Prg C Q X Y Cls Name)\n\n(de admin Prg\n (out 2\n (prinl *Pid \" "
},
{
"path": "lib/ulimit.l",
"chars": 948,
"preview": "# 27aug25 Software Lab. Alexander Burger\n\n(symbols 'ulimit 'pico)\n\n(local) (RLIMIT_STACK RLIMIT_NOFILE RLIMIT_NPROC stac"
},
{
"path": "lib/user.l",
"chars": 721,
"preview": "# 18oct21 Software Lab. Alexander Burger\n\n(must \"User Administration\" UserAdmin (== *Login *ID))\n\n(menu ,\"User Administr"
},
{
"path": "lib/vip/cal.rc.l",
"chars": 7716,
"preview": "# 26mar26 Software Lab. Alexander Burger\n\n(symbols '(pico)\n (load \"@lib/misc.l\") )\n\n(private) (*Cal *Pat slot entry ca"
},
{
"path": "lib/vip/draw.l",
"chars": 9045,
"preview": "# 19oct23 Software Lab. Alexander Burger\n\n(symbols 'vip~draw 'vip 'pico)\n\n(local) (*DX *DY *PX *PY *Draw *Boxes)\n\n(zero "
},
{
"path": "lib/vip/html.l",
"chars": 567,
"preview": "# 29oct23 Software Lab. Alexander Burger\n\n# View HTML buffers\n(let? *Class (isa '+Buffer This)\n (dm view> (Win)\n "
},
{
"path": "lib/vip/load.l",
"chars": 358,
"preview": "# 10dec24 Software Lab. Alexander Burger\n\n# View output of 'load'ing the file\n(let? *Class (isa '+Buffer This)\n (dm vi"
},
{
"path": "lib/vip.l",
"chars": 67382,
"preview": "# 11dec25 Software Lab. Alexander Burger\n\n(symbols 'vip 'pico)\n\n(sysdefs \"unistd\")\n\n(load \"@lib/term.l\")\n\n(local) (*Ns *"
},
{
"path": "lib/xhtml/area",
"chars": 73,
"preview": "<textarea wrap=\"off\" cols=\"¦COLS¦\" rows=\"¦ROWS¦\"¦(run PRG)¦>\n</textarea>\n"
},
{
"path": "lib/xhtml/field",
"chars": 34,
"preview": "<input type=\"¦TYPE¦\"¦(run PRG)¦/>\n"
},
{
"path": "lib/xhtml/grid",
"chars": 86,
"preview": "<table class=\"grid\">\n<tr>\n<td¦(and ATTR (htStyle @))¦>¦(run PRG)¦</td>\n</tr>\n</table>\n"
},
{
"path": "lib/xhtml/html",
"chars": 183,
"preview": "<!DOCTYPE html>\n<html lang=\"¦LANG¦\">\n<head>\n <meta name=\"viewport\" content=\"width=device-width\"/>\n ¦(run PRG)¦</head"
},
{
"path": "lib/xhtml/input",
"chars": 34,
"preview": "<input type=\"¦TYPE¦\"¦(run PRG)¦/>\n"
},
{
"path": "lib/xhtml/layout",
"chars": 0,
"preview": ""
},
{
"path": "lib/xhtml/menu",
"chars": 392,
"preview": "<>\n<ul>\n<li>¦(run PRG)¦</li>\n<li class=\"cmd\">¦(run PRG)¦</li>\n<li class=\"cmd\"><a href=\"¦(prin LINK)¦\" title=\"-->\">¦(r"
},
{
"path": "lib/xhtml/select",
"chars": 124,
"preview": "<select¦(run PRG)¦>\n<option¦(and ATTR (htStyle @))¦ title=\"¦TITLE¦\"¦(eval (car PRG))¦>¦(run (cdr PRG))¦</option>\n</selec"
},
{
"path": "lib/xhtml/submit",
"chars": 34,
"preview": "<input type=\"¦TYPE¦\"¦(run PRG)¦/>\n"
},
{
"path": "lib/xhtml/tab",
"chars": 132,
"preview": "<table class=\"tab\"><tr>\n<td class=\"top\">¦(run PRG)¦</td>\n<td class=\"sub\"><a href=\"¦(prin LINK)¦\">¦(run PRG)¦</a></td>\n</"
},
{
"path": "lib/xhtml/table",
"chars": 184,
"preview": "<table¦(and ATTR (htStyle @))¦>\n<caption>¦(run PRG)¦</caption>\n<tr>\n<th¦(and ATTR (htStyle @))¦>¦(run PRG)¦</th>\n</tr>\n<"
},
{
"path": "lib/xhtml.l",
"chars": 26386,
"preview": "# 11mar25 Software Lab. Alexander Burger\n\n(de xhtml (Path)\n (for X\n (quote\n (\"html\" . *XhtmlHtml)\n "
},
{
"path": "lib/xm.l",
"chars": 3565,
"preview": "# 07jun25 Software Lab. Alexander Burger\n\n(local) (xml? xml body attr)\n(private) (_xml xmlEsc escXml)\n\n# Check or write "
},
{
"path": "lib/xxhash.l",
"chars": 393,
"preview": "# 02nov25 Software Lab. Alexander Burger\n\n(default *Xxh64\n (native \"libxxhash.so\" \"XXH64_createState\" 'P) )\n\n(de xxh64"
},
{
"path": "lib.css",
"chars": 5498,
"preview": "/* 22nov21 Software Lab. Alexander Burger */\n\n/* Lib */\n.left {float: left}\n.right {float: right}\n.nofloat {float: none}"
},
{
"path": "lib.l",
"chars": 17282,
"preview": "# 27aug25 Software Lab. Alexander Burger\n\n(de task (Key . Prg)\n (nond\n (Prg (del (assoc Key *Run) '*Run))\n ("
},
{
"path": "loc/AE.l",
"chars": 317,
"preview": "(setq\n *Sep0 \".\"\n *Sep3 \",\"\n *CtryCode \"971\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@Y \"-\" @M \"-\" @D)\n *DayFmt '(\""
},
{
"path": "loc/AR.l",
"chars": 315,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \".\"\n *CtryCode \"54\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@D \"-\" @M \"-\" @Y)\n *DayFmt '(\"L"
},
{
"path": "loc/CH.l",
"chars": 316,
"preview": "(setq\n *Sep0 \".\"\n *Sep3 \"'\"\n *CtryCode \"41\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@D \".\" @M \".\" @Y)\n *DayFmt '(\"M"
},
{
"path": "loc/CKB.l",
"chars": 342,
"preview": "(setq\n *Sep0 \".\"\n *Sep3 \",\"\n *CtryCode \"964\"\n *NatTrunkPrf '(\"0\" \"0\")\n *DateFmt '(@Y \"/\" @M \"/\" @D)\n *DayFmt"
},
{
"path": "loc/CN.l",
"chars": 20,
"preview": "(load \"@loc/NIL.l\")\n"
},
{
"path": "loc/DE.l",
"chars": 316,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \".\"\n *CtryCode \"49\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@D \".\" @M \".\" @Y)\n *DayFmt '(\"M"
},
{
"path": "loc/ES.l",
"chars": 311,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \".\"\n *CtryCode \"34\"\n *NatTrunkPrf NIL\n *DateFmt '(@D \"/\" @M \"/\" @Y)\n *DayFmt '(\"Lune"
},
{
"path": "loc/FR.l",
"chars": 310,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \".\"\n *CtryCode \"33\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@D \"/\" @M \"/\" @Y)\n *DayFmt '(\"L"
},
{
"path": "loc/GB.l",
"chars": 316,
"preview": "(setq\n *Sep0 \".\"\n *Sep3 \",\"\n *CtryCode \"44\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@D \"/\" @M \"/\" @Y)\n *DayFmt '(\"M"
},
{
"path": "loc/GR.l",
"chars": 340,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \".\"\n *CtryCode \"30\"\n *NatTrunkPrf NIL\n *DateFmt '(@D \"/\" @M \"/\" @Y)\n *DayFmt '(\"Δευτ"
},
{
"path": "loc/HR.l",
"chars": 20,
"preview": "(load \"@loc/NIL.l\")\n"
},
{
"path": "loc/IT.l",
"chars": 20,
"preview": "(load \"@loc/NIL.l\")\n"
},
{
"path": "loc/JP.l",
"chars": 239,
"preview": "(setq\n *Sep0 \".\"\n *Sep3 \",\"\n *CtryCode \"81\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@Y \"/\" @M \"/\" @D)\n *DayFmt '(\"月"
},
{
"path": "loc/NIL.l",
"chars": 330,
"preview": "(setq # Default locale\n *Sep0 \".\"\n *Sep3 \",\"\n *CtryCode NIL\n *NatTrunkPrf NIL\n *DateFmt '(@Y \"-\" @M \"-\" @D)\n "
},
{
"path": "loc/NO.l",
"chars": 304,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \".\"\n *CtryCode \"47\"\n *NatTrunkPrf NIL\n *DateFmt '(@D \".\" @M \".\" @Y)\n *DayFmt '(\"mand"
},
{
"path": "loc/RU.l",
"chars": 314,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \" \"\n *CtryCode \"7\"\n *NatTrunkPrf '(\"8\")\n *DateFmt '(@D \".\" @M \".\" @Y)\n *DayFmt '(\"По"
},
{
"path": "loc/SE.l",
"chars": 309,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \" \"\n *CtryCode \"46\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@D \".\" @M \".\" @Y)\n *DayFmt '(\"M"
},
{
"path": "loc/TR.l",
"chars": 20,
"preview": "(load \"@loc/NIL.l\")\n"
},
{
"path": "loc/UA.l",
"chars": 325,
"preview": "(setq\n *Sep0 \",\"\n *Sep3 \" \"\n *CtryCode \"380\"\n *NatTrunkPrf '(\"0\")\n *DateFmt '(@D \".\" @M \".\" @Y)\n *DayFmt '(\""
},
{
"path": "loc/US.l",
"chars": 315,
"preview": "(setq\n *Sep0 \".\"\n *Sep3 \",\"\n *CtryCode \"1\"\n *NatTrunkPrf '(\"1\")\n *DateFmt '(@M \"/\" @D \"/\" @Y)\n *DayFmt '(\"Mo"
},
{
"path": "loc/ar",
"chars": 54,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\nT \"@loc/es\"\n"
},
{
"path": "loc/ca",
"chars": 2923,
"preview": "# 28aug17abu\n# Arnau Figueras\n\n\"Language\" \"Idioma\"\n\n# lib/db.l\n\"Boolean input expected\" \"S'espera l'ingrés de dades tipu"
},
{
"path": "loc/ch",
"chars": 54,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\nT \"@loc/de\"\n"
},
{
"path": "loc/ckb",
"chars": 2832,
"preview": "# 10jan22\n# Hunar Omar <hbkurd@gmail.com>\n\n\"Language\" \"زمان\"\n\n# lib/db.l\n\"Boolean input expected\" \"چاوەڕوانی تێچەی ڕاست "
},
{
"path": "loc/cn",
"chars": 42,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\n"
},
{
"path": "loc/de",
"chars": 2961,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\n\"Language\" \"Sprache\"\n\n# lib/db.l\n\"Boolean input expected\" \"Boolean-Type erwart"
},
{
"path": "loc/el",
"chars": 2922,
"preview": "# 23aug2016\n# Drakopoulos A. <anasdrak@gmail.com>\n\n\"Language\" \"Γλώσσα\"\n\n# lib/db.l\n\"Boolean input expected\" \"Αναμένονται"
},
{
"path": "loc/es",
"chars": 2995,
"preview": "# 28aug17abu\n# Armadillo <tc.rucho@gmail.com>\n# Manuel Cano <manutalcual@gmail.com>\n\n\"Language\" \"Idioma\"\n\n# lib/db.l\n\"Bo"
},
{
"path": "loc/fr",
"chars": 2983,
"preview": "# 28aug17abu\n# Raman Gopalan <ramangopalan@gmail.com>\n\n\"Language\" \"Langue\"\n\n# lib/db.l\n\"Boolean input expected\" \"Type bo"
},
{
"path": "loc/hr",
"chars": 42,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\n"
},
{
"path": "loc/it",
"chars": 42,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\n"
},
{
"path": "loc/ja",
"chars": 2172,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\n\"Language\" \"言語\"\n\n# lib/db.l\n\"Boolean input expected\" \"Booleanタイプが必要\"\n\"Numeric "
},
{
"path": "loc/no",
"chars": 2755,
"preview": "# 28aug17abu\n# Jon Kleiser <jon.kleiser@usit.uio.no>\n\n\"Language\" \"Språk\"\n\n# lib/db.l\n\"Boolean input expected\" \"Boolsk ve"
},
{
"path": "loc/ru",
"chars": 2984,
"preview": "# 17mar21abu\n# Mansur Mamkin <mmamkin@mail.ru>\n# Mike Pechkin <mike.pechkin@gmail.com>\n# Constantine Bytensky <kostya3@g"
},
{
"path": "loc/sv",
"chars": 2648,
"preview": "# 28aug17abu\n# Mattias Sundblad <mattias.sun@gmail.com>\n\n\"Language\" \"Språk\"\n\n# lib/db.l\n\"Boolean input expected\" \"Boolsk"
},
{
"path": "loc/tr",
"chars": 42,
"preview": "# 22nov21 Software Lab. Alexander Burger\n\n"
},
{
"path": "loc/uk",
"chars": 2915,
"preview": "# 17mar21abu\n# Constantine Bytensky <kostya3@gmail.com>\n\n\"Language\" \"Мова\"\n\n# lib/db.l\n\"Boolean input expected\" \"Очікуєт"
},
{
"path": "man/man1/picolisp.1",
"chars": 3034,
"preview": ".\\\" 26oct20abu\n.\\\"\n.TH PICOLISP 1 \"\" \"\" \"User Commands\"\n.SH NAME\npil, picolisp \\- a fast, lightweight Lisp interpreter\n."
},
{
"path": "man/man1/pil.1",
"chars": 20,
"preview": ".so man1/picolisp.1\n"
},
{
"path": "misc/bigtest",
"chars": 2581,
"preview": "#!bin/picolisp lib.l\n# 26may22abu\n# misc/bigtest <seed>\n\n(load \"@lib/misc.l\")\n\n(seed (car (argv)))\n\n# Random patterns:\n"
},
{
"path": "misc/stress.l",
"chars": 1472,
"preview": "# 18oct20 Software Lab. Alexander Burger\n# Use: nice pil misc/stress.l -main -go -bye; rm db/test jnl db/test2\n\n(load \"@"
},
{
"path": "pil",
"chars": 62,
"preview": "#!/bin/sh\nexec ${0%/*}/bin/picolisp ${0%/*}/lib.l @ext.l \"$@\"\n"
},
{
"path": "soTest.c",
"chars": 1077,
"preview": "/* 17sep25 Software Lab. Alexander Burger\n * $ cc -o soTest soTest.c lib/picolisp.so lib/ext.so lib/ht.so\n */\n\n#include "
},
{
"path": "src/Makefile",
"chars": 2918,
"preview": "# 13mar26 Software Lab. Alexander Burger\n\n.SILENT:\n\nCC = clang\nPIL = ../pil\nASM = opt -O2\nLLC = llc\nLINK = llvm-link\nSHA"
},
{
"path": "src/Makefile.macos",
"chars": 2501,
"preview": "# 23jan26\n\nHOMEBREW_PREFIX ?= /opt/homebrew\nCC ?= clang\n\nPIL = ../pil # pil\nASM = opt -O2 # llvm-as\nLLC = llc\nLINK = l"
},
{
"path": "src/Makefile.openbsd",
"chars": 2316,
"preview": "# 29mar24 Software Lab. Alexander Burger\n\n#.SILENT:\n\nCC = clang-19\nPIL = ../pil # pil\nASM = opt-19 -O3 # llvm-as\nLLC ="
},
{
"path": "src/apply.l",
"chars": 21784,
"preview": "# 09sep25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n# (apply 'fun 'lst ['any ..]) -> any\n(de _Apply (Exe)\n (l"
},
{
"path": "src/balance.c",
"chars": 2056,
"preview": "/* balance.c\n * 06jul05abu\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <string.h>\n#include "
},
{
"path": "src/base.ll",
"chars": 4588241,
"preview": "source_filename = \"base.l\"\n\ndeclare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64)\ndeclare {i64, i1} @llvm.usub.with.o"
},
{
"path": "src/big.l",
"chars": 53431,
"preview": "# 01sep25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (pos neg divErr)\n\n(inline pos (N)\n (any (& N -9))"
},
{
"path": "src/db.l",
"chars": 49483,
"preview": "# 27aug25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (dbfErr dbRdErr dbWrErr jnlErr dbSyncErr)\n\n(de NIL "
},
{
"path": "src/dec.l",
"chars": 13262,
"preview": "# 10nov25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (inFile outFile ioFrame ioxFrame ctFrame dbFile)\n\n#"
},
{
"path": "src/defs.l",
"chars": 1820,
"preview": "# 28sep20 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n# Constants\n(local) (HEAP CELLS STACK TOP BUFSIZ DB1)\n\n(equ"
},
{
"path": "src/ext.l",
"chars": 7572,
"preview": "# 09jul24 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(begin \"ext\" T\n \"vers.l\" \"defs.l\" \"glob.l\" \"dec.l\" )\n\n(lo"
},
{
"path": "src/ext.ll",
"chars": 43546,
"preview": "source_filename = \"ext.l\"\n\ndeclare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64)\ndeclare {i64, i1} @llvm.usub.with.ov"
},
{
"path": "src/flow.l",
"chars": 59247,
"preview": "# 09dec25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (redefMsg putSrc redefine)\n\n(de void redefMsg (Sym "
},
{
"path": "src/gc.l",
"chars": 13903,
"preview": "# 28aug25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (mark gc need3)\n\n(de void mark (E)\n (let Tos 0 #"
},
{
"path": "src/glob.l",
"chars": 19568,
"preview": "# 17mar26 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(var $AV0 i8* null) # Command name\n(var "
},
{
"path": "src/ht.l",
"chars": 10989,
"preview": "# 15jul24 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(begin \"ht\" T\n \"vers.l\" \"defs.l\" \"glob.l\" \"dec.l\" )\n\n(loc"
},
{
"path": "src/ht.ll",
"chars": 84048,
"preview": "source_filename = \"ht.l\"\n\ndeclare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64)\ndeclare {i64, i1} @llvm.usub.with.ove"
},
{
"path": "src/httpGate.c",
"chars": 14525,
"preview": "// 06nov25 Software Lab. Alexander Burger\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <fcntl.h>"
},
{
"path": "src/io.l",
"chars": 97546,
"preview": "# 17mar26 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (openErr closeErr pipeErr sizeErr eofErr badInput b"
},
{
"path": "src/lib/ex.l",
"chars": 119,
"preview": "# 10sep25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(exclude\n picolisp\n evaluate\n reflect\n stoplisp )\n"
},
{
"path": "src/lib/llvm.l",
"chars": 51966,
"preview": "# 05oct25 Software Lab. Alexander Burger\n\n### PicoLisp LLVM frontend ###\n(zap 'llvm) (symbols 'llvm 'pico)\n\n(local) (*Qu"
},
{
"path": "src/lib/so.l",
"chars": 699,
"preview": "# 15sep25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n#{\n For the \"full\" library\n -- In Makefile\n * Remo"
},
{
"path": "src/lib.c",
"chars": 81731,
"preview": "// 10nov25 Software Lab. Alexander Burger\n\n#include \"pico.h\"\n\nconst char TgOS[] = _OS;\nconst char TgCPU[] = _CPU;\n\n// I/"
},
{
"path": "src/lib.so.c",
"chars": 73176,
"preview": "// 05sep25 Software Lab. Alexander Burger\n\n#include \"pico.h\"\n\nconst char TgOS[] = _OS;\nconst char TgCPU[] = _CPU;\n\n// I/"
},
{
"path": "src/main.l",
"chars": 64129,
"preview": "# 27mar26 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(begin \"base\" NIL\n \"vers.l\" \"defs.l\" \"glob.l\" \"dec.l\" )\n\n"
},
{
"path": "src/pico.h",
"chars": 1503,
"preview": "// 27sep25 Software Lab. Alexander Burger\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n#include <unistd."
},
{
"path": "src/ssl.c",
"chars": 11383,
"preview": "// 09nov22 Software Lab. Alexander Burger\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <fcntl.h>"
},
{
"path": "src/subr.l",
"chars": 54980,
"preview": "# 31mar26 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (chkA chkD makeErr)\n\n(inline chkA (X)\n (car (need"
},
{
"path": "src/sym.l",
"chars": 63123,
"preview": "# 27aug25 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) (bufSize pathSize bufString pathString)\n\n(de i64 bu"
},
{
"path": "src/sysdefs.c",
"chars": 4023,
"preview": "// 12jan26 Software Lab. Alexander Burger\n\n#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <unistd.h"
},
{
"path": "src/vers.l",
"chars": 106,
"preview": "# 30apr26 Software Lab. Alexander Burger\n\n(symbols '(llvm))\n\n(local) *Version\n\n(pico~de *Version 26 4 30)\n"
},
{
"path": "test/lib/db.l",
"chars": 2214,
"preview": "# 21aug22 Software Lab. Alexander Burger\n\n### +Joint ###\n(test T (pool (tmp \"db\")))\n\n(class +A +Entity)\n(rel k (+Key +St"
},
{
"path": "test/lib/lint.l",
"chars": 429,
"preview": "# 06oct20 Software Lab. Alexander Burger\n\n### noLint ###\n(let foo '(() (bar FreeVariable))\n (use *NoLint\n (noLint"
},
{
"path": "test/lib/math.l",
"chars": 613,
"preview": "# 06oct20 Software Lab. Alexander Burger\n\n(scl 6)\n(load \"@lib/math.l\")\n\n### pow ###\n(test 8.0 (pow 2.0 3.0))\n(test 8.0 ("
},
{
"path": "test/lib/misc.l",
"chars": 4528,
"preview": "# 01jan26 Software Lab. Alexander Burger\n\n### locale ###\n(locale \"DE\" \"de\")\n(test \"Ja\" (val ,\"Yes\"))\n(locale)\n\n\n### alig"
},
{
"path": "test/lib.l",
"chars": 3723,
"preview": "# 23may25 Software Lab. Alexander Burger\n\n### task ###\n(test (3 . 4)\n (let (*Run NIL *A NIL *B NIL)\n (task -10 "
},
{
"path": "test/src/apply.l",
"chars": 3302,
"preview": "# 01may22 Software Lab. Alexander Burger\n\n### apply ###\n(test 6 (apply + (1 2 3)))\n(test 360 (apply * (5 6) 3 4))\n(test "
},
{
"path": "test/src/big.l",
"chars": 3751,
"preview": "# 27jul25 Software Lab. Alexander Burger\n\n### format ###\n(scl 0)\n(test \"123456789\" (format 123456789))\n(test \"12346\" (fo"
},
{
"path": "test/src/db.l",
"chars": 1110,
"preview": "# 21aug22 Software Lab. Alexander Burger\n\n(test T (pool (tmp \"db\") (2 3)))\n\n### extern ###\n(test NIL (extern (box)))\n(te"
},
{
"path": "test/src/ext.l",
"chars": 1333,
"preview": "# 03apr23 Software Lab. Alexander Burger\n\n### ext:Snx ###\n(test \"PSLSFSNTSNNLSF\"\n (ext:Snx \"PicoLisp is not Common Lis"
},
{
"path": "test/src/flow.l",
"chars": 9001,
"preview": "# 09feb25 Software Lab. Alexander Burger\n\n### quote ###\n(test (1 2 3) (quote 1 2 3))\n\n\n### as ###\n(test NIL (as (= 3 4) "
},
{
"path": "test/src/ht.l",
"chars": 1119,
"preview": "# 06oct20 Software Lab. Alexander Burger\n\n### ht:Prin ###\n(test \"1<2>3&äöü<i>ÄÖÜß\"\n (pipe (ht:Prin \"1<"
},
{
"path": "test/src/io.l",
"chars": 5069,
"preview": "# 26may22 Software Lab. Alexander Burger\n\n### path ###\n(test 'task (cadr (in (path \"@lib.l\") (read))))\n(test (char \"+\") "
},
{
"path": "test/src/main.l",
"chars": 4256,
"preview": "# 13dec23 Software Lab. Alexander Burger\n\n### Evaluation ###\n(test 2\n (when 1\n ('((N) N) (and 2))\n @ ) )\n\n##"
},
{
"path": "test/src/net.l",
"chars": 548,
"preview": "# 06oct20 Software Lab. Alexander Burger\n\n### port listen connect ###\n(test '(a b c)\n (let P (port 0 \"ListenPort\")\n "
},
{
"path": "test/src/subr.l",
"chars": 14120,
"preview": "# 21may25 Software Lab. Alexander Burger\n\n### c[ad]*r ###\n(let L '(1 2 3 4 5)\n (test 1 (car L))\n (test (2 3 4 5) (cd"
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the picolisp/pil21 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 202 files (6.6 MB), approximately 1.7M tokens, and a symbol index with 211 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.