mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
implement mono / lowering for tuples
This commit is contained in:
parent
65f8bb3d0d
commit
5a6be05ead
42 changed files with 1773 additions and 290 deletions
|
@ -17,7 +17,7 @@ use roc_can::expected::PExpected;
|
|||
use roc_can::expr::Expr::{self, *};
|
||||
use roc_can::expr::{
|
||||
AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef, ExpectLookup, Field,
|
||||
FunctionDef, OpaqueWrapFunctionData, RecordAccessorData, TupleAccessorData, WhenBranch,
|
||||
FunctionDef, OpaqueWrapFunctionData, StructAccessorData, WhenBranch,
|
||||
};
|
||||
use roc_can::pattern::Pattern;
|
||||
use roc_can::traverse::symbols_introduced_from_pattern;
|
||||
|
@ -30,7 +30,7 @@ use roc_region::all::{Loc, Region};
|
|||
use roc_types::subs::{IllegalCycleMark, Variable};
|
||||
use roc_types::types::Type::{self, *};
|
||||
use roc_types::types::{
|
||||
AliasKind, AnnotationSource, Category, OptAbleType, PReason, Reason, RecordField,
|
||||
AliasKind, AnnotationSource, Category, IndexOrField, OptAbleType, PReason, Reason, RecordField,
|
||||
TypeExtension, TypeTag, Types,
|
||||
};
|
||||
|
||||
|
@ -1162,7 +1162,7 @@ pub fn constrain_expr(
|
|||
[constraint, eq, record_con],
|
||||
)
|
||||
}
|
||||
RecordAccessor(RecordAccessorData {
|
||||
RecordAccessor(StructAccessorData {
|
||||
name: closure_name,
|
||||
function_var,
|
||||
field,
|
||||
|
@ -1176,19 +1176,32 @@ pub fn constrain_expr(
|
|||
let field_var = *field_var;
|
||||
let field_type = Variable(field_var);
|
||||
|
||||
let mut field_types = SendMap::default();
|
||||
let label = field.clone();
|
||||
field_types.insert(label, RecordField::Demanded(field_type.clone()));
|
||||
let record_type = Type::Record(
|
||||
field_types,
|
||||
TypeExtension::from_non_annotation_type(ext_type),
|
||||
);
|
||||
let record_type = match field {
|
||||
IndexOrField::Field(field) => {
|
||||
let mut field_types = SendMap::default();
|
||||
let label = field.clone();
|
||||
field_types.insert(label, RecordField::Demanded(field_type.clone()));
|
||||
Type::Record(
|
||||
field_types,
|
||||
TypeExtension::from_non_annotation_type(ext_type),
|
||||
)
|
||||
}
|
||||
IndexOrField::Index(index) => {
|
||||
let mut field_types = VecMap::with_capacity(1);
|
||||
field_types.insert(*index, field_type.clone());
|
||||
Type::Tuple(
|
||||
field_types,
|
||||
TypeExtension::from_non_annotation_type(ext_type),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let record_type_index = {
|
||||
let typ = types.from_old_type(&record_type);
|
||||
constraints.push_type(types, typ)
|
||||
};
|
||||
|
||||
let category = Category::RecordAccessor(field.clone());
|
||||
let category = Category::Accessor(field.clone());
|
||||
|
||||
let record_expected = constraints.push_expected_type(NoExpectation(record_type_index));
|
||||
let record_con =
|
||||
|
@ -1288,88 +1301,6 @@ pub fn constrain_expr(
|
|||
let eq = constraints.equal_types_var(elem_var, expected, category, region);
|
||||
constraints.exists_many([*tuple_var, elem_var, ext_var], [constraint, eq, tuple_con])
|
||||
}
|
||||
TupleAccessor(TupleAccessorData {
|
||||
name: closure_name,
|
||||
function_var,
|
||||
tuple_var,
|
||||
closure_var,
|
||||
ext_var,
|
||||
elem_var,
|
||||
index,
|
||||
}) => {
|
||||
let ext_var = *ext_var;
|
||||
let ext_type = Variable(ext_var);
|
||||
let elem_var = *elem_var;
|
||||
let elem_type = Variable(elem_var);
|
||||
|
||||
let mut elem_types = VecMap::with_capacity(1);
|
||||
elem_types.insert(*index, elem_type.clone());
|
||||
|
||||
let record_type = Type::Tuple(
|
||||
elem_types,
|
||||
TypeExtension::from_non_annotation_type(ext_type),
|
||||
);
|
||||
let record_type_index = {
|
||||
let typ = types.from_old_type(&record_type);
|
||||
constraints.push_type(types, typ)
|
||||
};
|
||||
|
||||
let category = Category::TupleAccessor(*index);
|
||||
|
||||
let record_expected = constraints.push_expected_type(NoExpectation(record_type_index));
|
||||
let record_con =
|
||||
constraints.equal_types_var(*tuple_var, record_expected, category.clone(), region);
|
||||
|
||||
let expected_lambda_set = {
|
||||
let lambda_set_ty = {
|
||||
let typ = types.from_old_type(&Type::ClosureTag {
|
||||
name: *closure_name,
|
||||
captures: vec![],
|
||||
ambient_function: *function_var,
|
||||
});
|
||||
constraints.push_type(types, typ)
|
||||
};
|
||||
constraints.push_expected_type(NoExpectation(lambda_set_ty))
|
||||
};
|
||||
|
||||
let closure_type = Type::Variable(*closure_var);
|
||||
|
||||
let function_type_index = {
|
||||
let typ = types.from_old_type(&Type::Function(
|
||||
vec![record_type],
|
||||
Box::new(closure_type),
|
||||
Box::new(elem_type),
|
||||
));
|
||||
constraints.push_type(types, typ)
|
||||
};
|
||||
|
||||
let cons = [
|
||||
constraints.equal_types_var(
|
||||
*closure_var,
|
||||
expected_lambda_set,
|
||||
category.clone(),
|
||||
region,
|
||||
),
|
||||
constraints.equal_types(function_type_index, expected, category.clone(), region),
|
||||
{
|
||||
let store_fn_var_index = constraints.push_variable(*function_var);
|
||||
let store_fn_var_expected =
|
||||
constraints.push_expected_type(NoExpectation(store_fn_var_index));
|
||||
constraints.equal_types(
|
||||
function_type_index,
|
||||
store_fn_var_expected,
|
||||
category,
|
||||
region,
|
||||
)
|
||||
},
|
||||
record_con,
|
||||
];
|
||||
|
||||
constraints.exists_many(
|
||||
[*tuple_var, *function_var, *closure_var, elem_var, ext_var],
|
||||
cons,
|
||||
)
|
||||
}
|
||||
LetRec(defs, loc_ret, cycle_mark) => {
|
||||
let body_con = constrain_expr(
|
||||
types,
|
||||
|
@ -4001,10 +3932,6 @@ fn is_generalizable_expr(mut expr: &Expr) -> bool {
|
|||
// RecordAccessor functions `.field` are equivalent to closures `\r -> r.field`, no need to weaken them.
|
||||
return true;
|
||||
}
|
||||
TupleAccessor(_) => {
|
||||
// TupleAccessor functions `.0` are equivalent to closures `\r -> r.0`, no need to weaken them.
|
||||
return true;
|
||||
}
|
||||
OpaqueWrapFunction(_) => {
|
||||
// Opaque wrapper functions `@Q` are equivalent to closures `\x -> @Q x`, no need to weaken them.
|
||||
return true;
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::expr::{constrain_expr, Env};
|
|||
use roc_can::constraint::{Constraint, Constraints, PExpectedTypeIndex, TypeOrVar};
|
||||
use roc_can::expected::{Expected, PExpected};
|
||||
use roc_can::pattern::Pattern::{self, *};
|
||||
use roc_can::pattern::{DestructType, ListPatterns, RecordDestruct};
|
||||
use roc_can::pattern::{DestructType, ListPatterns, RecordDestruct, TupleDestruct};
|
||||
use roc_collections::all::{HumanIndex, SendMap};
|
||||
use roc_collections::VecMap;
|
||||
use roc_module::ident::Lowercase;
|
||||
|
@ -125,6 +125,10 @@ fn headers_from_annotation_help(
|
|||
_ => false,
|
||||
},
|
||||
|
||||
TupleDestructure { destructs: _, .. } => {
|
||||
todo!();
|
||||
}
|
||||
|
||||
List { patterns, .. } => {
|
||||
if let Some((_, Some(rest))) = patterns.opt_rest {
|
||||
let annotation_index = {
|
||||
|
@ -465,6 +469,96 @@ pub fn constrain_pattern(
|
|||
));
|
||||
}
|
||||
|
||||
TupleDestructure {
|
||||
whole_var,
|
||||
ext_var,
|
||||
destructs,
|
||||
} => {
|
||||
state.vars.push(*whole_var);
|
||||
state.vars.push(*ext_var);
|
||||
let ext_type = Type::Variable(*ext_var);
|
||||
|
||||
let mut elem_types: VecMap<usize, Type> = VecMap::default();
|
||||
|
||||
for Loc {
|
||||
value:
|
||||
TupleDestruct {
|
||||
destruct_index: index,
|
||||
var,
|
||||
typ,
|
||||
},
|
||||
..
|
||||
} in destructs.iter()
|
||||
{
|
||||
let pat_type = Type::Variable(*var);
|
||||
let pat_type_index = constraints.push_variable(*var);
|
||||
let expected =
|
||||
constraints.push_pat_expected_type(PExpected::NoExpectation(pat_type_index));
|
||||
|
||||
let (guard_var, loc_guard) = typ;
|
||||
let elem_type = {
|
||||
let guard_type = constraints.push_variable(*guard_var);
|
||||
let expected_pat = constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
PReason::PatternGuard,
|
||||
pat_type_index,
|
||||
loc_guard.region,
|
||||
));
|
||||
|
||||
state.constraints.push(constraints.pattern_presence(
|
||||
guard_type,
|
||||
expected_pat,
|
||||
PatternCategory::PatternGuard,
|
||||
region,
|
||||
));
|
||||
state.vars.push(*guard_var);
|
||||
|
||||
constrain_pattern(
|
||||
types,
|
||||
constraints,
|
||||
env,
|
||||
&loc_guard.value,
|
||||
loc_guard.region,
|
||||
expected,
|
||||
state,
|
||||
);
|
||||
|
||||
pat_type
|
||||
};
|
||||
|
||||
elem_types.insert(*index, elem_type);
|
||||
|
||||
state.vars.push(*var);
|
||||
}
|
||||
|
||||
let tuple_type = {
|
||||
let typ = types.from_old_type(&Type::Tuple(
|
||||
elem_types,
|
||||
TypeExtension::from_non_annotation_type(ext_type),
|
||||
));
|
||||
constraints.push_type(types, typ)
|
||||
};
|
||||
|
||||
let whole_var_index = constraints.push_variable(*whole_var);
|
||||
let expected_record =
|
||||
constraints.push_expected_type(Expected::NoExpectation(tuple_type));
|
||||
let whole_con = constraints.equal_types(
|
||||
whole_var_index,
|
||||
expected_record,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
);
|
||||
|
||||
let record_con = constraints.pattern_presence(
|
||||
whole_var_index,
|
||||
expected,
|
||||
PatternCategory::Record,
|
||||
region,
|
||||
);
|
||||
|
||||
state.constraints.push(whole_con);
|
||||
state.constraints.push(record_con);
|
||||
}
|
||||
|
||||
RecordDestructure {
|
||||
whole_var,
|
||||
ext_var,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue