diff --git a/src/ast.rs b/src/ast.rs index 25353b6..031478e 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -12,7 +12,7 @@ use crate::error::{Error, RichError, Span, WithSpan}; use crate::num::{NonZeroPow2Usize, Pow2Usize}; use crate::parse::MatchPattern; use crate::pattern::Pattern; -use crate::str::{FunctionName, Identifier, ModuleName, WitnessName}; +use crate::str::{AliasName, FunctionName, Identifier, ModuleName, WitnessName}; use crate::types::{ AliasedType, ResolvedType, StructuralType, TypeConstructible, TypeDeconstructible, UIntType, }; @@ -485,7 +485,7 @@ impl<'a> TreeLike for ExprTree<'a> { #[derive(Clone, Debug, Eq, PartialEq, Default)] struct Scope { variables: Vec>, - aliases: HashMap, + aliases: HashMap, parameters: HashMap, witnesses: HashMap, functions: HashMap, @@ -569,7 +569,7 @@ impl Scope { /// There are any undefined aliases. pub fn resolve(&self, ty: &AliasedType) -> Result { let get_alias = - |name: &Identifier| -> Option { self.aliases.get(name).cloned() }; + |name: &AliasName| -> Option { self.aliases.get(name).cloned() }; ty.resolve(get_alias).map_err(Error::UndefinedAlias) } @@ -578,9 +578,9 @@ impl Scope { /// ## Errors /// /// There are any undefined aliases. - pub fn insert_alias(&mut self, alias: Identifier, ty: AliasedType) -> Result<(), Error> { + pub fn insert_alias(&mut self, name: AliasName, ty: AliasedType) -> Result<(), Error> { let resolved_ty = self.resolve(&ty)?; - self.aliases.insert(alias, resolved_ty); + self.aliases.insert(name, resolved_ty); Ok(()) } @@ -1082,7 +1082,7 @@ impl AbstractSyntaxTree for Call { let args_tys = crate::jet::source_type(jet) .iter() .map(AliasedType::resolve_builtin) - .collect::, Identifier>>() + .collect::, AliasName>>() .map_err(Error::UndefinedAlias) .with_span(from)?; check_argument_types(from.args(), &args_tys).with_span(from)?; diff --git a/src/error.rs b/src/error.rs index 9575450..e94635f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,7 +6,7 @@ use simplicity::hashes::{sha256, Hash, HashEngine}; use simplicity::{elements, Cmr}; use crate::parse::{MatchPattern, Rule}; -use crate::str::{FunctionName, Identifier, JetName, ModuleName, WitnessName}; +use crate::str::{AliasName, FunctionName, Identifier, JetName, ModuleName, WitnessName}; use crate::types::{ResolvedType, UIntType}; /// Position of an object inside a file. @@ -323,7 +323,7 @@ pub enum Error { ExpressionNotConstant, IntegerOutOfBounds(UIntType), UndefinedVariable(Identifier), - UndefinedAlias(Identifier), + UndefinedAlias(AliasName), VariableReuseInPattern(Identifier), WitnessReused(WitnessName), WitnessTypeMismatch(WitnessName, ResolvedType, ResolvedType), diff --git a/src/parse.rs b/src/parse.rs index 5fb2cbf..2822367 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -16,7 +16,8 @@ use crate::impl_eq_hash; use crate::num::NonZeroPow2Usize; use crate::pattern::Pattern; use crate::str::{ - Binary, Decimal, FunctionName, Hexadecimal, Identifier, JetName, ModuleName, WitnessName, + AliasName, Binary, Decimal, FunctionName, Hexadecimal, Identifier, JetName, ModuleName, + WitnessName, }; use crate::types::{AliasedType, BuiltinAlias, TypeConstructible, UIntType}; @@ -201,14 +202,14 @@ pub enum CallName { #[derive(Clone, Debug)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct TypeAlias { - name: Identifier, + name: AliasName, ty: AliasedType, span: Span, } impl TypeAlias { /// Access the name of the alias. - pub fn name(&self) -> &Identifier { + pub fn name(&self) -> &AliasName { &self.name } @@ -809,6 +810,7 @@ macro_rules! impl_parse_wrapped_string { impl_parse_wrapped_string!(FunctionName, function_name); impl_parse_wrapped_string!(Identifier, identifier); impl_parse_wrapped_string!(WitnessName, witness_name); +impl_parse_wrapped_string!(AliasName, alias_name); impl_parse_wrapped_string!(ModuleName, module_name); /// Copy of [`FromStr`] that internally uses the PEST parser. @@ -1064,7 +1066,7 @@ impl PestParse for TypeAlias { let span = Span::from(&pair); let mut it = pair.into_inner(); let _type_keyword = it.next().unwrap(); - let name = Identifier::parse(it.next().unwrap().into_inner().next().unwrap())?; + let name = AliasName::parse(it.next().unwrap())?; let ty = AliasedType::parse(it.next().unwrap())?; Ok(Self { name, ty, span }) } @@ -1329,9 +1331,8 @@ impl PestParse for AliasedType { for data in pair.post_order_iter() { match data.node.0.as_rule() { Rule::alias_name => { - let pair = data.node.0.into_inner().next().unwrap(); - let identifier = Identifier::parse(pair)?; - output.push(Item::Type(AliasedType::alias(identifier))); + let name = AliasName::parse(data.node.0)?; + output.push(Item::Type(AliasedType::alias(name))); } Rule::builtin_alias => { let builtin = BuiltinAlias::parse(data.node.0)?; diff --git a/src/str.rs b/src/str.rs index 0fc6ed3..71190b6 100644 --- a/src/str.rs +++ b/src/str.rs @@ -141,6 +141,69 @@ impl<'a> arbitrary::Arbitrary<'a> for JetName { } } +/// The name of a type alias. +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct AliasName(Arc); + +wrapped_string!(AliasName, "name of a type alias"); + +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for AliasName { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + const RESERVED_NAMES: [&str; 37] = [ + "Either", + "Option", + "bool", + "List", + "u128", + "u256", + "u16", + "u32", + "u64", + "u1", + "u2", + "u4", + "u8", + "Ctx8", + "Pubkey", + "Message64", + "Message", + "Signature", + "Scalar", + "Fe", + "Gej", + "Ge", + "Point", + "Height", + "Time", + "Distance", + "Duration", + "Lock", + "Outpoint", + "Confidential1", + "ExplicitAsset", + "Asset1", + "ExplicitAmount", + "Amount1", + "ExplicitNonce", + "Nonce", + "TokenAmount1", + ]; + + let len = u.int_in_range(1..=10)?; + let mut string = String::with_capacity(len); + for _ in 0..len { + let offset = u.int_in_range(0..=25)?; + string.push((b'a' + offset) as char) + } + if RESERVED_NAMES.contains(&string.as_str()) { + string.push('_'); + } + + Ok(Self::from_str_unchecked(string.as_str())) + } +} + /// A string of decimal digits. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct Decimal(Arc); diff --git a/src/types.rs b/src/types.rs index f17887b..b18092d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -7,7 +7,7 @@ use simplicity::types::{CompleteBound, Final}; use crate::array::{BTreeSlice, Partition}; use crate::num::{NonZeroPow2Usize, Pow2Usize}; -use crate::str::Identifier; +use crate::str::AliasName; /// Primitives of the Simfony type system, excluding type aliases. #[derive(Debug, PartialEq, Eq, Hash, Clone)] @@ -494,7 +494,7 @@ pub struct AliasedType(AliasedInner); #[derive(Debug, PartialEq, Eq, Hash, Clone)] enum AliasedInner { /// Type alias. - Alias(Identifier), + Alias(AliasName), /// Builtin type alias. Builtin(BuiltinAlias), /// Type primitive. @@ -533,9 +533,9 @@ pub enum BuiltinAlias { impl AliasedType { /// Access a user-defined alias. - pub const fn as_alias(&self) -> Option<&Identifier> { + pub const fn as_alias(&self) -> Option<&AliasName> { match &self.0 { - AliasedInner::Alias(identifier) => Some(identifier), + AliasedInner::Alias(name) => Some(name), _ => None, } } @@ -549,8 +549,8 @@ impl AliasedType { } /// Create a type alias from the given `identifier`. - pub const fn alias(identifier: Identifier) -> Self { - Self(AliasedInner::Alias(identifier)) + pub const fn alias(name: AliasName) -> Self { + Self(AliasedInner::Alias(name)) } /// Create a builtin type alias. @@ -559,15 +559,15 @@ impl AliasedType { } /// Resolve all aliases in the type based on the given map of `aliases` to types. - pub fn resolve(&self, mut get_alias: F) -> Result + pub fn resolve(&self, mut get_alias: F) -> Result where - F: FnMut(&Identifier) -> Option, + F: FnMut(&AliasName) -> Option, { let mut output = vec![]; for data in self.post_order_iter() { match &data.node.0 { - AliasedInner::Alias(alias) => { - let resolved = get_alias(alias).ok_or(alias.clone())?; + AliasedInner::Alias(name) => { + let resolved = get_alias(name).ok_or(name.clone())?; output.push(resolved); } AliasedInner::Builtin(builtin) => { @@ -608,7 +608,7 @@ impl AliasedType { } /// Resolve all aliases in the type based on the builtin type aliases only. - pub fn resolve_builtin(&self) -> Result { + pub fn resolve_builtin(&self) -> Result { self.resolve(|_| None) } } @@ -741,8 +741,8 @@ impl From for AliasedType { } } -impl From for AliasedType { - fn from(value: Identifier) -> Self { +impl From for AliasedType { + fn from(value: AliasName) -> Self { Self::alias(value) } } @@ -760,14 +760,14 @@ impl crate::ArbitraryRec for AliasedType { match budget.checked_sub(1) { None => match u.int_in_range(0..=3)? { - 0 => Identifier::arbitrary(u).map(Self::alias), + 0 => AliasName::arbitrary(u).map(Self::alias), 1 => BuiltinAlias::arbitrary(u).map(Self::builtin), 2 => Ok(Self::boolean()), 3 => UIntType::arbitrary(u).map(Self::from), _ => unreachable!(), }, Some(new_budget) => match u.int_in_range(0..=8)? { - 0 => Identifier::arbitrary(u).map(Self::alias), + 0 => AliasName::arbitrary(u).map(Self::alias), 1 => BuiltinAlias::arbitrary(u).map(Self::builtin), 2 => Ok(Self::boolean()), 3 => UIntType::arbitrary(u).map(Self::from),