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
|
||||
Var(Symbol),
|
||||
InterpolatedStr(Vec<(String, Expr)>, String),
|
||||
InterpolatedStr(Vec<(String, Located<Expr>)>, String),
|
||||
|
||||
// Pattern Matching
|
||||
Case(Box<Located<Expr>>, Vec<(Located<Pattern>, Located<Expr>)>),
|
||||
|
@ -431,7 +431,7 @@ fn canonicalize(
|
|||
|
||||
expr::Expr::InterpolatedStr(pairs, suffix) => {
|
||||
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.
|
||||
// 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
|
||||
|
@ -440,7 +440,7 @@ fn canonicalize(
|
|||
match resolve_ident(&env, &scope, loc_ident.value, &mut output.references) {
|
||||
Ok(symbol) => Var(symbol),
|
||||
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()));
|
||||
|
||||
|
@ -448,7 +448,7 @@ fn canonicalize(
|
|||
}
|
||||
};
|
||||
|
||||
(string, can_expr)
|
||||
(string, Located { region: loc_ident.region, value: can_expr })
|
||||
}).collect();
|
||||
|
||||
(InterpolatedStr(can_pairs, suffix), output)
|
||||
|
|
|
@ -32,7 +32,20 @@ pub fn constrain(
|
|||
Approx(_) => { fractional(subs, expected, region) },
|
||||
Str(_) => { 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) },
|
||||
EmptyList => { Eq(empty_list(subs.mk_flex_var()), expected, region) },
|
||||
List(elems) => { list(elems, bound_vars, subs, expected, region) },
|
||||
|
|
|
@ -39,6 +39,7 @@ pub enum Reason {
|
|||
OperatorLeftArg(Operator),
|
||||
OperatorRightArg(Operator),
|
||||
FractionalLiteral,
|
||||
InterpolatedStringVar,
|
||||
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
|
||||
|
||||
#[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]
|
||||
// fn int_thunk() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue