/// Parse call arguments for external calls
Parse call arguments for external calls
Parse call arguments for external calls
fn parse_call_args(
    call_args: &[&pt::NamedArgument],
    external_call: bool,
    file_no: usize,
    contract_no: Option<usize>,
    ns: &mut Namespace,
    symtable: &Symtable,
    diagnostics: &mut Vec<Diagnostic>,
) -> Result<CallArgs, ()> {
    let mut args: HashMap<&String, &pt::NamedArgument> = HashMap::new();
    for arg in call_args {
        if let Some(prev) = args.get(&arg.name.name) {
            diagnostics.push(Diagnostic::error_with_note(
                arg.loc,
                format!("‘{}’ specified multiple times", arg.name.name),
                prev.loc,
                format!("location of previous declaration of ‘{}’", arg.name.name),
            ));
            return Err(());
        }
        args.insert(&arg.name.name, arg);
    }
    let mut res = CallArgs {
        gas: Box::new(Expression::NumberLiteral(
            pt::Loc(0, 0, 0),
            Type::Uint(64),
            // See EIP150
            if ns.target == Target::Ewasm {
                BigInt::from(i64::MAX)
            } else {
                BigInt::zero()
            },
        )),
        value: None,
        salt: None,
    };
    for arg in args.values() {
        match arg.name.name.as_str() {
            "value" => {
                let ty = Type::Value;
                let expr = expression(
                    &arg.expr,
                    file_no,
                    contract_no,
                    ns,
                    symtable,
                    false,
                    diagnostics,
                    Some(&ty),
                )?;
                res.value = Some(Box::new(cast(
                    &arg.expr.loc(),
                    expr,
                    &ty,
                    true,
                    ns,
                    diagnostics,
                )?));
            }
            "gas" => {
                let ty = Type::Uint(64);
                let expr = expression(
                    &arg.expr,
                    file_no,
                    contract_no,
                    ns,
                    symtable,
                    false,
                    diagnostics,
                    Some(&ty),
                )?;
                res.gas = Box::new(cast(&arg.expr.loc(), expr, &ty, true, ns, diagnostics)?);
            }
            "salt" => {
                if external_call {
                    diagnostics.push(Diagnostic::error(
                        arg.loc,
                        "‘salt’ not valid for external calls".to_string(),
                    ));
                    return Err(());
                }
                let ty = Type::Uint(256);
                let expr = expression(
                    &arg.expr,
                    file_no,
                    contract_no,
                    ns,
                    symtable,
                    false,
                    diagnostics,
                    Some(&ty),
                )?;
                res.salt = Some(Box::new(cast(
                    &arg.expr.loc(),
                    expr,
                    &ty,
                    true,
                    ns,
                    diagnostics,
                )?));
            }
            _ => {
                diagnostics.push(Diagnostic::error(
                    arg.loc,
                    format!("‘{}’ not a valid call parameter", arg.name.name),
                ));
                return Err(());
            }
        }
    }
    Ok(res)
}
fn parse_call_args ( call_args : & [ & pt :: NamedArgument ] , external_call : bool , file_no : usize , contract_no : Option < usize > , ns : & mut Namespace , symtable : & Symtable , diagnostics : & mut Vec < Diagnostic > , ) -> Result < CallArgs , ( ) > { let mut args : HashMap < & String , & pt :: NamedArgument > = HashMap :: new ( ) ; for arg in call_args { if let Some ( prev ) = args . get ( & arg . name . name ) { diagnostics . push ( Diagnostic :: error_with_note ( arg . loc , format ! ( " r nam .nam ), prev . loc , format ! ( " r nam .nam ), ) ) ; return Err ( ( ) ) ; } args . insert ( & arg . name . name , arg ) ; } let mut res = CallArgs { gas : Box :: new ( Expression :: NumberLiteral ( pt :: Loc ( 0 , 0 , 0 ) , Type :: Uint ( 64 ) , // See EIP150 if ns . target == Target :: Ewasm { BigInt :: from ( i64 :: MAX ) } else { BigInt :: zero ( ) } , ) ) , value : None , salt : None , } ; for arg in args . values ( ) { match arg . name . name . as_str ( ) { " " => { let ty = Type :: Value ; let expr = expression ( & arg . expr , file_no , contract_no , ns , symtable , false , diagnostics , Some ( & ty ) , ) ? ; res . value = Some ( Box :: new ( cast ( & arg . expr . loc ( ) , expr , & ty , true , ns , diagnostics , ) ? ) ) ; } " " => { let ty = Type :: Uint ( 64 ) ; let expr = expression ( & arg . expr , file_no , contract_no , ns , symtable , false , diagnostics , Some ( & ty ) , ) ? ; res . gas = Box :: new ( cast ( & arg . expr . loc ( ) , expr , & ty , true , ns , diagnostics ) ? ) ; } " " => { if external_call { diagnostics . push ( Diagnostic :: error ( arg . loc , " _ s tring(), ) ) ; return Err ( ( ) ) ; } let ty = Type :: Uint ( 256 ) ; let expr = expression ( & arg . expr , file_no , contract_no , ns , symtable , false , diagnostics , Some ( & ty ) , ) ? ; res . salt = Some ( Box :: new ( cast ( & arg . expr . loc ( ) , expr , & ty , true , ns , diagnostics , ) ? ) ) ; } _ => { diagnostics . push ( Diagnostic :: error ( arg . loc , format ! ( " r nam .nam ), ) ) ; return Err ( ( ) ) ; } } } Ok ( res ) }
Parse call arguments for external calls
Parse call arguments for external calls
call_args
&[&pt::NamedArgument]
external_call
bool
file_no
usize
contract_no
Option<usize>
ns
&mut Namespace
symtable
&Symtable
diagnostics
&mut Vec<Diagnostic>