foreign-c-libraries/.tmp/system/guile/.akku/lib/laesare/writer.sls

176 lines
5.8 KiB
Scheme

;; -*- mode: scheme; coding: utf-8 -*-
;; Copyright © 2019 G. Weinholt
;; SPDX-License-Identifier: MIT
;; Permission is hereby granted, free of charge, to any person obtaining a
;; copy of this software and associated documentation files (the "Software"),
;; to deal in the Software without restriction, including without limitation
;; the rights to use, copy, modify, merge, publish, distribute, sublicense,
;; and/or sell copies of the Software, and to permit persons to whom the
;; Software is furnished to do so, subject to the following conditions:
;; The above copyright notice and this permission notice shall be included in
;; all copies or substantial portions of the Software.
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
;; DEALINGS IN THE SOFTWARE.
#!r6rs
;; RnRS writer
(library (laesare writer)
(export
put-token
make-writer writer?
writer-port writer-filename
writer-mode writer-mode-set!)
(import
(rnrs (6)))
(define-record-type writer
(fields port filename
(mutable mode))
(sealed #t) (opaque #f)
(nongenerative writer-v0-d2dafa98-4344-400d-ba4d-633e6a1e9133)
(protocol
(lambda (p)
(lambda (port filename)
(p port filename 'rnrs)))))
(define (assert-mode writer modes type token)
(unless (memq (writer-mode writer) modes)
(assertion-violation 'put-token
"Token type is not supported in this mode"
type token (writer-mode writer))))
(define r7rs-char-names
'((#\nul . "null")
(#\alarm . "alarm")
(#\backspace . "backspace")
(#\tab . "tab")
(#\linefeed . "newline")
(#\vtab . #f)
(#\page . #f)
(#\return . "return")
(#\esc . "escape")
(#\space . "space")
(#\delete . "delete")))
(define (put-token writer type token)
(let ((p (writer-port writer)))
(case type
((identifier)
;; FIXME: quoting according to R7RS
(write token p))
((value)
(cond
((and (eq? (writer-mode writer) 'r7rs) (assv token r7rs-char-names))
=> (lambda (name)
(cond ((cdr name)
(put-string p "#\\")
(put-string p (cdr name)))
(else
(put-string p "#\\x")
(put-string p (string-downcase (number->string (char->integer token) 16)))))))
((eqv? token #\linefeed)
(put-string p "#\\linefeed"))
((eqv? token #\esc)
(if (eq? (writer-mode writer) 'r6rs)
(put-string p "#\\esc") ;workaround for Larceny 1.3
(put-string p "#\\x1b")))
((and (char? token) (memq (char-general-category token) '(Cf Zp So)))
(put-string p "#\\x")
(put-string p (string-downcase (number->string (char->integer token) 16))))
(else
(write token p))))
((bytevector)
(case (writer-mode writer)
((r6rs) (put-string p "#vu8("))
((r7rs) (put-string p "#u8("))
(else
(assertion-violation 'put-token "Bytevectors are not supported in this mode"
type token (writer-mode writer)))))
((directive)
(put-string p "#!")
(display token p)
(case token
((r6rs) (writer-mode-set! writer 'r6rs))
((r7rs) (writer-mode-set! writer 'r7rs))
(else (values))))
((openb)
(case (writer-mode writer)
((r6rs) (put-char p #\[))
(else (put-char p #\())))
((closeb)
(case (writer-mode writer)
((r6rs) (put-char p #\]))
(else (put-char p #\)))))
((abbrev)
(case token
((quote) (put-string p "'"))
((quasiquote) (put-string p "`"))
((unquote) (put-string p ","))
((unquote-splicing) (put-string p ",@"))
((syntax)
(assert-mode writer '(rnrs r6rs) type token)
(put-string p "#'"))
((quasisyntax)
(assert-mode writer '(rnrs r6rs) type token)
(put-string p "#`"))
((unsyntax)
(assert-mode writer '(rnrs r6rs) type token)
(put-string p "#,"))
((unsyntax-splicing)
(assert-mode writer '(rnrs r6rs) type token)
(put-string p "#,@"))
(else
(assertion-violation 'put-token "Unrecognized abbreviation"
type token))))
((label reference)
(assert-mode writer '(rnrs r7rs) type token)
(put-string p "#")
(display token p)
(if (eq? type 'label)
(put-string p "=")
(put-string p "#")))
;; Mode independent
((dot)
(put-char p #\.))
((inline-comment)
(let ((atmosphere (car token))
(datum (cdr token)))
(put-string p "#;")
(for-each (lambda (t+t)
(put-token writer (car t+t) (cdr t+t)))
atmosphere)
(write datum p)))
((whitespace)
(put-string p token))
((openp) (put-char p #\())
((closep) (put-char p #\)))
((vector) (put-string p "#("))
((shebang)
(put-string p "#!")
(put-string p (caddr token))
(put-char p #\newline))
((comment)
(put-char p #\;)
(put-string p token))
((nested-comment)
(put-string p "#|")
(put-string p token)
(put-string p "|#"))
(else
(assertion-violation 'put-token "Unrecognized token type"
type token))))))