mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
cleanup
This commit is contained in:
parent
ecc689e84b
commit
5adeedba9d
2 changed files with 172 additions and 176 deletions
|
@ -494,6 +494,62 @@ impl<'a> ExprState<'a> {
|
||||||
self.spaces_after = &[];
|
self.spaces_after = &[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_assignment_or_backpassing<F>(
|
||||||
|
mut self,
|
||||||
|
arena: &'a Bump,
|
||||||
|
loc_op: Located<BinOp>,
|
||||||
|
argument_error: F,
|
||||||
|
) -> Result<Located<Expr<'a>>, EExpr<'a>>
|
||||||
|
where
|
||||||
|
F: Fn(Region, Row, Col) -> EExpr<'a>,
|
||||||
|
{
|
||||||
|
if !self.operators.is_empty() {
|
||||||
|
// this `=` or `:` likely occured inline; treat it as an invalid operator
|
||||||
|
let opchar = match loc_op.value {
|
||||||
|
BinOp::Assignment => arena.alloc([b'=']) as &[_],
|
||||||
|
BinOp::Backpassing => arena.alloc([b'<', b'-']) as &[_],
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let fail =
|
||||||
|
EExpr::BadOperator(opchar, loc_op.region.start_line, loc_op.region.start_col);
|
||||||
|
|
||||||
|
Err(fail)
|
||||||
|
} else if !self.arguments.is_empty() {
|
||||||
|
let region = Region::across_all(self.arguments.iter().map(|v| &v.region));
|
||||||
|
|
||||||
|
Err(argument_error(
|
||||||
|
region,
|
||||||
|
loc_op.region.start_line,
|
||||||
|
loc_op.region.start_col,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
self.consume_spaces(arena);
|
||||||
|
Ok(to_call(arena, self.arguments, self.expr, &[]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_has_type(
|
||||||
|
mut self,
|
||||||
|
arena: &'a Bump,
|
||||||
|
loc_op: Located<BinOp>,
|
||||||
|
) -> Result<(Located<Expr<'a>>, Vec<'a, &'a Located<Expr<'a>>>), EExpr<'a>> {
|
||||||
|
debug_assert_eq!(loc_op.value, BinOp::HasType);
|
||||||
|
|
||||||
|
if !self.operators.is_empty() || !self.arguments.is_empty() {
|
||||||
|
// this `:`; treat it as an invalid operator
|
||||||
|
let opchar = arena.alloc([b':']) as &[_];
|
||||||
|
|
||||||
|
let fail =
|
||||||
|
EExpr::BadOperator(opchar, loc_op.region.start_line, loc_op.region.start_col);
|
||||||
|
|
||||||
|
Err(fail)
|
||||||
|
} else {
|
||||||
|
self.consume_spaces(arena);
|
||||||
|
Ok((self.expr, self.arguments))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
@ -883,7 +939,7 @@ fn parse_defs_end<'a>(
|
||||||
parse_defs_end(start, def_state, arena, state)
|
parse_defs_end(start, def_state, arena, state)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// this is no def, because there is no `=`, `:` or `<-`; parse as an expr
|
// this is no def, because there is no `=` or `:`; parse as an expr
|
||||||
let state = initial;
|
let state = initial;
|
||||||
let parse_final_expr = space0_before_e(
|
let parse_final_expr = space0_before_e(
|
||||||
move |a, s| parse_expr_help(min_indent, a, s),
|
move |a, s| parse_expr_help(min_indent, a, s),
|
||||||
|
@ -952,175 +1008,123 @@ fn parse_expr_operator<'a>(
|
||||||
parse_expr_end(min_indent, start, expr_state, arena, state)
|
parse_expr_end(min_indent, start, expr_state, arena, state)
|
||||||
}
|
}
|
||||||
BinOp::Assignment => {
|
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 {
|
|
||||||
expr_state.consume_spaces(arena);
|
|
||||||
let expr_region = expr_state.expr.region;
|
|
||||||
|
|
||||||
let indented_more = start.col + 1;
|
|
||||||
|
|
||||||
let call = to_call(
|
|
||||||
arena,
|
|
||||||
expr_state.arguments,
|
|
||||||
expr_state.expr,
|
|
||||||
spaces_after_operator,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (loc_def, state) = {
|
|
||||||
match expr_to_pattern_help(arena, &call.value) {
|
|
||||||
Ok(good) => {
|
|
||||||
let (_, mut ann_type, state) =
|
|
||||||
parse_expr_help(indented_more, arena, state)?;
|
|
||||||
|
|
||||||
// put the spaces from after the operator in front of the call
|
|
||||||
if !spaces_after_operator.is_empty() {
|
|
||||||
ann_type = arena
|
|
||||||
.alloc(ann_type.value)
|
|
||||||
.with_spaces_before(spaces_after_operator, ann_type.region);
|
|
||||||
}
|
|
||||||
|
|
||||||
let alias_region = Region::span_across(&call.region, &ann_type.region);
|
|
||||||
|
|
||||||
let alias = Def::Body(
|
|
||||||
arena.alloc(Located::at(expr_region, good)),
|
|
||||||
arena.alloc(ann_type),
|
|
||||||
);
|
|
||||||
|
|
||||||
(&*arena.alloc(Located::at(alias_region, alias)), 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,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Err((MadeProgress, fail, state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let def_state = DefState {
|
|
||||||
defs: bumpalo::vec![in arena; loc_def],
|
|
||||||
spaces_after: &[],
|
|
||||||
};
|
|
||||||
|
|
||||||
parse_defs_end(start, def_state, arena, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BinOp::Backpassing => {
|
|
||||||
if !expr_state.operators.is_empty() {
|
|
||||||
// this `=` likely occured inline; treat it as an invalid operator
|
|
||||||
let fail = EExpr::BadOperator(
|
|
||||||
arena.alloc([b'<', 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 {
|
|
||||||
expr_state.consume_spaces(arena);
|
|
||||||
let expr_region = expr_state.expr.region;
|
|
||||||
|
|
||||||
let indented_more = start.col + 1;
|
|
||||||
|
|
||||||
let call = to_call(
|
|
||||||
arena,
|
|
||||||
expr_state.arguments,
|
|
||||||
expr_state.expr,
|
|
||||||
spaces_after_operator,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (loc_pattern, loc_body, state) = {
|
|
||||||
match expr_to_pattern_help(arena, &call.value) {
|
|
||||||
Ok(good) => {
|
|
||||||
let (_, mut ann_type, state) =
|
|
||||||
parse_expr_help(indented_more, arena, state)?;
|
|
||||||
|
|
||||||
// put the spaces from after the operator in front of the call
|
|
||||||
if !spaces_after_operator.is_empty() {
|
|
||||||
ann_type = arena
|
|
||||||
.alloc(ann_type.value)
|
|
||||||
.with_spaces_before(spaces_after_operator, ann_type.region);
|
|
||||||
}
|
|
||||||
|
|
||||||
(Located::at(expr_region, good), ann_type, 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,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Err((MadeProgress, fail, state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let parse_cont = space0_before_e(
|
|
||||||
move |a, s| parse_expr_help(min_indent, a, s),
|
|
||||||
min_indent,
|
|
||||||
EExpr::Space,
|
|
||||||
EExpr::IndentEnd,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (_, loc_cont, state) = parse_cont.parse(arena, state)?;
|
|
||||||
|
|
||||||
let ret = Expr::Backpassing(
|
|
||||||
arena.alloc([loc_pattern]),
|
|
||||||
arena.alloc(loc_body),
|
|
||||||
arena.alloc(loc_cont),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok((MadeProgress, ret, state))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BinOp::HasType => {
|
|
||||||
debug_assert!(expr_state.operators.is_empty());
|
|
||||||
|
|
||||||
let expr_region = expr_state.expr.region;
|
let expr_region = expr_state.expr.region;
|
||||||
|
|
||||||
let indented_more = start.col + 1;
|
let indented_more = start.col + 1;
|
||||||
|
|
||||||
expr_state.consume_spaces(arena);
|
let call = expr_state
|
||||||
|
.validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction)
|
||||||
|
.map_err(|fail| (MadeProgress, fail, state))?;
|
||||||
|
|
||||||
let (loc_def, state) = match &expr_state.expr.value {
|
let (loc_def, state) = {
|
||||||
|
match expr_to_pattern_help(arena, &call.value) {
|
||||||
|
Ok(good) => {
|
||||||
|
let (_, mut ann_type, state) =
|
||||||
|
parse_expr_help(indented_more, arena, state)?;
|
||||||
|
|
||||||
|
// put the spaces from after the operator in front of the call
|
||||||
|
if !spaces_after_operator.is_empty() {
|
||||||
|
ann_type = arena
|
||||||
|
.alloc(ann_type.value)
|
||||||
|
.with_spaces_before(spaces_after_operator, ann_type.region);
|
||||||
|
}
|
||||||
|
|
||||||
|
let alias_region = Region::span_across(&call.region, &ann_type.region);
|
||||||
|
|
||||||
|
let alias = Def::Body(
|
||||||
|
arena.alloc(Located::at(expr_region, good)),
|
||||||
|
arena.alloc(ann_type),
|
||||||
|
);
|
||||||
|
|
||||||
|
(&*arena.alloc(Located::at(alias_region, alias)), 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,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err((MadeProgress, fail, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let def_state = DefState {
|
||||||
|
defs: bumpalo::vec![in arena; loc_def],
|
||||||
|
spaces_after: &[],
|
||||||
|
};
|
||||||
|
|
||||||
|
parse_defs_end(start, def_state, arena, state)
|
||||||
|
}
|
||||||
|
BinOp::Backpassing => {
|
||||||
|
let expr_region = expr_state.expr.region;
|
||||||
|
let indented_more = start.col + 1;
|
||||||
|
|
||||||
|
let call = expr_state
|
||||||
|
.validate_assignment_or_backpassing(arena, loc_op, |_, r, c| {
|
||||||
|
EExpr::BadOperator(&[b'<', b'-'], r, c)
|
||||||
|
})
|
||||||
|
.map_err(|fail| (MadeProgress, fail, state))?;
|
||||||
|
|
||||||
|
let (loc_pattern, loc_body, state) = {
|
||||||
|
match expr_to_pattern_help(arena, &call.value) {
|
||||||
|
Ok(good) => {
|
||||||
|
let (_, mut ann_type, state) =
|
||||||
|
parse_expr_help(indented_more, arena, state)?;
|
||||||
|
|
||||||
|
// put the spaces from after the operator in front of the call
|
||||||
|
if !spaces_after_operator.is_empty() {
|
||||||
|
ann_type = arena
|
||||||
|
.alloc(ann_type.value)
|
||||||
|
.with_spaces_before(spaces_after_operator, ann_type.region);
|
||||||
|
}
|
||||||
|
|
||||||
|
(Located::at(expr_region, good), ann_type, 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,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err((MadeProgress, fail, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let parse_cont = space0_before_e(
|
||||||
|
move |a, s| parse_expr_help(min_indent, a, s),
|
||||||
|
min_indent,
|
||||||
|
EExpr::Space,
|
||||||
|
EExpr::IndentEnd,
|
||||||
|
);
|
||||||
|
|
||||||
|
let (_, loc_cont, state) = parse_cont.parse(arena, state)?;
|
||||||
|
|
||||||
|
let ret = Expr::Backpassing(
|
||||||
|
arena.alloc([loc_pattern]),
|
||||||
|
arena.alloc(loc_body),
|
||||||
|
arena.alloc(loc_cont),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok((MadeProgress, ret, state))
|
||||||
|
}
|
||||||
|
BinOp::HasType => {
|
||||||
|
let expr_region = expr_state.expr.region;
|
||||||
|
let indented_more = start.col + 1;
|
||||||
|
|
||||||
|
let (expr, arguments) = expr_state
|
||||||
|
.validate_has_type(arena, loc_op)
|
||||||
|
.map_err(|fail| (MadeProgress, fail, state))?;
|
||||||
|
|
||||||
|
let (loc_def, state) = match &expr.value {
|
||||||
Expr::GlobalTag(name) => {
|
Expr::GlobalTag(name) => {
|
||||||
let mut type_arguments =
|
let mut type_arguments = Vec::with_capacity_in(arguments.len(), arena);
|
||||||
Vec::with_capacity_in(expr_state.arguments.len(), arena);
|
|
||||||
|
|
||||||
for argument in expr_state.arguments {
|
for argument in arguments {
|
||||||
match expr_to_pattern_help(arena, &argument.value) {
|
match expr_to_pattern_help(arena, &argument.value) {
|
||||||
Ok(good) => {
|
Ok(good) => {
|
||||||
type_arguments.push(Located::at(argument.region, good));
|
type_arguments.push(Located::at(argument.region, good));
|
||||||
|
@ -1140,11 +1144,10 @@ fn parse_expr_operator<'a>(
|
||||||
)
|
)
|
||||||
.parse(arena, state)?;
|
.parse(arena, state)?;
|
||||||
|
|
||||||
let alias_region =
|
let alias_region = Region::span_across(&expr.region, &ann_type.region);
|
||||||
Region::span_across(&expr_state.expr.region, &ann_type.region);
|
|
||||||
|
|
||||||
let alias = Def::Alias {
|
let alias = Def::Alias {
|
||||||
name: Located::at(expr_state.expr.region, name),
|
name: Located::at(expr.region, name),
|
||||||
vars: type_arguments.into_bump_slice(),
|
vars: type_arguments.into_bump_slice(),
|
||||||
ann: ann_type,
|
ann: ann_type,
|
||||||
};
|
};
|
||||||
|
@ -1153,14 +1156,7 @@ fn parse_expr_operator<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
let call = to_call(
|
let call = to_call(arena, arguments, expr, spaces_after_operator);
|
||||||
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) {
|
match expr_to_pattern_help(arena, &call.value) {
|
||||||
Ok(good) => {
|
Ok(good) => {
|
||||||
|
|
|
@ -152,7 +152,7 @@ pub struct Position {
|
||||||
pub col: u16,
|
pub col: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Eq, Copy, PartialEq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Located<T> {
|
pub struct Located<T> {
|
||||||
pub region: Region,
|
pub region: Region,
|
||||||
pub value: T,
|
pub value: T,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue