fn translate_exp(&mut self, exp: &EA::Exp, expected_type: &Type) -> Exp {
        let loc = self.to_loc(&exp.loc);
        let make_value = |et: &mut ExpTranslator, val: Value, ty: Type| {
            let rty = et.check_type(&loc, &ty, expected_type, "in expression");
            let id = et.new_node_id_with_type_loc(&rty, &loc);
            Exp::Value(id, val)
        };
        match &exp.value {
            EA::Exp_::Value(v) => {
                if let Some((v, ty)) = self.translate_value(v) {
                    make_value(self, v, ty)
                } else {
                    self.new_error_exp()
                }
            }
            EA::Exp_::InferredNum(x) => {
                // We don't really need to infer type, because all ints are exchangeable.
                make_value(
                    self,
                    Value::Number(BigInt::from_u128(*x).unwrap()),
                    Type::new_prim(PrimitiveType::U128),
                )
            }
            EA::Exp_::Name(maccess, type_params) => {
                self.translate_name(&loc, maccess, type_params.as_deref(), expected_type)
            }
            EA::Exp_::Call(maccess, type_params, args) => {
                // Need to make a &[&Exp] out of args.
                let args = args.value.iter().map(|e| e).collect_vec();
                self.translate_fun_call(
                    expected_type,
                    &loc,
                    &maccess,
                    type_params.as_deref(),
                    &args,
                )
            }
            EA::Exp_::Pack(maccess, generics, fields) => {
                self.translate_pack(&loc, maccess, generics, fields, expected_type)
            }
            EA::Exp_::IfElse(cond, then, else_) => {
                let then = self.translate_exp(&*then, expected_type);
                let else_ = self.translate_exp(&*else_, expected_type);
                let cond = self.translate_exp(&*cond, &Type::new_prim(PrimitiveType::Bool));
                let id = self.new_node_id_with_type_loc(expected_type, &loc);
                Exp::IfElse(id, Box::new(cond), Box::new(then), Box::new(else_))
            }
            EA::Exp_::Block(seq) => self.translate_seq(&loc, seq, expected_type),
            EA::Exp_::Lambda(bindings, exp) => {
                self.translate_lambda(&loc, bindings, exp, expected_type)
            }
            EA::Exp_::BinopExp(l, op, r) => {
                let args = vec![l.as_ref(), r.as_ref()];
                let QualifiedSymbol {
                    module_name,
                    symbol,
                } = self.parent.parent.bin_op_symbol(&op.value);
                self.translate_call(&loc, &Some(module_name), symbol, None, &args, expected_type)
            }
            EA::Exp_::UnaryExp(op, exp) => {
                let args = vec![exp.as_ref()];
                let QualifiedSymbol {
                    module_name,
                    symbol,
                } = self.parent.parent.unary_op_symbol(&op.value);
                self.translate_call(&loc, &Some(module_name), symbol, None, &args, expected_type)
            }
            EA::Exp_::ExpDotted(dotted) => self.translate_dotted(dotted, expected_type),
            EA::Exp_::Index(target, index) => {
                self.translate_index(&loc, target, index, expected_type)
            }
            EA::Exp_::ExpList(exps) => {
                let mut types = vec![];
                let exps = exps
                    .iter()
                    .map(|exp| {
                        let (ty, exp) = self.translate_exp_free(exp);
                        types.push(ty);
                        exp
                    })
                    .collect_vec();
                let ty = self.check_type(
                    &loc,
                    &Type::Tuple(types),
                    expected_type,
                    "in expression list",
                );
                let id = self.new_node_id_with_type_loc(&ty, &loc);
                Exp::Call(id, Operation::Tuple, exps)
            }
            EA::Exp_::Unit { .. } => {
                let ty = self.check_type(
                    &loc,
                    &Type::Tuple(vec![]),
                    expected_type,
                    "in unit expression",
                );
                let id = self.new_node_id_with_type_loc(&ty, &loc);
                Exp::Call(id, Operation::Tuple, vec![])
            }
            EA::Exp_::Assign(..) => {
                self.error(&loc, "assignment only allowed in spec var updates");
                self.new_error_exp()
            }
            EA::Exp_::Dereference(exp) | EA::Exp_::Borrow(_, exp) => {
                if self.translating_fun_as_spec_fun {
                    self.translate_exp(exp, expected_type)
                } else {
                    self.error(&loc, "expression construct not supported in specifications");
                    self.new_error_exp()
                }
            }
            _ => {
                self.error(&loc, "expression construct not supported in specifications");
                self.new_error_exp()
            }
        }
    }
/// Translates an expression, with given expected type, which might be a type variable.
Translates an expression, with given expected type, which might be a type variable.
Translates an expression with given expected type which might be a type variable .
fn translate_exp(&mut self, exp: &EA::Exp, expected_type: &Type) -> Exp {
        let loc = self.to_loc(&exp.loc);
        let make_value = |et: &mut ExpTranslator, val: Value, ty: Type| {
            let rty = et.check_type(&loc, &ty, expected_type, "in expression");
            let id = et.new_node_id_with_type_loc(&rty, &loc);
            Exp::Value(id, val)
        };
        match &exp.value {
            EA::Exp_::Value(v) => {
                if let Some((v, ty)) = self.translate_value(v) {
                    make_value(self, v, ty)
                } else {
                    self.new_error_exp()
                }
            }
            EA::Exp_::InferredNum(x) => {
                // We don't really need to infer type, because all ints are exchangeable.
                make_value(
                    self,
                    Value::Number(BigInt::from_u128(*x).unwrap()),
                    Type::new_prim(PrimitiveType::U128),
                )
            }
            EA::Exp_::Name(maccess, type_params) => {
                self.translate_name(&loc, maccess, type_params.as_deref(), expected_type)
            }
            EA::Exp_::Call(maccess, type_params, args) => {
                // Need to make a &[&Exp] out of args.
                let args = args.value.iter().map(|e| e).collect_vec();
                self.translate_fun_call(
                    expected_type,
                    &loc,
                    &maccess,
                    type_params.as_deref(),
                    &args,
                )
            }
            EA::Exp_::Pack(maccess, generics, fields) => {
                self.translate_pack(&loc, maccess, generics, fields, expected_type)
            }
            EA::Exp_::IfElse(cond, then, else_) => {
                let then = self.translate_exp(&*then, expected_type);
                let else_ = self.translate_exp(&*else_, expected_type);
                let cond = self.translate_exp(&*cond, &Type::new_prim(PrimitiveType::Bool));
                let id = self.new_node_id_with_type_loc(expected_type, &loc);
                Exp::IfElse(id, Box::new(cond), Box::new(then), Box::new(else_))
            }
            EA::Exp_::Block(seq) => self.translate_seq(&loc, seq, expected_type),
            EA::Exp_::Lambda(bindings, exp) => {
                self.translate_lambda(&loc, bindings, exp, expected_type)
            }
            EA::Exp_::BinopExp(l, op, r) => {
                let args = vec![l.as_ref(), r.as_ref()];
                let QualifiedSymbol {
                    module_name,
                    symbol,
                } = self.parent.parent.bin_op_symbol(&op.value);
                self.translate_call(&loc, &Some(module_name), symbol, None, &args, expected_type)
            }
            EA::Exp_::UnaryExp(op, exp) => {
                let args = vec![exp.as_ref()];
                let QualifiedSymbol {
                    module_name,
                    symbol,
                } = self.parent.parent.unary_op_symbol(&op.value);
                self.translate_call(&loc, &Some(module_name), symbol, None, &args, expected_type)
            }
            EA::Exp_::ExpDotted(dotted) => self.translate_dotted(dotted, expected_type),
            EA::Exp_::Index(target, index) => {
                self.translate_index(&loc, target, index, expected_type)
            }
            EA::Exp_::ExpList(exps) => {
                let mut types = vec![];
                let exps = exps
                    .iter()
                    .map(|exp| {
                        let (ty, exp) = self.translate_exp_free(exp);
                        types.push(ty);
                        exp
                    })
                    .collect_vec();
                let ty = self.check_type(
                    &loc,
                    &Type::Tuple(types),
                    expected_type,
                    "in expression list",
                );
                let id = self.new_node_id_with_type_loc(&ty, &loc);
                Exp::Call(id, Operation::Tuple, exps)
            }
            EA::Exp_::Unit { .. } => {
                let ty = self.check_type(
                    &loc,
                    &Type::Tuple(vec![]),
                    expected_type,
                    "in unit expression",
                );
                let id = self.new_node_id_with_type_loc(&ty, &loc);
                Exp::Call(id, Operation::Tuple, vec![])
            }
            EA::Exp_::Assign(..) => {
                self.error(&loc, "assignment only allowed in spec var updates");
                self.new_error_exp()
            }
            EA::Exp_::Dereference(exp) | EA::Exp_::Borrow(_, exp) => {
                if self.translating_fun_as_spec_fun {
                    self.translate_exp(exp, expected_type)
                } else {
                    self.error(&loc, "expression construct not supported in specifications");
                    self.new_error_exp()
                }
            }
            _ => {
                self.error(&loc, "expression construct not supported in specifications");
                self.new_error_exp()
            }
        }
    }
fn translate_exp ( & mut self , exp : & EA :: Exp , expected_type : & Type ) -> Exp { let loc = self . to_loc ( & exp . loc ) ; let make_value = | et : & mut ExpTranslator , val : Value , ty : Type | { let rty = et . check_type ( & loc , & ty , expected_type , " " ) ; let id = et . new_node_id_with_type_loc ( & rty , & loc ) ; Exp :: Value ( id , val ) } ; match & exp . value { EA :: Exp_ :: Value ( v ) => { if let Some ( ( v , ty ) ) = self . translate_value ( v ) { make_value ( self , v , ty ) } else { self . new_error_exp ( ) } } EA :: Exp_ :: InferredNum ( x ) => { // We don't really need to infer type, because all ints are exchangeable. make_value ( self , Value :: Number ( BigInt :: from_u128 ( * x ) . unwrap ( ) ) , Type :: new_prim ( PrimitiveType :: U128 ) , ) } EA :: Exp_ :: Name ( maccess , type_params ) => { self . translate_name ( & loc , maccess , type_params . as_deref ( ) , expected_type ) } EA :: Exp_ :: Call ( maccess , type_params , args ) => { // Need to make a &[&Exp] out of args. let args = args . value . iter ( ) . map ( | e | e ) . collect_vec ( ) ; self . translate_fun_call ( expected_type , & loc , & maccess , type_params . as_deref ( ) , & args , ) } EA :: Exp_ :: Pack ( maccess , generics , fields ) => { self . translate_pack ( & loc , maccess , generics , fields , expected_type ) } EA :: Exp_ :: IfElse ( cond , then , else_ ) => { let then = self . translate_exp ( & * then , expected_type ) ; let else_ = self . translate_exp ( & * else_ , expected_type ) ; let cond = self . translate_exp ( & * cond , & Type :: new_prim ( PrimitiveType :: Bool ) ) ; let id = self . new_node_id_with_type_loc ( expected_type , & loc ) ; Exp :: IfElse ( id , Box :: new ( cond ) , Box :: new ( then ) , Box :: new ( else_ ) ) } EA :: Exp_ :: Block ( seq ) => self . translate_seq ( & loc , seq , expected_type ) , EA :: Exp_ :: Lambda ( bindings , exp ) => { self . translate_lambda ( & loc , bindings , exp , expected_type ) } EA :: Exp_ :: BinopExp ( l , op , r ) => { let args = vec ! [ l as_ref ( ) r as_ref ( ) ] ; let QualifiedSymbol { module_name , symbol , } = self . parent . parent . bin_op_symbol ( & op . value ) ; self . translate_call ( & loc , & Some ( module_name ) , symbol , None , & args , expected_type ) } EA :: Exp_ :: UnaryExp ( op , exp ) => { let args = vec ! [ exp as_ref ( ) ] ; let QualifiedSymbol { module_name , symbol , } = self . parent . parent . unary_op_symbol ( & op . value ) ; self . translate_call ( & loc , & Some ( module_name ) , symbol , None , & args , expected_type ) } EA :: Exp_ :: ExpDotted ( dotted ) => self . translate_dotted ( dotted , expected_type ) , EA :: Exp_ :: Index ( target , index ) => { self . translate_index ( & loc , target , index , expected_type ) } EA :: Exp_ :: ExpList ( exps ) => { let mut types = vec ! [ ] ; let exps = exps . iter ( ) . map ( | exp | { let ( ty , exp ) = self . translate_exp_free ( exp ) ; types . push ( ty ) ; exp } ) . collect_vec ( ) ; let ty = self . check_type ( & loc , & Type :: Tuple ( types ) , expected_type , " " , ) ; let id = self . new_node_id_with_type_loc ( & ty , & loc ) ; Exp :: Call ( id , Operation :: Tuple , exps ) } EA :: Exp_ :: Unit { .. } => { let ty = self . check_type ( & loc , & Type :: Tuple ( vec ! [ ] ) , expected_type , " " , ) ; let id = self . new_node_id_with_type_loc ( & ty , & loc ) ; Exp :: Call ( id , Operation :: Tuple , vec ! [ ] ) } EA :: Exp_ :: Assign ( .. ) => { self . error ( & loc , " " ) ; self . new_error_exp ( ) } EA :: Exp_ :: Dereference ( exp ) | EA :: Exp_ :: Borrow ( _ , exp ) => { if self . translating_fun_as_spec_fun { self . translate_exp ( exp , expected_type ) } else { self . error ( & loc , " " ) ; self . new_error_exp ( ) } } _ => { self . error ( & loc , " " ) ; self . new_error_exp ( ) } } }
Translates an expression, with given expected type, which might be a type variable.
Translates an expression with given expected type which might be a type variable .
&mut self
exp
&EA::Exp
expected_type
&Type
&mut self
exp
&EA::Exp
expected_type
&Type