Parse and format dbg

This commit is contained in:
Richard Feldman 2022-11-22 19:08:54 -05:00
parent ef5d83a42d
commit 49f8768271
No known key found for this signature in database
GPG key ID: F1F21AA5B1D9E43B
13 changed files with 176 additions and 54 deletions

View file

@ -5,6 +5,7 @@
"as"
"is"
"expect"
"dbg"
"app"
"platform"

View file

@ -339,6 +339,11 @@ pub enum ValueDef<'a> {
body_expr: &'a Loc<Expr<'a>>,
},
Dbg {
condition: &'a Loc<Expr<'a>>,
preceding_comment: Region,
},
Expect {
condition: &'a Loc<Expr<'a>>,
preceding_comment: Region,

View file

@ -586,6 +586,7 @@ pub fn parse_single_def<'a>(
let start = state.pos();
let parse_dbg = crate::parser::keyword_e(crate::keyword::DBG, EExpect::Dbg);
let parse_expect_vanilla = crate::parser::keyword_e(crate::keyword::EXPECT, EExpect::Expect);
let parse_expect_fx = crate::parser::keyword_e(crate::keyword::EXPECT_FX, EExpect::Expect);
let parse_expect = either!(parse_expect_fx, parse_expect_vanilla);
@ -596,37 +597,35 @@ pub fn parse_single_def<'a>(
min_indent,
) {
Err((NoProgress, _)) => {
match parse_expect.parse(arena, state, min_indent) {
match parse_expect.parse(arena, state.clone(), min_indent) {
Err((_, _)) => {
// a hacky way to get expression-based error messages. TODO fix this
Ok((NoProgress, None, initial))
}
Ok((_, expect_flavor, state)) => {
let parse_def_expr =
space0_before_e(increment_min_indent(loc_expr()), EExpr::IndentEnd);
let (_, loc_def_expr, state) =
parse_def_expr.parse(arena, state, min_indent)?;
let end = loc_def_expr.region.end();
let region = Region::new(start, end);
// drop newlines before the preceding comment
let spaces_before_start = spaces_before_current_start.offset as usize;
let spaces_before_end = start.offset as usize;
let mut spaces_before_current_start = spaces_before_current_start;
for byte in &state.original_bytes()[spaces_before_start..spaces_before_end] {
match byte {
b' ' | b'\n' => {
spaces_before_current_start.offset += 1;
}
_ => break,
match parse_dbg.parse(arena, state, min_indent) {
Ok((_, _, state)) => parse_statement_inside_def(
arena,
state,
min_indent,
start,
spaces_before_current_start,
spaces_before_current,
|preceding_comment, loc_def_expr| ValueDef::Dbg {
condition: arena.alloc(loc_def_expr),
preceding_comment,
},
),
Err((_, _)) => {
// a hacky way to get expression-based error messages. TODO fix this
Ok((NoProgress, None, initial))
}
}
let preceding_comment = Region::new(spaces_before_current_start, start);
let value_def = match expect_flavor {
}
Ok((_, expect_flavor, state)) => parse_statement_inside_def(
arena,
state,
min_indent,
start,
spaces_before_current_start,
spaces_before_current,
|preceding_comment, loc_def_expr| match expect_flavor {
Either::Second(_) => ValueDef::Expect {
condition: arena.alloc(loc_def_expr),
preceding_comment,
@ -635,18 +634,8 @@ pub fn parse_single_def<'a>(
condition: arena.alloc(loc_def_expr),
preceding_comment,
},
};
Ok((
MadeProgress,
Some(SingleDef {
type_or_value: Either::Second(value_def),
region,
spaces_before: spaces_before_current,
}),
state,
))
}
},
),
}
}
Err((MadeProgress, _)) => {
@ -870,6 +859,49 @@ pub fn parse_single_def<'a>(
}
}
/// e.g. Things that can be on their own line in a def, e.g. `expect`, `expect-fx`, or `dbg`
fn parse_statement_inside_def<'a>(
arena: &'a Bump,
state: State<'a>,
min_indent: u32,
start: Position,
spaces_before_current_start: Position,
spaces_before_current: &'a [CommentOrNewline<'a>],
get_value_def: impl Fn(Region, Loc<Expr<'a>>) -> ValueDef<'a>,
) -> Result<(Progress, Option<SingleDef<'a>>, State<'a>), (Progress, EExpr<'a>)> {
let parse_def_expr = space0_before_e(increment_min_indent(loc_expr()), EExpr::IndentEnd);
let (_, loc_def_expr, state) = parse_def_expr.parse(arena, state, min_indent)?;
let end = loc_def_expr.region.end();
let region = Region::new(start, end);
// drop newlines before the preceding comment
let spaces_before_start = spaces_before_current_start.offset as usize;
let spaces_before_end = start.offset as usize;
let mut spaces_before_current_start = spaces_before_current_start;
for byte in &state.original_bytes()[spaces_before_start..spaces_before_end] {
match byte {
b' ' | b'\n' => {
spaces_before_current_start.offset += 1;
}
_ => break,
}
}
let preceding_comment = Region::new(spaces_before_current_start, start);
let value_def = get_value_def(preceding_comment, loc_def_expr);
Ok((
MadeProgress,
Some(SingleDef {
type_or_value: Either::Second(value_def),
region,
spaces_before: spaces_before_current,
}),
state,
))
}
// This is a macro only because trying to make it be a function caused lifetime issues.
#[macro_export]
macro_rules! join_ann_to_body {

View file

@ -4,6 +4,7 @@ pub const ELSE: &str = "else";
pub const WHEN: &str = "when";
pub const AS: &str = "as";
pub const IS: &str = "is";
pub const DBG: &str = "dbg";
pub const EXPECT: &str = "expect";
pub const EXPECT_FX: &str = "expect-fx";

View file

@ -544,6 +544,7 @@ pub enum EIf<'a> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EExpect<'a> {
Space(BadInputError, Position),
Dbg(Position),
Expect(Position),
Condition(&'a EExpr<'a>, Position),
Continuation(&'a EExpr<'a>, Position),