1
1
use budvm::{
2
    CompareAction, Comparison, Destination, Function, Instruction, Symbol, Value, ValueOrSource,
3
    VirtualMachine,
4
};
5

            
6
1
fn main() {
7
1
    const ARG_N: usize = 0;
8
1
    let fib = Function {
9
1
        name: Symbol::from("fibonacci"),
10
1
        arg_count: 1,
11
1
        variable_count: 2,
12
1
        code: vec![
13
1
            // if n <= 2
14
1
            Instruction::Compare {
15
1
                comparison: Comparison::LessThanOrEqual,
16
1
                left: ValueOrSource::Argument(ARG_N),
17
1
                right: ValueOrSource::Value(Value::Integer(2)),
18
1
                action: CompareAction::JumpIfFalse(2),
19
1
            },
20
1
            Instruction::Return(Some(ValueOrSource::Value(Value::Integer(1)))),
21
1
            // v1 = self(n - 1)
22
1
            Instruction::Sub {
23
1
                left: ValueOrSource::Argument(ARG_N),
24
1
                right: ValueOrSource::Value(Value::Integer(1)),
25
1
                destination: Destination::Stack,
26
1
            },
27
1
            Instruction::Call {
28
1
                vtable_index: None,
29
1
                arg_count: 1,
30
1
                destination: Destination::Variable(0),
31
1
            },
32
1
            // v2 = self(n - 2)
33
1
            Instruction::Sub {
34
1
                left: ValueOrSource::Argument(ARG_N),
35
1
                right: ValueOrSource::Value(Value::Integer(2)),
36
1
                destination: Destination::Stack,
37
1
            },
38
1
            Instruction::Call {
39
1
                vtable_index: None,
40
1
                arg_count: 1,
41
1
                destination: Destination::Variable(1),
42
1
            },
43
1
            // return v1 + v2
44
1
            Instruction::Add {
45
1
                left: ValueOrSource::Variable(0),
46
1
                right: ValueOrSource::Variable(1),
47
1
                destination: Destination::Return,
48
1
            },
49
1
        ],
50
1
    };
51
1
    let mut context = VirtualMachine::empty().with_function(fib);
52
1
    let result: i64 = context
53
1
        .run(
54
1
            &[
55
1
                Instruction::Push(ValueOrSource::Value(Value::Integer(10))),
56
1
                Instruction::Call {
57
1
                    vtable_index: Some(0),
58
1
                    arg_count: 1,
59
1
                    destination: Destination::Stack,
60
1
                },
61
1
            ],
62
1
            0,
63
1
        )
64
1
        .unwrap();
65
1
    assert_eq!(result, 55);
66
1
}
67

            
68
1
#[test]
69
1
fn runs() {
70
1
    main()
71
1
}