<commit_before>
use types::{Int, ForthCell};
use error::{ForthResult, ForthError};
use dictionary::{Dictionary, DictionaryExt, Entry};
use statement::{Statement, StatementExt};
use word::ForthWord;

pub type Stack = Vec<Int>;

pub struct Interpreter {
    pub dictionary: Dictionary,
    last_result: Option<Stack>,
}

macro_rules! try_stack {
    ($x:expr) => {
        match $x {
            Some(i) => i,
            None => return Err(ForthError::EmptyStack),
        }
    }
}

macro_rules! binary_entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name,
                ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let b = try_stack!(stack.pop());
                    let a = try_stack!(stack.pop());
                    stack.push($f(a, b));
                    Ok(())
                })),
            ))
    }
}

macro_rules! unary_entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name,
                ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let a = try_stack!(stack.pop());
                    stack.push($f(a));
                    Ok(())
                })),
            ))
    }
}

macro_rules! nonary_entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name,
                ForthWord::Native(Box::new(|_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
                    ForthCell::Number($f);
                    Ok(())
                })),
            ))
    }
}

macro_rules! entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name, ForthWord::Native(Box::new($f))))
    }
}

impl Interpreter {
    pub fn new() -> Interpreter {
        let mut dict = Dictionary::new();

        binary_entry!(dict, "/", ::std::ops::Div::div);
        binary_entry!(dict, "*", ::std::ops::Mul::mul);
        binary_entry!(dict, "+", ::std::ops::Add::add);
        binary_entry!(dict, "-", ::std::ops::Sub::sub);
        binary_entry!(dict, "mod", ::std::ops::Rem::rem);
        binary_entry!(dict, "and", ::std::ops::BitAnd::bitand);
        binary_entry!(dict, "or", ::std::ops::BitOr::bitor);
        binary_entry!(dict, "xor", ::std::ops::BitXor::bitxor);
        binary_entry!(dict, "rshift", ::std::ops::Shr::shr);
        binary_entry!(dict, "lshift", ::std::ops::Shl::shl);
        binary_entry!(dict, "max", ::std::cmp::max);
        binary_entry!(dict, "min", ::std::cmp::min);

        unary_entry!(dict, "negate", ::std::ops::Neg::neg);
        unary_entry!(dict, "not", ::std::ops::Not::not);

        nonary_entry!(dict, "bye", ::std::process::exit(0));

        entry!(dict, "abs", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x.abs());
                    Ok(())
                });

        entry!(dict, "$", |interp: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(interp.last_result.clone());
                    for v in x {
                        stack.push(v);
                    }
                    Ok(())
                });

        entry!(dict, "<", | _: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x < y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, ">", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x > y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x == y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "0<", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(if x < 0 { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "0=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(if x == 0 { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "0>", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(if x > 0 { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "1+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x + 1);
                    Ok(())
                });

        entry!(dict, "1-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x - 1);
                    Ok(())
                });

        entry!(dict, "2+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x + 2);
                    Ok(())
                });

        entry!(dict, "2-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x - 2);
                    Ok(())
                });

        entry!(dict, "2/", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x >> 1); // Per fst83 standard
                    Ok(())
                });

        entry!(dict, "dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x.clone());
                    stack.push(x);
                    Ok(())
                });

        entry!(dict, "?dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    if x != 0 {
                        stack.push(x.clone());
                        stack.push(x);
                    } else {
                        stack.push(x);
                    }
                    Ok(())
                });

        entry!(dict, "drop", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let _ = try_stack!(stack.pop());
                    Ok(())
                });

        entry!(dict, "over", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    let y = try_stack!(stack.pop());
                    stack.push(x.clone());
                    stack.push(y);
                    stack.push(x);
                    Ok(())
                });

        entry!(dict, "swap", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    let y = try_stack!(stack.pop());
                    stack.push(x);
                    stack.push(y);
                    Ok(())
                });

        entry!(dict, "rot", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    let y = try_stack!(stack.pop());
                    let z = try_stack!(stack.pop());
                    stack.push(y);
                    stack.push(x);
                    stack.push(z);
                    Ok(())
                });

        entry!(dict, "dump", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    println!("ds =  {:?} ", stack);
                    Ok(())
                });

        entry!(dict, "cr", |_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
                    println!("");
                    Ok(())
                });

        entry!(dict, ".", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    println!("{}", try_stack!(stack.pop()));
                    Ok(())
                });

        entry!(dict, "branch", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x == y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "emit", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    if x < 0 || x > 256 { return Err(ForthError::InvalidCharacter) }
                    print!("{}", x as u8 as char);
                    Ok(())
                });

        let square = {
            let mut s = Statement::new();
            s.push_back(ForthCell::Word(dict.get("dup").unwrap().clone()));
            s.push_back(ForthCell::Word(dict.get("*").unwrap().clone()));
            s
        };
        dict.insert_entry(Entry::from_statement("square", square));

        Interpreter {
            dictionary: dict,
            last_result: None,
        }
    }

    pub fn exec(&mut self, statement: &str) -> ForthResult<()> {
        let mut words = statement.split(|c: char| c.is_whitespace());
        let mut stmt = Statement::new();
        while let Some(word) = words.next() { match word {
            "(" => while let Some(w) = words.next() { if w == ")" { break; } },
            "\\" => while let Some(w) = words.next() { if w == "\n" { break; } },
            ":" => {
                let mut comp = Statement::new();
                let name = match words.next() {
                    Some(w) => w,
                    None => return Err(ForthError::WordNameNotFound),
                };
                while let Some(w) = words.next() {
                    if w == ";" {
                        self.dictionary.insert_entry(Entry::from_statement(name, comp));
                        return Ok(());
                    }
                    match w.parse::<i32>() {
                        Ok(n) => comp.push_back(ForthCell::Number(n)),
                        Err(_) => comp.push_back(ForthCell::Word(self.dictionary.get(w).unwrap().clone())),
                    }
                }
                return Err(ForthError::UnterminatedWordDefinition);
            },
            _ => match word.parse::<i32>() {
                Ok(n) => {
                    stmt.push_back(ForthCell::Number(n));
                },
                Err(_) => {
                    if let Some(elem) = self.dictionary.get(word) {
                        stmt.push_back(ForthCell::Word(elem.clone()));
                    } else {
                        return Err(ForthError::WordNotFound)
                    }
                },
            },

        }}

        match stmt.run(self) {
            Err(e) => {
                self.last_result = None;
                Err(e)
            },
            Ok(s) => {
                self.last_result = Some(s);
                Ok(())
            }
        }
    }
}<commit_msg>Add '*/' '*/mod' and '2*' words<commit_after>
use types::{Int, ForthCell};
use error::{ForthResult, ForthError};
use dictionary::{Dictionary, DictionaryExt, Entry};
use statement::{Statement, StatementExt};
use word::ForthWord;

pub type Stack = Vec<Int>;

pub struct Interpreter {
    pub dictionary: Dictionary,
    last_result: Option<Stack>,
}

macro_rules! try_stack {
    ($x:expr) => {
        match $x {
            Some(i) => i,
            None => return Err(ForthError::EmptyStack),
        }
    }
}

macro_rules! binary_entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name,
                ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let b = try_stack!(stack.pop());
                    let a = try_stack!(stack.pop());
                    stack.push($f(a, b));
                    Ok(())
                })),
            ))
    }
}

macro_rules! unary_entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name,
                ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let a = try_stack!(stack.pop());
                    stack.push($f(a));
                    Ok(())
                })),
            ))
    }
}

macro_rules! nonary_entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name,
                ForthWord::Native(Box::new(|_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
                    ForthCell::Number($f);
                    Ok(())
                })),
            ))
    }
}

macro_rules! entry {
    ($dict:ident, $name:expr, $f:expr) => {
        $dict.insert_entry(Entry::new($name, ForthWord::Native(Box::new($f))))
    }
}

impl Interpreter {
    pub fn new() -> Interpreter {
        let mut dict = Dictionary::new();

        binary_entry!(dict, "/", ::std::ops::Div::div);
        binary_entry!(dict, "*", ::std::ops::Mul::mul);
        binary_entry!(dict, "+", ::std::ops::Add::add);
        binary_entry!(dict, "-", ::std::ops::Sub::sub);
        binary_entry!(dict, "mod", ::std::ops::Rem::rem);
        binary_entry!(dict, "and", ::std::ops::BitAnd::bitand);
        binary_entry!(dict, "or", ::std::ops::BitOr::bitor);
        binary_entry!(dict, "xor", ::std::ops::BitXor::bitxor);
        binary_entry!(dict, "rshift", ::std::ops::Shr::shr);
        binary_entry!(dict, "lshift", ::std::ops::Shl::shl);
        binary_entry!(dict, "max", ::std::cmp::max);
        binary_entry!(dict, "min", ::std::cmp::min);

        unary_entry!(dict, "negate", ::std::ops::Neg::neg);
        unary_entry!(dict, "not", ::std::ops::Not::not);

        nonary_entry!(dict, "bye", ::std::process::exit(0));

        entry!(dict, "*/", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let z = try_stack!(stack.pop()) as i64; // double-length intermediate result
                    let y = try_stack!(stack.pop()) as i64;
                    let x = try_stack!(stack.pop()) as i64;
                    stack.push((x * y / z) as i32);
                    Ok(())
                });

        entry!(dict, "*/mod", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let z = try_stack!(stack.pop()) as i64; // double-length intermediate result
                    let y = try_stack!(stack.pop()) as i64;
                    let x = try_stack!(stack.pop()) as i64;
                    stack.push((x * y % z) as i32);
                    stack.push((x * y / z) as i32);
                    Ok(())

        entry!(dict, "abs", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x.abs());
                    Ok(())
                });

        entry!(dict, "$", |interp: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(interp.last_result.clone());
                    for v in x {
                        stack.push(v);
                    }
                    Ok(())
                });

        entry!(dict, "<", | _: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x < y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, ">", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x > y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x == y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "0<", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(if x < 0 { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "0=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(if x == 0 { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "0>", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(if x > 0 { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "1+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x + 1);
                    Ok(())
                });

        entry!(dict, "1-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x - 1);
                    Ok(())
                });

        entry!(dict, "2+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x + 2);
                    Ok(())
                });

        entry!(dict, "2-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x - 2);
                    Ok(())
                });

        entry!(dict, "2/", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x >> 1); // Per fst83 standard
                    Ok(())
                });

        entry!(dict, "2*", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x << 1); // Per fst83 standard
                    Ok(())
                });

        entry!(dict, "dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    stack.push(x.clone());
                    stack.push(x);
                    Ok(())
                });

        entry!(dict, "?dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    if x != 0 {
                        stack.push(x.clone());
                        stack.push(x);
                    } else {
                        stack.push(x);
                    }
                    Ok(())
                });

        entry!(dict, "drop", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let _ = try_stack!(stack.pop());
                    Ok(())
                });

        entry!(dict, "over", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    let y = try_stack!(stack.pop());
                    stack.push(x.clone());
                    stack.push(y);
                    stack.push(x);
                    Ok(())
                });

        entry!(dict, "swap", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    let y = try_stack!(stack.pop());
                    stack.push(x);
                    stack.push(y);
                    Ok(())
                });

        entry!(dict, "rot", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    let y = try_stack!(stack.pop());
                    let z = try_stack!(stack.pop());
                    stack.push(y);
                    stack.push(x);
                    stack.push(z);
                    Ok(())
                });

        entry!(dict, "dump", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    println!("ds =  {:?} ", stack);
                    Ok(())
                });

        entry!(dict, "cr", |_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
                    println!("");
                    Ok(())
                });

        entry!(dict, ".", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    println!("{}", try_stack!(stack.pop()));
                    Ok(())
                });

        entry!(dict, "branch", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let y = try_stack!(stack.pop());
                    let x = try_stack!(stack.pop());
                    stack.push(if x == y { 1 } else { 0 });
                    Ok(())
                });

        entry!(dict, "emit", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
                    let x = try_stack!(stack.pop());
                    if x < 0 || x > 256 { return Err(ForthError::InvalidCharacter) }
                    print!("{}", x as u8 as char);
                    Ok(())
                });

        let square = {
            let mut s = Statement::new();
            s.push_back(ForthCell::Word(dict.get("dup").unwrap().clone()));
            s.push_back(ForthCell::Word(dict.get("*").unwrap().clone()));
            s
        };
        dict.insert_entry(Entry::from_statement("square", square));

        Interpreter {
            dictionary: dict,
            last_result: None,
        }
    }

    pub fn exec(&mut self, statement: &str) -> ForthResult<()> {
        let mut words = statement.split(|c: char| c.is_whitespace());
        let mut stmt = Statement::new();
        while let Some(word) = words.next() { match word {
            "(" => while let Some(w) = words.next() { if w == ")" { break; } },
            "\\" => while let Some(w) = words.next() { if w == "\n" { break; } },
            ":" => {
                let mut comp = Statement::new();
                let name = match words.next() {
                    Some(w) => w,
                    None => return Err(ForthError::WordNameNotFound),
                };
                while let Some(w) = words.next() {
                    if w == ";" {
                        self.dictionary.insert_entry(Entry::from_statement(name, comp));
                        return Ok(());
                    }
                    match w.parse::<i32>() {
                        Ok(n) => comp.push_back(ForthCell::Number(n)),
                        Err(_) => comp.push_back(ForthCell::Word(self.dictionary.get(w).unwrap().clone())),
                    }
                }
                return Err(ForthError::UnterminatedWordDefinition);
            },
            _ => match word.parse::<i32>() {
                Ok(n) => {
                    stmt.push_back(ForthCell::Number(n));
                },
                Err(_) => {
                    if let Some(elem) = self.dictionary.get(word) {
                        stmt.push_back(ForthCell::Word(elem.clone()));
                    } else {
                        return Err(ForthError::WordNotFound)
                    }
                },
            },

        }}

        match stmt.run(self) {
            Err(e) => {
                self.last_result = None;
                Err(e)
            },
            Ok(s) => {
                self.last_result = Some(s);
                Ok(())
            }
        }
    }
}<|endoftext|>


<commit_before>use super::{
    EdgeType,
    Incoming,
};
use super::graph::{
    Graph,
    IndexType,
    NodeIndex,
};

#[derive(Debug)]
struct Vf2State<Ix, Ty> {
    /// The current mapping M(s) of nodes from G0 → G1 and G1 → G0,
    /// NodeIndex::end() for no mapping.
    mapping: Vec<NodeIndex<Ix>>,
    /// out[i] is non-zero if i is in either M_0(s) or Tout_0(s)
    /// These are all the next vertices that are not mapped yet, but
    /// have an outgoing edge from the mapping.
    out: Vec<usize>,
    /// ins[i] is non-zero if i is in either M_0(s) or Tin_0(s)
    /// These are all the incoming vertices, those not mapped yet, but
    /// have an edge from them into the mapping.
    /// Unused if graph is undirected -- it's identical with out in that case.
    ins: Vec<usize>,
    generation: usize,
}

impl<Ix, Ty> Vf2State<Ix, Ty> where Ix: IndexType, Ty: EdgeType,
{
    pub fn new(c0: usize) -> Self
    {
        let mut state = Vf2State {
            mapping: Vec::with_capacity(c0),
            out: Vec::with_capacity(c0),
            ins: Vec::with_capacity(c0 * <Ty as EdgeType>::is_directed() as usize),
            generation: 0,
        };
        for _ in (0..c0) {
            state.mapping.push(NodeIndex::end());
            state.out.push(0);
            if <Ty as EdgeType>::is_directed() {
                state.ins.push(0);
            }
        }
        state
    }

    /// Return **true** if we have a complete mapping
    pub fn is_complete(&self) -> bool
    {
        self.generation == self.mapping.len()
    }

    /// Add mapping **from** <-> **to** to the state.
    pub fn push_mapping<N, E>(&mut self, from: NodeIndex<Ix>, to: NodeIndex<Ix>,
                              g: &Graph<N, E, Ty, Ix>)
    {
        self.generation += 1;
        let s = self.generation;
        self.mapping[from.index()] = to;
        // update T0 & T1 ins/outs
        // T0out: Node in G0 not in M0 but successor of a node in M0.
        // st.out[0]: Node either in M0 or successor of M0
        for ix in g.neighbors(from) {
            if self.out[ix.index()] == 0 {
                self.out[ix.index()] = s;
            }
        }
        if g.is_directed() {
            for ix in g.neighbors_directed(from, Incoming) {
                if self.ins[ix.index()] == 0 {
                    self.ins[ix.index()] = s;
                }
            }
        }
    }

    /// Restore the state to before the last added mapping
    pub fn pop_mapping<N, E>(&mut self, from: NodeIndex<Ix>,
                             g: &Graph<N, E, Ty, Ix>)
    {
        let s = self.generation;
        self.generation -= 1;

        // undo (n, m) mapping
        self.mapping[from.index()] = NodeIndex::end();

        // unmark in ins and outs
        for ix in g.neighbors(from) {
            if self.out[ix.index()] == s {
                self.out[ix.index()] = 0;
            }
        }
        if g.is_directed() {
            for ix in g.neighbors_directed(from, Incoming) {
                if self.ins[ix.index()] == s {
                    self.ins[ix.index()] = 0;
                }
            }
        }
    }

    /// Find the next (least) node in the Tout set.
    pub fn next_out_index(&self, from_index: usize) -> Option<usize>
    {
        self.out[from_index..].iter()
                    .enumerate()
                    .filter(|&(index, elt)| *elt > 0 && self.mapping[from_index + index] == NodeIndex::end())
                    .next()
                    .map(|(index, _)| index)
    }

    /// Find the next (least) node in the Tin set.
    pub fn next_in_index(&self, from_index: usize) -> Option<usize>
    {
        if !<Ty as EdgeType>::is_directed() {
            return None
        }
        self.ins[from_index..].iter()
                    .enumerate()
                    .filter(|&(index, elt)| *elt > 0 && self.mapping[from_index + index] == NodeIndex::end())
                    .next()
                    .map(|(index, _)| index)
    }

    /// Find the next (least) node in the N - M set.
    pub fn next_rest_index(&self, from_index: usize) -> Option<usize>
    {
        self.mapping[from_index..].iter()
               .enumerate()
               .filter(|&(_, elt)| *elt == NodeIndex::end())
               .next()
               .map(|(index, _)| index)
    }
}

/// Return **true** if the graphs **g0** and **g1** are isomorphic.
///
/// Using the VF2 algorithm.
///
/// Not implemented: Vertex or edge weight matching.
///
/// ## References
///
/// * A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs
///   Luigi P. Cordella, Pasquale Foggia, Carlo Sansone,
///   and Mario Vento
pub fn is_isomorphic<N, E, Ix, Ty>(g0: &Graph<N, E, Ty, Ix>,
                                   g1: &Graph<N, E, Ty, Ix>) -> bool where
    Ix: IndexType,
    Ty: EdgeType,
{
    if g0.node_count() != g1.node_count() || g0.edge_count() != g1.edge_count() {
        return false
    }

    /// Return Some(bool) if isomorphism is decided, else None.
    fn try_match<N, E, Ix, Ty>(st: &mut [Vf2State<Ix, Ty>; 2],
                               g0: &Graph<N, E, Ty, Ix>,
                               g1: &Graph<N, E, Ty, Ix>) -> Option<bool> where
        Ix: IndexType,
        Ty: EdgeType,
    {
        let g = [g0, g1];
        let graph_indices = 0..2us;
        let end = NodeIndex::end();

        // if all are mapped -- we are done and have an iso
        if st[0].is_complete() {
            return Some(true)
        }

        // A "depth first" search of a valid mapping from graph 1 to graph 2

        // F(s, n, m) -- evaluate state s and add mapping n <-> m

        // Find least T1out node (in st.out[1] but not in M[1])
        #[derive(Copy, Clone, PartialEq, Debug)]
        enum OpenList {
            Out,
            In,
            Other,
        }
        let mut open_list = OpenList::Out;

        let mut to_index;
        let mut from_index = None;
        // Try the out list
        to_index = st[1].next_out_index(0);

        if to_index.is_some() {
            from_index = st[0].next_out_index(0);
            open_list = OpenList::Out;
        }

        // Try the in list
        if to_index.is_none() || from_index.is_none() {
            to_index = st[1].next_in_index(0);

            if to_index.is_some() {
                from_index = st[0].next_in_index(0);
                open_list = OpenList::In;
            }
        }

        // Try the other list -- disconnected graph
        if to_index.is_none() || from_index.is_none() {
            to_index = st[1].next_rest_index(0);
            if to_index.is_some() {
                from_index = st[0].next_rest_index(0);
                open_list = OpenList::Other;
            }
        }

        let (cand0, cand1) = match (from_index, to_index) {
            (Some(n), Some(m)) => (n, m),
            // No more candidates
            _ => return None,
        };

        let mut nx = NodeIndex::new(cand0);
        let mx = NodeIndex::new(cand1);

        let mut first = true;

        'candidates: loop {
            if !first {
                // Find the next node index to try on the `from` side of the mapping
                let start = nx.index() + 1;
                let cand0 = match open_list {
                    OpenList::Out => st[0].next_out_index(start),
                    OpenList::In => st[0].next_in_index(start),
                    OpenList::Other => st[0].next_rest_index(start),
                }.map(|c| c + start); // compensate for start offset.
                nx = match cand0 {
                    None => break, // no more candidates
                    Some(ix) => NodeIndex::new(ix),
                };
                debug_assert!(nx.index() >= start);
            }
            first = false;

            let nodes = [nx, mx];

            /*
            print!("Mapping state: ");
            for (index, nmap) in st.mapping[0].iter().enumerate() {
                if *nmap == end {
                    continue;
                }
                print!("{} => {}, ", index, nmap.index());
            }
            println!("{} => {}", nx.index(), mx.index());
            */

            // Check syntactic feasibility of mapping by ensuring adjacencies
            // of nx map to adjacencies of mx.
            //
            // nx == map to => mx
            //
            // R_succ
            //
            // Check that every neighbor of nx is mapped to a neighbor of mx,
            // then check the reverse, from mx to nx. Check that they have the same
            // count of edges.
            let mut succ_count = [0, 0];
            for j in graph_indices.clone() {
                for n_neigh in g[j].neighbors(nodes[j]) {
                    succ_count[j] += 1;
                    let m_neigh = st[j].mapping[n_neigh.index()];
                    if m_neigh == end {
                        continue;
                    }
                    let has_edge = g[1-j].find_edge(nodes[1-j], m_neigh).is_some();
                    if !has_edge {
                        continue 'candidates;
                    }
                }
            }
            if succ_count[0] != succ_count[1] {
                continue 'candidates;
            }

            // R_pred
            if g[0].is_directed() {
                let mut pred_count = [0, 0];
                for j in graph_indices.clone() {
                    for n_neigh in g[j].neighbors_directed(nodes[j], Incoming) {
                        pred_count[j] += 1;
                        let m_neigh = st[j].mapping[n_neigh.index()];
                        if m_neigh == end {
                            continue;
                        }
                        let has_edge = g[1-j].find_edge(m_neigh, nodes[1-j]).is_some();
                        if !has_edge {
                            continue 'candidates;
                        }
                    }
                }
                if pred_count[0] != pred_count[1] {
                    continue 'candidates;
                }
            }

            // Check cardinalities of open sets, important to prune
            // the search tree.
            //
            // counts in Tin/Tout
            let t0in = st[0].ins.iter().filter(|&&x| x > 0).count();
            let t1in = st[1].ins.iter().filter(|&&x| x > 0).count();
            let t0out = st[0].out.iter().filter(|&&x| x > 0).count();
            let t1out = st[1].out.iter().filter(|&&x| x > 0).count();
            if t0in != t1in || t0out != t1out {
                continue 'candidates;
            }

            // counts in N0 - M0 - Tin - Tout
            // equal to count in N - ins - outs
            let n0 = st[0].ins.iter().zip(st[0].out.iter())
                        .filter(|&(&a, &b)| a == 0 && b == 0)
                        .count();
            let n1 = st[1].ins.iter().zip(st[1].out.iter())
                        .filter(|&(&a, &b)| a == 0 && b == 0)
                        .count();

            if n0 != n1 {
                continue 'candidates;
            }

            // Add mapping nx <-> mx to the state
            for j in graph_indices.clone() {
                st[j].push_mapping(nodes[j], nodes[1-j], g[j]);
            }

            // Recurse
            match try_match(st, g0, g1) {
                None => {}
                result => return result,
            }

            // Restore state.
            for j in graph_indices.clone() {
                st[j].pop_mapping(nodes[j], g[j]);
            }
        }
        None
    }
    let mut st = [Vf2State::new(g0.node_count()),
                  Vf2State::new(g1.node_count())];
    try_match(&mut st, g0, g1).unwrap_or(false)
}

<commit_msg>Keep count of Tout and Tin cardinality<commit_after>use super::{
    EdgeType,
    Incoming,
};
use super::graph::{
    Graph,
    IndexType,
    NodeIndex,
};

#[derive(Debug)]
struct Vf2State<Ix, Ty> {
    /// The current mapping M(s) of nodes from G0 → G1 and G1 → G0,
    /// NodeIndex::end() for no mapping.
    mapping: Vec<NodeIndex<Ix>>,
    /// out[i] is non-zero if i is in either M_0(s) or Tout_0(s)
    /// These are all the next vertices that are not mapped yet, but
    /// have an outgoing edge from the mapping.
    out: Vec<usize>,
    /// ins[i] is non-zero if i is in either M_0(s) or Tin_0(s)
    /// These are all the incoming vertices, those not mapped yet, but
    /// have an edge from them into the mapping.
    /// Unused if graph is undirected -- it's identical with out in that case.
    ins: Vec<usize>,
    out_size: usize,
    ins_size: usize,
    generation: usize,
}

impl<Ix, Ty> Vf2State<Ix, Ty> where Ix: IndexType, Ty: EdgeType,
{
    pub fn new(c0: usize) -> Self
    {
        let mut state = Vf2State {
            mapping: Vec::with_capacity(c0),
            out: Vec::with_capacity(c0),
            ins: Vec::with_capacity(c0 * <Ty as EdgeType>::is_directed() as usize),
            out_size: 0,
            ins_size: 0,
            generation: 0,
        };
        for _ in (0..c0) {
            state.mapping.push(NodeIndex::end());
            state.out.push(0);
            if <Ty as EdgeType>::is_directed() {
                state.ins.push(0);
            }
        }
        state
    }

    /// Return **true** if we have a complete mapping
    pub fn is_complete(&self) -> bool
    {
        self.generation == self.mapping.len()
    }

    /// Add mapping **from** <-> **to** to the state.
    pub fn push_mapping<N, E>(&mut self, from: NodeIndex<Ix>, to: NodeIndex<Ix>,
                              g: &Graph<N, E, Ty, Ix>)
    {
        self.generation += 1;
        let s = self.generation;
        self.mapping[from.index()] = to;
        // update T0 & T1 ins/outs
        // T0out: Node in G0 not in M0 but successor of a node in M0.
        // st.out[0]: Node either in M0 or successor of M0
        for ix in g.neighbors(from) {
            if self.out[ix.index()] == 0 {
                self.out[ix.index()] = s;
            }
            self.out_size += 1;
        }
        if g.is_directed() {
            for ix in g.neighbors_directed(from, Incoming) {
                if self.ins[ix.index()] == 0 {
                    self.ins[ix.index()] = s;
                }
            }
            self.ins_size += 1;
        }
    }

    /// Restore the state to before the last added mapping
    pub fn pop_mapping<N, E>(&mut self, from: NodeIndex<Ix>,
                             g: &Graph<N, E, Ty, Ix>)
    {
        let s = self.generation;
        self.generation -= 1;

        // undo (n, m) mapping
        self.mapping[from.index()] = NodeIndex::end();

        // unmark in ins and outs
        for ix in g.neighbors(from) {
            if self.out[ix.index()] == s {
                self.out[ix.index()] = 0;
            }
            self.out_size -= 1;
        }
        if g.is_directed() {
            for ix in g.neighbors_directed(from, Incoming) {
                if self.ins[ix.index()] == s {
                    self.ins[ix.index()] = 0;
                }
            }
            self.ins_size -= 1;
        }
    }

    /// Find the next (least) node in the Tout set.
    pub fn next_out_index(&self, from_index: usize) -> Option<usize>
    {
        self.out[from_index..].iter()
                    .enumerate()
                    .filter(|&(index, elt)| *elt > 0 && self.mapping[from_index + index] == NodeIndex::end())
                    .next()
                    .map(|(index, _)| index)
    }

    /// Find the next (least) node in the Tin set.
    pub fn next_in_index(&self, from_index: usize) -> Option<usize>
    {
        if !<Ty as EdgeType>::is_directed() {
            return None
        }
        self.ins[from_index..].iter()
                    .enumerate()
                    .filter(|&(index, elt)| *elt > 0 && self.mapping[from_index + index] == NodeIndex::end())
                    .next()
                    .map(|(index, _)| index)
    }

    /// Find the next (least) node in the N - M set.
    pub fn next_rest_index(&self, from_index: usize) -> Option<usize>
    {
        self.mapping[from_index..].iter()
               .enumerate()
               .filter(|&(_, elt)| *elt == NodeIndex::end())
               .next()
               .map(|(index, _)| index)
    }
}

/// Return **true** if the graphs **g0** and **g1** are isomorphic.
///
/// Using the VF2 algorithm.
///
/// Not implemented: Vertex or edge weight matching.
///
/// ## References
///
/// * A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs
///   Luigi P. Cordella, Pasquale Foggia, Carlo Sansone,
///   and Mario Vento
pub fn is_isomorphic<N, E, Ix, Ty>(g0: &Graph<N, E, Ty, Ix>,
                                   g1: &Graph<N, E, Ty, Ix>) -> bool where
    Ix: IndexType,
    Ty: EdgeType,
{
    if g0.node_count() != g1.node_count() || g0.edge_count() != g1.edge_count() {
        return false
    }

    /// Return Some(bool) if isomorphism is decided, else None.
    fn try_match<N, E, Ix, Ty>(st: &mut [Vf2State<Ix, Ty>; 2],
                               g0: &Graph<N, E, Ty, Ix>,
                               g1: &Graph<N, E, Ty, Ix>) -> Option<bool> where
        Ix: IndexType,
        Ty: EdgeType,
    {
        let g = [g0, g1];
        let graph_indices = 0..2us;
        let end = NodeIndex::end();

        // if all are mapped -- we are done and have an iso
        if st[0].is_complete() {
            return Some(true)
        }

        // A "depth first" search of a valid mapping from graph 1 to graph 2

        // F(s, n, m) -- evaluate state s and add mapping n <-> m

        // Find least T1out node (in st.out[1] but not in M[1])
        #[derive(Copy, Clone, PartialEq, Debug)]
        enum OpenList {
            Out,
            In,
            Other,
        }
        let mut open_list = OpenList::Out;

        let mut to_index;
        let mut from_index = None;
        // Try the out list
        to_index = st[1].next_out_index(0);

        if to_index.is_some() {
            from_index = st[0].next_out_index(0);
            open_list = OpenList::Out;
        }

        // Try the in list
        if to_index.is_none() || from_index.is_none() {
            to_index = st[1].next_in_index(0);

            if to_index.is_some() {
                from_index = st[0].next_in_index(0);
                open_list = OpenList::In;
            }
        }

        // Try the other list -- disconnected graph
        if to_index.is_none() || from_index.is_none() {
            to_index = st[1].next_rest_index(0);
            if to_index.is_some() {
                from_index = st[0].next_rest_index(0);
                open_list = OpenList::Other;
            }
        }

        let (cand0, cand1) = match (from_index, to_index) {
            (Some(n), Some(m)) => (n, m),
            // No more candidates
            _ => return None,
        };

        let mut nx = NodeIndex::new(cand0);
        let mx = NodeIndex::new(cand1);

        let mut first = true;

        'candidates: loop {
            if !first {
                // Find the next node index to try on the `from` side of the mapping
                let start = nx.index() + 1;
                let cand0 = match open_list {
                    OpenList::Out => st[0].next_out_index(start),
                    OpenList::In => st[0].next_in_index(start),
                    OpenList::Other => st[0].next_rest_index(start),
                }.map(|c| c + start); // compensate for start offset.
                nx = match cand0 {
                    None => break, // no more candidates
                    Some(ix) => NodeIndex::new(ix),
                };
                debug_assert!(nx.index() >= start);
            }
            first = false;

            let nodes = [nx, mx];

            /*
            print!("Mapping state: ");
            for (index, nmap) in st.mapping[0].iter().enumerate() {
                if *nmap == end {
                    continue;
                }
                print!("{} => {}, ", index, nmap.index());
            }
            println!("{} => {}", nx.index(), mx.index());
            */

            // Check syntactic feasibility of mapping by ensuring adjacencies
            // of nx map to adjacencies of mx.
            //
            // nx == map to => mx
            //
            // R_succ
            //
            // Check that every neighbor of nx is mapped to a neighbor of mx,
            // then check the reverse, from mx to nx. Check that they have the same
            // count of edges.
            let mut succ_count = [0, 0];
            for j in graph_indices.clone() {
                for n_neigh in g[j].neighbors(nodes[j]) {
                    succ_count[j] += 1;
                    let m_neigh = st[j].mapping[n_neigh.index()];
                    if m_neigh == end {
                        continue;
                    }
                    let has_edge = g[1-j].find_edge(nodes[1-j], m_neigh).is_some();
                    if !has_edge {
                        continue 'candidates;
                    }
                }
            }
            if succ_count[0] != succ_count[1] {
                continue 'candidates;
            }

            // R_pred
            if g[0].is_directed() {
                let mut pred_count = [0, 0];
                for j in graph_indices.clone() {
                    for n_neigh in g[j].neighbors_directed(nodes[j], Incoming) {
                        pred_count[j] += 1;
                        let m_neigh = st[j].mapping[n_neigh.index()];
                        if m_neigh == end {
                            continue;
                        }
                        let has_edge = g[1-j].find_edge(m_neigh, nodes[1-j]).is_some();
                        if !has_edge {
                            continue 'candidates;
                        }
                    }
                }
                if pred_count[0] != pred_count[1] {
                    continue 'candidates;
                }
            }

            // Check cardinalities of open sets, important to prune
            // the search tree.
            //
            // counts in Tin/Tout
            if st[0].out_size != st[0].out_size ||
               st[1].ins_size != st[1].ins_size {
                continue 'candidates;
            }

            // counts in N0 - M0 - Tin - Tout
            // equal to count in N - ins - outs
            let x0 = st[0].ins.iter().zip(st[0].out.iter())
                        .filter(|&(&a, &b)| a == 0 && b == 0)
                        .count();
            let x1 = st[1].ins.iter().zip(st[1].out.iter())
                        .filter(|&(&a, &b)| a == 0 && b == 0)
                        .count();

            if x0 != x1 {
                continue 'candidates;
            }

            // Add mapping nx <-> mx to the state
            for j in graph_indices.clone() {
                st[j].push_mapping(nodes[j], nodes[1-j], g[j]);
            }

            // Recurse
            match try_match(st, g0, g1) {
                None => {}
                result => return result,
            }

            // Restore state.
            for j in graph_indices.clone() {
                st[j].pop_mapping(nodes[j], g[j]);
            }
        }
        None
    }
    let mut st = [Vf2State::new(g0.node_count()),
                  Vf2State::new(g1.node_count())];
    try_match(&mut st, g0, g1).unwrap_or(false)
}

<|endoftext|>


<commit_before>use core::intrinsics::{atomic_xadd, atomic_xsub, breakpoint, volatile_load, volatile_store};
use core::mem;
use core::prelude::*;
use core::raw;

use common::{RingBuffer, Queue};

#[allow(improper_ctypes)]
extern {
    pub fn switch_to_user(user_stack: *mut u8) -> *mut u8;
}

/// Size of each processes's memory region in bytes
pub const PROC_MEMORY_SIZE : usize = 2048;

static mut MEMORIES: [[u8; PROC_MEMORY_SIZE]; 8] = [[0; PROC_MEMORY_SIZE]; 8];
static mut FREE_MEMORY_IDX: usize = 0;

#[derive(Copy,Clone,PartialEq,Eq)]
pub enum State {
    Running,
    Waiting
}

#[derive(Copy,Clone)]
pub struct Callback {
    pub r0: usize,
    pub r1: usize,
    pub r2: usize,
    pub pc: usize
}

pub struct Process<'a> {
    /// The process's memory.
    memory: &'a mut [u8],

    exposed_memory_start: *mut u8,

    /// The offset in `memory` to use for the process stack.
    cur_stack: *mut u8,

    wait_pc: usize,

    pub state: State,

    pub callbacks: RingBuffer<'a, Callback>
}

impl<'a> Process<'a> {
    pub unsafe fn create(init_fn: fn(*mut u8, usize)) -> Option<Process<'a>> {
        let cur_idx = atomic_xadd(&mut FREE_MEMORY_IDX, 1);
        if cur_idx > MEMORIES.len() {
            atomic_xsub(&mut FREE_MEMORY_IDX, 1);
            None
        } else {
            let memory = &mut MEMORIES[cur_idx];

            let stack_bottom = &mut memory[PROC_MEMORY_SIZE - 4] as *mut u8;

            // Take callback buffer from bottom of process memory
            let callback_len = 10;
            let callback_buf = mem::transmute(raw::Slice {
                data: &mut memory[0] as *mut u8 as *mut Option<Callback>,
                len: callback_len
            });
            let callback_size = mem::size_of::<Option<Callback>>();

            let mut callbacks = RingBuffer::new(callback_buf);

            let exposed_memory_start =
                    &mut memory[callback_len * callback_size] as *mut u8;

            let exposed_mem_len = memory.len() - callback_len * callback_size;
            callbacks.enqueue(Callback {
                pc: init_fn as usize,
                r0: exposed_memory_start as usize,
                r1: exposed_mem_len,
                r2: 0
            });

            Some(Process {
                memory: memory,
                exposed_memory_start: exposed_memory_start,
                cur_stack: stack_bottom as *mut u8,
                wait_pc: 0,
                state: State::Waiting,
                callbacks: callbacks
            })
        }
    }

    pub fn in_exposed_bounds(&self, start_addr: *const u8, size: usize) -> bool {
        /* Won't work until app is passed it's memory to allocate within
         * unsafe {
            start_addr >= self.exposed_memory_start &&
                (start_addr.offset(size as isize))
                    <=
                (&self.memory[self.memory.len()])
        }*/
        true
    }

    pub unsafe fn alloc(&mut self, size: usize) -> Option<&mut [u8]> {
        use core::raw::Slice;

        let mem_len = self.memory.len();
        let end_mem = &mut self.memory[mem_len - 1] as *mut u8;
        let new_start = self.exposed_memory_start.offset(size as isize);
        if new_start >= end_mem {
            None
        } else {
            let buf = Slice {
                data: self.exposed_memory_start,
                len: size
            };
            self.exposed_memory_start = new_start;
            Some(mem::transmute(buf))
        }
    }

    pub unsafe fn free<T>(&mut self, _: *mut T) {}

    pub fn pop_syscall_stack(&mut self) {
        let pspr = self.cur_stack as *const usize;
        unsafe {
            self.wait_pc = volatile_load(pspr.offset(6));
            self.cur_stack =
                (self.cur_stack as *mut usize).offset(8) as *mut u8;
        }
    }

    /// Context switch to the process.
    pub unsafe fn switch_to_callback(&mut self, callback: Callback) {
        // Fill in initial stack expected by SVC handler
        // Top minus 8 u32s for r0-r3, r12, lr, pc and xPSR
        let stack_bottom = (self.cur_stack as *mut usize).offset(-8);
        volatile_store(stack_bottom.offset(7), 0x01000000);
        volatile_store(stack_bottom.offset(6), callback.pc);
        // Set the LR register to the saved PC so the callback returns to
        // wherever wait was called. Set lowest bit to one because of THUMB
        // instruction requirements.
        volatile_store(stack_bottom.offset(5), self.wait_pc | 0x1);
        volatile_store(stack_bottom, callback.r0);
        volatile_store(stack_bottom.offset(1), callback.r1);
        volatile_store(stack_bottom.offset(2), callback.r2);

        self.cur_stack = stack_bottom as *mut u8;
        self.switch_to();
    }

    /// Context switch to the process.
    pub unsafe fn switch_to(&mut self) {
        if self.cur_stack < self.exposed_memory_start {
            breakpoint();
        }
        let psp = switch_to_user(self.cur_stack);
        self.cur_stack = psp;
    }

    pub fn svc_number(&self) -> Option<u8> {
        let psp = self.cur_stack as *const *const u16;
        unsafe {
            let pcptr = volatile_load((psp as *const *const u16).offset(6));
            let svc_instr = volatile_load(pcptr.offset(-1));
            Some((svc_instr & 0xff) as u8)
        }
    }

    pub fn lr(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(5)) }
    }

    pub fn r0(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr) }
    }

    pub fn set_r0(&mut self, val: isize) {
        let pspr = self.cur_stack as *mut isize;
        unsafe { volatile_store(pspr, val) }
    }

    pub fn r1(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(1)) }
    }

    pub fn r2(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(2)) }
    }

    pub fn r3(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(3)) }
    }

}

<commit_msg>Only allow `ALLOW` if app passes memory it owns<commit_after>use core::intrinsics::{atomic_xadd, atomic_xsub, breakpoint, volatile_load, volatile_store};
use core::mem;
use core::prelude::*;
use core::raw;

use common::{RingBuffer, Queue};

#[allow(improper_ctypes)]
extern {
    pub fn switch_to_user(user_stack: *mut u8) -> *mut u8;
}

/// Size of each processes's memory region in bytes
pub const PROC_MEMORY_SIZE : usize = 2048;

static mut MEMORIES: [[u8; PROC_MEMORY_SIZE]; 8] = [[0; PROC_MEMORY_SIZE]; 8];
static mut FREE_MEMORY_IDX: usize = 0;

#[derive(Copy,Clone,PartialEq,Eq)]
pub enum State {
    Running,
    Waiting
}

#[derive(Copy,Clone)]
pub struct Callback {
    pub r0: usize,
    pub r1: usize,
    pub r2: usize,
    pub pc: usize
}

pub struct Process<'a> {
    /// The process's memory.
    memory: &'a mut [u8],

    exposed_memory_start: *mut u8,

    /// The offset in `memory` to use for the process stack.
    cur_stack: *mut u8,

    wait_pc: usize,

    pub state: State,

    pub callbacks: RingBuffer<'a, Callback>
}

impl<'a> Process<'a> {
    pub unsafe fn create(init_fn: fn(*mut u8, usize)) -> Option<Process<'a>> {
        let cur_idx = atomic_xadd(&mut FREE_MEMORY_IDX, 1);
        if cur_idx > MEMORIES.len() {
            atomic_xsub(&mut FREE_MEMORY_IDX, 1);
            None
        } else {
            let memory = &mut MEMORIES[cur_idx];

            let stack_bottom = &mut memory[PROC_MEMORY_SIZE - 4] as *mut u8;

            // Take callback buffer from bottom of process memory
            let callback_len = 10;
            let callback_buf = mem::transmute(raw::Slice {
                data: &mut memory[0] as *mut u8 as *mut Option<Callback>,
                len: callback_len
            });
            let callback_size = mem::size_of::<Option<Callback>>();

            let mut callbacks = RingBuffer::new(callback_buf);

            let exposed_memory_start =
                    &mut memory[callback_len * callback_size] as *mut u8;

            let exposed_mem_len = memory.len() - callback_len * callback_size;
            callbacks.enqueue(Callback {
                pc: init_fn as usize,
                r0: exposed_memory_start as usize,
                r1: exposed_mem_len,
                r2: 0
            });

            Some(Process {
                memory: memory,
                exposed_memory_start: exposed_memory_start,
                cur_stack: stack_bottom as *mut u8,
                wait_pc: 0,
                state: State::Waiting,
                callbacks: callbacks
            })
        }
    }

    pub fn in_exposed_bounds(&self, buf_start_addr: *const u8, size: usize)
            -> bool {
        use core::raw::Repr;

        let buf_end_addr = ((buf_start_addr as usize) + size) as *const u8;

        let mem = self.memory.repr();
        let mem_end = ((mem.data as usize) + mem.len) as *const u8;

        buf_start_addr >= self.exposed_memory_start && buf_end_addr <= mem_end
    }

    pub unsafe fn alloc(&mut self, size: usize) -> Option<&mut [u8]> {
        use core::raw::Slice;

        let mem_len = self.memory.len();
        let end_mem = &mut self.memory[mem_len - 1] as *mut u8;
        let new_start = self.exposed_memory_start.offset(size as isize);
        if new_start >= end_mem {
            None
        } else {
            let buf = Slice {
                data: self.exposed_memory_start,
                len: size
            };
            self.exposed_memory_start = new_start;
            Some(mem::transmute(buf))
        }
    }

    pub unsafe fn free<T>(&mut self, _: *mut T) {}

    pub fn pop_syscall_stack(&mut self) {
        let pspr = self.cur_stack as *const usize;
        unsafe {
            self.wait_pc = volatile_load(pspr.offset(6));
            self.cur_stack =
                (self.cur_stack as *mut usize).offset(8) as *mut u8;
        }
    }

    /// Context switch to the process.
    pub unsafe fn switch_to_callback(&mut self, callback: Callback) {
        // Fill in initial stack expected by SVC handler
        // Top minus 8 u32s for r0-r3, r12, lr, pc and xPSR
        let stack_bottom = (self.cur_stack as *mut usize).offset(-8);
        volatile_store(stack_bottom.offset(7), 0x01000000);
        volatile_store(stack_bottom.offset(6), callback.pc);
        // Set the LR register to the saved PC so the callback returns to
        // wherever wait was called. Set lowest bit to one because of THUMB
        // instruction requirements.
        volatile_store(stack_bottom.offset(5), self.wait_pc | 0x1);
        volatile_store(stack_bottom, callback.r0);
        volatile_store(stack_bottom.offset(1), callback.r1);
        volatile_store(stack_bottom.offset(2), callback.r2);

        self.cur_stack = stack_bottom as *mut u8;
        self.switch_to();
    }

    /// Context switch to the process.
    pub unsafe fn switch_to(&mut self) {
        if self.cur_stack < self.exposed_memory_start {
            breakpoint();
        }
        let psp = switch_to_user(self.cur_stack);
        self.cur_stack = psp;
    }

    pub fn svc_number(&self) -> Option<u8> {
        let psp = self.cur_stack as *const *const u16;
        unsafe {
            let pcptr = volatile_load((psp as *const *const u16).offset(6));
            let svc_instr = volatile_load(pcptr.offset(-1));
            Some((svc_instr & 0xff) as u8)
        }
    }

    pub fn lr(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(5)) }
    }

    pub fn r0(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr) }
    }

    pub fn set_r0(&mut self, val: isize) {
        let pspr = self.cur_stack as *mut isize;
        unsafe { volatile_store(pspr, val) }
    }

    pub fn r1(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(1)) }
    }

    pub fn r2(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(2)) }
    }

    pub fn r3(&self) -> usize {
        let pspr = self.cur_stack as *const usize;
        unsafe { volatile_load(pspr.offset(3)) }
    }

}

<|endoftext|>


<commit_before>use std::thread;
use std::sync::Arc;
use std::thread::JoinHandle;

use config::Config;

pub struct ProcessHandler {
    pub config: Config,
}

impl ProcessHandler {
    pub fn new(config: Config) -> ProcessHandler {
        ProcessHandler {config: config}
    }

    pub fn execute(self) -> JoinHandle<()> {
        let config = Arc::new(self.config).clone();
        thread::spawn(move|| {
            println!("Launching {:?} using command: {:?}, with args: {:?}, from directory: {:?}", config.name, config.cmd, config.args, config.cwd);
        })
    }
}<commit_msg>spawning processes from process_handler<commit_after>use std::thread;
use std::sync::Arc;
use std::thread::JoinHandle;
use std::process::Command;

use config::Config;

pub struct ProcessHandler {
    pub config: Config,
}

impl ProcessHandler {
    pub fn new(config: Config) -> ProcessHandler {
        ProcessHandler {config: config}
    }

    pub fn execute(self) -> JoinHandle<()> {
        let config = Arc::new(self.config).clone();
        thread::spawn(move|| {
            loop {
                println!("Launching {:?} using command: {:?}, with args: {:?}, from directory: {:?}", config.name, config.cmd, config.args, config.cwd);
                let mut child = Command::new(&config.cmd)
                            .current_dir(&config.cwd)
                            .spawn()
                            .unwrap_or_else(|e| { panic!("failed to execute child: {}", e) });

                child.wait().unwrap_or_else(|e| { panic!("failed to wait on child: {}", e) });
            }
        })
    }
}<|endoftext|>


<commit_before>use std::thread;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use ram::chunk::Chunks;
use ram::cell::CellHeader;
use ram::tombstone::Tombstone;

pub mod combine;
pub mod compact;

pub struct Cleaner {
    chunks: Arc<Chunks>,
    stopped: Arc<AtomicBool>,
    segments_compact_per_turn: usize,
    segments_combine_per_turn: usize,
}

// The two-level cleaner
impl Cleaner {
    pub fn new_and_start(chunks: Arc<Chunks>) -> Cleaner {
        debug!("Starting cleaner for {} chunks", chunks.list.len());
        let stop_tag = Arc::new(AtomicBool::new(false));
        let segments_compact_per_turn = chunks.list[0].segs.len() / 10 + 1;
        let segments_combine_per_turn = chunks.list[0].segs.len() / 20 + 2;
        let cleaner = Cleaner {
            chunks: chunks.clone(),
            stopped: stop_tag.clone(),
            segments_compact_per_turn,
            segments_combine_per_turn
        };
        let stop_tag_ref_clone = stop_tag.clone();
        let checks_ref_clone = chunks.clone();
        thread::Builder::new()
            .name("Cleaner sweeper".into())
            .spawn(move || {
                while !stop_tag.load(Ordering::Relaxed) {
                    for chunk in &chunks.list {
                        chunk.apply_dead_entry();
                        chunk.scan_tombstone_survival();
                    }
                    thread::sleep(Duration::from_millis(100));
                }
            });
        thread::Builder::new()
            .name("Cleaner main".into())
            .spawn(move || {
                while !stop_tag_ref_clone.load(Ordering::Relaxed) {
                    for chunk in &checks_ref_clone.list {
                        trace!("Cleaning chunk {}", chunk.id);
                        let mut cleaned_space: usize = 0;
                        {
                            // compact
                            let segments_for_compact = chunk.segs_for_compact_cleaner();
                            if !segments_for_compact.is_empty() {
                                debug!("Chunk {} have {} segments to compact, overflow {}",
                                       chunk.id, segments_for_compact.len(), segments_compact_per_turn);
                                cleaned_space += segments_for_compact.into_iter()
                                    .take(segments_compact_per_turn) // limit max segment to clean per turn
                                    .map(|segment|
                                        compact::CompactCleaner::clean_segment(chunk, &segment))
                                    .sum::<usize>();
                            }
                        }

                        {
                            // combine
                            let segments_candidates_for_combine: Vec<_> = chunk.segs_for_combine_cleaner();
                            let segments_for_combine: Vec<_> = segments_candidates_for_combine.into_iter()
                                    .take(segments_combine_per_turn)
                                    .collect();
                            if !segments_for_combine.is_empty() {
                                debug!("Chunk {} have {} segments to combine, overflow {}",
                                       chunk.id, segments_for_combine.len(), segments_combine_per_turn);
                                cleaned_space += combine::CombinedCleaner::combine_segments(chunk, &segments_for_combine);
                            }
                        }

                        chunk.total_space.fetch_sub(cleaned_space, Ordering::Relaxed);
                        chunk.check_and_archive_segments();
                    }
                    debug!("Cleaner round finished");
                    thread::sleep(Duration::from_millis(100));
                }
                warn!("Cleaner main thread stopped");
            });
        return cleaner;
    }
}<commit_msg>scan for dead tombstone right before cleaner<commit_after>use std::thread;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use ram::chunk::Chunks;
use ram::cell::CellHeader;
use ram::tombstone::Tombstone;

pub mod combine;
pub mod compact;

pub struct Cleaner {
    chunks: Arc<Chunks>,
    stopped: Arc<AtomicBool>,
    segments_compact_per_turn: usize,
    segments_combine_per_turn: usize,
}

// The two-level cleaner
impl Cleaner {
    pub fn new_and_start(chunks: Arc<Chunks>) -> Cleaner {
        debug!("Starting cleaner for {} chunks", chunks.list.len());
        let stop_tag = Arc::new(AtomicBool::new(false));
        let segments_compact_per_turn = chunks.list[0].segs.len() / 10 + 1;
        let segments_combine_per_turn = chunks.list[0].segs.len() / 20 + 2;
        let cleaner = Cleaner {
            chunks: chunks.clone(),
            stopped: stop_tag.clone(),
            segments_compact_per_turn,
            segments_combine_per_turn
        };
        let stop_tag_ref_clone = stop_tag.clone();
        let checks_ref_clone = chunks.clone();
        thread::Builder::new()
            .name("Cleaner sweeper".into())
            .spawn(move || {
                while !stop_tag.load(Ordering::Relaxed) {
                    for chunk in &chunks.list {
                        chunk.apply_dead_entry();
                    }
                    thread::sleep(Duration::from_millis(100));
                }
            });
        thread::Builder::new()
            .name("Cleaner main".into())
            .spawn(move || {
                while !stop_tag_ref_clone.load(Ordering::Relaxed) {
                    for chunk in &checks_ref_clone.list {
                        // have to put it right here for cleaners will clear the tombstone death counter
                        chunk.scan_tombstone_survival();
                        trace!("Cleaning chunk {}", chunk.id);
                        let mut cleaned_space: usize = 0;
                        {
                            // compact
                            let segments_for_compact = chunk.segs_for_compact_cleaner();
                            if !segments_for_compact.is_empty() {
                                debug!("Chunk {} have {} segments to compact, overflow {}",
                                       chunk.id, segments_for_compact.len(), segments_compact_per_turn);
                                cleaned_space += segments_for_compact.into_iter()
                                    .take(segments_compact_per_turn) // limit max segment to clean per turn
                                    .map(|segment|
                                        compact::CompactCleaner::clean_segment(chunk, &segment))
                                    .sum::<usize>();
                            }
                        }

                        {
                            // combine
                            let segments_candidates_for_combine: Vec<_> = chunk.segs_for_combine_cleaner();
                            let segments_for_combine: Vec<_> = segments_candidates_for_combine.into_iter()
                                    .take(segments_combine_per_turn)
                                    .collect();
                            if !segments_for_combine.is_empty() {
                                debug!("Chunk {} have {} segments to combine, overflow {}",
                                       chunk.id, segments_for_combine.len(), segments_combine_per_turn);
                                cleaned_space += combine::CombinedCleaner::combine_segments(chunk, &segments_for_combine);
                            }
                        }

                        chunk.total_space.fetch_sub(cleaned_space, Ordering::Relaxed);
                        chunk.check_and_archive_segments();
                    }
                    debug!("Cleaner round finished");
                    thread::sleep(Duration::from_millis(100));
                }
                warn!("Cleaner main thread stopped");
            });
        return cleaner;
    }
}<|endoftext|>


<commit_before>//! TODO Documentation

use Output;
use render::Texture;
use wlroots_sys::{wlr_backend, wlr_render_colored_ellipse, wlr_render_colored_quad,
                  wlr_render_texture_create, wlr_render_with_matrix, wlr_renderer,
                  wlr_renderer_begin, wlr_renderer_clear, wlr_renderer_destroy, wlr_renderer_end,
                  wlr_gles2_renderer_create};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let renderer = wlr_gles2_renderer_create(backend);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output>(&mut self, output: &'output mut Output) -> Renderer<'output> {
        unsafe {
            output.make_current();
            wlr_renderer_begin(self.renderer, output.as_ptr());
            Renderer { renderer: self.renderer,
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    /// Create a texture using this renderer
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    pub fn clear(&mut self, float: [f32; 4]) {
        unsafe { wlr_renderer_clear(self.renderer, &float) }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_with_matrix(&mut self, texture: &Texture, matrix: &[f32; 16]) -> bool {
        // TODO FIXME Add alpha as param
        unsafe { wlr_render_with_matrix(self.renderer, texture.as_ptr(), matrix, 1.0) }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_quad(self.renderer, color, matrix) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_ellipse(self.renderer, color, matrix) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            // TODO What about damage tracking?
            self.output.swap_buffers(None, None);
        }
    }
}

unsafe fn create_texture(renderer: *mut wlr_renderer) -> Option<Texture> {
    let texture = wlr_render_texture_create(renderer);
    if texture.is_null() {
        wlr_log!(L_ERROR, "Could not create texture");
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<commit_msg>Fixed renderer from wlroots update<commit_after>//! TODO Documentation

use Output;
use render::Texture;
use wlroots_sys::{wlr_backend, wlr_render_colored_ellipse, wlr_render_colored_quad,
                  wlr_render_texture_create, wlr_render_with_matrix, wlr_renderer,
                  wlr_renderer_begin, wlr_renderer_clear, wlr_renderer_destroy, wlr_renderer_end,
                  wlr_gles2_renderer_create};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let renderer = wlr_gles2_renderer_create(backend);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output>(&mut self, output: &'output mut Output) -> Renderer<'output> {
        unsafe {
            output.make_current();
            let (width, height) = output.dimensions();
            wlr_renderer_begin(self.renderer, width, height);
            Renderer { renderer: self.renderer,
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    /// Create a texture using this renderer
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    pub fn clear(&mut self, float: [f32; 4]) {
        unsafe { wlr_renderer_clear(self.renderer, float.as_ptr()) }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_with_matrix(&mut self, texture: &Texture, matrix: &[f32; 16]) -> bool {
        // TODO FIXME Add alpha as param
        unsafe { wlr_render_with_matrix(self.renderer, texture.as_ptr(), matrix.as_ptr(), 1.0) }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_quad(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_ellipse(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            // TODO What about damage tracking?
            self.output.swap_buffers(None, None);
        }
    }
}

unsafe fn create_texture(renderer: *mut wlr_renderer) -> Option<Texture> {
    let texture = wlr_render_texture_create(renderer);
    if texture.is_null() {
        wlr_log!(L_ERROR, "Could not create texture");
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<|endoftext|>