Allow using non-Some-wrapped values in optional KV attributes
This commit is contained in:
parent
dc8447f08e
commit
16f3488d20
@ -83,6 +83,11 @@ pub enum MatchBinding {
|
|||||||
/// `None =>`
|
/// `None =>`
|
||||||
UnitVariant { name: IStr },
|
UnitVariant { name: IStr },
|
||||||
|
|
||||||
|
/// `$var`
|
||||||
|
/// (A fallback case)
|
||||||
|
/// TODO this is not implemented in the grammar yet, but is used in generated rules
|
||||||
|
Variable { name: IStr },
|
||||||
|
|
||||||
/// `_ =>`
|
/// `_ =>`
|
||||||
Ignore,
|
Ignore,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -363,10 +363,10 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
warn!(
|
// warn!(
|
||||||
"trying to `match` non-reflective vs {name} at {}",
|
// "trying to `match` non-reflective vs {name} at {}",
|
||||||
step.locator
|
// step.locator
|
||||||
);
|
// );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,14 +416,19 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
warn!(
|
// warn!(
|
||||||
"trying to `match` non-reflective vs {name}(...) at {}",
|
// "trying to `match` non-reflective vs {name}(...) at {}",
|
||||||
step.locator
|
// step.locator
|
||||||
);
|
// );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MatchBinding::Variable { name } => binder.bind(
|
||||||
|
&mut self.scopes[scope_idx].variables,
|
||||||
|
&Binding::Variable(name.clone()),
|
||||||
|
matchable_evaled,
|
||||||
|
),
|
||||||
MatchBinding::Ignore => {
|
MatchBinding::Ignore => {
|
||||||
// always matches: no variable to bind, no conditions to check!
|
// always matches: no variable to bind, no conditions to check!
|
||||||
}
|
}
|
||||||
@ -782,11 +787,7 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
|
|||||||
Expression::Variable { name, loc } => {
|
Expression::Variable { name, loc } => {
|
||||||
let locals = &self.scopes[scope_idx].variables;
|
let locals = &self.scopes[scope_idx].variables;
|
||||||
match locals.get(name as &str) {
|
match locals.get(name as &str) {
|
||||||
Some(variable_value) => {
|
Some(variable_value) => Ok(variable_value.clone()),
|
||||||
let new = variable_value.clone();
|
|
||||||
eprintln!("{variable_value:?} -> {new:?}");
|
|
||||||
Ok(variable_value.clone())
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let locals_list = locals.keys().join(", ");
|
let locals_list = locals.keys().join(", ");
|
||||||
Err(InterpreterError::TypeError {
|
Err(InterpreterError::TypeError {
|
||||||
|
|||||||
@ -215,20 +215,30 @@ fn compile_ast_block_to_steps(
|
|||||||
let extra_inject = (attr_name.as_str() == "class" && !he.classes.is_empty())
|
let extra_inject = (attr_name.as_str() == "class" && !he.classes.is_empty())
|
||||||
.then(|| intern(he.classes.iter().map(|istr| istr.as_str()).join(" ") + " "));
|
.then(|| intern(he.classes.iter().map(|istr| istr.as_str()).join(" ") + " "));
|
||||||
if attr_flags.optional {
|
if attr_flags.optional {
|
||||||
|
// For optional fields:
|
||||||
|
// - if it matches Some($x), unwrap to $x and emit $x
|
||||||
|
// - if it matches None, skip
|
||||||
|
// - if it matches neither, assume it's already unwrapped and emit directly
|
||||||
|
// A little bit ugly to say the least...
|
||||||
let mut some_stage = Vec::new();
|
let mut some_stage = Vec::new();
|
||||||
|
let virtual_varname = intern("___attrval");
|
||||||
|
|
||||||
gen_steps_to_write_attribute(
|
gen_steps_to_write_attribute(
|
||||||
he,
|
he,
|
||||||
attr_name,
|
attr_name,
|
||||||
attr_expr,
|
&Expression::Variable {
|
||||||
|
name: virtual_varname.clone(),
|
||||||
|
loc: he.loc.clone(),
|
||||||
|
},
|
||||||
extra_inject.clone(),
|
extra_inject.clone(),
|
||||||
&mut some_stage,
|
&mut some_stage,
|
||||||
);
|
);
|
||||||
let binding = MatchBinding::TupleVariant {
|
let binding = MatchBinding::TupleVariant {
|
||||||
name: intern("Some"),
|
name: intern("Some"),
|
||||||
pieces: vec![Binding::Variable(intern("___attrval"))],
|
pieces: vec![Binding::Variable(virtual_varname.clone())],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut arms = vec![(binding, some_stage)];
|
let mut arms = vec![(binding, some_stage.clone())];
|
||||||
|
|
||||||
if let Some(extra_inject) = extra_inject {
|
if let Some(extra_inject) = extra_inject {
|
||||||
let mut none_stage = Vec::new();
|
let mut none_stage = Vec::new();
|
||||||
@ -244,15 +254,29 @@ fn compile_ast_block_to_steps(
|
|||||||
},
|
},
|
||||||
none_stage,
|
none_stage,
|
||||||
));
|
));
|
||||||
|
} else {
|
||||||
|
arms.push((
|
||||||
|
MatchBinding::UnitVariant {
|
||||||
|
name: intern("None"),
|
||||||
|
},
|
||||||
|
Vec::new(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arms.push((
|
||||||
|
MatchBinding::Variable {
|
||||||
|
name: virtual_varname.clone(),
|
||||||
|
},
|
||||||
|
some_stage,
|
||||||
|
));
|
||||||
|
|
||||||
instructions.push(Step {
|
instructions.push(Step {
|
||||||
def: StepDef::Match {
|
def: StepDef::Match {
|
||||||
matchable: attr_expr.clone(),
|
matchable: attr_expr.clone(),
|
||||||
arms,
|
arms,
|
||||||
},
|
},
|
||||||
locator: he.loc.clone(),
|
locator: he.loc.clone(),
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
gen_steps_to_write_attribute(
|
gen_steps_to_write_attribute(
|
||||||
he,
|
he,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user