can for normal (no-list) as

This commit is contained in:
Folkert 2022-12-31 15:46:11 +01:00
parent 06cfdd71cc
commit 905341d849
No known key found for this signature in database
GPG Key ID: 1F17F6FFD112B97C
9 changed files with 98 additions and 19 deletions

View File

@ -654,6 +654,7 @@ fn deep_copy_pattern_help<C: CopyEnv>(
match pat {
Identifier(s) => Identifier(*s),
As(subpattern, s) => As(Box::new(subpattern.map(|p| go_help!(p))), *s),
AppliedTag {
whole_var,
ext_var,

View File

@ -431,6 +431,9 @@ fn pattern<'a>(
| AbilityMemberSpecialization {
specializes: sym, ..
} => pp_sym(c, f, *sym),
As(subpattern, symbol) => pattern(c, prec, f, &subpattern.value)
.append(f.text(" as "))
.append(pp_sym(c, f, *symbol)),
AppliedTag {
tag_name,
arguments,

View File

@ -1967,6 +1967,12 @@ fn pattern_to_vars_by_symbol(
vars_by_symbol.insert(*symbol, expr_var);
}
As(subpattern, symbol) => {
vars_by_symbol.insert(*symbol, expr_var);
pattern_to_vars_by_symbol(vars_by_symbol, &subpattern.value, expr_var);
}
AbilityMemberSpecialization {
ident,
specializes: _,

View File

@ -301,6 +301,7 @@ fn sketch_pattern(pattern: &crate::pattern::Pattern) -> SketchedPattern {
use SketchedPattern as SP;
match pattern {
As(subpattern, _) => sketch_pattern(&subpattern.value),
&NumLiteral(_, _, IntValue::I128(n), _) | &IntLiteral(_, _, _, IntValue::I128(n), _) => {
SP::Literal(Literal::Int(n))
}

View File

@ -929,6 +929,14 @@ fn fix_values_captured_in_closure_pattern(
);
}
}
As(subpattern, _) => {
fix_values_captured_in_closure_pattern(
&mut subpattern.value,
no_capture_symbols,
closure_captures,
);
}
Identifier(_)
| NumLiteral(..)
| IntLiteral(..)

View File

@ -22,6 +22,7 @@ use roc_types::types::{LambdaSet, OptAbleVar, PatternCategory, Type};
#[derive(Clone, Debug)]
pub enum Pattern {
Identifier(Symbol),
As(Box<Loc<Pattern>>, Symbol),
AppliedTag {
whole_var: Variable,
ext_var: Variable,
@ -94,6 +95,7 @@ impl Pattern {
use Pattern::*;
match self {
Identifier(_) => None,
As(pattern, _) => pattern.value.opt_var(),
AppliedTag { whole_var, .. } => Some(*whole_var),
UnwrappedOpaque { whole_var, .. } => Some(*whole_var),
@ -129,6 +131,7 @@ impl Pattern {
| MalformedPattern(..)
| AbilityMemberSpecialization { .. } => true,
RecordDestructure { destructs, .. } => destructs.is_empty(),
As(pattern, _identifier) => pattern.value.surely_exhaustive(),
List { patterns, .. } => patterns.surely_exhaustive(),
AppliedTag { .. }
| NumLiteral(..)
@ -151,6 +154,7 @@ impl Pattern {
match self {
Identifier(_) => C::PatternDefault,
As(pattern, _) => pattern.value.category(),
AppliedTag { tag_name, .. } => C::Ctor(tag_name.clone()),
UnwrappedOpaque { opaque, .. } => C::Opaque(*opaque),
@ -832,6 +836,10 @@ impl<'a> BindingsFromPattern<'a> {
} => {
return Some((*symbol, loc_pattern.region));
}
As(pattern, symbol) => {
stack.push(Pattern(pattern));
return Some((*symbol, loc_pattern.region));
}
AppliedTag {
arguments: loc_args,
..

View File

@ -476,6 +476,9 @@ pub fn walk_pattern<V: Visitor>(visitor: &mut V, pattern: &Pattern) {
match pattern {
Identifier(..) => { /* terminal */ }
As(subpattern, _symbol) => {
visitor.visit_pattern(&subpattern.value, subpattern.region, None)
}
AppliedTag { arguments, .. } => arguments
.iter()
.for_each(|(v, lp)| visitor.visit_pattern(&lp.value, lp.region, Some(*v))),

View File

@ -60,16 +60,31 @@ fn headers_from_annotation_help(
match pattern {
Identifier(symbol)
| Shadowed(_, _, symbol)
// TODO(abilities): handle linking the member def to the specialization ident
| AbilityMemberSpecialization {
ident: symbol,
// TODO(abilities): handle linking the member def to the specialization ident
specializes: _,
} => {
let annotation_index = { let typ = types.from_old_type(annotation.value); constraints.push_type(types, typ) };
let annotation_index = {
let typ = types.from_old_type(annotation.value);
constraints.push_type(types, typ)
};
let typ = Loc::at(annotation.region, annotation_index);
headers.insert(*symbol, typ);
true
}
As(subpattern, symbol) => {
let annotation_index = {
let typ = types.from_old_type(annotation.value);
constraints.push_type(types, typ)
};
let typ = Loc::at(annotation.region, annotation_index);
headers.insert(*symbol, typ);
headers_from_annotation_help(types, constraints, &subpattern.value, annotation, headers)
}
Underscore
| MalformedPattern(_, _)
| UnsupportedPattern(_)
@ -93,7 +108,10 @@ fn headers_from_annotation_help(
// `{ x ? 0 } = rec` or `{ x: 5 } -> ...` in all cases
// the type of `x` within the binding itself is the same.
if let Some(field_type) = fields.get(&destruct.label) {
let field_type_index = { let typ = types.from_old_type(&field_type.as_inner().clone()); constraints.push_type(types, typ) };
let field_type_index = {
let typ = types.from_old_type(&field_type.as_inner().clone());
constraints.push_type(types, typ)
};
headers.insert(
destruct.symbol,
Loc::at(annotation.region, field_type_index),
@ -114,7 +132,7 @@ fn headers_from_annotation_help(
// \[..] -> <body>
// which does not introduce any symbols.
false
},
}
AppliedTag {
tag_name,
@ -165,7 +183,10 @@ fn headers_from_annotation_help(
&& type_arguments.len() == pat_type_arguments.len()
&& lambda_set_variables.len() == pat_lambda_set_variables.len() =>
{
let annotation_index = { let typ = types.from_old_type(annotation.value); constraints.push_type(types, typ) };
let annotation_index = {
let typ = types.from_old_type(annotation.value);
constraints.push_type(types, typ)
};
let typ = Loc::at(annotation.region, annotation_index);
headers.insert(*opaque, typ);
@ -183,6 +204,32 @@ fn headers_from_annotation_help(
}
}
fn constrain_pattern_symbol(
types: &mut Types,
constraints: &mut Constraints,
region: Region,
expected: PExpectedTypeIndex,
state: &mut PatternState,
symbol: Symbol,
) {
let expected = &constraints[expected];
let type_index = *expected.get_type_ref();
if could_be_a_tag_union(types, type_index) {
state
.delayed_is_open_constraints
.push(constraints.is_open_type(type_index));
}
state.headers.insert(
symbol,
Loc {
region,
value: type_index,
},
);
}
/// This accepts PatternState (rather than returning it) so that the caller can
/// initialize the Vecs in PatternState using with_capacity
/// based on its knowledge of their lengths.
@ -215,22 +262,21 @@ pub fn constrain_pattern(
}
Identifier(symbol) | Shadowed(_, _, symbol) => {
let expected = &constraints[expected];
let type_index = *expected.get_type_ref();
constrain_pattern_symbol(types, constraints, region, expected, state, *symbol);
}
if could_be_a_tag_union(types, type_index) {
state
.delayed_is_open_constraints
.push(constraints.is_open_type(type_index));
}
As(subpattern, symbol) => {
constrain_pattern_symbol(types, constraints, region, expected, state, *symbol);
state.headers.insert(
*symbol,
Loc {
region,
value: type_index,
},
);
constrain_pattern(
types,
constraints,
env,
&subpattern.value,
subpattern.region,
expected,
state,
)
}
AbilityMemberSpecialization {

View File

@ -2870,6 +2870,8 @@ fn pattern_to_when<'a>(
(*new_symbol, Loc::at_zero(RuntimeError(error)))
}
As(_, _) => todo!("as bindings are not supported yet"),
UnsupportedPattern(region) => {
// create the runtime error here, instead of delegating to When.
// UnsupportedPattern should then never occur in When
@ -9398,6 +9400,7 @@ fn from_can_pattern_help<'a>(
match can_pattern {
Underscore => Ok(Pattern::Underscore),
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
As(_, _) => todo!(),
AbilityMemberSpecialization { ident, .. } => Ok(Pattern::Identifier(*ident)),
IntLiteral(var, _, int_str, int, _bound) => Ok(make_num_literal_pattern(
env,