The binfix Reference Manual

Table of Contents

Next: , Previous: , Up: (dir)   [Contents][Index]

The binfix Reference Manual

This is the binfix Reference Manual, version 0.50, generated automatically by Declt version 3.0 "Montgomery Scott" on Mon Dec 02 09:06:09 2019 GMT+0.


Next: , Previous: , Up: Top   [Contents][Index]

1 Introduction

BINFIX

Viktor Cerovski, August 2019.

Build Status Quicklisp dist

Introduction

BINFIX (blend from "Binary Infix") is a powerful infix syntax notation for S-expressions of Common LISP ranging from simple arithmetic and logical forms to whole programs.

NEW FEATURES in v0.50 (July/August 2019): ;-separated definitions of functions which makes use of def for this purpose obsolete; Simpler local definitions of longer/multiple functions; No need to import any symbols to use BINFIX.

NEW FEATURE (July 2019): let supports multiple-value- and destructuring-bind. NEW FEATURES (July 2019): Introduced => for writing cond forms, use of ? is depreciated. Introduced BINFIX with-slots. NEW FEATURE (Jun 2019): B-terms, allowing indexing-like operations.

Currently developed v0.50, once it's finished, should mark transition from experimental to a stable version of BINFIX. Although there are still a few important new features to come, BINFIX begins to look about right.


Content


Installation

Quicklisp makes the downloading/installation/loading trivial:

(ql:quickload :binfix)

System can be tested via

(asdf:test-system :binfix)

Supported LISP implementations are SBCL (also used for development,) Clozure CL, ECL (tested with v15.3.7 and v16.1.3) and ABCL, while CLISP as of this release is not supported.

BINFIX shadows @ in Clozure CL and ECL, as well as var (sb-debug:var) and struct (sb-alien:struct) in SBCL.

The latest version is available at github, and can be obtained by

git clone https://github.com/vcerovski/binfix

There is also a syntax-highlighting file for vim editor, binfix.vim. Its installation consists of copying it into vimrc/syntax folder, which is on Linux located at ~/.vim/syntax (should be created if it doesn't exist.)

Once installed, after loading a LISP file, LISP+BINFIX syntax highlighting can be activated by :set syntax=binfix. Loading can be done automatically by adding

filetype on
au BufNewFile,BufRead *.lisp,*.cl set syntax=binfix

to .vimrc.

B-expression

BINFIX rewrites a B-expression (B-expr) into an S-expression, written using curly brackets {...}, and may contain, in addition to symbols, constants, S-exprs and B-exprs, also B-operations (B-ops) and B-terms. Bops are just symbols that BINFIX recognizes and prioritizes according to each Bop's precedence (priority). In addition to priority, each Bop may have properties, which further specify how to handle Bop's left- and right-hand side. B-term is a B-op that works from within B-expr to allow indexing-like operations.

BINFIX is a free-form notation (just like S-expr), i.e any number of empty spaces (including tabs and newlines) between tokens is treated the same as a single white space.

Generally, quoting a BINFIX expression in REPL will produce the corresponding S-expression.

Examples

For easier comparison of input and output forms in following examples, LISP printer is first setq (Bop =.) to lowercase output with

{*print-case* =. :downcase}

=> :downcase

Arithmetic and logical expressions

Classic math stuff:

{2 * 3 + 4}

=> 10

'{a * {b + c}}

=> (* a (+ b c))

'{- {x + y} / x * y}

=> (- (/ (+ x y) (* x y)))

'{0 < x < 1 && y >= 1 || y >= 2}

=> (or (and (< 0 x 1) (>= y 1)) (>= y 2))

'{- f x - g x - h x}

=> (- (- (f x)) (g x) (h x))

Expressions like {(f x y) * (g a b)} and {{f x y} * {g a b}} generally produce the same result. The inner brackets, however, can be removed:

'{sqrt x * sin x}

=> (* (sqrt x) (sin x))

'{A ! i .= B ! j + C ! k}

=> (setf (aref a i) (+ (aref b j) (aref c k)))

'{a ! i j += b ! i k * c ! k j}

=> (incf (aref a i j) (* (aref b i k) (aref c k j)))

'{listp A && car A == 'x && cdr A || A}

