forked from alex-eg/sex
fix (¤ int N) expanding to int N a[]
Now only C type keywords will stay as a part of type, i.e. (¤ unsigned int) -> unsigned int a[] was and is okay
This commit is contained in:
@@ -292,6 +292,27 @@ forms, and what remains."
|
|||||||
(list)
|
(list)
|
||||||
(walk-expr (drop form 3)))))) ; optional init expression
|
(walk-expr (drop form 3)))))) ; optional init expression
|
||||||
|
|
||||||
|
;;; `(¤ int N)' is N of int
|
||||||
|
;;; `(¤ unsigned int)' is an unsized array of unsigned int
|
||||||
|
;;; An aggregate is the exception -- `(¤ struct point)' ends in a tag,
|
||||||
|
;;; which is part of the type and not a bound.
|
||||||
|
|
||||||
|
(define +c-type-words+
|
||||||
|
'(void char short int long float double signed unsigned
|
||||||
|
bool _Bool complex _Complex _Atomic const volatile restrict))
|
||||||
|
|
||||||
|
(define (array-bound? array-type)
|
||||||
|
(and (> (length array-type) 1)
|
||||||
|
(let ((bound (last array-type))
|
||||||
|
(preceding (last (drop-right array-type 1))))
|
||||||
|
(cond
|
||||||
|
((not (symbol? bound)) #t)
|
||||||
|
((memq bound +c-type-words+) #f)
|
||||||
|
;; a tag always follows its keyword, so `(¤ * struct tt)' ends
|
||||||
|
;; in a name belonging to the type
|
||||||
|
((memq preceding '(struct union enum)) #f)
|
||||||
|
(else #t)))))
|
||||||
|
|
||||||
(define (walk-type form)
|
(define (walk-type form)
|
||||||
;; int -> int
|
;; int -> int
|
||||||
;; (const int) -> const int
|
;; (const int) -> const int
|
||||||
@@ -302,7 +323,7 @@ forms, and what remains."
|
|||||||
;; (fn ((int) (float)) void) -> (%fun void ((int) (float)))
|
;; (fn ((int) (float)) void) -> (%fun void ((int) (float)))
|
||||||
(match form
|
(match form
|
||||||
(('¤ . array-type)
|
(('¤ . array-type)
|
||||||
(if (integer? (last array-type))
|
(if (array-bound? array-type)
|
||||||
;; sized array
|
;; sized array
|
||||||
(let* ((type-list (drop-right array-type 1))
|
(let* ((type-list (drop-right array-type 1))
|
||||||
(type (maybe-unwrap-type type-list))
|
(type (maybe-unwrap-type type-list))
|
||||||
|
|||||||
@@ -345,4 +345,23 @@ compiles."
|
|||||||
(test-assert "so is address-of in an argument"
|
(test-assert "so is address-of in an argument"
|
||||||
(emits? (in-fn "(g (& a))") "g(&a)"))
|
(emits? (in-fn "(g (& a))") "g(&a)"))
|
||||||
(test-assert "and negation beside a binary operator"
|
(test-assert "and negation beside a binary operator"
|
||||||
(emits? (in-fn "(var n int (+ (- a) b))") "-a + b"))))
|
(emits? (in-fn "(var n int (+ (- a) b))") "-a + b")))
|
||||||
|
|
||||||
|
;; An array bound was taken only when it was an integer literal, so a
|
||||||
|
;; symbolic one fell into the type: `(¤ int N)' came out `int N a[]'.
|
||||||
|
(test-group "array bounds"
|
||||||
|
(test-assert "a symbolic bound"
|
||||||
|
(emits? "(define N 4) (struct s ((a (¤ int N))))" "int a[N]"))
|
||||||
|
(test-assert "an expression bound"
|
||||||
|
(emits? "(define N 4) (struct s ((a (¤ char (* 2 N)))))" "char a[2 * N]"))
|
||||||
|
(test-assert "an integer bound still works"
|
||||||
|
(emits? "(struct s ((a (¤ int 4))))" "int a[4]"))
|
||||||
|
;; a multi-word type is keywords all the way down, so a trailing
|
||||||
|
;; keyword belongs to the type and leaves the array unsized
|
||||||
|
(test-assert "a multi-word type is not a bound"
|
||||||
|
(emits? "(struct s ((a (¤ unsigned int))))" "unsigned int a[]"))
|
||||||
|
;; ...and a tag always follows its keyword
|
||||||
|
(test-assert "nor is an aggregate tag"
|
||||||
|
(emits? "(struct t ((z int))) (struct s ((a (¤ struct t))))" "struct t a[]"))
|
||||||
|
(test-assert "nor one behind a pointer"
|
||||||
|
(emits? "(struct t ((z int))) (struct s ((a (¤ * struct t))))" "struct t* a[]"))))
|
||||||
|
|||||||
Reference in New Issue
Block a user