1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::fmt::{Display, Formatter, Result};
use std::iter;

use Function;
use Statement;

#[cfg(test)]
mod tests {
    use {Argument, Assignment, Block, Function, FunctionCall, Statement};
    #[test]
    fn it_makes_a_complex_function() {
        let mut program = Block::new();

        let mut function =
            Function::new("hello",
                          vec![Argument::new("name", Some("\"World\""), None, None)],
                          &program);
        function.add_statement(
      Statement::Assignment(
        Assignment::new(
          Argument::input("internal_name"), Statement::Argument(Argument::input("name")))));
        let arguments = vec![Statement::Argument(Argument::bare("Hello")),
                             Statement::Argument(Argument::input("internal_name"))];
        let function_call = FunctionCall::new("print", arguments);
        function.add_statement(Statement::FunctionCall(function_call));

        program.add_function(function);

        let function_call = FunctionCall::new("hello",
                                              vec![Statement::Argument(Argument::bare("Chris"))]);
        program.add_statement(Statement::FunctionCall(function_call));
        let expected = r#"def hello(name="World"):
    internal_name = name
    print("Hello", internal_name)

hello("Chris")
"#;
        let actual = format!("{}", program);
        println!("expected:");
        println!("\"{}\"", expected);
        println!("actual:");
        println!("\"{}\"", actual);
        assert_eq!(expected, actual);

    }
}

#[derive(Debug, Clone)]
pub struct Block {
    pub indentation: usize,
    pub statements: Vec<Statement>,
}

impl Block {
    pub fn new() -> Block {
        Block {
            indentation: 0,
            statements: vec![],
        }
    }

    pub fn new_with_parent(parent: &Block) -> Block {
        Block {
            indentation: parent.indentation + 1,
            statements: vec![],
        }
    }

    pub fn add_function(&mut self, function: Function) {
        self.add_statement(Statement::Function(function));
    }

    pub fn add_statement(&mut self, statement: Statement) {
        self.statements.push(statement);
    }

    pub fn indentation(&self) -> String {
        iter::repeat("    ").take(self.indentation).collect()
    }
}

impl Display for Block {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let indent: String = iter::repeat("    ").take(self.indentation).collect();
        let statements = self.statements
            .iter()
            .map(|s| format!("{}{}", indent, s))
            .collect::<Vec<String>>()
            .join("\n");

        write!(f, "{}\n", statements)

    }
}