c64-livecoding/wip-duuqnd/user-side-compiler/error-handling.lisp

50 lines
2.1 KiB
Common Lisp

(in-package #:user-side-compiler)
(defun string-nth-line (string line)
(assert (> line 0))
(let ((start (loop :repeat line
:for start := 0 :then (1+ (position #\Newline string
:start start))
:finally (return start))))
(subseq string
start
(position #\Newline string :start (1+ start)))))
(defun point-out-source (source)
(if (null source)
"No source info."
(destructuring-bind (text line . column)
source
(cond ((null text)
(format nil "Line ~D, column ~D" line column))
((stringp text)
(with-output-to-string (output)
(format output "~%Found on line ~D, column ~D:~%~A~%"
line column
(string-nth-line text line))
(loop :repeat column :do (write-char #\Space output))
(write-char #\^ output)))))))
(define-condition usc-error (error)
((%source :accessor source :initarg :source :initform nil)
(%format-control :accessor format-control :initarg :format-control)
(%format-arguments :accessor format-arguments :initarg :format-arguments :initform '())
(%context-string :reader context-string :initform "User-side compiler error at unknown stage:"))
(:report (lambda (c s)
(format s "~A~%~A~%~A" (context-string c)
(apply #'format nil (format-control c) (format-arguments c))
(point-out-source (source c))))))
(define-condition tokenizer-error (usc-error)
((%context-string :initform "Tokenizing error:")))
(define-condition missing-function-error (usc-error)
((%context-string :initform "Non-existent function (TODO nicer error for this):")))
(define-condition parser-error (usc-error)
((%context-string :initform "Syntax error:")))
(defun error-parser (source format-control &rest format-arguments)
(error 'parser-error :source source :format-control format-control
:format-arguments format-arguments))