(module rope (empty-rope current-maximum-leaf-length string->rope rope->string rope-length rope-depth rope rope? rope=? rope-null? rope-balanced? rope-balance rope-ref subrope rope-reverse rope-append rope-concatenate rope-fold rope-for-each read-rope make-rope-iterator open-input-rope open-output-rope get-output-rope) (import scheme chicken srfi-1 srfi-13 ports extras) (require-library srfi-1 srfi-13) (define-type rope (or (struct node) (struct leaf))) (: empty-rope rope) (: current-maximum-leaf-length (#!optional fixnum -> number)) (: rope (#!rest string -> rope)) (: string->rope (string -> rope)) (: rope->string (rope -> string)) (: rope? (rope -> boolean : rope)) (: rope=? (rope rope -> boolean)) (: rope-null? (rope -> boolean)) (: rope-length (rope -> fixnum)) (: rope-ref (rope fixnum -> char)) (: subrope (rope fixnum #!optional fixnum -> rope)) (: rope-append (#!rest rope -> rope)) (: rope-concatenate ((list-of rope) -> rope)) (: rope-reverse (rope -> rope)) (: rope-depth (rope -> fixnum)) (: rope-balanced? (rope -> boolean)) (: rope-balance (rope -> rope)) (: rope-fold ((any #!rest any -> any) any rope #!rest rope -> any)) (: rope-for-each ((any #!rest any -> undefined) rope #!rest rope -> void)) (: read-rope (#!optional input-port fixnum -> rope)) (: make-rope-iterator (rope -> (-> char))) (: open-input-rope (rope -> input-port)) (: open-output-rope (-> output-port)) (: get-output-rope (#!optional output-port -> rope)) (include "rope.scm") (define (printer o p) (display "#" p)) (define-record-printer node printer) (define-record-printer leaf printer) (define (open-input-rope r) (make-input-port (make-rope-iterator r) (lambda () #t) void)) (define open-output-rope open-output-string) (define get-output-rope (case-lambda (() (get-output-rope (current-output-port))) ((port) (string->rope (get-output-string port))))) (define read-rope (case-lambda (() (read-rope (current-input-port) most-positive-fixnum)) ((port) (read-rope port most-positive-fixnum)) ((port len) (let ((mll (current-maximum-leaf-length))) (let lp ((i len) (a '())) (if (zero? i) (rope-concatenate (reverse a)) (let* ((part (read-string (min i mll) port)) (plen (string-length part))) (if (zero? plen) (lp 0 a) (lp (- i plen) (cons (make-leaf part plen) a)))))))))))