Skip to content

Instantly share code, notes, and snippets.

@justindvs
Last active August 29, 2015 14:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save justindvs/e70c0fb971e308b62f01 to your computer and use it in GitHub Desktop.
Save justindvs/e70c0fb971e308b62f01 to your computer and use it in GitHub Desktop.
(Ab)Using Language Features: The Common Lisp Condition System
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This script works with GNU CLISP but may not work with other
;; implementations since the restarts which are provided are
;; implementation dependant. This will *not* work when compiled
;; since CLISP removes the use-value restart in compiled code.
;;
;; This script also uses quicklisp to load several third party
;; libraries (see http://www.quicklisp.org)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; C-Style Hex Literals
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(ql:quickload :cl-ppcre)
(defun hex-val (str)
"If a string looks like a hex string (like \"0x100\"), returns
the numeric value it represents. Else return nil."
(multiple-value-bind (match regs)
(cl-ppcre:scan-to-strings "^0[xX]([0-9a-fA-F]+)$" str)
(if match
(parse-integer (aref regs 0) :radix 16)
nil)))
(defun c-like-hex-literal-handler (condition)
"Given an unbound-variable condition, invokes the use-value
restart if the \"variable\" looks like a hex value."
(let* ((var-name (symbol-name (cell-error-name condition)))
(val (hex-val var-name)))
(when val
(invoke-restart 'use-value val))))
(defmacro with-hex-literals (&body body)
"Execute code within an environment where c-style hex literals
can be used (0x100, 0xFFFFFFFF) instead of the common lisp
hex literals (#x100, #xFFFFFFFF)"
`(handler-bind ((unbound-variable #'c-like-hex-literal-handler))
,@body))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Limited Infix Notation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(ql:quickload :infix)
(defun infix-val (str)
"Try to evaluate a string as an infix expression and returns
its result (or nil if this fails)."
(let ((infix-form (handler-case (infix:string->prefix str)
(condition () nil))))
(when infix-form
(eval infix-form))))
(defun infix-literal-handler (condition)
"Given an unbound-variable condition, invokes the use-value
restart if the \"variable\" looks like an infix expression."
(let* ((var-name (symbol-name (cell-error-name condition)))
(val (infix-val var-name)))
(when val
(invoke-restart 'use-value val))))
(defmacro with-infix-literals (&body body)
"Execute code within an environment where simple infix
expressions can be used (like 1+1, 1+3/pi, etc). Note that
there cannot be any spaces in the infix expression."
`(handler-bind ((unbound-variable #'infix-literal-handler))
,@body))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Supreme Abuse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(ql:quickload :infix)
(defmacro with-crazy-stuff (&body body)
"Execute code within an environment where both infix literals
and c-style hex literals can be used."
`(with-hex-literals
(with-infix-literals
,@body)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment