In a move that's bound to offend Lisp purists, I have added support for C-style arrays in pLisp; it is now possible to get and set array elements by syntax like a[10 2]. I initially thought of doing this the canonical way, i.e. a[10][2], but this complicates the lexical analysis (I have already introduced shift/reduce conflicts with these changes), so a single pair of square brackets will have to do.
You can thus do things like these now:
USER> (define a (array (2 2) 1))
A
USER> a
[[1 1] [1 1]]
USER> a[0 0]
1
USER> (aset a[0 0] 100)
100
USER> a
[[100 1] [1 1]]
array and aset are macros that internally call make-array and array-get/array-set respectively:
(defmacro array (dims default-value)
(if (eq (length dims) 1)
`(make-array ,(car dims) ,default-value)
`(make-array ,(car dims) (array ,(cdr dims) ,default-value))))
(defmacro aset (ref val)
(let ((a (second ref))
(last-index (last ref))
(indexes (butlast (cddr ref) 1)))
`(array-set (build-ref ,a ,indexes) ,last-index ,val)))
During lexical analysis, the form a[x y] is converted into a list (aref x y) so that the sanctum sanctorum of the interpreter and other bits of pLisp are not polluted by the impurity of the square brackets.
build-ref is a macro that is used internally to convert a reference of the form (aref array-name i1 i2 ...) to one that uses array-get.
(defmacro build-ref (a indexes)
(let ((rev-indexes (reverse indexes)))
(if (eq (length rev-indexes) 1)
`(array-get ,a ,(car rev-indexes))
`(array-get (build-ref ,a ,(cdr rev-indexes)) ,(car rev-indexes)))))
You can thus do things like these now:
USER> (define a (array (2 2) 1))
A
USER> a
[[1 1] [1 1]]
USER> a[0 0]
1
USER> (aset a[0 0] 100)
100
USER> a
[[100 1] [1 1]]
array and aset are macros that internally call make-array and array-get/array-set respectively:
(defmacro array (dims default-value)
(if (eq (length dims) 1)
`(make-array ,(car dims) ,default-value)
`(make-array ,(car dims) (array ,(cdr dims) ,default-value))))
(defmacro aset (ref val)
(let ((a (second ref))
(last-index (last ref))
(indexes (butlast (cddr ref) 1)))
`(array-set (build-ref ,a ,indexes) ,last-index ,val)))
During lexical analysis, the form a[x y] is converted into a list (aref x y) so that the sanctum sanctorum of the interpreter and other bits of pLisp are not polluted by the impurity of the square brackets.
build-ref is a macro that is used internally to convert a reference of the form (aref array-name i1 i2 ...) to one that uses array-get.
(defmacro build-ref (a indexes)
(let ((rev-indexes (reverse indexes)))
(if (eq (length rev-indexes) 1)
`(array-get ,a ,(car rev-indexes))
`(array-get (build-ref ,a ,(cdr rev-indexes)) ,(car rev-indexes)))))