[css-values] Concrete proposal for unit algebra in calc()

I brought up the question of being able to divide two <length>s in
calc() earlier this week, along with min/max expressions.  I'm
convinced min/max are Too Hard for right now, but I think it's not too
hard to specify enough unit algebra to make <length> ratios feasible.
Here is a concrete proposal relative to the current ED.

In section 8.1.1 (calc() syntax):

-  product : unit [ S* [ "*" S* unit | "/" S* NUMBER ] ]*;
+  product : unit [ S* [ "*" S* unit | "/" S* unit ] ]*;

In section 8.1.2 (type checking), replace the second two bullet points
in the list with the following:

 * At '*', apply these rules in order:

   1. If both sides are <integer>, resolve to <integer>.
   2. If one side is <number> and the other is <number> or <integer>,
      resolve to <number>.
   3. If one side is <number> or <integer> and the other is a
      _dimension_, resolve to the type of the _dimension_.
   4. If one side is <time> and the other is <frequency>, resolve to
      <number>.
   5. If one side is <length> and the other is <resolution>, resolve
      to <number>.
   6. All other combinations of units are invalid.

 * At '/', apply these rules in order:

   1. If both sides have the same type, resolve to <number>.
   2. If the left side is a <number> or <integer> and the right side is
      also a <number> or <integer>, resolve to <number>.
   3. If the left side is a _dimension_ and the right side is <number>
      or <integer>, resolve to the type of the _dimension_.
   4. If the left side is a <number> or <integer> and the right side
      is a <length>, resolve to <resolution>.
   5. If the left side is a <number> or <integer> and the right side
      is a <time>, resolve to <frequency>.
   6. All other combinations of units are invalid.

Also, replace from "Also, division by zero is invalid" through the end
of that paragraph with:

   ... The expression is also invalid if it contains a division by
   zero which can be detected at parse time.  For example,
   `calc(10px/0)` and `calc(10px/(1em - 1em))` are both invalid.
   However, `calc(10px/1em)` and `calc(10px/5%)` are *not* invalid,
   even though `1em` might evaluate to zero when the value is
   computed, and `5%` might evaluate to zero when the value is used.

In section 8.1.3 (computed value), delete the note about the
representation of a computed calc(), and perhaps also add some more
examples.

In section 8.1.4 (range checking), add immediately after "...to the
range allowed in the target context":

    If a (sub-)expression contains a division by zero which was not
    detected at parse time, the value of that (sub-)expression is
    infinite.  The result of any further computation on infinite
    values is also infinite, except that dividing any finite value
    by an infinite value produces zero.

    If the value resulting from a complete `calc()` expression is
    infinite, it is clamped and becomes the most positive value
    allowed in the target context.

| NOTE: This deliberately differs from the behavior specified in IEEE
| 754 in order to avoid introducing NaNs and negative zero into CSS,
| However, implementations using IEEE 754-conformant floating point
| arithmetic internally can produce the above semantics by treating
| -Inf, +Inf, and NaN as "infinite", and -0 as equivalent to +0.

That should be all that is required.

zw

Received on Thursday, 10 April 2014 19:44:13 UTC