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
 95
 96
 97
 98
 99
100
101
102
103
#![recursion_limit="256"]

extern crate gluon;
#[macro_use]
extern crate gluon_vm;
extern crate falcon;


#[macro_use]
macro_rules! falcon_type_wrapper {
    ($p: path, $n: ident) => {
        #[derive(Clone, Debug)] pub struct $n { pub x: $p }
        impl VmType for $n { type Type = $n; }
        impl Traverseable for $n {}
        impl Userdata for $n {}
    }
}


pub mod analysis;
pub mod architecture;
pub mod il;
pub mod loader;
pub mod memory;


fn hex(v: u64) -> String {
    format!("{:x}", v)
}


fn println(string: String) {
    println!("{}", string);
}


fn env (name: String) -> Option<String> {
    match std::env::var(&name) {
        Ok(v) => Some(v),
        Err(_) => None
    }
}


fn eval(expression: &il::IlExpression) -> Option<il::IlConstant> {
    falcon::executor::eval(&expression.x)
        .ok()
        .map(|constant| il::IlConstant {x: constant})
}


fn int_to_string(i: usize) -> Option<String> {
    String::from_utf8(vec![i as u8]).ok()
}


pub fn bindings (vm: gluon::RootedThread) -> gluon::RootedThread {
    fn falcon_prim_loader(vm: &gluon::Thread)
        -> gluon::vm::Result<gluon::vm::ExternModule> {
        
        gluon::vm::ExternModule::new(vm, record! {
            env => primitive!(1 env),
            eval => primitive!(1 eval),
            hex => primitive!(1 hex),
            int_to_string => primitive!(1 int_to_string),
            println => primitive!(1 println)
        })
    }

    gluon::import::add_extern_module(&vm, "falcon_prim", falcon_prim_loader);
    
    vm
}


pub fn attach_bindings(vm: gluon::RootedThread) -> gluon::RootedThread {
    // The order is important
    let vm = bindings(vm);
    let vm = analysis::bindings(vm);
    let vm = architecture::bindings(vm);
    let vm = il::bindings(vm);
    let vm = memory::bindings(vm);
    let vm = loader::bindings(vm);
    vm
}


pub fn run_code(code: &str) -> gluon::RootedThread {
    let vm = gluon::new_vm();

    let vm = attach_bindings(vm);

    let mut compiler = gluon::Compiler::new();
    match compiler.run_expr::<()>(&vm, "code", code) {
        Ok(r) => r,
        Err(e) => {
            println!("{}", e);
            panic!("Compile error");
        }
    };

    vm
}