Skip to content

Commit 42020ac

Browse files
committed
add span to str types
It would improve error reporting and could be useful for LSP. Also remove `MatchPattern` from `IncompatibleMatchArms` because it would exceed error size limit.
1 parent 6bd62dc commit 42020ac

3 files changed

Lines changed: 87 additions & 54 deletions

File tree

src/error.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ use itertools::Itertools;
1212
use simplicity::elements;
1313

1414
use crate::lexer::Token;
15-
use crate::parse::MatchPattern;
1615
use crate::str::{AliasName, FunctionName, Identifier, JetName, ModuleName, WitnessName};
1716
use crate::types::{ResolvedType, UIntType};
1817

1918
/// Area that an object spans inside a file.
20-
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
19+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
2120
pub struct Span {
2221
/// Position where the object starts, inclusively.
2322
pub start: usize,
@@ -408,7 +407,7 @@ pub enum Error {
408407
label: Option<String>,
409408
found: Option<String>,
410409
},
411-
IncompatibleMatchArms(MatchPattern, MatchPattern),
410+
IncompatibleMatchArms(String, String),
412411
// TODO: Remove CompileError once SimplicityHL has a type system
413412
// The SimplicityHL compiler should never produce ill-typed Simplicity code
414413
// The compiler can only be this precise if it knows a type system at least as expressive as Simplicity's

src/parse.rs

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -851,8 +851,9 @@ macro_rules! impl_parse_wrapped_string {
851851
I: ValueInput<'tokens, Token = Token<'src>, Span = Span>,
852852
{
853853
select! {
854-
Token::Ident(ident) => Self::from_str_unchecked(ident)
854+
Token::Ident(ident) => ident
855855
}
856+
.map_with(|s, e| Self::from_str_unchecked(s).with_span(e.span()))
856857
.labelled($label)
857858
}
858859
}
@@ -1002,27 +1003,27 @@ impl ChumskyParse for AliasedType {
10021003
I: ValueInput<'tokens, Token = Token<'src>, Span = Span>,
10031004
{
10041005
let atom = select! {
1005-
Token::Ident(ident) => {
1006-
match ident
1007-
{
1008-
"u1" => AliasedType::u1(),
1009-
"u2" => AliasedType::u2(),
1010-
"u4" => AliasedType::u4(),
1011-
"u8" => AliasedType::u8(),
1012-
"u16" => AliasedType::u16(),
1013-
"u32" => AliasedType::u32(),
1014-
"u64" => AliasedType::u64(),
1015-
"u128" => AliasedType::u128(),
1016-
"u256" => AliasedType::u256(),
1017-
"Ctx8" | "Pubkey" | "Message64" | "Message" | "Signature" | "Scalar" | "Fe" | "Gej"
1018-
| "Ge" | "Point" | "Height" | "Time" | "Distance" | "Duration" | "Lock" | "Outpoint"
1019-
| "Confidential1" | "ExplicitAsset" | "Asset1" | "ExplicitAmount" | "Amount1"
1020-
| "ExplicitNonce" | "Nonce" | "TokenAmount1" => AliasedType::builtin(BuiltinAlias::from_str(ident).unwrap()),
1021-
"bool" => AliasedType::boolean(),
1022-
_ => AliasedType::alias(AliasName::from_str_unchecked(ident)),
1023-
}
1024-
},
1025-
};
1006+
Token::Ident(ident) => ident
1007+
}
1008+
.map_with(|ident, e| match ident {
1009+
"u1" => AliasedType::u1(),
1010+
"u2" => AliasedType::u2(),
1011+
"u4" => AliasedType::u4(),
1012+
"u8" => AliasedType::u8(),
1013+
"u16" => AliasedType::u16(),
1014+
"u32" => AliasedType::u32(),
1015+
"u64" => AliasedType::u64(),
1016+
"u128" => AliasedType::u128(),
1017+
"u256" => AliasedType::u256(),
1018+
"Ctx8" | "Pubkey" | "Message64" | "Message" | "Signature" | "Scalar" | "Fe" | "Gej"
1019+
| "Ge" | "Point" | "Height" | "Time" | "Distance" | "Duration" | "Lock"
1020+
| "Outpoint" | "Confidential1" | "ExplicitAsset" | "Asset1" | "ExplicitAmount"
1021+
| "Amount1" | "ExplicitNonce" | "Nonce" | "TokenAmount1" => {
1022+
AliasedType::builtin(BuiltinAlias::from_str(ident).unwrap())
1023+
}
1024+
"bool" => AliasedType::boolean(),
1025+
_ => AliasedType::alias(AliasName::from_str_unchecked(ident).with_span(e.span())),
1026+
});
10261027

10271028
let num = select! {
10281029
Token::DecLiteral(i) => i.clone()
@@ -1437,7 +1438,8 @@ impl ChumskyParse for CallName {
14371438
Token::Macro("dbg!") => CallName::Debug,
14381439
};
14391440

1440-
let jet = select! { Token::Jet(s) => JetName::from_str_unchecked(s) }.map(CallName::Jet);
1441+
let jet = select! { Token::Jet(s) => s }
1442+
.map_with(|s, e| CallName::Jet(JetName::from_str_unchecked(s).with_span(e.span())));
14411443

14421444
let custom_func = FunctionName::parser().map(CallName::Custom);
14431445

@@ -1591,10 +1593,16 @@ impl SingleExpression {
15911593
Token::DecLiteral(s) => SingleExpressionInner::Decimal(s),
15921594
Token::HexLiteral(s) => SingleExpressionInner::Hexadecimal(s),
15931595
Token::BinLiteral(s) => SingleExpressionInner::Binary(s),
1594-
Token::Witness(s) => SingleExpressionInner::Witness(WitnessName::from_str_unchecked(s)),
1595-
Token::Param(s) => SingleExpressionInner::Parameter(WitnessName::from_str_unchecked(s)),
15961596
};
15971597

1598+
let witness = select! { Token::Witness(s) => s}.map_with(|s, e| {
1599+
SingleExpressionInner::Witness(WitnessName::from_str_unchecked(s).with_span(e.span()))
1600+
});
1601+
1602+
let param = select! { Token::Param(s) => s}.map_with(|s, e| {
1603+
SingleExpressionInner::Parameter(WitnessName::from_str_unchecked(s).with_span(e.span()))
1604+
});
1605+
15981606
let call = Call::parser(expr.clone()).map(SingleExpressionInner::Call);
15991607

16001608
let match_expr = Match::parser(expr.clone()).map(SingleExpressionInner::Match);
@@ -1609,7 +1617,7 @@ impl SingleExpression {
16091617

16101618
choice((
16111619
left, right, some, none, boolean, match_expr, expression, list, array, tuple, call,
1612-
literal, variable,
1620+
literal, witness, param, variable,
16131621
))
16141622
.map_with(|inner, e| Self {
16151623
inner,
@@ -1738,7 +1746,7 @@ impl Match {
17381746

17391747
(p1, p2) => {
17401748
emit.emit(
1741-
Error::IncompatibleMatchArms(p1.clone(), p2.clone())
1749+
Error::IncompatibleMatchArms(p1.to_string(), p2.to_string())
17421750
.with_span(e.span()),
17431751
);
17441752
(first, second)

src/str.rs

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
33
use std::sync::Arc;
44

5+
use crate::error::Span;
6+
57
/// Implementations for newtypes that wrap [`Arc<str>`].
68
macro_rules! wrapped_string {
79
($wrapper:ident, $name:expr) => {
@@ -16,7 +18,7 @@ macro_rules! wrapped_string {
1618
#[doc = "## Panics\n\n"]
1719
#[doc = "Panics may occur down the line if the precondition is not satisfied."]
1820
pub fn from_str_unchecked(s: &str) -> Self {
19-
Self(Arc::from(s))
21+
Self(Arc::from(s), Span::new(0, 0))
2022
}
2123

2224
/// Access the inner string.
@@ -26,7 +28,17 @@ macro_rules! wrapped_string {
2628

2729
/// Make a cheap copy of the name.
2830
pub fn shallow_clone(&self) -> Self {
29-
Self(Arc::clone(&self.0))
31+
Self(Arc::clone(&self.0), self.1)
32+
}
33+
34+
/// Add span to the name.
35+
pub fn with_span(self, span: Span) -> Self {
36+
Self(self.0, span)
37+
}
38+
39+
/// Access span of the name.
40+
pub fn span(&self) -> Span {
41+
self.1
3042
}
3143
}
3244

@@ -41,6 +53,20 @@ macro_rules! wrapped_string {
4153
std::fmt::Display::fmt(&self.0, f)
4254
}
4355
}
56+
57+
impl PartialEq for $wrapper {
58+
fn eq(&self, other: &Self) -> bool {
59+
self.0 == other.0
60+
}
61+
}
62+
63+
impl Eq for $wrapper {}
64+
65+
impl std::hash::Hash for $wrapper {
66+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
67+
self.0.hash(state);
68+
}
69+
}
4470
};
4571
}
4672

@@ -68,13 +94,13 @@ macro_rules! impl_arbitrary_lowercase_alpha {
6894
}
6995

7096
/// The name of a function.
71-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
72-
pub struct FunctionName(Arc<str>);
97+
#[derive(Clone, Ord, PartialOrd)]
98+
pub struct FunctionName(Arc<str>, Span);
7399

74100
impl FunctionName {
75101
/// Return the name of the main function.
76102
pub fn main() -> Self {
77-
Self(Arc::from("main"))
103+
Self::from_str_unchecked("main")
78104
}
79105
}
80106

@@ -112,22 +138,22 @@ impl<'a> arbitrary::Arbitrary<'a> for FunctionName {
112138
}
113139

114140
/// The identifier of a variable.
115-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
116-
pub struct Identifier(Arc<str>);
141+
#[derive(Clone, Ord, PartialOrd)]
142+
pub struct Identifier(Arc<str>, Span);
117143

118144
wrapped_string!(Identifier, "variable identifier");
119145
impl_arbitrary_lowercase_alpha!(Identifier);
120146

121147
/// The name of a witness.
122-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
123-
pub struct WitnessName(Arc<str>);
148+
#[derive(Clone, Ord, PartialOrd)]
149+
pub struct WitnessName(Arc<str>, Span);
124150

125151
wrapped_string!(WitnessName, "witness name");
126152
impl_arbitrary_lowercase_alpha!(WitnessName);
127153

128154
/// The name of a jet.
129-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
130-
pub struct JetName(Arc<str>);
155+
#[derive(Clone, Ord, PartialOrd)]
156+
pub struct JetName(Arc<str>, Span);
131157

132158
wrapped_string!(JetName, "jet name");
133159

@@ -137,13 +163,13 @@ impl<'a> arbitrary::Arbitrary<'a> for JetName {
137163
u.choose(&simplicity::jet::Elements::ALL)
138164
.map(simplicity::jet::Elements::to_string)
139165
.map(Arc::from)
140-
.map(Self)
166+
.map(|jet| Self(jet, Span::DUMMY))
141167
}
142168
}
143169

144170
/// The name of a type alias.
145-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
146-
pub struct AliasName(Arc<str>);
171+
#[derive(Clone, Ord, PartialOrd)]
172+
pub struct AliasName(Arc<str>, Span);
147173

148174
wrapped_string!(AliasName, "name of a type alias");
149175

@@ -205,8 +231,8 @@ impl<'a> arbitrary::Arbitrary<'a> for AliasName {
205231
}
206232

207233
/// A string of decimal digits.
208-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
209-
pub struct Decimal(Arc<str>);
234+
#[derive(Clone, Ord, PartialOrd)]
235+
pub struct Decimal(Arc<str>, Span);
210236

211237
wrapped_string!(Decimal, "decimal string");
212238

@@ -224,8 +250,8 @@ impl<'a> arbitrary::Arbitrary<'a> for Decimal {
224250
}
225251

226252
/// A string of binary digits.
227-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
228-
pub struct Binary(Arc<str>);
253+
#[derive(Clone, Ord, PartialOrd)]
254+
pub struct Binary(Arc<str>, Span);
229255

230256
wrapped_string!(Binary, "binary string");
231257

@@ -244,8 +270,8 @@ impl<'a> arbitrary::Arbitrary<'a> for Binary {
244270
}
245271

246272
/// A string of hexadecimal digits.
247-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
248-
pub struct Hexadecimal(Arc<str>);
273+
#[derive(Clone, Ord, PartialOrd)]
274+
pub struct Hexadecimal(Arc<str>, Span);
249275

250276
wrapped_string!(Hexadecimal, "hexadecimal string");
251277

@@ -268,18 +294,18 @@ impl<'a> arbitrary::Arbitrary<'a> for Hexadecimal {
268294
}
269295

270296
/// The name of a module.
271-
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
272-
pub struct ModuleName(Arc<str>);
297+
#[derive(Clone, Ord, PartialOrd)]
298+
pub struct ModuleName(Arc<str>, Span);
273299

274300
impl ModuleName {
275301
/// Return the name of the witness module.
276302
pub fn witness() -> Self {
277-
Self(Arc::from("witness"))
303+
Self::from_str_unchecked("witness")
278304
}
279305

280306
/// Return the name of the parameter module.
281307
pub fn param() -> Self {
282-
Self(Arc::from("param"))
308+
Self::from_str_unchecked("param")
283309
}
284310
}
285311

0 commit comments

Comments
 (0)