give fmt-c a name for every parameter
fmt-c takes a parameter's name with `cadr', so an unnamed one handed over bare lost its second word to it: `(* const char)' dropped its star, and `(int)' had no second word at all.
This commit is contained in:
2
Makefile
2
Makefile
@@ -98,7 +98,7 @@ sextest:
|
||||
|
||||
SEX_TEST_PROGRAMS = hello-world lists comments unicode serialize features \
|
||||
feature-flags lambdas compound-literals closures fixpoint \
|
||||
wildcards inference type-shapes
|
||||
wildcards inference type-shapes unnamed-params
|
||||
|
||||
# Multi-module linking is checked end to end; see tests/modules/Makefile.
|
||||
check-modules: sexc
|
||||
|
||||
@@ -378,20 +378,21 @@ forms, and what remains."
|
||||
(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))))
|
||||
;; are not part of it: ((* const char)), (int)
|
||||
(walk-type (maybe-unwrap-type arg))))
|
||||
|
||||
;;; A parameter reaches fmt-c as `(type name)' and nothing else: it
|
||||
;;; reads the name out with `cadr', so a nameless one is the type and
|
||||
;;; an explicit #f. Handing it the bare type instead made it read the
|
||||
;;; type's own second word as the name -- `(* const char)' lost its
|
||||
;;; star -- and a one-word type had no second word to read at all.
|
||||
(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 (lambda (arg)
|
||||
(if (named-arg? arg)
|
||||
(list (arg-type arg) (walk-type (car arg)))
|
||||
(arg-type arg)))
|
||||
(list (arg-type arg)
|
||||
(and (named-arg? arg) (walk-type (car arg)))))
|
||||
(remove comment-form? form)))
|
||||
|
||||
(define (walk-arg-types form)
|
||||
|
||||
@@ -40,15 +40,15 @@
|
||||
(walk-type '(const * const char)))
|
||||
|
||||
(test
|
||||
'(%fun void ((int) (float) (%array (struct what * const))))
|
||||
'(%fun void (int float (%array (struct what * const))))
|
||||
(walk-type '(fn ((int) (float) (¤ (const * struct what))) void)))
|
||||
|
||||
(test
|
||||
'(%fun void ((int) (%array float) (%array (struct what * const))))
|
||||
'(%fun void (int (%array float) (%array (struct what * const))))
|
||||
(walk-type '(fn ((int) (¤ float) (¤ (const * struct what))) void)))
|
||||
|
||||
(test
|
||||
'(%array (%fun void ((int) (%array float) (%array (struct what * const)))))
|
||||
'(%array (%fun void (int (%array float) (%array (struct what * const)))))
|
||||
(walk-type '(¤ (fn ((int) (¤ float) (¤ (const * struct what))) void))))
|
||||
|
||||
;; Type convert to C
|
||||
@@ -136,7 +136,7 @@
|
||||
|
||||
;;; Fn defs
|
||||
(test
|
||||
'(%fun void puk ((int) (%array float 8)))
|
||||
'(%fun void puk ((int #f) ((%array float 8) #f)))
|
||||
(walk-fn-def '(fn puk ((int) (¤ float 8)) void)))
|
||||
|
||||
(test
|
||||
@@ -183,7 +183,7 @@
|
||||
(test
|
||||
'(struct mega_kebab ((int a)
|
||||
((struct ((int year) (int month) (int day))) dob)
|
||||
((%fun bool ((int) (%array int))) min)))
|
||||
((%fun bool (int (%array int))) min)))
|
||||
(walk-struct '(struct mega-kebab
|
||||
((a int)
|
||||
(dob (struct ((year int)
|
||||
|
||||
51
tests/sex-programs/unnamed-params.sex
Normal file
51
tests/sex-programs/unnamed-params.sex
Normal file
@@ -0,0 +1,51 @@
|
||||
(input)
|
||||
(output "one word: 7"
|
||||
"pointer: 2"
|
||||
"aggregate: 3"
|
||||
"array: 2.5"
|
||||
"variadic: 1 two")
|
||||
(return 0)
|
||||
|
||||
;;; A parameter that names nothing still has to reach the C writer as a
|
||||
;;; type and a name, the name being absent. Handed the bare type
|
||||
;;; instead, fmt-c read the type's own second word as the name -- so
|
||||
;;; `(* const char)' came out `const char', which is a different
|
||||
;;; function -- and a one-word type had no second word to read at all.
|
||||
|
||||
(include stdio.h)
|
||||
(include stdarg.h)
|
||||
|
||||
(struct point ((x int) (y int)))
|
||||
|
||||
;;; declared here rather than included, so the prototype we emit is the
|
||||
;;; one the C compiler checks the call against
|
||||
(extern fn abs ((int)) int)
|
||||
(extern fn strlen ((* const char)) size-t)
|
||||
|
||||
(fn origin-x ((p (* (struct point)))) int
|
||||
(return (. (* p) x)))
|
||||
|
||||
(fn second-of ((xs (¤ float 4))) float
|
||||
(return (¤ xs 1)))
|
||||
|
||||
(fn say ((fmt (* const char)) ...) void
|
||||
(var ap va-list)
|
||||
(va-start ap fmt)
|
||||
(vprintf fmt ap)
|
||||
(va-end ap))
|
||||
|
||||
(pub fn main () int
|
||||
(printf "one word: %d\n" (abs -7))
|
||||
(printf "pointer: %d\n" (cast (strlen "hi") int))
|
||||
|
||||
;; the same parameter lists written as types
|
||||
(var p (struct point) #((struct point) : 3 4))
|
||||
(var f (fn ((* (struct point))) int) origin-x)
|
||||
(printf "aggregate: %d\n" (f (& p)))
|
||||
|
||||
(var xs (¤ float 4) #(1.5 2.5 3.5 4.5))
|
||||
(var g (fn ((¤ float 4)) float) second-of)
|
||||
(printf "array: %g\n" (g xs))
|
||||
|
||||
(say "variadic: %d %s\n" 1 "two")
|
||||
(return 0))
|
||||
Reference in New Issue
Block a user