rust_to_dtr 0.16.0

Convert Rust Soroban contracts to DTR format.
Documentation
use crate::common::compilation_state;
use crate::errors::not_translatable_error::NotTranslatableError;
use crate::instruction::Instruction;
use crate::translate::expression::parse_expression;
use crate::translate::pattern::handle_pattern;

pub fn handle_let_expression(
    let_expr: syn::ExprLet,
    compilation_state: &mut compilation_state::CompilationState,
) -> Result<Vec<Instruction>, NotTranslatableError> {
    let global_uuid = compilation_state.get_global_uuid();
    let input_value_name_for_let = format!("INPUT_VALUE_NAME_FOR_LET_{}", global_uuid);

    let original_assignment = compilation_state.next_assignment.clone();
    let mut preceding_instructions = parse_expression(
        &let_expr.expr,
        &mut compilation_state.with_assignment(Some(input_value_name_for_let.to_string())),
    )?;
    compilation_state.with_assignment(original_assignment);

    let result = handle_pattern(*(let_expr.pat.clone()));
    let result_instruction: Instruction = if compilation_state.next_assignment.is_none() {
        Instruction::new(
            compilation_state.get_global_uuid(),
            "assign".to_string(),
            vec![input_value_name_for_let.to_string()],
            result.unwrap_or(
                compilation_state
                    .next_assignment
                    .clone()
                    .unwrap_or_default(),
            ),
            compilation_state.scope(),
        )
    } else {
        if result.is_err() {
            Instruction::new(
                compilation_state.get_global_uuid(),
                "try_assign".to_string(),
                vec![input_value_name_for_let.to_string()],
                compilation_state
                    .next_assignment
                    .clone()
                    .unwrap_or_default(),
                compilation_state.scope(),
            )
        } else {
            Instruction::new(
                compilation_state.get_global_uuid(),
                "try_assign".to_string(),
                vec![
                    input_value_name_for_let.to_string(),
                    result.unwrap_or("".to_string()),
                ],
                compilation_state
                    .next_assignment
                    .clone()
                    .unwrap_or_default(),
                compilation_state.scope(),
            )
        }
    };

    preceding_instructions.push(result_instruction);

    Ok(preceding_instructions)
}

#[cfg(test)]
mod tests {
    use crate::common::compilation_state::CompilationState;
    use crate::instruction::Instruction;
    use crate::translate::expression::parse_expression;
    use syn;

    mod let_expression {
        use syn::ExprLet;

        use super::*;

        #[test]
        fn test_let_expression_simple_x_equals_1() {
            let parsed_expr_let: ExprLet = syn::parse_str("let x = 1").unwrap();
            let result = parse_expression(
                &syn::Expr::Let(parsed_expr_let),
                &mut CompilationState::new(),
            );
            let expected: Vec<Instruction> = vec![
                Instruction::new(
                    1,
                    "assign".to_string(),
                    vec!["1".to_string()],
                    "INPUT_VALUE_NAME_FOR_LET_0".to_string(),
                    0,
                ),
                Instruction::new(
                    2,
                    "assign".to_string(),
                    vec!["INPUT_VALUE_NAME_FOR_LET_0".to_string()],
                    "x".to_string(),
                    0,
                ),
            ];

            assert_eq!(result, Ok(expected));
        }

        #[test]
        fn test_let_expression_less_simple_foo_equals_bar() {
            let parsed_expr_let: ExprLet = syn::parse_str("let foo = bar").unwrap();
            let result = parse_expression(
                &syn::Expr::Let(parsed_expr_let),
                &mut CompilationState::new(),
            );
            let expected = vec![
                Instruction::new(
                    1,
                    "assign".to_string(),
                    vec!["bar".to_string()],
                    "INPUT_VALUE_NAME_FOR_LET_0".to_string(),
                    0,
                ),
                Instruction::new(
                    2,
                    "assign".to_string(),
                    vec!["INPUT_VALUE_NAME_FOR_LET_0".to_string()],
                    "foo".to_string(),
                    0,
                ),
            ];

            assert_eq!(result, Ok(expected));
        }
    }
}