X-Git-Url: https://git.distorted.org.uk/~mdw/lisp/blobdiff_plain/1b35c11e81637c1fb06cab552c2ca91facb373a9..fe0f07ea19b36ce1abc1ec305d0203323cbf2316:/infix.lisp diff --git a/infix.lisp b/infix.lisp index 73fc339..9c77afe 100644 --- a/infix.lisp +++ b/infix.lisp @@ -34,7 +34,8 @@ #:++ #:-- #:<< #:>> #:if #:then #:else - #:let #:let* #:in)) + #:let #:let* #:in + #:bind)) (defpackage #:infix (:use #:common-lisp #:infix-keywords) @@ -69,7 +70,7 @@ (name nil :type symbol) (lprec nil :type (or fixnum null)) (rprec nil :type (or fixnum null)) - (func (lambda () nil) :type (function () t))) + (func (lambda () nil) :type #-ecl (function () t) #+ecl function)) ;;;-------------------------------------------------------------------------- ;;; Global parser state. @@ -606,20 +607,22 @@ (defopfunc loop operand (get-token) - (pushval `(loop ,@(progn (strip-progn (parse-infix 0)))))) - -(defopfunc multiple-value-bind operand - (get-token) - (pushval `(multiple-value-bind - ,(parse-ident-list) - ,(progn (delim '=) (parse-infix)) - ,@(progn (delim 'in) (strip-progn (parse-infix 0)))))) - -(defopfunc multiple-value-setq operand - (get-token) - (pushval `(multiple-value-setq - ,(parse-ident-list) - ,(progn (delim '=) (parse-infix 0))))) + (pushval `(loop ,@(strip-progn (parse-infix 0))))) + +(defopfunc bind operand + (labels ((loop () + (let ((ids (parse-ident-list)) + (valform (progn (delim '=) (parse-infix 0))) + (body (if (delim '|,| nil) + (loop) + (progn + (delim 'in) + (strip-progn (parse-infix 0)))))) + (list (if (and ids (null (cdr ids))) + `(let ((,(car ids) ,valform)) ,@body) + `(multiple-value-bind ,ids ,valform ,@body)))))) + (get-token) + (pushval (car (loop))))) ;;;-------------------------------------------------------------------------- ;;; Parsing function bodies and lambda lists. @@ -714,14 +717,27 @@ (unless (eq *token* delim) (error "expected ~S; found ~S" delim *token*))))) -(defun install-infix-reader (&optional (char #\$)) - "Installs a macro character `$ INFIX... $' for translating infix notation +(defun install-infix-reader + (&optional (start #\{) (end #\}) &key dispatch (readtable *readtable*)) + "Installs a macro character `{ INFIX... }' for translating infix notation to Lisp forms. You also want to (use-package :infix-keywords) if you do this." - (let ((delim (intern (string #\$) 'infix-keywords))) - (set-macro-character char (lambda (stream ch) - (declare (ignore ch)) - (read-infix stream :delim delim))))) + (let ((delim (intern (string end) 'infix-keywords))) + (flet ((doit (stream &rest noise) + (declare (ignore noise)) + (read-infix stream :delim delim))) + (if dispatch + (set-dispatch-macro-character dispatch start #'doit readtable) + (set-macro-character start #'doit nil readtable)) + (unless (or (eql start end) + (multiple-value-bind + (func nontermp) + (get-macro-character end readtable) + (and func (not nontermp)))) + (set-macro-character end (lambda (noise) + (declare (ignore noise)) + (error "Unexpected `~C'." end)) + nil readtable))))) ;;;-------------------------------------------------------------------------- ;;; Testing things. @@ -799,8 +815,14 @@ (labels ((foo (x) (+ x 1)) (bar (x) (- x 1))) (foo (bar y)))) ("defun foo (x) x - 6" . (defun foo (x) (- x 6))) - ("multiple-value-bind x, y, z = values(4, 6, 8) in x + y + z" . - (multiple-value-bind (x y z) (values 4 6 8) (+ x y z))))) + ("bind x = 3 in x - 2" . (let ((x 3)) (- x 2))) + ("bind x, y = values(1, 2), + z = 3, + docs, decls, body = parse-body(body) in complicated" . + (multiple-value-bind (x y) (values 1 2) + (let ((z 3)) + (multiple-value-bind (docs decls body) (parse-body body) + complicated)))))) ;;;-------------------------------------------------------------------------- ;;; Debugging guff.