Skip to content

Commit

Permalink
Merge pull request #7110 from smores56/remove-old-record-builder
Browse files Browse the repository at this point in the history
Remove Old Record Builder Syntax
  • Loading branch information
smores56 committed Sep 21, 2024
2 parents 6c846a5 + 2ea6a5d commit 82036e2
Show file tree
Hide file tree
Showing 20 changed files with 57 additions and 2,280 deletions.
138 changes: 4 additions & 134 deletions crates/compiler/can/src/desugar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use roc_module::called_via::{BinOp, CalledVia};
use roc_module::ident::ModuleName;
use roc_parse::ast::Expr::{self, *};
use roc_parse::ast::{
AssignedField, Collection, Defs, ModuleImportParams, OldRecordBuilderField, Pattern,
StrLiteral, StrSegment, TypeAnnotation, ValueDef, WhenBranch,
AssignedField, Collection, Defs, ModuleImportParams, Pattern, StrLiteral, StrSegment,
TypeAnnotation, ValueDef, WhenBranch,
};
use roc_problem::can::Problem;
use roc_region::all::{Loc, Region};
Expand Down Expand Up @@ -321,8 +321,6 @@ pub fn desugar_expr<'a>(
| MalformedClosure
| MalformedSuffixed(..)
| PrecedenceConflict { .. }
| MultipleOldRecordBuilders(_)
| UnappliedOldRecordBuilder(_)
| EmptyRecordBuilder(_)
| SingleFieldRecordBuilder(_)
| OptionalFieldInRecordBuilder { .. }
Expand Down Expand Up @@ -555,10 +553,6 @@ pub fn desugar_expr<'a>(
}
}
}
OldRecordBuilder(_) => env.arena.alloc(Loc {
value: UnappliedOldRecordBuilder(loc_expr),
region: loc_expr.region,
}),
RecordBuilder { mapper, fields } => {
// NOTE the `mapper` is always a `Var { .. }`, we only desugar it to get rid of
// any spaces before/after
Expand Down Expand Up @@ -853,25 +847,11 @@ pub fn desugar_expr<'a>(
}
Apply(loc_fn, loc_args, called_via) => {
let mut desugared_args = Vec::with_capacity_in(loc_args.len(), env.arena);
let mut builder_apply_exprs = None;

for loc_arg in loc_args.iter() {
let mut current = loc_arg.value;
let arg = loop {
match current {
OldRecordBuilder(fields) => {
if builder_apply_exprs.is_some() {
return env.arena.alloc(Loc {
value: MultipleOldRecordBuilders(loc_expr),
region: loc_expr.region,
});
}

let builder_arg = old_record_builder_arg(env, loc_arg.region, fields);
builder_apply_exprs = Some(builder_arg.apply_exprs);

break builder_arg.closure;
}
SpaceBefore(expr, _) | SpaceAfter(expr, _) => {
current = *expr;
}
Expand All @@ -884,33 +864,14 @@ pub fn desugar_expr<'a>(

let desugared_args = desugared_args.into_bump_slice();

let mut apply: &Loc<Expr> = env.arena.alloc(Loc {
env.arena.alloc(Loc {
value: Apply(
desugar_expr(env, scope, loc_fn),
desugared_args,
*called_via,
),
region: loc_expr.region,
});

match builder_apply_exprs {
None => {}

Some(apply_exprs) => {
for expr in apply_exprs {
let desugared_expr = desugar_expr(env, scope, expr);

let args = std::slice::from_ref(env.arena.alloc(apply));

apply = env.arena.alloc(Loc {
value: Apply(desugared_expr, args, CalledVia::OldRecordBuilder),
region: loc_expr.region,
});
}
}
}

apply
})
}
When(loc_cond_expr, branches) => {
let loc_desugared_cond = &*env.arena.alloc(desugar_expr(env, scope, loc_cond_expr));
Expand Down Expand Up @@ -1390,97 +1351,6 @@ fn desugar_dbg_stmt<'a>(
))
}

struct OldRecordBuilderArg<'a> {
closure: &'a Loc<Expr<'a>>,
apply_exprs: Vec<'a, &'a Loc<Expr<'a>>>,
}

fn old_record_builder_arg<'a>(
env: &mut Env<'a>,
region: Region,
fields: Collection<'a, Loc<OldRecordBuilderField<'a>>>,
) -> OldRecordBuilderArg<'a> {
let mut record_fields = Vec::with_capacity_in(fields.len(), env.arena);
let mut apply_exprs = Vec::with_capacity_in(fields.len(), env.arena);
let mut apply_field_names = Vec::with_capacity_in(fields.len(), env.arena);

// Build the record that the closure will return and gather apply expressions

