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