     if op not in '^'
         ops = " #{ops} "
 
-    if (hasPrecedence expr, l) > 0
+    if needsParens expr, l
         ls = parens ls
 
-    if (hasPrecedence expr, r) > 0
+    if needsParens expr, r
         rs = parens rs
 
     "#{ls}#{ops}#{rs}"

compare = (a, b) ->
    (a > b) - (b - a)

hasPrecedence = (a, b) ->
    comparison = compare (rank a), (rank b)
    return comparison unless comparison is 0

    if a in SYMBOLS
        if b in SYMBOLS
            return PRECEDENCE[a] - PRECEDENCE[b]
        else
            return 1
    else if isExpression a
        for [l, r] in _.zip a, b
            comparison = hasPrecedence l, r
            return comparison if comparison isnt 0
        return 0
    else
        return compare a, b

canonical = modifies isExpression, destructured (expr, op, l, r) ->
    if (isCommutative expr) and (compare l, r) < 0

        else
            ops = ' '

    if not isFraction and needsParens expr, l
        ls = parens ls

    if op is '^'
        rs = braces rs
    else if not isFraction and needsParens expr, r
        rs = parens rs

    if fractions and op is '/'
