fix (. (* p) x) expanding to *(p).x
Was an fmt-c-writer bug: unary-op must parenthize itself, and not it's arg
This commit is contained in:
@@ -1015,9 +1015,24 @@
|
||||
(cat nl (make-space (+ 2 (fmt-col st))) str " "))
|
||||
st))))))))))
|
||||
|
||||
;; `-' arrives as the symbol binary minus uses, and so with binary
|
||||
;; precedence: `(+ (- b) b)' asked under that spelling comes out
|
||||
;; `(-b) + b'.
|
||||
(define (unary-operator op)
|
||||
(case op
|
||||
((-) 'unary-)
|
||||
((+) 'unary+)
|
||||
((*) 'unary-*)
|
||||
((&) 'unary-&)
|
||||
(else op)))
|
||||
|
||||
;; Parenthesises the whole expression rather than the operand: the
|
||||
;; other way round, `(. (* p) x)' came out `*(p).x', which C reads as
|
||||
;; `*(p.x)'.
|
||||
(define (c-unary-op op x)
|
||||
(c-wrap-stmt
|
||||
(cat (display-to-string op) (c-maybe-paren op (c-expr x)))))
|
||||
(c-maybe-paren (unary-operator op)
|
||||
(cat (display-to-string op) (c-expr x)))))
|
||||
|
||||
;; some convenience definitions
|
||||
|
||||
|
||||
@@ -325,4 +325,24 @@ compiles."
|
||||
(test-assert "a closure passed as an argument stays a value"
|
||||
(emits? "(fn g ((c (closure ((int)) int))) int (return 0))
|
||||
(fn f ((c (closure ((int)) int))) int (return (g c)))"
|
||||
"g(c)"))))
|
||||
"g(c)")))
|
||||
|
||||
;; A unary expression parenthesised its operand rather than itself, so
|
||||
;; the parens landed inside: `*(p).x', which C reads as `*(p.x)'.
|
||||
(test-group "unary operand precedence"
|
||||
(test-assert "member access through a dereference"
|
||||
(emits? "(struct pt ((x int))) (fn f ((p (* (struct pt)))) int (return (. (* p) x)))"
|
||||
"(*p).x"))
|
||||
(test-assert "and not with the parens inside"
|
||||
(not (emits? "(struct pt ((x int))) (fn f ((p (* (struct pt)))) int (return (. (* p) x)))"
|
||||
"*(p).x")))
|
||||
(test-assert "member access through a cast"
|
||||
(emits? (in-fn "(var n int (. (* (cast a (* (struct s)))) f))")
|
||||
"(*(struct s*)a).f"))
|
||||
;; ...without gaining parens where none are due
|
||||
(test-assert "a bare dereference is left alone"
|
||||
(emits? (in-fn "(var p (* int) 0) (= a (* p))") "a = *p"))
|
||||
(test-assert "so is address-of in an argument"
|
||||
(emits? (in-fn "(g (& a))") "g(&a)"))
|
||||
(test-assert "and negation beside a binary operator"
|
||||
(emits? (in-fn "(var n int (+ (- a) b))") "-a + b"))))
|
||||
|
||||
Reference in New Issue
Block a user