for field in fields.iter() {
let mut current = field.value;

let new_field = loop {
match current {
OldRecordBuilderField::Value(label, spaces, expr) => {
break AssignedField::RequiredValue(label, spaces, expr)
}
OldRecordBuilderField::ApplyValue(label, _, _, expr) => {
apply_field_names.push(label);
apply_exprs.push(expr);

let var = env.arena.alloc(Loc {
region: label.region,
value: Expr::Var {
module_name: "",
ident: env.arena.alloc("#".to_owned() + label.value),
},
});

break AssignedField::RequiredValue(label, &[], var);
}
OldRecordBuilderField::LabelOnly(label) => break AssignedField::LabelOnly(label),
OldRecordBuilderField::SpaceBefore(sub_field, _) => {
current = *sub_field;
}
OldRecordBuilderField::SpaceAfter(sub_field, _) => {
current = *sub_field;
}
OldRecordBuilderField::Malformed(malformed) => {
break AssignedField::Malformed(malformed)
}
}
};

record_fields.push(Loc {
value: new_field,
region: field.region,
});
}

let record_fields = fields.replace_items(record_fields.into_bump_slice());

let mut body = env.arena.alloc(Loc {
value: Record(record_fields),
region,
});

// Construct the builder's closure
//
// { x: #x, y: #y, z: 3 }
// \#y -> { x: #x, y: #y, z: 3 }
// \#x -> \#y -> { x: #x, y: #y, z: 3 }

for label in apply_field_names.iter().rev() {
let name = env.arena.alloc("#".to_owned() + label.value);
let ident = roc_parse::ast::Pattern::Identifier { ident: name };

let arg_pattern = env.arena.alloc(Loc {
value: ident,
region: label.region,
});

body = env.arena.alloc(Loc {
value: Closure(std::slice::from_ref(arg_pattern), body),
region,
});
}

OldRecordBuilderArg {
closure: body,
apply_exprs,
}
}

// TODO move this desugaring to canonicalization, so we can use Symbols instead of strings
#[inline(always)]
fn binop_to_function(binop: BinOp) -> (&'static str, &'static str) {
Expand Down
44 changes: 1 addition & 43 deletions crates/compiler/can/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,11 +1013,8 @@ pub fn canonicalize_expr<'a>(
can_defs_with_return(env, var_store, inner_scope, env.arena.alloc(defs), loc_ret)
})
}
ast::Expr::OldRecordBuilder(_) => {
internal_error!("Old record builder should have been desugared by now")
}
ast::Expr::RecordBuilder { .. } => {
internal_error!("New record builder should have been desugared by now")
internal_error!("Record builder should have been desugared by now")
}
ast::Expr::Backpassing(_, _, _) => {
internal_error!("Backpassing should have been desugared by now")
Expand Down Expand Up @@ -1356,22 +1353,6 @@ pub fn canonicalize_expr<'a>(
use roc_problem::can::RuntimeError::*;
(RuntimeError(MalformedSuffixed(region)), Output::default())
}
ast::Expr::MultipleOldRecordBuilders(sub_expr) => {
use roc_problem::can::RuntimeError::*;

let problem = MultipleOldRecordBuilders(sub_expr.region);
env.problem(Problem::RuntimeError(problem.clone()));

(RuntimeError(problem), Output::default())
}
ast::Expr::UnappliedOldRecordBuilder(sub_expr) => {
use roc_problem::can::RuntimeError::*;

let problem = UnappliedOldRecordBuilder(sub_expr.region);
env.problem(Problem::RuntimeError(problem.clone()));

(RuntimeError(problem), Output::default())
}
ast::Expr::EmptyRecordBuilder(sub_expr) => {
use roc_problem::can::RuntimeError::*;

Expand Down Expand Up @@ -2552,8 +2533,6 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
.iter()
.all(|loc_field| is_valid_interpolation(&loc_field.value)),
ast::Expr::MalformedSuffixed(loc_expr)
| ast::Expr::MultipleOldRecordBuilders(loc_expr)
| ast::Expr::UnappliedOldRecordBuilder(loc_expr)
| ast::Expr::EmptyRecordBuilder(loc_expr)
| ast::Expr::SingleFieldRecordBuilder(loc_expr)
| ast::Expr::OptionalFieldInRecordBuilder(_, loc_expr)
Expand Down Expand Up @@ -2603,27 +2582,6 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::AssignedField::SpaceAfter(_, _) => false,
})
}
ast::Expr::OldRecordBuilder(fields) => {
fields.iter().all(|loc_field| match loc_field.value {
ast::OldRecordBuilderField::Value(_label, comments, loc_expr) => {
comments.is_empty() && is_valid_interpolation(&loc_expr.value)
}
ast::OldRecordBuilderField::ApplyValue(
_label,
comments_before,
comments_after,
loc_expr,
) => {
comments_before.is_empty()
&& comments_after.is_empty()
&& is_valid_interpolation(&loc_expr.value)
}
ast::OldRecordBuilderField::Malformed(_)
| ast::OldRecordBuilderField::LabelOnly(_) => true,
ast::OldRecordBuilderField::SpaceBefore(_, _)
| ast::OldRecordBuilderField::SpaceAfter(_, _) => false,
})
}
ast::Expr::RecordBuilder { mapper, fields } => {
is_valid_interpolation(&mapper.value)
&& fields.iter().all(|loc_field| match loc_field.value {
Expand Down
Loading

0 comments on commit 82036e2

Please sign in to comment.