mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Implement new builder syntax alongside old one
This commit is contained in:
parent
1bcf30391b
commit
f415017c90
17 changed files with 1023 additions and 211 deletions
|
@ -438,7 +438,21 @@ pub enum Expr<'a> {
|
|||
Tuple(Collection<'a, &'a Loc<Expr<'a>>>),
|
||||
|
||||
// Record Builders
|
||||
RecordBuilder(Collection<'a, Loc<RecordBuilderField<'a>>>),
|
||||
/// Applicative record builders, e.g.
|
||||
/// build {
|
||||
/// foo: <- getData Foo,
|
||||
/// bar: <- getData Bar,
|
||||
/// }
|
||||
OldRecordBuilder(Collection<'a, Loc<OldRecordBuilderField<'a>>>),
|
||||
/// Mapper-based record builders, e.g.
|
||||
/// { Task.parallel <-
|
||||
/// foo: Task.getData Foo,
|
||||
/// bar: Task.getData Bar,
|
||||
/// }
|
||||
NewRecordBuilder {
|
||||
mapper: &'a Loc<Expr<'a>>,
|
||||
fields: Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>,
|
||||
},
|
||||
|
||||
// Lookups
|
||||
Var {
|
||||
|
@ -501,8 +515,11 @@ pub enum Expr<'a> {
|
|||
// Both operators were non-associative, e.g. (True == False == False).
|
||||
// We should tell the author to disambiguate by grouping them with parens.
|
||||
PrecedenceConflict(&'a PrecedenceConflict<'a>),
|
||||
MultipleRecordBuilders(&'a Loc<Expr<'a>>),
|
||||
UnappliedRecordBuilder(&'a Loc<Expr<'a>>),
|
||||
MultipleOldRecordBuilders(&'a Loc<Expr<'a>>),
|
||||
UnappliedOldRecordBuilder(&'a Loc<Expr<'a>>),
|
||||
EmptyNewRecordBuilder(&'a Loc<Expr<'a>>),
|
||||
SingleFieldNewRecordBuilder(&'a Loc<Expr<'a>>),
|
||||
OptionalFieldInNewRecordBuilder(&'a Loc<&'a str>, &'a Loc<Expr<'a>>),
|
||||
}
|
||||
|
||||
impl Expr<'_> {
|
||||
|
@ -615,9 +632,12 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
|||
.iter()
|
||||
.any(|field| is_assigned_value_suffixed(&field.value)),
|
||||
Expr::Tuple(items) => items.iter().any(|x| is_expr_suffixed(&x.value)),
|
||||
Expr::RecordBuilder(items) => items
|
||||
Expr::OldRecordBuilder(items) => items
|
||||
.iter()
|
||||
.any(|rbf| is_record_builder_field_suffixed(&rbf.value)),
|
||||
Expr::NewRecordBuilder { mapper: _, fields } => fields
|
||||
.iter()
|
||||
.any(|field| is_assigned_value_suffixed(&field.value)),
|
||||
Expr::Underscore(_) => false,
|
||||
Expr::Crash => false,
|
||||
Expr::Tag(_) => false,
|
||||
|
@ -637,8 +657,11 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
|||
Expr::MalformedClosure => false,
|
||||
Expr::MalformedSuffixed(_) => false,
|
||||
Expr::PrecedenceConflict(_) => false,
|
||||
Expr::MultipleRecordBuilders(_) => false,
|
||||
Expr::UnappliedRecordBuilder(_) => false,
|
||||
Expr::MultipleOldRecordBuilders(_) => false,
|
||||
Expr::UnappliedOldRecordBuilder(_) => false,
|
||||
Expr::EmptyNewRecordBuilder(_) => false,
|
||||
Expr::SingleFieldNewRecordBuilder(_) => false,
|
||||
Expr::OptionalFieldInNewRecordBuilder(_, _) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,14 +686,14 @@ fn is_assigned_value_suffixed<'a>(value: &AssignedField<'a, Expr<'a>>) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_record_builder_field_suffixed(field: &RecordBuilderField<'_>) -> bool {
|
||||
fn is_record_builder_field_suffixed(field: &OldRecordBuilderField<'_>) -> bool {
|
||||
match field {
|
||||
RecordBuilderField::Value(_, _, a) => is_expr_suffixed(&a.value),
|
||||
RecordBuilderField::ApplyValue(_, _, _, a) => is_expr_suffixed(&a.value),
|
||||
RecordBuilderField::LabelOnly(_) => false,
|
||||
RecordBuilderField::SpaceBefore(a, _) => is_record_builder_field_suffixed(a),
|
||||
RecordBuilderField::SpaceAfter(a, _) => is_record_builder_field_suffixed(a),
|
||||
RecordBuilderField::Malformed(_) => false,
|
||||
OldRecordBuilderField::Value(_, _, a) => is_expr_suffixed(&a.value),
|
||||
OldRecordBuilderField::ApplyValue(_, _, _, a) => is_expr_suffixed(&a.value),
|
||||
OldRecordBuilderField::LabelOnly(_) => false,
|
||||
OldRecordBuilderField::SpaceBefore(a, _) => is_record_builder_field_suffixed(a),
|
||||
OldRecordBuilderField::SpaceAfter(a, _) => is_record_builder_field_suffixed(a),
|
||||
OldRecordBuilderField::Malformed(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -840,10 +863,10 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
use AssignedField::*;
|
||||
|
||||
match current {
|
||||
RequiredValue(_, _, loc_val) => break expr_stack.push(&loc_val.value),
|
||||
OptionalValue(_, _, loc_val) => break expr_stack.push(&loc_val.value),
|
||||
SpaceBefore(next, _) => current = *next,
|
||||
SpaceAfter(next, _) => current = *next,
|
||||
RequiredValue(_, _, loc_val) | OptionalValue(_, _, loc_val) => {
|
||||
break expr_stack.push(&loc_val.value)
|
||||
}
|
||||
SpaceBefore(next, _) | SpaceAfter(next, _) => current = *next,
|
||||
LabelOnly(_) | Malformed(_) => break,
|
||||
}
|
||||
}
|
||||
|
@ -881,13 +904,13 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
expr_stack.push(&loc_expr.value);
|
||||
}
|
||||
}
|
||||
RecordBuilder(fields) => {
|
||||
OldRecordBuilder(fields) => {
|
||||
expr_stack.reserve(fields.len());
|
||||
for loc_record_builder_field in fields.items {
|
||||
let mut current_field = loc_record_builder_field.value;
|
||||
|
||||
loop {
|
||||
use RecordBuilderField::*;
|
||||
use OldRecordBuilderField::*;
|
||||
|
||||
match current_field {
|
||||
Value(_, _, loc_val) => break expr_stack.push(&loc_val.value),
|
||||
|
@ -901,6 +924,14 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
}
|
||||
}
|
||||
}
|
||||
NewRecordBuilder {
|
||||
mapper: map2,
|
||||
fields,
|
||||
} => {
|
||||
expr_stack.reserve(fields.len() + 1);
|
||||
expr_stack.push(&map2.value);
|
||||
push_stack_from_record_fields!(fields);
|
||||
}
|
||||
Closure(_, body) => expr_stack.push(&body.value),
|
||||
Backpassing(_, a, b) => {
|
||||
expr_stack.reserve(2);
|
||||
|
@ -965,9 +996,11 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
| SpaceAfter(expr, _)
|
||||
| ParensAround(expr) => expr_stack.push(expr),
|
||||
|
||||
MultipleRecordBuilders(loc_expr) | UnappliedRecordBuilder(loc_expr) => {
|
||||
expr_stack.push(&loc_expr.value)
|
||||
}
|
||||
MultipleOldRecordBuilders(loc_expr)
|
||||
| UnappliedOldRecordBuilder(loc_expr)
|
||||
| EmptyNewRecordBuilder(loc_expr)
|
||||
| SingleFieldNewRecordBuilder(loc_expr)
|
||||
| OptionalFieldInNewRecordBuilder(_, loc_expr) => expr_stack.push(&loc_expr.value),
|
||||
|
||||
Float(_)
|
||||
| Num(_)
|
||||
|
@ -1568,7 +1601,7 @@ impl<'a, Val> AssignedField<'a, Val> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum RecordBuilderField<'a> {
|
||||
pub enum OldRecordBuilderField<'a> {
|
||||
// A field with a value, e.g. `{ name: "blah" }`
|
||||
Value(Loc<&'a str>, &'a [CommentOrNewline<'a>], &'a Loc<Expr<'a>>),
|
||||
|
||||
|
@ -1584,8 +1617,8 @@ pub enum RecordBuilderField<'a> {
|
|||
LabelOnly(Loc<&'a str>),
|
||||
|
||||
// We preserve this for the formatter; canonicalization ignores it.
|
||||
SpaceBefore(&'a RecordBuilderField<'a>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a RecordBuilderField<'a>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceBefore(&'a OldRecordBuilderField<'a>, &'a [CommentOrNewline<'a>]),
|
||||
SpaceAfter(&'a OldRecordBuilderField<'a>, &'a [CommentOrNewline<'a>]),
|
||||
|
||||
/// A malformed assigned field, which will code gen to a runtime error
|
||||
Malformed(&'a str),
|
||||
|
@ -2099,12 +2132,12 @@ impl<'a, Val> Spaceable<'a> for AssignedField<'a, Val> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Spaceable<'a> for RecordBuilderField<'a> {
|
||||
impl<'a> Spaceable<'a> for OldRecordBuilderField<'a> {
|
||||
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
|
||||
RecordBuilderField::SpaceBefore(self, spaces)
|
||||
OldRecordBuilderField::SpaceBefore(self, spaces)
|
||||
}
|
||||
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
|
||||
RecordBuilderField::SpaceAfter(self, spaces)
|
||||
OldRecordBuilderField::SpaceAfter(self, spaces)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2403,7 +2436,8 @@ impl<'a> Malformed for Expr<'a> {
|
|||
Record(items) => items.is_malformed(),
|
||||
Tuple(items) => items.is_malformed(),
|
||||
|
||||
RecordBuilder(items) => items.is_malformed(),
|
||||
OldRecordBuilder(items) => items.is_malformed(),
|
||||
NewRecordBuilder { mapper: map2, fields } => map2.is_malformed() || fields.is_malformed(),
|
||||
|
||||
Closure(args, body) => args.iter().any(|arg| arg.is_malformed()) || body.is_malformed(),
|
||||
Defs(defs, body) => defs.is_malformed() || body.is_malformed(),
|
||||
|
@ -2425,8 +2459,11 @@ impl<'a> Malformed for Expr<'a> {
|
|||
MalformedClosure |
|
||||
MalformedSuffixed(..) |
|
||||
PrecedenceConflict(_) |
|
||||
MultipleRecordBuilders(_) |
|
||||
UnappliedRecordBuilder(_) => true,
|
||||
MultipleOldRecordBuilders(_) |
|
||||
UnappliedOldRecordBuilder(_) |
|
||||
EmptyNewRecordBuilder(_) |
|
||||
SingleFieldNewRecordBuilder(_) |
|
||||
OptionalFieldInNewRecordBuilder(_, _) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2503,15 +2540,15 @@ impl<'a, T: Malformed> Malformed for AssignedField<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Malformed for RecordBuilderField<'a> {
|
||||
impl<'a> Malformed for OldRecordBuilderField<'a> {
|
||||
fn is_malformed(&self) -> bool {
|
||||
match self {
|
||||
RecordBuilderField::Value(_, _, expr)
|
||||
| RecordBuilderField::ApplyValue(_, _, _, expr) => expr.is_malformed(),
|
||||
RecordBuilderField::LabelOnly(_) => false,
|
||||
RecordBuilderField::SpaceBefore(field, _)
|
||||
| RecordBuilderField::SpaceAfter(field, _) => field.is_malformed(),
|
||||
RecordBuilderField::Malformed(_) => true,
|
||||
OldRecordBuilderField::Value(_, _, expr)
|
||||
| OldRecordBuilderField::ApplyValue(_, _, _, expr) => expr.is_malformed(),
|
||||
OldRecordBuilderField::LabelOnly(_) => false,
|
||||
OldRecordBuilderField::SpaceBefore(field, _)
|
||||
| OldRecordBuilderField::SpaceAfter(field, _) => field.is_malformed(),
|
||||
OldRecordBuilderField::Malformed(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::ast::{
|
|||
is_expr_suffixed, is_top_level_suffixed, AssignedField, Collection, CommentOrNewline, Defs,
|
||||
Expr, ExtractSpaces, Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword,
|
||||
ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport,
|
||||
ModuleImport, ModuleImportParams, Pattern, RecordBuilderField, Spaceable, Spaced, Spaces,
|
||||
ModuleImport, ModuleImportParams, OldRecordBuilderField, Pattern, Spaceable, Spaced, Spaces,
|
||||
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
};
|
||||
use crate::blankspace::{
|
||||
|
@ -996,11 +996,21 @@ fn import_params<'a>() -> impl Parser<'a, ModuleImportParams<'a>, EImportParams<
|
|||
specialize_err(EImportParams::Record, record_help()),
|
||||
),
|
||||
|arena, state, _, (before, record): (_, RecordHelp<'a>)| {
|
||||
if let Some(update) = record.update {
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EImportParams::RecordUpdateFound(update.region),
|
||||
));
|
||||
if let Some(prefix) = record.prefix {
|
||||
match prefix {
|
||||
RecordHelpPrefix::Update(update) => {
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EImportParams::RecordUpdateFound(update.region),
|
||||
))
|
||||
}
|
||||
RecordHelpPrefix::Mapper(mapper) => {
|
||||
return Err((
|
||||
MadeProgress,
|
||||
EImportParams::RecordBuilderFound(mapper.region),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let params = record.fields.map_items_result(arena, |loc_field| {
|
||||
|
@ -2370,7 +2380,8 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
Expr::SpaceBefore(..)
|
||||
| Expr::SpaceAfter(..)
|
||||
| Expr::ParensAround(..)
|
||||
| Expr::RecordBuilder(..) => unreachable!(),
|
||||
| Expr::OldRecordBuilder(..)
|
||||
| Expr::NewRecordBuilder { .. } => unreachable!(),
|
||||
|
||||
Expr::Record(fields) => {
|
||||
let patterns = fields.map_items_result(arena, |loc_assigned_field| {
|
||||
|
@ -2417,8 +2428,11 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
| Expr::MalformedClosure
|
||||
| Expr::MalformedSuffixed(..)
|
||||
| Expr::PrecedenceConflict { .. }
|
||||
| Expr::MultipleRecordBuilders { .. }
|
||||
| Expr::UnappliedRecordBuilder { .. }
|
||||
| Expr::MultipleOldRecordBuilders { .. }
|
||||
| Expr::UnappliedOldRecordBuilder { .. }
|
||||
| Expr::EmptyNewRecordBuilder(_)
|
||||
| Expr::SingleFieldNewRecordBuilder(_)
|
||||
| Expr::OptionalFieldInNewRecordBuilder(_, _)
|
||||
| Expr::RecordUpdate { .. }
|
||||
| Expr::UnaryOp(_, _)
|
||||
| Expr::TaskAwaitBang(..)
|
||||
|
@ -3110,8 +3124,8 @@ impl<'a> RecordField<'a> {
|
|||
fn to_builder_field(
|
||||
self,
|
||||
arena: &'a Bump,
|
||||
) -> Result<RecordBuilderField<'a>, FoundOptionalValue> {
|
||||
use RecordBuilderField::*;
|
||||
) -> Result<OldRecordBuilderField<'a>, FoundOptionalValue> {
|
||||
use OldRecordBuilderField::*;
|
||||
|
||||
match self {
|
||||
RecordField::RequiredValue(loc_label, spaces, loc_expr) => {
|
||||
|
@ -3234,8 +3248,20 @@ fn record_updateable_identifier<'a>() -> impl Parser<'a, Expr<'a>, ERecord<'a>>
|
|||
)
|
||||
}
|
||||
|
||||
fn record_builder_mapper_identifier<'a>() -> impl Parser<'a, Expr<'a>, ERecord<'a>> {
|
||||
specialize_err(
|
||||
|_, pos| ERecord::BuilderMapper(pos),
|
||||
map_with_arena(parse_ident, ident_to_expr),
|
||||
)
|
||||
}
|
||||
|
||||
enum RecordHelpPrefix<'a> {
|
||||
Update(Loc<Expr<'a>>),
|
||||
Mapper(Loc<Expr<'a>>),
|
||||
}
|
||||
|
||||
struct RecordHelp<'a> {
|
||||
update: Option<Loc<Expr<'a>>>,
|
||||
prefix: Option<RecordHelpPrefix<'a>>,
|
||||
fields: Collection<'a, Loc<RecordField<'a>>>,
|
||||
}
|
||||
|
||||
|
@ -3245,16 +3271,28 @@ fn record_help<'a>() -> impl Parser<'a, RecordHelp<'a>, ERecord<'a>> {
|
|||
reset_min_indent(record!(RecordHelp {
|
||||
// You can optionally have an identifier followed by an '&' to
|
||||
// make this a record update, e.g. { Foo.user & username: "blah" }.
|
||||
update: optional(backtrackable(skip_second(
|
||||
spaces_around(
|
||||
// We wrap the ident in an Expr here,
|
||||
// so that we have a Spaceable value to work with,
|
||||
// and then in canonicalization verify that it's an Expr::Var
|
||||
// (and not e.g. an `Expr::Access`) and extract its string.
|
||||
loc(record_updateable_identifier()),
|
||||
prefix: optional(map_with_arena(
|
||||
either(
|
||||
backtrackable(skip_second(
|
||||
spaces_around(
|
||||
// We wrap the ident in an Expr here,
|
||||
// so that we have a Spaceable value to work with,
|
||||
// and then in canonicalization verify that it's an Expr::Var
|
||||
// (and not e.g. an `Expr::Access`) and extract its string.
|
||||
loc(record_updateable_identifier()),
|
||||
),
|
||||
byte(b'&', ERecord::Ampersand)
|
||||
)),
|
||||
backtrackable(skip_second(
|
||||
spaces_around(loc(record_builder_mapper_identifier()),),
|
||||
two_bytes(b'<', b'-', ERecord::Arrow),
|
||||
)),
|
||||
),
|
||||
byte(b'&', ERecord::Ampersand)
|
||||
))),
|
||||
|_arena, output| match output {
|
||||
Either::First(update) => RecordHelpPrefix::Update(update),
|
||||
Either::Second(mapper) => RecordHelpPrefix::Mapper(mapper),
|
||||
}
|
||||
)),
|
||||
fields: collection_inner(
|
||||
loc(record_field()),
|
||||
byte(b',', ERecord::End),
|
||||
|
@ -3273,16 +3311,21 @@ fn record_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
|||
record_field_access_chain(),
|
||||
),
|
||||
move |arena, state, _, (record, accessors)| {
|
||||
let expr_result = match record.update {
|
||||
Some(update) => record_update_help(arena, update, record.fields),
|
||||
let expr_result = match record.prefix {
|
||||
Some(RecordHelpPrefix::Update(update)) => {
|
||||
record_update_help(arena, update, record.fields)
|
||||
}
|
||||
Some(RecordHelpPrefix::Mapper(mapper)) => {
|
||||
new_record_builder_help(arena, mapper, record.fields)
|
||||
}
|
||||
None => {
|
||||
let is_record_builder = record
|
||||
let is_old_record_builder = record
|
||||
.fields
|
||||
.iter()
|
||||
.any(|field| field.value.is_apply_value());
|
||||
|
||||
if is_record_builder {
|
||||
record_builder_help(arena, record.fields)
|
||||
if is_old_record_builder {
|
||||
old_record_builder_help(arena, record.fields)
|
||||
} else {
|
||||
let fields = record.fields.map_items(arena, |loc_field| {
|
||||
loc_field.map(|field| field.to_assigned_field(arena).unwrap())
|
||||
|
@ -3316,7 +3359,7 @@ fn record_update_help<'a>(
|
|||
region: loc_field.region,
|
||||
value: builder_field,
|
||||
}),
|
||||
Err(FoundApplyValue) => Err(EExpr::RecordUpdateBuilder(loc_field.region)),
|
||||
Err(FoundApplyValue) => Err(EExpr::RecordUpdateAccumulator(loc_field.region)),
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3326,7 +3369,28 @@ fn record_update_help<'a>(
|
|||
})
|
||||
}
|
||||
|
||||
fn record_builder_help<'a>(
|
||||
fn new_record_builder_help<'a>(
|
||||
arena: &'a Bump,
|
||||
mapper: Loc<Expr<'a>>,
|
||||
fields: Collection<'a, Loc<RecordField<'a>>>,
|
||||
) -> Result<Expr<'a>, EExpr<'a>> {
|
||||
let result = fields.map_items_result(arena, |loc_field| {
|
||||
match loc_field.value.to_assigned_field(arena) {
|
||||
Ok(builder_field) => Ok(Loc {
|
||||
region: loc_field.region,
|
||||
value: builder_field,
|
||||
}),
|
||||
Err(FoundApplyValue) => Err(EExpr::RecordBuilderAccumulator(loc_field.region)),
|
||||
}
|
||||
});
|
||||
|
||||
result.map(|fields| Expr::NewRecordBuilder {
|
||||
mapper: &*arena.alloc(mapper),
|
||||
fields,
|
||||
})
|
||||
}
|
||||
|
||||
fn old_record_builder_help<'a>(
|
||||
arena: &'a Bump,
|
||||
fields: Collection<'a, Loc<RecordField<'a>>>,
|
||||
) -> Result<Expr<'a>, EExpr<'a>> {
|
||||
|
@ -3340,7 +3404,7 @@ fn record_builder_help<'a>(
|
|||
}
|
||||
});
|
||||
|
||||
result.map(Expr::RecordBuilder)
|
||||
result.map(Expr::OldRecordBuilder)
|
||||
}
|
||||
|
||||
fn apply_expr_access_chain<'a>(
|
||||
|
|
|
@ -370,7 +370,8 @@ pub enum EExpr<'a> {
|
|||
InParens(EInParens<'a>, Position),
|
||||
Record(ERecord<'a>, Position),
|
||||
OptionalValueInRecordBuilder(Region),
|
||||
RecordUpdateBuilder(Region),
|
||||
RecordUpdateAccumulator(Region),
|
||||
RecordBuilderAccumulator(Region),
|
||||
|
||||
// SingleQuote errors are folded into the EString
|
||||
Str(EString<'a>, Position),
|
||||
|
@ -422,6 +423,7 @@ pub enum ERecord<'a> {
|
|||
Open(Position),
|
||||
|
||||
Updateable(Position),
|
||||
BuilderMapper(Position),
|
||||
Field(Position),
|
||||
Colon(Position),
|
||||
QuestionMark(Position),
|
||||
|
@ -570,6 +572,7 @@ pub enum EImportParams<'a> {
|
|||
Indent(Position),
|
||||
Record(ERecord<'a>, Position),
|
||||
RecordUpdateFound(Region),
|
||||
RecordBuilderFound(Region),
|
||||
RecordApplyFound(Region),
|
||||
Space(BadInputError, Position),
|
||||
}
|
||||
|
@ -737,6 +740,7 @@ pub enum ETypeAbilityImpl<'a> {
|
|||
Space(BadInputError, Position),
|
||||
|
||||
Updateable(Position),
|
||||
BuilderMapper(Position),
|
||||
QuestionMark(Position),
|
||||
Ampersand(Position),
|
||||
Expr(&'a EExpr<'a>, Position),
|
||||
|
@ -754,6 +758,7 @@ impl<'a> From<ERecord<'a>> for ETypeAbilityImpl<'a> {
|
|||
ERecord::Arrow(p) => ETypeAbilityImpl::Arrow(p),
|
||||
ERecord::Space(s, p) => ETypeAbilityImpl::Space(s, p),
|
||||
ERecord::Updateable(p) => ETypeAbilityImpl::Updateable(p),
|
||||
ERecord::BuilderMapper(p) => ETypeAbilityImpl::BuilderMapper(p),
|
||||
ERecord::QuestionMark(p) => ETypeAbilityImpl::QuestionMark(p),
|
||||
ERecord::Ampersand(p) => ETypeAbilityImpl::Ampersand(p),
|
||||
ERecord::Expr(e, p) => ETypeAbilityImpl::Expr(e, p),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue