X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/4979de888ad699695849a884e0ab8faedd3544f1..2c6153373f927d948a74b283ebb16330af8ee49a:/src/pset-parse.lisp diff --git a/src/pset-parse.lisp b/src/pset-parse.lisp index cfd2b4a..e3c0d4b 100644 --- a/src/pset-parse.lisp +++ b/src/pset-parse.lisp @@ -77,7 +77,25 @@ ;; Evaluate X and Y to integers, and apply INTOP to the ;; results, giving another integer. (oplambda - (values :int (funcall intop (want :int x) (want :int y)))))) + (values :int (funcall intop (want :int x) (want :int y))))) + + (compareop (intop strop x y) + ;; Evaluate X and Y. If they're integers, then apply INTOP to + ;; them; if they're strings, apply STROP. The result is a + ;; boolean. + (oplambda + (multiple-value-bind (xty xval) (funcall x) + (case xty + (:int + (values :boolean + (funcall intop xval (want :int y)))) + ((:id :string :symbol) + (values :boolean + (funcall strop + (coerce-property-value xval xty :id) + (want :id y)))) + (t + (error "Can't compare objects of type ~(~A~)" xty))))))) (with-parser-context (token-scanner-context :scanner scanner) (when-parse () @@ -145,10 +163,42 @@ (when (zerop y) (error "Division by zero")) (values :int (floor x y))))) (:op #\+ binop "+" (x y 60) (int-binop #'+ x y)) - (:op #\- binop "-" (x y 60) (int-binop #'- x y))) + (:op #\- binop "-" (x y 60) (int-binop #'- x y)) + (:op :shl binop "<<" (x y 50) (int-binop #'ash x y)) + (:op :shr binop ">>" (x y 50) + (int-binop (lambda (x y) (ash x (- y))) x y)) + (:op #\< binop "<" (x y 45) + (compareop #'< #'string< x y)) + (:op :le binop "<=" (x y 45) + (compareop #'<= #'string<= x y)) + (:op :ge binop ">=" (x y 45) + (compareop #'>= #'string>= x y)) + (:op #\> binop ">" (x y 45) + (compareop #'> #'string> x y)) + (:op :eq binop "==" (x y 40) + (compareop #'= #'string= x y)) + (:op :ne binop "!=" (x y 40) + (compareop #'/= #'string/= x y)) + (:op #\& binop "&" (x y 37) (int-binop #'logand x y)) + (:op #\^ binop "^" (x y 35) (int-binop #'logxor x y)) + (:op #\| binop "|" (x y 32) (int-binop #'logior x y)) + (:op :and binop "&&" (x y 27) + (oplambda (if (want :boolean x) (funcall y) + (values :boolean nil)))) + (:op :or binop "||" (x y 22) + (oplambda + (multiple-value-bind (xty xval) (funcall x) + (if (coerce-property-value xval xty :boolean) + (values xty xval) + (funcall y)))))) ;; Prefix operators. - ((:op #\+ preop "+" (x 90) (int-unop #'identity x)) + ((:op #\~ preop "~" (x 90) (int-unop #'lognot x)) + (:op #\! preop "!" (x 90) + (oplambda + (values :boolean + (not (want :boolean (funcall x)))))) + (:op #\+ preop "+" (x 90) (int-unop #'identity x)) (:op #\- preop "-" (x 90) (int-unop #'- x)) (:op #\( lparen #\)))