=> (or (and (listp a) (eql (car a) 'x) (cdr x)) a)

Consing

Operation :. stands for cons. For instance,

{-2 :. loop for i to 9 collect i}

=> (-2 0 1 2 3 4 5 6 7 8 9)

with the familiar behavior:

{1 :. 2 :. 3 equal '(1 2 . 3)}

=> t

{1 :. 2 :. 3 :. {} equal '(1 2 3)}

=> t

Lambdas, definitions and type annotations

lambda

'{x -> sqrt x * sin x}

=> (lambda (x) (* (sqrt x) (sin x)))

'{x :single-float -> sqrt x * sin x}

=> (lambda (x) (declare (type single-float x)) (* (sqrt x) (sin x)))

'{x y -> {x - y}/{x + y}}

=> (lambda (x y) (/ (- x y) (+ x y)))

Mixing of notations works as well, so each of the following

{x y -> / (- x y) (+ x y)}
{x y -> (- x y)/(+ x y)}
{x y -> (/ (- x y) (+ x y))}

produces the same form.

Fancy way of writing {2 * 3 + 4}

{x -> y -> z -> x * y + z @ 2 @ 3 @ 4}

=> 10

Quoting reveals the expanded S-expr

'{x -> y -> z -> x * y + z @ 2 @ 3 @ 4}

=>

(funcall (funcall (funcall
  (lambda (x) (lambda (y) (lambda (z) (+ (* x y) z))))
    2) 3) 4)

Indeed, @ is left-associative, standing for funcall.

More complicated types can be also explicitly given after an argument,

'{x :|or symbol number| -> x :. x}

=>

(lambda (x) (declare (type (or symbol number) x)) (cons x x))

Mappings

mapcar is also supported:

'{x -> sin x * sqrt x @. (f x)}

=>

(mapcar (lambda (x) (* (sin x) (sqrt x))) (f x))

Alternatively, it is possible to use the expression-termination symbol ;,

{x -> sin x * sqrt x @. f x;}

to the same effect.

reduce is represented by @/,

'{#'max @/ x y -> abs{x - y} @. a b}

=>

(reduce #'max (mapcar (lambda (x y) (abs (- x y))) a b))

and other maps have their @'s as well.

defun

Factorial fun:

'{f n :integer := if {n <= 0} 1 {n * f {1- n}}}

=>

(defun f (n)
  (declare (type integer n))
  (if (<= n 0)
      1
      (* n (f (1- n)))))

Function documentation, local declarations, local bindings and comments have a straightforward syntax:

'{g x := "Auxilary fn."
   declare (inline)
   let x*x = x * x; ;; Note binds termination via ;
     x*x / 1+ x*x}

=>

(defun g (x)
  "Auxilary fn."
  (declare (inline))
  (let ((x*x (* x x)))
    (/ x*x (1+ x*x))))

&optional is optional

Explicitly tail-recursive version of f

'{fac n m = 1 :=
   declare (integer m n)
   if {n <= 0} m
      {fac {n - 1} {n * m}}}

=>

(defun fac (n &optional (m 1))
  (declare (integer m n))
  (if (<= n 0)
      m
      (fac (- n 1) (* n m))))

As you may by now expect, the following is also permitted

{fac n :integer m :integer = 1 :=
  if {n <= 0} m
     {fac {n - 1} {n * m}}}

supplied-p variable var for an optional/keyword argument is given by ?var after the assignment.

{f x y = 0 ?supplied-y &key z = 0 ?supplied-z := <body expr>},

where, within <body expr>, boolean variables supplied-y and supplied-z are available (for the standard check whether respective values were provided in the call of f.)

Multiple definitions (new feature in v0.50)

Definitions of several functions are simply written as ;-separated individual definitions,

'{f x y := print "Addition";
           x + y;
  g x :num y :num :- x + y;
  m x y :== `{,x + ,y}}

=>

(progn
 (defun f (x y) (print "Addition") (+ x y))
 (defmethod g ((x num) (y num)) (+ x y))
 (defmacro m (x y) `(+ ,x ,y)))

Another way to obtain the same Sexpr until v0.50 was to use def,

'{def f x y := print "Addition";
               x + y
  def g x :num y :num :- x + y
  def m x y :== `{,x + ,y}}

but this way of defining functions is obsolete.

Furthermore, to define types or compiler macros in v0.50, it is sufficient to prefix a macro definition with type or compiler-macro, respectively. Here is the simplest example that puts together defining various kinds of Common LISP functions using BINFIX,

'{f x := x;
  g x :- x;
  m x :== x;
  type I x :== x;
  compiler-macro c x :== x}

=>

(progn
 (defun f (x) x)
 (defmethod g (x) x)
 (defmacro m (x) x)
 (deftype i (x) x)
 (define-compiler-macro c (x) x))

Local functions (new feature in v0.50)

Version of fac with a local recursive function f prior to v0.50 could be written as:

{fac n :integer :=
  labels
    f n m := {if {n = 0} m
                 {f (1- n) {n * m}}}
   f n 1}

or, by using a single ; to terminate definition, as in

{fac n :integer :=
  labels
    f n m := if {n = 0} m
                {f (1- n) {n * m}};
   f n 1}

where both forms are translated into the following S-expr,

(defun fac (n)
  (declare (type integer n))
  (labels ((f (n m)
             (if (= n 0)
                 m
                 (f (1- n) (* n m)))))
    (f n 1)))

which can be demonstrated by simply evaluating the quoted expressions.

These two ways of defining local functions are not supported anymore starting with v0.50. Instead, the local function definition(s) must be enclosed in {...},

{fac n :integer :=
  labels {f n m :=
           if {n = 0} m
             {f (1- n) {n * m}}}
   f n 1}

The new way of writing local definitions has advantages over old when multiple and/or more complicated local functions are defined.

The same syntax is used also in the case of flet and macrolet, except that in the latter case :== is written instead of :=.

defmethod

The following two generic versions of f

'{f n :integer :- if {n <= 0} 1 {n * f {1- n}}}
'{f (n integer):- if {n <= 0} 1 {n * f {1- n}}}

both produce

(defmethod f ((n integer))
  (if (<= n 0)
      1
      (* n (f (1- n)))))

:- supports also eql-specialization via == op, analogous to the way = is used for optional arguments initialization, as well as an optional method qualifier, given as the first argument after the method name, that can be either a keyword or an atom surrounded by parens (i.e :around, (reduce) etc.)

defmacro

Macros are defined via :== operation, similar to the previous examples. See Sec. Support for macros.

Type annotations, declarations and definitions

The examples shown so far demonstrate the possibility to type-annotate symbols in binds and lambda-lists by an (optional) keyword representing the type (for instance :fixnum, :my-class, :|simple-array single-float|, :|or symbol number|, :|{symbol or number}|, etc.)

Bops that represent LISP forms which allow declaration(s), in BINFIX can have in addition to the standard (declare ...) form also unparenthesized variant:

'{f x :fixnum y = 2 :=
   declare (inline)
   declare (fixnum y)
   x + y ** 2}

=>

(defun f (x &optional (y 2))
  (declare (type fixnum x))
  (declare (inline))
  (declare (fixnum y))
  (+ x (expt y 2)))

Another way to declare x and y is

'{f x y = 2 :=
   declare x y :fixnum
   declare (inline)
   x + y ** 2}

=>

(defun f (x &optional (y 2))
  (declare (inline))
  (declare (fixnum x y))
  (+ x (expt y 2)))

Function types

Operation :-> can be used to specify function type. For example, in SBCL 1.1.17 function sin has declared type that can be written as

'{number :-> single-float -1.0 1.0 ||
             double-float -1.0 1.0 ||
             complex single-float  ||
             complex double-float .x. &optional}

=>

(function (number)
 (values
  (or (single-float -1.0 1.0)
      (double-float -1.0 1.0)
      (complex single-float)
      (complex double-float))
  &optional))

Function fac with a local function from this example can have its type declared as

'{fac n :integer :=
   labels
     {f n m := if {n = 0} m
                 {f (1- n) {n * m}}}
     declare f {integer integer :-> integer}
    f n 1}

=>

(defun fac (n)
  (declare (type integer n))
  (labels ((f (n m)
             (if (= n 0)
                 m
                 (f (1- n) (* n m)))))
    (declare (ftype (function (integer integer) integer) f))
    (f n 1)))

Declaration which annotates that symbol value of a symbol is a function can be achieved by using -> instead of :-> in declaration of the symbol. For instance:

'{f x :integer :=
   let f = x -> 1+ x;
     declare f {integer -> integer}
     flet {f x := 1- x}
       declare f {integer :-> integer}
       cons (f x) {f @ x}}

=>

(defun f (x)
  (declare (type integer x))
  (let ((f (lambda (x) (1+ x))))
    (declare (type (function (integer) integer) f))
    (flet ((f (x)
             (1- x)))
      (declare (ftype (function (integer) integer) f))
      (cons (f x) (funcall f x)))))

which has the expected behavior: (f 0) => (-1 . 1)

Type definitions are given using :type= OP, as in

`{mod n :type= `(integer 0 (,n))}

=>

(deftype mod (n) `(integer 0 (,n)))

def

Program typically consists of a number of definitions. Bop def can be used to define variables, parameters, constants, structures, classes and generic functions. For instance,

'{def parameter *x* = 1 *y* = 2
  def struct point x y z
  def f x := sqrt x * sin x}

=>

(progn
 nil
 (defparameter *x* 1)
 (defparameter *y* 2)
 (defstruct point x y z)
 (defun f (x) (* (sqrt x) (sin x))))

As it is clear from the example, the definitions are wrapped up in progn.

More detailed definitions are also straightforward to specify:

'{def parameter
    *y* :single-float = 1f0
    *z* :single-float = 1f0

  def struct point "Point"
    :print-function {p s d ->
                       declare (ignore d)
                       with-slots x y z :_ p
                         format s "#<~$ ~$ ~$>" x y z}
    :constructor create-point (x y = *y* z = *z*)
    x :single-float = 0f0
    y :single-float = 0f0
    z :single-float = 0f0;

  point+= p :point q :point :=
    p _'x += q _'x;
    p _'y += q _'y;
    p _'z += q _'z;
    p;

  point-= p :point q :point :=
    with-slots x y z :_ p
      with-slots dx = x dy = y dz = z :_ q
        x -= dx;
        y -= dy;
        z -= dz;
        p}

=>

(progn
 (declaim (type single-float *y*)
          (type single-float *z*))
 (defparameter *y* 1.0)
 (defparameter *z* 1.0)
 (defstruct
     (point
      (:print-function
       (lambda (p s d)
         (declare (ignore d))
         (with-slots (x y z)
             p
           (format s "#<~$ ~$ ~$>" x y z))))
      (:constructor create-point (x &optional (y *y*) (z *z*))))
   "Point"
   (x 0.0 :type single-float)
   (y 0.0 :type single-float)
   (z 0.0 :type single-float))
 (progn
  (defun point+= (p q)
    (declare (type point p)
             (type point q))
    (incf (slot-value p 'x) (slot-value q 'x))
    (incf (slot-value p 'y) (slot-value q 'y))
    (incf (slot-value p 'z) (slot-value q 'z))
    p)
  (defun point-= (p q)
    (declare (type point p)
             (type point q))
    (with-slots (x y z)
        p
      (with-slots ((dx x) (dy y) (dz z))
          q
        (decf x dx)
        (decf y dy)
        (decf z dz)
        p)))))

def class syntax is like defclass without parens. For this to work, class options (:documentation and :metaclass) have to be given before description of slots, while :default-initargs comes last as usual, just unparenthesized (see example.)

defining of symbols follows the same syntax as let binding, which is covered next.

Definitions and declarations without parens

BINFIX allows writing of standard LISP definition forms without outer parens, as in

'{declaim (fixnum a b c)
  defvar a 0
  defvar b 1 "variable b"
  defvar c 2}

=>

(progn
 (declaim (fixnum a b c))
 (defvar a 0)
 (defvar b 1 "variable b")
 (defvar c 2))

This extends to all Common LISP def-forms, declaim and proclaim.

The result is wrapped up in a progn.

LETs (new feature)

