Documentation
#![feature(nll)]
extern crate smallvec;
extern crate byteorder;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;

#[macro_use]
pub mod debug;

#[macro_use]
pub mod fixed_array;

pub mod hybrid;
pub mod builtin;

pub mod basic_block;
pub mod call_stack;
pub mod dynamic_trait;
pub mod errors;
pub mod executor;
pub mod function_optimizer;
pub mod function;
pub mod generic_arithmetic;
//pub mod hybrid_bridge;
pub mod object_info;
pub mod object_pool;
pub mod object;
pub mod opcode;
pub mod primitive;
pub mod static_root;
pub mod value;


use executor::Executor;
use opcode::OpCode;
use basic_block::BasicBlock;
use function::Function;
use value::ValueContext;
use value::Value;

fn main() {
    /*let executor = Executor::new();
    let mut handle = executor.handle_mut();

    const END: i64 = 100000;

    let mut sum_fn = Box::new(Function::from_basic_blocks(vec! [
        // bb 0
        BasicBlock::from_opcodes(vec! [
            { OpCode::InitLocal(8) },
            { OpCode::LoadInt(0) }, // current (initial) value (exclusive)
            { OpCode::SetLocal(0) },
            { OpCode::LoadInt(END) }, // end value (inclusive)
            { OpCode::SetLocal(1) },
            { OpCode::LoadInt(0) }, // sum
            { OpCode::SetLocal(2) },
            { OpCode::Branch(1) }
        ]),
        // bb 1
        BasicBlock::from_opcodes(vec! [
            { OpCode::GetLocal(1) },
            { OpCode::GetLocal(0) },
            { OpCode::TestLt },
            { OpCode::Not },
            { OpCode::ConditionalBranch(3, 2) }
        ]),
        // bb 2
        BasicBlock::from_opcodes(vec! [
            { OpCode::LoadInt(1) },
            { OpCode::GetLocal(0) },
            { OpCode::IntAdd },
            { OpCode::Dup },
            { OpCode::SetLocal(0) },
            { OpCode::GetLocal(2) },
            { OpCode::IntAdd },
            { OpCode::SetLocal(2) },
            { OpCode::Branch(1) }
        ]),
        // bb 3
        BasicBlock::from_opcodes(vec! [
            { OpCode::GetLocal(2) },
            { OpCode::Return }
        ])
    ]));
    sum_fn.enable_optimization();
    handle.create_static_object("sum", sum_fn);

    let blocks: Vec<BasicBlock> = vec! [
        BasicBlock::from_opcodes(vec! [
            { OpCode::InitLocal(8) },
            { OpCode::LoadString("sum".to_string()) },
            { OpCode::GetStatic },
            { OpCode::SetLocal(0) },
            { OpCode::LoadNull },
            { OpCode::GetLocal(0) },
            { OpCode::Call(0) },
            { OpCode::LoadString("output".to_string()) },
            { OpCode::SetStatic },
            { OpCode::LoadNull },
            { OpCode::Return }
        ])
    ];
    handle.create_static_object("entry", Box::new(Function::from_basic_blocks(blocks)));
    match handle.run_callable("entry") {
        Ok(_) => {},
        Err(e) => panic!(e.unwrap().to_string())
    }

    handle.gc();

    let result_value = handle.get_static_object("output").unwrap();
    let result = ValueContext::new(
        &result_value,
        handle.get_object_pool()
    ).to_i64();*/

    let executor = Executor::new();
    let mut handle = executor.handle_mut();

    const END: i64 = 100000;

    /*let mut sum_fn = Box::new(Function::from_basic_blocks(vec! [
        // bb 0
        BasicBlock::from_opcodes(vec! [
            { OpCode::InitLocal(8) },
            { OpCode::LoadInt(0) }, // current (initial) value (exclusive)
            { OpCode::SetLocal(0) },
            { OpCode::LoadInt(END) }, // end value (inclusive)
            { OpCode::SetLocal(1) },
            { OpCode::LoadInt(0) }, // sum
            { OpCode::SetLocal(2) },
            { OpCode::Branch(1) }
        ]),
        // bb 1
        BasicBlock::from_opcodes(vec! [
            { OpCode::GetLocal(1) },
            { OpCode::GetLocal(0) },
            { OpCode::TestLt },
            { OpCode::Not },
            { OpCode::ConditionalBranch(3, 2) }
        ]),
        // bb 2
        BasicBlock::from_opcodes(vec! [
            { OpCode::LoadInt(1) },
            { OpCode::GetLocal(0) },
            { OpCode::IntAdd },
            { OpCode::Dup },
            { OpCode::SetLocal(0) },
            { OpCode::GetLocal(2) },
            { OpCode::IntAdd },
            { OpCode::SetLocal(2) },
            { OpCode::Branch(1) }
        ]),
        // bb 3
        BasicBlock::from_opcodes(vec! [
            { OpCode::GetLocal(2) },
            { OpCode::Return }
        ])
    ]));
    sum_fn.enable_optimization();
    handle.create_static_object("sum", sum_fn);*/

    let blocks: Vec<BasicBlock> = vec! [
        BasicBlock::from_opcodes(vec! [
            { OpCode::InitLocal(8) },
            OpCode::LoadInt(0),
            OpCode::SetLocal(0),
            OpCode::GetLocal(0),
            OpCode::LoadString("out".to_string()),
            OpCode::SetVariable,
            OpCode::Branch(1),



        ]),
        BasicBlock::from_opcodes(vec! [
            OpCode::LoadString("out".to_string()),
            OpCode::GetVariable,
            OpCode::LoadInt(1),
            OpCode::IntAdd,
            OpCode::LoadString("out".to_string()),
            OpCode::SetVariable,
            OpCode::LoadNull,
            OpCode::Return,
        ]),
    ];
    handle.create_static_object("entry", Box::new(Function::from_basic_blocks(blocks)));
    match handle.run_callable("entry") {
        Ok(_) => {},
        Err(e) => panic!(e.unwrap().to_string())
    };

    handle.gc();
    let ret = handle.get_static_object("out");

    println!("{:?}",ret);
}