ANSWER: is 3 a position, or a convention we agreed on?

Both, at different layers, and the split is the same as everywhere else. The
NUMERAL is convention -- int_to_str was already form 1, because no position
determines that twelve is written 1 then 2 in base ten. The NUMBER is a
position: three things are three things regardless of notation.

But the sharper answer follows from `love = 0`. A bare `3` is a MAGNITUDE WITH
NO AXIS. It is not a position until something gives it a direction, which is
exactly why 3.days needs a calendar and why time_add(t, n, "min") had to carry
its axis as a string.

PREDICTIONS AND RESULTS
  P1 numeral = convention, number = position                TRUE
  P2 a bare literal is dimensionless until context types it TRUE
  P3 there is a measurable place where El guesses           TRUE
  P4 Instant + Int is not caught though Duration + Int is   TRUE
  P5 the rule catches it                                    TRUE
  P6 nothing legitimate in the tree relies on it            TRUE

P3/P4 IS THE DEFECT, and it was found by reasoning from the philosophy and then
measured. Duration + Int was refused -- "an Int carries no unit" -- while

    let t: Instant = now()
    let u: Instant = t + 3

compiled to raw (t + 3) and reported CLEAN. Adding a dimensionless number to a
point is worse than adding it to a displacement: it silently moves the instant
by an unspecified amount. 3 of what? Whatever the representation happens to be,
which is the leak itself. The asymmetry had no justification; the rule was
simply never written.

P6 MATTERED. Two calendar tests looked like Instant + Int:

    let later: Instant = i + 1.hour
    let later: Instant = base + 15.hours

They are not. `1.hour` lexes to a Duration -- el_duration_from_nanos(1LL *
3600000000000LL) -- and both stay clean. That is the whole answer demonstrated
in one line: t + 3 is refused because 3 has no axis; t + 1.hour is accepted
because .hour supplies one.

104/104 native + 2 new, integration green, fixpoint ok.
This commit is contained in:
bigmerge
2026-08-17 09:49:50 -05:00
parent 93aa96cfaf
commit c48db6c2a8
3 changed files with 30 additions and 0 deletions
+9
View File
@@ -610,6 +610,15 @@ fn cg_expr(expr: Map<String, Any>) -> String {
record_call(state_get("__cg_current_fn"), "temporal:instant_plus_instant")
return "0 /* TIME_TYPE_ERROR: Instant + Instant */"
}
// A bare literal is a MAGNITUDE WITH NO AXIS. Duration + Int
// was already refused because an Int carries no unit; adding
// one to a POINT is worse, because it silently moves the
// instant by an unspecified amount. The asymmetry had no
// justification -- it was simply never written.
if is_int_expr(right) {
record_call(state_get("__cg_current_fn"), "temporal:instant_plus_int")
return "0 /* TIME_TYPE_ERROR: Instant + Int */"
}
}
if left_is_dur {
if right_is_inst {