diff --git a/fmt-c-writer.scm b/fmt-c-writer.scm index 50daaac..d64b749 100644 --- a/fmt-c-writer.scm +++ b/fmt-c-writer.scm @@ -276,7 +276,7 @@ forms, and what remains." ;; it's a strong semantic cue `(%array ,(walk-type (maybe-unwrap-type array-type))))) (('fn arglist ret-type) - `(%fun ,(walk-type ret-type) ,(walk-arglist arglist))) + `(%fun ,(walk-type ret-type) ,(walk-arg-types arglist))) (('fn . _) (sex-error form "malformed function type" form)) @@ -288,8 +288,13 @@ forms, and what remains." (else (type-convert-to-c form)))) +;;; An array or a function type +(define (structured-type? form) + (and (pair? form) (memq (car form) '(¤ fn)))) + (define (has-pointer-star? form) (and (pair? form) + (not (structured-type? form)) (or (memq '* form) (any has-pointer-star? (filter pair? form))))) @@ -301,6 +306,10 @@ forms, and what remains." (and (pair? type) (any has-pointer-star? (filter pair? type)))) +(define (nested-structured-type type) + (and (pair? type) + (find structured-type? (filter pair? type)))) + (define (type-convert-to-c type) ;; Our pointers to C pointers ;; int -> int @@ -308,6 +317,12 @@ forms, and what remains." ;; const * const char -> const char * const (when (nested-pointer? type) (sex-error type "pointer chains are written flat, as (* * T), not nested" type)) + (let ((inner (nested-structured-type type))) + (when inner + (if (eq? (car inner) 'fn) + ;; (fn ...) is spelled as the pointer it already is in C + (sex-error type "a fn type is a function pointer already: write (fn ...), not (* (fn ...))" type) + (sex-error type "a pointer to an array is not supported" type)))) (if (atom? type) (atom-to-fmt-c type) (flatten (tree-map atom-to-fmt-c @@ -331,26 +346,39 @@ forms, and what remains." ((¤ * const volatile struct union) #t) (else #f))) +;;; Does the parameter name itself? +;;; (f1 float) does +;;; (float), (const char) and (¤ float 4) do not +(define (named-arg? arg) + (and (pair? arg) + (pair? (cdr arg)) ; 1 element args are always type + (not (eq? (car arg) '¤)) + (not (is-probably-type arg)))) + +;;; The type of one parameter +(define (arg-type arg) + (if (named-arg? arg) + (walk-type (maybe-unwrap-type (cdr arg))) + ;; A lone type may arrive wrapped in parens of its own, and those + ;; are not part of it: ((* const char)) + ;; Plain names e.g. (int) are left as is + (walk-type (if (and (pair? arg) (null? (cdr arg)) (pair? (car arg))) + (car arg) + arg)))) + (define (walk-arglist form) ;; E.g.: ;; ((float) (int) (const char) (* const char) (¤ (* const struct res) 32)) ;; ((f1 float) (f2 float) (f3 float) (res (¤ float 4))) - (map (fn - (match x - (('¤ . _) (walk-type x)) - - ;; yeah shitty, but I don't know yet how to determine if the - ;; first entry is part of the type and not an argument name - ;; :( - ((? is-probably-type) (walk-type x)) - - ;; 1 element args are always type - ((_) (walk-type x)) - - ((var . type) (append (list (walk-type (maybe-unwrap-type type))) - (list (walk-type var)))))) + (map (lambda (arg) + (if (named-arg? arg) + (list (arg-type arg) (walk-type (car arg))) + (arg-type arg))) (remove comment-form? form))) +(define (walk-arg-types form) + (map arg-type (remove comment-form? form))) + (define (walk-function form) ;; (fn ret-type name arglist body) -> normal function ;; (fn ret-type name arglist) -> prototype diff --git a/sex-fmt-c.scm b/sex-fmt-c.scm index 6680ffc..7740383 100644 --- a/sex-fmt-c.scm +++ b/sex-fmt-c.scm @@ -737,10 +737,13 @@ (cat (c-type (cadr type) #f) " (*" (or name "") ")(" (fmt-join (lambda (x) (c-type x #f)) (caddr type) ", ") ")")) + ;; MODIFIED FROM UPSTREAM fmt-c: a nameless declarator -- an + ;; array parameter of a function type, where C has no room + ;; for a name -- arrives as #f, and upstream printed it ((%array) - (let ((name (cat name "[" (if (pair? (cddr type)) - (c-expr (caddr type)) - "") + (let ((name (cat (or name "") "[" (if (pair? (cddr type)) + (c-expr (caddr type)) + "") "]"))) (c-type (cadr type) name))) ((%pointer *) @@ -773,10 +776,13 @@ (cat (c-type (cadr type) #f) " (*" (or name "") ")(" (fmt-join (lambda (x) (c-type x #f)) (caddr type) ", ") ")")) + ;; MODIFIED FROM UPSTREAM fmt-c: a nameless declarator -- an + ;; array parameter of a function type, where C has no room + ;; for a name -- arrives as #f, and upstream printed it ((%array) - (let ((name (cat name "[" (if (pair? (cddr type)) - (c-expr (caddr type)) - "") + (let ((name (cat (or name "") "[" (if (pair? (cddr type)) + (c-expr (caddr type)) + "") "]"))) (c-type (cadr type) name))) ((%pointer *)