diff --git a/bauble/src/parse/parser.rs b/bauble/src/parse/parser.rs index 049ff02..7e30e65 100644 --- a/bauble/src/parse/parser.rs +++ b/bauble/src/parse/parser.rs @@ -639,18 +639,8 @@ pub fn parser<'a>() -> impl Parser<'a, ParserSource<'a>, ParseValues, Extra<'a>> .boxed() } - enum ItemType { - Value, - Copy, - } - uses.then( - just("copy") - .padded() - .ignore_then(binding(ident, object.clone(), path.clone(), comments)) - .map(|binding| (binding, ItemType::Copy)) - .or(binding(ident, object, path.clone(), comments) - .map(|binding| (binding, ItemType::Value))) + binding(ident, object, path.clone(), comments) .repeated() .collect::>(), ) @@ -659,24 +649,17 @@ pub fn parser<'a>() -> impl Parser<'a, ParserSource<'a>, ParseValues, Extra<'a>> ParseValues { uses, values: IndexMap::default(), - copies: IndexMap::default(), }, - |mut values, ((ident, type_path, value), ty)| { + |mut values, (ident, type_path, value)| { let binding = Binding { type_path, value }; - match ty { - ItemType::Value => { - if values.values.contains_key(&ident) { - emitter.emit(Rich::custom( - ident.span, - "This identifier was already used".to_string(), - )); - } - values.values.insert(ident, binding); - } - ItemType::Copy => { - values.copies.insert(ident, binding); - } + + if values.values.contains_key(&ident) { + emitter.emit(Rich::custom( + ident.span, + "This identifier was already used".to_string(), + )); } + values.values.insert(ident, binding); values }, ) diff --git a/bauble/src/parse/value.rs b/bauble/src/parse/value.rs index 968003c..ca6142f 100644 --- a/bauble/src/parse/value.rs +++ b/bauble/src/parse/value.rs @@ -174,5 +174,4 @@ pub struct Binding { pub struct ParseValues { pub uses: Vec>, pub values: IndexMap, - pub copies: IndexMap, } diff --git a/bauble/src/value/convert.rs b/bauble/src/value/convert.rs index 34f5102..e527cd7 100644 --- a/bauble/src/value/convert.rs +++ b/bauble/src/value/convert.rs @@ -10,8 +10,8 @@ use crate::{ }; use super::{ - Attributes, CopyVal, CopyValInner, Ident, Result, SpannedValue, Symbols, UnspannedVal, Val, - Value, ValueContainer, ValueTrait, + Attributes, Ident, Result, SpannedValue, Symbols, UnspannedVal, Val, Value, ValueContainer, + ValueTrait, }; pub fn no_attr() -> Option<&'static Attributes> { @@ -102,16 +102,7 @@ pub(super) fn value_type(value: &ParseVal, symbols: &Symbols) -> Result { - // Don't resolve types of copy types. - if let Some(ident) = path.as_ident() - && symbols.try_resolve_copy(&ident).is_some() - { - None - } else { - Some(symbols.resolve_asset(path)?.0.spanned(path.span())) - } - } + Value::Ref(path) => Some(symbols.resolve_asset(path)?.0.spanned(path.span())), Value::Or(paths) => { let mut ty = None; for path in paths { @@ -227,7 +218,6 @@ pub(super) fn default_value_type( #[derive(Clone, Copy, Debug)] pub enum AnyVal<'a> { Parse(&'a ParseVal), - Copy(&'a CopyValInner), Complete(&'a Val), Unspanned(&'a UnspannedVal), } @@ -441,8 +431,6 @@ where fn get_asset(ident: &Self::Ref, symbols: &Symbols) -> Result; - fn ref_ident(path: &Self::Ref) -> Option>; - fn convert_inner<'a, C: ConvertValue>( value: Spanned<&Value>, attributes: Spanned<&Attributes>, @@ -451,49 +439,6 @@ where expected_type: TypeId, extra_attributes: Option<&'a Attributes>, ) -> Result { - // Resolve copy refs. - if let Value::Ref(r) = &value.value - && let Some(ident) = Self::ref_ident(r) - && let Some((copy, Some(val))) = meta.symbols.try_resolve_copy(ident.as_str()) - { - return match extra_attributes { - Some(s) if !s.0.is_empty() => { - let mut extra = ConvertValue::to_any_attributes(s, &meta); - - for (i, v) in attributes.iter() { - let i = Self::get_spanned_field(i, &meta); - if let Some((ident, _)) = extra.0.get_key_value(i.as_str()) { - Err(ConversionError::DuplicateAttribute { - first: ident.clone(), - second: i.clone(), - } - .spanned(i.span))? - } - - extra.0.insert(i, v.container_to_any()); - } - - val.convert(meta.reborrow(), expected_type, Some(&extra)) - } - _ => val.convert( - meta.reborrow(), - expected_type, - if attributes.is_empty() { - None - } else { - Some(attributes.value) - }, - ), - } - .map_err(|err| { - ConversionError::ErrorInCopy { - copy: copy.to_owned().spanned(val.span()), - error: Box::new(err), - } - .spanned(value.span) - }); - } - let raw_val_type = val_ty; let mut val_ty = val_ty.or(matches!( value.value, @@ -1204,10 +1149,9 @@ where /// /// We do type resolution, validating etc here. /// -/// There are three stages of bauble values: +/// There are two stages of bauble values: /// 1. `ParseVal`, which we get when we parse bauble from types. -/// 2. `CopyVal`, an intermediate value that we convert all copy values to. -/// 3. `Val`, the fully resolved type, which is always correct to convert to rust. +/// 2. `Val`, the fully resolved type, which is always correct to convert to rust. pub(super) trait ConvertValue: ValueContainer { fn get_spanned_field(field: &Self::ContainerField, meta: &ConvertMeta) -> Ident; @@ -1245,10 +1189,6 @@ impl ConvertValueInner for UnspannedVal { Ok(asset.clone()) } - fn ref_ident(path: &Self::Ref) -> Option> { - TypePathElem::try_from(path.borrow()).ok() - } - fn variant_span(_variant: &Self::Variant, meta: &ConvertMeta) -> Span { meta.default_span } @@ -1286,10 +1226,6 @@ impl ConvertValueInner for Val { Ok(asset.clone()) } - fn ref_ident(path: &Self::Ref) -> Option> { - TypePathElem::try_from(path.borrow()).ok() - } - fn variant_span(variant: &Self::Variant, _meta: &ConvertMeta) -> Span { variant.span } @@ -1372,71 +1308,6 @@ impl ConvertValue for Val { } } -impl ConvertValueInner for CopyValInner { - fn get_variant(ident: &Self::Variant, _symbols: &Symbols) -> Result { - Ok(ident.value.clone()) - } - - fn get_asset(asset: &Self::Ref, _symbols: &Symbols) -> Result { - Ok(asset.clone()) - } - - fn ref_ident(path: &Self::Ref) -> Option> { - TypePathElem::try_from(path.borrow()).ok() - } - - fn variant_span(variant: &Self::Variant, _meta: &ConvertMeta) -> Span { - variant.span - } -} - -impl ConvertValue for CopyValInner { - fn get_spanned_field(field: &Self::ContainerField, _meta: &ConvertMeta) -> Ident { - field.clone() - } - - fn convert<'a, C: ConvertValue>( - &self, - meta: ConvertMeta<'a>, - expected_type: TypeId, - extra_attributes: Option<&'a Attributes>, - ) -> Result { - Self::convert_inner( - self.value.as_ref(), - self.attributes.as_ref(), - self.ty, - meta, - expected_type, - extra_attributes, - ) - } -} - -impl ConvertValue for CopyVal { - fn get_spanned_field(field: &Self::ContainerField, _meta: &ConvertMeta) -> Ident { - field.clone() - } - - fn get_span(&self, meta: &ConvertMeta) -> Span { - match self { - CopyVal::Copy(v) => v.get_span(meta), - CopyVal::Resolved(v) => v.get_span(meta), - } - } - - fn convert<'a, C: ConvertValue>( - &self, - meta: ConvertMeta, - expected_type: TypeId, - extra_attributes: Option<&Attributes>, - ) -> Result { - match self { - CopyVal::Copy(val) => val.convert(meta, expected_type, extra_attributes), - CopyVal::Resolved(val) => val.convert(meta, expected_type, extra_attributes), - } - } -} - impl ConvertValueInner for ParseVal { fn get_variant(ident: &Self::Variant, symbols: &Symbols) -> Result { Ok(symbols @@ -1455,11 +1326,6 @@ impl ConvertValueInner for ParseVal { symbols.resolve_asset(asset).map(|(_, p)| p) } - fn ref_ident(path: &Self::Ref) -> Option> { - path.as_ident() - .and_then(|p| TypePathElem::new(p.value).ok()) - } - fn variant_span(variant: &Self::Variant, _meta: &ConvertMeta) -> Span { variant.span() } @@ -1501,7 +1367,6 @@ impl ConvertValue for AnyVal<'_> { fn get_span(&self, meta: &ConvertMeta) -> Span { match self { AnyVal::Parse(v) => v.get_span(meta), - AnyVal::Copy(v) => v.get_span(meta), AnyVal::Complete(v) => v.get_span(meta), AnyVal::Unspanned(v) => v.get_span(meta), } @@ -1515,103 +1380,8 @@ impl ConvertValue for AnyVal<'_> { ) -> Result { match self { AnyVal::Parse(v) => v.convert(meta, expected_type, extra_attributes), - AnyVal::Copy(v) => v.convert(meta, expected_type, extra_attributes), AnyVal::Complete(v) => v.convert(meta, expected_type, extra_attributes), AnyVal::Unspanned(v) => v.convert(meta, expected_type, extra_attributes), } } } - -pub(super) fn convert_copy_value(value: &ParseVal, mut meta: ConvertMeta) -> Result { - let types = meta.symbols.ctx.type_registry(); - let val_type = value_type(value, meta.symbols)?; - - if let Some(val_type) = val_type.as_ref() - && types.key_type(val_type.value).kind.instanciable() - { - let val_type = - default_value_type(meta.symbols, value.value.primitive_type(), Some(*val_type)) - .unwrap_or(val_type.value); - value - .convert(meta, val_type, no_attr()) - .map(CopyVal::Resolved) - } else { - let mut parse_attributes = || { - value - .attributes - .0 - .iter() - .map(|(ident, value)| { - Ok::<_, Spanned>(( - ident.clone(), - convert_copy_value(value, meta.reborrow())?, - )) - }) - .try_collect::>() - }; - - let attributes = parse_attributes()?; - let inner: Value = match &value.value.value { - Value::Primitive(p) => Value::Primitive(p.clone()), - Value::Ref(_) => todo!(), - Value::Tuple(seq) => Value::Tuple( - seq.iter() - .map(|v| convert_copy_value(v, meta.reborrow())) - .collect::>()?, - ), - Value::Array(seq) => Value::Array( - seq.iter() - .map(|v| convert_copy_value(v, meta.reborrow())) - .collect::>()?, - ), - Value::Map(map) => Value::Map( - map.iter() - .map(|(key, value)| { - Ok(( - convert_copy_value(key, meta.reborrow())?, - convert_copy_value(value, meta.reborrow())?, - )) - }) - .collect::>()?, - ), - Value::Struct(fields_kind) => Value::Struct(match fields_kind { - FieldsKind::Unit => FieldsKind::Unit, - FieldsKind::Unnamed(seq) => FieldsKind::Unnamed( - seq.iter() - .map(|v| convert_copy_value(v, meta.reborrow())) - .collect::>()?, - ), - FieldsKind::Named(fields) => FieldsKind::Named( - fields - .iter() - .map(|(field, v)| { - Ok((field.clone(), convert_copy_value(v, meta.reborrow())?)) - }) - .collect::>()?, - ), - }), - Value::Or(paths) => Value::Or( - paths - .iter() - .map(|path| { - let ident = path.last_ident(); - Ok(TypePathElem::new(ident.value) - .map_err(|e| e.spanned(ident.span))? - .to_owned() - .spanned(ident.span)) - }) - .collect::>()?, - ), - Value::Transparent(inner) => { - Value::Transparent(Box::new(convert_copy_value(inner, meta)?)) - } - Value::Enum(_, _) => unimplemented!("We don't get enums from parsing"), - }; - - Ok(CopyVal::Copy(CopyValInner { - ty: val_type, - value: inner.spanned(value.value.span), - attributes: Attributes(attributes).spanned(value.attributes.span), - })) - } -} diff --git a/bauble/src/value/display.rs b/bauble/src/value/display.rs index 6534dc6..edd6ad0 100644 --- a/bauble/src/value/display.rs +++ b/bauble/src/value/display.rs @@ -735,36 +735,6 @@ impl> IndentedDisplay for ParseValues { written = true; } - let mut iter = self.copies.iter(); - - if let Some((ident, binding)) = iter.next() { - if written { - w.write("\n\n"); - } - - w.write("copy "); - w.write(ident); - if let Some(ty) = &binding.type_path { - w.write(": "); - w.fmt(ty); - } - w.write(" = "); - binding.value.indented_display(w.reborrow()); - } - - for (ident, binding) in iter { - w.write("\n\n"); - - w.write("copy "); - w.write(ident); - if let Some(ty) = &binding.type_path { - w.write(": "); - w.fmt(ty); - } - w.write(" = "); - binding.value.indented_display(w.reborrow()); - } - let mut iter = self.values.iter(); if let Some((ident, binding)) = iter.next() { diff --git a/bauble/src/value/error.rs b/bauble/src/value/error.rs index 9fdcfe4..da007bd 100644 --- a/bauble/src/value/error.rs +++ b/bauble/src/value/error.rs @@ -9,11 +9,11 @@ use crate::{ types::{self, TypeId}, }; -use super::{Ident, PathKind, RefCopy}; +use super::{Ident, PathKind}; #[derive(Clone, Debug)] pub struct RefError { - pub(super) uses: Option>, + pub(super) uses: Option>, pub(super) path: PathKind, pub(super) path_ref: PathReference, pub(super) kind: RefKind, @@ -78,10 +78,6 @@ pub enum ConversionError { }, PathError(crate::path::PathError), Cycle(Vec<(Spanned, Vec>)>), - ErrorInCopy { - copy: Spanned, - error: Box>, - }, NotInstantiable { ty: TypeId, }, @@ -152,7 +148,6 @@ impl BaubleError for Spanned { "Expected the type `{}`", types.key_type(*expected).meta.path )), - ConversionError::ErrorInCopy { error, .. } => return error.msg_general(ctx), ConversionError::UnregisteredAsset => Cow::Borrowed("Unregistered asset"), ConversionError::NotInstantiable { ty } => Cow::Owned(format!( "Can't construct a default value of the type {}", @@ -578,16 +573,7 @@ impl BaubleError for Spanned { && let Some(uses) = &ref_err.uses { if let Some(suggestions) = get_suggestions( - uses.iter() - .filter(|(_, p)| match p { - RefCopy::Unresolved => false, - RefCopy::Resolved(_) => false, - RefCopy::Ref(path_reference) => { - path_reference.asset.is_some() - } - }) - .map(|(ident, _)| ident.as_str()) - .chain(options), + uses.keys().map(|ident| ident.as_str()).chain(options), path.as_str(), ) { errs.push(( @@ -640,20 +626,6 @@ impl BaubleError for Spanned { Cow::Owned(s) } - ConversionError::ErrorInCopy { copy, error } => { - let mut v = error.msgs_specific(ctx); - - v.push(( - Spanned::new(copy.span, Cow::Borrowed("In this copy value")), - Level::Info, - )); - v.push(( - Spanned::new(self.span, Cow::Borrowed("In this copy reference")), - Level::Info, - )); - - return v; - } ConversionError::UnregisteredAsset => Cow::Borrowed( "This asset hasn't been registered with `BaubleContext::register_asset`", ), diff --git a/bauble/src/value/mod.rs b/bauble/src/value/mod.rs index 8efcd21..a541be8 100644 --- a/bauble/src/value/mod.rs +++ b/bauble/src/value/mod.rs @@ -1,11 +1,7 @@ -use std::{ - collections::{HashMap, HashSet}, - hash::Hash, -}; +use std::{collections::HashMap, hash::Hash}; use indexmap::IndexMap; use rust_decimal::Decimal; -use symbols::RefCopy; use crate::{ BaubleErrors, FileId, VariantKind, @@ -97,38 +93,12 @@ impl ValueContainer for V { } } -impl ValueContainer for CopyVal { - type ContainerField = Ident; - - fn has_attributes(&self) -> bool { - match self { - CopyVal::Copy(v) => v.has_attributes(), - CopyVal::Resolved(v) => v.has_attributes(), - } - } - - fn container_ty(&self) -> TypeId { - match self { - CopyVal::Copy(v) => v.ty(), - CopyVal::Resolved(v) => v.ty(), - } - } - - fn container_to_any(&self) -> AnyVal { - match self { - CopyVal::Copy(v) => v.to_any(), - CopyVal::Resolved(v) => v.to_any(), - } - } -} - impl ValueContainer for AnyVal<'_> { type ContainerField = Ident; fn has_attributes(&self) -> bool { match self { AnyVal::Parse(v) => v.has_attributes(), - AnyVal::Copy(v) => v.has_attributes(), AnyVal::Complete(v) => v.has_attributes(), AnyVal::Unspanned(v) => v.has_attributes(), } @@ -137,7 +107,6 @@ impl ValueContainer for AnyVal<'_> { fn container_ty(&self) -> TypeId { match self { AnyVal::Parse(v) => v.ty(), - AnyVal::Copy(v) => v.ty(), AnyVal::Complete(v) => v.ty(), AnyVal::Unspanned(v) => v.ty(), } @@ -453,71 +422,6 @@ impl UnspannedVal { } } -#[derive(Clone, Debug)] -pub struct CopyValInner { - ty: Option>, - value: Spanned>, - attributes: Spanned>, -} - -impl ValueTrait for CopyValInner { - type Inner = CopyVal; - - type Ref = TypePath; - - type Variant = Spanned; - - type Field = Ident; - - fn ty(&self) -> TypeId { - *self - .ty - .as_deref() - .unwrap_or(&types::TypeRegistry::any_type()) - } - - fn attributes(&self) -> &Attributes { - &self.attributes - } - - fn value(&self) -> &Value { - &self.value - } - - fn to_any(&self) -> AnyVal { - AnyVal::Copy(self) - } -} - -impl SpannedValue for CopyValInner { - fn type_span(&self) -> crate::Span { - self.ty.map(|s| s.span).unwrap_or(self.value.span) - } - - fn value_span(&self) -> crate::Span { - self.value.span - } - - fn attributes_span(&self) -> crate::Span { - self.attributes.span - } -} - -#[derive(Clone, Debug)] -pub enum CopyVal { - Copy(CopyValInner), - Resolved(Val), -} - -impl CopyVal { - fn span(&self) -> crate::Span { - match self { - CopyVal::Copy(val) => val.span(), - CopyVal::Resolved(val) => val.span(), - } - } -} - pub type Ident = Spanned; #[allow(missing_docs)] @@ -980,80 +884,8 @@ pub(crate) fn convert_values( symbols.add(use_symbols); - for (symbol, _) in &values.copies { - let span = symbol.span; - let symbol = match TypePathElem::new(symbol.as_str()).map_err(|e| e.spanned(span)) { - Ok(s) => s, - Err(e) => { - use_errors.push(e.into()); - continue; - } - }; - symbols.uses.insert(symbol.to_owned(), RefCopy::Unresolved); - } - - let mut spans = HashMap::new(); - let mut contained_spans = - HashMap::, Vec>>>::new(); - let mut copy_graph = petgraph::graphmap::DiGraphMap::new(); - - for (symbol, value) in &values.copies { - let span = symbol.span; - let symbol = match TypePathElem::new(symbol.as_str()).map_err(|e| e.spanned(span)) { - Ok(s) => s, - Err(e) => { - use_errors.push(e.into()); - continue; - } - }; - - spans.insert(symbol, span); - copy_graph.add_node(symbol); - find_copy_refs(&value.value, &symbols, &mut |s| { - copy_graph.add_edge(symbol, s.value, ()); - contained_spans.entry(symbol).or_default().push(s); - }); - } - let mut additional_objects = AdditionalObjects::new(path.to_owned()); - let mut node_removals = Vec::new(); - for scc in petgraph::algo::tarjan_scc(©_graph) { - if scc.len() == 1 - && contained_spans - .get(&scc[0]) - .is_none_or(|i| i.iter().all(|s| s.value != scc[0])) - { - continue; - } - let scc_set = HashSet::>::from_iter(scc.iter().copied()); - use_errors.push( - ConversionError::Cycle( - scc.iter() - .map(|s| { - ( - s.to_string().spanned(spans[s]), - contained_spans - .get(s) - .into_iter() - .flatten() - .filter(|s| scc_set.contains(&s.value)) - .map(|s| (*s).map(|s| s.to_string())) - .collect(), - ) - }) - .collect(), - ) - .spanned(spans[&scc[0]]), - ); - - node_removals.extend(scc); - } - - for removal in node_removals { - copy_graph.remove_node(removal); - } - let default_span = crate::Span::new(file, 0..0); macro_rules! meta { @@ -1067,27 +899,6 @@ pub(crate) fn convert_values( }; } - match petgraph::algo::toposort(©_graph, None) { - Ok(order) => { - let order = order.into_iter().map(|o| o.to_owned()).collect::>(); - for item in order { - let val = match convert::convert_copy_value( - &values.copies[item.as_str()].value, - meta!(item.borrow()), - ) { - Ok(v) => v, - Err(err) => { - use_errors.push(err); - continue; - } - }; - - symbols.uses.insert(item.to_owned(), RefCopy::Resolved(val)); - } - } - Err(_) => unreachable!("We removed all scc before running toposort"), - } - let mut ok = Vec::new(); let mut err = use_errors; @@ -1129,46 +940,6 @@ pub(crate) fn convert_values( } } -fn find_copy_refs<'a>( - val: &ParseVal, - symbols: &'a Symbols, - found: &mut impl FnMut(Spanned>), -) { - for obj in val.attributes.values() { - find_copy_refs(obj, symbols, found) - } - - match &val.value.value { - Value::Ref(reference) => { - if let Some(ident) = reference.as_ident() { - if let Some((ident, _)) = symbols.try_resolve_copy(&ident) { - found(ident.spanned(reference.span())) - } - } - } - Value::Map(map) => { - for (k, v) in map.iter() { - find_copy_refs(k, symbols, found); - find_copy_refs(v, symbols, found); - } - } - Value::Struct(FieldsKind::Named(fields)) => { - for obj in fields.values() { - find_copy_refs(obj, symbols, found) - } - } - Value::Enum(_, inner) | Value::Transparent(inner) => find_copy_refs(inner, symbols, found), - Value::Tuple(fields) - | Value::Array(fields) - | Value::Struct(FieldsKind::Unnamed(fields)) => { - for obj in fields.iter() { - find_copy_refs(obj, symbols, found); - } - } - Value::Or(_) | Value::Primitive(_) | Value::Struct(FieldsKind::Unit) => {} - } -} - /// Converts a parsed value to a object value using a conversion context and existing symbols. Also /// does some rudimentary checking if the symbols are okay. fn convert_object( diff --git a/bauble/src/value/symbols.rs b/bauble/src/value/symbols.rs index a4a97f1..9630b55 100644 --- a/bauble/src/value/symbols.rs +++ b/bauble/src/value/symbols.rs @@ -9,53 +9,17 @@ use crate::{ types::{self, TypeId}, }; -use super::{ConversionError, CopyVal, PathKind, RefError, RefKind, Result}; - -/// This is either a reference to another value or a "copy" value which was copied into here. -#[derive(Clone, Debug)] -pub(super) enum RefCopy { - /// Unresolved copy value. - Unresolved, - /// Resolved copy value. - Resolved(CopyVal), - /// Reference to a type, asset, or module? - Ref(PathReference), -} - -impl Default for RefCopy { - fn default() -> Self { - Self::Ref(Default::default()) - } -} - -impl RefCopy { - /// # Panics - /// Panics if self isn't a reference. - fn unwrap_ref(&self) -> &PathReference { - match self { - RefCopy::Ref(r) => r, - RefCopy::Unresolved | RefCopy::Resolved(_) => panic!("Not a reference"), - } - } - - fn add(self, other: PathReference) -> Option { - match self { - RefCopy::Unresolved | RefCopy::Resolved(_) => None, - RefCopy::Ref(reference) => Some(RefCopy::Ref(reference.combined(other)?)), - } - } -} +use super::{ConversionError, PathKind, RefError, RefKind, Result}; /// Representation of item names available in the current module. /// /// There are multiple namespaces: types, assets (i.e. values defined in bauble), and modules. -/// There are also copy values (TODO: which overlap all namespaces?). #[derive(Clone)] pub(crate) struct Symbols<'a> { + /// Context for looking up things referenced by full path. pub(super) ctx: &'a BaubleContext, - // Map of identifiers to ref-copies (which can be unresolved-copy, resolved-copy, or reference) - // A resolved copy is either `CopyVal::Copy` or `CopyVal::Resolved(Val)` - pub(super) uses: HashMap, + /// Map of identifiers to path references. + pub(super) uses: HashMap, } impl<'a> Symbols<'a> { @@ -75,7 +39,7 @@ impl<'a> Symbols<'a> { *r = r .clone() - .add(reference) + .combined(reference) .ok_or(ConversionError::AmbiguousUse { ident })?; Ok(()) @@ -187,22 +151,10 @@ impl<'a> Symbols<'a> { add_use_inner(self, leading, &use_path.end) } - pub(super) fn try_resolve_copy<'b>( - &'b self, - ident: &str, - ) -> Option<(TypePathElem<&'b str>, Option<&'b CopyVal>)> { - let (key, value) = self.uses.get_key_value(ident)?; - match value { - RefCopy::Unresolved => Some((key.borrow(), None)), - RefCopy::Resolved(val) => Some((key.borrow(), Some(val))), - RefCopy::Ref(_) => None, - } - } - pub fn get_module(&self, ident: &str) -> Option { self.uses .get(ident) - .and_then(|reference| reference.unwrap_ref().module.clone()) + .and_then(|reference| reference.module.clone()) } pub fn resolve_path(&self, raw_path: &Path) -> Result> { @@ -273,7 +225,11 @@ impl<'a> Symbols<'a> { Ok(path.spanned(raw_path.span())) } - pub fn resolve_item(&self, raw_path: &Path, ref_kind: RefKind) -> Result> { + pub fn resolve_item( + &self, + raw_path: &Path, + ref_kind: RefKind, + ) -> Result> { fn resolve_path( symbols: &Symbols, raw_path: &Path, @@ -291,7 +247,7 @@ impl<'a> Symbols<'a> { Ok(if matches!(ref_kind, RefKind::Type) { match path.value { PathKind::Direct(type_path) => { - if let Some(RefCopy::Ref(r)) = symbols.uses.get(type_path.as_str()) + if let Some(r) = symbols.uses.get(type_path.as_str()) && let Some(ty) = r.ty { let path = &symbols.ctx.type_registry().key_type(ty).meta.path; @@ -332,19 +288,21 @@ impl<'a> Symbols<'a> { let path = resolve_path(self, raw_path, ref_kind)?; - match &path.value { + let reference = match &path.value { PathKind::Direct(path) => { - if let Some(RefCopy::Ref(r)) = self.uses.get(path.as_str()) { - return Ok(Cow::Borrowed(r)); + if let Some(r) = self.uses.get(path.as_str()) { + Some(Cow::Borrowed(r)) } else { - self.ctx.get_ref(path.borrow()) + self.ctx.get_ref(path.borrow()).map(Cow::Owned) } } - PathKind::Indirect(path, ident) => { - self.ctx.ref_with_ident(path.borrow(), ident.borrow()) - } - } - .ok_or_else(|| { + PathKind::Indirect(path, ident) => self + .ctx + .ref_with_ident(path.borrow(), ident.borrow()) + .map(Cow::Owned), + }; + + reference.ok_or_else(|| { if let PathKind::Direct(path) = &*path && let Some((leading, ident)) = path.get_end() && let Some(r) = self.ctx.get_ref(leading) @@ -368,7 +326,6 @@ impl<'a> Symbols<'a> { } .spanned(raw_path.span()) }) - .map(Cow::Owned) } pub fn resolve_asset(&self, path: &Path) -> Result<(TypeId, TypePath)> { diff --git a/bauble_macros/tests/derive.rs b/bauble_macros/tests/derive.rs index dc86044..8841743 100644 --- a/bauble_macros/tests/derive.rs +++ b/bauble_macros/tests/derive.rs @@ -116,17 +116,14 @@ fn test_std_types() { bauble_test!( [Test] r#" - copy key = "🔑" - copy value = Some("💖") - test = derive::Test { a: [(2, 0), (1, -1), (5, 10)], b: { - $key: [true, true, false], + "🔑": [true, true, false], "no key": [false, true], }, c: { - [1, 2, 3]: [$value, None, Some("hi")], + [1, 2, 3]: [Some("💖"), None, Some("hi")], }, } "# @@ -145,6 +142,31 @@ fn test_std_types() { ); } +#[test] +fn test_complex_flatten() { + #[derive(Bauble, PartialEq, Debug)] + #[bauble(flatten)] + struct Inner( + u32, + #[bauble(attribute = a, default)] u32, + #[bauble(attribute = b)] u32, + ); + + #[derive(Bauble, PartialEq, Debug)] + #[bauble(flatten)] + struct Transparent(Inner, #[bauble(attribute = a)] u32); + + bauble_test!( + [Transparent] + r#" + a: derive::Transparent = #[a = 1, b = 2] 3 + "# + [ + Transparent(Inner(3, 0, 2), 1), + ] + ); +} + #[test] fn test_from() { #[derive(Bauble, PartialEq, Debug)]