mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
Initial working version of proper try
keyword
This commit is contained in:
parent
a7168a4ad6
commit
eedade8e81
33 changed files with 1036 additions and 521 deletions
|
@ -26,7 +26,9 @@ use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError};
|
|||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::num::SingleQuoteBound;
|
||||
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, RedundantMark, VarStore, Variable};
|
||||
use roc_types::types::{Alias, Category, IndexOrField, LambdaSet, OptAbleVar, Type};
|
||||
use roc_types::types::{
|
||||
Alias, Category, EarlyReturnKind, IndexOrField, LambdaSet, OptAbleVar, Type,
|
||||
};
|
||||
use soa::Index;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::path::PathBuf;
|
||||
|
@ -328,6 +330,15 @@ pub enum Expr {
|
|||
symbol: Symbol,
|
||||
},
|
||||
|
||||
Try {
|
||||
result_expr: Box<Loc<Expr>>,
|
||||
result_var: Variable,
|
||||
return_var: Variable,
|
||||
ok_payload_var: Variable,
|
||||
err_payload_var: Variable,
|
||||
err_ext_var: Variable,
|
||||
},
|
||||
|
||||
Return {
|
||||
return_value: Box<Loc<Expr>>,
|
||||
return_var: Variable,
|
||||
|
@ -403,9 +414,10 @@ impl Expr {
|
|||
}
|
||||
Self::Expect { .. } => Category::Expect,
|
||||
Self::Crash { .. } => Category::Crash,
|
||||
Self::Return { .. } => Category::Return,
|
||||
Self::Return { .. } => Category::Return(EarlyReturnKind::Return),
|
||||
|
||||
Self::Dbg { .. } => Category::Expect,
|
||||
Self::Try { .. } => Category::TrySuccess,
|
||||
|
||||
// these nodes place no constraints on the expression's type
|
||||
Self::RuntimeError(..) => Category::Unknown,
|
||||
|
@ -429,7 +441,7 @@ impl Expr {
|
|||
| Self::ZeroArgumentTag { .. }
|
||||
| Self::OpaqueWrapFunction(_)
|
||||
| Self::RuntimeError(..) => false,
|
||||
Self::Return { .. } => true,
|
||||
Self::Return { .. } | Self::Try { .. } => true,
|
||||
Self::List { loc_elems, .. } => loc_elems
|
||||
.iter()
|
||||
.any(|elem| elem.value.contains_any_early_returns()),
|
||||
|
@ -545,7 +557,7 @@ pub struct ClosureData {
|
|||
pub closure_type: Variable,
|
||||
pub return_type: Variable,
|
||||
pub fx_type: Variable,
|
||||
pub early_returns: Vec<(Variable, Region)>,
|
||||
pub early_returns: Vec<(Variable, Region, EarlyReturnKind)>,
|
||||
pub name: Symbol,
|
||||
pub captured_symbols: Vec<(Symbol, Variable)>,
|
||||
pub recursive: Recursive,
|
||||
|
@ -1385,6 +1397,28 @@ pub fn canonicalize_expr<'a>(
|
|||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::LowLevelTry(loc_expr) => {
|
||||
let (loc_result_expr, output) =
|
||||
canonicalize_expr(env, var_store, scope, loc_expr.region, &loc_expr.value);
|
||||
|
||||
let return_var = var_store.fresh();
|
||||
|
||||
scope
|
||||
.early_returns
|
||||
.push((return_var, loc_expr.region, EarlyReturnKind::Try));
|
||||
|
||||
(
|
||||
Try {
|
||||
result_expr: Box::new(loc_result_expr),
|
||||
result_var: var_store.fresh(),
|
||||
return_var,
|
||||
ok_payload_var: var_store.fresh(),
|
||||
err_payload_var: var_store.fresh(),
|
||||
err_ext_var: var_store.fresh(),
|
||||
},
|
||||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::Return(return_expr, after_return) => {
|
||||
let mut output = Output::default();
|
||||
|
||||
|
@ -1409,7 +1443,9 @@ pub fn canonicalize_expr<'a>(
|
|||
|
||||
let return_var = var_store.fresh();
|
||||
|
||||
scope.early_returns.push((return_var, return_expr.region));
|
||||
scope
|
||||
.early_returns
|
||||
.push((return_var, return_expr.region, EarlyReturnKind::Return));
|
||||
|
||||
(
|
||||
Return {
|
||||
|
@ -2351,6 +2387,29 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
|
|||
}
|
||||
}
|
||||
|
||||
Try {
|
||||
result_expr,
|
||||
result_var,
|
||||
return_var,
|
||||
ok_payload_var,
|
||||
err_payload_var,
|
||||
err_ext_var,
|
||||
} => {
|
||||
let loc_result_expr = Loc {
|
||||
region: result_expr.region,
|
||||
value: inline_calls(var_store, result_expr.value),
|
||||
};
|
||||
|
||||
Try {
|
||||
result_expr: Box::new(loc_result_expr),
|
||||
result_var,
|
||||
return_var,
|
||||
ok_payload_var,
|
||||
err_payload_var,
|
||||
err_ext_var,
|
||||
}
|
||||
}
|
||||
|
||||
LetRec(defs, loc_expr, mark) => {
|
||||
let mut new_defs = Vec::with_capacity(defs.len());
|
||||
|
||||
|
@ -2645,6 +2704,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),
|
||||
// Newlines are disallowed inside interpolation, and these all require newlines
|
||||
ast::Expr::DbgStmt { .. }
|
||||
| ast::Expr::LowLevelDbg(_, _, _)
|
||||
|
@ -3401,7 +3461,7 @@ pub struct FunctionDef {
|
|||
pub closure_type: Variable,
|
||||
pub return_type: Variable,
|
||||
pub fx_type: Variable,
|
||||
pub early_returns: Vec<(Variable, Region)>,
|
||||
pub early_returns: Vec<(Variable, Region, EarlyReturnKind)>,
|
||||
pub captured_symbols: Vec<(Symbol, Variable)>,
|
||||
pub arguments: Vec<(Variable, AnnotatedMark, Loc<Pattern>)>,
|
||||
}
|
||||
|
@ -3543,6 +3603,9 @@ pub(crate) fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
|
|||
// Intentionally ignore the lookups in the nested `expect` condition itself,
|
||||
// because they couldn't possibly influence the outcome of this `expect`!
|
||||
}
|
||||
Expr::Try { result_expr, .. } => {
|
||||
stack.push(&result_expr.value);
|
||||
}
|
||||
Expr::Return { return_value, .. } => {
|
||||
stack.push(&return_value.value);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue