mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Use new try impl for ? operator
This commit is contained in:
parent
193c23bac8
commit
de626102c8
20 changed files with 429 additions and 110 deletions
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
|||
use crate::abilities::SpecializationId;
|
||||
use crate::exhaustive::{ExhaustiveContext, SketchedRows};
|
||||
use crate::expected::{Expected, PExpected};
|
||||
use crate::expr::TryKind;
|
||||
use roc_collections::soa::{index_push_new, slice_extend_new};
|
||||
use roc_module::ident::{IdentSuffix, TagName};
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
|
@ -643,12 +644,14 @@ impl Constraints {
|
|||
ok_payload_var: Variable,
|
||||
err_payload_var: Variable,
|
||||
region: Region,
|
||||
kind: TryKind,
|
||||
) -> Constraint {
|
||||
let constraint = TryTargetConstraint {
|
||||
target_type_index: result_type_index,
|
||||
ok_payload_var,
|
||||
err_payload_var,
|
||||
region,
|
||||
kind,
|
||||
};
|
||||
|
||||
let constraint_index = index_push_new(&mut self.try_target_constraints, constraint);
|
||||
|
@ -939,6 +942,7 @@ pub struct TryTargetConstraint {
|
|||
pub ok_payload_var: Variable,
|
||||
pub err_payload_var: Variable,
|
||||
pub region: Region,
|
||||
pub kind: TryKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
|
@ -725,6 +725,7 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
ok_payload_var,
|
||||
err_payload_var,
|
||||
err_ext_var,
|
||||
kind,
|
||||
} => Try {
|
||||
result_expr: Box::new(result_expr.map(|e| go_help!(e))),
|
||||
result_var: sub!(*result_var),
|
||||
|
@ -732,6 +733,7 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
ok_payload_var: sub!(*ok_payload_var),
|
||||
err_payload_var: sub!(*err_payload_var),
|
||||
err_ext_var: sub!(*err_ext_var),
|
||||
kind: *kind,
|
||||
},
|
||||
|
||||
RuntimeError(err) => RuntimeError(err.clone()),
|
||||
|
|
|
@ -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::{
|
||||
is_expr_suffixed, AssignedField, Collection, Defs, ModuleImportParams, Pattern, StrLiteral,
|
||||
StrSegment, TypeAnnotation, ValueDef, WhenBranch,
|
||||
is_expr_suffixed, AssignedField, Collection, Defs, ModuleImportParams, Pattern, ResultTryKind,
|
||||
StrLiteral, StrSegment, TryTarget, TypeAnnotation, ValueDef, WhenBranch,
|
||||
};
|
||||
use roc_problem::can::Problem;
|
||||
use roc_region::all::{Loc, Region};
|
||||
|
@ -44,7 +44,10 @@ fn new_op_call_expr<'a>(
|
|||
match right_without_spaces {
|
||||
Try => {
|
||||
let desugared_left = desugar_expr(env, scope, left);
|
||||
return Loc::at(region, Expr::LowLevelTry(desugared_left));
|
||||
return Loc::at(
|
||||
region,
|
||||
Expr::LowLevelTry(desugared_left, ResultTryKind::KeywordPrefix),
|
||||
);
|
||||
}
|
||||
Apply(&Loc { value: Try, .. }, arguments, _called_via) => {
|
||||
let try_fn = desugar_expr(env, scope, arguments.first().unwrap());
|
||||
|
@ -60,10 +63,71 @@ fn new_op_call_expr<'a>(
|
|||
|
||||
return Loc::at(
|
||||
region,
|
||||
Expr::LowLevelTry(env.arena.alloc(Loc::at(
|
||||
region,
|
||||
Expr::Apply(try_fn, args.into_bump_slice(), CalledVia::Try),
|
||||
))),
|
||||
Expr::LowLevelTry(
|
||||
env.arena.alloc(Loc::at(
|
||||
region,
|
||||
Expr::Apply(try_fn, args.into_bump_slice(), CalledVia::Try),
|
||||
)),
|
||||
ResultTryKind::KeywordPrefix,
|
||||
),
|
||||
);
|
||||
}
|
||||
TrySuffix {
|
||||
target: TryTarget::Result,
|
||||
expr: fn_expr,
|
||||
} => {
|
||||
let loc_fn = env.arena.alloc(Loc::at(right.region, **fn_expr));
|
||||
let function = desugar_expr(env, scope, loc_fn);
|
||||
|
||||
return Loc::at(
|
||||
region,
|
||||
LowLevelTry(
|
||||
env.arena.alloc(Loc::at(
|
||||
region,
|
||||
Expr::Apply(
|
||||
function,
|
||||
env.arena.alloc([desugar_expr(env, scope, left)]),
|
||||
CalledVia::Try,
|
||||
),
|
||||
)),
|
||||
ResultTryKind::OperatorSuffix,
|
||||
),
|
||||
);
|
||||
}
|
||||
Apply(
|
||||
&Loc {
|
||||
value:
|
||||
TrySuffix {
|
||||
target: TryTarget::Result,
|
||||
expr: fn_expr,
|
||||
},
|
||||
region: fn_region,
|
||||
},
|
||||
loc_args,
|
||||
_called_via,
|
||||
) => {
|
||||
let loc_fn = env.arena.alloc(Loc::at(fn_region, *fn_expr));
|
||||
let function = desugar_expr(env, scope, loc_fn);
|
||||
|
||||
let mut desugared_args = Vec::with_capacity_in(loc_args.len() + 1, env.arena);
|
||||
desugared_args.push(desugar_expr(env, scope, left));
|
||||
for loc_arg in &loc_args[..] {
|
||||
desugared_args.push(desugar_expr(env, scope, loc_arg));
|
||||
}
|
||||
|
||||
return Loc::at(
|
||||
region,
|
||||
LowLevelTry(
|
||||
env.arena.alloc(Loc::at(
|
||||
region,
|
||||
Expr::Apply(
|
||||
function,
|
||||
desugared_args.into_bump_slice(),
|
||||
CalledVia::Try,
|
||||
),
|
||||
)),
|
||||
ResultTryKind::OperatorSuffix,
|
||||
),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -456,23 +520,32 @@ pub fn desugar_expr<'a>(
|
|||
|
||||
env.arena.alloc(Loc { region, value })
|
||||
}
|
||||
// desugar the sub_expression, but leave the TrySuffix as this will
|
||||
// be unwrapped later in desugar_value_def_suffixed
|
||||
TrySuffix {
|
||||
expr: sub_expr,
|
||||
target,
|
||||
} => {
|
||||
let intermediate = env.arena.alloc(Loc::at(loc_expr.region, **sub_expr));
|
||||
let new_sub_loc_expr = desugar_expr(env, scope, intermediate);
|
||||
let new_sub_expr = env.arena.alloc(new_sub_loc_expr.value);
|
||||
|
||||
env.arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
TrySuffix {
|
||||
expr: new_sub_expr,
|
||||
target: *target,
|
||||
},
|
||||
))
|
||||
match target {
|
||||
TryTarget::Result => env.arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
LowLevelTry(new_sub_loc_expr, ResultTryKind::OperatorSuffix),
|
||||
)),
|
||||
TryTarget::Task => {
|
||||
let new_sub_expr = env.arena.alloc(new_sub_loc_expr.value);
|
||||
|
||||
// desugar the sub_expression, but leave the TrySuffix as this will
|
||||
// be unwrapped later in desugar_value_def_suffixed
|
||||
env.arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
TrySuffix {
|
||||
expr: new_sub_expr,
|
||||
target: *target,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
RecordAccess(sub_expr, paths) => {
|
||||
let region = loc_expr.region;
|
||||
|
@ -965,8 +1038,43 @@ pub fn desugar_expr<'a>(
|
|||
))
|
||||
};
|
||||
|
||||
env.arena
|
||||
.alloc(Loc::at(loc_expr.region, Expr::LowLevelTry(result_expr)))
|
||||
env.arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::LowLevelTry(result_expr, ResultTryKind::KeywordPrefix),
|
||||
))
|
||||
}
|
||||
Apply(
|
||||
Loc {
|
||||
value:
|
||||
TrySuffix {
|
||||
target: TryTarget::Result,
|
||||
expr: fn_expr,
|
||||
},
|
||||
region: fn_region,
|
||||
},
|
||||
loc_args,
|
||||
_called_via,
|
||||
) => {
|
||||
let loc_fn = env.arena.alloc(Loc::at(*fn_region, **fn_expr));
|
||||
let function = desugar_expr(env, scope, loc_fn);
|
||||
|
||||
let mut desugared_args = Vec::with_capacity_in(loc_args.len(), env.arena);
|
||||
for loc_arg in &loc_args[..] {
|
||||
desugared_args.push(desugar_expr(env, scope, loc_arg));
|
||||
}
|
||||
|
||||
let args_region =
|
||||
Region::span_across(&loc_args[0].region, &loc_args[loc_args.len() - 1].region);
|
||||
|
||||
let result_expr = env.arena.alloc(Loc::at(
|
||||
args_region,
|
||||
Expr::Apply(function, desugared_args.into_bump_slice(), CalledVia::Try),
|
||||
));
|
||||
|
||||
env.arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
Expr::LowLevelTry(result_expr, ResultTryKind::OperatorSuffix),
|
||||
))
|
||||
}
|
||||
Apply(loc_fn, loc_args, called_via) => {
|
||||
let mut desugared_args = Vec::with_capacity_in(loc_args.len(), env.arena);
|
||||
|
@ -1138,7 +1246,7 @@ pub fn desugar_expr<'a>(
|
|||
}
|
||||
|
||||
// note these only exist after desugaring
|
||||
LowLevelDbg(_, _, _) | LowLevelTry(_) => loc_expr,
|
||||
LowLevelDbg(_, _, _) | LowLevelTry(_, _) => loc_expr,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use roc_module::called_via::CalledVia;
|
|||
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentId, ModuleId, Symbol};
|
||||
use roc_parse::ast::{self, Defs, PrecedenceConflict, StrLiteral};
|
||||
use roc_parse::ast::{self, Defs, PrecedenceConflict, ResultTryKind, StrLiteral};
|
||||
use roc_parse::ident::Accessor;
|
||||
use roc_parse::pattern::PatternType::*;
|
||||
use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError};
|
||||
|
@ -337,6 +337,7 @@ pub enum Expr {
|
|||
ok_payload_var: Variable,
|
||||
err_payload_var: Variable,
|
||||
err_ext_var: Variable,
|
||||
kind: TryKind,
|
||||
},
|
||||
|
||||
Return {
|
||||
|
@ -348,6 +349,12 @@ pub enum Expr {
|
|||
RuntimeError(RuntimeError),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum TryKind {
|
||||
KeywordPrefix,
|
||||
OperatorSuffix,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct ExpectLookup {
|
||||
pub symbol: Symbol,
|
||||
|
@ -1397,7 +1404,7 @@ pub fn canonicalize_expr<'a>(
|
|||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::LowLevelTry(loc_expr) => {
|
||||
ast::Expr::LowLevelTry(loc_expr, kind) => {
|
||||
let (loc_result_expr, output) =
|
||||
canonicalize_expr(env, var_store, scope, loc_expr.region, &loc_expr.value);
|
||||
|
||||
|
@ -1415,6 +1422,10 @@ pub fn canonicalize_expr<'a>(
|
|||
ok_payload_var: var_store.fresh(),
|
||||
err_payload_var: var_store.fresh(),
|
||||
err_ext_var: var_store.fresh(),
|
||||
kind: match kind {
|
||||
ResultTryKind::KeywordPrefix => TryKind::KeywordPrefix,
|
||||
ResultTryKind::OperatorSuffix => TryKind::OperatorSuffix,
|
||||
},
|
||||
},
|
||||
output,
|
||||
)
|
||||
|
@ -2394,6 +2405,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
ok_payload_var,
|
||||
err_payload_var,
|
||||
err_ext_var,
|
||||
kind,
|
||||
} => {
|
||||
let loc_result_expr = Loc {
|
||||
region: result_expr.region,
|
||||
|
@ -2407,6 +2419,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
ok_payload_var,
|
||||
err_payload_var,
|
||||
err_ext_var,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2704,7 +2717,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
| ast::Expr::MalformedIdent(_, _)
|
||||
| ast::Expr::Tag(_)
|
||||
| ast::Expr::OpaqueRef(_) => true,
|
||||
ast::Expr::LowLevelTry(loc_expr) => is_valid_interpolation(&loc_expr.value),
|
||||
ast::Expr::LowLevelTry(loc_expr, _) => is_valid_interpolation(&loc_expr.value),
|
||||
// Newlines are disallowed inside interpolation, and these all require newlines
|
||||
ast::Expr::DbgStmt { .. }
|
||||
| ast::Expr::LowLevelDbg(_, _, _)
|
||||
|
|
|
@ -407,6 +407,7 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
|
|||
ok_payload_var: _,
|
||||
err_payload_var: _,
|
||||
err_ext_var: _,
|
||||
kind: _,
|
||||
} => {
|
||||
visitor.visit_expr(&result_expr.value, result_expr.region, *result_var);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue