;; -*- Mode: Irken -*- (include "self/cps.scm") (include "self/typing.scm") (include "self/graph.scm") (include "self/analyze.scm") (define (make-writer file) (let ((level 1)) (define (write-indent) (let loop ((i level)) (cond ((> i 0) (write file.fd " ") (loop (- i 1)))))) (define (write-string s) (write-indent) (write file.fd s) (write file.fd "\n") #u) (define (copy s) (write file.fd s)) (define (indent) (set! level (+ level 1))) (define (dedent) (set! level (- level 1))) (define (close-file) (close file.fd)) {write=write-string indent=indent dedent=dedent copy=copy close=close-file} )) (define (make-name-frobber) (define safe-name-map (literal (alist/make (#\! "_bang") (#\* "_splat") (#\? "_question") (#\- "_") (#\+ "_plus") (#\% "_percent") ))) (define c-legal? (char-class (string->list "abcdefghijklmnopqrstuvwxyz_0123456789"))) (define (frob-name name) (define (frob) (let loop ((i 0) (r '())) (if (= i (string-length name)) r (let ((ch (string-ref name i))) (loop (+ i 1) (list:cons (if (c-legal? ch) (char->string ch) (match (alist/lookup safe-name-map ch) with (maybe:yes sub) -> sub (maybe:no) -> (format "_" (hex (char->ascii ch))))) r)))))) (let ((r (string-concat (reverse (frob))))) (if (string=? r "_") ;; special-case "minus" r))) frob-name) (define label-maker (let ((counter (make-counter 0))) (lambda () (format "L" (int (counter.inc)))))) (define encode-immediate (literal:int n) -> (logior 1 (<< n 1)) (literal:char ch) -> (logior 2 (<< (char->ascii ch) 8)) (literal:undef) -> #x0e (literal:cons 'bool 'true _) -> #x106 (literal:cons 'bool 'false _) -> #x006 x -> (error1 "expected immediate literal " x)) (define (wrap-in type arg) (match type with (type:tvar id _) -> arg (type:pred name predargs _) -> (match name with 'int -> (format "unbox(" arg ")") 'string -> (format "((pxll_string*)(" arg "))->data") 'cstring -> (format "(char*)" arg) 'buffer -> (format "(" (irken-type->c-type type) "(((pxll_vector*)" arg ")+1))") 'ptr -> arg 'arrow -> arg 'vector -> arg 'symbol -> arg 'char -> arg 'continuation -> arg 'raw -> (match predargs with ((type:pred 'string _ _)) -> (format "((pxll_string*)(" arg "))") _ -> (error1 "unknown raw type in %cexp" type)) kind -> (if (member-eq? kind c-int-types) (format "unbox(" arg ")") (error1 "wrap-in:" type)) ))) ;; (buffer (struct sockaddr_t)) => (struct sockaddr_t *) (define (irken-type->c-type t) (match t with (type:pred 'buffer (arg) _) -> (format "(" (irken-type->c-type arg) "*)") (type:pred 'struct (arg) _) -> (format "struct " (irken-type->c-type arg)) (type:pred name () _) -> (format (sym name)) _ -> (error1 "malformed ctype" (type-repr t)))) ;; ;; ok, for *now*, I don't really want subtyping. but I *do* want ;; automatic casting/conversion... what's the cleanest way to get that? ;; We have to deal with both typing and code generation. ;; (define c-int-types ;; XXX distinguish between signed and unsigned! ;; XXX also need to handle 64-bit types on a 32-bit platform. '(uint8_t uint16_t uint32_t uint64_t int8_t int16_t int32_t int64_t)) (define (wrap-out type exp) (match type with (type:pred 'int _ _) -> (format "box((pxll_int)" exp ")") (type:pred 'bool _ _) -> (format "PXLL_TEST(" exp ")") (type:pred 'cstring _ _) -> (format "(object*)" exp) (type:pred 'ptr _ _) -> (format "(object*)" exp) (type:pred kind _ _) -> (if (member-eq? kind c-int-types) (format "box((pxll_int)" exp ")") exp) _ -> exp )) ;; substitute into