Make unit assignment optional for suffixed defs

This commit is contained in:
Luke Boswell 2024-03-23 14:40:28 +11:00
parent 237bd942ed
commit 42fdcb7ff1
No known key found for this signature in database
GPG key ID: F6DB3C9DB47377B0
15 changed files with 208 additions and 7 deletions

View file

@ -872,6 +872,10 @@ impl<'a> PatternAs<'a> {
pub enum Pattern<'a> {
// Identifier
Identifier(&'a str),
QualifiedIdentifier {
module_name: &'a str,
ident: &'a str,
},
Tag(&'a str),
@ -923,10 +927,9 @@ pub enum Pattern<'a> {
// Malformed
Malformed(&'a str),
MalformedIdent(&'a str, crate::ident::BadIdent),
QualifiedIdentifier {
module_name: &'a str,
ident: &'a str,
},
// Statement e.g. `Stdout.line! "Hello"`
Stmt(&'a str),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@ -1126,6 +1129,8 @@ impl<'a> Pattern<'a> {
false
}
}
Stmt(_) => todo!(),
}
}
}
@ -1773,6 +1778,8 @@ impl<'a> Malformed for Pattern<'a> {
Malformed(_) |
MalformedIdent(_, _) |
QualifiedIdentifier { .. } => true,
Stmt(_) => todo!(),
}
}
}

View file

@ -626,6 +626,40 @@ pub fn parse_single_def<'a>(
// a hacky way to get expression-based error messages. TODO fix this
Ok((NoProgress, None, initial))
}
// Check if we have a Statement with Suffixed first,
// re-parse the state as an expression
// and then use a `{}=` pattern for the ValueDef::Body.
Ok((
MadeProgress,
Loc {
region,
value: Pattern::Stmt(_),
..
},
_,
)) => {
let parse_def_expr =
space0_before_e(increment_min_indent(expr_start(options)), EExpr::IndentEnd);
let (_, loc_def_expr, updated_state) =
parse_def_expr.parse(arena, state, min_indent)?;
let loc_pattern = Loc::at(region, Pattern::RecordDestructure(Collection::empty()));
let value_def = ValueDef::Body(arena.alloc(loc_pattern), &*arena.alloc(loc_def_expr));
let region = Region::span_across(&loc_pattern.region, &loc_def_expr.region);
Ok((
MadeProgress,
Some(SingleDef {
type_or_value: Either::Second(value_def),
region,
spaces_before: spaces_before_current,
}),
updated_state,
))
}
Ok((_, loc_pattern, state)) => {
// First let's check whether this is an ability definition.
let opt_tag_and_args: Option<(&str, Region, &[Loc<Pattern>])> = match loc_pattern.value

View file

@ -12,6 +12,7 @@ use crate::string_literal::StrLikeLiteral;
use bumpalo::collections::string::String;
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_error_macros::internal_error;
use roc_region::all::{Loc, Region};
/// Different patterns are supported in different circumstances.
@ -49,6 +50,11 @@ pub fn loc_pattern_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>>
let pattern_state = state.clone();
// Return early with the suffixed statement
if let Pattern::Stmt(_) = pattern.value {
return Ok((MadeProgress, pattern, pattern_state));
}
let (pattern_spaces, state) =
match space0_e(EPattern::AsKeyword).parse(arena, state, min_indent) {
Err(_) => return Ok((MadeProgress, pattern, pattern_state)),
@ -385,6 +391,39 @@ fn loc_ident_pattern_help<'a>(
Ok((MadeProgress, loc_pat, state))
}
}
// Parse a statement that begins with a suffixed identifier, e.g. `Stdout.line! "Hello"`
Ident::Access {
module_name,
parts,
suffixed,
..
} if suffixed => {
if module_name.is_empty() && parts.len() == 1 {
if let Accessor::RecordField(var) = &parts[0] {
return Ok((
MadeProgress,
Loc {
region: loc_ident.region,
value: Pattern::Stmt(var),
},
state,
));
} else {
internal_error!("unexpected suffixed TupleIndex");
}
} else if let Accessor::RecordField(var) = &parts[0] {
return Ok((
MadeProgress,
Loc {
region: loc_ident.region,
value: Pattern::Stmt(arena.alloc(format!("{}.{}", module_name, var))),
},
state,
));
} else {
internal_error!("unexpected suffixed TupleIndex");
}
}
Ident::Access {
module_name, parts, ..
} => {