mirror of
https://github.com/edwinb/Idris2-boot.git
synced 2024-11-24 12:54:28 +03:00
66d67c84cc
and support for Chez and Racket
232 lines
6.9 KiB
Scheme
232 lines
6.9 KiB
Scheme
(define blodwen-read-args (lambda (desc)
|
|
(case (vector-ref desc 0)
|
|
((0) '())
|
|
((1) (cons (vector-ref desc 2)
|
|
(blodwen-read-args (vector-ref desc 3)))))))
|
|
(define b+ (lambda (x y bits) (remainder (+ x y) (expt 2 bits))))
|
|
(define b- (lambda (x y bits) (remainder (- x y) (expt 2 bits))))
|
|
(define b* (lambda (x y bits) (remainder (* x y) (expt 2 bits))))
|
|
(define b/ (lambda (x y bits) (remainder (floor (/ x y)) (expt 2 bits))))
|
|
|
|
(define blodwen-shl (lambda (x y) (ash x y)))
|
|
(define blodwen-shr (lambda (x y) (ash x (- y))))
|
|
(define blodwen-and (lambda (x y) (logand x y)))
|
|
(define blodwen-or (lambda (x y) (logor x y)))
|
|
(define blodwen-xor (lambda (x y) (logxor x y)))
|
|
|
|
(define cast-num
|
|
(lambda (x)
|
|
(if (number? x) x 0)))
|
|
(define destroy-prefix
|
|
(lambda (x)
|
|
(if (eqv? (string-ref x 0) #\#) "" x)))
|
|
(define cast-string-int
|
|
(lambda (x)
|
|
(floor (cast-num (string->number (destroy-prefix x))))))
|
|
(define cast-string-double
|
|
(lambda (x)
|
|
(cast-num (string->number (destroy-prefix x)))))
|
|
(define string-cons (lambda (x y) (string-append (string x) y)))
|
|
(define get-tag (lambda (x) (vector-ref x 0)))
|
|
(define string-reverse (lambda (x)
|
|
(list->string (reverse (string->list x)))))
|
|
(define (string-substr off len s)
|
|
(let* ((l (string-length s))
|
|
(b (max 0 off))
|
|
(x (max 0 len))
|
|
(end (min l (+ b x))))
|
|
(substring s b end)))
|
|
|
|
(define either-left
|
|
(lambda (x)
|
|
(vector 0 #f #f x)))
|
|
|
|
(define either-right
|
|
(lambda (x)
|
|
(vector 1 #f #f x)))
|
|
|
|
(define blodwen-error-quit
|
|
(lambda (msg)
|
|
(display msg)
|
|
(newline)
|
|
(exit 1)))
|
|
|
|
;; Buffers
|
|
|
|
(define (blodwen-new-buffer size)
|
|
(make-bytevector size 0))
|
|
|
|
(define (blodwen-buffer-size buf)
|
|
(bytevector-length buf))
|
|
|
|
(define (blodwen-buffer-setbyte buf loc val)
|
|
(bytevector-u8-set! buf loc val))
|
|
|
|
(define (blodwen-buffer-getbyte buf loc)
|
|
(bytevector-u8-ref buf loc))
|
|
|
|
(define (blodwen-buffer-setint buf loc val)
|
|
(bytevector-s64-set! buf loc val (native-endianness)))
|
|
|
|
(define (blodwen-buffer-getint buf loc)
|
|
(bytevector-s64-ref buf loc (native-endianness)))
|
|
|
|
(define (blodwen-buffer-setdouble buf loc val)
|
|
(bytevector-ieee-double-set! buf loc val (native-endianness)))
|
|
|
|
(define (blodwen-buffer-getdouble buf loc)
|
|
(bytevector-ieee-double-ref buf loc (native-endianness)))
|
|
|
|
(define (blodwen-stringbytelen str)
|
|
(bytevector-length (string->utf8 str)))
|
|
|
|
(define (blodwen-buffer-setstring buf loc val)
|
|
(let* [(strvec (string->utf8 val))
|
|
(len (bytevector-length strvec))]
|
|
(bytevector-copy! strvec 0 buf loc len)))
|
|
|
|
(define (blodwen-buffer-getstring buf loc len)
|
|
(let [(newvec (make-bytevector len))]
|
|
(bytevector-copy! buf loc newvec 0 len)
|
|
(utf8->string newvec)))
|
|
|
|
(define (blodwen-buffer-copydata buf start len dest loc)
|
|
(bytevector-copy! buf start dest loc len))
|
|
|
|
(define (blodwen-readbuffer-bytes h buf loc max)
|
|
(guard (x (#t -1))
|
|
(get-bytevector-n! h buf loc max)))
|
|
|
|
(define (blodwen-readbuffer h)
|
|
(guard (x (#t (bytevector)))
|
|
(get-bytevector-all h)))
|
|
|
|
(define (blodwen-writebuffer h buf loc max)
|
|
(guard (x (#t -1))
|
|
(put-bytevector h buf loc max)
|
|
max))
|
|
|
|
;; Files: Much of the following adapted from idris-chez, thanks to Niklas
|
|
;; Larsson
|
|
|
|
;; All the file operations are implemented as primitives which return
|
|
;; Either Int x, where the Int is an error code:
|
|
(define (blodwen-error-code x)
|
|
(cond
|
|
((i/o-read-error? x) 1)
|
|
((i/o-write-error? x) 2)
|
|
((i/o-file-does-not-exist-error? x) 3)
|
|
((i/o-file-protection-error? x) 4)
|
|
(else 255)))
|
|
|
|
;; If the file operation raises an error, catch it and return an appropriate
|
|
;; error code
|
|
(define (blodwen-file-op op)
|
|
(guard
|
|
(x ((i/o-error? x) (either-left (blodwen-error-code x))))
|
|
(either-right (op))))
|
|
|
|
(define (blodwen-get-n n p)
|
|
(if (port? p) (get-string-n p n) ""))
|
|
|
|
(define (blodwen-putstring p s)
|
|
(if (port? p) (put-string p s) void)
|
|
0)
|
|
|
|
(define (blodwen-open file mode bin)
|
|
(define tc (if (= bin 1) #f (make-transcoder (utf-8-codec))))
|
|
(define bm (buffer-mode line))
|
|
(case mode
|
|
(("r") (open-file-input-port file (file-options) bm tc))
|
|
(("w") (open-file-output-port file (file-options no-fail) bm tc))
|
|
(("wx") (open-file-output-port file (file-options) bm tc))
|
|
(("a") (open-file-output-port file (file-options no-fail no-truncate) bm tc))
|
|
(("r+") (open-file-input/output-port file (file-options no-create) bm tc))
|
|
(("w+") (open-file-input/output-port file (file-options no-fail) bm tc))
|
|
(("w+x") (open-file-input/output-port file (file-options) bm tc))
|
|
(("a+") (open-file-input/output-port file (file-options no-fail no-truncate) bm tc))
|
|
(else (raise (make-i/o-error)))))
|
|
|
|
(define (blodwen-close-port p)
|
|
(when (port? p) (close-port p)))
|
|
|
|
(define (blodwen-get-line p)
|
|
(if (and (port? p) (not (port-eof? p)))
|
|
(let ((str (get-line p)))
|
|
(string-append str "\n"))
|
|
""))
|
|
|
|
(define (blodwen-file-size p)
|
|
(port-length p))
|
|
|
|
(define (blodwen-eof p)
|
|
(if (port-eof? p)
|
|
1
|
|
0))
|
|
|
|
;; Directories
|
|
|
|
(define (blodwen-current-directory)
|
|
(current-directory))
|
|
|
|
(define (blodwen-change-directory dir)
|
|
(if (file-directory? dir)
|
|
(begin (current-directory dir) 1)
|
|
0))
|
|
|
|
(define (blodwen-create-directory dir)
|
|
(blodwen-file-op (lambda () (mkdir dir) 0)))
|
|
|
|
; Scheme only gives a primitive for reading all the files in a directory,
|
|
; so this is faking the C interface!
|
|
(define (blodwen-open-directory dir)
|
|
(blodwen-file-op (lambda () (box (directory-list dir)))))
|
|
|
|
(define (blodwen-close-directory dir) '()) ; no-op, it's not really open
|
|
|
|
(define (blodwen-next-dir-entry dir)
|
|
(let [(dlist (unbox dir))]
|
|
(if (null? dlist)
|
|
(either-left 255)
|
|
(begin (set-box! dir (cdr dlist))
|
|
(either-right (car dlist))))))
|
|
|
|
;; Threads
|
|
|
|
(define blodwen-thread-data (make-thread-parameter #f))
|
|
|
|
(define (blodwen-thread p)
|
|
(fork-thread (lambda () (p (vector 0)))))
|
|
|
|
(define (blodwen-get-thread-data)
|
|
(blodwen-thread-data))
|
|
|
|
(define (blodwen-set-thread-data a)
|
|
(blodwen-thread-data a))
|
|
|
|
(define (blodwen-mutex) (make-mutex))
|
|
(define (blodwen-lock m) (mutex-acquire m))
|
|
(define (blodwen-unlock m) (mutex-release m))
|
|
(define (blodwen-thisthread) (get-thread-id))
|
|
|
|
(define (blodwen-condition) (make-condition))
|
|
(define (blodwen-condition-wait c m) (condition-wait c m))
|
|
(define (blodwen-condition-wait-timeout c m t) (condition-wait c m t))
|
|
(define (blodwen-condition-signal c) (condition-signal c))
|
|
(define (blodwen-condition-broadcast c) (condition-broadcast c))
|
|
|
|
(define (blodwen-sleep s) (sleep (make-time 'time-duration 0 s)))
|
|
(define (blodwen-usleep s)
|
|
(let ((sec (div s 1000000))
|
|
(micro (mod s 1000000)))
|
|
(sleep (make-time 'time-duration (* 1000 micro) sec))))
|
|
|
|
(define (blodwen-time) (time-second (current-time)))
|
|
|
|
(define (blodwen-args)
|
|
(define (blodwen-build-args args)
|
|
(if (null? args)
|
|
(vector 0 '())
|
|
(vector 1 '() (car args) (blodwen-build-args (cdr args)))))
|
|
(blodwen-build-args (command-line)))
|