LET symbol-binding forms (let, let*, symbol-macrolet, etc) in BINFIX use = with an optional type-annotation:

'{let x :bit = 1
      y = {2 ** 3}
      z = 4
    x + y * z}

=>

(let ((x 1) (y (expt 2 3)) (z 4))
  (declare (type bit x))
  (+ x (* y z)))

New feature: BINFIX let supports multiple-value-bind and destructuring-bind

A single ; can be used as a terminator of bindings:

'{let x :bit = 1
      y = 2 ** 3
      z = f a;
    x + y * z}

=>

(let ((x 1) (y (expt 2 3)) (z (f a)))
  (declare (type bit x))
  (+ x (* y z)))

Finally, a single ; can also be used to separate forms in implicit-progn, as in

'{let x :bit = 1
      y = 2 ** 3
      z = f a;         ;; end of binds
    print "Let binds"; ;; 1st form
    x + y * z}         ;; 2nd form of implicit-progn

=>

(let ((x 1) (y (expt 2 3)) (z (f a)))
  (declare (type bit x))
  (print "Let binds")
  (+ x (* y z)))

Nesting of lets without parens follows the right-associativity

'{let a = f x;
    if a
      (g x)
      let b = h x;
        f b}

=>

(let ((a (f x)))
  (if a
      (g x)
      (let ((b (h x)))
        (f b))))

Note the three levels of parens gone.

SETs

In addition to =., =... and .=, Bops representing, respectively, a single setq, multiple-value-setq and setf assignment, multiple assignments via SETs can be done using =,

'{psetq x =   cos a * x + sin a * y
        y = - sin a * x + cos a * y}

=>

(psetq x (+ (* (cos a) x) (* (sin a) y))
       y (+ (- (* (sin a) x)) (* (cos a) y)))

If it is necessary to remove repeating sin a and cos a, it is easy to use let,

{let sin = sin a
     cos = cos a;
   psetq x =   cos * x + sin * y
         y = - sin * x + cos * y}

and in the case of SETF assignments, RHS are represented with a single expression,

'{psetf a ! 0 = {a ! 1}
        a ! 1 = {a ! 0}}

=>

(psetf (aref a 0) (aref a 1)
       (aref a 1) (aref a 0))

Alternatively, it is possible to use a single ; as an expression-termination symbol,

'{psetf a ! 0 = a ! 1; ;; expr. termination via single ;
        a ! 1 = a ! 0}

=>

(psetf (aref a 0) (aref a 1)
       (aref a 1) (aref a 0))

It is also possible to mix infix SETFs with other expressions:

'{f x + setf a = b
             c = d;
      * h a c}

=>

(+ (f x)
   (*
    (setf a b
          c d)
    (h a c)))

setf and setq can be also represented via .= and =. Bops, and the main difference is in priority---the latter can be embedded within lambdas without parens. For instance, both

'{a -> {setf car a = 0} .@ list}

and

'{a -> car a .= 0 .@ list}

=>

(mapc (lambda (a) (setf (car a) 0)) list)

In the case of implicit-progn within lambda,

'{a b -> {setf car a = car b;
               car b = 0}
      .@ l1 l2}

=>

(mapc (lambda (a b)
        (setf (car a) (car b)
              (car b) 0))
      l1 l2)

while

'{a b -> car a .= car b;
         car b .= 0
      .@ l1 l2}

=>

(mapc (lambda (a b)
        (setf (car a) (car b))
        (setf (car b) 0))
      l1 l2)

Implicit progn

An implicit progn in BINFIX is achieved with a single ; separating the forms forming the progn. In all cases (->, :=, :- and LETs) the syntax is following that of the LET example above.

As expected, other progs have to be explicitly given,

'{x -> prog2 (format t "Calculating... ")
             {f $ x * x}
             (format t "done.~%")}

or

'{x -> prog2
         format t "Calculating... ";
         f {x * x};
         format t "done.~%"}

both producing the following form

(lambda (x)
  (prog2 (format t "Calculating... ") (f (* x x)) (format t "done.~%")))

Since BINFIX is a free-form notation, the following one-liner also works:

'{x -> prog2 format t "Calculating... "; f{x * x}; format t "done.~%"}

Bop <& stands for prog1,

'{x -> {f {x * x} <&
        format t "Calculation done.~%"}}

=>

(lambda (x) (prog1 (f (* x x)) (format t "Calculation done.~%")))

while multiple-value-prog1 is given by <&...

$plitters

Infix $ is a vanishing OP, leaving only its arguments, effectively splitting the list in two parts.

'{f $ g $ h x y z}

=> (f (g (h x y z)))

Effect of $ is similar to $ in Haskell, except that here it works with Sexpr, so it is also possible to write

'{declare $ optimize (speed 1) (safety 1)}

or

'{declare {optimize $ speed 3; safety 1}}

both of which evaluate to

(declare (optimize (speed 1) (safety 1)))

$ also allows writing a shorter cond, as in

(cond {p x $ f x}
      {q x $ g x}
      {r x $ h x}
      {t $ x})

compared to the equivalent

(cond ((p x) (f x))
      ((q x) (g x))
      ((r x) (h x))
      (t x))

$ parenthesizes its l.h.s, leaving r.h.s. unchanged. Another splitter is .$, which does the opposite, namely parenthesizes its r.h.s leaving l.h.s unchanged, providing yet another way to omit parens:

'{loop for i to n
       append loop for j to m
                   collect .$ i :. j}

=>

(loop for i to n
      append (loop for j to m
                   collect (cons i j)))

Multiple-choice forms (cond, case, ...) (new feature)

An alternative, depreciated, syntax to describe multiple-choice forms is to use ? and ;

{cond p x ? f x;
      q x ? g x;
      r x ? h x;
        t ? x}

Preferred way to write such a form is to use => instead:

{cond p x => f x;
      q x => g x;
      r x => h x;
        t => x}

Similarly, case-like forms accept a B-expr before =>-clauses,

