From 0c0fc4417166764c49d491a94c6974f20cfb9483 Mon Sep 17 00:00:00 2001 From: Jan Max Meyer Date: Sat, 3 Feb 2024 12:59:25 +0100 Subject: [PATCH] Replace ImlValue::Unset by Option --- src/compiler/ast.rs | 22 +++++---- src/compiler/iml/imlparselet.rs | 59 +++++++++++----------- src/compiler/iml/imlprogram.rs | 7 ++- src/compiler/iml/imlvalue.rs | 87 +++++++++++++++++++-------------- 4 files changed, 99 insertions(+), 76 deletions(-) diff --git a/src/compiler/ast.rs b/src/compiler/ast.rs index 4752e7b..70a1d9f 100644 --- a/src/compiler/ast.rs +++ b/src/compiler/ast.rs @@ -196,10 +196,8 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option) -> ImlV assert!(children.len() <= 2); // Evaluate default parameter - let mut default = ImlValue::Unset; - - if children.len() == 2 { - default = traverse_node_static( + let default = if children.len() == 2 { + let default = traverse_node_static( scope, Some(name.clone()), children[1].borrow().object::().unwrap(), @@ -214,7 +212,11 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option) -> ImlV ), ); } - } + + Some(default) + } else { + None + }; if generics.insert(name.clone(), default).is_some() { scope.error( @@ -252,13 +254,13 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option) -> ImlV name.clone(), if children.len() == 2 { let default = children[1].borrow(); - traverse_node_static( + Some(traverse_node_static( scope, None, default.object::().unwrap(), - ) + )) } else { - ImlValue::Unset + None }, ) .is_some() @@ -331,7 +333,7 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option) -> ImlV let param = &genarg["children"].borrow(); let param = param.object::().unwrap(); - args.push((offset, traverse_node_static(scope, None, param))); + args.push((offset, Some(traverse_node_static(scope, None, param)))); } "genarg_named" => { @@ -356,7 +358,7 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option) -> ImlV nargs.insert( ident.to_string(), - (offset, traverse_node_static(scope, None, param)), + (offset, Some(traverse_node_static(scope, None, param))), ); } diff --git a/src/compiler/iml/imlparselet.rs b/src/compiler/iml/imlparselet.rs index 187faa9..96c60f8 100644 --- a/src/compiler/iml/imlparselet.rs +++ b/src/compiler/iml/imlparselet.rs @@ -20,18 +20,18 @@ during compilation. */ #[derive(Debug, Clone)] pub(in crate::compiler) struct ImlParseletModel { - pub is_consuming: bool, // Flag if parselet is consuming - pub locals: usize, // Total number of local variables present (including arguments) - pub signature: IndexMap, // Arguments signature with default values + pub is_consuming: bool, // Flag if parselet is consuming + pub locals: usize, // Total number of local variables present (including arguments) + pub signature: IndexMap>, // Arguments signature with default values pub variables: IndexMap, // Named local variables pub temporaries: Vec, // Unnamed temporary variables - pub begin: ImlOp, // Begin intermediate operations - pub end: ImlOp, // End intermediate operations - pub body: ImlOp, // Body intermediate Operations + pub begin: ImlOp, // Begin intermediate operations + pub end: ImlOp, // End intermediate operations + pub body: ImlOp, // Body intermediate Operations } impl ImlParseletModel { - pub fn new(signature: Option>) -> Self { + pub fn new(signature: Option>>) -> Self { let signature = signature.unwrap_or(IndexMap::new()); // Generate variables from signature, addresses are enumerated! let variables = signature @@ -105,18 +105,18 @@ is turned into a executable parselet. #[derive(Debug)] pub(in crate::compiler) struct ImlParseletInstance { pub model: Rc>, // Parselet base model - pub generics: IndexMap, // Generic signature with default configuration - pub offset: Option, // Offset of definition - pub name: Option, // Assigned name from source (for debugging) - pub severity: u8, // Capture push severity - pub is_generated: bool, // Flag if parselet instance is auto-generated + pub generics: IndexMap>, // Generic signature with default configuration + pub offset: Option, // Offset of definition + pub name: Option, // Assigned name from source (for debugging) + pub severity: u8, // Capture push severity + pub is_generated: bool, // Flag if parselet instance is auto-generated } /** Representation of parselet instance in intermediate code. */ impl ImlParseletInstance { pub fn new( model: Option, - generics: Option>, + generics: Option>>, offset: Option, name: Option, severity: u8, @@ -148,10 +148,10 @@ impl std::fmt::Display for ImlParseletInstance { if !self.generics.is_empty() { write!(f, "<")?; for (i, (name, value)) in self.generics.iter().enumerate() { - if matches!(value, ImlValue::Unset) { - write!(f, "{}{}", if i > 0 { ", " } else { "" }, name)?; - } else { + if let Some(value) = value { write!(f, "{}{}:{}", if i > 0 { ", " } else { "" }, name, value)?; + } else { + write!(f, "{}{}", if i > 0 { ", " } else { "" }, name)?; } } write!(f, ">")?; @@ -224,19 +224,22 @@ impl ImlParselet { for (name, value) in generics.iter_mut() { // Replace any generics until no more are open - while let ImlValue::Generic { name, .. } = value { + while let Some(ImlValue::Generic { name, .. }) = value { *value = from.borrow().generics.get(name).unwrap().clone(); changes = true; } - match value { - ImlValue::SelfValue | ImlValue::SelfToken => { - // Replace any references of self by from - *value = ImlValue::Parselet(from.clone()); - changes = true; + if let Some(value) = value { + match value { + ImlValue::SelfValue | ImlValue::SelfToken => { + // Replace any references of self by from + *value = ImlValue::Parselet(from.clone()); + changes = true; + } + _ => {} } - ImlValue::Unset => required.push(name.to_string()), - _ => {} + } else { + required.push(name.to_string()); } } @@ -282,10 +285,10 @@ impl ImlParselet { // Copy parameter name var_value.0.clone(), // Register default value, if any - match &var_value.1 { - ImlValue::Unset => None, - value => Some(program.register(value)), - }, + var_value + .1 + .as_ref() + .and_then(|value| Some(program.register(value))), ) }) .collect(), diff --git a/src/compiler/iml/imlprogram.rs b/src/compiler/iml/imlprogram.rs index f8f323c..e4fb1b9 100644 --- a/src/compiler/iml/imlprogram.rs +++ b/src/compiler/iml/imlprogram.rs @@ -189,7 +189,12 @@ impl ImlProgram { } ImlValue::Generic { name, .. } => { // fixme: Is this still relevant??? - finalize_value(¤t.borrow().generics[name], current, visited, configs) + finalize_value( + current.borrow().generics[name].as_ref().unwrap(), + current, + visited, + configs, + ) } _ => None, } diff --git a/src/compiler/iml/imlvalue.rs b/src/compiler/iml/imlvalue.rs index 6462d53..d7ef75a 100644 --- a/src/compiler/iml/imlvalue.rs +++ b/src/compiler/iml/imlvalue.rs @@ -20,7 +20,6 @@ modified and resolved during the compilation process. */ #[derive(Debug, Clone, PartialEq, Eq)] pub(in crate::compiler) enum ImlValue { - Unset, // Unset Unresolved(Rc>), // Unresolved ImlValues are shared SelfValue, // self-reference (value) SelfToken, // Self-reference (consuming) @@ -35,7 +34,7 @@ pub(in crate::compiler) enum ImlValue { addr: usize, // Address }, Generic { - // Known generic placeholder + // Generic placeholder offset: Option, // Source offset name: String, // Identifier }, @@ -46,11 +45,11 @@ pub(in crate::compiler) enum ImlValue { }, Instance { // Unresolved parselet instance definition - offset: Option, // Source offset - target: Box, // Instance target - args: Vec<(Option, ImlValue)>, // Sequential generic args - nargs: IndexMap, ImlValue)>, // Named generic args - severity: Option, // optional desired severity + offset: Option, // Source offset + target: Box, // Instance target + args: Vec<(Option, Option)>, // Sequential generic args + nargs: IndexMap, Option)>, // Named generic args + severity: Option, // optional desired severity is_generated: bool, }, } @@ -70,7 +69,7 @@ impl ImlValue { offset: None, name: name.to_string(), }), - args: vec![(offset, self)], + args: vec![(offset, Some(self))], nargs: IndexMap::new(), severity, is_generated: true, @@ -121,15 +120,19 @@ impl ImlValue { // Resolve sequential generic args for arg in args.iter_mut() { - if !arg.1.resolve(scope) { - is_resolved = false; + if let Some(arg) = arg.1.as_mut() { + if !arg.resolve(scope) { + is_resolved = false; + } } } // Resolve named generic args for narg in nargs.values_mut() { - if !narg.1.resolve(scope) { - is_resolved = false; + if let Some(narg) = narg.1.as_mut() { + if !narg.resolve(scope) { + is_resolved = false; + } } } @@ -155,28 +158,30 @@ impl ImlValue { }; // Check integrity of constant names - if let Self::Unset = arg.1 { - scope.error( - arg.0, - format!("Expecting argument for generic '{}'", name), - ); - } else if arg.1.is_consuming() { - if !utils::identifier_is_consumable(name) { + if let (offset, Some(value)) = &arg { + if value.is_consuming() { + if !utils::identifier_is_consumable(name) { + scope.error( + *offset, + format!( + "Cannot assign consumable {} to non-consumable generic '{}'", + value, name + ) + ); + } + } else if utils::identifier_is_consumable(name) { scope.error( - arg.0, + *offset, format!( - "Cannot assign consumable {} to non-consumable generic '{}'", - arg.1, name + "Cannot assign non-consumable {} to consumable generic {} of {}", + value, name, parselet ) ); } - } else if utils::identifier_is_consumable(name) { + } else { scope.error( arg.0, - format!( - "Cannot assign non-consumable {} to consumable generic {} of {}", - arg.1, name, parselet - ) + format!("Expecting argument for generic '{}'", name), ); } @@ -275,10 +280,7 @@ impl ImlValue { if without_arguments { parselet.signature.len() == 0 - || parselet - .signature - .iter() - .all(|arg| !matches!(arg.1, Self::Unset)) + || parselet.signature.iter().all(|arg| arg.1.is_some()) } else { true } @@ -324,7 +326,6 @@ impl ImlValue { let start = ops.len(); match self { - ImlValue::Unset => return, ImlValue::Unresolved(value) => { return value.borrow().compile(program, current, offset, call, ops) } @@ -352,6 +353,8 @@ impl ImlValue { } ImlValue::Generic { name, .. } => { return current.0.borrow().generics[name] + .as_ref() + .unwrap() .compile(program, current, offset, call, ops) } ImlValue::SelfValue | ImlValue::SelfToken | ImlValue::Parselet(_) => {} @@ -406,7 +409,6 @@ impl ImlValue { impl std::fmt::Display for ImlValue { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Unset => write!(f, "unset"), Self::Unresolved(value) => value.borrow().fmt(f), Self::SelfValue => write!(f, "self"), Self::SelfToken => write!(f, "Self"), @@ -439,7 +441,15 @@ impl std::fmt::Display for ImlValue { let mut first = true; for arg in args { - write!(f, "{}{}", if !first { ", " } else { "" }, arg.1)?; + write!( + f, + "{}{}", + if !first { ", " } else { "" }, + arg.1 + .as_ref() + .map(|v| v.to_string()) + .unwrap_or("None".to_string()) + )?; first = false; } @@ -449,7 +459,11 @@ impl std::fmt::Display for ImlValue { "{}{}:{}", if !first { ", " } else { "" }, narg, - nargs[narg].1 + nargs[narg] + .1 + .as_ref() + .map(|v| v.to_string()) + .unwrap_or("None".to_string()) )?; first = false; } @@ -463,7 +477,6 @@ impl std::fmt::Display for ImlValue { impl std::hash::Hash for ImlValue { fn hash(&self, state: &mut H) { match self { - Self::Unset => state.write_u8('u' as u8), Self::Unresolved(value) => value.borrow().hash(state), Self::VoidToken => state.write_u8('V' as u8), Self::Value(value) => { @@ -480,7 +493,7 @@ impl std::hash::Hash for ImlValue { consumable.hash(state); } */ - other => unreachable!("{} is unhashable", other), + other => unreachable!("{:?} is unhashable", other), } } }