(define-module (language python string) #:use-module (parser stis-parser) #:use-module (oop goops) #:use-module (oop pf-objects) #:use-module (language python hash) #:use-module (ice-9 match) #:use-module (ice-9 iconv) #:use-module (language python list) #:use-module (language python exceptions) #:use-module (language python for) #:use-module (language python def) #:use-module (language python bool) #:use-module (language python persist) #:use-module (rnrs bytevectors) #:export (py-format py-capitalize py-center py-endswith py-expandtabs py-find py-rfind py-isalnum py-isalpha py-isdigit py-islower py-isspace py-isupper py-istitle py-join py-ljust py-rjust py-format-map py-encode py-rljust py-lower py-upper py-lstrip py-rstrip py-partition py-replace py-strip py-title py-rpartitio py-rindex py-split py-rsplit py-splitlines py-startswith py-swapcase py-translate py-zfill pystring-listing pystring py-string? scm-str scm-sym py-identifier?)) (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y))) (define (scm-str x) (if (string? x) x (slot-ref (pystring x) 'str))) (define (scm-sym x) (if (symbol? x) x (string->symbol (scm-str x)))) (define (py-string? x) (or (string? x) (is-a? x ))) (define-class () str) (name-object ) (cpit (o (lambda (o s) (slot-set! o 'str s)) (list (slot-ref o 'str)))) (define-syntax-rule (define-py (f n o . u) code ...) (begin (define-method (f (o ) . u) code ...) (define-method (f (o ) . l) (apply f (slot-ref o 'str) l)) (define-method (f (o

) . l) (aif it (ref o 'n) (apply it l) (next-method))))) (define-syntax-rule (define-py0 (f o . u) code ...) (begin (define-method (f (o ) . u) code ...) (define-method (f (o ) . l) (apply f (slot-ref o 'str) l)))) (define-py0 (pylist-ref s i) (list->string (list (string-ref s (if (< i 0) (+ (len s) i) i))))) (define-py0 (bool s) (if (= (len s) 0) #f s)) (define-py (py-capitalize capitalize s) (let* ((n (len s)) (w (make-string n))) (let lp ((i 0) (first? #t)) (if (< i n) (let ((ch (string-ref s i))) (if (and first? (char-alphabetic? ch)) (begin (string-set! w i (char-upcase ch)) (lp (+ i 1) #f)) (begin (string-set! w i ch) (lp (+ i 1) first?)))) w)))) (define-py (py-center center o w . l) (let* ((ws (if (pair? l) (car (string->list (car l))) #\space)) (n (string-length o)) (w (if (< w n) n w)) (d (- w n)) (e (floor-quotient (- w n) 2)) (s (make-string w #\space))) (let lp ((i 0) (j e)) (if (< i n) (begin (string-set! s j (string-ref o i)) (lp (+ i 1) (+ j 1))))) s)) (define-py (py-endswith endswith o (suff ) . l) (let* ((n (string-length o)) (ns (string-length suff)) (f (lambda (x) (< x 0) (+ n x) x))) (call-with-values (lambda () (match l (() (values 0 n )) ((x) (values (f x) n )) ((x y) (values (f x) (f y))))) (lambda (start end) (string-suffix? suff o 0 ns start end))))) (define-py (py-startswith startswith o (suff ) . l) (let* ((n (string-length o)) (ns (string-length suff)) (f (lambda (x) (< x 0) (+ n x) x))) (call-with-values (lambda () (match l (() (values 0 n )) ((x) (values (f x) n )) ((x y) (values (f x) (f y))))) (lambda (start end) (string-prefix? suff o 0 ns start end))))) (define-py (py-expandtabs expandtabs s . l) (let* ((tabsize (match l (() 8) ((x) x))) (u (string->list (make-string tabsize #\space))) (n (string-length s))) (let lp ((l (string->list s)) (r '())) (if (pair? l) (let ((x (car l))) (if (eq? x #\tab) (lp (cdr l) (append u r)) (lp (cdr l) (cons x r)))) (list->string (reverse r)))))) (define-py (py-find find s sub . l) (let* ((n (string-length s)) (f (lambda (x) (< x 0) (+ n x) x))) (call-with-values (lambda () (match l (() (values 0 n )) ((x) (values (f x) n )) ((x y) (values (f x) (f y))))) (lambda (start end) (aif it (string-contains s sub start end) it -1))))) (define-py (py-rfind rfind s sub . l) (let* ((n (string-length s)) (s (string-reverse s)) (sub (string-reverse sub)) (f (lambda (x) (< x 0) (+ n x) x))) (call-with-values (lambda () (match l (() (values 0 n )) ((x) (values (f x) n )) ((x y) (values (f x) (f y))))) (lambda (start end) (aif it (string-contains s sub start end) (- n it (len sub)) -1))))) (define formatter #f) (define-py (py-strformat format s . l) (apply (ref formatter 'format) s l)) (define-py (py-format-map format_map s map) (apply (ref formatter 'vformat) s '() map)) (define format (lambda (a b) a)) (define-py (py-format format s format-string) (format s format-string)) (define-syntax-rule (mk-is py-isalnum isalnum x ...) (define-py (py-isalnum isalnum s) (and (> (len s) 0) (string-fold (lambda (ch s) (if (or (x ch) ...) s #f)) #t s)))) (mk-is py-isalnum isalnum char-alphabetic? char-numeric?) (mk-is py-isalpha isalpha char-alphabetic?) (mk-is py-isdigit isdigit char-numeric?) (mk-is py-islower islower (lambda (ch) (or (eq? ch #\_) (char-lower-case? ch)))) (mk-is py-isspace isspace char-whitespace?) (mk-is py-isupper isupper (lambda (ch) (or (eq? ch #\_) (char-upper-case? ch)))) (define-py (py-identifier? isidentifier s) (let lp ((l (string->list s)) (first? #t)) (if (pair? l) (let ((x (car l))) (if first? (if (or (char-alphabetic? x) (eq? x #\_)) (lp (cdr l) #f) #f) (if (or (char-alphabetic? x) (char-numeric? x) (eq? x #\_)) (lp (cdr l) #f) #f))) (if ((@ (language python module keyword) iskeyword) s) #f #t)))) (define-py (py-istitle istitle s) (let ((n (len s))) (if ((> n 0)) (let lp ((i 0) (space? #t)) (if (< i n) (let ((ch (string-ref s i))) (if space? (cond ((char-whitespace? ch) (lp (+ i 1) #t)) ((char-upper-case? ch) (lp (+ i 1) #f)) (else #f)) (cond ((char-whitespace? ch) (lp (+ i 1) #t)) ((char-upper-case? ch) #f) ((char-lower-case? ch) (lp (+ i 1) #f)) (else #f)))) #t)) #f))) (define-py (py-join join s iterator) (string-join (to-list iterator) s)) (define-py (py-ljust ljust s width . l) (let* ((n (len s)) (ch (match l ((x . l) (if (string? x) (string-ref x 0) x)) (() #\space)))) (if (< width n) (pylist-slice s 0 width 1) (let ((ret (make-string width ch))) (let lp ((i 0)) (if (< i n) (begin (string-set! ret i (string-ref s i)) (lp (+ i 1))) ret)))))) (define-py (py-rjust rjust s width . l) (let* ((n (len s)) (ch (match l ((x . l) (if (string? x) (string-ref x 0) x)) (() #\space)))) (if (< width n) (pylist-slice s (- width) (len s) 1) (let ((ret (make-string width ch))) (let lp ((i 0) (j (- width n))) (if (< i n) (begin (string-set! ret j (string-ref s i)) (lp (+ i 1) (+ j 1))) ret)))))) (define-py (py-lower lower s) (string-downcase s)) (define-py (py-upper upper s) (string-upcase s)) (define-py (py-lstrip lstrip s . l) (match l (() (string-trim s)) ((x . _) (let ((l (map (lambda (x) (if (string? x) (string-ref x 0) x)) (to-list x)))) (string-trim s (lambda (ch) (member ch l))))))) (define-py (py-rstrip rstrip s . l) (match l (() (string-trim-right s)) ((x . _) (let ((l (map (lambda (x) (if (string? x) (string-ref x 0) x)) (to-list x)))) (string-trim-right s (lambda (ch) (member ch l))))))) (define-py (py-partition partition s (sep )) (let ((n (len s)) (m (len sep))) (define (test i) (let lp ((i i) (j 0)) (if (< i n) (if (< j m) (if (eq? (string-ref s i) (string-ref sep j)) (lp (+ i 1) (+ j 1)) #f) #t) #f))) (let lp ((i 0)) (if (< i n) (if (test i) (list (pylist-slice s 0 i 1) sep (pylist-slice s (+ i m) n 1)) (lp (+ i 1))) (list s "" ""))))) (define-py (py-partition partition s (sep )) (py-partition s (slot-ref sep 'str))) (define-py (py-rpartition rpartition ss (ssep )) (let* ((s (string-reverse ss)) (sep (string-reverse ssep)) (n (len s)) (m (len sep))) (define (test i) (let lp ((i i) (j 0)) (if (< i n) (if (< j m) (if (eq? (string-ref s i) (string-ref sep j)) (lp (+ i 1) (+ j 1)) #f) #t) #f))) (let lp ((i 0)) (if (< i n) (if (test i) (list (string-reverse (pylist-slice s (+ i m) n 1)) ssep (string-reverse (pylist-slice s 0 i 1))) (lp (+ i 1))) (list "" "" s))))) (define-py (py-rpartition rpartition s (sep )) (py-rpartition s (slot-ref sep 'str))) (define-py (py-replace replace s old new . l) (let ((n (match l (() #f) ((n . _) n)))) (string-join (reverse (let lp ((s s) (r '())) (let ((l (py-partition s old))) (if (equal? (cadr l) "") (cons s r) (lp (list-ref l 2) (cons (car l) r)))))) new))) (define-py (py-strip strip s . l) (apply py-rstrip (apply py-lstrip s l) l)) (define-py (py-title title s) (string-titlecase s)) (define-py (py-rindex rindex s . l) (let ((n (len s))) (- n (apply pylist-index (string-reverse s) l) 1))) (define bytes #f) (define (geterr errors) (set! errors (py-lower (scm-str errors))) (cond ((equal? errors "strict") 'error) ((equal? errors "escape") 'escape) ((equal? errors "replace") 'substitute) ((equal? errors "ignore") (warn (string-append "not possible to use ignore " "encodong error strategy " "using replace in stead")) 'substitute) (else (warn "not a correct encodong error strategy") 'error))) (define-py (py-encode encode s . l) (apply (lam ((= encoding "UTF-8") (= errors "strict")) (set! encoding (py-upper (scm-str encoding))) (set! errors (geterr errors)) (bytes (string->bytevector (scm-str s) encoding errors))) l)) (define-py (py-split split s . l) (define N 1000000000000) (define ws? #f) (define ws (list #\space #\newline #\tab #\return)) (define (to-ch x) (string-ref (scm-str x) 0)) (define (mksep sep) (for ((x : sep)) ((l '())) (cons (cond ((and (number? x) (integer? x)) (integer->char x)) ((char? x) x) (else (to-ch x))) l) #:final (reverse l))) (call-with-values (lambda () (match l (() (set! ws? #t) (values '() N)) ((sep) (values (mksep sep) N)) ((sep n) (values (mksep sep) n)))) (lambda (sep n) (let lp ((l (string->list (scm-str s))) (i 0) (v '()) (r '())) (if (= i n) (reverse (cons (list->string l) r)) (if (pair? l) (let ((ch (car l))) (if ws? (if (member ch ws) (let lp2 ((l (cdr l))) (if (pair? l) (let ((ch (car l))) (if (member ch ws) (lp2 (cdr l)) (lp l (+ i 1) '() (cons (list->string (reverse v)) r)))) (lp l (+ i 1) '() (cons (list->string (reverse v)) r)))) (lp (cdr l) i (cons ch v) r)) (if (eq? ch (car sep)) (let lp2 ((ll (cdr l)) (s (cdr sep))) (if (pair? s) (if (pair? ll) (let ((ch2 (car ll))) (if (eq? ch2 (car s)) (lp2 (cdr ll) (cdr sep)) (lp (cdr l) i (cons ch v) r))) (lp (cdr l) i (cons ch v) r)) (lp ll (+ i 1) '() (cons (list->string (reverse v)) r)))) (lp (cdr l) i (cons ch v) r)))) (reverse (cons (list->string (reverse v)) r)))))))) (define-py (py-rsplit rsplit s . l) (reverse (map string-reverse (apply py-split (string-reverse s) (match l (() '()) ((sep . l) (cons (string-reverse sep) l))))))) (define-py (py-splitlines splitlines s . l) (let ((n (len s)) (keep? (match l ((#:keepends v) v) ((v) v) (_ #f)))) (let lp ((i 0) (r '()) (old 0)) (if (< i n) (let ((ch (string-ref s i))) (if (eq? ch #\newline) (if keep? (lp (+ i 1) (cons (pylist-slice s old (+ i 1) 1) r) (+ i 1)) (lp (+ i 1) (cons (pylist-slice s old i 1) r) (+ i 1))) (lp (+ i 1) r old))) (reverse r))))) (define-py (py-swapcase swapcase s) (list->string (string-fold (lambda (ch s) (cons (cond ((char-upper-case? ch) (char-downcase ch)) ((char-lower-case? ch) (char-upcase ch)) (else ch)) s)) '() s))) (define-py (py-translate translate s table . l) (let* ((n (len s)) (w (make-string n)) (t (if (eq? table None) #f table)) (d (match l (() #f) ((x) x)))) (define (tr ch) (define (e) (if t (let ((i (char->integer ch))) (catch #t (lambda () (integer->char (pylist-ref t i))) (lambda x ch))) ch)) (if d (if (string-contains d (list->string (list ch))) #f (e)) (e))) (let lp ((i 0) (k 0)) (if (< i n) (let ((ch (tr (string-ref s i)))) (if ch (begin (string-set! w k ch) (lp (+ i 1) (+ k 1))) (lp (+ i 1) k))) (if (= k n) w (pylist-slice w 0 k 1)))))) (define-syntax-rule (a b x y) (b (symbol->string x) (symbol->string y))) (define-syntax-rule (mkop op) (begin (define-method (op (s1 ) (s2 )) (op s1 (slot-ref s2 'str))) (define-method (op (s2 ) (s1 )) (op s1 (slot-ref s2 'str))))) (mkop <) (mkop <=) (mkop >) (mkop >=) (mkop +) (mkop *) (define-method (< (s1 ) (s2 )) (string-ci< s1 s2)) (define-method (<= (s1 ) (s2 )) (string-ci<= s1 s2)) (define-method (> (s1 ) (s2 )) (string-ci> s1 s2)) (define-method (>= (s1 ) (s2 )) (string-ci>= s1 s2)) (define-method (< (s1 ) (s2 )) (a string-ci< s1 s2)) (define-method (<= (s1 ) (s2 )) (a string-ci<= s1 s2)) (define-method (> (s1 ) (s2 )) (a string-ci> s1 s2)) (define-method (>= (s1 ) (s2 )) (a string-ci>= s1 s2)) (define-py (py-zfill zfill s width) (let* ((n (len s)) (w (pylist-slice s 0 n 1))) (let lp ((i 0)) (if (< i n) (let ((ch (string-ref s i))) (if (char-numeric? ch) (let lp ((j (max 0 (- i width)))) (if (< j i) (begin (string-set! w j #\0) (lp (+ j 1))) w)) (lp (+ i 1)))) s)))) (define b? #f) (define b-decode #f) (define-python-class string ( ) (define __init__ (case-lambda ((self) "") ((self s . l) (cond ((is-a? s ) (slot-ref s 'str)) ((is-a? s ) s) ((b? s) (apply b-decode s l)) (else (aif it (ref s '__str__) (it) (__init__ self ((@ (guile) format) #f "~a" s)))))))) (define __new__ (lambda x (apply __init__ x))) (define __newobj__ (lambda (cls value) (let ((obj ((rawref object '__new__) cls))) (slot-set! obj 'str (__new__ cls value)) obj))) (define __repr__ (lambda (self) (slot-ref self 'str)))) (name-object string) (define pystring string) (define-method (py-class (o )) string) (define-method (py-class (o )) string) (define-method (pyhash (o )) (hash (slot-ref o 'str) pyhash-N)) (define-method (py-equal? (o ) x) (equal? (slot-ref o 'str) x)) (define-method (py-equal? x (o )) (equal? (slot-ref o 'str) x)) (define-class () str i d) (name-object ) (cpit (o (lambda (o str i d) (slot-set! o 'str str) (slot-set! o 'i i ) (slot-set! o 'd d )) (list (slot-ref o 'str) (slot-ref o 'i) (slot-ref o 'd)))) (define-method (write (o ) . l) (define port (if (null? l) #t (car l))) (for ((x : o)) ((l '())) (cons (string-ref x 0) l) #:final ((@ (guile) format) port "iter(~s)" (list->string (reverse l))))) (define-method (wrap-in (o )) (let ((out (make ))) (slot-set! out 'str (slot-ref o 'str)) (slot-set! out 'i (slot-ref o 'i)) (slot-set! out 'd (slot-ref o 'd)) out)) (define-method (wrap-in (s )) (let ((out (make ))) (slot-set! out 'str s) (slot-set! out 'i 0) (slot-set! out 'd 1) out)) (define-method (py-reversed (s )) (let ((out (make ))) (slot-set! out 'str s) (slot-set! out 'i (- (string-length s) 1)) (slot-set! out 'd -1) out)) (define-method (next (o )) (let ((i (slot-ref o 'i )) (d (slot-ref o 'd)) (str (slot-ref o 'str))) (if (> d 0) (if (< i (string-length str)) (let ((ret (string-ref str i))) (slot-set! o 'i (+ i d)) (list->string (list ret))) (throw StopIteration)) (if (>= i 0) (let ((ret (string-ref str i))) (slot-set! o 'i (+ i d)) (list->string (list ret))) (throw StopIteration))))) (define (pystring-listing) (let ((l (to-pylist (map symbol->string '(__add__ __class__ __contains__ __delattr__ __doc__ __eq__ __format__ __ge__ __getattribute__ __getitem__ __getnewargs__ __getslice__ __gt__ __hash__ __init__ __le__ __len__ __lt__ __mod__ __mul__ __ne__ __new__ __reduce__ __reduce_ex__ __repr__ __rmod__ __rmul__ __setattr__ __sizeof__ __str__ __subclasshook__ _formatter_field_name_split _formatter_parser capitalize center count encode endswith expandtabs find format index isalnum isalpha isdigit islower isspace istitle isupper join ljust lower lstrip partition replace rfind rindex rjust rpartition rsplit rstrip split splitlines startswith strip swapcase format_map title translate upper zfill))))) (pylist-sort! l) l))