{ecase f x;
   0 1 2 => #\a;
   3 4   => #\b;
   6     => #\c}

where in simple cases => can be omitted

'{case f a; 1 a; 2 b; 3 c}

=>

(case (f a) (1 a) (2 b) (3 c))

Writing of implicit-progn in each clause is also supported in a straightforward way

{ecase f x;
   0 1 2 => print "a"; g #\a;
   3 4   => print "b"; g #\b;
   6     => print "c"; h #\c}

=>

(ecase (f x)
  ((0 1 2) (print "a") (g #\a))
  ((3 4)   (print "b") (g #\b))
  (6       (print "c") (h #\c)))

See also ordinal example below.

Destructuring, multiple values (new feature)

BINFIX let supports binding of multiple values as well as destructuring,

`{let a = 1 b = 2 c = 3
    let x y z = values 1 2 3;
      let (p (q = 2) r = 3) = '(1 nil);
        a = x = p = 1 &&
        b = y = q = 2 &&
        c = z = r = 3}

=>

(let ((a 1) (b 2) (c 3))
  (multiple-value-bind (x y z) (values 1 2 3)
    (destructuring-bind (p (&optional (q 2)) &optional (r 3)) '(1 nil)
      (and (= a x p 1)
           (= b y q 2)
           (= c z r 3)))))

which evaluates to t.

Multiple values (values) are represented by .x. as well as values, multiple-value-bind by =.. , and destructuring-bind by ..=

'{a (b) c ..= (f x) a + 1 .x. b + 2 .x. c + 3}

=>

(destructuring-bind (a (b) c) (f x) (values (+ a 1) (+ b 2) (+ c 3)))

Another way to write the same expr:

'{a (b) c ..= (f x) values a + 1; b + 2; c + 3}

multiple-value-call is represented by .@.

'{#'list .@. 1 '(b 2) 3}

=>

(multiple-value-call #'list 1 '(b 2) 3)

=>

(1 (b 2) 3)

Both ..= and =.. can be nested,

'{a b c =.. (f x)
  x y z =.. (g z)
  a * x + b * y + c * z}

=>

(multiple-value-bind (a b c)
    (f x)
  (multiple-value-bind (x y z) (g z) (+ (* a x) (* b y) (* c z))))

multiple-value-setq is given by =...

Loops

Loops can be also nested without writing parens:

'{loop for i = 1 to 3
       collect loop for j = 2 to 4
                    collect {i :. j}}

=>

(loop for i = 1 to 3
      collect (loop for j = 2 to 4
                    collect (cons i j))) 

Hash tables and association lists

Hash tables are supported via ~! (gethash), ~~ (remhash) and @~ (maphash) Bops. See also indexing.

Association lists are accessible via !~~ (assoc) and ~~! (rassoc).

Mappings

Mappings and function applications are what @-ops are all about, as summarized in the following table,

They all have the same priority and are right-associative. Since they bind weaker than ->, they are easy to string together with lambdas, as in a map-reduce expr.

{'max @/ x y -> abs{x - y} @. a b}

Indexing (new feature)

Indexing can be done using square brackets, [...], by default set to aref,

'{a[i;j] += b[i;k] * c[k;j]}

=>

(incf (aref a i j) (* (aref b i k) (aref c k j)))

or using double-square brackets, [[...]], with one or two arguments, by default set to indexing of hash table,

'{ table[[key; default]] }

=>

(gethash key table default)

What square-brackets represent can be changed using setbinfix.

The following table summarizes indexing Bops, from the weakest to the strongest binding:

!.. and th-value are mere synonyms and thus of the same priority, as are .! !. and !!., while !! is a weaker binding !, allowing easier writing of expr. with arithmetic operations with indices, like

{a !! i + j}

{a !! i + j; 1- k;}

etc. In the same relation stand .!. and .!!.

Indexing of arrays is by default supported by the new square-brackets BINFIX reader, so the above two examples can be written as {a[i + j]} and {a[i + j; 1- k]}, respectively.

Working with bits

Integer bit-logical BINFIX ops are given with a . after the name of OP, while bit-array version of the same OP with . before and after the name. For instance, {a or. b} transforms to (logior a b), while {a .or. b} transforms to (bit-ior a b).

Support for macros

If BINFIX terms only are inserted under backquote, everything should work fine,

'{let t1 = 'x
      t2 = '{x + x}
     `{x -> ,t1 / ,t2}}

=>

(let ((t1 'x) (t2 '(+ x x)))
  `(lambda (x) (/ ,t1 ,t2)))

Replacing, however, BINFIX operations inside a backquoted BINFIX will not work. This is currently not considered as a problem because direct call of binfix will cover some important cases of macro transformations in a straightforward manner:

{m x y op = '/ type = :double-float :==
   let a = (gensym)
       b = (gensym)
     binfix:binfix
       `(let ,a ,type = ,x
             ,b ,type = ,y
           {,a - ,b} ,op {,a + ,b})}

Now macro m works as expected:

(macroexpand-1 '(m (f x y) {a + b}))

=>

(let ((#:g805 (f x y)) (#:g806 (+ a b)))
  (declare (type double-float #:g806)
           (type double-float #:g805))
  (/ (- #:g805 #:g806) (+ #:g805 #:g806)))
t

or,

(macroexpand-1 '(m (f x y) {a + b}) * :double-float)

=>

(let ((#:g817 (f x y)) (#:g818 (+ a b)))
  (declare (type double-float #:g817)
           (type double-float #:g818))
  (* (- #:g817 #:g818) (+ #:g817 #:g818)))
t

See more in implementation details

More involved examples

ordinal

Converting an integer into ordinal string in English can be defined as

{ordinal i :integer :=
   let* a = i mod 10
        b = i mod 100
      suf = {cond
               a = b = 1 || a = 1 && 21 <= b <= 91 => "st";
               a = b = 2 || a = 2 && 22 <= b <= 92 => "nd";
               a = b = 3 || a = 3 && 23 <= b <= 93 => "rd";
                                                t  => "th"}
        format () "~D~a" i suf}

It can be also written in a more "lispy" way without parens as

{ordinal1 i :integer :=
   let* a = i mod 10
        b = i mod 100
      suf = {cond
               = a b 1 or = a 1 and <= b 21 91 => "st";
               = a b 2 or = a 2 and <= b 22 92 => "nd";
               = a b 3 or = a 3 and <= b 23 93 => "rd";
                                            t  => "th"}
        format () "~D~a" i suf}

which can be tried using @. (mapcar)

{#'ordinal @. '(0 1 12 22 43 57 1901)}

=> ("0th" "1st" "12th" "22nd" "43rd" "57th" "1901st")

(This example is picked up from Rust blog)

join

APL-ish joining of things into list:

{
  defgeneric join (a b) &

  join a :list  b :list :- append a b        &
  join a :t     b :list :- cons a b          &
  join a :list  b :t    :- append a (list b) &
  join a :t     b :t    :- list a b          &

  defbinfix ++ join
}
; Must close here in order to use ++

{let e = '{2 in 'x ++ '(1 2 3) ++ '((a)) ++ -1 * 2}
    format t "~S~%=> ~S" e (eval e)}

Evaluation of the above returns t and prints the following

(member 2 (join 'x (join '(1 2 3) (join '((a)) (* -1 2)))))
=> (2 3 (a) -2)

Another way to write join is as a single defgeneric definition, using def generic,

{def generic join a b;
   "Generic join."
   a :list b :list :- append a b;
   a :t    b :list :- a :. b;
   a :list b :t    :- `(,@a ,b);
   a :t    b :t    :- list a b}

which expands into

(progn
 (defgeneric join
     (a b)
   (:documentation "Generic join.")
   (:method ((a list) (b list)) (append a b))
   (:method ((a t) (b list)) (cons a b))
   (:method ((a list) (b t)) `(,@a ,b))
   (:method ((a t) (b t)) (list a b))))

(new feature in v0.50) This way of writing ;-separated instances is possible also in the first example, by replacing the four join lines with

  join a :list  b :list :- append a b;
  join a :t     b :list :- cons a b;
  join a :list  b :t    :- append a (list b);
  join a :t     b :t    :- list a b;

values-bind

Macro multiple-value-bind with symbol _ in variable list standing for an ignored value can be defined as

{values-bind v e &rest r :==
  let*  _ = ()
     vars = a -> if {a == '_} {car $ push (gensym) _} a @. v;
    `(multiple-value-bind ,vars ,e
        ,@{_ && `({declare $ ignore ,@_})}
        ,@r)}

So, for instance,

(macroexpand-1 '(values-bind (a _) (truncate 10 3) a))

=>

(multiple-value-bind (a #:g823) (truncate 10 3) (declare (ignore #:g823)) a)
t

for

Nested BINFIX lambda lists can be used in definitions of macros, as in the following example of a procedural for-loop macro

{for (v :symbol from below by = 1) &rest r :==
  `(loop for,v fixnum from,from below,below ,@{by /= 1 && `(by,by)}
         do ,@r)}

Now

(macroexpand-1 '(for (i 0 n)
                  {a ! i .= 1+ i}))

=>

(loop for i fixnum from 0 below n
      do (setf (aref a i) (1+ i)))
t

Cartesian to polar coordinates

An example from Common LISP the Language 2nd ed. where Cartesian coordinates are converted into polar coordinates via change of class can be straightforwardly written in BINFIX (prior to v0.50) as

{def class position () ();

     class x-y-position (position) 
      x :initform 0 :initarg :x
      y :initform 0 :initarg :y;

     class rho-theta-position (position) 
      rho :initform 0
      theta :initform 0

 def update-instance-for-different-class :before 
      old :x-y-position
      new :rho-theta-position &key :-
      ;; Copy the position information from old to new to make new 
      ;; be a rho-theta-position at the same position as old. 
        let x = old _'x 
            y = old _'y;
          new _'rho .= sqrt {x * x + y * y};
          new _'theta .= atan y x

;;; At this point an instance of the class x-y-position can be 
;;; changed to be an instance of the class rho-theta-position 
;;; using change-class: 

& p1 =. make-instance 'x-y-position :x 2 :y 0

& change-class p1 'rho-theta-position

;;; The result is that the instance bound to p1 is now 
;;; an instance of the class rho-theta-position. 
;;; The update-instance-for-different-class method 
;;; performed the initialization of the rho and theta 
;;; slots based on the values of the x and y slots, 
;;; which were maintained by the old instance.
}

while in v0.50 def class section of the code has to be finished by ; and def before update-instance-for-different-class is superfluous,

{def class position () ();

     class x-y-position (position) 
      x :initform 0 :initarg :x
      y :initform 0 :initarg :y;

     class rho-theta-position (position) 
      rho :initform 0
      theta :initform 0;

 update-instance-for-different-class :before 
   old :x-y-position
   new :rho-theta-position &key :-
   ;; Copy the position information from old to new to make new 
   ;; be a rho-theta-position at the same position as old. 
     let x = old _'x 
         y = old _'y;
       new _'rho .= sqrt {x * x + y * y};
       new _'theta .= atan y x

;;; At this point an instance of the class x-y-position can be 
;;; changed to be an instance of the class rho-theta-position 
;;; using change-class: 

& p1 =. make-instance 'x-y-position :x 2 :y 0

& change-class p1 'rho-theta-position

;;; The result is that the instance bound to p1 is now 
;;; an instance of the class rho-theta-position. 
;;; The update-instance-for-different-class method 
;;; performed the initialization of the rho and theta 
;;; slots based on the values of the x and y slots, 
;;; which were maintained by the old instance.
}

where Steele's comments are left verbatim.

Using BINFIX in packages (new feature)

v0.50 of BINFIX greatly simplifies use of BINFIX in packages by recognizing symbols representing Bops as having no package membership. Thus there is no need to export Bops by BINFIX and consequently no importing of Bops by a package is needed. The only symbols exported by BINFIX are names of macros needed for controlling Bops, described next.

Controlling Bops (new feature)

The following set of forms modify BINFIX behavior by adding/removing/redefining Bops. They must be evaluated before and outside B-exprs in which the modified behavior takes place.

Implementation

BINFIX expression is written as a list enclosed in curly brackets { ... } handled through LISP reader, so the usual syntax rules of LISP apply, e.g a+b is a single symbol, while a + b is three symbols. Lisp reader after tokenization calls the function binfix which does shallow transformation of BINFIX into S-expr representation of the expression.

BINFIX uses a simple rewrite algorithm that divides a list in two, LHS and RHS of the lowest priority infix operator found within the list, then recursively processes each one.

proto-BINFIX

Bootstrapping is done beginning with proto-BINFIX,

(defparameter *binfix*
  '((|;|    infix     (progn))
    (:==    def       defmacro)
    (:=     def       defun)
    (:-     def       defmethod)
    ( =.    infix     (setq))
    (.=     infix     (setf))
    (->     def-lambda)
    ($      infix     ())
    (symbol-macrolet  let= symbol-macrolet)
    (let    let=      let)
    (let*   let=      let*)
    (labels flet=     labels)
    (=..    var-bind  multiple-value-bind)
    (.x.    unreduc   .x. values)
    (:.     infix     (cons))
    (||     infix     (or))
    (&&     infix     (and))
    (==     infix     (eql))
    (=c=    infix     (char=))
    (in     infix     (member))
    ( !     infix     (aref))))
 
(defun binfix (e &optional (ops *binfix*))
  (cond ((atom e) e)
        ((null ops) (if (cdr e) e (car e)))
        (t (let* ((op (car ops))
                  (op.rhs (member (pop op) e)))
             (if (null op.rhs)
               (binfix e (cdr ops))
               (let ((lhs (ldiff e op.rhs)))
                 (macroexpand-1
                   `(,@op ,lhs ,(cdr op.rhs)))))))))
 
(defmacro infix (op lhs rhs)
  `(,@op ,(binfix lhs) ,(binfix rhs)))
 
(set-macro-character #\{
  (lambda (s ch) (declare (ignore ch))
    (binfix (read-delimited-list #\} s t))))
 
(set-macro-character #\} (get-macro-character #\) ))

which captures the basics of BINFIX.

Since v0.15, BINFIX interns a symbol consisting of a single ; char not followed by ; char, while two or more consecutive ; are interpreted as a usual LISP comment. This behavior is limited to BINFIX expressions only, while outside of them the standard LISP rules apply.

The next bootstrap phase defines macros def, def-lambda, let=, flet=, unreduc and var-bind, done in proto1.lisp,

{defmacro def (what args body)
  `(,what ,@(if (atom args)
               `(,args ())
               `(,(car args),(cdr args)))
          ,(binfix body));

 def-lambda args body :==
  `(lambda ,(if (consp args) args `(,args))
     ,(binfix body));

 let= let lhs body &aux vars :==
  loop while {cadr body == '=}
     do {push `(,(car body),(caddr body)) vars;
         body =. cdddr body}
     finally (return (let ((let `(,let ,(nreverse vars) ,(binfix body))))
                       (if lhs (binfix `(,@lhs ,let)) let)));

 flet= flet lhs body &aux funs :==
  loop for r = {'= in body} while r
       for (name . lambda) = (ldiff body r)
       do {push `(,name ,lambda ,(cadr r)) funs;
           body =. cddr r}
       finally {return let flet = `(,flet ,(reverse funs) ,(binfix body))
                         if lhs (binfix `(,@lhs ,flet)) flet};

 unreduc op op-lisp lhs rhs :==
   labels
     unreduce e &optional args arg =
       (cond {null e      $ nreverse {binfix (nreverse arg) :. args}}
             {car e == op $ unreduce (cdr e) {binfix (nreverse arg) :. args}}
             {t           $ unreduce (cdr e) args {car e :. arg}})
   `(,op-lisp ,@(unreduce rhs `(,(binfix lhs))));

 var-bind op lhs rhs :== `(,op ,lhs ,(car rhs) ,(binfix (cdr rhs)))}

which wraps up proto-BINFIX.

Since v0.15, BINFIX interns a symbol consisting of a single ; char not followed by ; char, while two or more consecutive ; are interpreted as starting a comment. This behavior is limited to BINFIX expressions only, while outside of them the standard LISP rules apply.

The rest is written using proto-BINFIX syntax, and consists of handling of lambda lists and lets, a longer list of OPs with properties, redefined binfix to its full capability, and, finally, several interface functions for dealing with OPs (lsbinfix, defbinfix and rmbinfix).

Priorities of operations in proto-BINFIX are given only relatively, with no numerical values and thus with no two operations of the same priority.

LHS and RHS of proto-BINFIX expressions refer to other proto-BINFIX expressions (since v0.22.3), which in particular means that there is no implicit-progn in proto-BINFIX let's and def's.

Since v0.20, symbol of a BINFIX operation has a list of properties stored into the symbol property binfix::properties, which includes a numerically given priority of the OP (which also considerably speeds up parsing.) The actual value of number representing priority is supposed to be immaterial since only relation to other Bops priority values is relevant. Defining a new same-priority Bop should be done via defbinfix with :as option. Using defbinfix typically changes priority values of other Bops.

Since shallow transformation into standard syntax is done by function binfix invoked recursively by the reader, binfix cannot be directly called for arbitrary macro transformation of BINFIX into BINFIX when standard macro helpers BACKTICK, COMA and COMA-AT are used. The reason is that {...} is invoked before them while the correct order would be after them. Examples of successful combinations of backquoting and BINFIX are given above.

Problems with CLISP

The latest version of clisp I have tried is 2.49.93+ (2018-02-18), which has two problems with BINFIX:

  1. There seems to be a bug in set-macro-character (see here.) Workaround is possible, but BINFIX still doesn't work (while other implementations tried do.)

  2. Test subsystem of the current version of BINFIX uses fiveam, which requires ASDF>=3.1, which clisp does not seem to support. Workaround is of course possible pending solving problem 1.

Appendix

Syntax highlighting

Provided binfix.vim file covers vim editor with a syntax-highlighting extension, which is based and depends on lisp.vim that comes bundled with vim.

Here are GUI and terminal looks:

gui (theme: solarized, font: Inconsolata Medium)

gui (theme: herald, font: Terminus)

Operation properties

Unused symbols

BINFIX does not use symbols ~, % and ^. The use of splitter ? as a Bop is depreciated and will be removed. The current plan is that these four will be left for user-defined Bops.

List of all operations

Command (binfix:list-Bops) prints the table of all Bops and their properties from the weakest- to the strongest-binding Bop, with parens enclosing Bop(s) of the same priority:

  BINFIX         LISP            Properties
==============================================================================
( <&            prog1
  <&..          multiple-value-prog1 )
( &             progn            :progn )
( def           nil              :binfix-defs
  defclass      defclass         :progn          :prefix         :quote-rhs
  defstruct     defstruct        :progn          :prefix         :quote-rhs
  deftype       deftype          :progn          :prefix         :quote-rhs
  defparameter  defparameter     :progn          :prefix         :quote-rhs
  defvar        defvar           :progn          :prefix         :quote-rhs
  defconstant   defconstant      :progn          :prefix         :quote-rhs
  define-condition define-condition              :progn          :prefix         :quote-rhs
  define-setf-expander define-setf-expander      :progn          :prefix         :quote-rhs
  define-setf-method binfix::define-setf-method  :progn          :prefix         :quote-rhs
  defsetf       defsetf          :progn          :prefix         :quote-rhs
  defgeneric    defgeneric       :progn          :prefix         :quote-rhs
  defmethod     defmethod        :progn          :prefix         :quote-rhs
  define-method-combination define-method-combination            :progn          :prefix         :quote-rhs
  defun         defun            :progn          :prefix         :quote-rhs
  defmacro      defmacro         :progn          :prefix         :quote-rhs
  define-compiler-macro define-compiler-macro    :progn          :prefix         :quote-rhs
  define-symbol-macro define-symbol-macro        :progn          :prefix         :quote-rhs
  define-modify-macro define-modify-macro        :progn          :prefix         :quote-rhs
  declaim       declaim          :progn          :prefix         :quote-rhs
  proclaim      proclaim         :progn          :prefix         :quote-rhs )
( :==           defmacro         :def            ((type . deftype)
                                                  (compiler-macro
                                                   . define-compiler-macro))
  :=            defun            :def
  :-            defmethod        :defm
  :type=        deftype          :def )
( cond          cond             :rhs-implicit-progn             binfix::=>      :prefix
  case          case             :rhs-implicit-progn             binfix::=>      :prefix
  ccase         ccase            :rhs-implicit-progn             binfix::=>      :prefix
  ecase         ecase            :rhs-implicit-progn             binfix::=>      :prefix
  typecase      typecase         :rhs-implicit-progn             binfix::=>      :prefix
  ctypecase     ctypecase        :rhs-implicit-progn             binfix::=>      :prefix
  etypecase     etypecase        :rhs-implicit-progn             binfix::=>      :prefix )
( let           let              :rhs-lbinds
  let*          let*             :rhs-lbinds
  symbol-macrolet symbol-macrolet                :rhs-lbinds
  prog*         prog*            :rhs-lbinds
  prog          prog             :rhs-lbinds
  with-slots    with-slots       :rhs-slots
  macrolet      macrolet         :rhs-mbinds
  flet          flet             :rhs-fbinds
  labels        labels           :rhs-fbinds )
( block         block            :prefix
  tagbody       tagbody          :prefix
  catch         catch            :prefix
  prog1         prog1            :prefix
  prog2         prog2            :prefix
  progn         progn            :prefix )
( ?             nil              :split )
( setq          setq             :rhs-sbinds
  set           set              :rhs-sbinds
  psetq         psetq            :rhs-sbinds )
( setf          setf             :rhs-ebinds
  psetf         psetf            :rhs-ebinds )
( $             nil              :split          :rhs-args
  .$            nil              :split-left     :rhs-args )
( .@            mapc             :rhs-args
  ..@           mapl             :rhs-args
  @/            reduce           :rhs-args
  @.            mapcar           :rhs-args
  @..           maplist          :rhs-args
  @n            mapcan           :rhs-args
  @.n           mapcon           :rhs-args
  @~            maphash
  @@            apply            :rhs-args
  .@.           multiple-value-call              :rhs-args
  @             funcall          :rhs-args       :left-assoc     :also-postfix )
( :->           function         :lhs-lambda )
( ->            lambda           :lhs-lambda )
( =..           multiple-value-bind              :syms/expr
  ..=           destructuring-bind               :lambda/expr )
( values        values           :prefix         :single
  .x.           values           :unreduce       :single )
( loop          loop             :prefix         :quote-rhs )
( =...          multiple-value-setq              :quote-lhs
  .=            setf
  +=            incf
  -=            decf
  =.            setq
  .=.           set )
( ||            or               :unreduce
  or            or               :unreduce       :also-prefix )
( &&            and              :unreduce
  and           and              :unreduce       :also-prefix )
( ===           equalp           :single
  equal         equal            :single
  ==            eql              :single
  eql           eql              :single
  eq            eq               :single
  ~~            remhash          :single
  subtype-of    subtypep         :single )
( :.            cons )
( in            member )
( th-cdr        nthcdr )
( =s=           string=          :single
  =c=           char=            :single         :unreduce
  =             =                :single         :unreduce       :also-prefix
  /=            /=               :single         :unreduce       :also-prefix
  <             <                :single         :unreduce       :also-prefix
  >             >                :single         :unreduce       :also-prefix
  <=            <=               :single         :unreduce       :also-prefix
  >=            >=               :single         :unreduce       :also-prefix )
( th-bit        logbitp )
( coerce        coerce )
( !..           nth-value
  th-value      nth-value )
( th            nth )
( .!            elt
  !.            svref
  !!.           row-major-aref )
( .!!.          bit              :rhs-args )
( !!            aref             :rhs-args )
( ~!            gethash          :single         :rhs-args
  !~~           assoc            :single
  ~~!           rassoc           :single )
( .eqv.         bit-eqv          :rhs-args
  .or.          bit-ior          :rhs-args
  .xor.         bit-xor          :rhs-args
  .and.         bit-and          :rhs-args
  .nand.        bit-and          :rhs-args
  .nor.         bit-nor          :rhs-args
  .not.         bit-not          :also-unary
  .orc1.        bit-orc1         :rhs-args
  .orc2.        bit-orc2         :rhs-args
  .andc1.       bit-andc1        :rhs-args
  .andc2.       bit-andc2        :rhs-args )
( dpb           dpb              :rhs-args )
( ldb           ldb )
( ldb-test      ldb-test )
( deposit-field deposit-field    :rhs-args )
( mask-field    mask-field )
( byte          byte )
( eqv.          logeqv           :also-unary     :unreduce )
( or.           logior           :also-unary     :unreduce )
( xor.          logxor           :also-unary     :unreduce )
( and.          logand           :also-unary     :unreduce )
( nand.         lognand )
( nor.          lognor )
( test.         logtest )
( orc1.         logorc1 )
( orc2.         logorc2 )
( andc1.        logandc1 )
( andc2.        logandc2 )
( <<            ash )
( lcm           lcm              :also-unary     :unreduce )
( gcd           gcd              :also-unary     :unreduce )
( mod           mod )
( rem           rem )
( min           min              :also-prefix    :unreduce       :single
  max           max              :also-prefix    :unreduce       :single )
( +             +                :also-unary     :unreduce )
( -             -                :also-unary     :unreduce )
( /             /                :also-unary )
( *             *                :also-prefix    :unreduce )
( **            expt )
( .!.           bit              :rhs-args )
( !             aref             :rhs-args       :single
  _             slot-value       :single )
( ;             binfix::|;| )
( index         aref             :term
  index2        binfix::hashget  :term           :macro )
------------------------------------------------------------------------------

=> nil


Next: , Previous: , Up: Top   [Contents][Index]

2 Systems

The main system appears first, followed by any subsystem dependency.


Previous: , Up: Systems   [Contents][Index]

2.1 binfix

Author

Viktor Cerovski

License

GNU GPLv2

Description

BINFIX – A powerful binary infix syntax for Common LISP.

Version

0.50

Source

binfix.asd (file)

Components

Next: , Previous: , Up: Top   [Contents][Index]

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


Next: , Previous: , Up: Files   [Contents][Index]

3.1 Lisp


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.1 binfix.asd

Location

binfix.asd

Systems

binfix (system)


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.2 binfix/package.lisp

Parent

binfix (system)

Location

package.lisp

Packages

binfix


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.3 binfix/proto.lisp

Dependency

package.lisp (file)

Parent

binfix (system)

Location

proto.lisp

Internal Definitions

Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.4 binfix/proto1.lisp

Dependency

proto.lisp (file)

Parent

binfix (system)

Location

proto1.lisp

Internal Definitions

Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.5 binfix/binfix.lisp

Dependency

proto1.lisp (file)

Parent

binfix (system)

Location

binfix.lisp

Exported Definitions

binfix (function)

Internal Definitions

Previous: , Up: Lisp files   [Contents][Index]

3.1.6 binfix/interface.lisp

Dependency

binfix.lisp (file)

Parent

binfix (system)

Location

interface.lisp

Exported Definitions
Internal Definitions

Previous: , Up: Files   [Contents][Index]

3.2 Static


Next: , Previous: , Up: Static files   [Contents][Index]

3.2.1 binfix/README.md

Dependency

interface.lisp (file)

Parent

binfix (system)

Location

README.md


Next: , Previous: , Up: Static files   [Contents][Index]

3.2.2 binfix/doc/index.html

Dependency

readme.md (file)

Parent

binfix (system)

Location

doc/index.html


Next: , Previous: , Up: Static files   [Contents][Index]

3.2.3 binfix/doc/markdown.css

Dependency

doc/index.html (file)

Parent

binfix (system)

Location

doc/markdown.css


Next: , Previous: , Up: Static files   [Contents][Index]

3.2.4 binfix/doc/syntax-term.png

Dependency

doc/markdown.css (file)

Parent

binfix (system)

Location

doc/syntax-term.png


Previous: , Up: Static files   [Contents][Index]

3.2.5 binfix/doc/syntax-gui.png

Dependency

doc/syntax-term.png (file)

Parent

binfix (system)

Location

doc/syntax-gui.png


Next: , Previous: , Up: Top   [Contents][Index]

4 Packages

Packages are listed by definition order.


Previous: , Up: Packages   [Contents][Index]

4.1 binfix

Source

package.lisp (file)

Use List

common-lisp

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


Next: , Previous: , Up: Definitions   [Contents][Index]

5.1 Exported definitions


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.1 Macros

Macro: def-bop BOP &optional LISP-OP P &rest PROP

DEFBINFIX bop [lisp-op [priority op [property]*]] Defines new or redefines existing Bop BOP.

Package

binfix

Source

interface.lisp (file)

Macro: keep-bops &rest BOPS

Keep only Bops represented by symbols in argument(s) BOPS. Without arguments restores all binfix Bops. Handles also implicit dependence of := :== and :- on progn Bop. Returns nil.

Package

binfix

Source

interface.lisp (file)

Macro: rem-bops &rest BOPS

Macro that removes Bops represented by symbols in BOPS. Returns nil.

Package

binfix

Source

interface.lisp (file)

Macro: set-bop OP LISP-OP &rest PROPS

Set already defined binfix OP to represent lisp LISP-OP, with the same properties unless properties PROPS are non-nil.

Package

binfix

Source

interface.lisp (file)


Previous: , Up: Exported definitions   [Contents][Index]

5.1.2 Functions

Function: binfix E &optional MAX-PRIORITY
Package

binfix

Source

binfix.lisp (file)

Function: list-bops &optional S
Package

binfix

Source

interface.lisp (file)


Previous: , Up: Definitions   [Contents][Index]

5.2 Internal definitions


Next: , Previous: , Up: Internal definitions   [Contents][Index]

5.2.1 Special variables

Special Variable: *binfix*
Package

binfix

Source

proto.lisp (file)

Special Variable: *decls*
Package

binfix

Source

binfix.lisp (file)

Special Variable: *def-symbol*
Package

binfix

Source

binfix.lisp (file)

Special Variable: *init-binfix*
Package

binfix

Source

binfix.lisp (file)

Special Variable: *no-of-bops*
Package

binfix

Source

binfix.lisp (file)

Special Variable: *timing*
Package

binfix

Source

proto.lisp (file)


Next: , Previous: , Up: Internal definitions   [Contents][Index]

5.2.2 Macros

Macro: &lambdap S
Package

binfix

Source

binfix.lisp (file)

Macro: binfix-reader ()
Package

binfix

Source

proto.lisp (file)

Macro: declare* DECL* &optional DECL
Package

binfix

Source

binfix.lisp (file)

Macro: def WHAT ARGS BODY
Package

binfix

Source

proto1.lisp (file)

Macro: def-lambda ARGS BODY
Package

binfix

Source

proto1.lisp (file)

Macro: def-sbind* BINDS
Package

binfix

Source

binfix.lisp (file)

Macro: defs-macro &rest DEFS
Package

binfix

Source

binfix.lisp (file)

Macro: flet= FLET LHS BODY
Package

binfix

Source

proto1.lisp (file)

Macro: hashget TABLE KEY &rest OPT
Package

binfix

Source

binfix.lisp (file)

Macro: infix OP LHS RHS
Package

binfix

Source

proto.lisp (file)

Macro: init-binfix ()
Package

binfix

Source

binfix.lisp (file)

Macro: let= LET LHS BODY
Package

binfix

Source

proto1.lisp (file)

Macro: semicolon-in E
Package

binfix

Source

binfix.lisp (file)

Macro: unreduc OP OP-LISP LHS RHS
Package

binfix

Source

proto1.lisp (file)

Macro: var-bind OP LHS RHS
Package

binfix

Source

proto1.lisp (file)


Next: , Previous: , Up: Internal definitions   [Contents][Index]

5.2.3 Functions

Function: assign-properties ()
Package

binfix

Source

binfix.lisp (file)

Function: bop-p S
Package

binfix

Source

binfix.lisp (file)

Function: collect-&parts L &optional ARG TYPES
Package

binfix

Source

binfix.lisp (file)

Function: dbind E &optional LLIST
Package

binfix

Source

binfix.lisp (file)

Function: decls E &optional DECLS DOC
Package

binfix

Source

binfix.lisp (file)

Function: def-class B &optional SLOT SLOTS CLASS-OPTS
Package

binfix

Source

binfix.lisp (file)

Function: def-generic B &optional PARAMS ENTRIES
Package

binfix

Source

binfix.lisp (file)

Function: defs X &optional DEFS TYPES
Package

binfix

Source

binfix.lisp (file)

Function: doc-decls E &optional DECLS
Package

binfix

Source

binfix.lisp (file)

Function: dstruct X &optional DEFS TYPES NAME OPTS SLOTS DOC
Package

binfix

Source

binfix.lisp (file)

Function: fbinds E DEF
Package

binfix

Source

binfix.lisp (file)

Function: find-bop S &key TERMS
Package

binfix

Source

binfix.lisp (file)

Function: find-bop-in E &optional P LAST-BOP O.R
Package

binfix

Source

binfix.lisp (file)

Function: implicit-progn E
Package

binfix

Source

binfix.lisp (file)

Function: indexing S CH
Package

binfix

Source

proto.lisp (file)

Function: keyword-type-spec K
Package

binfix

Source

binfix.lisp (file)

Function: lambda-list L &optional ARG TYPES
Package

binfix

Source

binfix.lisp (file)

Function: lbinds E
Package

binfix

Source

binfix.lisp (file)

Function: mbind N LL D B
Package

binfix

Source

binfix.lisp (file)

Function: method-lambda-list L &optional ARGS
Package

binfix

Source

binfix.lisp (file)

Function: mvbind E &optional SYMS DECLS
Package

binfix

Source

binfix.lisp (file)

Function: op-position OP

Returns index of the first element of *binfix* that contains op, or nil otherwise.

Package

binfix

Source

interface.lisp (file)

Function: progn-monad FORM1 &optional FORM2
Package

binfix

Source

binfix.lisp (file)

Function: rmbop OP

Removes binfix operation OP. Returns nil.

Package

binfix

Source

interface.lisp (file)

Function: save-binfix ()
Package

binfix

Source

binfix.lisp (file)

Function: sbind* E &optional BINDS S CURRENT DECLS
Package

binfix

Source

binfix.lisp (file)

Function: semicolon S CH
Package

binfix

Source

proto.lisp (file)

Function: singleton X
Package

binfix

Source

binfix.lisp (file)

Function: slots E
Package

binfix

Source

binfix.lisp (file)

Function: slots+ E &optional SLOTS DECLS
Package

binfix

Source

binfix.lisp (file)

Function: split E OP &optional ARGS ARG
Package

binfix

Source

binfix.lisp (file)

Function: sym-eql S1 S2
Package

binfix

Source

binfix.lisp (file)

Function: type-keyword-type S KTYPE
Package

binfix

Source

binfix.lisp (file)

Function: unreduce-rhs OP E &optional CDR-P FORM0 FORMS
Package

binfix

Source

binfix.lisp (file)

Function: vbinds E &optional VARS DECLS
Package

binfix

Source

binfix.lisp (file)


Previous: , Up: Internal definitions   [Contents][Index]

5.2.4 Types

Type: priority ()
Package

binfix

Source

interface.lisp (file)

Type: property ()
Package

binfix

Source

interface.lisp (file)


Previous: , Up: Top   [Contents][Index]

Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts

Jump to:   B   F   L   S  
Index Entry  Section

B
binfix.asd: The binfix․asd file
binfix/binfix.lisp: The binfix/binfix․lisp file
binfix/doc/index.html: The binfix/doc/index․html file
binfix/doc/markdown.css: The binfix/doc/markdown․css file
binfix/doc/syntax-gui.png: The binfix/doc/syntax-gui․png file
binfix/doc/syntax-term.png: The binfix/doc/syntax-term․png file
binfix/interface.lisp: The binfix/interface․lisp file
binfix/package.lisp: The binfix/package․lisp file
binfix/proto.lisp: The binfix/proto․lisp file
binfix/proto1.lisp: The binfix/proto1․lisp file
binfix/README.md: The binfix/readme․md file

F
File, Lisp, binfix.asd: The binfix․asd file
File, Lisp, binfix/binfix.lisp: The binfix/binfix․lisp file
File, Lisp, binfix/interface.lisp: The binfix/interface․lisp file
File, Lisp, binfix/package.lisp: The binfix/package․lisp file
File, Lisp, binfix/proto.lisp: The binfix/proto․lisp file
File, Lisp, binfix/proto1.lisp: The binfix/proto1․lisp file
File, static, binfix/doc/index.html: The binfix/doc/index․html file
File, static, binfix/doc/markdown.css: The binfix/doc/markdown․css file
File, static, binfix/doc/syntax-gui.png: The binfix/doc/syntax-gui․png file
File, static, binfix/doc/syntax-term.png: The binfix/doc/syntax-term․png file
File, static, binfix/README.md: The binfix/readme․md file

L
Lisp File, binfix.asd: The binfix․asd file
Lisp File, binfix/binfix.lisp: The binfix/binfix․lisp file
Lisp File, binfix/interface.lisp: The binfix/interface․lisp file
Lisp File, binfix/package.lisp: The binfix/package․lisp file
Lisp File, binfix/proto.lisp: The binfix/proto․lisp file
Lisp File, binfix/proto1.lisp: The binfix/proto1․lisp file

S
Static File, binfix/doc/index.html: The binfix/doc/index․html file
Static File, binfix/doc/markdown.css: The binfix/doc/markdown․css file
Static File, binfix/doc/syntax-gui.png: The binfix/doc/syntax-gui․png file
Static File, binfix/doc/syntax-term.png: The binfix/doc/syntax-term․png file
Static File, binfix/README.md: The binfix/readme․md file

Jump to:   B   F   L   S  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   &  
A   B   C   D   F   H   I   K   L   M   O   P   R   S   T   U   V  
Index Entry  Section

&
&lambdap: Internal macros

A
assign-properties: Internal functions

B
binfix: Exported functions
binfix-reader: Internal macros
bop-p: Internal functions

C
collect-&parts: Internal functions

D
dbind: Internal functions
declare*: Internal macros
decls: Internal functions
def: Internal macros
def-bop: Exported macros
def-class: Internal functions
def-generic: Internal functions
def-lambda: Internal macros
def-sbind*: Internal macros
defs: Internal functions
defs-macro: Internal macros
doc-decls: Internal functions
dstruct: Internal functions

F
fbinds: Internal functions
find-bop: Internal functions
find-bop-in: Internal functions
flet=: Internal macros
Function, assign-properties: Internal functions
Function, binfix: Exported functions
Function, bop-p: Internal functions
Function, collect-&parts: Internal functions
Function, dbind: Internal functions
Function, decls: Internal functions
Function, def-class: Internal functions
Function, def-generic: Internal functions
Function, defs: Internal functions
Function, doc-decls: Internal functions
Function, dstruct: Internal functions
Function, fbinds: Internal functions
Function, find-bop: Internal functions
Function, find-bop-in: Internal functions
Function, implicit-progn: Internal functions
Function, indexing: Internal functions
Function, keyword-type-spec: Internal functions
Function, lambda-list: Internal functions
Function, lbinds: Internal functions
Function, list-bops: Exported functions
Function, mbind: Internal functions
Function, method-lambda-list: Internal functions
Function, mvbind: Internal functions
Function, op-position: Internal functions
Function, progn-monad: Internal functions
Function, rmbop: Internal functions
Function, save-binfix: Internal functions
Function, sbind*: Internal functions
Function, semicolon: Internal functions
Function, singleton: Internal functions
Function, slots: Internal functions
Function, slots+: Internal functions
Function, split: Internal functions
Function, sym-eql: Internal functions
Function, type-keyword-type: Internal functions
Function, unreduce-rhs: Internal functions
Function, vbinds: Internal functions

H
hashget: Internal macros

I
implicit-progn: Internal functions
indexing: Internal functions
infix: Internal macros
init-binfix: Internal macros

K
keep-bops: Exported macros
keyword-type-spec: Internal functions

L
lambda-list: Internal functions
lbinds: Internal functions
let=: Internal macros
list-bops: Exported functions

M
Macro, &lambdap: Internal macros
Macro, binfix-reader: Internal macros
Macro, declare*: Internal macros
Macro, def: Internal macros
Macro, def-bop: Exported macros
Macro, def-lambda: Internal macros
Macro, def-sbind*: Internal macros
Macro, defs-macro: Internal macros
Macro, flet=: Internal macros
Macro, hashget: Internal macros
Macro, infix: Internal macros
Macro, init-binfix: Internal macros
Macro, keep-bops: Exported macros
Macro, let=: Internal macros
Macro, rem-bops: Exported macros
Macro, semicolon-in: Internal macros
Macro, set-bop: Exported macros
Macro, unreduc: Internal macros
Macro, var-bind: Internal macros
mbind: Internal functions
method-lambda-list: Internal functions
mvbind: Internal functions

O
op-position: Internal functions

P
progn-monad: Internal functions

R
rem-bops: Exported macros
rmbop: Internal functions

S
save-binfix: Internal functions
sbind*: Internal functions
semicolon: Internal functions
semicolon-in: Internal macros
set-bop: Exported macros
singleton: Internal functions
slots: Internal functions
slots+: Internal functions
split: Internal functions
sym-eql: Internal functions

T
type-keyword-type: Internal functions

U
unreduc: Internal macros
unreduce-rhs: Internal functions

V
var-bind: Internal macros
vbinds: Internal functions

Jump to:   &  
A   B   C   D   F   H   I   K   L   M   O   P   R   S   T   U   V  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.3 Variables

Jump to:   *  
S  
Index Entry  Section

*
*binfix*: Internal special variables
*decls*: Internal special variables
*def-symbol*: Internal special variables
*init-binfix*: Internal special variables
*no-of-bops*: Internal special variables
*timing*: Internal special variables

S
Special Variable, *binfix*: Internal special variables
Special Variable, *decls*: Internal special variables
Special Variable, *def-symbol*: Internal special variables
Special Variable, *init-binfix*: Internal special variables
Special Variable, *no-of-bops*: Internal special variables
Special Variable, *timing*: Internal special variables

Jump to:   *  
S  

Previous: , Up: Indexes   [Contents][Index]

A.4 Data types

Jump to:   B   P   S   T  
Index Entry  Section

B
binfix: The binfix system
binfix: The binfix package

P
Package, binfix: The binfix package
priority: Internal types
property: Internal types

S
System, binfix: The binfix system

T
Type, priority: Internal types
Type, property: Internal types

Jump to:   B   P   S   T