M3: document the colour-calculation functions this change touches (#1280)

Why type_of gives references no type, what display shows, how resolve_memo bounds one resolve,
and what variable.create and variable.set check before anything changes.
This commit is contained in:
Christopher Linnett
2026-10-30 16:25:26 +08:00
parent 1784567497
commit 55e5f31eb5
2 changed files with 17 additions and 2 deletions
+9 -2
View File
@@ -140,17 +140,21 @@ impl VariableValue {
}
}
/// The type this value has on its own, which a typed literal needs. None for references
/// (aliases and colour calculations): what they read may be missing or loop, so only
/// resolving them gives a type, and an expression can't take one as a literal.
pub fn type_of(&self) -> Option<VariableType> {
match self {
VariableValue::Color(_) => Some(VariableType::Color),
VariableValue::Number(_) => Some(VariableType::Number),
VariableValue::String(_) => Some(VariableType::String),
VariableValue::Boolean(_) => Some(VariableType::Boolean),
// References have no type of their own: what they read may be missing or loop, so an
// expression can't take one as a typed literal.
VariableValue::Alias(_) | VariableValue::ColorAlpha { .. } | VariableValue::ColorMix { .. } => None,
}
}
/// The value on one line, as the panel shows it: `→ id` for an alias, `α 50% · id` and
/// `from + to @ 40%` for colour calculations, variables by id ([`Self::display_with`] names
/// them).
pub fn display(&self) -> String {
self.display_with(&|id| id.to_string())
}
@@ -406,6 +410,9 @@ impl Variables {
var.values.get(mode).or_else(|| var.values.values().next())
}
/// [`Self::resolve`] with `done` shared by every variable one call reads: each is resolved once
/// and its outcome kept, one met again while still in flight is a cycle (None), and the call
/// reads at most [`Self::RESOLVE_LIMIT`] variables.
fn resolve_memo(
&self,
id: &str,
+8
View File
@@ -902,6 +902,10 @@ fn var_value(cmd: &str, vars: &Variables, kind: VariableType, for_id: Option<&Va
})
}
/// `variable.create`: a variable with a value for every mode of its collection (`values` by mode,
/// then `value` for the modes left, then its type's default). Every value is checked before the
/// variable exists (alias targets, calculation operands, the 32-variable limit), so a refused one
/// leaves nothing behind.
fn var_create(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "variable.create";
let c = req_string(cmd, p, "collection")?;
@@ -966,6 +970,10 @@ fn var_create(s: &mut Session, p: &Value) -> Result<Value> {
Ok(json!({"id": id}))
}
/// `variable.set`: one mode's value (the default mode when none is named), checked against the
/// variable as it stands before anything changes: an alias or calculation may not lead back to it,
/// and a calculation must fit the 32-variable limit. On a variable an extended collection inherits,
/// the value becomes that mode's override.
pub fn var_set(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "variable.set";
let v = req_string(cmd, p, "variable")?;