aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--csc/compare.csc243
-rw-r--r--csc/compiler.csc10
-rw-r--r--csc/format.csc59
-rw-r--r--csc/strings-test.csc52
-rw-r--r--csc/strings.csc69
-rw-r--r--csc/testing.csc54
6 files changed, 264 insertions, 223 deletions
diff --git a/csc/compare.csc b/csc/compare.csc
index fad9e4b..e8e68d3 100644
--- a/csc/compare.csc
+++ b/csc/compare.csc
@@ -1,25 +1,34 @@
(define-library (csc compare)
- (export diff)
+ (export diff apply-transformer)
(import (scheme base)
- (only (csc format) fprintf)
- (only (csc loop)
- loop
- return)
+ (only (scheme write)
+ display
+ write)
(only (csc strings)
- contains
- split)
- (only (csc vec)
- vec
- vec-append))
+ contains?
+ split))
(begin
; compare is inspired by Go's cmp.Diff.
+ (define (print w . xs)
+ (unless (null? xs)
+ (let ((x (car xs)))
+ (if (or (string? x)
+ (symbol? x))
+ (display x w)
+ (write x w)))
+ (apply print w (cdr xs))))
+
+
(define (apply-transformer t x)
(if (list? t)
- (loop for transformer in t
- do (set! x (apply-transformer transformer x))
- finally (return x))
+ (let loop ((transformers t)
+ (x x))
+ (if (null? transformers)
+ x
+ (loop (cdr transformers)
+ (apply-transformer (car transformers) x))))
(if ((car t) x)
((cdr t) x)
x)))
@@ -27,11 +36,13 @@
(define (alist? l)
(and (list? l)
- (loop for x in l
- unless (and (pair? x)
- (symbol? (car x)))
- return #f
- finally (return #t))))
+ (let loop ((l l))
+ (cond
+ ((null? l) #t)
+ ((not (and (pair? (car l))
+ (symbol? (caar l))))
+ #f)
+ (else (loop (cdr l)))))))
(define (transform x transformers)
@@ -57,13 +68,16 @@
(define table (make-vector (* (+ 1 (vector-length x-vals)) (+ 1 (vector-length y-vals))) 0))
(define (index i j)
(+ j (* i (+ 1 (vector-length y-vals)))))
- (loop for i from 1 to (vector-length x-vals)
- do (loop for j from 1 to (vector-length y-vals)
- if (cmp (vector-ref x-vals (- i 1)) (vector-ref y-vals (- j 1)))
- do (vector-set! table (index i j) (+ 1 (vector-ref table (index (- i 1) (- j 1)))))
- else
- do (vector-set! table (index i j) (max (vector-ref table (index (- i 1) j))
- (vector-ref table (index i (- j 1)))))))
+ (let loop-i ((i 1))
+ (when (<= i (vector-length x-vals))
+ (let loop-j ((j 1))
+ (when (<= j (vector-length y-vals))
+ (if (cmp (vector-ref x-vals (- i 1)) (vector-ref y-vals (- j 1)))
+ (vector-set! table (index i j) (+ 1 (vector-ref table (index (- i 1) (- j 1)))))
+ (vector-set! table (index i j) (max (vector-ref table (index (- i 1) j))
+ (vector-ref table (index i (- j 1))))))
+ (loop-j (+ 1 j))))
+ (loop-i (+ 1 i))))
(let loop ((i (vector-length x-vals))
(j (vector-length y-vals))
(lcs '()))
@@ -79,17 +93,18 @@
(define (pretty w x indent)
(cond
((list? x)
- (fprintf w "{} (\n" indent)
- (loop with new-indent = (string-append indent " ")
- for v in x
- do (pretty w v new-indent))
- (fprintf w "{} )\n" indent))
+ (print w indent " (\n")
+ (let ((new-indent (string-append indent " ")))
+ (for-each (lambda (v)
+ (pretty w v new-indent))
+ x))
+ (print w indent " )\n"))
((and (pair? x)
(symbol? (car x)))
- (fprintf w "{} ({} .\n" indent (car x))
+ (print w indent " (" (car x) " .\n")
(pretty w (cdr x) (string-append indent " "))
- (fprintf w "{} )\n" indent))
- (else (fprintf w "{} {}\n" indent x))))
+ (print w indent " )\n"))
+ (else (print w indent " " x "\n"))))
(define (diff* w x y indent)
@@ -101,89 +116,94 @@
(and (string? x) (string? y)))
(if (equal? x y)
(begin
- (fprintf w "{} {}\n" indent x)
+ (print w indent " " x "\n")
#t)
(begin
- (fprintf w "{}- {}\n{}+ {}\n" indent x indent y)
+ (print w indent "- " x "\n" indent "+ " y "\n")
#f)))
((and (alist? x) (alist? y))
- (fprintf w "{} (\n" indent)
+ (print w indent " (\n")
(let ((key-lcs (lcs (map car x) (map car y) symbol=?))
(indent* (string-append indent " "))
(equal #t))
- (loop if (null? key-lcs)
- if (null? x)
- if (null? y)
- do (return)
- else
- do (pretty w (car y) (string-append indent* "+"))
- (set! y (cdr y))
- (set! equal #f)
- else
- do (pretty w (car x) (string-append indent* "-"))
- (set! x (cdr x))
- (set! equal #f)
- else
- if (symbol=? (caar x) (caar y) (car key-lcs))
- do (fprintf w "{} ({} .\n" indent* (car key-lcs))
- (set! equal (and (diff* w (cdar x) (cdar y) (string-append indent* " "))
- equal))
- (fprintf w "{} )\n" indent*)
- (set! x (cdr x))
- (set! y (cdr y))
- (set! key-lcs (cdr key-lcs))
- else if (symbol=? (caar x) (car key-lcs))
- do (pretty w (car y) (string-append indent* "+"))
- (set! y (cdr y))
- (set! equal #f)
- else
- do (pretty w (car x) (string-append indent* "-"))
- (set! x (cdr x))
- (set! equal #f))
- (fprintf w "{} )\n" indent)
+ (let loop ()
+ (unless (and (null? key-lcs)
+ (null? x)
+ (null? y))
+ (cond
+ ((and (null? key-lcs)
+ (null? x))
+ (pretty w (car y) (string-append indent* "+"))
+ (set! y (cdr y))
+ (set! equal #f))
+ ((null? key-lcs)
+ (pretty w (car x) (string-append indent* "-"))
+ (set! x (cdr x))
+ (set! equal #f))
+ ((symbol=? (caar x) (caar y) (car key-lcs))
+ (print w indent* " (" (car key-lcs) " .\n")
+ (set! equal (and (diff* w (cdar x) (cdar y) (string-append indent* " "))
+ equal))
+ (print w indent* " )\n")
+ (set! x (cdr x))
+ (set! y (cdr y))
+ (set! key-lcs (cdr key-lcs)))
+ ((symbol=? (caar x) (car key-lcs))
+ (pretty w (car y) (string-append indent* "+"))
+ (set! y (cdr y))
+ (set! equal #f))
+ (else
+ (pretty w (car x) (string-append indent* "-"))
+ (set! x (cdr x))
+ (set! equal #f)))
+ (loop)))
+ (print w indent " )\n")
equal))
((and (list? x) (list? y))
- (fprintf w "{} (\n" indent)
+ (print w indent " (\n")
(let* ((common (lcs x y equal?))
(indent* (string-append indent " "))
(equal #t))
- (loop if (null? common)
- if (null? x)
- if (null? y)
- do (return)
- else
- do (pretty w (car y) (string-append indent* "+"))
- (set! y (cdr y))
- (set! equal #f)
- else if (null? y)
- do (pretty w (car x) (string-append indent* "-"))
- (set! x (cdr x))
- (set! equal #f)
- else
- do (diff* w (car x) (car y) indent*)
- (set! x (cdr x))
- (set! y (cdr y))
- (set! equal #f)
- else
- if (equal? (car x) (car y))
- do (pretty w (car x) (string-append indent* " "))
- (set! x (cdr x))
- (set! y (cdr y))
- (set! common (cdr common))
- else if (equal? (car x) (car common))
- do (pretty w (car y) (string-append indent* "+"))
- (set! y (cdr y))
- (set! equal #f)
- else if (equal? (car y) (car common))
- do (pretty w (car x) (string-append indent* "-"))
- (set! x (cdr x))
- (set! equal #f)
- else
- do (diff* w (car x) (car y) indent*)
- (set! x (cdr x))
- (set! y (cdr y))
- (set! equal #f))
- (fprintf w "{} )\n" indent)
+ (let loop ()
+ (unless (and (null? common)
+ (null? x)
+ (null? y))
+ (cond
+ ((and (null? common)
+ (null? x))
+ (pretty w (car y) (string-append indent* "+"))
+ (set! y (cdr y))
+ (set! equal #f))
+ ((and (null? common)
+ (null? y))
+ (pretty w (car x) (string-append indent* "-"))
+ (set! x (cdr x))
+ (set! equal #f))
+ ((null? common)
+ (diff* w (car x) (car y) indent*)
+ (set! x (cdr x))
+ (set! y (cdr y))
+ (set! equal #f))
+ ((equal? (car x) (car y))
+ (pretty w (car x) (string-append indent* " "))
+ (set! x (cdr x))
+ (set! y (cdr y))
+ (set! common (cdr common)))
+ ((equal? (car x) (car common))
+ (pretty w (car y) (string-append indent* "+"))
+ (set! y (cdr y))
+ (set! equal #f))
+ ((equal? (car y) (car common))
+ (pretty w (car x) (string-append indent* "-"))
+ (set! x (cdr x))
+ (set! equal #f))
+ (else
+ (diff* w (car x) (car y) indent*)
+ (set! x (cdr x))
+ (set! y (cdr y))
+ (set! equal #f)))
+ (loop)))
+ (print w indent " )\n")
equal))
(else
(pretty w x (string-append indent "-"))
@@ -195,7 +215,7 @@
(list
(cons (lambda (s)
(and (string? s)
- (contains s "\n")))
+ (contains? s "\n")))
(lambda (s)
(list (cons '!type 'string)
(cons 'value (split s "\n")))))
@@ -204,10 +224,15 @@
(cons 'value (vector->list v)))))
(cons bytevector? (lambda (b)
(list (cons '!type 'bytevector)
- (cons 'value (loop for i below (bytevector-length b)
- collect (string-append "0x" (number->string
- (bytevector-u8-ref b i)
- 16)))))))))
+ (cons 'value (let loop ((i 0)
+ (acc '()))
+ (when (< i (bytevector-length b))
+ (loop (+ 1 i)
+ (cons (string-append "0x" (number->string
+ (bytevector-u8-ref b i)
+ 16))
+ acc)))
+ (reverse acc))))))))
; Returns a string diff between x and y. Diff knows how to compare lists,
diff --git a/csc/compiler.csc b/csc/compiler.csc
index 4f1cafc..728b8c5 100644
--- a/csc/compiler.csc
+++ b/csc/compiler.csc
@@ -3,6 +3,8 @@
*library-search-dir*
compile)
(import (scheme base)
+ (only (scheme file)
+ file-exists?)
(only (csc codegen)
ir2->ir3)
(only (csc config)
@@ -10,6 +12,8 @@
(only (csc cps)
closure-convert
ir1->ir2)
+ (only (csc encoding)
+ encode)
(only (csc format)
sprintf)
(only (csc hash-map)
@@ -22,9 +26,7 @@
(only (csc list)
revappend)
(only (csc match)
- match)
- (only (scheme file)
- file-exists?))
+ match))
(begin
@@ -131,5 +133,5 @@
(compile (cons (list 'import (append imports1 imports2)) rest)))
((('import . imports) . body)
(define compiled-body (ir1->bytecode (expand-body 'main body (make-import-map imports))))
- (link (revappend library-code (list compiled-body)))
+ (encode (link (revappend library-code (list compiled-body)))))
(_ (error "unexpected form in compile" program))))))
diff --git a/csc/format.csc b/csc/format.csc
index 0469812..6ffd736 100644
--- a/csc/format.csc
+++ b/csc/format.csc
@@ -4,39 +4,40 @@
printf
sprintf)
(import (scheme base)
- (only (scheme write) display)
+ (only (scheme write)
+ display)
+ (only (csc loop)
+ loop)
(only (csc strings)
- find
- not-found-error?
- prefix?))
+ index
+ has-prefix?))
(begin
- (define (fprintf port format-string . format-args)
- (let loop ((start 0)
- (args format-args))
- (cond ((>= start (string-length format-string)))
- ((prefix? "{{" format-string start)
- (write-string "{" port)
- (loop (+ 2 start) args))
- ((prefix? "}}" format-string start)
- (write-string "}" port)
- (loop (+ 2 start) args))
- ((prefix? "{}" format-string start)
- (display (car args) port)
- (loop (+ 2 start) (cdr args)))
- ((prefix? "{" format-string start)
- (raise (error "invalid format string" format-string)))
- (else
- (let* ((open-brace-pos (guard (e
- ((not-found-error? e) (string-length format-string)))
- (find "{" format-string start)))
- (close-brace-pos (guard (e
- ((not-found-error? e) (string-length format-string)))
- (find "}" format-string start)))
- (format-pos (min open-brace-pos close-brace-pos)))
- (write-string format-string port start format-pos)
- (loop format-pos args))))))
+ (define (fprintf port format-string . args)
+ (loop with s = format-string
+ until (string=? "" s)
+ if (has-prefix? s "{{")
+ do (write-string "{" port)
+ (set! s (string-copy s 2))
+ else if (has-prefix? s "}}")
+ do (write-string "}" port)
+ (set! s (string-copy s 2))
+ else if (has-prefix? s "{}")
+ do (display (car args) port)
+ (set! args (cdr args))
+ (set! s (string-copy s 2))
+ else if (or (has-prefix? s "{")
+ (has-prefix? s "}"))
+ do (error "invalid format string" format-string)
+ else
+ do (let* ((open-brace-pos (index s "{"))
+ (close-brace-pos (index s "}"))
+ (format-pos (min open-brace-pos close-brace-pos)))
+ (when (negative? format-pos)
+ (set! format-pos (string-length s)))
+ (write-string s port 0 format-pos)
+ (set! s (string-copy s format-pos)))))
(define (printf format-string . format-args)
diff --git a/csc/strings-test.csc b/csc/strings-test.csc
index 60bfb08..1f981ad 100644
--- a/csc/strings-test.csc
+++ b/csc/strings-test.csc
@@ -8,16 +8,16 @@
(begin
- (test prefix?-good
- (assert-equal #t (prefix? "asdf" "asdfjkl;")))
+ (test has-prefix?-good
+ (assert-equal #t (has-prefix? "asdfjkl;" "asdf")))
- (test prefix?-bad
- (assert-equal #f (prefix? "asdf" "asdbjkl;")))
+ (test has-prefix?-bad
+ (assert-equal #f (has-prefix? "asdbjkl;" "asdf")))
- (test prefix?-too-long
- (assert-equal #f (prefix? "asdf" "as")))
+ (test has-prefix?-too-long
+ (assert-equal #f (has-prefix? "as" "asdf")))
(test str-quote-simple
@@ -28,46 +28,42 @@
(assert-equal "\"this string \\\" has a quote\"" (str-quote "this string \" has a quote")))
- (test find-ok
- (assert-equal 8 (find "abc" "dabsadfdabcdfdfd")))
+ (test index-ok
+ (assert-equal 8 (index "dabsadfdabcdfdfd" "abc")))
- (test find-one-letter
- (assert-equal 8 (find "a" "sdfdfdfsasdfe")))
+ (test index-one-letter
+ (assert-equal 8 (index "sdfdfdfsasdfe" "a")))
- (test find-notfound
- (let* ((match "a")
- (str "def")
- (got-exception '()))
- (guard (e
- ((not-found-error? e) (set! got-exception e)))
- (find match str))
- (assert (not-found-error? got-exception))))
+ (test index-notfound
+ (assert-equal
+ -1
+ (index "def" "a")))
(test contains
(assert-equal
#t
- (contains "abc" "b")))
+ (contains? "abc" "b")))
(test doesnt-contain
(assert-equal
#f
- (contains "abc" "d")))
+ (contains? "abc" "d")))
(test contains-empty
(assert-equal
#t
- (contains "" "")))
+ (contains? "" "")))
(test empty-contains
(assert-equal
#f
- (contains "" "a")))
+ (contains? "" "a")))
(test join-,
@@ -94,4 +90,14 @@
(test split-trailing-empty
- (assert-equal '("a" "") (split "a " " ")))))
+ (assert-equal '("a" "") (split "a " " ")))
+
+
+ (test split-n
+ (assert-equal '("a" "b" "c d e") (split "a b c d e" " " 3)))
+
+
+ (test split-none
+ (assert-equal
+ '()
+ (split "a b c d e" " " 0)))))
diff --git a/csc/strings.csc b/csc/strings.csc
index 75175f0..255a2fd 100644
--- a/csc/strings.csc
+++ b/csc/strings.csc
@@ -1,26 +1,24 @@
(define-library (csc strings)
(export
- contains
- find
+ contains?
+ has-prefix?
+ index
join
- not-found-error?
- prefix?
split
str-quote)
(import (scheme base)
(only (scheme case-lambda) case-lambda)
(only (scheme write) write)
(only (csc list) intercalate)
- (only (csc loop) loop))
+ (only (csc loop)
+ loop
+ return))
(begin
- (define prefix?
- (case-lambda
- ((prefix str) (prefix? prefix str 0))
- ((prefix str start)
- (and (<= (string-length prefix) (- (string-length str) start))
- (string=? prefix (substring str start (+ start (string-length prefix))))))))
+ (define (has-prefix? str prefix)
+ (and (<= (string-length prefix) (string-length str))
+ (string=? prefix (substring str 0 (string-length prefix)))))
(define (str-quote s)
@@ -29,37 +27,38 @@
(get-output-string out)))
- (define-record-type <not-found-error>
- (make-not-found-error)
- not-found-error?)
-
+ (define (index s substr)
+ (loop for i from 0
+ for s = s then (string-copy s 1)
+ until (string=? "" s)
+ if (has-prefix? s substr)
+ return i
+ finally (return -1)))
- (define find
- (case-lambda
- ((match str) (find match str 0 (string-length str)))
- ((match str start) (find match str start (string-length str)))
- ((match str start end)
- (let loop ((i start))
- (cond ((>= i end) (raise (make-not-found-error)))
- ((prefix? match str i) i)
- (else (loop (+ 1 i))))))))
-
- (define (contains s substr)
+ (define (contains? s substr)
(if (string=? "" substr)
#t
- (guard (e ((not-found-error? e) #f))
- (find substr s)
- #t)))
+ (not (negative? (index s substr)))))
(define (join sep strings)
(apply string-append (intercalate sep strings)))
- (define (split s sep)
- (loop for s* = s then (string-copy s* (+ i (string-length sep)))
- for i = (guard (e ((not-found-error? e) (string-length s*)))
- (find sep s*))
- collect (substring s* 0 i)
- while (< i (string-length s*))))))
+ (define split
+ (case-lambda
+ ((s sep n)
+ (if (= 0 n)
+ '()
+ (loop for n = n then (- n 1)
+ for s = s then (string-copy s (+ i (string-length sep)))
+ for i = (let ((i (index s sep)))
+ (if (or (negative? i)
+ (= 1 n))
+ (string-length s)
+ i))
+ collect (substring s 0 i)
+ while (< i (string-length s)))))
+ ((s sep)
+ (split s sep -1))))))
diff --git a/csc/testing.csc b/csc/testing.csc
index 3fa8ad5..68678ca 100644
--- a/csc/testing.csc
+++ b/csc/testing.csc
@@ -6,10 +6,10 @@
test
test-main)
(import (scheme base)
- (only (csc compare) diff)
- (only (csc format)
- printf
- sprintf))
+ (only (scheme write)
+ display
+ write)
+ (only (csc compare) diff))
(begin
@@ -30,32 +30,41 @@
test-error?)
+ (define *test-error* (make-test-error))
+
+
(define *test-handle* (make-test-handle "global"))
+ (define (print . xs)
+ (unless (null? xs)
+ (let ((x (car xs)))
+ (if (or (string? x)
+ (symbol? x))
+ (display x)
+ (write x)))
+ (apply print (cdr xs))))
+
+
(define-syntax test
(syntax-rules ()
((test name body body* ...)
(begin
(set-name! *test-handle* (symbol->string 'name))
- (printf "=== RUN {}\n" 'name)
+ (print "=== RUN " 'name "\n")
(guard (e ((test-error? e)
- (printf "--- FAIL: {}\n" 'name)
- (set-all-succeeded! #f)))
+ (print "--- FAIL: " 'name "\n")
+ (set-all-succeeded! #f)))
body body* ...
- (printf "--- PASS: {}\n" 'name))))))
-
-
- (define (fatalf format-string . format-args)
- (printf "{}: {}\n" (test-name *test-handle*) (apply sprintf format-string format-args))
- (raise (make-test-error)))
+ (print "--- PASS: " 'name "\n"))))))
(define-syntax assert
(syntax-rules ()
((assert expr)
(unless expr
- (fatalf "(assert {}) failed." 'expr)))))
+ (print (test-name *test-handle*) ": (assert " 'expr ") failed.\n")
+ (raise *test-error*)))))
(define-syntax assert-equal
@@ -63,21 +72,20 @@
((assert-equal left right transformers ...)
(let ((d (diff left right transformers ...)))
(unless (string=? "" d)
- (fatalf "Fatal:\n {}\nis not equal to\n {}.\ndiff (-left +right):\n{}" 'left 'right d))))
- ((assert-equal left right)
- (assert-equal equal? left right))))
+ (print "Fatal:\n " 'left "\nis not equal to\n " 'right "\ndiff (-left +right):\n" d "\n")
+ (raise *test-error*))))))
(define-syntax assert-raises
(syntax-rules ()
((assert-raises predicate body body* ...)
- (assert
- (guard (e ((predicate e) #t))
- body body* ...
- #f)))))
+ (assert
+ (guard (e ((predicate e) #t))
+ body body* ...
+ #f)))))
(define (test-main)
(if *all-tests-succeeded*
- (printf "PASS\n")
- (printf "FAIL\n")))))
+ (print "PASS\n")
+ (print "FAIL\n")))))