<commit_before>;; recognize symbol characters that must be escaped when writing

;; TODO: indent? pretty printing? optional formatting styles?
;; quote/abbreviations, padding, packing, numeric formats/radixes/rounding
;; fine-grained writing styles? express write in terms of richer documents?

(define (write v out)
  (define punc? (cset "\\\"#'(),;[]`{}"))
  (define (bad-symbol? c) (or (unicode-space? c) (punc? c)))
  (define (pr s) (out 'put* s))
  (define (write* v)
    (write (car v) out)
    (cond ((pair? (cdr v))       (pr " ")   (write* (cdr v)))
          ((not (null? (cdr v))) (pr " . ") (write (cdr v) out))))
  (define (bracket l r v) (pr l) (write* v) (pr r))
  (cond ((eq? v #t)  (pr "#t"))
        ((eq? v #f)  (pr "#f"))
        ((null? v)   (pr "()"))
        ((number? v) (write-number v out))
        ((symbol? v)
         (define s (symbol->string v))
         (cond ((eq? v '|.|)       (pr "|.|"))
               ((string->number s) (pr "|") (pr s) (pr "|"))
               (else (define cs   (string->unicodes s))
                     (define bad? (ormap bad-symbol? cs))
                     (when bad? (pr "|"))
                     (for-each
                       (lambda (c)
                         (cond ((eqv? c (char "|")) (when bad? (pr "|"))
                                                    (pr "\\|")
                                                    (when bad? (pr "|")))
                               (else (pr (list->string (unicode->utf8 c))))))
                       cs)
                     (when bad? (pr "|")))))
        ((string? v)
         (pr "\"")
         (for-each
           (lambda (c)
             (pr (case/char c ("\"" "\\\"") ("\\" "\\\\") ("\a" "\\a")
                   ("\b" "\\b") ("\e" "\\e") ("\f" "\\f") ("\n" "\\n")
                   ("\r" "\\r") ("\t" "\\t") ("\v" "\\v")
                   (else (if (or (unicode-control? c) (unicode-vspace? c))
                           (string-append "\\u" (number->string c) ";")
                           (list->string (list c)))))))
           (string->unicodes v))
         (pr "\""))
        ((pair?      v) (bracket "(" ")" v))
        ((vector?    v) (cond ((eqv? (vector-length  v) 0) (pr "#()"))
                              (else (bracket "#(" ")"  (vector->list  v)))))
        ((mvector?   v) (cond ((eqv? (mvector-length v) 0) (pr "#m()"))
                              (else (bracket "#m(" ")" (mvector->list v)))))
        ((procedure? v) (pr "#<procedure>"))))

;; TODO: reduce dependency on exact->inexact and inexact->exact
;; manipulate floating point representation directly via:
;;   (real->floating-point-bytes x 8)<commit_msg>Factor out write-string and write-symbol<commit_after>;; recognize symbol characters that must be escaped when writing

;; TODO: indent? pretty printing? optional formatting styles?
;; quote/abbreviations, padding, packing, numeric formats/radixes/rounding
;; fine-grained writing styles? express write in terms of richer documents?

(define (write v out)
  (define (pr s) (out 'put* s))
  (define (write* v)
    (write (car v) out)
    (cond ((pair? (cdr v))       (pr " ")   (write* (cdr v)))
          ((not (null? (cdr v))) (pr " . ") (write (cdr v) out))))
  (define (bracket l r v) (pr l) (write* v) (pr r))
  (cond ((eq? #t     v) (pr "#t"))
        ((eq? #f     v) (pr "#f"))
        ((null?      v) (pr "()"))
        ((number?    v) (write-number v out))
        ((symbol?    v) (write-symbol v out))
        ((string?    v) (write-string v out))
        ((pair?      v) (bracket "(" ")" v))
        ((vector?    v) (cond ((eqv? (vector-length  v) 0) (pr "#()"))
                              (else (bracket "#(" ")"  (vector->list  v)))))
        ((mvector?   v) (cond ((eqv? (mvector-length v) 0) (pr "#m()"))
                              (else (bracket "#m(" ")" (mvector->list v)))))
        ((procedure? v) (pr "#<procedure>"))))

(define (write-string v out)
  (define (pr s) (out 'put* s))
  (pr "\"")
  (for-each
    (lambda (c)
      (pr (case/char c ("\"" "\\\"") ("\\" "\\\\") ("\a" "\\a")
            ("\b" "\\b") ("\e" "\\e") ("\f" "\\f") ("\n" "\\n")
            ("\r" "\\r") ("\t" "\\t") ("\v" "\\v")
            (else (if (or (unicode-control? c) (unicode-vspace? c))
                    (string-append "\\u" (number->string c) ";")
                    (list->string (list c)))))))
    (string->unicodes v))
  (pr "\""))

(define write-symbol
  (let* ((punc?       (cset "\\\"#'(),;[]`{}"))
         (bad-symbol? (lambda (c) (or (unicode-space? c) (punc? c)))))
    (lambda (v out)
      (define (pr s) (out 'put* s))
      (define s (symbol->string v))
      (cond ((eq? v '|.|)       (pr "|.|"))
            ((string->number s) (pr "|") (pr s) (pr "|"))
            (else (define cs   (string->unicodes s))
                  (define bad? (ormap bad-symbol? cs))
                  (when bad? (pr "|"))
                  (for-each
                    (lambda (c)
                      (cond ((eqv? c (char "|")) (when bad? (pr "|"))
                                                 (pr "\\|")
                                                 (when bad? (pr "|")))
                            (else (pr (list->string (unicode->utf8 c))))))
                    cs)
                  (when bad? (pr "|")))))))

;; TODO: reduce dependency on exact->inexact and inexact->exact
;; manipulate floating point representation directly via:
;;   (real->floating-point-bytes x 8)
{'fraction_non_alphanumeric': 0.22179487179487178, 'fraction_numerical': 0.0014652014652014652, 'mean_word_length': 1.5857007575757576, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1729619', 'n_tokens_mistral': 1833, 'n_tokens_neox': 1740, 'n_words': 532}