use super::*;
pub type CallError = mtk::Error;
#[derive(Clone)]
pub struct Routine {
data: Vec<i128>,
env: *mut Env
}
impl Routine {
pub fn new(env: &mut Env) -> Routine {
Routine {
data: Vec::new(),
env
}
}
pub fn from(env: &mut Env, data: Vec<i128>) -> Routine {
Routine { data, env }
}
pub fn push(&mut self, byte: i128) {
self.data.push(byte)
}
pub fn pop(&mut self) -> Option<i128> {
self.data.pop()
}
pub fn get(&self, index: usize) -> Option<&i128> {
self.data.get(index)
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut i128> {
self.data.get_mut(index)
}
pub unsafe fn call(&mut self, argv: Vec<usize>) -> Result<Result<usize, usize>, CallError> {
let mut pc = 0;
let mut c: i128 = 0;
let mut e: i128 = 0;
while pc < self.data.len() {
if self.data[pc] == ALLOC {
pc += 1;
let l = match self.data.get(pc) {
Some(some) => *some,
None => return Err(CallError::from(format!("can not get from index {}", pc)))
};
c = match (*self.env).alloc(l as usize) {
Ok(ok) => ok as i128,
Err(err) => return Err(err.clone())
};
} else if self.data[pc] == DEALLOC {
pc += 1;
let l = match self.data.get(pc) {
Some(some) => *some,
None => return Err(CallError::from(format!("can not get from index {}", pc)))
};
c = match (*self.env).dealloc(l as usize) {
Ok(ok) => ok as i128,
Err(err) => return Err(err.clone())
};
} else if self.data[pc] == THROW {
pc += 1;
let l = match self.data.get(pc) {
Some(some) => *some,
None => return Err(CallError::from(format!("can not get from index {}", pc)))
};
return Ok(Err(l as usize));
} else if self.data[pc] == RETURN {
pc += 1;
let l = match self.data.get(pc) {
Some(some) => *some,
None => return Err(CallError::from(format!("can not get from index {}", pc)))
};
return Ok(Ok(l as usize));
} else if self.data[pc] == CALL {
pc += 1;
let l = match self.data.get(pc) {
Some(some) => *some,
None => return Err(CallError::from(format!("can not get from index {}", pc)))
};
pc += 1;
let r = match self.data.get(pc) {
Some(some) => *some,
None => return Err(CallError::from(format!("can not get from index {}", pc)))
};
let mut argv_p: Vec<usize> = Vec::new();
match (*self.env).get_mem().get(r as usize) {
Some(some) => {
match some {
Some(some) => {
for elem in some.iter() {
argv_p.push(*elem as usize);
}
},
None => return Err(CallError::from(format!("memory on address {} was deallocated", r)))
}
},
None => return Err(CallError::from(format!("no memory was allocated on address {}", r)))
};
let x = (*self.env).call(l as usize, argv_p);
match x {
Ok(ok) => {
match ok {
Ok(ok) => c = ok as i128,
Err(err) => e = err as i128
}
},
Err(err) => return Err(err)
};
} else if self.data[pc] == RETURN_C {
return Ok(Ok(c as usize));
} else if self.data[pc] == FETCH_ARG {
pc += 1;
let l = match self.data.get(pc) {
Some(some) => *some,
None => return Err(CallError::from(format!("can not get from index {}", pc)))
};
c = match argv.get(l as usize) {
Some(some) => *some as i128,
None => return Err(CallError::from(format!("can not get from index {} of argv", l)))
};
} else {
pc += 1;
}
}
Err(CallError::from(format!("routine ended without return")))
}
}