mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 05:34:11 +03:00
all is working again
This commit is contained in:
parent
022ed7b24c
commit
c26fd45d54
@ -125,10 +125,11 @@ where
|
||||
E: 'a,
|
||||
{
|
||||
move |_, state: State<'a>| {
|
||||
if state.column > state.indent_col {
|
||||
if state.column > min_indent {
|
||||
Ok((NoProgress, (), state))
|
||||
} else {
|
||||
Err((NoProgress, indent_problem(state.line, state.column), state))
|
||||
//Ok((NoProgress, (), state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -366,6 +366,7 @@ fn parse_loc_term<'a>(
|
||||
in_parens_region_fix(min_indent),
|
||||
loc!(specialize(EExpr::Str, string_literal_help())),
|
||||
loc!(specialize(EExpr::Number, number_literal_help())),
|
||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent))),
|
||||
loc!(record_literal_help(min_indent)),
|
||||
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
||||
loc!(ident_etc_help(min_indent))
|
||||
@ -382,6 +383,7 @@ fn parse_loc_term_better<'a>(
|
||||
in_parens_region_fix(min_indent),
|
||||
loc!(specialize(EExpr::Str, string_literal_help())),
|
||||
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent))),
|
||||
loc!(record_literal_help(min_indent)),
|
||||
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
||||
// loc!(ident_etc_help(min_indent))
|
||||
@ -579,7 +581,7 @@ fn foobar<'a>(
|
||||
let initial = state;
|
||||
let end = state.get_position();
|
||||
|
||||
match dbg!(space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state)) {
|
||||
match space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state) {
|
||||
Err((_, _, state)) => Ok((MadeProgress, expr.value, state)),
|
||||
Ok((_, spaces_before_op, state)) => {
|
||||
let expr_state = ExprState {
|
||||
@ -605,6 +607,43 @@ struct ExprState<'a> {
|
||||
end: Position,
|
||||
}
|
||||
|
||||
// expr_state.expr = if spaces.is_empty() {
|
||||
// expr_state.expr
|
||||
// } else {
|
||||
// arena
|
||||
// .alloc(expr_state.expr.value)
|
||||
// .with_spaces_after(spaces, expr_state.expr.region)
|
||||
// };
|
||||
|
||||
// fn attach_spaces<'a>(&'a Bump, expr: &mut Located<Expr<'a>>, spaces: &'a [CommentOrNewline<'a>] ) {
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
impl<'a> ExprState<'a> {
|
||||
fn consume_spaces(&mut self, arena: &'a Bump) {
|
||||
if !self.spaces_after.is_empty() {
|
||||
if let Some(last) = self.arguments.pop() {
|
||||
let new = last.value.with_spaces_after(self.spaces_after, last.region);
|
||||
|
||||
self.arguments.push(arena.alloc(new));
|
||||
} else {
|
||||
let region = self.expr.region;
|
||||
|
||||
let mut value = Expr::Num("");
|
||||
std::mem::swap(&mut self.expr.value, &mut value);
|
||||
|
||||
self.expr = arena
|
||||
.alloc(value)
|
||||
.with_spaces_after(self.spaces_after, region);
|
||||
};
|
||||
|
||||
self.spaces_after = &[];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_expr_final<'a>(
|
||||
min_indent: u16,
|
||||
expr_state: ExprState<'a>,
|
||||
@ -631,7 +670,7 @@ fn to_call<'a>(
|
||||
arena: &'a Bump,
|
||||
arguments: Vec<'a, &'a Located<Expr<'a>>>,
|
||||
loc_expr1: Located<Expr<'a>>,
|
||||
_spaces_before: &'a [CommentOrNewline<'a>],
|
||||
spaces_before: &'a [CommentOrNewline<'a>],
|
||||
) -> Located<Expr<'a>> {
|
||||
if arguments.is_empty() {
|
||||
loc_expr1
|
||||
@ -712,20 +751,9 @@ fn parse_expr_operator<'a>(
|
||||
arena: &'a Bump,
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||
let (space_progress, mut spaces, state) =
|
||||
let (_, spaces_after_operator, state) =
|
||||
space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state)?;
|
||||
|
||||
// add previous spaces to the expr
|
||||
std::mem::swap(&mut spaces, &mut expr_state.spaces_after);
|
||||
|
||||
expr_state.expr = if spaces.is_empty() {
|
||||
expr_state.expr
|
||||
} else {
|
||||
arena
|
||||
.alloc(expr_state.expr.value)
|
||||
.with_spaces_after(spaces, expr_state.expr.region)
|
||||
};
|
||||
|
||||
// a `-` is unary if it is preceded by a space and not followed by a space
|
||||
|
||||
let op = loc_op.value;
|
||||
@ -761,16 +789,39 @@ fn parse_expr_operator<'a>(
|
||||
|
||||
parse_expr_end2(min_indent, expr_state, arena, state)
|
||||
}
|
||||
BinOp::Assignment => {
|
||||
if !expr_state.operators.is_empty() {
|
||||
// this `:` likely occured inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(
|
||||
arena.alloc([b'=']),
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
);
|
||||
|
||||
Err((MadeProgress, fail, state))
|
||||
} else if !expr_state.arguments.is_empty() {
|
||||
let region = Region::across_all(expr_state.arguments.iter().map(|v| &v.region));
|
||||
|
||||
let fail = EExpr::ElmStyleFunction(
|
||||
region,
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
);
|
||||
|
||||
Err((MadeProgress, fail, state))
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
BinOp::HasType => {
|
||||
debug_assert!(expr_state.operators.is_empty());
|
||||
dbg!(&expr_state.expr, &expr_state.arguments);
|
||||
|
||||
let expr_region = expr_state.expr.region;
|
||||
|
||||
match &expr_state.expr.value {
|
||||
Expr::GlobalTag(name) => {
|
||||
let indented_more = min_indent + 1;
|
||||
|
||||
let region = expr_state.expr.region;
|
||||
|
||||
let (_, ann_type, state) = specialize(
|
||||
EExpr::Type,
|
||||
space0_before_e(
|
||||
@ -820,31 +871,86 @@ fn parse_expr_operator<'a>(
|
||||
state,
|
||||
));
|
||||
}
|
||||
_ => panic!(),
|
||||
_ => {
|
||||
expr_state.consume_spaces(arena);
|
||||
let call = to_call(
|
||||
arena,
|
||||
expr_state.arguments,
|
||||
expr_state.expr,
|
||||
spaces_after_operator,
|
||||
);
|
||||
|
||||
// let aligned_like_a_def = expr_state.expr.region.start_col == state.indent_col;
|
||||
|
||||
match expr_to_pattern_help(arena, &call.value) {
|
||||
Ok(good) => {
|
||||
let indented_more = min_indent + 1;
|
||||
|
||||
let (_, ann_type, state) = specialize(
|
||||
EExpr::Type,
|
||||
space0_before_e(
|
||||
type_annotation::located_help(indented_more),
|
||||
min_indent,
|
||||
Type::TSpace,
|
||||
Type::TIndentStart,
|
||||
),
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
|
||||
let alias_region = Region::span_across(&expr_region, &ann_type.region);
|
||||
|
||||
let alias = Def::Annotation(Located::at(expr_region, good), ann_type);
|
||||
|
||||
let loc_def = &*arena.alloc(Located::at(alias_region, alias));
|
||||
|
||||
let foo = space0_before_e(
|
||||
move |a, s| parse_expr_help(min_indent, a, s),
|
||||
min_indent,
|
||||
EExpr::Space,
|
||||
EExpr::IndentEnd,
|
||||
);
|
||||
|
||||
let (_, loc_ret, state) = foo.parse(arena, state)?;
|
||||
|
||||
return Ok((
|
||||
MadeProgress,
|
||||
Expr::Defs(&*arena.alloc([loc_def]), arena.alloc(loc_ret)),
|
||||
state,
|
||||
));
|
||||
}
|
||||
Err(_) => {
|
||||
// this `:` likely occured inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(
|
||||
arena.alloc([b':']),
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
);
|
||||
|
||||
Err((MadeProgress, fail, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => match loc_possibly_negative_or_negated_term(min_indent).parse(arena, state) {
|
||||
Err((MadeProgress, f, s)) => Err((MadeProgress, f, s)),
|
||||
Ok((_, new_expr, state)) => {
|
||||
Ok((_, mut new_expr, state)) => {
|
||||
let new_end = state.get_position();
|
||||
|
||||
expr_state.initial = state;
|
||||
|
||||
// put the spaces from after the operator in front of the new_expr
|
||||
if !spaces_after_operator.is_empty() {
|
||||
new_expr = arena
|
||||
.alloc(new_expr.value)
|
||||
.with_spaces_before(spaces_after_operator, new_expr.region);
|
||||
}
|
||||
|
||||
match space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state) {
|
||||
Err((_, _, state)) => {
|
||||
let spaces = expr_state.spaces_after;
|
||||
|
||||
let new_expr = if spaces.is_empty() {
|
||||
new_expr
|
||||
} else {
|
||||
arena
|
||||
.alloc(new_expr.value)
|
||||
.with_spaces_before(spaces, new_expr.region)
|
||||
};
|
||||
|
||||
let args = std::mem::replace(&mut expr_state.arguments, Vec::new_in(arena));
|
||||
|
||||
let call = to_call(arena, args, expr_state.expr, spaces);
|
||||
let call = to_call(arena, args, expr_state.expr, &[]);
|
||||
|
||||
expr_state.operators.push((call, loc_op));
|
||||
expr_state.expr = new_expr;
|
||||
@ -853,17 +959,7 @@ fn parse_expr_operator<'a>(
|
||||
|
||||
parse_expr_final(min_indent, expr_state, arena, state)
|
||||
}
|
||||
Ok((_, mut spaces, state)) => {
|
||||
std::mem::swap(&mut spaces, &mut expr_state.spaces_after);
|
||||
|
||||
let new_expr = if spaces.is_empty() {
|
||||
new_expr
|
||||
} else {
|
||||
arena
|
||||
.alloc(new_expr.value)
|
||||
.with_spaces_before(spaces, new_expr.region)
|
||||
};
|
||||
|
||||
Ok((_, spaces, state)) => {
|
||||
let args = std::mem::replace(&mut expr_state.arguments, Vec::new_in(arena));
|
||||
|
||||
let call = to_call(arena, args, expr_state.expr, spaces);
|
||||
@ -871,6 +967,7 @@ fn parse_expr_operator<'a>(
|
||||
expr_state.operators.push((call, loc_op));
|
||||
expr_state.expr = new_expr;
|
||||
expr_state.end = new_end;
|
||||
expr_state.spaces_after = spaces;
|
||||
|
||||
parse_expr_end(min_indent, expr_state, arena, state)
|
||||
}
|
||||
@ -896,42 +993,31 @@ fn parse_expr_end2<'a>(
|
||||
|
||||
match parser.parse(arena, state) {
|
||||
Err((MadeProgress, f, s)) => Err((MadeProgress, f, s)),
|
||||
Ok((_, arg, state)) => {
|
||||
Ok((_, mut arg, state)) => {
|
||||
let new_end = state.get_position();
|
||||
|
||||
// now that we have `function arg1 ... <spaces> argn`, attach the spaces to the `argn`
|
||||
if !expr_state.spaces_after.is_empty() {
|
||||
arg = arena
|
||||
.alloc(arg.value)
|
||||
.with_spaces_before(expr_state.spaces_after, arg.region);
|
||||
|
||||
expr_state.spaces_after = &[];
|
||||
}
|
||||
expr_state.initial = state;
|
||||
|
||||
match space0_e(min_indent, EExpr::Space, EExpr::IndentEnd).parse(arena, state) {
|
||||
Err((_, _, state)) => {
|
||||
let spaces = expr_state.spaces_after;
|
||||
|
||||
let arg = if spaces.is_empty() {
|
||||
arg
|
||||
} else {
|
||||
arena
|
||||
.alloc(arg.value)
|
||||
.with_spaces_before(spaces, arg.region)
|
||||
};
|
||||
|
||||
expr_state.arguments.push(arena.alloc(arg));
|
||||
expr_state.end = new_end;
|
||||
expr_state.spaces_after = &[];
|
||||
|
||||
parse_expr_final(min_indent, expr_state, arena, state)
|
||||
}
|
||||
Ok((_, mut spaces, state)) => {
|
||||
std::mem::swap(&mut spaces, &mut expr_state.spaces_after);
|
||||
|
||||
let arg = if spaces.is_empty() {
|
||||
arg
|
||||
} else {
|
||||
arena
|
||||
.alloc(arg.value)
|
||||
.with_spaces_before(spaces, arg.region)
|
||||
};
|
||||
|
||||
Ok((_, new_spaces, state)) => {
|
||||
expr_state.arguments.push(arena.alloc(arg));
|
||||
expr_state.end = new_end;
|
||||
expr_state.spaces_after = new_spaces;
|
||||
|
||||
parse_expr_end(min_indent, expr_state, arena, state)
|
||||
}
|
||||
@ -943,6 +1029,7 @@ fn parse_expr_end2<'a>(
|
||||
match loc!(operator()).parse(arena, state) {
|
||||
Err((MadeProgress, f, s)) => Err((MadeProgress, f, s)),
|
||||
Ok((_, loc_op, state)) => {
|
||||
expr_state.consume_spaces(arena);
|
||||
expr_state.initial = before_op;
|
||||
parse_expr_operator(min_indent, expr_state, loc_op, arena, state)
|
||||
}
|
||||
@ -988,41 +1075,6 @@ fn parse_expr_end<'a>(
|
||||
state: State<'a>,
|
||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||
return parse_expr_end2(min_indent, expr_state, arena, state);
|
||||
let parser = and!(
|
||||
loc!(operator()),
|
||||
// The spaces *after* the operator can be attached directly to
|
||||
// the expression following the operator.
|
||||
space0_before_e(
|
||||
move |arena, state| parse_expr_help(min_indent, arena, state),
|
||||
min_indent,
|
||||
EExpr::Space,
|
||||
EExpr::IndentEnd,
|
||||
)
|
||||
);
|
||||
|
||||
match parser.parse(arena, state) {
|
||||
Ok((_, (loc_op, loc_expr2), state)) => {
|
||||
let ExprState {
|
||||
expr: loc_expr1,
|
||||
spaces_after: spaces_before,
|
||||
..
|
||||
} = expr_state;
|
||||
|
||||
let loc_expr1 = if spaces_before.is_empty() {
|
||||
loc_expr1
|
||||
} else {
|
||||
// Attach the spaces retroactively to the expression preceding the operator.
|
||||
arena
|
||||
.alloc(loc_expr1.value)
|
||||
.with_spaces_after(spaces_before, loc_expr1.region)
|
||||
};
|
||||
let tuple = arena.alloc((loc_expr1, loc_op, loc_expr2));
|
||||
|
||||
Ok((MadeProgress, Expr::BinOp(tuple), state))
|
||||
}
|
||||
Err((NoProgress, _, _)) => Ok((MadeProgress, expr_state.expr.value, expr_state.initial)),
|
||||
Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_expr_help<'a>(
|
||||
|
@ -254,7 +254,12 @@ fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> {
|
||||
if state.has_reached_end() {
|
||||
Ok((NoProgress, (), state))
|
||||
} else {
|
||||
Err((NoProgress, SyntaxError::ConditionFailed, state))
|
||||
dbg!(state);
|
||||
Err((
|
||||
NoProgress,
|
||||
SyntaxError::NotEndOfFile(state.line, state.column),
|
||||
state,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,6 +191,7 @@ pub enum SyntaxError<'a> {
|
||||
Expr(EExpr<'a>),
|
||||
Header(EHeader<'a>),
|
||||
Space(BadInputError),
|
||||
NotEndOfFile(Row, Col),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -125,6 +125,22 @@ fn to_syntax_report<'a>(
|
||||
|
||||
report(doc)
|
||||
}
|
||||
NotEndOfFile(row, col) => {
|
||||
let surroundings = Region::from_rows_cols(start_row, start_col, *row, *col);
|
||||
let region = Region::from_row_col(*row, *col);
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"I expected to reach the end of the file, but got stuck here:"),
|
||||
alloc.region_with_subregion(surroundings, region),
|
||||
alloc.concat(vec![alloc.reflow("no hints")]),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "NOT END OF FILE".to_string(),
|
||||
}
|
||||
}
|
||||
SyntaxError::Eof(region) => {
|
||||
let doc = alloc.stack(vec![alloc.reflow("End of Field"), alloc.region(*region)]);
|
||||
|
||||
|
@ -65,6 +65,7 @@ mod test_reporting {
|
||||
problems: can_problems,
|
||||
..
|
||||
} = can_expr(arena, expr_src)?;
|
||||
dbg!(&loc_expr);
|
||||
let mut subs = Subs::new(var_store.into());
|
||||
|
||||
for (var, name) in output.introduced_variables.name_by_var {
|
||||
@ -4205,12 +4206,12 @@ mod test_reporting {
|
||||
indoc!(
|
||||
r#"
|
||||
── TOO MANY ARGS ───────────────────────────────────────────────────────────────
|
||||
|
||||
The `add` function expects 2 arguments, but it got 3 instead:
|
||||
|
||||
4│ Num.add 1 2
|
||||
^^^^^^^
|
||||
|
||||
|
||||
This value is not a function, but it was given 3 arguments:
|
||||
|
||||
3│ x == 5
|
||||
^
|
||||
|
||||
Are there any missing commas? Or missing parentheses?
|
||||
"#
|
||||
),
|
||||
@ -5727,22 +5728,24 @@ mod test_reporting {
|
||||
indoc!(
|
||||
r#"
|
||||
main =
|
||||
5 : I64
|
||||
(\x -> x) : I64
|
||||
|
||||
3
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── UNKNOWN OPERATOR ────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
This looks like an operator, but it's not one I recognize!
|
||||
|
||||
|
||||
1│ main =
|
||||
2│ 5 : I64
|
||||
^
|
||||
|
||||
2│ (\x -> x) : I64
|
||||
^
|
||||
|
||||
The has-type operator : can only occur in a definition's type
|
||||
signature, like
|
||||
|
||||
|
||||
increment : I64 -> I64
|
||||
increment = \x -> x + 1
|
||||
"#
|
||||
|
Loading…
Reference in New Issue
Block a user