SubX Summary
Common Lisp extension that facilitates the use of infix notation for unary and binary operators. Includes arithmetic, logic, binary functions, assignment, sequencing. Allows the incorporation of s-expressions in an infix expression and vice versa.
Dependecies
ispbuilder-lexer => sublexer
lispbuilder-yacc, sublexer => subx
Download lispbuilder-yacc and lispbuilder-lexer here
Instalation
- Step1: load lispbuilder-yacc and lispbuilder-lexer
- Step2: (load "sublexer.lisp")
- Step3: (load "subx.lisp")
- Step4: import the package that contains the expressions (use-package :subx)
- Final step: to see it in action just (load "tests.lisp")
Description
The initial intent was to create a lisp extension that allows to easily write arithmetic expressions that can be understood by someone unfamiliar with lisp. Because function evaluation is a strongly desired feature in an expression, s-expressions are permitted in the context of an infix expression. Binary functions can also be used as operators with highest precedence. Variable scopes are implicitly set to the local infix expression if the variables don't exist otherwise the external context of the variables is used. Local scope can be forced by the local statement. Sequencing is done by the ',' operator.
The extension is created using Common Lisp read-time macros and standard macros. The '[' ']' characters are used as delimiters for the infix expression. The available operators are: + - * / = == >= <= > < += *= && || or any binary function.
Example 1:
[ x = 11, y = x mod 2, "x is " ++ (if [y == 0] "even" "odd") ]
Returns: "x is odd"
Here ++ is:
(defmethod ++((a list) (b list))
(concatenate 'list a b))
(defmethod ++((a string) (b string))
(concatenate 'string a b))
Obviously operators can be redefined because all of them are translated to function calls:
(defmacro __(x y)
`(range ,x ,y))
(defmacro ==(x y)
`(= ,x ,y))
(defmacro +=(x incval)
`(incf ,x ,incval))
(defmacro *=(x mulval)
`(setf ,x (* ,x ,mulval)))
Example2:
[ h = (make-hash-table), 'a gethash h = "a", 'a gethash h]
Returns: “a”
(progn
(defparameter x 1)
[ local (x) ( x = 2) ]
x)
Returns: 1
(mapcar (lambda (x) [x + 1]) [1 __ 5])
Returns: (2 3 4 5 6)
Use
Because lisp atoms can contain -/+* and these are frequently used in global vars : *global*, function names : make-hash-table subx requires spacing between each atom. This is not strictly required but there will be some inconsistencies if it is not supplied.
So just to be sure to separate everything with spaces (except the parens).
Future extensions
- Binary function call based on delimited operators: func-name start-delimiter parameter stop-delimiter. => a-hash { index }
- Where { is the start-delimiterand } is the stop delimiter.
- Generic methods toolkit for use with infix expressions.
- Binary operator user defined precedence and parameter pass order.
(ex: element gethash a-hash-table is better written a-hash-table gethash element, same for other functions)