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

On 10/04/2014 20:43, Zack Weinberg wrote:
> 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>.

If we have those last two, should we also have these?

(<number> or <integer>) / <resolution> = <length>
(<number> or <integer>) / <frequency> = <time>

>     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.

"can be detected at parse time" would need to be defined with more than 
examples. (But see below.)


> 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,

Having two different ways to handle division would confuse authors 
unless they learn the details of when each one is used, which they 
shouldn’t have to as it’s likely to be non-obvious.

Would it make sense to not detect divisions by zero at parse time at all 
and always do as below?


>      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.

So Inf/Inf and 0/0 are both infinite? This is implied by the proposed 
text, but might be worth mentioning explicitly.


>      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.

"Most positive value" seems hard to define when the context indicates no 
upper bound.


> | 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.

-- 
Simon Sapin

Received on Thursday, 10 April 2014 22:42:13 UTC