bind.scm (5667B)
1 ;;;; bind.scm - highlevel foreign interface 2 ; 3 ; Binding syntax: 4 ; 5 ; ["function"] ID "(" [ARG {"," ARG}] ")" ["{" ... "}" | ";"] 6 ; "var" ID ["=" TYPE] {"," ID ["=" TYPE]} [";"] 7 ; 8 ; ARG = TYPE [ "..." ] 9 ; | "..." 10 ; TYPE = "number" | "string" | "function" | "object" | "null" | "undefined" 11 ; | "[" [ARG {"," ARG}] "]" 12 ; | "_" | "*" 13 14 15 ;; needs honu.scm and match.scm 16 17 (define (method-name? str) 18 (and (memv #\. (string->list str)) #t)) 19 20 (define (method-name-split str) 21 (if (char-upper-case? (string-ref str 0)) 22 str 23 (let ((res (string-split str "."))) 24 (if (= (length res) 1) 25 (car res) 26 (list (car res) (foldl (cut string-append <> "." <>) 27 "" (cdr res))))))) 28 29 (define parse-bindings 30 (let ((semicolon (string->symbol ";")) 31 (comma (string->symbol ",")) 32 (dot (string->symbol "."))) 33 (lambda (str) 34 (let ((tokens 35 (with-input-from-string str 36 (lambda () 37 (let loop ((xs '())) 38 (let ((x (read-honu))) 39 (if (eof-object? x) 40 (reverse xs) 41 (loop (cons x xs)))))))) 42 (code '())) 43 (define (add expr) 44 (set! code (cons expr code))) 45 (define (parse t) 46 (match t 47 (() (reverse code)) 48 (('function . more) 49 (parse (function more))) 50 (('var . more) 51 (parse (var more))) 52 (((? symbol?) . _) 53 (parse (function t))) 54 (_ (error "invalid binding syntax" t)))) 55 (define (function t0) 56 (match-let (((name . t) (parse-name t0))) 57 (match t 58 ((('%parens . args) . t) 59 (let ((tl (typelist args))) 60 (match t 61 (((or (? semicolon?) ('%braces . _)) . t2) 62 (set! t t2)) 63 (_ #f)) 64 (add (generate-function-binding name tl)) 65 t)) 66 (_ (error "invalid function binding syntax" t0))))) 67 (define (var t0) 68 (match-let (((name . t) (parse-name t0))) 69 (let ((type #f)) 70 (match t 71 (('= type2 . t2) 72 (set! type (parse-type type2)) 73 (set! t t2)) 74 (_ #f)) 75 (add (generate-variable-binding name type)) 76 (match t 77 (((? semicolon?) . t2) t2) 78 (((? comma?) . t2) (var t2)) 79 (_ t))))) 80 (define (semicolon? t) (eq? t semicolon)) 81 (define (comma? t) (eq? t comma)) 82 (define (dot? t) (eq? t dot)) 83 (define (dots? t) (eq? t '...)) 84 (define (parse-type type) 85 (case type 86 ((number string object null undefined function) type) 87 ((_ *) #f) 88 (else 89 (match type 90 (('%brackets) '()) 91 (('%brackets . args) (typelist args)) 92 (_ (error "invalid binding type" type)))))) 93 (define (typelist lst) 94 (let loop ((lst lst) (tl '())) 95 (match lst 96 (() (reverse tl)) 97 (((? dots?)) (reverse (cons '... tl))) 98 ((type (? dots?)) 99 (reverse (cons (vector (parse-type type)) tl))) 100 ((type (? comma?) . lst) 101 (loop lst (cons (parse-type type) tl))) 102 ((type) 103 (reverse (cons (parse-type type) tl)))))) 104 (define (parse-name t) 105 (match t 106 (((? symbol? s) . t) 107 (let loop ((t t) (name (symbol->string s))) 108 (match t 109 (((? dot?) (? symbol? s2) . t) 110 (loop t (string-append name "." (symbol->string s2)))) 111 (_ (cons name t))))) 112 (_ (error "invalid binding name" t)))) 113 (parse tokens) 114 `(begin ,@(reverse code)))))) 115 116 ;; these must generate expanded code, as parsing of bind expressions happens 117 ;; during canonicalization 118 (define (generate-function-binding name tl) 119 ;;XXX doesn't handle methods (do we need to?) 120 (let ((name (method-name-split name))) 121 (define (finish wraps tmps rest rtmp) 122 (let ((sname 123 (if (string? name) 124 name 125 (cadr name)))) 126 `(define-syntax ,(string->symbol sname) 127 (syntax-rules () 128 ((_ ,@tmps ,@(if rest (list rtmp '...) '())) 129 (%inline 130 ,sname 131 ,@wraps 132 ,@(cond ((eq? #t rest) (list rtmp '...)) 133 (rest (list rest '...)) 134 (else '())))))) )) 135 (define (wrap type tmp) 136 (case type 137 ((number function object null undefined) 138 `(%check ,(symbol->string type) ,tmp)) 139 ((string) 140 `(%string->jstring ,tmp)) 141 (else 142 (if (pair? type) 143 (wrap-vector type tmp) 144 tmp)))) 145 (define (wrap-vector tl tmp) 146 (let loop ((tl tl) (cs '()) (f #f) (i 0)) 147 (match tl 148 (() 149 (if f 150 `(vector ,@(reverse cs)) 151 tmp)) 152 ;;XXX currently not handled 153 ((type (? (cut eq? '... <>))) 154 (loop '() cs f i)) 155 (((? (cut eq? <> '...))) 156 (if f 157 `(%inline 158 ".concat" 159 `(vector ,(reverse cs)) 160 (%inline ".slice" ,tmp ,i)) 161 tmp)) 162 ((type . tl) 163 (let* ((wt `(vector-ref ,tmp ,i)) ;XXX nested access will be inefficient 164 (w (wrap type wt))) 165 (loop tl (cons w cs) (not (equal? w wt)) (+ i 1))))))) 166 (let loop ((tl tl) (wraps '()) (tmps '())) 167 ;; (write tl (current-error-port)) 168 (match tl 169 (() (finish (reverse wraps) (reverse tmps) #f #f)) ; fixed 170 (((? (cut eq? <> '...))) 171 (finish (reverse wraps) (reverse tmps) #t (temp))) ; N + rest 172 ((#(type)) 173 (let ((tmp (temp))) 174 (finish (reverse wraps) (reverse tmps) (wrap type tmp) tmp))) ; N + rest with type 175 ((type . tl) 176 (let ((tmp (temp))) 177 (loop tl (cons (wrap type tmp) wraps) (cons tmp tmps)))))))) 178 179 (define (generate-variable-binding name type) 180 (let ((sname (string->symbol name)) 181 (tmp (temp)) 182 (tmp2 (temp))) 183 `(begin 184 (define-syntax set! 185 (let-syntax ((old-set! set!)) 186 (syntax-rules (,sname) 187 ((_ ,sname ,tmp) 188 (%host-set! 189 ,name 190 ,(case type 191 ((number function object null undefined) 192 `(%check ,(symbol->string type) x)) 193 ((string) 194 `(%string->jstring x)) 195 (else 'x)))) 196 ((_ ,tmp tmp2) 197 (old-set! ,tmp ,tmp2))))) 198 (define-syntax ,sname (%host-ref ,name)))))