fn incr_decr(
    v: &pt::Expression,
    expr: &pt::Expression,
    file_no: usize,
    contract_no: Option<usize>,
    ns: &mut Namespace,
    symtable: &Symtable,
    diagnostics: &mut Vec<Diagnostic>,
) -> Result<Expression, ()> {
    let op = |e: Expression, ty: Type| -> Expression {
        match expr {
            pt::Expression::PreIncrement(loc, _) => Expression::PreIncrement(*loc, ty, Box::new(e)),
            pt::Expression::PreDecrement(loc, _) => Expression::PreDecrement(*loc, ty, Box::new(e)),
            pt::Expression::PostIncrement(loc, _) => {
                Expression::PostIncrement(*loc, ty, Box::new(e))
            }
            pt::Expression::PostDecrement(loc, _) => {
                Expression::PostDecrement(*loc, ty, Box::new(e))
            }
            _ => unreachable!(),
        }
    };

    let var = expression(
        v,
        file_no,
        contract_no,
        ns,
        symtable,
        false,
        diagnostics,
        None,
    )?;
    let var_ty = var.ty();

    match &var {
        Expression::ConstantVariable(loc, _, Some(contract_no), var_no) => {
            diagnostics.push(Diagnostic::error(
                *loc,
                format!(
                    "cannot assign to constant ‘{}’",
                    ns.contracts[*contract_no].variables[*var_no].name
                ),
            ));
            Err(())
        }
        Expression::ConstantVariable(loc, _, None, var_no) => {
            diagnostics.push(Diagnostic::error(
                *loc,
                format!("cannot assign to constant ‘{}’", ns.constants[*var_no].name),
            ));
            Err(())
        }
        Expression::Variable(_, ty, n) => {
            match ty {
                Type::Int(_) | Type::Uint(_) => (),
                _ => {
                    diagnostics.push(Diagnostic::error(
                        var.loc(),
                        format!(
                            "variable ‘{}’ of incorrect type {}",
                            symtable.get_name(*n),
                            var_ty.to_string(ns)
                        ),
                    ));
                    return Err(());
                }
            };
            Ok(op(var.clone(), ty.clone()))
        }
        _ => match &var_ty {
            Type::Ref(r_ty) | Type::StorageRef(r_ty) => match r_ty.as_ref() {
                Type::Int(_) | Type::Uint(_) => Ok(op(var, r_ty.as_ref().clone())),
                _ => {
                    diagnostics.push(Diagnostic::error(
                        var.loc(),
                        format!("assigning to incorrect type {}", r_ty.to_string(ns)),
                    ));
                    Err(())
                }
            },
            _ => {
                diagnostics.push(Diagnostic::error(
                    var.loc(),
                    "expression is not modifiable".to_string(),
                ));
                Err(())
            }
        },
    }
}
/// Resolve an increment/decrement with an operator
Resolve an increment/decrement with an operator
Resolve an increment / decrement with an operator
fn incr_decr(
    v: &pt::Expression,
    expr: &pt::Expression,
    file_no: usize,
    contract_no: Option<usize>,
    ns: &mut Namespace,
    symtable: &Symtable,
    diagnostics: &mut Vec<Diagnostic>,
) -> Result<Expression, ()> {
    let op = |e: Expression, ty: Type| -> Expression {
        match expr {
            pt::Expression::PreIncrement(loc, _) => Expression::PreIncrement(*loc, ty, Box::new(e)),
            pt::Expression::PreDecrement(loc, _) => Expression::PreDecrement(*loc, ty, Box::new(e)),
            pt::Expression::PostIncrement(loc, _) => {
                Expression::PostIncrement(*loc, ty, Box::new(e))
            }
            pt::Expression::PostDecrement(loc, _) => {
                Expression::PostDecrement(*loc, ty, Box::new(e))
            }
            _ => unreachable!(),
        }
    };
    let var = expression(
        v,
        file_no,
        contract_no,
        ns,
        symtable,
        false,
        diagnostics,
        None,
    )?;
    let var_ty = var.ty();
    match &var {
        Expression::ConstantVariable(loc, _, Some(contract_no), var_no) => {
            diagnostics.push(Diagnostic::error(
                *loc,
                format!(
                    "cannot assign to constant ‘{}’",
                    ns.contracts[*contract_no].variables[*var_no].name
                ),
            ));
            Err(())
        }
        Expression::ConstantVariable(loc, _, None, var_no) => {
            diagnostics.push(Diagnostic::error(
                *loc,
                format!("cannot assign to constant ‘{}’", ns.constants[*var_no].name),
            ));
            Err(())
        }
        Expression::Variable(_, ty, n) => {
            match ty {
                Type::Int(_) | Type::Uint(_) => (),
                _ => {
                    diagnostics.push(Diagnostic::error(
                        var.loc(),
                        format!(
                            "variable ‘{}’ of incorrect type {}",
                            symtable.get_name(*n),
                            var_ty.to_string(ns)
                        ),
                    ));
                    return Err(());
                }
            };
            Ok(op(var.clone(), ty.clone()))
        }
        _ => match &var_ty {
            Type::Ref(r_ty) | Type::StorageRef(r_ty) => match r_ty.as_ref() {
                Type::Int(_) | Type::Uint(_) => Ok(op(var, r_ty.as_ref().clone())),
                _ => {
                    diagnostics.push(Diagnostic::error(
                        var.loc(),
                        format!("assigning to incorrect type {}", r_ty.to_string(ns)),
                    ));
                    Err(())
                }
            },
            _ => {
                diagnostics.push(Diagnostic::error(
                    var.loc(),
                    "expression is not modifiable".to_string(),
                ));
                Err(())
            }
        },
    }
}
fn incr_decr ( v : & pt :: Expression , expr : & pt :: Expression , file_no : usize , contract_no : Option < usize > , ns : & mut Namespace , symtable : & Symtable , diagnostics : & mut Vec < Diagnostic > , ) -> Result < Expression , ( ) > { let op = | e : Expression , ty : Type | -> Expression { match expr { pt :: Expression :: PreIncrement ( loc , _ ) => Expression :: PreIncrement ( * loc , ty , Box :: new ( e ) ) , pt :: Expression :: PreDecrement ( loc , _ ) => Expression :: PreDecrement ( * loc , ty , Box :: new ( e ) ) , pt :: Expression :: PostIncrement ( loc , _ ) => { Expression :: PostIncrement ( * loc , ty , Box :: new ( e ) ) } pt :: Expression :: PostDecrement ( loc , _ ) => { Expression :: PostDecrement ( * loc , ty , Box :: new ( e ) ) } _ => unreachable ! ( ) , } } ; let var = expression ( v , file_no , contract_no , ns , symtable , false , diagnostics , None , ) ? ; let var_ty = var . ty ( ) ; match & var { Expression :: ConstantVariable ( loc , _ , Some ( contract_no ) , var_no ) => { diagnostics . push ( Diagnostic :: error ( * loc , format ! ( " ns contracts [ contract_no ] variables [ var_no ] name ) , ) ) ; Err ( ( ) ) } Expression :: ConstantVariable ( loc , _ , None , var_no ) => { diagnostics . push ( Diagnostic :: error ( * loc , format ! ( " s on tants[*va r no].na m ), ) ) ; Err ( ( ) ) } Expression :: Variable ( _ , ty , n ) => { match ty { Type :: Int ( _ ) | Type :: Uint ( _ ) => ( ) , _ => { diagnostics . push ( Diagnostic :: error ( var . loc ( ) , format ! ( " symtable get_name ( n ) var_ty to_string ( ns ) ) , ) ) ; return Err ( ( ) ) ; } } ; Ok ( op ( var . clone ( ) , ty . clone ( ) ) ) } _ => match & var_ty { Type :: Ref ( r_ty ) | Type :: StorageRef ( r_ty ) => match r_ty . as_ref ( ) { Type :: Int ( _ ) | Type :: Uint ( _ ) => Ok ( op ( var , r_ty . as_ref ( ) . clone ( ) ) ) , _ => { diagnostics . push ( Diagnostic :: error ( var . loc ( ) , format ! ( " " r_ty to_string ( ns ) ) , ) ) ; Err ( ( ) ) } } , _ => { diagnostics . push ( Diagnostic :: error ( var . loc ( ) , " " . to_string ( ) , ) ) ; Err ( ( ) ) } } , } }
Resolve an increment/decrement with an operator
Resolve an increment / decrement with an operator
v
&pt::Expression
expr
&pt::Expression
file_no
usize
contract_no
Option<usize>
ns
&mut Namespace
symtable
&Symtable
diagnostics
&mut Vec<Diagnostic>
v
&pt::Expression
expr
&pt::Expression
file_no
usize
contract_no
Option<usize>
ns
&mut Namespace
symtable
&Symtable
diagnostics
&mut Vec<Diagnostic>