mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
transform expression
This commit is contained in:
parent
d382988362
commit
2db94cf4e8
2 changed files with 93 additions and 3 deletions
|
@ -1469,6 +1469,33 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn word2<'a, ToError, E>(word_1: u8, word_2: u8, to_error: ToError) -> impl Parser<'a, (), E>
|
||||||
|
where
|
||||||
|
ToError: Fn(Row, Col) -> E,
|
||||||
|
E: 'a,
|
||||||
|
{
|
||||||
|
debug_assert_ne!(word_1, b'\n');
|
||||||
|
debug_assert_ne!(word_2, b'\n');
|
||||||
|
|
||||||
|
let needle = [word_1, word_2];
|
||||||
|
|
||||||
|
move |_arena: &'a Bump, state: State<'a>| {
|
||||||
|
if state.bytes.starts_with(&needle) {
|
||||||
|
Ok((
|
||||||
|
MadeProgress,
|
||||||
|
(),
|
||||||
|
State {
|
||||||
|
bytes: &state.bytes[2..],
|
||||||
|
column: state.column + 2,
|
||||||
|
..state
|
||||||
|
},
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Err((NoProgress, to_error(state.line, state.column), state))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn in_context<'a, AddContext, P1, P2, Start, A, X, Y>(
|
fn in_context<'a, AddContext, P1, P2, Start, A, X, Y>(
|
||||||
add_context: AddContext,
|
add_context: AddContext,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::ident::join_module_parts;
|
||||||
use crate::keyword;
|
use crate::keyword;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
allocated, ascii_char, ascii_string, backtrackable, not_e, optional, peek_utf8_char_e,
|
allocated, ascii_char, ascii_string, backtrackable, not_e, optional, peek_utf8_char_e,
|
||||||
specialize, specialize_ref, word1, BadInputError, Col, Either, ParseResult, Parser,
|
specialize, specialize_ref, word1, word2, BadInputError, Col, Either, ParseResult, Parser,
|
||||||
Progress::{self, *},
|
Progress::{self, *},
|
||||||
Row, State, SyntaxError, TApply, TInParens, TRecord, TTagUnion, TVariable, Type,
|
Row, State, SyntaxError, TApply, TInParens, TRecord, TTagUnion, TVariable, Type,
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,7 @@ use roc_region::all::{Located, Region};
|
||||||
pub fn located<'a>(
|
pub fn located<'a>(
|
||||||
min_indent: u16,
|
min_indent: u16,
|
||||||
) -> impl Parser<'a, Located<TypeAnnotation<'a>>, SyntaxError<'a>> {
|
) -> impl Parser<'a, Located<TypeAnnotation<'a>>, SyntaxError<'a>> {
|
||||||
expression(min_indent)
|
specialize(|x, _, _| SyntaxError::Type(x), expression_e(min_indent))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -190,7 +190,7 @@ fn loc_type_in_parens<'a>(
|
||||||
between!(
|
between!(
|
||||||
word1(b'(', TInParens::Open),
|
word1(b'(', TInParens::Open),
|
||||||
space0_around_e(
|
space0_around_e(
|
||||||
move |arena, state| specialize_ref(TInParens::Syntax, expression(min_indent))
|
move |arena, state| specialize_ref(TInParens::Type, expression_e(min_indent))
|
||||||
.parse(arena, state),
|
.parse(arena, state),
|
||||||
min_indent,
|
min_indent,
|
||||||
TInParens::Space,
|
TInParens::Space,
|
||||||
|
@ -414,6 +414,69 @@ fn expression<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expression_e<'a>(min_indent: u16) -> impl Parser<'a, Located<TypeAnnotation<'a>>, Type<'a>> {
|
||||||
|
move |arena, state: State<'a>| {
|
||||||
|
let (p1, first, state) = space0_before_e(
|
||||||
|
term_help(min_indent),
|
||||||
|
min_indent,
|
||||||
|
Type::TSpace,
|
||||||
|
Type::TIndentStart,
|
||||||
|
)
|
||||||
|
.parse(arena, state)?;
|
||||||
|
|
||||||
|
let (p2, rest, state) = zero_or_more!(skip_first!(
|
||||||
|
word1(b',', Type::TStart),
|
||||||
|
space0_around_e(
|
||||||
|
term_help(min_indent),
|
||||||
|
min_indent,
|
||||||
|
Type::TSpace,
|
||||||
|
Type::TIndentStart
|
||||||
|
)
|
||||||
|
))
|
||||||
|
.parse(arena, state)?;
|
||||||
|
|
||||||
|
// TODO this space0 is dropped, so newlines just before the function arrow when there
|
||||||
|
// is only one argument are not seen by the formatter. Can we do better?
|
||||||
|
let (p3, is_function, state) = optional(skip_first!(
|
||||||
|
space0_e(min_indent, Type::TSpace, Type::TIndentStart),
|
||||||
|
word2(b'-', b'>', Type::TStart)
|
||||||
|
))
|
||||||
|
.parse(arena, state)?;
|
||||||
|
|
||||||
|
if is_function.is_some() {
|
||||||
|
let (p4, return_type, state) = space0_before_e(
|
||||||
|
term_help(min_indent),
|
||||||
|
min_indent,
|
||||||
|
Type::TSpace,
|
||||||
|
Type::TIndentStart,
|
||||||
|
)
|
||||||
|
.parse(arena, state)?;
|
||||||
|
|
||||||
|
// prepare arguments
|
||||||
|
let mut arguments = Vec::with_capacity_in(rest.len() + 1, &arena);
|
||||||
|
arguments.push(first);
|
||||||
|
arguments.extend(rest);
|
||||||
|
let output = arena.alloc(arguments);
|
||||||
|
|
||||||
|
let result = Located {
|
||||||
|
region: return_type.region,
|
||||||
|
value: TypeAnnotation::Function(output, arena.alloc(return_type)),
|
||||||
|
};
|
||||||
|
let progress = p1.or(p2).or(p3).or(p4);
|
||||||
|
Ok((progress, result, state))
|
||||||
|
} else {
|
||||||
|
let progress = p1.or(p2).or(p3);
|
||||||
|
// if there is no function arrow, there cannot be more than 1 "argument"
|
||||||
|
if rest.is_empty() {
|
||||||
|
Ok((progress, first, state))
|
||||||
|
} else {
|
||||||
|
// e.g. `Int,Int` without an arrow and return type
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a basic type annotation that's a combination of variables
|
/// Parse a basic type annotation that's a combination of variables
|
||||||
/// (which are lowercase and unqualified, e.g. `a` in `List a`),
|
/// (which are lowercase and unqualified, e.g. `a` in `List a`),
|
||||||
/// type applications (which are uppercase and optionally qualified, e.g.
|
/// type applications (which are uppercase and optionally qualified, e.g.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue