Skip to content

Commit

Permalink
feat(parser): Allow partial parsing when patterns are missing
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwes committed Jun 19, 2017
1 parent 9e666fe commit e328542
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 7 deletions.
4 changes: 4 additions & 0 deletions base/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub enum Pattern<Id> {
elems: Vec<SpannedPattern<Id>>,
},
Ident(TypedIdent<Id>),
Error,
}

#[derive(Clone, PartialEq, Debug)]
Expand Down Expand Up @@ -294,6 +295,7 @@ pub fn walk_mut_pattern<V: ?Sized + MutVisitor>(v: &mut V, p: &mut Pattern<V::Id
}
}
Pattern::Ident(ref mut id) => v.visit_typ(&mut id.typ),
Pattern::Error => (),
}
}

Expand Down Expand Up @@ -407,6 +409,7 @@ pub fn walk_pattern<V: ?Sized + Visitor>(v: &mut V, p: &Pattern<V::Ident>) {
}
}
Pattern::Ident(ref id) => v.visit_typ(&id.typ),
Pattern::Error => (),
}
}

Expand Down Expand Up @@ -491,6 +494,7 @@ impl Typed for Pattern<Symbol> {
Pattern::Record { ref typ, .. } => typ.clone(),
Pattern::Tuple { ref typ, .. } => typ.clone(),
Pattern::Constructor(ref id, ref args) => get_return_type(env, &id.typ, args.len()),
Pattern::Error => Type::hole(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions check/src/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ impl<E: TypeEnv> OnFound for Suggest<E> {
self.on_pattern(arg);
}
}
Pattern::Error => ()
}
}

Expand Down
2 changes: 1 addition & 1 deletion check/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn metadata(
self.stack_var(id.name.clone(), metadata);
}
Pattern::Tuple { .. } |
Pattern::Constructor(..) => (),
Pattern::Constructor(..) | Pattern::Error => (),
}
}

Expand Down
1 change: 1 addition & 0 deletions check/src/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ pub fn rename(
self.new_pattern(arg_type, arg);
}
}
ast::Pattern::Error => ()
}
}

Expand Down
12 changes: 7 additions & 5 deletions check/src/typecheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ pub enum TypeError<I> {
UndefinedRecord { fields: Vec<I> },
/// Found a case expression without any alternatives
EmptyCase,
/// An `Error` expression was found indicating an invalid parse
ErrorExpression,
/// An `Error` ast node was found indicating an invalid parse
ErrorAst(&'static str),
}

impl<I> From<KindCheckError<I>> for TypeError<I>
Expand Down Expand Up @@ -134,7 +134,7 @@ impl<I: fmt::Display + AsRef<str>> fmt::Display for TypeError<I> {
Ok(())
}
EmptyCase => write!(f, "`case` expression with no alternatives"),
ErrorExpression => write!(f, "`Error` expression found during typechecking"),
ErrorAst(typ) => write!(f, "`Error` {} found during typechecking", typ),
}
}
}
Expand Down Expand Up @@ -428,7 +428,7 @@ impl<'a> Typecheck<'a> {
DuplicateField(_) |
UndefinedRecord { .. } |
EmptyCase |
ErrorExpression |
ErrorAst(_) |
Rename(_) |
KindError(_) => (),
NotAFunction(ref mut typ) |
Expand Down Expand Up @@ -855,7 +855,7 @@ impl<'a> Typecheck<'a> {
}
Ok(TailCall::Type(self.typecheck(last)))
}
Expr::Error => Err(TypeError::ErrorExpression),
Expr::Error => Err(TypeError::ErrorAst("expression")),
}
}

Expand Down Expand Up @@ -1039,6 +1039,7 @@ impl<'a> Typecheck<'a> {
id.typ = match_type.clone();
match_type
}
Pattern::Error => self.error(span, TypeError::ErrorAst("pattern")),
}
}

Expand Down Expand Up @@ -1284,6 +1285,7 @@ impl<'a> Typecheck<'a> {
self.finish_pattern(level, arg, &arg_type);
}
}
Pattern::Error => (),
}
}

Expand Down
21 changes: 21 additions & 0 deletions check/tests/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,27 @@ test test1
assert_eq!(result, expected);
}

#[test]
fn suggest_alternative() {
let _ = env_logger::init();

let text = r#"
type Test = | A Int | B Int String
match A 3 with
|
"#;
let result = suggest(text, BytePos::from(30));
let expected = Ok(vec!["abb".into(), "abc".into()]);

assert_eq!(result, expected);

let result = suggest(text, BytePos::from(40));
let expected = Ok(vec!["abb".into(), "abc".into()]);

assert_eq!(result, expected);
}


#[test]
fn metadata_at_variable() {
let _ = env_logger::init();
Expand Down
5 changes: 5 additions & 0 deletions parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ AtomicPattern: Pattern<Id> = {
fields: values,
}
},

<!> => {
errors.push(<>.error);
Pattern::Error
},
};

Pattern = {
Expand Down
21 changes: 21 additions & 0 deletions parser/tests/error_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,24 @@ let x = 1
);
assert!(result.is_err());
}

#[test]
fn missing_pattern() {
let _ = ::env_logger::init();

let expr = r#"
match 1 with
| -> x
"#;
let result = parse(expr);
assert!(result.is_err());
let (expr, err) = result.unwrap_err();
assert_eq!(expr,
Some(case(int(1),
vec![(Pattern::Error, id("x"))])));

let error = Error::UnexpectedToken("RArrow".into(), vec![]);
let span = pos::span(BytePos::from(24), BytePos::from(26));
assert_eq!(remove_expected(err),
ParseErrors::from(vec![pos::spanned(span, error)]));
}
5 changes: 4 additions & 1 deletion vm/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,8 @@ impl<'a, 'e> PatternTranslator<'a, 'e> {
}
ast::Pattern::Tuple { .. } |
ast::Pattern::Record { .. } |
ast::Pattern::Ident(_) => unreachable!(),
ast::Pattern::Ident(_) |
ast::Pattern::Error => unreachable!(),
}
}
let complete = groups.len() ==
Expand Down Expand Up @@ -1036,6 +1037,7 @@ impl<'a, 'e> PatternTranslator<'a, 'e> {
ast::Pattern::Record { .. } |
ast::Pattern::Tuple { .. } => CType::Record,
ast::Pattern::Constructor(_, _) => CType::Constructor,
ast::Pattern::Error => panic!("ICE: Error pattern survived typechecking")
}
}

Expand Down Expand Up @@ -1142,6 +1144,7 @@ impl<'a, 'e> PatternTranslator<'a, 'e> {
}
}
}
ast::Pattern::Error => ()
}
}
if record_fields.is_empty() {
Expand Down

0 comments on commit e328542

Please sign in to comment.