A LISP interpreter written only with TeX macros. It works as a style file of LaTeX. LISP on TeX adopts static scoping, dynamic typing, and eager evaluation. We can program easily with LISP on TeX.
To use LISP on TeX, you should include the lisp-on-tex
package.
\usepackage{lisp-on-tex}
If you do it, you can write LISP codes as a argument of \lispinterp
.
\lispintrep{
(\some \LISP 'codes')
% example
(\define (\sum \a \b) (\+ \a \b))
}
In LISP on TeX, a symbol is a control sequence; a string is tokens surrounded by quotation marks; and an integer is a TeX's integer using colon prefix.
Put all files into your TEXMF tree.
Option Name | Meaning |
---|---|
noGC |
Never using GC (default) |
markGC |
Using Mark-Sweep GC |
GCopt=... |
Passing option to the GC engine |
Currently, LISP on TeX supports Mark-Sweep GC.
If you want to use it, you should use markGC
option.
You can also control heap size by using GCopt={heapsize=n}
where n
is greater than 3000. The default heap size is 32768.
For example, the code
\usepackage[markGC, GCopt={heapsize=5000}]{lisp-on-tex}
shows that LISP on TeX uses Mark-Sweep GC and the heap size is 5000.
Kinds | Literals | Examples |
---|---|---|
CONS Cell | ( obj ... . obj ) , ( obj ... ) |
(\+ :1 :2) |
Integer | : TeX's integer |
:42 , :"3A |
String | ' TeX's balanced tokens ' |
'\foo{bar}baz' |
Symbol | TeX's control sequence | \cs |
Boolean | /t or /f |
|
Nil | () |
|
Skip | @ TeX's skip |
@12pt plus 34cm |
Dimen | ! TeX's dimen |
!56pt |
\define
: Define a symbol.
% symbol form
(\define \foo :42) % ()
\foo % :42
% function form
(\define (\foo \n) (\* \n :2))
(\foo :3) % :6
\defineM
: Define a mutable symbol.
\setB
: Rewrite a mutable symbol.
% symbol form
(\defineM \foo :42) % ()
\foo % :42
(\setB \foo 'bar')
\foo % 'bar'
\defmacro
: Define a macro.
\macroexpand
: Expand a macro
(\defmacro (\foo \x) (\list (\quote \bar) \x \x \x)) % ()
(\macroexpand (\quote (\foo :1))) % (\bar :1 :1 :1)
\lambda
: Create a function.
% normal form
((\lambda (\x) (\+ \x :2)) :3) % :5
% list form
((\lambda \x \x) :1 :2) % (:1 :2)
% remain argument form
((\lambda (\x . \y) \y) :1 :2 :3) % (:2 :3)
\let
: Define local symbols.
(\define \x 'foo')
(\let ((\x :4) (\y :3)) (\+ \x \y)) % :7
\x % 'foo'
\letM
: Define mutable local symbols.
(\letM ((\x 'foo'))
(\begin (\setB \x 'bar') \x)) % 'bar'
\letrec
: Define local symbols recursively.
(\letrec
((\oddQ (\lambda (\n)
(\lispif (\= \n :0) /f (\evenQ (\- \n :1)))))
(\evenQ (\lambda (\n)
(\lispif (\= \n :0) /t (\oddQ (\- \n :1))))))
(\oddQ :42)) % /f
\lispif
: Branch.
(\lispif /t 'true' 'false') % 'true'
(\lispif /f 'true' 'false') % 'false'
\begin
: Execute expressions.
(\letM ((\x :1)) (\begin (\setB \s 'foo') \x))
% 'foo'
\callOCC
: One-shot continuation.
(\defineM \x 'unchanged')
(\callOCC (\lambda (\c)
(\begin (\c '\foo ')
(\setB \x 'changed')))) % '\foo '
\x % 'unchanged'
(\callOCC (\lambda (\c) :42)) % :42
\concat
: Concatenate tokens.
(\concat '$' '\foo ' '{bar}' '$') % '$\foo {bar}$'
\intTOstring
: Convert a integer to TeX's tokens.
(\intTOstring :42) % '42'
\stringTOint
: Convert a string to integer
(\stringTOint '42') % :42
\group
: Grouping.
(\group '\some {tokens}') % '{\some {tokens}}'
\ungroup
: Ungrouping.
(\ungroup '{\some {tokens}}') % '\some {tokens}'
\expand
: Expand tokens.
\newcommand\foo[1]{I got #1!}
\lispinterp{
(\expand '\foo{Foo}') % 'I got Foo!'
}
\+
: Addition.
(\+) % :0
(\+ :1 :2) % :3
(\+ :3 :4 :5) % :12
\-
: Subtraction.
(\- :1) % :-1
(\- :3 :2) % :1
(\- :3 :2 :1) % :0
\*
: Multiplication.
(\*) % :1
(\* :2 :3) % :6
(\* :3 :4 :5) % :60
\/
: Division.
(\/ 2) % :0 (1/2 -> 0)
(\/ 7 2) % :3
\mod
: Modulo.
(\mod :42 :23) % :19
(\mod :3 :2) % :1
(\mod :3 :-2) % :1
(\mod :-3 :2) % :-1
(\mod :-3 :-2) % :-1
\>
, \<
, \geq
, \leq
: Comparison.
(\> :3 :2) % /t
(\< :2 :3) % /t
(\geq :3 :2) % /t
(\geq :3 :3) % /t
(\leq :2 :3) % /t
(\leq :3 :3) % /t
Some predicates.
(\isZeroQ :0) % /t
(\positiveQ :42) % /t
(\negativeQ :-2) % /t
\max
: Maximum.
(\max :-10 :-5 :0 :5 :10) % :10
\min
: Minimum.
(\min :-10 :-5 :0 :5 :10) % :-10
\and
, \or
, \not
: Logical and, or, not
(\and /t /t) % /t
(\and /t /f) % /f
(\or /t /t) % /t
(\or /t /f) % /t
(\not /t) % /f
\quote
: Quote.
(\quote :42) % :42
(\quote (\+ :1 :2)) % (\+ :1 :2)
\cons
, \car
, \cdr
: CONS, CAR, CDR
(\cons :42 'foo') % (:42 . 'foo')
(\car (\quote (:1 :2))) % :1
(\cdr (\quote (:1 :2))) % (:2)
\list
: Create a list
(\list :1 :2 (\+ :3 :4)) % (:1 :2 :7)
\length
: Get the length of a list.
(\length ()) % :0
(\length (\list :1 :2 'three')) % :3
\map
: Map function.
(\define (\f \x \y \z) (\+ \x \y \z))
(\map \f (\list :1 :2 :3)
(\list :4 :5 :6)
(\list :7 :8 :9)) % (:12 :15 :18)
\nth
: Get the n-th value of a list (starting with 0).
(\nth (\list 'foo' 'bar' 'baz') :1) % 'bar'
\=
: Equality.
(\= '42' :42) % /f
(\= :23 :23) % /t
(\= (\cons :1 'foo') (\cons :1 'foo')) % /f
(\= 'foo' 'foo') % /t
\texprint
: Convert a object to TeX's tokens and output it to the document
(\texprint (\concat '\foo' (\group '42'))) % return () andoutput \foo{42}
(\texprint :42) % output 42
\print
: (For test) output a object as TeX's tokens
(\print ()) % output ()
(\print (\quote \foo)) % output \string\foo
(\print :42) % output :42
(\print 'bar') % output 'bar'
Type predicates
(\symbolQ (\quote \cs))
(\stringQ 'foo')
(\intQ :42)
(\booleanQ /f)
(\dimenQ !12pt)
(\skipQ @12pt plus 1in minus 3mm)
(\pairQ (\cons :1 :2))
(\nilQ ())
(\funcQ \+)
(\closureQ (\lambda () ()))
(\defmacro (\x) ())
(\macroQ \x)
(\listQ ())
(\listQ (\list :1 :2))
(\atomQ :23)
(\atomQ 'bar')
(\procedureQ \+)
(\procedureQ (\lambda () ()))
\readLaTeXCounter
: Read an integer from LaTeX
\setcounter{foo}{42}
\lispinterp{
(\readLaTeXCounter 'foo') % :42
}
\message
: Wrapper of LaTeX's \message
(\message 'output') % output "message" to console and return ()
\read
: Read a LISP expression from stdin
(\read) % input :42 and return it
\fgets
: Read a string from stdin.
(\fgets) % input \some {tokens} and return '\some {tokens}'
##Additional Packages ##
The package lisp-mod-fpnum adds fixed point numbers
to LISP on TeX. Load it by \usepackage
:
\usepackage{lisp-on-tex}
\usepackage{lisp-mod-fpnum}
Kinds | Literals | Examples |
---|---|---|
Fixed point number | +{fpnum:: number } |
+{fpnum::1.23} |
\fpnumTOstring
: Convert a fixed point number to a string.
(\fpnumTOstring +{fpnum::1.23}) % '1.23'
\fpplus
: Addition.
(\fpplus +{fpnum::1.2} +{fpnum::1.4}) % 2.59999 (arithmetical error)
\fpminus
: Subtraction.
(\fpminus +{fpnum::4.2} +{fpnum::2.3}) % 1.9
\fpmul
: Multiplication.
(\fpmul +{fpnum::1.2} +{fpnum::1.4}) % 1.67998
\fplt
: Comparison.
(\fplt +{fpnum::1.2} +{fpnum::2.3}) % /t
The package lisp-mod-l3regex is thin wrapper
of l3regex. Load it by \usepackage
:
\usepackage{lisp-on-tex}
\usepackage{lisp-mod-l3regex}
\regMatch
, \regMatchResult
: Match.
(\regMatch 'hoge+' 'hogeeeeeee') % /t
(\regMatchResult '(\w+)\s+is\s+(\w+)\.' 'He is crazy.')
% ('He is crazy.' 'He' 'crazy')
\regExtract
: Extraction.
(\regExtract '\w+' 'hello regex world') % ('hello' 'regex' 'world')
\regReplaceAll
, \regReplaceOnce
: Replace.
(\regReplaceAll '(\w+?)to(\w+?)' '$\1\c{to}\2$' 'AtoB BtoC') % '$A\to B$ $B\to C$'
(\regReplaceOnce 'foo+' '[\0]' 'foooofooooooo') % '[foooo]fooooooo'
\regSplit
: Split.
(\regSplit '/' '/path/to/hogehoge') % ('' 'path' 'to' 'hogehoge')
- Writing user manual
- Add functions and special forms
Dec. 18, 2024 : 2.1
- Add \stringTOint function, thanks for @homologic
Oct. 25, 2015 : 2.0
- Add GC
- Refine some special forms like \define
- Add checking #args for some functions.
- Add thin wrapper of l3regex
Jul. 12, 2014 : 1.3
- Add one shot continuations.
- Add some arithmetical functions.
- Debug environment.
Jan. 03, 2014 : 1.2
- Added TUG2013's examples.
- Improved the performance.
Aug. 10, 2013 : 1.1
- Added \letrec and \expand.
- debug
Mar. 04, 2013 : 1.0
Modified BSD (see LICENCE)
HAKUTA Shizuya hak7a3@live.jp