Skip to content

Commit

Permalink
Merge branch 'main' into dict-update-with-a-result
Browse files Browse the repository at this point in the history
  • Loading branch information
Anton-4 authored Sep 24, 2024
2 parents 9745e19 + 5f3a956 commit 1525ddd
Show file tree
Hide file tree
Showing 27 changed files with 209 additions and 2,407 deletions.
19 changes: 19 additions & 0 deletions crates/cli/tests/cli_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,25 @@ mod cli_run {
);
}

#[test]
#[cfg_attr(windows, ignore)]
fn module_params_multiline_pattern() {
test_roc_app(
"crates/cli/tests/module_params",
"multiline_params.roc",
&[],
&[],
&[],
indoc!(
r#"
hi
"#
),
UseValgrind::No,
TestCliCommands::Dev,
);
}

#[test]
#[cfg_attr(windows, ignore)]
fn transitive_expects() {
Expand Down
8 changes: 8 additions & 0 deletions crates/cli/tests/module_params/MultilineParams.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module {
sendHttpReq,
getEnvVar
} -> [hi]

hi : Str
hi =
"hi"
11 changes: 11 additions & 0 deletions crates/cli/tests/module_params/multiline_params.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
app [main] {
pf: platform "../fixtures/multi-dep-str/platform/main.roc",
}

import MultilineParams {
sendHttpReq: \_ -> crash "todo",
getEnvVar: \_ -> crash "todo",
}

main =
MultilineParams.hi
167 changes: 22 additions & 145 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 @@ -1226,17 +1187,7 @@ fn desugar_pattern<'a>(env: &mut Env<'a>, scope: &mut Scope, pattern: Pattern<'a
Apply(tag, desugared_arg_patterns.into_bump_slice())
}
RecordDestructure(field_patterns) => {
let mut allocated = Vec::with_capacity_in(field_patterns.len(), env.arena);
for field_pattern in field_patterns.iter() {
let value = desugar_pattern(env, scope, field_pattern.value);
allocated.push(Loc {
value,
region: field_pattern.region,
});
}
let field_patterns = field_patterns.replace_items(allocated.into_bump_slice());

RecordDestructure(field_patterns)
RecordDestructure(desugar_record_destructures(env, scope, field_patterns))
}
RequiredField(name, field_pattern) => {
RequiredField(name, desugar_loc_pattern(env, scope, field_pattern))
Expand Down Expand Up @@ -1274,6 +1225,23 @@ fn desugar_pattern<'a>(env: &mut Env<'a>, scope: &mut Scope, pattern: Pattern<'a
}
}

pub fn desugar_record_destructures<'a>(
env: &mut Env<'a>,
scope: &mut Scope,
field_patterns: Collection<'a, Loc<Pattern<'a>>>,
) -> Collection<'a, Loc<Pattern<'a>>> {
let mut allocated = Vec::with_capacity_in(field_patterns.len(), env.arena);
for field_pattern in field_patterns.iter() {
let value = desugar_pattern(env, scope, field_pattern.value);
allocated.push(Loc {
value,
region: field_pattern.region,
});
}

field_patterns.replace_items(allocated.into_bump_slice())
}

/// Desugars a `dbg expr` expression into a statement block that prints and returns the
/// value produced by `expr`. Essentially:
/// (
Expand Down Expand Up @@ -1383,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
6 changes: 5 additions & 1 deletion crates/compiler/can/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::path::Path;
use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl};
use crate::annotation::{canonicalize_annotation, AnnotationFor};
use crate::def::{canonicalize_defs, report_unused_imports, Def};
use crate::desugar::desugar_record_destructures;
use crate::env::Env;
use crate::expr::{
ClosureData, DbgLookup, Declarations, ExpectLookup, Expr, Output, PendingDerives,
Expand Down Expand Up @@ -326,13 +327,16 @@ pub fn canonicalize_module_defs<'a>(
before_arrow: _,
after_arrow: _,
}| {
let desugared_patterns =
desugar_record_destructures(&mut env, &mut scope, pattern.value);

let (destructs, _) = canonicalize_record_destructs(
&mut env,
var_store,
&mut scope,
&mut output,
PatternType::ModuleParams,
&pattern.value,
&desugared_patterns,
pattern.region,
PermitShadows(false),
);
Expand Down
5 changes: 4 additions & 1 deletion crates/compiler/can/src/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,10 @@ pub fn canonicalize_record_destructs<'a>(
}
};
}
_ => unreachable!("Any other pattern should have given a parse error"),
_ => unreachable!(
"Any other pattern should have given a parse error: {:?}",
loc_pattern.value
),
}
}

Expand Down
Loading

0 comments on commit 1525ddd

Please sign in to comment.