fix: better constructor pattern parsing
This commit is contained in:
parent
ef9fd15e12
commit
72bf27d467
|
@ -575,6 +575,7 @@ pub enum Pattern<Constructor, Type> {
|
||||||
|
|
||||||
/// The constructor for a custom type. Starts with an uppercase letter.
|
/// The constructor for a custom type. Starts with an uppercase letter.
|
||||||
Constructor {
|
Constructor {
|
||||||
|
is_record: bool,
|
||||||
location: Span,
|
location: Span,
|
||||||
name: String,
|
name: String,
|
||||||
arguments: Vec<CallArg<Self>>,
|
arguments: Vec<CallArg<Self>>,
|
||||||
|
|
|
@ -737,6 +737,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
args: &'a [CallArg<UntypedPattern>],
|
args: &'a [CallArg<UntypedPattern>],
|
||||||
module: &'a Option<String>,
|
module: &'a Option<String>,
|
||||||
with_spread: bool,
|
with_spread: bool,
|
||||||
|
is_record: bool,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
fn is_breakable(expr: &UntypedPattern) -> bool {
|
fn is_breakable(expr: &UntypedPattern) -> bool {
|
||||||
match expr {
|
match expr {
|
||||||
|
@ -754,25 +755,32 @@ impl<'comments> Formatter<'comments> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if args.is_empty() && with_spread {
|
if args.is_empty() && with_spread {
|
||||||
name.append("(..)")
|
if is_record {
|
||||||
|
name.append("{..}")
|
||||||
|
} else {
|
||||||
|
name.append("(..)")
|
||||||
|
}
|
||||||
} else if args.is_empty() {
|
} else if args.is_empty() {
|
||||||
name
|
name
|
||||||
} else if with_spread {
|
} else if with_spread {
|
||||||
name.append(wrap_args_with_spread(
|
let wrapped_args = if is_record {
|
||||||
args.iter().map(|a| self.pattern_call_arg(a)),
|
wrap_fields_with_spread(args.iter().map(|a| self.pattern_call_arg(a)))
|
||||||
))
|
} else {
|
||||||
|
wrap_args_with_spread(args.iter().map(|a| self.pattern_call_arg(a)))
|
||||||
|
};
|
||||||
|
|
||||||
|
name.append(wrapped_args)
|
||||||
} else {
|
} else {
|
||||||
match args {
|
match args {
|
||||||
[arg] if is_breakable(&arg.value) => name
|
[arg] if is_breakable(&arg.value) => name
|
||||||
.append(if arg.label.is_some() { "{" } else { "(" })
|
.append(if is_record { "{" } else { "(" })
|
||||||
.append(self.pattern_call_arg(arg))
|
.append(self.pattern_call_arg(arg))
|
||||||
.append(if arg.label.is_some() { "}" } else { ")" })
|
.append(if is_record { "}" } else { ")" })
|
||||||
.group(),
|
.group(),
|
||||||
|
|
||||||
_ => name
|
_ => name
|
||||||
.append(wrap_args(
|
.append(wrap_args(
|
||||||
args.iter()
|
args.iter().map(|a| (self.pattern_call_arg(a), is_record)),
|
||||||
.map(|a| (self.pattern_call_arg(a), a.label.is_some())),
|
|
||||||
))
|
))
|
||||||
.group(),
|
.group(),
|
||||||
}
|
}
|
||||||
|
@ -1254,8 +1262,9 @@ impl<'comments> Formatter<'comments> {
|
||||||
arguments: args,
|
arguments: args,
|
||||||
module,
|
module,
|
||||||
with_spread,
|
with_spread,
|
||||||
|
is_record,
|
||||||
..
|
..
|
||||||
} => self.pattern_constructor(name, args, module, *with_spread),
|
} => self.pattern_constructor(name, args, module, *with_spread, *is_record),
|
||||||
};
|
};
|
||||||
commented(doc, comments)
|
commented(doc, comments)
|
||||||
}
|
}
|
||||||
|
@ -1396,10 +1405,10 @@ where
|
||||||
|
|
||||||
let args = args.map(|a| a.0);
|
let args = args.map(|a| a.0);
|
||||||
|
|
||||||
let ((open_broken, open_unbroken), close) = if curly {
|
let (open_broken, open_unbroken, close) = if curly {
|
||||||
((" {", " { "), "}")
|
(" {", " { ", "}")
|
||||||
} else {
|
} else {
|
||||||
(("(", "("), ")")
|
("(", "(", ")")
|
||||||
};
|
};
|
||||||
|
|
||||||
break_(open_broken, open_unbroken)
|
break_(open_broken, open_unbroken)
|
||||||
|
@ -1444,6 +1453,25 @@ where
|
||||||
.group()
|
.group()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wrap_fields_with_spread<'a, I>(args: I) -> Document<'a>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = Document<'a>>,
|
||||||
|
{
|
||||||
|
let mut args = args.into_iter().peekable();
|
||||||
|
if args.peek().is_none() {
|
||||||
|
return "()".to_doc();
|
||||||
|
}
|
||||||
|
|
||||||
|
break_(" {", " { ")
|
||||||
|
.append(join(args, break_(",", ", ")))
|
||||||
|
.append(break_(",", ", "))
|
||||||
|
.append("..")
|
||||||
|
.nest(INDENT)
|
||||||
|
.append(break_("", " "))
|
||||||
|
.append("}")
|
||||||
|
.group()
|
||||||
|
}
|
||||||
|
|
||||||
fn list<'a>(elements: Document<'a>, length: usize, tail: Option<Document<'a>>) -> Document<'a> {
|
fn list<'a>(elements: Document<'a>, length: usize, tail: Option<Document<'a>>) -> Document<'a> {
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return match tail {
|
return match tail {
|
||||||
|
|
|
@ -913,7 +913,13 @@ pub fn pub_parser() -> impl Parser<Token, (), Error = ParseError> {
|
||||||
|
|
||||||
pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = ParseError> {
|
pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = ParseError> {
|
||||||
recursive(|r| {
|
recursive(|r| {
|
||||||
let constructor_pattern_arg_parser = choice((
|
let no_label = r.clone().map_with_span(|pattern, span| ast::CallArg {
|
||||||
|
location: span,
|
||||||
|
value: pattern,
|
||||||
|
label: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let record_constructor_pattern_arg_parser = choice((
|
||||||
select! {Token::Name {name} => name}
|
select! {Token::Name {name} => name}
|
||||||
.then_ignore(just(Token::Colon))
|
.then_ignore(just(Token::Colon))
|
||||||
.then(r.clone())
|
.then(r.clone())
|
||||||
|
@ -922,14 +928,19 @@ pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = Parse
|
||||||
label: Some(name),
|
label: Some(name),
|
||||||
value: pattern,
|
value: pattern,
|
||||||
}),
|
}),
|
||||||
r.map_with_span(|pattern, span| ast::CallArg {
|
no_label.clone(),
|
||||||
location: span,
|
))
|
||||||
value: pattern,
|
.separated_by(just(Token::Comma))
|
||||||
label: None,
|
.allow_trailing()
|
||||||
}),
|
.then(
|
||||||
));
|
just(Token::DotDot)
|
||||||
|
.then_ignore(just(Token::Comma).or_not())
|
||||||
|
.ignored()
|
||||||
|
.or_not(),
|
||||||
|
)
|
||||||
|
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace));
|
||||||
|
|
||||||
let constructor_pattern_args_parser = constructor_pattern_arg_parser
|
let tuple_constructor_pattern_arg_parser = no_label
|
||||||
.separated_by(just(Token::Comma))
|
.separated_by(just(Token::Comma))
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
.then(
|
.then(
|
||||||
|
@ -938,13 +949,18 @@ pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = Parse
|
||||||
.ignored()
|
.ignored()
|
||||||
.or_not(),
|
.or_not(),
|
||||||
)
|
)
|
||||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen));
|
||||||
.or_not()
|
|
||||||
.map(|opt_args| {
|
let constructor_pattern_args_parser = choice((
|
||||||
opt_args
|
record_constructor_pattern_arg_parser.map(|a| (a, true)),
|
||||||
.map(|(a, b)| (a, b.is_some()))
|
tuple_constructor_pattern_arg_parser.map(|a| (a, false)),
|
||||||
.unwrap_or_else(|| (vec![], false))
|
))
|
||||||
});
|
.or_not()
|
||||||
|
.map(|opt_args| {
|
||||||
|
opt_args
|
||||||
|
.map(|((a, b), c)| (a, b.is_some(), c))
|
||||||
|
.unwrap_or_else(|| (vec![], false, false))
|
||||||
|
});
|
||||||
|
|
||||||
let constructor_pattern_parser =
|
let constructor_pattern_parser =
|
||||||
select! {Token::UpName { name } => name}.then(constructor_pattern_args_parser);
|
select! {Token::UpName { name } => name}.then(constructor_pattern_args_parser);
|
||||||
|
@ -957,8 +973,9 @@ pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = Parse
|
||||||
.or_not(),
|
.or_not(),
|
||||||
)
|
)
|
||||||
.map_with_span(|(name, opt_pattern), span| {
|
.map_with_span(|(name, opt_pattern), span| {
|
||||||
if let Some((c_name, (arguments, with_spread))) = opt_pattern {
|
if let Some((c_name, (arguments, with_spread, is_record))) = opt_pattern {
|
||||||
ast::UntypedPattern::Constructor {
|
ast::UntypedPattern::Constructor {
|
||||||
|
is_record,
|
||||||
location: span,
|
location: span,
|
||||||
name: c_name,
|
name: c_name,
|
||||||
arguments,
|
arguments,
|
||||||
|
@ -974,17 +991,20 @@ pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = Parse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
constructor_pattern_parser.map_with_span(|(name, (arguments, with_spread)), span| {
|
constructor_pattern_parser.map_with_span(
|
||||||
ast::UntypedPattern::Constructor {
|
|(name, (arguments, with_spread, is_record)), span| {
|
||||||
location: span,
|
ast::UntypedPattern::Constructor {
|
||||||
name,
|
is_record,
|
||||||
arguments,
|
location: span,
|
||||||
module: None,
|
name,
|
||||||
constructor: (),
|
arguments,
|
||||||
with_spread,
|
module: None,
|
||||||
tipo: (),
|
constructor: (),
|
||||||
}
|
with_spread,
|
||||||
}),
|
tipo: (),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
|
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
|
||||||
ast::UntypedPattern::Discard {
|
ast::UntypedPattern::Discard {
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -409,6 +409,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
name,
|
name,
|
||||||
arguments: mut pattern_args,
|
arguments: mut pattern_args,
|
||||||
with_spread,
|
with_spread,
|
||||||
|
is_record,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
// Register the value as seen for detection of unused values
|
// Register the value as seen for detection of unused values
|
||||||
|
@ -525,6 +526,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
constructor,
|
constructor,
|
||||||
with_spread,
|
with_spread,
|
||||||
tipo: instantiated_constructor_type,
|
tipo: instantiated_constructor_type,
|
||||||
|
is_record,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(Error::IncorrectArity {
|
Err(Error::IncorrectArity {
|
||||||
|
@ -552,6 +554,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
constructor,
|
constructor,
|
||||||
with_spread,
|
with_spread,
|
||||||
tipo: instantiated_constructor_type,
|
tipo: instantiated_constructor_type,
|
||||||
|
is_record,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(Error::IncorrectArity {
|
Err(Error::IncorrectArity {
|
||||||
|
|
|
@ -33,9 +33,10 @@ pub fn spend(
|
||||||
rdmr: Redeemer,
|
rdmr: Redeemer,
|
||||||
ctx: spend.ScriptContext,
|
ctx: spend.ScriptContext,
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
when datum.rdmr is {
|
let x = datum.rdmr
|
||||||
sample.Buy(tipo1, fin) -> fin > 0
|
when x is {
|
||||||
sample.Sell(twice, find: fin) -> fin > 0
|
sample.Buy { fin: fin, .. } -> fin > 0
|
||||||
|
sample.Sell { find: fin, .. } -> fin > 0
|
||||||
sample.Hold(some) -> some > 0
|
sample.Hold(some) -> some > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue