fn typecheck_opt(
        &mut self,
        mut expr: &mut SpannedExpr<Symbol>,
        expected_type: Option<&ArcType>,
    ) -> ArcType {
        fn moving<T>(t: T) -> T {
            t
        }
        // How many scopes that have been entered in this "tailcall" loop
        let mut scope_count = 0;
        let returned_type;
        let expected_type = expected_type.map(|t| self.new_skolem_scope(&t));
        let mut expected_type = expected_type.as_ref();
        loop {
            match self.typecheck_(expr, &mut expected_type) {
                Ok(tailcall) => {
                    match tailcall {
                        TailCall::TailCall => {
                            // Call typecheck_ again with the next expression
                            expr = match moving(expr).value {
                                Expr::LetBindings(_, ref mut new_expr)
                                | Expr::TypeBindings(_, ref mut new_expr)
                                | Expr::Do(Do {
                                    body: ref mut new_expr,
                                    ..
                                }) => new_expr,
                                _ => ice!("Only Let and Type expressions can tailcall"),
                            };
                            scope_count += 1;
                        }
                        TailCall::TypeImplicit(typ, args) => {
                            if !args.is_empty() {
                                match expr.value {
                                    Expr::App {
                                        ref mut implicit_args,
                                        ..
                                    } => {
                                        if implicit_args.is_empty() {
                                            *implicit_args = args;
                                        } else {
                                            implicit_args.extend(args);
                                        }
                                    }
                                    _ => {
                                        let dummy = Expr::Literal(Literal::Int(0));
                                        let func = mem::replace(&mut expr.value, dummy);
                                        expr.value = Expr::App {
                                            func: Box::new(pos::spanned(expr.span, func)),
                                            implicit_args: args,
                                            args: vec![],
                                        }
                                    }
                                }
                            }

                            returned_type = match expected_type {
                                Some(expected_type) => {
                                    self.subsumes_expr(expr.span, &typ, expected_type.clone(), expr)
                                }
                                None => typ,
                            };
                            break;
                        }
                        TailCall::Type(typ) => {
                            returned_type = match expected_type {
                                Some(expected_type) => {
                                    self.subsumes_expr(expr.span, &typ, expected_type.clone(), expr)
                                }
                                None => typ,
                            };
                            break;
                        }
                    }
                }
                Err(err) => {
                    returned_type = self.type_cache.error();
                    self.errors.push(Spanned {
                        span: expr_check_span(expr),
                        value: err.into(),
                    });
                    break;
                }
            }
        }
        for _ in 0..scope_count {
            self.exit_scope();
        }
        returned_type
    }
/// Main typechecking function. Returns the type of the expression if typechecking was
/// successful
Main typechecking function. Returns the type of the expression if typechecking was
successful
Main typechecking function . Returns the type of the expression if typechecking was successful
fn typecheck_opt(
        &mut self,
        mut expr: &mut SpannedExpr<Symbol>,
        expected_type: Option<&ArcType>,
    ) -> ArcType {
        fn moving<T>(t: T) -> T {
            t
        }
        // How many scopes that have been entered in this "tailcall" loop
        let mut scope_count = 0;
        let returned_type;
        let expected_type = expected_type.map(|t| self.new_skolem_scope(&t));
        let mut expected_type = expected_type.as_ref();
        loop {
            match self.typecheck_(expr, &mut expected_type) {
                Ok(tailcall) => {
                    match tailcall {
                        TailCall::TailCall => {
                            // Call typecheck_ again with the next expression
                            expr = match moving(expr).value {
                                Expr::LetBindings(_, ref mut new_expr)
                                | Expr::TypeBindings(_, ref mut new_expr)
                                | Expr::Do(Do {
                                    body: ref mut new_expr,
                                    ..
                                }) => new_expr,
                                _ => ice!("Only Let and Type expressions can tailcall"),
                            };
                            scope_count += 1;
                        }
                        TailCall::TypeImplicit(typ, args) => {
                            if !args.is_empty() {
                                match expr.value {
                                    Expr::App {
                                        ref mut implicit_args,
                                        ..
                                    } => {
                                        if implicit_args.is_empty() {
                                            *implicit_args = args;
                                        } else {
                                            implicit_args.extend(args);
                                        }
                                    }
                                    _ => {
                                        let dummy = Expr::Literal(Literal::Int(0));
                                        let func = mem::replace(&mut expr.value, dummy);
                                        expr.value = Expr::App {
                                            func: Box::new(pos::spanned(expr.span, func)),
                                            implicit_args: args,
                                            args: vec![],
                                        }
                                    }
                                }
                            }
                            returned_type = match expected_type {
                                Some(expected_type) => {
                                    self.subsumes_expr(expr.span, &typ, expected_type.clone(), expr)
                                }
                                None => typ,
                            };
                            break;
                        }
                        TailCall::Type(typ) => {
                            returned_type = match expected_type {
                                Some(expected_type) => {
                                    self.subsumes_expr(expr.span, &typ, expected_type.clone(), expr)
                                }
                                None => typ,
                            };
                            break;
                        }
                    }
                }
                Err(err) => {
                    returned_type = self.type_cache.error();
                    self.errors.push(Spanned {
                        span: expr_check_span(expr),
                        value: err.into(),
                    });
                    break;
                }
            }
        }
        for _ in 0..scope_count {
            self.exit_scope();
        }
        returned_type
    }
fn typecheck_opt ( & mut self , mut expr : & mut SpannedExpr < Symbol > , expected_type : Option < & ArcType > , ) -> ArcType { fn moving < T > ( t : T ) -> T { t } // How many scopes that have been entered in this "tailcall" loop let mut scope_count = 0 ; let returned_type ; let expected_type = expected_type . map ( | t | self . new_skolem_scope ( & t ) ) ; let mut expected_type = expected_type . as_ref ( ) ; loop { match self . typecheck_ ( expr , & mut expected_type ) { Ok ( tailcall ) => { match tailcall { TailCall :: TailCall => { // Call typecheck_ again with the next expression expr = match moving ( expr ) . value { Expr :: LetBindings ( _ , ref mut new_expr ) | Expr :: TypeBindings ( _ , ref mut new_expr ) | Expr :: Do ( Do { body : ref mut new_expr , .. } ) => new_expr , _ => ice ! ( " " ) , } ; scope_count += 1 ; } TailCall :: TypeImplicit ( typ , args ) => { if ! args . is_empty ( ) { match expr . value { Expr :: App { ref mut implicit_args , .. } => { if implicit_args . is_empty ( ) { * implicit_args = args ; } else { implicit_args . extend ( args ) ; } } _ => { let dummy = Expr :: Literal ( Literal :: Int ( 0 ) ) ; let func = mem :: replace ( & mut expr . value , dummy ) ; expr . value = Expr :: App { func : Box :: new ( pos :: spanned ( expr . span , func ) ) , implicit_args : args , args : vec ! [ ] , } } } } returned_type = match expected_type { Some ( expected_type ) => { self . subsumes_expr ( expr . span , & typ , expected_type . clone ( ) , expr ) } None => typ , } ; break ; } TailCall :: Type ( typ ) => { returned_type = match expected_type { Some ( expected_type ) => { self . subsumes_expr ( expr . span , & typ , expected_type . clone ( ) , expr ) } None => typ , } ; break ; } } } Err ( err ) => { returned_type = self . type_cache . error ( ) ; self . errors . push ( Spanned { span : expr_check_span ( expr ) , value : err . into ( ) , } ) ; break ; } } } for _ in 0 .. scope_count { self . exit_scope ( ) ; } returned_type }
Main typechecking function.
Main typechecking function .
&mut self
expr
&mut SpannedExpr<Symbol>
expected_type
Option<&ArcType>