1(library (yuni transformer cirs writer) 2 (export cirs-write) 3 (import (rnrs) 4 (srfi :8) 5 (shorten)) 6 7(define (cirs-write obj p) 8 (define (cirs-exp->string obj) 9 10 (define binops ;; (OP X Y Z ...) 11 ;; * / % + - << >> bit-xor bit-and bit-or and or = 12 ;; (* X Y Z ...) => (X * Y * Z) 13 ;; (pref X Y Z ...) => X->Y->Z .. 14 ;; (fref X Y Z ...) => X.Y.Z 15 '((* . " * ") (/ . " / ") (% . " % ") (+ . " + ") 16 (- . " - ") (<< . " << ") (>> . " >> ") (bit-xor . " ^ ") 17 (bit-and . " & ") (bit-or . " | ") (and . " && ") 18 (or . " || ") (= . " = ") 19 (pref . "->") (fref . "."))) 20 21 (define compops ;; (OP X Y) 22 ;; < > <= >= == != 23 ;; *= /= %= add= sub= <<= >>= bit-and= bit-xor= bit-or= 24 ;; (< X Y) => (X < Y) 25 '((< . " < ") (> . " > ") (<= . " <= ") (>= . " >= ") (== . " == ") 26 (!= . " != ") (*= . " *= ") (/= . " /= ") (%= . " %= ") (add= . " += ") 27 (sub= . " -= ") (<<= . " <<= ") (>>= . " >>= ") (bit-xor= . " ^= ") 28 (bit-and= . " &= ") (bit-or= . " |= "))) 29 30 ;; inc dec ++ -- not bit-not 31 ;; (inc X) => X++ 32 ;; FIXME: (++ X) => ++X 33 ;; (mref X) => (*(X)) 34 ;; (ptr X) => (&(X)) 35 (define uniops/pre 36 '( 37 #| ;; we cannot do this in R6RS... 38 (++ . "++") 39 (-- . "--") 40 |# 41 (mref . "*") 42 (ptr . "&"))) 43 (define uniops/post 44 '((inc . "++") 45 (dec . "--"))) 46 (define (output-op l p) 47 (define (fold-ops str rest*) 48 (define (itr rest) 49 (when (pair? rest) 50 (display str p) 51 (display (car rest) p) 52 (itr (cdr rest)))) 53 (cond 54 ((pair? rest*) 55 (display "(" p) 56 (display (car rest*) p) 57 (itr (cdr rest*)) 58 (display ")" p)) 59 (else 60 (display "()" p)))) 61 (let ((op (car l)) 62 (rest (cdr l))) 63 (cond 64 ((assoc op binops) 65 => (^x (let ((str (cdr x))) 66 (fold-ops 67 str 68 (map cirs-exp->string rest))))) 69 ((assoc op compops) 70 => (^x (let ((str (cdr x))) 71 ;; FIXME: check op length here.. 72 (fold-ops 73 str 74 (map cirs-exp->string rest))))) 75 ((assoc op uniops/pre) 76 => (^x (let ((str (cdr x))) 77 (display str p) 78 (display (cirs-exp->string (car rest)) p)))) 79 ((assoc op uniops/post) 80 => (^x (let ((str (cdr x))) 81 (display (cirs-exp->string (car rest)) p) 82 (display str p)))) 83 ;; ((quote X) Y Z ...) => X(Y, Z); // function call 84 ((and (list? op) (eq? 'quote (car op))) 85 (let ((name (cirs-exp->string (cadr op))) 86 (args rest)) 87 (display name p) 88 (fold-ops ", " (map cirs-exp->string args)))) 89 (else 90 (case op 91 ;; (comment X) => /* X */ 92 ((comment) 93 (display " /* " p) 94 (display (car rest) p) 95 (display " */ " p)) 96 ;; (aref X Y Z ...) => (X)[Y][Z] 97 ((aref) 98 (let ((X (cirs-exp->string (car rest))) 99 (refs (map (^e (string-append "[" e "]")) 100 (map cirs-exp->string (cdr rest))))) 101 (display (string-append X refs) p))) 102 ;; (seq X Y Z ...) => X , Y , Z 103 ((seq) 104 (fold-ops ", " (map cirs-exp->string rest))) 105 ;; (? X Y Z) => X ? Y : Z 106 ((?) 107 (let ((X (cirs-exp->string (car rest))) 108 (Y (cirs-exp->string (cadr rest))) 109 (Z (cirs-exp->string (caddr rest)))) 110 (display (string-append "(" X " ? " Y " : " Z ")") p))) 111 ;; (sizeof X) => (sizeof(X)) 112 ((sizeof) 113 (display op p) 114 (display (string-append "(" (cirs-exp->string (car rest)) ")") p)) 115 ;; (cast X Y) => ((X)Y) 116 ;; (cast (X Y Z) W) => ((X Y Z) W) 117 ((cast) 118 (let ((type (car rest)) 119 (value (cirs-exp->string (cadr rest)))) 120 (display "((" p) 121 (cond 122 ((list? type) 123 (for-each (^e (display e p)) 124 (map cirs-exp->string type))) 125 (else 126 (display (cirs-exp->string type)))) 127 (display ") " p) 128 (display value p) 129 (display ") " p))) 130 (else 131 (assertion-violation 'cirs-exp->string "invalid op" op))))))) 132 133 (receive (p str) (open-string-output-port) 134 ;; write 135 (cond 136 ((string? obj) 137 (write obj p)) 138 ((or (symbol? obj) (number? obj)) 139 (display obj p)) 140 ((list? obj) 141 (output-op obj p)) 142 (else 143 (assertion-violation 'cirs-exp->string "invalid datum" obj))) 144 ;; output 145 (let ((out (str))) 146 (close-port p) 147 out))) 148 (let ((current-indent 0)) 149 (define (indent+) (set! current-indent (+ 1 current-indent))) 150 (define (indent-) (set! current-indent (- current-indent 1))) 151 (define (out str) 152 (display str p)) 153 (define (indent) 154 (define (itr rest) 155 (unless (= rest 0) 156 (out " ") 157 (itr (- rest 1)))) 158 (itr current-indent)) 159 (define (outi str) 160 (indent) 161 (out str)) 162 (define (line str) 163 (indent) 164 (out str) 165 (out "\n")) 166 (define (out-exp obj) 167 (out (cirs-exp->string obj))) 168 (define (emit-block body-k) 169 (out " {\n") 170 (indent+) 171 (body-k) 172 (indent-) 173 (indent) 174 (out "} ")) 175 (define (put-form l) 176 ;; struct/union members 177 ;; (name type) 178 ;; (name type ... (init value)) 179 ;; (name (bit pos) type ...) 180 ;; (name (bit pos) type ... (init value)) 181 (define (emit-members m) 182 (define (emit-member x) 183 (indent) 184 (let ((name (car x)) 185 (args (cdr x)) 186 (init #f) 187 (bit #f)) 188 ;; consume args 189 (for-each (^e 190 (cond 191 ((symbol? e) 192 (out (symbol->string e)) 193 (out " ")) 194 ((list? e) 195 (let ((op (car e)) 196 (arg (cadr e))) 197 (case op 198 ((bit) 199 (set! bit arg)) 200 ((init) 201 (set! init arg)) 202 (else 203 (assertion-violation 'emit-members "invalid op" 204 e))))))) 205 args) 206 ;; emit name 207 (out (symbol->string name)) 208 ;; emit bit 209 (when bit 210 (out ":") 211 (out (number->string bit))) 212 ;; emit init 213 (when init 214 (out " = ") 215 (put-form init)) 216 (out ";\n"))) 217 (for-each emit-member m)) 218 (define (put-begin obj) 219 (for-each put-form obj)) 220 (define (complain x) 221 (assertion-violation 'put-form "invalid form" x)) 222 (if (pair? l) 223 (let ((op (car l)) 224 (rest (cdr l))) 225 (case op 226 ((if) 227 (outi "if (") 228 (out-exp (car rest)) 229 (out ")") 230 (case (length rest) 231 ;; (if P X) => if (P) { X } 232 ((2) 233 (emit-block (^[] (put-form (cadr rest))))) 234 ;; (if P X Y) => if (P) { X } else { Y } 235 ((3) 236 (emit-block (^[] (put-form (cadr rest)))) 237 (out " else ") 238 (emit-block (^[] (put-form (caddr rest))))) 239 (else (complain l)))) 240 ((begin) 241 (put-begin rest)) 242 243 ;; (cond (P X) (P Y) ... (else Z)) 244 ((cond) 245 (for-each (^e 246 (if (list? e) 247 (let ((op (car e)) 248 (code (cdr e))) 249 (cond 250 ((eq? op 'else) 251 (out " else ") 252 (emit-block (^[] (put-begin code)))) 253 (else 254 (out " else if (") 255 (out-exp op) 256 (out ")") 257 (emit-block (^[] (put-begin code)))))) 258 (complain e))) 259 rest)) 260 261 ;; (switch P (X Y ...) (X Y ...) ... (default Y ...)) 262 ;; => switch (P) { case X: Y ,,, ... default: Y ,,, } 263 ((switch) 264 (let ((pred (car rest)) 265 (cases (cdr rest))) 266 (outi "switch (") 267 (out-exp pred) 268 (out ")") 269 (emit-block (^[] 270 (for-each (^e (if (list? e) 271 (let ((op (car e)) 272 (code (cdr e))) 273 (if (eq? op 'default) 274 (line "default:") 275 (line (string-append 276 (cirs-exp->string op) 277 ":"))) 278 (put-begin code)) 279 (complain e))) 280 cases))))) 281 282 ;; (while P ...) => while (P) { ... } 283 ((while) 284 (outi "while (") 285 (out-exp (car rest)) 286 (out ")") 287 (emit-block (^[] (put-begin (cdr rest))))) 288 289 ;; (do-while P ...) => do { ... } while (P) ; 290 ((do-while) 291 (outi "do ") 292 (emit-block (^[] (put-begin (cdr rest)))) 293 (out " while (") 294 (out-exp (car rest)) 295 (out ");\n")) 296 297 ;; (for (X Y Z) ...) => for ( X ; Y ; Z ) { ... } 298 ;; (for (#f #f #f) ...) => for ( ;; ) { ... } 299 ((for) 300 (let ((cntl (car rest)) 301 (code (cdr rest))) 302 (if (= (length cntl) 3) 303 (let ((x (car cntl)) 304 (y (cadr cntl)) 305 (z (caddr cntl))) 306 (outi "for (") 307 (when x (out-exp x)) 308 (out " ; ") 309 (when y (out-exp y)) 310 (out " ; ") 311 (when z (out-exp z)) 312 (out ")") 313 (emit-block (^[] (put-begin code)))) 314 (complain cntl)))) 315 316 ;; (goto X) => goto X; 317 ((goto) 318 (outi "goto ") 319 (out-exp (car rest)) 320 (out ";\n")) 321 322 ;; (continue) => continue; 323 ((continue) 324 (outi "continue;\n")) 325 326 ;; (break) => break; 327 ((break) 328 (outi "break;\n")) 329 330 ;; (return) => return; 331 ;; (return X) => return(X); 332 ((return) 333 (cond 334 ((null? rest) 335 (outi "return;\n")) 336 (else 337 (outi "return ") 338 (out-exp (car rest)) 339 (out ";\n")))) 340 341 ;; (label X) => X: 342 ((label) 343 ;; labels won't be indented 344 (out-exp (car rest)) 345 (out " :\n")) 346 347 ;; struct / union 348 ;; FIXME: (struct TAG (DECL ...) MEMBER ...) 349 ;; (struct TAG DECL MEMBER ...) 350 ;; => struct TAG { ... } DECL ... ; 351 ((struct union) 352 (let ((name op) 353 (tag (car rest)) 354 (decl (cadr rest)) 355 (members (cddr rest))) 356 (case name 357 ((struct) 358 (outi "struct ")) 359 ((union) 360 (outi "union "))) 361 (emit-block (^[] (emit-members members))) 362 (out-exp decl) 363 (out "; \n"))) 364 365 ;; (def NAME DEF attribute ...) 366 ;; (def NAME DEF attribute ... (init x)) 367 ;; (decl NAME DEF attribute ...) 368 ;; (decl NAME struct attribute ...) 369 ;; (decl NAME union attribute ...) 370 ((def decl) 371 (let ((definition (cadr rest)) 372 (name (car rest)) 373 (body (cddr rest))) 374 (cond 375 ((symbol? definition) 376 ;; forward definition of union/struct cannot contain any 377 ;; attributes 378 (case definition 379 ((struct union) 380 (outi (symbol->string definition)) 381 (out " ") 382 (out (symbol->string name)) 383 (out ";\n")))) 384 (else 385 (let ((init #f)) 386 (for-each (^e (out (symbol->string e)) 387 (out " ")) 388 definition) 389 (out (symbol->string name)) 390 (for-each (^e 391 (let ((op (car e)) 392 (args (cdr e))) 393 (case op 394 ((init) 395 (set! init (car args)))))) 396 body) 397 (when init 398 (out " = ") 399 (out (cirs-exp->string init))) 400 (out "; \n")))))) 401 402 ;; (defn NAME RETTYPE DEF attributes ... body ...) 403 ;; DEF: ((NAME def ...) ...) 404 ((defn) 405 (let ((name (car rest)) 406 (rettype (cadr rest)) 407 (def (caddr rest)) 408 (body (cdddr rest))) 409 (define (out-types l) 410 (cond 411 ((list? l) 412 (for-each (^e 413 (out (symbol->string e)) 414 (out " ")) 415 l)) 416 (else 417 (out (symbol->string l)) 418 (out " ")))) 419 (define (out-def r) 420 (define (out-entry e) 421 (let ((name (car e)) 422 (types (cdr e))) 423 (out-types types) 424 (out (symbol->string name)))) 425 (let ((head (car r)) 426 (tail (cdr r))) 427 (out-entry head) 428 (unless (null? tail) 429 (out ", ") 430 (out-def tail)))) 431 432 ;; output 433 (indent) 434 (out-types rettype) 435 (out "\n") 436 (outi (symbol->string name)) 437 (cond 438 ((null? def) 439 (out "(void)")) 440 (else 441 (out "(") 442 (out-def def) 443 (out ")"))) 444 (emit-block (^[] (put-begin body))) 445 (out "\n"))) 446 #| 447 ;; (deftype NAME DEF) => typedef DEF name; 448 ((deftype) 449 ) 450 |# 451 452 (else 453 (indent) 454 (out-exp l) 455 (out ";\n") 456 ))) 457 (out (cirs-exp->string l)))) 458 (for-each put-form obj))) 459 ;; === keywords === 460 ;; (array X Y Z ...) => { X , Y , Z , ... } 461 ;; (attribute A X) => UNSPEC 462 ;; (cpp-if P X Y) 463 ;; (cpp-cond (P X) (P Y) ... (else Z)) 464 ;; (cpp-ifdef S X Y) 465 ;; (cpp-ifndef S X Y) 466 ;; (cpp-include FN) 467 468) 469