diff --git a/code/basic-output.lisp b/code/basic-output.lisp index c392ec7..baf1ef4 100644 --- a/code/basic-output.lisp +++ b/code/basic-output.lisp @@ -10,10 +10,8 @@ (defmethod specialize-directive ((client client) (char (eql #\C)) directive) (change-class directive 'character-directive)) -(defmethod calculate-argument-position (position (item character-directive)) - (setf position (call-next-method)) - (when position - (1+ position))) +(defmethod traverse-item ((client client) (directive character-directive)) + (go-to-argument 1)) (defun format-char (client colon-p at-sign-p char) (cond (colon-p diff --git a/code/control-flow-operations.lisp b/code/control-flow-operations.lisp index c8de95e..3951f33 100644 --- a/code/control-flow-operations.lisp +++ b/code/control-flow-operations.lisp @@ -16,16 +16,16 @@ :bind nil :default nil))) -(defmethod calculate-argument-position (position (item go-to-directive)) - (when (and position - (typep (car (parameters item)) 'literal-parameter)) - (let ((n (parameter-value (car (parameters item))))) - (cond ((colon-p item) - (- position (or n 1))) - ((at-sign-p item) - (or n 0)) - (t - (+ position (or n 1))))))) +(defmethod traverse-item ((client client) (item go-to-directive)) + (if (not (typep (car (parameters item)) 'literal-parameter)) + (go-to-argument nil t) + (let ((n (parameter-value (car (parameters item))))) + (cond ((colon-p item) + (go-to-argument (- (or n 1)))) + ((at-sign-p item) + (go-to-argument (or n 0) t)) + (t + (go-to-argument (or n 1))))))) (defmethod interpret-item ((client client) (directive go-to-directive) &optional parameters) @@ -121,45 +121,48 @@ :bind nil :default nil))) -(defmethod calculate-argument-position (position (directive conditional-expression-directive)) - (setf position (call-next-method)) - (when position - (cond ((at-sign-p directive) +(defmethod traverse-item ((client client) (directive conditional-expression-directive)) + (let ((index (funcall *argument-index*))) + (cond ((null index)) + ((at-sign-p directive) + (traverse-item client (first (clauses directive))) ;; consequent must consume 1 argument. - (when (eql (1+ position) - (calculate-argument-position position (first (clauses directive)))) - (1+ position))) + (unless (= (1+ index) (funcall *argument-index*)) + (go-to-argument nil))) ((colon-p directive) - ;; alternative and consequent must consume the same number of arguments. - (incf position) - (let ((pos0 (calculate-argument-position position (first (clauses directive)))) - (pos1 (calculate-argument-position position (second (clauses directive))))) - (when (eql pos0 pos1) - pos0))) + (go-to-argument 1) + (let ((pos0 (funcall *argument-index*))) + (traverse-item client (first (clauses directive))) + (let ((pos1 (funcall *argument-index*))) + (go-to-argument pos0 t) + (traverse-item client (second (clauses directive))) + ;; alternative and consequent must consume the same number of arguments. + (unless (eql pos1 (funcall *argument-index*)) + (go-to-argument nil))))) ((typep (car (parameters directive)) 'argument-reference-parameter) - nil) + (go-to-argument nil)) ((and (typep (car (parameters directive)) 'literal-parameter) (parameter-value (car (parameters directive)))) (let ((value (parameter-value (car (parameters directive))))) (cond ((< -1 value (length (clauses directive))) - (calculate-argument-position position (nth value (clauses directive)))) + (traverse-item client (nth value (clauses directive)))) ((last-clause-is-default-p directive) - (calculate-argument-position position - (nth (1- (length (clauses directive))) - (clauses directive)))) - (t - position)))) + (traverse-item client + (nth (1- (length (clauses directive))) + (clauses directive))))))) (t (when (typep (car (parameters directive)) 'literal-parameter) - (incf position)) - (let ((new-position (if (last-clause-is-default-p directive) - (calculate-argument-position position (first (clauses directive))) - position))) - (when (every (lambda (clause) - (eql new-position - (calculate-argument-position position clause))) - (clauses directive)) - new-position)))))) + (go-to-argument 1)) + (let ((start-index (funcall *argument-index*))) + (when (last-clause-is-default-p directive) + (traverse-item client (car (last (clauses directive))))) + (let ((end-index (funcall *argument-index*))) + (loop for clause in (clauses directive) + do (go-to-argument start-index t) + (traverse-item client clause) + unless (eql (funcall *argument-index*) end-index) + do (go-to-argument nil) + and return nil))))))) (defmethod check-item-syntax progn ((client client) (directive conditional-expression-directive) global-layout @@ -290,10 +293,13 @@ :type (or null (integer 0)) :default nil))) -(defmethod calculate-argument-position (position (directive iteration-directive)) - (unless (at-sign-p directive) - (+ position - (if (empty-clause-p (first (clauses directive))) 2 1)))) +(defmethod traverse-item ((client client) (directive iteration-directive)) + (go-to-argument (cond ((at-sign-p directive) + nil) + ((empty-clause-p (first (clauses directive))) + 2) + (t + 1)))) (defun format-single-recursive-iteration (client colon-p oncep iteration-limit control arg) (if colon-p @@ -481,9 +487,10 @@ (defmethod specialize-directive ((client client) (char (eql #\?)) directive) (change-class directive 'recursive-processing-directive)) -(defmethod calculate-argument-position (position (directive recursive-processing-directive)) - (unless (at-sign-p directive) - (1+ position))) +(defmethod traverse-item ((client client) (directive recursive-processing-directive)) + (if (at-sign-p directive) + (go-to-argument nil t) + (go-to-argument 2))) (defmethod interpret-item ((client client) (directive recursive-processing-directive) &optional parameters) diff --git a/code/directive.lisp b/code/directive.lisp index 7900e0d..b25b7e3 100644 --- a/code/directive.lisp +++ b/code/directive.lisp @@ -55,9 +55,8 @@ (defclass argument-reference-parameter (parameter) ()) -(defmethod calculate-argument-position (position (item argument-reference-parameter)) - (when position - (1+ position))) +(defmethod traverse-item ((client client) (item argument-reference-parameter)) + (go-to-argument 1)) (defclass remaining-argument-count-parameter (parameter) ()) @@ -133,12 +132,10 @@ (defun empty-clause-p (clause) (null (items clause))) -(defmethod calculate-argument-position (position (clause clause)) - (setf position (reduce #'calculate-argument-position (items clause) - :initial-value position)) - (if (terminator clause) - (calculate-argument-position position (terminator clause)) - position)) +(defmethod traverse-item ((client client) (clause clause)) + (loop for item in (items clause) + do (traverse-item client item) + finally (traverse-item client (terminator clause)))) (defmethod interpret-item ((client client) (clause clause) &optional parameters) (declare (ignore parameters)) @@ -186,8 +183,9 @@ (end (terminator (car (last (clauses directive))))) (end directive))) -(defmethod calculate-argument-position (position (item directive)) - (reduce #'calculate-argument-position (parameters item) :initial-value position)) +(defmethod traverse-item :before ((client client) (item directive)) + (loop for parameter in (parameters item) + do (traverse-item client parameter))) ;;; Checking syntax, interpreting, and compiling directives. diff --git a/code/expansion.lisp b/code/expansion.lisp index c18d561..1a7eca3 100644 --- a/code/expansion.lisp +++ b/code/expansion.lisp @@ -1,115 +1,144 @@ (cl:in-package #:invistra) +(defun expand-formatter/indeterminate (client items) + (with-unique-names (rest) + `(lambda (*format-output* &rest ,rest) + (with-arguments (,(trinsic:client-form client) ,rest) + ,@(compile-items client items) + (pop-remaining-arguments))))) + (defstruct lambda-argument (name (unique-name '#:arg)) namep (type t)) -(defun expand-formatter (client control-string) - (check-type control-string string) +(defun expand-formatter/determinate (client items) (with-unique-names (block rest count) - (let ((items (parse-control-string client control-string))) - (if (reduce #'calculate-argument-position items :initial-value 0) - (let* ((args (make-array 8 :adjustable t :fill-pointer 0)) - (restp t) - (guts (let* ((pos 0) - (*outer-exit-if-exhausted* *inner-exit-if-exhausted*) - (*outer-exit* *inner-exit*) - (*more-arguments-p* - (lambda () - (if (< pos (length args)) - (or (lambda-argument-namep (aref args pos)) t) - (let ((arg (make-lambda-argument :namep - (unique-name '#:argp)))) - (vector-push-extend arg args) - (or (lambda-argument-namep arg) t))))) - (*argument-index* - (lambda () pos)) - (*remaining-argument-count* - (lambda () - `(- ,count - ,(loop for arg across args - repeat pos - count (not (lambda-argument-namep arg)))))) - (*pop-argument* - (lambda (&optional (type t)) - (if (< pos (length args)) - (let ((arg (aref args pos))) - (when (subtypep type (lambda-argument-type arg)) - (setf (lambda-argument-type arg) type)) - (incf pos) - (lambda-argument-name arg)) - (let ((arg (make-lambda-argument :type type))) - (vector-push-extend arg args) - (incf pos) - (lambda-argument-name arg))))) - (pop-remaining-arguments-hook - (lambda () - (when restp - (setf restp nil) - (if (< pos (length args)) - (nconc (list 'list*) - (loop for i from pos - below (length args) - collect (lambda-argument-name (aref args i))) - (list rest)) - rest)))) - (*pop-remaining-arguments* pop-remaining-arguments-hook) - (*go-to-argument* - (lambda (index &optional absolutep) - (setf pos (if absolutep index (+ index pos))) - (when (minusp pos) - (error 'go-to-out-of-bounds - :argument-position pos - :argument-count (length args))) - (loop for i from (length args) below pos - do (vector-push-extend (make-lambda-argument) args)))) - (*inner-exit-if-exhausted* - (lambda () - (unless (< pos (length args)) - (let ((arg (make-lambda-argument :namep - (unique-name '#:argp)))) - (vector-push-extend arg args) - `((unless ,(lambda-argument-namep arg) - (return-from ,block - ,(funcall pop-remaining-arguments-hook)))))))) - (*inner-exit* (lambda () - `((return-from ,block - ,(pop-remaining-arguments-form)))))) - (nconc (compile-items client items) - (list (pop-remaining-arguments-form))))) - (lambda-args (loop with required = t - for arg across args - when (and (lambda-argument-namep arg) - required) - collect '&optional - and do (setf required nil) - when (lambda-argument-namep arg) - collect `(,(lambda-argument-name arg) nil - ,(lambda-argument-namep arg)) - else - collect (lambda-argument-name arg))) - (declarations (loop for arg across args - for type = (lambda-argument-type arg) - unless (eq type t) - collect `(type ,type ,(lambda-argument-name arg))))) - `(lambda (*format-output* ,@lambda-args &rest ,rest) - (declare (ignorable ,@(map 'list #'lambda-argument-name args) ,rest) - ,@declarations) - (let ((,count (+ ,(loop for arg across args - count (not (lambda-argument-namep arg))) - (list-length ,rest)))) - (declare (ignorable ,count)) - (block ,block - ,@guts)))) - `(lambda (*format-output* &rest ,rest) - (with-arguments (,(trinsic:client-form client) ,rest) - ,@(compile-items client items) - (pop-remaining-arguments))))))) + (let* ((args (make-array 8 :adjustable t :fill-pointer 0)) + (restp t) + (guts (let* ((pos 0) + (*outer-exit-if-exhausted* *inner-exit-if-exhausted*) + (*outer-exit* *inner-exit*) + (*more-arguments-p* + (lambda () + (if (< pos (length args)) + (or (lambda-argument-namep (aref args pos)) t) + (let ((arg (make-lambda-argument :namep + (unique-name '#:argp)))) + (vector-push-extend arg args) + (or (lambda-argument-namep arg) t))))) + (*argument-index* + (lambda () pos)) + (*remaining-argument-count* + (lambda () + `(- ,count + ,(loop for arg across args + repeat pos + count (not (lambda-argument-namep arg)))))) + (*pop-argument* + (lambda (&optional (type t)) + (if (< pos (length args)) + (let ((arg (aref args pos))) + (when (subtypep type (lambda-argument-type arg)) + (setf (lambda-argument-type arg) type)) + (incf pos) + (lambda-argument-name arg)) + (let ((arg (make-lambda-argument :type type))) + (vector-push-extend arg args) + (incf pos) + (lambda-argument-name arg))))) + (pop-remaining-arguments-hook + (lambda () + (when restp + (setf restp nil) + (if (< pos (length args)) + (nconc (list 'list*) + (loop for i from pos + below (length args) + collect (lambda-argument-name (aref args i))) + (list rest)) + rest)))) + (*pop-remaining-arguments* pop-remaining-arguments-hook) + (*go-to-argument* + (lambda (index &optional absolutep) + (setf pos (if absolutep index (+ index pos))) + (when (minusp pos) + (error 'go-to-out-of-bounds + :argument-position pos + :argument-count (length args))) + (loop for i from (length args) below pos + do (vector-push-extend (make-lambda-argument) args)))) + (*inner-exit-if-exhausted* + (lambda () + (unless (< pos (length args)) + (let ((arg (make-lambda-argument :namep + (unique-name '#:argp)))) + (vector-push-extend arg args) + `((unless ,(lambda-argument-namep arg) + (return-from ,block + ,(funcall pop-remaining-arguments-hook)))))))) + (*inner-exit* (lambda () + `((return-from ,block + ,(pop-remaining-arguments-form)))))) + (nconc (compile-items client items) + (list (pop-remaining-arguments-form))))) + (lambda-args (loop with required = t + for arg across args + when (and (lambda-argument-namep arg) + required) + collect '&optional + and do (setf required nil) + when (lambda-argument-namep arg) + collect `(,(lambda-argument-name arg) nil + ,(lambda-argument-namep arg)) + else + collect (lambda-argument-name arg))) + (declarations (loop for arg across args + for type = (lambda-argument-type arg) + unless (eq type t) + collect `(type ,type ,(lambda-argument-name arg))))) + `(lambda (*format-output* ,@lambda-args &rest ,rest) + (declare (ignorable ,@(map 'list #'lambda-argument-name args) ,rest) + ,@declarations) + (let ((,count (+ ,(loop for arg across args + count (not (lambda-argument-namep arg))) + (list-length ,rest)))) + (declare (ignorable ,count)) + (block ,block + ,@guts)))))) + +(defun expand-formatter (client control-string &optional argument-count) + (check-type control-string string) + (let ((items (parse-control-string client control-string)) + (pos 0)) + (loop with *go-to-argument* = (lambda (index &optional absolutep) + (cond ((null pos)) + ((null index) + (setf pos nil)) + (t + (setf pos (if absolutep index (+ index pos))) + (when (or (minusp pos) + (and argument-count + (> pos argument-count))) + (error 'go-to-out-of-bounds + :argument-position pos + :argument-count argument-count))))) + with *argument-index* = (lambda () pos) + with *inner-exit-if-exhausted* = (lambda () + (when (and pos argument-count + (>= pos argument-count)) + (return nil))) + with *inner-exit* = (lambda () + (return nil)) + for item in items + do (traverse-item client item)) + (if pos + (expand-formatter/determinate client items) + (expand-formatter/indeterminate client items)))) -(defun maybe-expand-formatter (client control-string) +(defun maybe-expand-formatter (client control-string &optional argument-count) (if (stringp control-string) - (values (expand-formatter client control-string) t) + (values (expand-formatter client control-string argument-count) t) (values control-string nil))) (defun expand-format (client form destination control-string args) @@ -126,7 +155,7 @@ `(format-with-client ,(trinsic:client-form client) ,destination ,formatter ,@args))))) (cond ((stringp control-string) - (funcall-expand (expand-formatter client control-string))) + (funcall-expand (expand-formatter client control-string (length args)))) ((and (consp control-string) (eq (car control-string) 'function) (cdr control-string) diff --git a/code/extension-extrinsic/interface.lisp b/code/extension-extrinsic/interface.lisp index 9ed045c..5948db9 100644 --- a/code/extension-extrinsic/interface.lisp +++ b/code/extension-extrinsic/interface.lisp @@ -2,7 +2,7 @@ (defclass client (inravina-extension-extrinsic:client invistra-extension:client) ()) -(defclass client-impl (client quaviver/schubfach:client quaviver/liebler:client) ()) +(defclass client-impl (client quaviver/schubfach:client) ()) (change-class incless-extension-extrinsic:*client* 'client-impl) diff --git a/code/extension-intrinsic/interface.lisp b/code/extension-intrinsic/interface.lisp index 837d781..1ebd778 100644 --- a/code/extension-intrinsic/interface.lisp +++ b/code/extension-intrinsic/interface.lisp @@ -2,7 +2,7 @@ (defclass client (inravina-extension-intrinsic:client invistra:client) ()) -(defclass client-impl (client quaviver/schubfach:client quaviver/liebler:client) ()) +(defclass client-impl (client quaviver/schubfach:client) ()) (change-class incless-extension-intrinsic:*client* 'client-impl) diff --git a/code/extrinsic/interface.lisp b/code/extrinsic/interface.lisp index a338add..f669962 100644 --- a/code/extrinsic/interface.lisp +++ b/code/extrinsic/interface.lisp @@ -2,7 +2,7 @@ (defclass client (inravina-extrinsic:client invistra:client) ()) -(defclass client-impl (client quaviver/schubfach:client quaviver/liebler:client) ()) +(defclass client-impl (client quaviver/schubfach:client) ()) (change-class incless-extrinsic:*client* 'client-impl) diff --git a/code/extrinsic/unit-test/test.lisp b/code/extrinsic/unit-test/test.lisp index 639a057..6b4d578 100644 --- a/code/extrinsic/unit-test/test.lisp +++ b/code/extrinsic/unit-test/test.lisp @@ -1277,6 +1277,7 @@ ;; Test that going beyond the first or last argument ;; gives an error. +#-(or abcl clasp ecl cmucl) (define-argument-fail-test go-to.12 (fmt nil "~c~c~*" #\a #\b)) @@ -1289,6 +1290,7 @@ (define-control-fail-test go-to.15 (fmt nil "~c~-1@*~0@*~c" #\a #\b #\c)) +#-(or abcl clasp ecl cmucl) (define-argument-fail-test go-to.16 (fmt nil "~c~4@*~0@*~c" #\a #\b #\c)) diff --git a/code/extrinsic/unit-test/utilities.lisp b/code/extrinsic/unit-test/utilities.lisp index c6879ff..126416b 100644 --- a/code/extrinsic/unit-test/utilities.lisp +++ b/code/extrinsic/unit-test/utilities.lisp @@ -62,7 +62,7 @@ (defmacro define-argument-fail-test (name form) `(define-test ,name :compile-at :execute - (fail (macrolet ((fmt (destination control-string &rest args) + (fail-compile (macrolet ((fmt (destination control-string &rest args) `(invistra-extrinsic:format ,destination ,control-string ,@args))) ,form)) (fail (macrolet ((fmt (destination control-string &rest args) diff --git a/code/floating-point-printers.lisp b/code/floating-point-printers.lisp index 6a66958..dee69f0 100644 --- a/code/floating-point-printers.lisp +++ b/code/floating-point-printers.lisp @@ -34,22 +34,28 @@ (quaviver:float-triple client 10 coerced-value))))) (defun round-away-from-zero (client value significand exponent sign n) + (declare (ignore sign)) (multiple-value-bind (q r) (truncate significand n) (let ((d (* 2 r))) - (cond ((< d n) + (cond ((< d n) ; rounding down q) - ((> d 10) - (1+ q)) - ((< (abs (- (quaviver:triple-float client (type-of value) 10 (+ significand 5) - exponent sign) - value)) - (abs (- value - (quaviver:triple-float client (type-of value) 10 (- significand 5) - exponent sign)))) + ((> d 10) ; we are rounding up on a digit that is not a 5 in the ones place. (1+ q)) + ((minusp exponent) + (multiple-value-bind (significand2 exponent2) + (quaviver:float-triple client 2 value) + (if (<= (ash significand (- exponent2)) + (* significand2 (expt 10 (- exponent)))) + (1+ q) ; base-10 significand was underestimate so round up + q))) ; base-10 significand was overestimate so round down (t - q))))) + (multiple-value-bind (significand2 exponent2) + (quaviver:float-triple client 2 value) + (if (<= (* significand (expt 10 exponent)) + (ash significand2 exponent2)) + (1+ q) ; base-10 significand was underestimate so round up + q))))))) ; base-10 significand was overestimate so round down (defun trim-fractional (client value significand exponent sign digit-count fractional-position d) @@ -118,12 +124,12 @@ :default #\Space :bind nil))) -(defmethod calculate-argument-position (position (directive fixed-format-directive)) - (1+ (call-next-method))) +(defmethod traverse-item ((client client) (directive fixed-format-directive)) + (go-to-argument 1)) (defun %format-fixed-format-float (client colon-p at-sign-p w d k overflowchar padchar value significand exponent sign) - (declare (ignore client colon-p)) + (declare (ignore colon-p)) (let* ((sign-char (cond ((minusp sign) #\-) ((and at-sign-p (plusp sign)) #\+))) (digit-count (quaviver.math:count-digits 10 significand)) @@ -244,13 +250,13 @@ :default nil :bind nil))) -(defmethod calculate-argument-position (position (directive exponential-directive)) - (1+ (call-next-method))) +(defmethod traverse-item ((client client) (directive exponential-directive)) + (go-to-argument 1)) (defun %format-exponential-float (client colon-p at-sign-p w d e k overflowchar padchar exponentchar value significand exponent sign) - (declare (ignore client colon-p)) + (declare (ignore colon-p)) (let* ((sign-char (cond ((minusp sign) #\-) ((and at-sign-p (plusp sign)) #\+))) (digit-count (quaviver.math:count-digits 10 significand)) @@ -386,8 +392,8 @@ :default nil :bind nil))) -(defmethod calculate-argument-position (position (directive general-directive)) - (1+ (call-next-method))) +(defmethod traverse-item ((client client) (directive general-directive)) + (go-to-argument 1)) (defun %format-general-float (client colon-p at-sign-p w d e k overflowchar padchar exponentchar value significand @@ -455,9 +461,6 @@ :default #\Space :bind nil))) -(defmethod calculate-argument-position (position (directive monetary-directive)) - (1+ (call-next-method))) - (defun %format-monetary-float (client colon-p at-sign-p d n w padchar value significand exponent sign) (let* ((sign-char (cond ((minusp sign) #\-) diff --git a/code/generic-functions.lisp b/code/generic-functions.lisp index a08a912..2ba1a30 100644 --- a/code/generic-functions.lisp +++ b/code/generic-functions.lisp @@ -68,10 +68,9 @@ (defgeneric make-argument-cursor (client object)) -(defgeneric calculate-argument-position (position item) - (:method (position item) - (declare (ignore item)) - position)) +(defgeneric traverse-item (client item) + (:method (client item) + (declare (ignore client item)))) (defgeneric end (directive)) diff --git a/code/interface.lisp b/code/interface.lisp index e4f6e60..7f6d88b 100644 --- a/code/interface.lisp +++ b/code/interface.lisp @@ -68,7 +68,7 @@ (expand-function ,client-form form 1)) (define-compiler-macro ,invalid-method-error-sym (&whole form &rest args) - (declare (ignore method args)) + (declare (ignore args)) (expand-function ,client-form form 2)) (define-compiler-macro ,method-combination-error-sym (&whole form &rest args) diff --git a/code/intrinsic/interface.lisp b/code/intrinsic/interface.lisp index 0a1dc04..a823928 100644 --- a/code/intrinsic/interface.lisp +++ b/code/intrinsic/interface.lisp @@ -4,7 +4,7 @@ (#-sicl inravina-intrinsic:client #+sicl incless-intrinsic:client invistra:client) ()) -(defclass client-impl (client quaviver/schubfach:client quaviver/liebler:client) ()) +(defclass client-impl (client quaviver/schubfach:client) ()) (setf incless-intrinsic:*client* (make-instance 'client-impl)) diff --git a/code/layout-control.lisp b/code/layout-control.lisp index 6509f22..55a5bc0 100644 --- a/code/layout-control.lisp +++ b/code/layout-control.lisp @@ -125,10 +125,9 @@ :dynamic (colon-p (terminator (first (clauses directive))))) parent group position)) -(defmethod calculate-argument-position (position (directive justification-directive)) - (reduce #'calculate-argument-position - (clauses directive) - :initial-value (call-next-method))) +(defmethod traverse-item ((client client) (directive justification-directive)) + (loop for clause in (clauses directive) + do (traverse-item client clause))) (defun str-line-length (stream) (or *print-right-margin* diff --git a/code/miscellaneous-operations.lisp b/code/miscellaneous-operations.lisp index 229c3b8..8f1e924 100644 --- a/code/miscellaneous-operations.lisp +++ b/code/miscellaneous-operations.lisp @@ -15,8 +15,8 @@ (defclass case-conversion-directive (directive structured-directive-mixin) ()) -(defmethod calculate-argument-position (position (directive case-conversion-directive)) - (calculate-argument-position position (first (clauses directive)))) +(defmethod traverse-item ((client client) (directive case-conversion-directive)) + (traverse-item client (first (clauses directive)))) (defmethod specialize-directive ((client client) (char (eql #\()) directive) (change-class directive 'case-conversion-directive)) @@ -70,10 +70,9 @@ (defmethod specialize-directive ((client client) (char (eql #\P)) directive) (change-class directive 'plural-directive)) -(defmethod calculate-argument-position (position (directive plural-directive)) - (if (or (colon-p directive) (null position)) - position - (1+ position))) +(defmethod traverse-item ((client client) (directive plural-directive)) + (unless (colon-p directive) + (go-to-argument 1))) (defmethod interpret-item ((client client) (directive plural-directive) &optional parameters) diff --git a/code/miscellaneous-pseudo-operations.lisp b/code/miscellaneous-pseudo-operations.lisp index e544a89..24b8b0f 100644 --- a/code/miscellaneous-pseudo-operations.lisp +++ b/code/miscellaneous-pseudo-operations.lisp @@ -77,6 +77,25 @@ (not (colon-p parent)))) (signal-illegal-outer-modifier client directive))) +(defmethod traverse-item + ((client client) (directive escape-upward-directive)) + (when (every (lambda (parameter) + (typep parameter 'literal-parameter)) + (parameters directive)) + (let ((p1 (parameter-value (first (parameters directive)))) + (p2 (parameter-value (second (parameters directive)))) + (p3 (parameter-value (third (parameters directive))))) + (cond ((and (null p1) (null p2) (null p3)) + (funcall *inner-exit-if-exhausted*)) + ((or (and p3 + (<= p1 p2 p3)) + (and (null p3) + (or (and (null p2) + (eql p1 0)) + (and p2 + (eql p1 p2))))) + (funcall *inner-exit*)))))) + (defmethod interpret-item ((client client) (directive escape-upward-directive) &optional parameters) (with-accessors ((colon-p colon-p)) diff --git a/code/packages.lisp b/code/packages.lisp index 5ae8776..ee296f5 100644 --- a/code/packages.lisp +++ b/code/packages.lisp @@ -93,6 +93,7 @@ #:start #:suffix-start #:symbol-not-external + #:traverse-item #:unknown-directive-character #:write-cardinal-numeral #:write-old-roman-numeral diff --git a/code/pretty-printer-operations.lisp b/code/pretty-printer-operations.lisp index 95f2d7d..4f97b43 100644 --- a/code/pretty-printer-operations.lisp +++ b/code/pretty-printer-operations.lisp @@ -63,15 +63,13 @@ (declare (ignore items)) (change-class directive 'logical-block-directive)) -(defmethod calculate-argument-position (position (directive logical-block-directive)) - (setf position (call-next-method)) - (cond ((at-sign-p directive) - (calculate-argument-position (if (cdr (clauses directive)) - (second (clauses directive)) - (first (clauses directive))) - position)) - (position - (1+ position)))) +(defmethod traverse-item ((client client) (directive logical-block-directive)) + (if (at-sign-p directive) + (traverse-item client + (if (cdr (clauses directive)) + (second (clauses directive)) + (first (clauses directive)))) + (go-to-argument 1))) (defmethod check-item-syntax :around ((client client) (directive logical-block-directive) global-layout local-layout diff --git a/code/printer-operations.lisp b/code/printer-operations.lisp index 5cd6ed4..f86d281 100644 --- a/code/printer-operations.lisp +++ b/code/printer-operations.lisp @@ -27,10 +27,8 @@ :bind nil :default #\Space))) -(defmethod calculate-argument-position (position (directive aesthetic-directive)) - (setf position (call-next-method)) - (when position - (1+ position))) +(defmethod traverse-item ((client client) (directive aesthetic-directive)) + (go-to-argument 1)) (defun format-aesthetic (client colon-p at-sign-p mincol colinc minpad padchar value) (flet ((write-value () @@ -114,10 +112,8 @@ :bind nil :default #\Space))) -(defmethod calculate-argument-position (position (directive standard-directive)) - (setf position (call-next-method)) - (when position - (1+ position))) +(defmethod traverse-item ((client client) (directive standard-directive)) + (go-to-argument 1)) (defun format-standard (client colon-p at-sign-p mincol colinc minpad padchar value) (flet ((write-value () @@ -186,10 +182,8 @@ (merge-layout client directive global-layout local-layout :logical-block t) parent group position)) -(defmethod calculate-argument-position (position (directive write-directive)) - (setf position (call-next-method)) - (when position - (1+ position))) +(defmethod traverse-item ((client client) (directive write-directive)) + (go-to-argument 1)) (defun format-write (client colon-p at-sign-p value) (cond ((and colon-p at-sign-p) diff --git a/code/radix-control.lisp b/code/radix-control.lisp index 863317a..9a717d4 100644 --- a/code/radix-control.lisp +++ b/code/radix-control.lisp @@ -23,10 +23,8 @@ :bind nil :default 3))) -(defmethod calculate-argument-position (position (directive base-radix-directive)) - (setf position (call-next-method)) - (when position - (1+ position))) +(defmethod traverse-item ((client client) (directive base-radix-directive)) + (go-to-argument 1)) (defun format-radix-numeral (client colon-p at-sign-p radix mincol padchar commachar comma-interval value) diff --git a/invistra-extension-extrinsic.asd b/invistra-extension-extrinsic.asd index a7181ad..9eab645 100644 --- a/invistra-extension-extrinsic.asd +++ b/invistra-extension-extrinsic.asd @@ -10,8 +10,7 @@ :homepage "https://github.com/s-expressionists/Invistra" :bug-tracker "https://github.com/s-expressionists/Invistra/issues" :depends-on ("invistra-extension" - "inravina-extension-extrinsic" - "quaviver/liebler") + "inravina-extension-extrinsic") :components ((:module code :pathname "code/extension-extrinsic/" :serial t diff --git a/invistra-extension-intrinsic.asd b/invistra-extension-intrinsic.asd index 9304878..2170cdb 100644 --- a/invistra-extension-intrinsic.asd +++ b/invistra-extension-intrinsic.asd @@ -10,8 +10,7 @@ :homepage "https://github.com/s-expressionists/Invistra" :bug-tracker "https://github.com/s-expressionists/Invistra/issues" :depends-on ("invistra-extension" - "inravina-extension-intrinsic" - "quaviver/liebler") + "inravina-extension-intrinsic") :components ((:module code :pathname "code/extension-intrinsic/" :serial t diff --git a/invistra-extrinsic.asd b/invistra-extrinsic.asd index bc9e575..ad6cb5e 100644 --- a/invistra-extrinsic.asd +++ b/invistra-extrinsic.asd @@ -10,8 +10,7 @@ :homepage "https://github.com/s-expressionists/Invistra" :bug-tracker "https://github.com/s-expressionists/Invistra/issues" :depends-on ("invistra" - "inravina-extrinsic" - "quaviver/liebler") + "inravina-extrinsic") :in-order-to ((asdf:test-op (asdf:test-op "invistra-extrinsic/ansi-test"))) :components ((:module code :pathname "code/extrinsic/" diff --git a/invistra-intrinsic.asd b/invistra-intrinsic.asd index 8b527d1..03a3cb3 100644 --- a/invistra-intrinsic.asd +++ b/invistra-intrinsic.asd @@ -10,8 +10,7 @@ :homepage "https://github.com/s-expressionists/Invistra" :bug-tracker "https://github.com/s-expressionists/Invistra/issues" :depends-on ("invistra" - "inravina-intrinsic" - "quaviver/liebler") + "inravina-intrinsic") :components ((:module code :pathname "code/intrinsic/" :serial t