mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-11 18:58:24 +03:00
Parse and format dbg
This commit is contained in:
parent
ef5d83a42d
commit
49f8768271
@ -278,6 +278,7 @@ fn to_pending_def<'a>(
|
||||
Type(TypeDef::Opaque { .. }) => internal_error!("opaques not implemented"),
|
||||
Type(TypeDef::Ability { .. }) => todo_abilities!(),
|
||||
|
||||
Value(AstValueDef::Dbg { .. }) => todo!(),
|
||||
Value(AstValueDef::Expect { .. }) => todo!(),
|
||||
Value(AstValueDef::ExpectFx { .. }) => todo!(),
|
||||
|
||||
|
@ -88,20 +88,21 @@ pub struct Annotation {
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CanDefs {
|
||||
defs: Vec<Option<Def>>,
|
||||
expects: Expects,
|
||||
expects_fx: Expects,
|
||||
dbgs: ExpectsOrDbgs,
|
||||
expects: ExpectsOrDbgs,
|
||||
expects_fx: ExpectsOrDbgs,
|
||||
def_ordering: DefOrdering,
|
||||
aliases: VecMap<Symbol, Alias>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Expects {
|
||||
pub struct ExpectsOrDbgs {
|
||||
pub conditions: Vec<Expr>,
|
||||
pub regions: Vec<Region>,
|
||||
pub preceding_comment: Vec<Region>,
|
||||
}
|
||||
|
||||
impl Expects {
|
||||
impl ExpectsOrDbgs {
|
||||
fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
conditions: Vec::with_capacity(capacity),
|
||||
@ -239,8 +240,8 @@ pub enum Declaration {
|
||||
Declare(Def),
|
||||
DeclareRec(Vec<Def>, IllegalCycleMark),
|
||||
Builtin(Def),
|
||||
Expects(Expects),
|
||||
ExpectsFx(Expects),
|
||||
Expects(ExpectsOrDbgs),
|
||||
ExpectsFx(ExpectsOrDbgs),
|
||||
/// If we know a cycle is illegal during canonicalization.
|
||||
/// Otherwise we will try to detect this during solving; see [`IllegalCycleMark`].
|
||||
InvalidCycle(Vec<CycleEntry>),
|
||||
@ -1017,6 +1018,7 @@ fn canonicalize_value_defs<'a>(
|
||||
// the ast::Expr values in pending_exprs for further canonicalization
|
||||
// once we've finished assembling the entire scope.
|
||||
let mut pending_value_defs = Vec::with_capacity(value_defs.len());
|
||||
let mut pending_dbgs = Vec::with_capacity(value_defs.len());
|
||||
let mut pending_expects = Vec::with_capacity(value_defs.len());
|
||||
let mut pending_expect_fx = Vec::with_capacity(value_defs.len());
|
||||
|
||||
@ -1030,10 +1032,12 @@ fn canonicalize_value_defs<'a>(
|
||||
pending_value_defs.push(pending_def);
|
||||
}
|
||||
PendingValue::SignatureDefMismatch => { /* skip */ }
|
||||
PendingValue::Dbg(pending_dbg) => {
|
||||
pending_dbgs.push(pending_dbg);
|
||||
}
|
||||
PendingValue::Expect(pending_expect) => {
|
||||
pending_expects.push(pending_expect);
|
||||
}
|
||||
|
||||
PendingValue::ExpectFx(pending_expect) => {
|
||||
pending_expect_fx.push(pending_expect);
|
||||
}
|
||||
@ -1094,8 +1098,23 @@ fn canonicalize_value_defs<'a>(
|
||||
def_ordering.insert_symbol_references(def_id as u32, &temp_output.references)
|
||||
}
|
||||
|
||||
let mut expects = Expects::with_capacity(pending_expects.len());
|
||||
let mut expects_fx = Expects::with_capacity(pending_expects.len());
|
||||
let mut dbgs = ExpectsOrDbgs::with_capacity(pending_dbgs.len());
|
||||
let mut expects = ExpectsOrDbgs::with_capacity(pending_expects.len());
|
||||
let mut expects_fx = ExpectsOrDbgs::with_capacity(pending_expects.len());
|
||||
|
||||
for pending in pending_dbgs {
|
||||
let (loc_can_condition, can_output) = canonicalize_expr(
|
||||
env,
|
||||
var_store,
|
||||
scope,
|
||||
pending.condition.region,
|
||||
&pending.condition.value,
|
||||
);
|
||||
|
||||
dbgs.push(loc_can_condition, pending.preceding_comment);
|
||||
|
||||
output.union(can_output);
|
||||
}
|
||||
|
||||
for pending in pending_expects {
|
||||
let (loc_can_condition, can_output) = canonicalize_expr(
|
||||
@ -1127,6 +1146,7 @@ fn canonicalize_value_defs<'a>(
|
||||
|
||||
let can_defs = CanDefs {
|
||||
defs,
|
||||
dbgs,
|
||||
expects,
|
||||
expects_fx,
|
||||
def_ordering,
|
||||
@ -1534,6 +1554,7 @@ pub(crate) fn sort_can_defs_new(
|
||||
) -> (Declarations, Output) {
|
||||
let CanDefs {
|
||||
defs,
|
||||
dbgs,
|
||||
expects,
|
||||
expects_fx,
|
||||
def_ordering,
|
||||
@ -1750,6 +1771,7 @@ pub(crate) fn sort_can_defs(
|
||||
) -> (Vec<Declaration>, Output) {
|
||||
let CanDefs {
|
||||
mut defs,
|
||||
dbgs,
|
||||
expects,
|
||||
expects_fx,
|
||||
def_ordering,
|
||||
@ -2581,12 +2603,13 @@ fn to_pending_type_def<'a>(
|
||||
|
||||
enum PendingValue<'a> {
|
||||
Def(PendingValueDef<'a>),
|
||||
Expect(PendingExpect<'a>),
|
||||
ExpectFx(PendingExpect<'a>),
|
||||
Dbg(PendingExpectOrDbg<'a>),
|
||||
Expect(PendingExpectOrDbg<'a>),
|
||||
ExpectFx(PendingExpectOrDbg<'a>),
|
||||
SignatureDefMismatch,
|
||||
}
|
||||
|
||||
struct PendingExpect<'a> {
|
||||
struct PendingExpectOrDbg<'a> {
|
||||
condition: &'a Loc<ast::Expr<'a>>,
|
||||
preceding_comment: Region,
|
||||
}
|
||||
@ -2684,10 +2707,18 @@ fn to_pending_value_def<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
Dbg {
|
||||
condition,
|
||||
preceding_comment,
|
||||
} => PendingValue::Dbg(PendingExpectOrDbg {
|
||||
condition,
|
||||
preceding_comment: *preceding_comment,
|
||||
}),
|
||||
|
||||
Expect {
|
||||
condition,
|
||||
preceding_comment,
|
||||
} => PendingValue::Expect(PendingExpect {
|
||||
} => PendingValue::Expect(PendingExpectOrDbg {
|
||||
condition,
|
||||
preceding_comment: *preceding_comment,
|
||||
}),
|
||||
@ -2695,7 +2726,7 @@ fn to_pending_value_def<'a>(
|
||||
ExpectFx {
|
||||
condition,
|
||||
preceding_comment,
|
||||
} => PendingValue::ExpectFx(PendingExpect {
|
||||
} => PendingValue::ExpectFx(PendingExpectOrDbg {
|
||||
condition,
|
||||
preceding_comment: *preceding_comment,
|
||||
}),
|
||||
|
@ -82,6 +82,16 @@ fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a>
|
||||
body_pattern,
|
||||
body_expr: desugar_expr(arena, body_expr),
|
||||
},
|
||||
Dbg {
|
||||
condition,
|
||||
preceding_comment,
|
||||
} => {
|
||||
let desugared_condition = &*arena.alloc(desugar_expr(arena, condition));
|
||||
Dbg {
|
||||
condition: desugared_condition,
|
||||
preceding_comment: *preceding_comment,
|
||||
}
|
||||
}
|
||||
Expect {
|
||||
condition,
|
||||
preceding_comment,
|
||||
|
@ -168,6 +168,7 @@ impl<'a> Formattable for ValueDef<'a> {
|
||||
AnnotatedBody { .. } => true,
|
||||
Expect { condition, .. } => condition.is_multiline(),
|
||||
ExpectFx { condition, .. } => condition.is_multiline(),
|
||||
Dbg { condition, .. } => condition.is_multiline(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,6 +242,7 @@ impl<'a> Formattable for ValueDef<'a> {
|
||||
Body(loc_pattern, loc_expr) => {
|
||||
fmt_body(buf, &loc_pattern.value, &loc_expr.value, indent);
|
||||
}
|
||||
Dbg { condition, .. } => fmt_dbg_in_def(buf, condition, self.is_multiline(), indent),
|
||||
Expect { condition, .. } => fmt_expect(buf, condition, self.is_multiline(), indent),
|
||||
ExpectFx { condition, .. } => {
|
||||
fmt_expect_fx(buf, condition, self.is_multiline(), indent)
|
||||
@ -294,6 +296,27 @@ impl<'a> Formattable for ValueDef<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_dbg_in_def<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
is_multiline: bool,
|
||||
indent: u16,
|
||||
) {
|
||||
buf.ensure_ends_with_newline();
|
||||
buf.indent(indent);
|
||||
buf.push_str("dbg");
|
||||
|
||||
let return_indent = if is_multiline {
|
||||
buf.newline();
|
||||
indent + INDENT
|
||||
} else {
|
||||
buf.spaces(1);
|
||||
indent
|
||||
};
|
||||
|
||||
condition.format(buf, return_indent);
|
||||
}
|
||||
|
||||
fn fmt_expect<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
|
@ -540,6 +540,13 @@ impl<'a> RemoveSpaces<'a> for ValueDef<'a> {
|
||||
body_pattern: arena.alloc(body_pattern.remove_spaces(arena)),
|
||||
body_expr: arena.alloc(body_expr.remove_spaces(arena)),
|
||||
},
|
||||
Dbg {
|
||||
condition,
|
||||
preceding_comment: _,
|
||||
} => Dbg {
|
||||
condition: arena.alloc(condition.remove_spaces(arena)),
|
||||
preceding_comment: Region::zero(),
|
||||
},
|
||||
Expect {
|
||||
condition,
|
||||
preceding_comment: _,
|
||||
|
@ -200,6 +200,11 @@ fn generate_entry_docs<'a>(
|
||||
|
||||
ValueDef::Body(_, _) => (),
|
||||
|
||||
ValueDef::Dbg { .. } => {
|
||||
|
||||
// Don't generate docs for `dbg`s
|
||||
}
|
||||
|
||||
ValueDef::Expect { .. } => {
|
||||
// Don't generate docs for `expect`s
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
"as"
|
||||
"is"
|
||||
"expect"
|
||||
"dbg"
|
||||
|
||||
"app"
|
||||
"platform"
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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),
|
||||
|
@ -33,6 +33,7 @@ pub enum Token {
|
||||
KeywordEffects = 0b_0011_0000,
|
||||
KeywordPlatform = 0b_0011_0001,
|
||||
KeywordRequires = 0b_0011_0010,
|
||||
KeywordDbg = 0b_0111_1011,
|
||||
|
||||
Comma = 0b_0100_0000,
|
||||
Colon = 0b_0100_0001,
|
||||
@ -417,6 +418,7 @@ fn lex_ident(uppercase: bool, bytes: &[u8]) -> (Token, usize) {
|
||||
b"when" => Token::KeywordWhen,
|
||||
b"as" => Token::KeywordAs,
|
||||
b"is" => Token::KeywordIs,
|
||||
b"dbg" => Token::KeywordDbg,
|
||||
b"expect" => Token::KeywordExpect,
|
||||
b"app" => Token::KeywordApp,
|
||||
b"interface" => Token::KeywordInterface,
|
||||
|
@ -196,6 +196,9 @@ impl ReplState {
|
||||
| ValueDef::AnnotatedBody { .. } => {
|
||||
todo!("handle pattern other than identifier (which repl doesn't support)")
|
||||
}
|
||||
ValueDef::Dbg { .. } => {
|
||||
todo!("handle receiving a `dbg` - what should the repl do for that?")
|
||||
}
|
||||
ValueDef::Expect { .. } => {
|
||||
todo!("handle receiving an `expect` - what should the repl do for that?")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user