forked from alex-eg/sex
implement compound and designated literals support
This commit is contained in:
@@ -172,9 +172,7 @@ forms, and what remains."
|
||||
|
||||
(define (walk-expr form)
|
||||
(match form
|
||||
((? vector?)
|
||||
(list->vector
|
||||
(walk-expr (vector->list form))))
|
||||
((? vector?) (walk-initializer (vector->list form)))
|
||||
((? atom?)
|
||||
(atom-to-fmt-c form))
|
||||
;; (comment "text") -> /* text */. `%comment' is the fmt-c directive.
|
||||
@@ -234,6 +232,48 @@ forms, and what remains."
|
||||
;; Drop comments so they will not generate additional comma
|
||||
(else (map walk-expr (remove comment-form? form)))))
|
||||
|
||||
;;; #(a b c) is a brace initializer. A `:' inside one ends a type and
|
||||
;;; turns the whole thing into a C99 compound literal:
|
||||
;;; #(struct point : 1 2) is (struct point){1, 2}, and the type is
|
||||
;;; written as bare words, the way it is everywhere else in the
|
||||
;;; language. `:' is the separator because it is the one thing that can
|
||||
;;; be neither a type word nor an expression -- a named form would be a
|
||||
;;; C identifier, and so shadowable (see issue #36).
|
||||
(define (walk-initializer elements)
|
||||
(let ((parts (list-split (remove comment-form? elements) ':)))
|
||||
(if (null? (cdr parts))
|
||||
(list->vector (walk-designators (car parts)))
|
||||
(cons* '%compound
|
||||
(walk-type (maybe-unwrap-type (car parts)))
|
||||
(walk-designators (cadr parts))))))
|
||||
|
||||
;;; `.field value' is a designated initializer; anything else is
|
||||
;;; positional. C lets the two be mixed, and nothing here stops it. A
|
||||
;;; leading `.' cannot begin a C identifier, so a field name needs no
|
||||
;;; keyword to introduce it and cannot collide with one.
|
||||
(define (walk-designators elements)
|
||||
(let loop ((es elements) (acc (list)))
|
||||
(match es
|
||||
(() (reverse acc))
|
||||
(((? designator? d))
|
||||
(sex-error elements "designated initializer without a value" d))
|
||||
(((? designator? d) value . rest)
|
||||
(loop rest
|
||||
(cons (list '%designate
|
||||
(atom-to-fmt-c (designator-field d))
|
||||
(walk-expr value))
|
||||
acc)))
|
||||
((e . rest) (loop rest (cons (walk-expr e) acc))))))
|
||||
|
||||
(define (designator? x)
|
||||
(and (symbol? x)
|
||||
(let ((s (symbol->string x)))
|
||||
(and (> (string-length s) 1)
|
||||
(char=? #\. (string-ref s 0))))))
|
||||
|
||||
(define (designator-field d)
|
||||
(string->symbol (substring (symbol->string d) 1)))
|
||||
|
||||
(define (walk-var form)
|
||||
;; (var a int) -> (%var int a)
|
||||
;; (var a (const int) 32) -> (%var (const int) a 32)
|
||||
|
||||
Reference in New Issue
Block a user