mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Merge remote-tracking branch 'remote/main' into upgrade-llvm-zig
This commit is contained in:
commit
2feb5d3c2e
426 changed files with 8889 additions and 4190 deletions
|
@ -489,7 +489,6 @@ pub enum Expr<'a> {
|
|||
Defs(&'a Defs<'a>, &'a Loc<Expr<'a>>),
|
||||
|
||||
Backpassing(&'a [Loc<Pattern<'a>>], &'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
|
||||
Expect(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
|
||||
|
||||
Dbg,
|
||||
DbgStmt(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
|
||||
|
@ -539,7 +538,6 @@ pub enum Expr<'a> {
|
|||
|
||||
// Problems
|
||||
MalformedIdent(&'a str, crate::ident::BadIdent),
|
||||
MalformedClosure,
|
||||
MalformedSuffixed(&'a Loc<Expr<'a>>),
|
||||
// Both operators were non-associative, e.g. (True == False == False).
|
||||
// We should tell the author to disambiguate by grouping them with parens.
|
||||
|
@ -672,7 +670,6 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
|||
Expr::Tag(_) => false,
|
||||
Expr::OpaqueRef(_) => false,
|
||||
Expr::Backpassing(_, _, _) => false, // TODO: we might want to check this?
|
||||
Expr::Expect(a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
|
||||
Expr::Dbg => false,
|
||||
Expr::DbgStmt(a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
|
||||
Expr::LowLevelDbg(_, a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
|
||||
|
@ -687,7 +684,6 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
|||
Expr::SpaceBefore(a, _) => is_expr_suffixed(a),
|
||||
Expr::SpaceAfter(a, _) => is_expr_suffixed(a),
|
||||
Expr::MalformedIdent(_, _) => false,
|
||||
Expr::MalformedClosure => false,
|
||||
Expr::MalformedSuffixed(_) => false,
|
||||
Expr::PrecedenceConflict(_) => false,
|
||||
Expr::EmptyRecordBuilder(_) => false,
|
||||
|
@ -713,7 +709,6 @@ fn is_assigned_value_suffixed<'a>(value: &AssignedField<'a, Expr<'a>>) -> bool {
|
|||
AssignedField::SpaceBefore(a, _) | AssignedField::SpaceAfter(a, _) => {
|
||||
is_assigned_value_suffixed(a)
|
||||
}
|
||||
AssignedField::Malformed(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -830,11 +825,6 @@ pub enum ValueDef<'a> {
|
|||
preceding_comment: Region,
|
||||
},
|
||||
|
||||
ExpectFx {
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
preceding_comment: Region,
|
||||
},
|
||||
|
||||
/// e.g. `import InternalHttp as Http exposing [Req]`.
|
||||
ModuleImport(ModuleImport<'a>),
|
||||
|
||||
|
@ -889,7 +879,7 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
| OptionalValue(_, _, loc_val)
|
||||
| IgnoredValue(_, _, loc_val) => break expr_stack.push(&loc_val.value),
|
||||
SpaceBefore(next, _) | SpaceAfter(next, _) => current = *next,
|
||||
LabelOnly(_) | Malformed(_) => break,
|
||||
LabelOnly(_) => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -940,11 +930,6 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
expr_stack.push(&a.value);
|
||||
expr_stack.push(&b.value);
|
||||
}
|
||||
Expect(condition, cont) => {
|
||||
expr_stack.reserve(2);
|
||||
expr_stack.push(&condition.value);
|
||||
expr_stack.push(&cont.value);
|
||||
}
|
||||
DbgStmt(condition, cont) => {
|
||||
expr_stack.reserve(2);
|
||||
expr_stack.push(&condition.value);
|
||||
|
@ -1038,7 +1023,6 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
| Tag(_)
|
||||
| OpaqueRef(_)
|
||||
| MalformedIdent(_, _)
|
||||
| MalformedClosure
|
||||
| PrecedenceConflict(_)
|
||||
| MalformedSuffixed(_) => { /* terminal */ }
|
||||
}
|
||||
|
@ -1074,10 +1058,6 @@ impl<'a, 'b> Iterator for RecursiveValueDefIter<'a, 'b> {
|
|||
| ValueDef::Expect {
|
||||
condition,
|
||||
preceding_comment: _,
|
||||
}
|
||||
| ValueDef::ExpectFx {
|
||||
condition,
|
||||
preceding_comment: _,
|
||||
} => self.push_pending_from_expr(&condition.value),
|
||||
|
||||
ValueDef::ModuleImport(ModuleImport {
|
||||
|
@ -1614,9 +1594,6 @@ pub enum Tag<'a> {
|
|||
// We preserve this for the formatter; canonicalization ignores it.
|
||||
SpaceBefore(&'a Tag<'a>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a Tag<'a>, &'a [CommentOrNewline<'a>]),
|
||||
|
||||
/// A malformed tag, which will code gen to a runtime error
|
||||
Malformed(&'a str),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
@ -1639,9 +1616,6 @@ pub enum AssignedField<'a, Val> {
|
|||
// We preserve this for the formatter; canonicalization ignores it.
|
||||
SpaceBefore(&'a AssignedField<'a, Val>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a AssignedField<'a, Val>, &'a [CommentOrNewline<'a>]),
|
||||
|
||||
/// A malformed assigned field, which will code gen to a runtime error
|
||||
Malformed(&'a str),
|
||||
}
|
||||
|
||||
impl<'a, Val> AssignedField<'a, Val> {
|
||||
|
@ -1653,7 +1627,7 @@ impl<'a, Val> AssignedField<'a, Val> {
|
|||
Self::RequiredValue(_, _, val)
|
||||
| Self::OptionalValue(_, _, val)
|
||||
| Self::IgnoredValue(_, _, val) => break Some(val),
|
||||
Self::LabelOnly(_) | Self::Malformed(_) => break None,
|
||||
Self::LabelOnly(_) => break None,
|
||||
Self::SpaceBefore(next, _) | Self::SpaceAfter(next, _) => current = *next,
|
||||
}
|
||||
}
|
||||
|
@ -2501,7 +2475,6 @@ impl<'a> Malformed for Expr<'a> {
|
|||
Closure(args, body) => args.iter().any(|arg| arg.is_malformed()) || body.is_malformed(),
|
||||
Defs(defs, body) => defs.is_malformed() || body.is_malformed(),
|
||||
Backpassing(args, call, body) => args.iter().any(|arg| arg.is_malformed()) || call.is_malformed() || body.is_malformed(),
|
||||
Expect(condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
|
||||
Dbg => false,
|
||||
DbgStmt(condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
|
||||
LowLevelDbg(_, condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
|
||||
|
@ -2518,7 +2491,6 @@ impl<'a> Malformed for Expr<'a> {
|
|||
ParensAround(expr) => expr.is_malformed(),
|
||||
|
||||
MalformedIdent(_, _) |
|
||||
MalformedClosure |
|
||||
MalformedSuffixed(..) |
|
||||
PrecedenceConflict(_) |
|
||||
EmptyRecordBuilder(_) |
|
||||
|
@ -2593,7 +2565,6 @@ impl<'a, T: Malformed> Malformed for AssignedField<'a, T> {
|
|||
AssignedField::SpaceBefore(field, _) | AssignedField::SpaceAfter(field, _) => {
|
||||
field.is_malformed()
|
||||
}
|
||||
AssignedField::Malformed(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2738,10 +2709,6 @@ impl<'a> Malformed for ValueDef<'a> {
|
|||
| ValueDef::Expect {
|
||||
condition,
|
||||
preceding_comment: _,
|
||||
}
|
||||
| ValueDef::ExpectFx {
|
||||
condition,
|
||||
preceding_comment: _,
|
||||
} => condition.is_malformed(),
|
||||
ValueDef::ModuleImport(ModuleImport {
|
||||
before_name: _,
|
||||
|
@ -2815,7 +2782,6 @@ impl<'a> Malformed for Tag<'a> {
|
|||
match self {
|
||||
Tag::Apply { name: _, args } => args.iter().any(|arg| arg.is_malformed()),
|
||||
Tag::SpaceBefore(tag, _) | Tag::SpaceAfter(tag, _) => tag.is_malformed(),
|
||||
Tag::Malformed(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ use roc_region::all::{Loc, Position, Region};
|
|||
|
||||
use crate::parser::Progress::{self, *};
|
||||
|
||||
fn expr_end<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
||||
pub fn expr_end<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
||||
|_arena, state: State<'a>, _min_indent: u32| {
|
||||
if state.has_reached_end() {
|
||||
Ok((NoProgress, (), state))
|
||||
|
@ -545,10 +545,6 @@ fn stmt_start<'a>(
|
|||
EExpr::Expect,
|
||||
expect_help(options, preceding_comment)
|
||||
)),
|
||||
loc(specialize_err(
|
||||
EExpr::Dbg,
|
||||
dbg_stmt_help(options, preceding_comment)
|
||||
)),
|
||||
loc(specialize_err(EExpr::Return, return_help(options))),
|
||||
loc(specialize_err(EExpr::Import, map(import(), Stmt::ValueDef))),
|
||||
map(
|
||||
|
@ -2094,7 +2090,7 @@ pub fn merge_spaces<'a>(
|
|||
fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<'a>, ()> {
|
||||
let mut expr = expr.extract_spaces();
|
||||
|
||||
if let Expr::ParensAround(loc_expr) = &expr.item {
|
||||
while let Expr::ParensAround(loc_expr) = &expr.item {
|
||||
let expr_inner = loc_expr.extract_spaces();
|
||||
|
||||
expr.before = merge_spaces(arena, expr.before, expr_inner.before);
|
||||
|
@ -2175,12 +2171,10 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
| Expr::Defs(_, _)
|
||||
| Expr::If { .. }
|
||||
| Expr::When(_, _)
|
||||
| Expr::Expect(_, _)
|
||||
| Expr::Dbg
|
||||
| Expr::DbgStmt(_, _)
|
||||
| Expr::LowLevelDbg(_, _, _)
|
||||
| Expr::Return(_, _)
|
||||
| Expr::MalformedClosure
|
||||
| Expr::MalformedSuffixed(..)
|
||||
| Expr::PrecedenceConflict { .. }
|
||||
| Expr::EmptyRecordBuilder(_)
|
||||
|
@ -2254,7 +2248,6 @@ fn assigned_expr_field_to_pattern_help<'a>(
|
|||
arena.alloc(assigned_expr_field_to_pattern_help(arena, nested)?),
|
||||
spaces,
|
||||
),
|
||||
AssignedField::Malformed(string) => Pattern::Malformed(string),
|
||||
AssignedField::IgnoredValue(_, _, _) => return Err(()),
|
||||
})
|
||||
}
|
||||
|
@ -2621,11 +2614,9 @@ fn expect_help<'a>(
|
|||
preceding_comment: Region,
|
||||
) -> impl Parser<'a, Stmt<'a>, EExpect<'a>> {
|
||||
move |arena: &'a Bump, state: State<'a>, min_indent| {
|
||||
let parse_expect_vanilla = crate::parser::keyword(crate::keyword::EXPECT, EExpect::Expect);
|
||||
let parse_expect_fx = crate::parser::keyword(crate::keyword::EXPECT_FX, EExpect::Expect);
|
||||
let parse_expect = either(parse_expect_vanilla, parse_expect_fx);
|
||||
let parse_expect = crate::parser::keyword(crate::keyword::EXPECT, EExpect::Expect);
|
||||
|
||||
let (_, kw, state) = parse_expect.parse(arena, state, min_indent)?;
|
||||
let (_, _kw, state) = parse_expect.parse(arena, state, min_indent)?;
|
||||
|
||||
let (_, condition, state) = parse_block(
|
||||
options,
|
||||
|
@ -2637,15 +2628,9 @@ fn expect_help<'a>(
|
|||
)
|
||||
.map_err(|(_, f)| (MadeProgress, f))?;
|
||||
|
||||
let vd = match kw {
|
||||
Either::First(_) => ValueDef::Expect {
|
||||
condition: arena.alloc(condition),
|
||||
preceding_comment,
|
||||
},
|
||||
Either::Second(_) => ValueDef::ExpectFx {
|
||||
condition: arena.alloc(condition),
|
||||
preceding_comment,
|
||||
},
|
||||
let vd = ValueDef::Expect {
|
||||
condition: arena.alloc(condition),
|
||||
preceding_comment,
|
||||
};
|
||||
|
||||
Ok((MadeProgress, Stmt::ValueDef(vd), state))
|
||||
|
@ -2679,34 +2664,6 @@ fn return_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Stmt<'a>, ERetu
|
|||
.trace("return_help")
|
||||
}
|
||||
|
||||
fn dbg_stmt_help<'a>(
|
||||
options: ExprParseOptions,
|
||||
preceding_comment: Region,
|
||||
) -> impl Parser<'a, Stmt<'a>, EExpect<'a>> {
|
||||
(move |arena: &'a Bump, state: State<'a>, min_indent| {
|
||||
let (_, _, state) =
|
||||
parser::keyword(keyword::DBG, EExpect::Dbg).parse(arena, state, min_indent)?;
|
||||
|
||||
let (_, condition, state) = parse_block(
|
||||
options,
|
||||
arena,
|
||||
state,
|
||||
true,
|
||||
EExpect::IndentCondition,
|
||||
EExpect::Condition,
|
||||
)
|
||||
.map_err(|(_, f)| (MadeProgress, f))?;
|
||||
|
||||
let stmt = Stmt::ValueDef(ValueDef::Dbg {
|
||||
condition: arena.alloc(condition),
|
||||
preceding_comment,
|
||||
});
|
||||
|
||||
Ok((MadeProgress, stmt, state))
|
||||
})
|
||||
.trace("dbg_stmt_help")
|
||||
}
|
||||
|
||||
fn dbg_kw<'a>() -> impl Parser<'a, Expr<'a>, EExpect<'a>> {
|
||||
(move |arena: &'a Bump, state: State<'a>, min_indent: u32| {
|
||||
let (_, _, next_state) =
|
||||
|
@ -3121,12 +3078,43 @@ fn stmts_to_defs<'a>(
|
|||
}
|
||||
Stmt::Expr(e) => {
|
||||
if i + 1 < stmts.len() {
|
||||
defs.push_value_def(
|
||||
ValueDef::Stmt(arena.alloc(Loc::at(sp_stmt.item.region, e))),
|
||||
sp_stmt.item.region,
|
||||
sp_stmt.before,
|
||||
&[],
|
||||
);
|
||||
if let Expr::Apply(
|
||||
Loc {
|
||||
value: Expr::Dbg, ..
|
||||
},
|
||||
args,
|
||||
_,
|
||||
) = e
|
||||
{
|
||||
if args.len() != 1 {
|
||||
// TODO: this should be done in can, not parsing!
|
||||
return Err(EExpr::Dbg(
|
||||
EExpect::DbgArity(sp_stmt.item.region.start()),
|
||||
sp_stmt.item.region.start(),
|
||||
));
|
||||
}
|
||||
let condition = &args[0];
|
||||
let rest = stmts_to_expr(&stmts[i + 1..], arena)?;
|
||||
let e = Expr::DbgStmt(condition, arena.alloc(rest));
|
||||
|
||||
let e = if sp_stmt.before.is_empty() {
|
||||
e
|
||||
} else {
|
||||
arena.alloc(e).before(sp_stmt.before)
|
||||
};
|
||||
|
||||
last_expr = Some(Loc::at(sp_stmt.item.region, e));
|
||||
|
||||
// don't re-process the rest of the statements; they got consumed by the dbg expr
|
||||
break;
|
||||
} else {
|
||||
defs.push_value_def(
|
||||
ValueDef::Stmt(arena.alloc(Loc::at(sp_stmt.item.region, e))),
|
||||
sp_stmt.item.region,
|
||||
sp_stmt.before,
|
||||
&[],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let e = if sp_stmt.before.is_empty() {
|
||||
e
|
||||
|
|
|
@ -8,7 +8,6 @@ pub const IS: &str = "is";
|
|||
pub const DBG: &str = "dbg";
|
||||
pub const IMPORT: &str = "import";
|
||||
pub const EXPECT: &str = "expect";
|
||||
pub const EXPECT_FX: &str = "expect-fx";
|
||||
pub const RETURN: &str = "return";
|
||||
pub const CRASH: &str = "crash";
|
||||
|
||||
|
@ -22,6 +21,6 @@ pub const WHERE: &str = "where";
|
|||
// These keywords are valid in headers
|
||||
pub const PLATFORM: &str = "platform";
|
||||
|
||||
pub const KEYWORDS: [&str; 12] = [
|
||||
IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, EXPECT_FX, RETURN, CRASH,
|
||||
pub const KEYWORDS: [&str; 11] = [
|
||||
IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, RETURN, CRASH,
|
||||
];
|
||||
|
|
|
@ -427,13 +427,6 @@ impl<'a> Normalize<'a> for ValueDef<'a> {
|
|||
condition: arena.alloc(condition.normalize(arena)),
|
||||
preceding_comment: Region::zero(),
|
||||
},
|
||||
ExpectFx {
|
||||
condition,
|
||||
preceding_comment: _,
|
||||
} => ExpectFx {
|
||||
condition: arena.alloc(condition.normalize(arena)),
|
||||
preceding_comment: Region::zero(),
|
||||
},
|
||||
ModuleImport(module_import) => ModuleImport(module_import.normalize(arena)),
|
||||
IngestedFileImport(ingested_file_import) => {
|
||||
IngestedFileImport(ingested_file_import.normalize(arena))
|
||||
|
@ -556,7 +549,6 @@ impl<'a, T: Normalize<'a> + Copy + std::fmt::Debug> Normalize<'a> for AssignedFi
|
|||
arena.alloc(c.normalize(arena)),
|
||||
),
|
||||
AssignedField::LabelOnly(a) => AssignedField::LabelOnly(a.normalize(arena)),
|
||||
AssignedField::Malformed(a) => AssignedField::Malformed(a),
|
||||
AssignedField::SpaceBefore(a, _) => a.normalize(arena),
|
||||
AssignedField::SpaceAfter(a, _) => a.normalize(arena),
|
||||
}
|
||||
|
@ -743,10 +735,6 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
|||
arena.alloc(b.normalize(arena)),
|
||||
arena.alloc(c.normalize(arena)),
|
||||
),
|
||||
Expr::Expect(a, b) => Expr::Expect(
|
||||
arena.alloc(a.normalize(arena)),
|
||||
arena.alloc(b.normalize(arena)),
|
||||
),
|
||||
Expr::Dbg => Expr::Dbg,
|
||||
Expr::DbgStmt(a, b) => Expr::DbgStmt(
|
||||
arena.alloc(a.normalize(arena)),
|
||||
|
@ -784,7 +772,6 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
|||
a.normalize(arena)
|
||||
}
|
||||
Expr::MalformedIdent(a, b) => Expr::MalformedIdent(a, remove_spaces_bad_ident(b)),
|
||||
Expr::MalformedClosure => Expr::MalformedClosure,
|
||||
Expr::MalformedSuffixed(a) => Expr::MalformedSuffixed(a),
|
||||
Expr::PrecedenceConflict(a) => Expr::PrecedenceConflict(a),
|
||||
Expr::SpaceBefore(a, _) => a.normalize(arena),
|
||||
|
@ -938,7 +925,6 @@ impl<'a> Normalize<'a> for Tag<'a> {
|
|||
name: name.normalize(arena),
|
||||
args: args.normalize(arena),
|
||||
},
|
||||
Tag::Malformed(a) => Tag::Malformed(a),
|
||||
Tag::SpaceBefore(a, _) => a.normalize(arena),
|
||||
Tag::SpaceAfter(a, _) => a.normalize(arena),
|
||||
}
|
||||
|
@ -1479,6 +1465,7 @@ impl<'a> Normalize<'a> for EExpect<'a> {
|
|||
EExpect::Continuation(arena.alloc(inner_err.normalize(arena)), Position::zero())
|
||||
}
|
||||
EExpect::IndentCondition(_) => EExpect::IndentCondition(Position::zero()),
|
||||
EExpect::DbgArity(_) => EExpect::DbgArity(Position::zero()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -513,6 +513,7 @@ pub enum EExpect<'a> {
|
|||
Condition(&'a EExpr<'a>, Position),
|
||||
Continuation(&'a EExpr<'a>, Position),
|
||||
IndentCondition(Position),
|
||||
DbgArity(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -1056,7 +1057,11 @@ where
|
|||
// the next character should not be an identifier character
|
||||
// to prevent treating `whence` or `iffy` as keywords
|
||||
match state.bytes().get(width) {
|
||||
Some(next) if *next == b' ' || *next == b'#' || *next == b'\n' || *next == b'\r' => {
|
||||
Some(
|
||||
b' ' | b'#' | b'\n' | b'\r' | b'\t' | b',' | b'(' | b')' | b'[' | b']' | b'{'
|
||||
| b'}' | b'"' | b'\'' | b'/' | b'\\' | b'+' | b'*' | b'%' | b'^' | b'&' | b'|'
|
||||
| b'<' | b'>' | b'=' | b'!' | b'~' | b'`' | b';' | b':' | b'?' | b'.',
|
||||
) => {
|
||||
state = state.advance(width);
|
||||
Ok((MadeProgress, (), state))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue