#![cfg_attr(feature="nightly", feature(test, drain))]
extern crate byteorder;
#[macro_use] extern crate log;
use std::collections::HashMap;
use std::io::{ self, Write };
use std::fmt;
use byteorder::{ WriteBytesExt, LittleEndian };
mod options;
mod template;
mod error;
pub mod interpreter;
pub mod compiler;
pub mod stream;
pub mod bytecode;
pub use options::{ OptionsTemplate, Options };
pub use template::{ Template };
pub use error::seek::SeekError;
pub use error::little::{ LittleError, LittleResult };
pub use error::build::{ BuildError };
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Binding(pub u32);
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Call(pub u32);
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Constant(pub u32);
#[derive(Copy, Clone, Debug)]
pub enum Mem {
Const(Constant),
Binding(Binding),
Parameter { name: Constant },
Parameters,
StackTop1,
StackTop2,
}
#[derive(Copy, Clone, Debug)]
pub enum Cond {
Eq,
Ne,
Gt,
Lt,
Gte,
Lte,
}
#[derive(Copy, Clone, Debug)]
pub enum Instruction {
Output { location: Mem },
Property { name: Mem },
Push { location: Mem },
Pop { times: u16 },
Jump { pc: u16 },
CondJump { pc: u16, location: Mem, test: Cond },
Call { call: Call, argc: u8, push_result_to_stack: bool },
Load { binding: Binding, location: Mem },
Interupt,
}
pub trait Function<V> {
fn invoke<'r>(&self, &'r [V]) -> LittleResult<V>;
}
impl<V, F: for<'z> Fn(&'z [V]) -> LittleResult<V>> Function<V> for F {
fn invoke<'r>(&self, args: &'r [V]) -> LittleResult<V> {
self(args)
}
}
#[derive(Hash, Eq, PartialEq)]
pub struct Fingerprint([u8;20]);
impl Fingerprint {
pub fn empty() -> Fingerprint {
Fingerprint([0;20])
}
pub fn new(inner: [u8;20]) -> Fingerprint {
Fingerprint(inner)
}
}
pub trait Build<'a, V> {
type Output: Execute<'a, V>;
fn build(
&'a mut self,
id: &str,
template: Template<V>,
calls: &'a HashMap<&'a str, &'a (Function<V> + 'a)>
) -> LittleResult<Self::Output>;
fn load(&'a mut self, id: &str, env: Fingerprint, calls: &'a Vec<&'a (Function<V> + 'a)>)
-> LittleResult<Self::Output>;
}
pub trait Execute<'a, V> {
type Stream: io::Read;
fn execute(&'a self, V) -> Self::Stream;
fn get_id<'r>(&'r self) -> &'r str;
fn identify_env(&self) -> Fingerprint;
}
pub trait IdentifyValue {
fn identify_value(&self) -> Option<Fingerprint>;
fn hash_value<H: Sha1Hasher>(&self, hasher: &mut H) -> Result<(), ()>;
}
pub trait Sha1Hasher {
fn finish(&self) -> Fingerprint;
fn write(&mut self, bytes: &[u8]);
#[inline]
fn write_u8(&mut self, i: u8) {
self.write(&[i])
}
#[inline]
fn write_u16(&mut self, i: u16) {
let mut buf_ref: &mut [u8] = &mut [0u8;2];
buf_ref.write_u16::<LittleEndian>(i).unwrap();
self.write(buf_ref);
}
#[inline]
fn write_u32(&mut self, i: u32) {
let mut buf_ref: &mut [u8] = &mut [0u8;4];
buf_ref.write_u32::<LittleEndian>(i).unwrap();
self.write(buf_ref);
}
#[inline]
fn write_u64(&mut self, i: u64) {
let mut buf_ref: &mut [u8] = &mut [0u8;8];
buf_ref.write_u64::<LittleEndian>(i).unwrap();
self.write(buf_ref);
}
#[inline]
fn write_i8(&mut self, i: i8) {
let mut buf_ref: &mut [u8] = &mut [0u8;1];
buf_ref.write_i8(i).unwrap();
self.write(buf_ref);
}
#[inline]
fn write_i16(&mut self, i: i16) {
let mut buf_ref: &mut [u8] = &mut [0u8;2];
buf_ref.write_i16::<LittleEndian>(i).unwrap();
self.write(buf_ref);
}
#[inline]
fn write_i32(&mut self, i: i32) {
let mut buf_ref: &mut [u8] = &mut [0u8;4];
buf_ref.write_i32::<LittleEndian>(i).unwrap();
self.write(buf_ref);
}
#[inline]
fn write_i64(&mut self, i: i64) {
let mut buf_ref: &mut [u8] = &mut [0u8;8];
buf_ref.write_i64::<LittleEndian>(i).unwrap();
self.write(buf_ref);
}
}
pub trait LittleValue : Default + PartialEq + PartialOrd + Clone + IdentifyValue + fmt::Display { }
pub trait PositionSeek {
fn seek(&mut self, pos: usize) -> Result<usize, SeekError>;
}