cover all parsed patterns with an error message

but, some invalid patterns are not parsed as expected. See https://github.com/rtfeldman/roc/issues/399
This commit is contained in:
Folkert 2020-07-04 20:18:03 +02:00
parent 0c7a4179aa
commit b7d689226c
4 changed files with 53 additions and 24 deletions

View file

@ -175,14 +175,12 @@ pub fn canonicalize_pattern<'a>(
} }
Ok(float) => Pattern::FloatLiteral(float), Ok(float) => Pattern::FloatLiteral(float),
}, },
ptype @ DefExpr | ptype @ TopLevelDef | ptype @ FunctionArg => { ptype => unsupported_pattern(env, ptype, region),
unsupported_pattern(env, ptype, region)
}
}, },
Underscore => match pattern_type { Underscore => match pattern_type {
WhenBranch | FunctionArg => Pattern::Underscore, WhenBranch | FunctionArg => Pattern::Underscore,
ptype @ DefExpr | ptype @ TopLevelDef => unsupported_pattern(env, ptype, region), ptype => unsupported_pattern(env, ptype, region),
}, },
NumLiteral(string) => match pattern_type { NumLiteral(string) => match pattern_type {
@ -193,9 +191,7 @@ pub fn canonicalize_pattern<'a>(
} }
Ok(int) => Pattern::NumLiteral(var_store.fresh(), int), Ok(int) => Pattern::NumLiteral(var_store.fresh(), int),
}, },
ptype @ DefExpr | ptype @ TopLevelDef | ptype @ FunctionArg => { ptype => unsupported_pattern(env, ptype, region),
unsupported_pattern(env, ptype, region)
}
}, },
NonBase10Literal { NonBase10Literal {
@ -216,19 +212,20 @@ pub fn canonicalize_pattern<'a>(
} }
} }
}, },
ptype @ DefExpr | ptype @ TopLevelDef | ptype @ FunctionArg => { ptype => unsupported_pattern(env, ptype, region),
unsupported_pattern(env, ptype, region)
}
}, },
StrLiteral(_string) => match pattern_type { StrLiteral(string) => match pattern_type {
WhenBranch => { WhenBranch => {
// TODO report whether string was malformed // TODO report whether string was malformed
Pattern::StrLiteral((*string).into()) Pattern::StrLiteral((*string).into())
} }
ptype @ DefExpr | ptype @ TopLevelDef | ptype @ FunctionArg => { ptype => unsupported_pattern(env, ptype, region),
unsupported_pattern(env, ptype, region) },
}
BlockStrLiteral(_lines) => match pattern_type {
WhenBranch => todo!("TODO block string literal pattern"),
ptype => unsupported_pattern(env, ptype, region),
}, },
SpaceBefore(sub_pattern, _) | SpaceAfter(sub_pattern, _) | Nested(sub_pattern) => { SpaceBefore(sub_pattern, _) | SpaceAfter(sub_pattern, _) | Nested(sub_pattern) => {
@ -296,7 +293,7 @@ pub fn canonicalize_pattern<'a>(
}, },
}); });
} }
_ => panic!("invalid pattern in record"), _ => unreachable!("Any other pattern should have given a parse error"),
} }
} }
@ -312,7 +309,15 @@ pub fn canonicalize_pattern<'a>(
unreachable!("should have been handled in RecordDestructure"); unreachable!("should have been handled in RecordDestructure");
} }
_ => panic!("TODO finish restoring can_pattern branch for {:?}", pattern), Malformed(_str) => {
let problem = MalformedPatternProblem::Unknown;
malformed_pattern(env, problem, region)
}
QualifiedIdentifier { .. } => {
let problem = MalformedPatternProblem::QualifiedIdentifier;
malformed_pattern(env, problem, region)
}
}; };
Located { Located {

View file

@ -92,7 +92,6 @@ pub enum RuntimeError {
InvalidHex(std::num::ParseIntError, Box<str>), InvalidHex(std::num::ParseIntError, Box<str>),
InvalidOctal(std::num::ParseIntError, Box<str>), InvalidOctal(std::num::ParseIntError, Box<str>),
InvalidBinary(std::num::ParseIntError, Box<str>), InvalidBinary(std::num::ParseIntError, Box<str>),
QualifiedPatternIdent(InlinableString),
CircularDef(Vec<Symbol>, Vec<(Region /* pattern */, Region /* expr */)>), CircularDef(Vec<Symbol>, Vec<(Region /* pattern */, Region /* expr */)>),
/// When the author specifies a type annotation but no implementation /// When the author specifies a type annotation but no implementation
@ -104,4 +103,6 @@ pub enum MalformedPatternProblem {
MalformedInt, MalformedInt,
MalformedFloat, MalformedFloat,
MalformedBase(Base), MalformedBase(Base),
Unknown,
QualifiedIdentifier,
} }

View file

@ -343,20 +343,33 @@ fn pretty_runtime_error<'b>(
use roc_problem::can::MalformedPatternProblem::*; use roc_problem::can::MalformedPatternProblem::*;
let name = match problem { let name = match problem {
MalformedInt => "integer", MalformedInt => " integer ",
MalformedFloat => "float", MalformedFloat => " float ",
MalformedBase(Base::Hex) => "hex integer", MalformedBase(Base::Hex) => " hex integer ",
MalformedBase(Base::Binary) => "binary integer", MalformedBase(Base::Binary) => " binary integer ",
MalformedBase(Base::Octal) => "octal integer", MalformedBase(Base::Octal) => " octal integer ",
Unknown => " ",
QualifiedIdentifier => " qualified ",
};
let hint = match problem {
MalformedInt | MalformedFloat | MalformedBase(_) => alloc
.hint()
.append(alloc.reflow("Learn more about number literals at TODO")),
Unknown => alloc.nil(),
QualifiedIdentifier => alloc.hint().append(
alloc.reflow("In patterns, only private and global tags can be qualified"),
),
}; };
alloc.stack(vec![ alloc.stack(vec![
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow("This "), alloc.reflow("This"),
alloc.text(name), alloc.text(name),
alloc.reflow(" pattern is malformed:"), alloc.reflow("pattern is malformed:"),
]), ]),
alloc.region(region), alloc.region(region),
hint,
]) ])
} }

View file

@ -1486,6 +1486,8 @@ mod test_reporting {
2 100A -> 3 2 100A -> 3
^^^^ ^^^^
Hint: Learn more about number literals at TODO
"# "#
), ),
) )
@ -1509,6 +1511,8 @@ mod test_reporting {
2 2.X -> 3 2 2.X -> 3
^^^ ^^^
Hint: Learn more about number literals at TODO
"# "#
), ),
) )
@ -1532,6 +1536,8 @@ mod test_reporting {
2 0xZ -> 3 2 0xZ -> 3
^^^ ^^^
Hint: Learn more about number literals at TODO
"# "#
), ),
) )
@ -1555,6 +1561,8 @@ mod test_reporting {
2 0o9 -> 3 2 0o9 -> 3
^^^ ^^^
Hint: Learn more about number literals at TODO
"# "#
), ),
) )
@ -1578,6 +1586,8 @@ mod test_reporting {
2 0b4 -> 3 2 0b4 -> 3
^^^ ^^^
Hint: Learn more about number literals at TODO
"# "#
), ),
) )