Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

416 lines
12 KiB

4 years ago
  1. ;; swank-r6rs.sls --- Shareable code between swank-ikarus and swank-larceny
  2. ;;
  3. ;; Licence: public domain
  4. ;; Author: Helmut Eller
  5. ;;
  6. ;; This is a Swank server barely capable enough to process simple eval
  7. ;; requests from Emacs before dying. No fancy features like
  8. ;; backtraces, module redefintion, M-. etc. are implemented. Don't
  9. ;; even think about pc-to-source mapping.
  10. ;;
  11. ;; Despite standard modules, this file uses (swank os) and (swank sys)
  12. ;; which define implementation dependend functionality. There are
  13. ;; multiple modules in this files, which is probably not standardized.
  14. ;;
  15. ;; Naive FORMAT implementation which supports: ~a ~s ~d ~x ~c
  16. (library (swank format)
  17. (export format printf fprintf)
  18. (import (rnrs))
  19. (define (format f . args)
  20. (call-with-string-output-port
  21. (lambda (port) (apply fprintf port f args))))
  22. (define (printf f . args)
  23. (let ((port (current-output-port)))
  24. (apply fprintf port f args)
  25. (flush-output-port port)))
  26. (define (fprintf port f . args)
  27. (let ((len (string-length f)))
  28. (let loop ((i 0) (args args))
  29. (cond ((= i len) (assert (null? args)))
  30. ((and (char=? (string-ref f i) #\~)
  31. (< (+ i 1) len))
  32. (dispatch-format (string-ref f (+ i 1)) port (car args))
  33. (loop (+ i 2) (cdr args)))
  34. (else
  35. (put-char port (string-ref f i))
  36. (loop (+ i 1) args))))))
  37. (define (dispatch-format char port arg)
  38. (let ((probe (assoc char format-dispatch-table)))
  39. (cond (probe ((cdr probe) arg port))
  40. (else (error "invalid format char: " char)))))
  41. (define format-dispatch-table
  42. `((#\a . ,display)
  43. (#\s . ,write)
  44. (#\d . ,(lambda (arg port) (put-string port (number->string arg 10))))
  45. (#\x . ,(lambda (arg port) (put-string port (number->string arg 16))))
  46. (#\c . ,(lambda (arg port) (put-char port arg))))))
  47. ;; CL-style restarts to let us continue after errors.
  48. (library (swank restarts)
  49. (export with-simple-restart compute-restarts invoke-restart restart-name
  50. write-restart-report)
  51. (import (rnrs))
  52. (define *restarts* '())
  53. (define-record-type restart
  54. (fields name reporter continuation))
  55. (define (with-simple-restart name reporter thunk)
  56. (call/cc
  57. (lambda (k)
  58. (let ((old-restarts *restarts*)
  59. (restart (make-restart name (coerce-to-reporter reporter) k)))
  60. (dynamic-wind
  61. (lambda () (set! *restarts* (cons restart old-restarts)))
  62. thunk
  63. (lambda () (set! *restarts* old-restarts)))))))
  64. (define (compute-restarts) *restarts*)
  65. (define (invoke-restart restart . args)
  66. (apply (restart-continuation restart) args))
  67. (define (write-restart-report restart port)
  68. ((restart-reporter restart) port))
  69. (define (coerce-to-reporter obj)
  70. (cond ((string? obj) (lambda (port) (put-string port obj)))
  71. (#t (assert (procedure? obj)) obj)))
  72. )
  73. ;; This module encodes & decodes messages from the wire and queues them.
  74. (library (swank event-queue)
  75. (export make-event-queue wait-for-event enqueue-event
  76. read-event write-event)
  77. (import (rnrs)
  78. (rnrs mutable-pairs)
  79. (swank format))
  80. (define-record-type event-queue
  81. (fields (mutable q) wait-fun)
  82. (protocol (lambda (init)
  83. (lambda (wait-fun)
  84. (init '() wait-fun)))))
  85. (define (wait-for-event q pattern)
  86. (or (poll q pattern)
  87. (begin
  88. ((event-queue-wait-fun q) q)
  89. (wait-for-event q pattern))))
  90. (define (poll q pattern)
  91. (let loop ((lag #f)
  92. (l (event-queue-q q)))
  93. (cond ((null? l) #f)
  94. ((event-match? (car l) pattern)
  95. (cond (lag
  96. (set-cdr! lag (cdr l))
  97. (car l))
  98. (else
  99. (event-queue-q-set! q (cdr l))
  100. (car l))))
  101. (else (loop l (cdr l))))))
  102. (define (event-match? event pattern)
  103. (cond ((or (number? pattern)
  104. (member pattern '(t nil)))
  105. (equal? event pattern))
  106. ((symbol? pattern) #t)
  107. ((pair? pattern)
  108. (case (car pattern)
  109. ((quote) (equal? event (cadr pattern)))
  110. ((or) (exists (lambda (p) (event-match? event p)) (cdr pattern)))
  111. (else (and (pair? event)
  112. (event-match? (car event) (car pattern))
  113. (event-match? (cdr event) (cdr pattern))))))
  114. (else (error "Invalid pattern: " pattern))))
  115. (define (enqueue-event q event)
  116. (event-queue-q-set! q
  117. (append (event-queue-q q)
  118. (list event))))
  119. (define (write-event event port)
  120. (let ((payload (call-with-string-output-port
  121. (lambda (port) (write event port)))))
  122. (write-length (string-length payload) port)
  123. (put-string port payload)
  124. (flush-output-port port)))
  125. (define (write-length len port)
  126. (do ((i 24 (- i 4)))
  127. ((= i 0))
  128. (put-string port
  129. (number->string (bitwise-bit-field len (- i 4) i)
  130. 16))))
  131. (define (read-event port)
  132. (let* ((header (string-append (get-string-n port 2)
  133. (get-string-n port 2)
  134. (get-string-n port 2)))
  135. (_ (printf "header: ~s\n" header))
  136. (len (string->number header 16))
  137. (_ (printf "len: ~s\n" len))
  138. (payload (get-string-n port len)))
  139. (printf "payload: ~s\n" payload)
  140. (read (open-string-input-port payload))))
  141. )
  142. ;; Entry points for SLIME commands.
  143. (library (swank rpc)
  144. (export connection-info interactive-eval
  145. ;;compile-string-for-emacs
  146. throw-to-toplevel sldb-abort
  147. operator-arglist buffer-first-change
  148. create-repl listener-eval)
  149. (import (rnrs)
  150. (rnrs eval)
  151. (only (rnrs r5rs) scheme-report-environment)
  152. (swank os)
  153. (swank format)
  154. (swank restarts)
  155. (swank sys)
  156. )
  157. (define (connection-info . _)
  158. `(,@'()
  159. :pid ,(getpid)
  160. :package (:name ">" :prompt ">")
  161. :lisp-implementation (,@'()
  162. :name ,(implementation-name)
  163. :type "R6RS-Scheme")))
  164. (define (interactive-eval string)
  165. (call-with-values
  166. (lambda ()
  167. (eval-in-interaction-environment (read-from-string string)))
  168. (case-lambda
  169. (() "; no value")
  170. ((value) (format "~s" value))
  171. (values (format "values: ~s" values)))))
  172. (define (throw-to-toplevel) (invoke-restart-by-name-or-nil 'toplevel))
  173. (define (sldb-abort) (invoke-restart-by-name-or-nil 'abort))
  174. (define (invoke-restart-by-name-or-nil name)
  175. (let ((r (find (lambda (r) (eq? (restart-name r) name))
  176. (compute-restarts))))
  177. (if r (invoke-restart r) 'nil)))
  178. (define (create-repl target)
  179. (list "" ""))
  180. (define (listener-eval string)
  181. (call-with-values (lambda () (eval-region string))
  182. (lambda values `(:values ,@(map (lambda (v) (format "~s" v)) values)))))
  183. (define (eval-region string)
  184. (let ((sexp (read-from-string string)))
  185. (if (eof-object? exp)
  186. (values)
  187. (eval-in-interaction-environment sexp))))
  188. (define (read-from-string string)
  189. (call-with-port (open-string-input-port string) read))
  190. (define (operator-arglist . _) 'nil)
  191. (define (buffer-first-change . _) 'nil)
  192. )
  193. ;; The server proper. Does the TCP stuff and exception handling.
  194. (library (swank)
  195. (export start-server)
  196. (import (rnrs)
  197. (rnrs eval)
  198. (swank os)
  199. (swank format)
  200. (swank event-queue)
  201. (swank restarts))
  202. (define-record-type connection
  203. (fields in-port out-port event-queue))
  204. (define (start-server port)
  205. (accept-connections (or port 4005) #f))
  206. (define (start-server/port-file port-file)
  207. (accept-connections #f port-file))
  208. (define (accept-connections port port-file)
  209. (let ((sock (make-server-socket port)))
  210. (printf "Listening on port: ~s\n" (local-port sock))
  211. (when port-file
  212. (write-port-file (local-port sock) port-file))
  213. (let-values (((in out) (accept sock (latin-1-codec))))
  214. (dynamic-wind
  215. (lambda () #f)
  216. (lambda ()
  217. (close-socket sock)
  218. (serve in out))
  219. (lambda ()
  220. (close-port in)
  221. (close-port out))))))
  222. (define (write-port-file port port-file)
  223. (call-with-output-file
  224. (lambda (file)
  225. (write port file))))
  226. (define (serve in out)
  227. (let ((err (current-error-port))
  228. (q (make-event-queue
  229. (lambda (q)
  230. (let ((e (read-event in)))
  231. (printf "read: ~s\n" e)
  232. (enqueue-event q e))))))
  233. (dispatch-loop (make-connection in out q))))
  234. (define-record-type sldb-state
  235. (fields level condition continuation next))
  236. (define (dispatch-loop conn)
  237. (let ((event (wait-for-event (connection-event-queue conn) 'x)))
  238. (case (car event)
  239. ((:emacs-rex)
  240. (with-simple-restart
  241. 'toplevel "Return to SLIME's toplevel"
  242. (lambda ()
  243. (apply emacs-rex conn #f (cdr event)))))
  244. (else (error "Unhandled event: ~s" event))))
  245. (dispatch-loop conn))
  246. (define (recover thunk on-error-thunk)
  247. (let ((ok #f))
  248. (dynamic-wind
  249. (lambda () #f)
  250. (lambda ()
  251. (call-with-values thunk
  252. (lambda vals
  253. (set! ok #t)
  254. (apply values vals))))
  255. (lambda ()
  256. (unless ok
  257. (on-error-thunk))))))
  258. ;; Couldn't resist to exploit the prefix feature.
  259. (define rpc-entries (environment '(prefix (swank rpc) swank:)))
  260. (define (emacs-rex conn sldb-state form package thread tag)
  261. (let ((out (connection-out-port conn)))
  262. (recover
  263. (lambda ()
  264. (with-exception-handler
  265. (lambda (condition)
  266. (call/cc
  267. (lambda (k)
  268. (sldb-exception-handler conn condition k sldb-state))))
  269. (lambda ()
  270. (let ((value (apply (eval (car form) rpc-entries) (cdr form))))
  271. (write-event `(:return (:ok ,value) ,tag) out)))))
  272. (lambda ()
  273. (write-event `(:return (:abort) ,tag) out)))))
  274. (define (sldb-exception-handler connection condition k sldb-state)
  275. (when (serious-condition? condition)
  276. (let ((level (if sldb-state (+ (sldb-state-level sldb-state) 1) 1))
  277. (out (connection-out-port connection)))
  278. (write-event `(:debug 0 ,level ,@(debugger-info condition connection))
  279. out)
  280. (dynamic-wind
  281. (lambda () #f)
  282. (lambda ()
  283. (sldb-loop connection
  284. (make-sldb-state level condition k sldb-state)))
  285. (lambda () (write-event `(:debug-return 0 ,level nil) out))))))
  286. (define (sldb-loop connection state)
  287. (apply emacs-rex connection state
  288. (cdr (wait-for-event (connection-event-queue connection)
  289. '(':emacs-rex . _))))
  290. (sldb-loop connection state))
  291. (define (debugger-info condition connection)
  292. (list `(,(call-with-string-output-port
  293. (lambda (port) (print-condition condition port)))
  294. ,(format " [type ~s]" (if (record? condition)
  295. (record-type-name (record-rtd condition))
  296. ))
  297. ())
  298. (map (lambda (r)
  299. (list (format "~a" (restart-name r))
  300. (call-with-string-output-port
  301. (lambda (port)
  302. (write-restart-report r port)))))
  303. (compute-restarts))
  304. '()
  305. '()))
  306. (define (print-condition obj port)
  307. (cond ((condition? obj)
  308. (let ((list (simple-conditions obj)))
  309. (case (length list)
  310. ((0)
  311. (display "Compuond condition with zero components" port))
  312. ((1)
  313. (assert (eq? obj (car list)))
  314. (print-simple-condition (car list) port))
  315. (else
  316. (display "Compound condition:\n" port)
  317. (for-each (lambda (c)
  318. (display " " port)
  319. (print-simple-condition c port)
  320. (newline port))
  321. list)))))
  322. (#t
  323. (fprintf port "Non-condition object: ~s" obj))))
  324. (define (print-simple-condition condition port)
  325. (fprintf port "~a" (record-type-name (record-rtd condition)))
  326. (case (count-record-fields condition)
  327. ((0) #f)
  328. ((1)
  329. (fprintf port ": ")
  330. (do-record-fields condition (lambda (name value) (write value port))))
  331. (else
  332. (fprintf port ":")
  333. (do-record-fields condition (lambda (name value)
  334. (fprintf port "\n~a: ~s" name value))))))
  335. ;; Call FUN with RECORD's rtd and parent rtds.
  336. (define (do-record-rtds record fun)
  337. (do ((rtd (record-rtd record) (record-type-parent rtd)))
  338. ((not rtd))
  339. (fun rtd)))
  340. ;; Call FUN with RECORD's field names and values.
  341. (define (do-record-fields record fun)
  342. (do-record-rtds
  343. record
  344. (lambda (rtd)
  345. (let* ((names (record-type-field-names rtd))
  346. (len (vector-length names)))
  347. (do ((i 0 (+ 1 i)))
  348. ((= i len))
  349. (fun (vector-ref names i) ((record-accessor rtd i) record)))))))
  350. ;; Return the number of fields in RECORD
  351. (define (count-record-fields record)
  352. (let ((i 0))
  353. (do-record-rtds
  354. record (lambda (rtd)
  355. (set! i (+ i (vector-length (record-type-field-names rtd))))))
  356. i))
  357. )