mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Infer interpolated strings
This commit is contained in:
parent
429e7cd26d
commit
eae1f564db
4 changed files with 34 additions and 16 deletions
|
@ -23,7 +23,7 @@ pub enum Expr {
|
||||||
|
|
||||||
// Lookups
|
// Lookups
|
||||||
Var(Symbol),
|
Var(Symbol),
|
||||||
InterpolatedStr(Vec<(String, Expr)>, String),
|
InterpolatedStr(Vec<(String, Located<Expr>)>, String),
|
||||||
|
|
||||||
// Pattern Matching
|
// Pattern Matching
|
||||||
Case(Box<Located<Expr>>, Vec<(Located<Pattern>, Located<Expr>)>),
|
Case(Box<Located<Expr>>, Vec<(Located<Pattern>, Located<Expr>)>),
|
||||||
|
@ -431,7 +431,7 @@ fn canonicalize(
|
||||||
|
|
||||||
expr::Expr::InterpolatedStr(pairs, suffix) => {
|
expr::Expr::InterpolatedStr(pairs, suffix) => {
|
||||||
let mut output = Output::new();
|
let mut output = Output::new();
|
||||||
let can_pairs: Vec<(String, Expr)> = pairs.into_iter().map(|(string, loc_ident)| {
|
let can_pairs: Vec<(String, Located<Expr>)> = pairs.into_iter().map(|(string, loc_ident)| {
|
||||||
// From a language design perspective, we only permit idents in interpolation.
|
// From a language design perspective, we only permit idents in interpolation.
|
||||||
// However, in a canonical Expr we store it as a full Expr, not a Symbol.
|
// However, in a canonical Expr we store it as a full Expr, not a Symbol.
|
||||||
// This is so that we can resolve it to either Var or Unrecognized; if we
|
// This is so that we can resolve it to either Var or Unrecognized; if we
|
||||||
|
@ -440,7 +440,7 @@ fn canonicalize(
|
||||||
match resolve_ident(&env, &scope, loc_ident.value, &mut output.references) {
|
match resolve_ident(&env, &scope, loc_ident.value, &mut output.references) {
|
||||||
Ok(symbol) => Var(symbol),
|
Ok(symbol) => Var(symbol),
|
||||||
Err(ident) => {
|
Err(ident) => {
|
||||||
let loc_ident = Located {region: loc_ident.region, value: ident};
|
let loc_ident = Located {region: loc_ident.region.clone(), value: ident};
|
||||||
|
|
||||||
env.problem(Problem::UnrecognizedConstant(loc_ident.clone()));
|
env.problem(Problem::UnrecognizedConstant(loc_ident.clone()));
|
||||||
|
|
||||||
|
@ -448,7 +448,7 @@ fn canonicalize(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(string, can_expr)
|
(string, Located { region: loc_ident.region, value: can_expr })
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
(InterpolatedStr(can_pairs, suffix), output)
|
(InterpolatedStr(can_pairs, suffix), output)
|
||||||
|
|
|
@ -32,7 +32,20 @@ pub fn constrain(
|
||||||
Approx(_) => { fractional(subs, expected, region) },
|
Approx(_) => { fractional(subs, expected, region) },
|
||||||
Str(_) => { Eq(string(), expected, region) },
|
Str(_) => { Eq(string(), expected, region) },
|
||||||
EmptyStr => { Eq(string(), expected, region) },
|
EmptyStr => { Eq(string(), expected, region) },
|
||||||
InterpolatedStr(_, _) => { Eq(string(), expected, region) },
|
InterpolatedStr(pairs, _) => {
|
||||||
|
let mut constraints = Vec::with_capacity(pairs.len() + 1);
|
||||||
|
|
||||||
|
for (_, loc_interpolated_expr) in pairs {
|
||||||
|
let expected_str = ForReason(Reason::InterpolatedStringVar, string(), loc_interpolated_expr.region.clone());
|
||||||
|
let constraint = constrain(bound_vars, subs, loc_interpolated_expr, expected_str);
|
||||||
|
|
||||||
|
constraints.push(constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints.push(Eq(string(), expected, region));
|
||||||
|
|
||||||
|
And(constraints)
|
||||||
|
},
|
||||||
EmptyRecord => { Eq(EmptyRec, expected, region) },
|
EmptyRecord => { Eq(EmptyRec, expected, region) },
|
||||||
EmptyList => { Eq(empty_list(subs.mk_flex_var()), expected, region) },
|
EmptyList => { Eq(empty_list(subs.mk_flex_var()), expected, region) },
|
||||||
List(elems) => { list(elems, bound_vars, subs, expected, region) },
|
List(elems) => { list(elems, bound_vars, subs, expected, region) },
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub enum Reason {
|
||||||
OperatorLeftArg(Operator),
|
OperatorLeftArg(Operator),
|
||||||
OperatorRightArg(Operator),
|
OperatorRightArg(Operator),
|
||||||
FractionalLiteral,
|
FractionalLiteral,
|
||||||
|
InterpolatedStringVar,
|
||||||
ElemInList,
|
ElemInList,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,21 @@ mod test_infer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// INTERPOLATED STRING
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_interpolated_string() {
|
||||||
|
infer_eq(
|
||||||
|
indoc!(r#"
|
||||||
|
whatItIs = "great"
|
||||||
|
|
||||||
|
"type inference is \(whatItIs)!"
|
||||||
|
"#),
|
||||||
|
"String.String"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// LIST MISMATCH
|
// LIST MISMATCH
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -343,17 +358,6 @@ mod test_infer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn infer_interpolated_string() {
|
|
||||||
// infer_eq(
|
|
||||||
// indoc!(r#"
|
|
||||||
// whatItIs = "great"
|
|
||||||
|
|
||||||
// "type inference is \(whatItIs)!"
|
|
||||||
// "#),
|
|
||||||
// "String.String"
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn int_thunk() {
|
// fn int_thunk() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue