<commit_before>use std::fmt::{Display, Error, Formatter};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Ge,
    Gt,
    Eql,       // ==
    EqlStrict, // ===
    Le,
    Lt,
    Minus,
    Neq,       // !=
    NeqStrict, // !==
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 70,
    Add = 60,
    Equality = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Ge | BinOp::Gt | BinOp::Eql | BinOp::Le | BinOp::Lt |
                BinOp::Neq | BinOp::EqlStrict | BinOp::NeqStrict
                => Precedence::Equality,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Ge => write!(fmt, ">="),
            BinOp::Gt => write!(fmt, ">"),
            BinOp::Eql => write!(fmt, "=="),
            BinOp::EqlStrict => write!(fmt, "==="),
            BinOp::Le => write!(fmt, "<="),
            BinOp::Lt => write!(fmt, "<"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Neq => write!(fmt, "!="),
            BinOp::NeqStrict => write!(fmt, "!=="),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Call(Box<Exp>, Vec<Box<Exp>>),
    Defun(Option<String>, Vec<String>, Vec<Stmt>),
    Float(f64),
    InstanceVar(Box<Exp>, String),
    Neg(Box<Exp>),
    Null,
    NewObject(Box<Exp>, Vec<Box<Exp>>),
    Object(Vec<(String, Box<Exp>)>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    TypeOf(Box<Exp>),
    Str(String),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
            _ => Precedence::Const
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Exp {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Call(ref func, ref args) => {
                try!(write!(fmt, "{}(", func));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg));
                }

                write!(fmt, ")")
            }
            Exp::Defun(ref opt, ref params, ref body) => {
                try!(write!(fmt, "function"));

                if let &Some(ref func) = opt {
                    try!(write!(fmt, " {}", func));
                }

                try!(write!(fmt, "("));

                for (i, param) in params.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", param));
                }

                try!(write!(fmt, ") {{\n"));
                stmt_block!(body);

                let indent : String = (0..indent_level).map(|_| " ").collect();

                write!(fmt, "{}}}", indent)
            }
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::InstanceVar(ref obj, ref name) => write!(fmt, "{}.{}", obj, name),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::NewObject(ref name, ref args) => {
                try!(write!(fmt, "new {}(", name));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg))
                }

                write!(fmt, ")")
            }
            Exp::Null => write!(fmt, "null"),
            Exp::Object(ref properties) => {
                if properties.is_empty() {
                    return write!(fmt, "{{}}");
                }

                try!(writeln!(fmt, "{{"));

                let indent : String = (0..indent_level + 2).map(|_| " ").collect();

                for (i, &(ref name, ref prop)) in properties.iter().enumerate() {
                    if i != 0 {
                        try!(writeln!(fmt, ","));
                    }

                    try!(write!(fmt, "{}{}: ", indent, name));
                    try!(prop.fmt_helper(&mut fmt, indent_level + 2));
                }

                write!(fmt, "\n}}")
            }
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::TypeOf(ref e) => write!(fmt, "typeof {}", e),
            Exp::Str(ref s) => write!(fmt, "\"{}\"", s),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

impl Display for Exp {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}

#[derive(Clone, Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    Empty,
    If(Exp, Vec<Stmt>, Vec<Stmt>),
    Ret(Exp),
    Seq(Box<Stmt>, Box<Stmt>),
    Try(Vec<Stmt>, Vec<Stmt>, Vec<Stmt>),
    Throw(Box<Exp>),
    While(Exp, Vec<Stmt>),
}

impl Stmt {
    pub fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        macro_rules! indented_stmt {
            ($s:expr) => {
                try!($s.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        macro_rules! exp_semi {
            ($exp:expr) => {{
                try!($exp.fmt_helper(&mut fmt, indent_level));
                writeln!(fmt, ";")
            }}
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => {
                try!(write!(fmt, "{}{} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::BareExp(ref exp) => {
                try!(write!(fmt, "{}", indent));
                exp_semi!(exp)
            }
            Stmt::Decl(ref v, ref exp) => {
                try!(write!(fmt, "{}var {} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::Empty => Ok(()),
            Stmt::If(ref e, ref s, ref els) => {
                try!(write!(fmt, "{}if (", indent));
                try!(e.fmt_helper(&mut fmt, indent_level + 2));
                try!(writeln!(fmt, ") {{\n"));
                stmt_block!(s);

                if els.len() > 0 {
                    stmt_block!(s);
                }

                //if let &Some(ref stmt) = els {
                //    try!(write!(fmt, "{}else {{\n", indent));
                //    indented_stmt!(stmt);
                //    try!(write!(fmt, "{}}}\n", indent));
                //}

                Ok(())
            }
            Stmt::Ret(ref e) => {
                try!(write!(fmt, "{}return ", indent));
                exp_semi!(e)
            }
            Stmt::Seq(ref s1, ref s2) => {
                try!(s1.fmt_helper(&mut fmt, indent_level));
                s2.fmt_helper(&mut fmt, indent_level)
            }
            Stmt::Throw(ref e) => {
                write!(fmt, "{}throw {}", indent, e)
            }
            Stmt::Try(ref stmt, ref catch_block, ref finally_block) => {
                try!(write!(fmt, "{}try {{\n", indent));
                stmt_block!(stmt);
                try!(write!(fmt, "{}}}\n", indent));

                if catch_block.len() > 0 {
                    try!(write!(fmt, "{}catch {{\n", indent));
                    stmt_block!(catch_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                if finally_block.len() > 0 {
                    try!(write!(fmt, "{}finally {{\n", indent));
                    stmt_block!(finally_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                Ok(())
            }
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                stmt_block!(stmt);
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<commit_msg>add try/catch variable binding<commit_after>use std::fmt::{Display, Error, Formatter};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Ge,
    Gt,
    Eql,       // ==
    EqlStrict, // ===
    Le,
    Lt,
    Minus,
    Neq,       // !=
    NeqStrict, // !==
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 70,
    Add = 60,
    Equality = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Ge | BinOp::Gt | BinOp::Eql | BinOp::Le | BinOp::Lt |
                BinOp::Neq | BinOp::EqlStrict | BinOp::NeqStrict
                => Precedence::Equality,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Ge => write!(fmt, ">="),
            BinOp::Gt => write!(fmt, ">"),
            BinOp::Eql => write!(fmt, "=="),
            BinOp::EqlStrict => write!(fmt, "==="),
            BinOp::Le => write!(fmt, "<="),
            BinOp::Lt => write!(fmt, "<"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Neq => write!(fmt, "!="),
            BinOp::NeqStrict => write!(fmt, "!=="),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Call(Box<Exp>, Vec<Box<Exp>>),
    Defun(Option<String>, Vec<String>, Vec<Stmt>),
    Float(f64),
    InstanceVar(Box<Exp>, String),
    Neg(Box<Exp>),
    Null,
    NewObject(Box<Exp>, Vec<Box<Exp>>),
    Object(Vec<(String, Box<Exp>)>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    TypeOf(Box<Exp>),
    Str(String),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
            _ => Precedence::Const
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Exp {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Call(ref func, ref args) => {
                try!(write!(fmt, "{}(", func));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg));
                }

                write!(fmt, ")")
            }
            Exp::Defun(ref opt, ref params, ref body) => {
                try!(write!(fmt, "function"));

                if let &Some(ref func) = opt {
                    try!(write!(fmt, " {}", func));
                }

                try!(write!(fmt, "("));

                for (i, param) in params.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", param));
                }

                try!(write!(fmt, ") {{\n"));
                stmt_block!(body);

                let indent : String = (0..indent_level).map(|_| " ").collect();

                write!(fmt, "{}}}", indent)
            }
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::InstanceVar(ref obj, ref name) => write!(fmt, "{}.{}", obj, name),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::NewObject(ref name, ref args) => {
                try!(write!(fmt, "new {}(", name));

                for (i, arg) in args.iter().enumerate() {
                    if i != 0 {
                        try!(write!(fmt, ", "));
                    }

                    try!(write!(fmt, "{}", arg))
                }

                write!(fmt, ")")
            }
            Exp::Null => write!(fmt, "null"),
            Exp::Object(ref properties) => {
                if properties.is_empty() {
                    return write!(fmt, "{{}}");
                }

                try!(writeln!(fmt, "{{"));

                let indent : String = (0..indent_level + 2).map(|_| " ").collect();

                for (i, &(ref name, ref prop)) in properties.iter().enumerate() {
                    if i != 0 {
                        try!(writeln!(fmt, ","));
                    }

                    try!(write!(fmt, "{}{}: ", indent, name));
                    try!(prop.fmt_helper(&mut fmt, indent_level + 2));
                }

                write!(fmt, "\n}}")
            }
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::TypeOf(ref e) => write!(fmt, "typeof {}", e),
            Exp::Str(ref s) => write!(fmt, "\"{}\"", s),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

impl Display for Exp {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}

#[derive(Clone, Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    Empty,
    If(Exp, Vec<Stmt>, Vec<Stmt>),
    Ret(Exp),
    Seq(Box<Stmt>, Box<Stmt>),
    Try(Vec<Stmt>, Vec<Stmt>, String, Vec<Stmt>), // try block, catch block, catch variable, finally block
    Throw(Box<Exp>),
    While(Exp, Vec<Stmt>),
}

impl Stmt {
    pub fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! stmt_block {
            ($stmt:expr) => {
                for s in $stmt {
                    try!(s.fmt_helper(&mut fmt, indent_level + 2))
                }
            }
        }

        macro_rules! indented_stmt {
            ($s:expr) => {
                try!($s.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        macro_rules! exp_semi {
            ($exp:expr) => {{
                try!($exp.fmt_helper(&mut fmt, indent_level));
                writeln!(fmt, ";")
            }}
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => {
                try!(write!(fmt, "{}{} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::BareExp(ref exp) => {
                try!(write!(fmt, "{}", indent));
                exp_semi!(exp)
            }
            Stmt::Decl(ref v, ref exp) => {
                try!(write!(fmt, "{}var {} = ", indent, v));
                exp_semi!(exp)
            }
            Stmt::Empty => Ok(()),
            Stmt::If(ref e, ref s, ref els) => {
                try!(write!(fmt, "{}if (", indent));
                try!(e.fmt_helper(&mut fmt, indent_level + 2));
                try!(writeln!(fmt, ") {{\n"));
                stmt_block!(s);

                if els.len() > 0 {
                    stmt_block!(s);
                }

                //if let &Some(ref stmt) = els {
                //    try!(write!(fmt, "{}else {{\n", indent));
                //    indented_stmt!(stmt);
                //    try!(write!(fmt, "{}}}\n", indent));
                //}

                Ok(())
            }
            Stmt::Ret(ref e) => {
                try!(write!(fmt, "{}return ", indent));
                exp_semi!(e)
            }
            Stmt::Seq(ref s1, ref s2) => {
                try!(s1.fmt_helper(&mut fmt, indent_level));
                s2.fmt_helper(&mut fmt, indent_level)
            }
            Stmt::Throw(ref e) => {
                write!(fmt, "{}throw {}", indent, e)
            }
            Stmt::Try(ref stmt, ref catch_block, ref finally_block) => {
                try!(write!(fmt, "{}try {{\n", indent));
                stmt_block!(stmt);
                try!(write!(fmt, "{}}}\n", indent));

                if catch_block.len() > 0 {
                    try!(write!(fmt, "{}catch {{\n", indent));
                    stmt_block!(catch_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                if finally_block.len() > 0 {
                    try!(write!(fmt, "{}finally {{\n", indent));
                    stmt_block!(finally_block);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                Ok(())
            }
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                stmt_block!(stmt);
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;

use BinaryOp::*;
use Data::*;
use Expression::*;

#[derive(Clone,Debug,PartialEq)]
pub enum Data {
    Nil,
    Boolean(bool),
    Number(f64),
    Str(String),
}

impl fmt::Display for Data {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Nil => write!(f, "nil"),
            &Boolean(b) => write!(f, "{}", b),
            &Number(n) => write!(f, "{}", n),
            &Str(ref s) => write!(f, "{}", s),
        }
    }
}

#[derive(Clone,Debug,PartialEq)]
pub enum Expression {
    NilLiteral,
    BooleanLiteral(bool),
    NumberLiteral(f64),
    StrLiteral(String),
    Variable(String),
    ParenExpr(Box<Expression>),
    Block(Vec<Expression>),
    Assignment{left: String, right: Box<Expression>},
    FunctionCall{name: String, args: Vec<Expression>},
    BinaryExpr{left: Box<Expression>, op: BinaryOp, right: Box<Expression>},
    IfExpr{cond: Box<Expression>, body: Box<Expression>, else_branch: Option<Box<Expression>>},
    WhileLoop{cond: Box<Expression>, body: Box<Expression>},
}

impl Expression {
    pub fn eval(&self, p: &mut Program) -> Data {
        match self {
            &NilLiteral => Nil,
            &BooleanLiteral(b) => Boolean(b),
            &NumberLiteral(n) => Number(n),
            &StrLiteral(ref s) => Str(s.clone()),
            &Variable(ref name) => {
                match p.vars.get(name) {
                    Some(d) => d.clone(),
                    None => Nil,
                }
            },
            &ParenExpr(ref expr) => expr.eval(p),
            &Block(ref exprs) => {
                let mut last_result = Data::Nil;
                for expr in exprs {
                    last_result = expr.eval(p);
                }
                last_result
            },
            &Assignment{ref left, ref right} => {
                let res = right.eval(p);
                p.vars.insert(left.clone(), res.clone());
                res
            },
            &FunctionCall{ref name, ref args} => {
                let f = match name.as_ref() {
                    "println" => println,
                    _ => return Nil,
                };

                let mut new_args = Vec::new();
                for item in args.iter() {
                    new_args.push(item.eval(p));
                }

                f(&new_args)
            },
            &BinaryExpr{ref left, ref op, ref right} => {
                let (left_data, right_data) = (left.eval(p), right.eval(p));
                op.eval(&left_data, &right_data)
            },
            &IfExpr{ref cond, ref body, ref else_branch} => {
                if cond.eval(p) != Boolean(false) {
                    body.eval(p)
                } else if let &Some(ref b) = else_branch {
                    b.eval(p)
                } else {
                    Nil
                }
            },
            &WhileLoop{ref cond, ref body} => {
                let mut last_data = Nil;
                loop {
                    if let Boolean(false) = cond.eval(p) {
                        break
                    }

                    last_data = body.eval(p);
                }

                last_data
            },
        }
    }
}

#[derive(Clone,Debug,PartialEq)]
pub enum BinaryOp {
    Add,
    Sub,
    Mul,
    Div,
    Mod,
    Eq,
    Lt,
    LtEq,
    Gt,
    GtEq,
}

impl BinaryOp {
    fn eval(&self, left: &Data, right: &Data) -> Data {
        match (self, left, right) {
            (&Add, &Number(l), &Number(r)) => Number(l+r),
            (&Sub, &Number(l), &Number(r)) => Number(l-r),
            (&Mul, &Number(l), &Number(r)) => Number(l*r),
            (&Div, &Number(l), &Number(r)) => Number(l/r),
            (&Mod, &Number(l), &Number(r)) => Number(l%r),
            (&Eq, _, _) => Boolean(left == right),
            (&Lt, &Number(l), &Number(r)) => Boolean(l < r),
            (&LtEq, &Number(l), &Number(r)) => Boolean(l <= r),
            (&Gt, &Number(l), &Number(r)) => Boolean(l > r),
            (&GtEq, &Number(l), &Number(r)) => Boolean(l >= r),
            _ => Nil,
        }
    }

    pub fn precendence(&self) -> u8 {
        match self {
            &Add => 3,
            &Sub => 3,
            &Mul => 4,
            &Div => 4,
            &Mod => 2,
            &Eq => 0,
            &Lt => 1,
            &LtEq => 1,
            &Gt => 1,
            &GtEq => 1,
        }
    }
}

pub struct Program {
    pub vars: HashMap<String, Data>,
    pub funcs: HashMap<String, i64>,
}

impl Program {
    pub fn new() -> Self {
        Program {
            vars: HashMap::new(),
            funcs: HashMap::new(),
        }
    }

    pub fn eval(&mut self, e: &Expression) -> Data {
        e.eval(self)
    }
}

pub fn println(v: &Vec<Data>) -> Data {
    for item in v {
        print!("{}", item);
    }
    println!("");
    Data::Nil
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::BinaryOp::*;
    use super::Data::*;
    use super::Expression::*;

    #[test]
    fn test_variables() {
        let ast = vec![
            Assignment {
                left: "x".to_owned(),
                right: Box::new(NumberLiteral(2.0)),
            },
            Assignment {
                left: "y".to_owned(),
                right: Box::new(Variable("x".to_owned())),
            },
            Assignment {
                left: "z".to_owned(),
                right: Box::new(Variable("w".to_owned())),
            },
            Assignment {
                left: "y".to_owned(),
                right: Box::new(BinaryExpr {
                    left: Box::new(Variable("y".to_owned())),
                    op: Add,
                    right: Box::new(NumberLiteral(1.0)),
                }),
            },
        ];

        let mut p = Program::new();
        for exp in ast {
            p.eval(&exp);
        }

        assert_eq!(p.vars.get("w"), None);
        assert_eq!(p.vars.get("x"), Some(&Number(2.0)));
        assert_eq!(p.vars.get("y"), Some(&Number(3.0)));
        assert_eq!(p.vars.get("z"), Some(&Nil));
    }

    #[test]
    fn test_paren_expr() {
        let expr = Expression::ParenExpr(
            Box::new(Expression::BooleanLiteral(true)),
        );

        let mut p = Program::new();
        assert_eq!(expr.eval(&mut p), Data::Boolean(true));
    }

    #[test]
    fn test_block() {
        let block = Expression::Block(vec![
            Expression::NumberLiteral(1.0),
            Expression::NumberLiteral(2.0),
            Expression::NumberLiteral(3.0),
        ]);

        let mut p = Program::new();
        assert_eq!(block.eval(&mut p), Data::Number(3.0));
    }

    #[test]
    fn test_binary_expr() {
        let cases = vec![
            // Add
            (Add, Number(1.0), Number(2.0), Number(3.0)),
            (Add, Boolean(false), Number(2.0), Nil),
            (Add, Number(2.0), Str("1.0".to_owned()), Nil),
            // Sub
            (Sub, Number(1.0), Number(2.0), Number(-1.0)),
            (Sub, Boolean(false), Number(2.0), Nil),
            (Sub, Number(2.0), Str("1.0".to_owned()), Nil),
            // Mul
            (Mul, Number(1.5), Number(2.0), Number(3.0)),
            (Mul, Boolean(false), Number(2.0), Nil),
            (Mul, Number(2.0), Str("1.0".to_owned()), Nil),
            // Div
            (Div, Number(1.0), Number(2.0), Number(0.5)),
            (Div, Boolean(false), Number(2.0), Nil),
            (Div, Number(2.0), Str("1.0".to_owned()), Nil),
            // Mod
            (Mod, Number(17.0), Number(4.0), Number(1.0)),
            (Mod, Boolean(false), Number(2.0), Nil),
            (Mod, Number(2.0), Str("1.0".to_owned()), Nil),
            // Eq
            (Eq, Number(2.0), Number(2.0), Boolean(true)),
            (Eq, Number(-2.0), Number(2.0), Boolean(false)),
            (Eq, Str("foo".to_owned()), Str("foo".to_owned()), Boolean(true)),
            (Eq, Str("foo".to_owned()), Str("bar".to_owned()), Boolean(false)),
            (Eq, Boolean(false), Boolean(false), Boolean(true)),
            (Eq, Boolean(true), Boolean(true), Boolean(true)),
            (Eq, Boolean(true), Boolean(false), Boolean(false)),
            (Eq, Nil, Boolean(false), Boolean(false)),
            (Eq, Nil, Nil, Boolean(true)),
            // Lt
            (Lt, Number(-1.0), Number(0.5), Boolean(true)),
            (Lt, Number(1.0), Number(1.0), Boolean(false)),
            (Lt, Number(1.0), Number(0.5), Boolean(false)),
            // LtEq
            (LtEq, Number(-1.0), Number(0.5), Boolean(true)),
            (LtEq, Number(1.0), Number(1.0), Boolean(true)),
            (LtEq, Number(1.0), Number(0.5), Boolean(false)),
            // Gt
            (Gt, Number(-1.0), Number(0.5), Boolean(false)),
            (Gt, Number(1.0), Number(1.0), Boolean(false)),
            (Gt, Number(1.0), Number(0.5), Boolean(true)),
            // GtEq
            (GtEq, Number(-1.0), Number(0.5), Boolean(false)),
            (GtEq, Number(1.0), Number(1.0), Boolean(true)),
            (GtEq, Number(1.0), Number(0.5), Boolean(true)),
        ];

        for (op, left, right, exp) in cases {
            assert_eq!(op.eval(&left, &right), exp);
        }
    }

    #[test]
    fn test_if_expr() {
        let mut p = Program::new();

        let cases = vec![
            (BooleanLiteral(true), NumberLiteral(1.0), None, Number(1.0)),
            (BooleanLiteral(true), NumberLiteral(1.0), Some(NumberLiteral(2.0)), Number(1.0)),
            (BooleanLiteral(false), NumberLiteral(1.0), None, Nil),
            (BooleanLiteral(false), NumberLiteral(1.0), Some(NumberLiteral(2.0)), Number(2.0)),
        ];

        for (cond, body, else_branch, exp) in cases {
            let x = IfExpr {
                cond: Box::new(cond),
                body: Box::new(body),
                else_branch: else_branch.map(|e| Box::new(e)),
            };

            assert_eq!(x.eval(&mut p), exp);
        }
    }

    #[test]
    fn test_while_loop() {
        let mut p = Program::new();
        p.eval(&Assignment{left: "x".to_owned(), right: Box::new(NumberLiteral(0.0))});

        let out = p.eval(&WhileLoop {
            cond: Box::new(BinaryExpr {
                left: Box::new(Variable("x".to_owned())),
                op: Lt,
                right: Box::new(NumberLiteral(5.0)),
            }),
            body: Box::new(Assignment {
                left: "x".to_owned(),
                right: Box::new(BinaryExpr {
                    left: Box::new(Variable("x".to_owned())),
                    op: Add,
                    right: Box::new(NumberLiteral(1.0)),
                }),
            }),
        });

        assert_eq!(out, Number(5.0));
        assert_eq!(p.eval(&Variable("x".to_owned())), Number(5.0));
    }
}
<commit_msg>Remove unused funcs from Program<commit_after>use std::collections::HashMap;
use std::fmt;

use BinaryOp::*;
use Data::*;
use Expression::*;

#[derive(Clone,Debug,PartialEq)]
pub enum Data {
    Nil,
    Boolean(bool),
    Number(f64),
    Str(String),
}

impl fmt::Display for Data {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Nil => write!(f, "nil"),
            &Boolean(b) => write!(f, "{}", b),
            &Number(n) => write!(f, "{}", n),
            &Str(ref s) => write!(f, "{}", s),
        }
    }
}

#[derive(Clone,Debug,PartialEq)]
pub enum Expression {
    NilLiteral,
    BooleanLiteral(bool),
    NumberLiteral(f64),
    StrLiteral(String),
    Variable(String),
    ParenExpr(Box<Expression>),
    Block(Vec<Expression>),
    Assignment{left: String, right: Box<Expression>},
    FunctionCall{name: String, args: Vec<Expression>},
    BinaryExpr{left: Box<Expression>, op: BinaryOp, right: Box<Expression>},
    IfExpr{cond: Box<Expression>, body: Box<Expression>, else_branch: Option<Box<Expression>>},
    WhileLoop{cond: Box<Expression>, body: Box<Expression>},
}

impl Expression {
    pub fn eval(&self, p: &mut Program) -> Data {
        match self {
            &NilLiteral => Nil,
            &BooleanLiteral(b) => Boolean(b),
            &NumberLiteral(n) => Number(n),
            &StrLiteral(ref s) => Str(s.clone()),
            &Variable(ref name) => {
                match p.vars.get(name) {
                    Some(d) => d.clone(),
                    None => Nil,
                }
            },
            &ParenExpr(ref expr) => expr.eval(p),
            &Block(ref exprs) => {
                let mut last_result = Data::Nil;
                for expr in exprs {
                    last_result = expr.eval(p);
                }
                last_result
            },
            &Assignment{ref left, ref right} => {
                let res = right.eval(p);
                p.vars.insert(left.clone(), res.clone());
                res
            },
            &FunctionCall{ref name, ref args} => {
                let f = match name.as_ref() {
                    "println" => println,
                    _ => return Nil,
                };

                let mut new_args = Vec::new();
                for item in args.iter() {
                    new_args.push(item.eval(p));
                }

                f(&new_args)
            },
            &BinaryExpr{ref left, ref op, ref right} => {
                let (left_data, right_data) = (left.eval(p), right.eval(p));
                op.eval(&left_data, &right_data)
            },
            &IfExpr{ref cond, ref body, ref else_branch} => {
                if cond.eval(p) != Boolean(false) {
                    body.eval(p)
                } else if let &Some(ref b) = else_branch {
                    b.eval(p)
                } else {
                    Nil
                }
            },
            &WhileLoop{ref cond, ref body} => {
                let mut last_data = Nil;
                loop {
                    if let Boolean(false) = cond.eval(p) {
                        break
                    }

                    last_data = body.eval(p);
                }

                last_data
            },
        }
    }
}

#[derive(Clone,Debug,PartialEq)]
pub enum BinaryOp {
    Add,
    Sub,
    Mul,
    Div,
    Mod,
    Eq,
    Lt,
    LtEq,
    Gt,
    GtEq,
}

impl BinaryOp {
    fn eval(&self, left: &Data, right: &Data) -> Data {
        match (self, left, right) {
            (&Add, &Number(l), &Number(r)) => Number(l+r),
            (&Sub, &Number(l), &Number(r)) => Number(l-r),
            (&Mul, &Number(l), &Number(r)) => Number(l*r),
            (&Div, &Number(l), &Number(r)) => Number(l/r),
            (&Mod, &Number(l), &Number(r)) => Number(l%r),
            (&Eq, _, _) => Boolean(left == right),
            (&Lt, &Number(l), &Number(r)) => Boolean(l < r),
            (&LtEq, &Number(l), &Number(r)) => Boolean(l <= r),
            (&Gt, &Number(l), &Number(r)) => Boolean(l > r),
            (&GtEq, &Number(l), &Number(r)) => Boolean(l >= r),
            _ => Nil,
        }
    }

    pub fn precendence(&self) -> u8 {
        match self {
            &Add => 3,
            &Sub => 3,
            &Mul => 4,
            &Div => 4,
            &Mod => 2,
            &Eq => 0,
            &Lt => 1,
            &LtEq => 1,
            &Gt => 1,
            &GtEq => 1,
        }
    }
}

pub struct Program {
    pub vars: HashMap<String, Data>,
}

impl Program {
    pub fn new() -> Self {
        Program {
            vars: HashMap::new(),
        }
    }

    pub fn eval(&mut self, e: &Expression) -> Data {
        e.eval(self)
    }
}

pub fn println(v: &Vec<Data>) -> Data {
    for item in v {
        print!("{}", item);
    }
    println!("");
    Data::Nil
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::BinaryOp::*;
    use super::Data::*;
    use super::Expression::*;

    #[test]
    fn test_variables() {
        let ast = vec![
            Assignment {
                left: "x".to_owned(),
                right: Box::new(NumberLiteral(2.0)),
            },
            Assignment {
                left: "y".to_owned(),
                right: Box::new(Variable("x".to_owned())),
            },
            Assignment {
                left: "z".to_owned(),
                right: Box::new(Variable("w".to_owned())),
            },
            Assignment {
                left: "y".to_owned(),
                right: Box::new(BinaryExpr {
                    left: Box::new(Variable("y".to_owned())),
                    op: Add,
                    right: Box::new(NumberLiteral(1.0)),
                }),
            },
        ];

        let mut p = Program::new();
        for exp in ast {
            p.eval(&exp);
        }

        assert_eq!(p.vars.get("w"), None);
        assert_eq!(p.vars.get("x"), Some(&Number(2.0)));
        assert_eq!(p.vars.get("y"), Some(&Number(3.0)));
        assert_eq!(p.vars.get("z"), Some(&Nil));
    }

    #[test]
    fn test_paren_expr() {
        let expr = Expression::ParenExpr(
            Box::new(Expression::BooleanLiteral(true)),
        );

        let mut p = Program::new();
        assert_eq!(expr.eval(&mut p), Data::Boolean(true));
    }

    #[test]
    fn test_block() {
        let block = Expression::Block(vec![
            Expression::NumberLiteral(1.0),
            Expression::NumberLiteral(2.0),
            Expression::NumberLiteral(3.0),
        ]);

        let mut p = Program::new();
        assert_eq!(block.eval(&mut p), Data::Number(3.0));
    }

    #[test]
    fn test_binary_expr() {
        let cases = vec![
            // Add
            (Add, Number(1.0), Number(2.0), Number(3.0)),
            (Add, Boolean(false), Number(2.0), Nil),
            (Add, Number(2.0), Str("1.0".to_owned()), Nil),
            // Sub
            (Sub, Number(1.0), Number(2.0), Number(-1.0)),
            (Sub, Boolean(false), Number(2.0), Nil),
            (Sub, Number(2.0), Str("1.0".to_owned()), Nil),
            // Mul
            (Mul, Number(1.5), Number(2.0), Number(3.0)),
            (Mul, Boolean(false), Number(2.0), Nil),
            (Mul, Number(2.0), Str("1.0".to_owned()), Nil),
            // Div
            (Div, Number(1.0), Number(2.0), Number(0.5)),
            (Div, Boolean(false), Number(2.0), Nil),
            (Div, Number(2.0), Str("1.0".to_owned()), Nil),
            // Mod
            (Mod, Number(17.0), Number(4.0), Number(1.0)),
            (Mod, Boolean(false), Number(2.0), Nil),
            (Mod, Number(2.0), Str("1.0".to_owned()), Nil),
            // Eq
            (Eq, Number(2.0), Number(2.0), Boolean(true)),
            (Eq, Number(-2.0), Number(2.0), Boolean(false)),
            (Eq, Str("foo".to_owned()), Str("foo".to_owned()), Boolean(true)),
            (Eq, Str("foo".to_owned()), Str("bar".to_owned()), Boolean(false)),
            (Eq, Boolean(false), Boolean(false), Boolean(true)),
            (Eq, Boolean(true), Boolean(true), Boolean(true)),
            (Eq, Boolean(true), Boolean(false), Boolean(false)),
            (Eq, Nil, Boolean(false), Boolean(false)),
            (Eq, Nil, Nil, Boolean(true)),
            // Lt
            (Lt, Number(-1.0), Number(0.5), Boolean(true)),
            (Lt, Number(1.0), Number(1.0), Boolean(false)),
            (Lt, Number(1.0), Number(0.5), Boolean(false)),
            // LtEq
            (LtEq, Number(-1.0), Number(0.5), Boolean(true)),
            (LtEq, Number(1.0), Number(1.0), Boolean(true)),
            (LtEq, Number(1.0), Number(0.5), Boolean(false)),
            // Gt
            (Gt, Number(-1.0), Number(0.5), Boolean(false)),
            (Gt, Number(1.0), Number(1.0), Boolean(false)),
            (Gt, Number(1.0), Number(0.5), Boolean(true)),
            // GtEq
            (GtEq, Number(-1.0), Number(0.5), Boolean(false)),
            (GtEq, Number(1.0), Number(1.0), Boolean(true)),
            (GtEq, Number(1.0), Number(0.5), Boolean(true)),
        ];

        for (op, left, right, exp) in cases {
            assert_eq!(op.eval(&left, &right), exp);
        }
    }

    #[test]
    fn test_if_expr() {
        let mut p = Program::new();

        let cases = vec![
            (BooleanLiteral(true), NumberLiteral(1.0), None, Number(1.0)),
            (BooleanLiteral(true), NumberLiteral(1.0), Some(NumberLiteral(2.0)), Number(1.0)),
            (BooleanLiteral(false), NumberLiteral(1.0), None, Nil),
            (BooleanLiteral(false), NumberLiteral(1.0), Some(NumberLiteral(2.0)), Number(2.0)),
        ];

        for (cond, body, else_branch, exp) in cases {
            let x = IfExpr {
                cond: Box::new(cond),
                body: Box::new(body),
                else_branch: else_branch.map(|e| Box::new(e)),
            };

            assert_eq!(x.eval(&mut p), exp);
        }
    }

    #[test]
    fn test_while_loop() {
        let mut p = Program::new();
        p.eval(&Assignment{left: "x".to_owned(), right: Box::new(NumberLiteral(0.0))});

        let out = p.eval(&WhileLoop {
            cond: Box::new(BinaryExpr {
                left: Box::new(Variable("x".to_owned())),
                op: Lt,
                right: Box::new(NumberLiteral(5.0)),
            }),
            body: Box::new(Assignment {
                left: "x".to_owned(),
                right: Box::new(BinaryExpr {
                    left: Box::new(Variable("x".to_owned())),
                    op: Add,
                    right: Box::new(NumberLiteral(1.0)),
                }),
            }),
        });

        assert_eq!(out, Number(5.0));
        assert_eq!(p.eval(&Variable("x".to_owned())), Number(5.0));
    }
}
<|endoftext|>


<commit_before>
use std::sync::Arc;
use std::sync::Mutex;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::str::SplitWhitespace;
use std::error::Error;

use sim::{Io, TestPacket, NodeMeta, RoutingAlgorithm};
use vivaldi_routing::VivaldiRouting;
use random_routing::RandomRouting;
use spring_routing::SpringRouting;
use genetic_routing::GeneticRouting;
use importer::import_file;
use exporter::export_file;

use utils::fmt_duration;
use *; //import from crate root

static CMD_SOCKET_ADDRESS : &'static str = "127.0.0.1:8011";

pub fn send_to_socket(args: &[String]) {
	use std::io::Read;
	use std::io::Write;
	use std::time::{Instant, Duration};
	use std::net::{TcpListener, TcpStream};
	use std::net::{ToSocketAddrs, SocketAddr};
	let mut buf = vec![0; 1024];

	match TcpStream::connect(CMD_SOCKET_ADDRESS) {
		Ok(mut stream) => {
			stream.set_read_timeout(Some(Duration::from_millis(100)));
			stream.write(args.join(" ").as_bytes());
			let mut i = 0;
			loop {
				if let Ok(n) = stream.read(&mut buf) {
					if n > 0 {
						if let Ok(s) = std::str::from_utf8(&buf[0..n]) {
							//println!("received {} byte: '{}'", n, s);
							print!("{}", s);
							i += 1;
						}
					} else {
						break;
					}
				} else {
					break;
				}
			}
		},
		Err(e) => {
			eprintln!("{}", e);
		}
	}
}

pub fn ext_loop(sim: Arc<Mutex<GlobalState>>) {
	use std::io::Read;
	use std::io::Write;
	use std::net::{TcpListener, TcpStream};

	let listener = TcpListener::bind(CMD_SOCKET_ADDRESS).unwrap();
	println!("Listen for commands on {}", CMD_SOCKET_ADDRESS);
	//let mut input =  vec![0u8; 512];
	let mut output = Vec::<u8>::new();

	loop {
		//input.clear();
		output.clear();
		if let Ok((mut stream, addr)) = listener.accept() {
			let mut buf = [0; 512];
			if let Ok(n) = stream.read(&mut buf) {
				if let Ok(s) = std::str::from_utf8(&buf[0..n]) {
					if let Ok(mut sim) = sim.lock() {
						cmd_handler(&mut output, &mut sim, s);
						stream.write(&output);
					}
				}
			}
		}
	}
}

pub fn cmd_loop(sim: Arc<Mutex<GlobalState>>) {
	let mut input = String::new();
	loop {
		if let Ok(_) = io::stdin().read_line(&mut input) {
			if let Ok(mut sim) = sim.lock() {
				cmd_handler(&mut io::stdout(), &mut sim, &input);
			}
		}
		input.clear();
	}
}

macro_rules! scan {
    ( $iter:expr, $( $x:ty ),+ ) => {{
        ($($iter.next().and_then(|word| word.parse::<$x>().ok()),)*)
    }}
}

#[derive(Clone)]
enum Command {
	Error(String),
	Help,
	Clear,
	State,
	Reset,
	Test,
	ConnectInRange(f32),
	RemoveUnconnected,
	Algorithm(String),
	AddLine(u32, bool),
	AddTree(u32, u32),
	AddLattice4(u32, u32),
	AddLattice8(u32, u32),
	RemoveNodes(Vec<u32>),
	ConnectNodes(Vec<u32>),
	DisconnectNodes(Vec<u32>),
	Step(u32),
	Import(String),
	Export(String)
}

pub struct SimState {
	algorithm: Box<RoutingAlgorithm>,
	graph: Graph,
	test: PassiveRoutingTest,
	sim_steps: u32,
	do_init: bool
}

impl SimState {
	pub fn new() -> Self {
		Self {
			algorithm: Box::new(RandomRouting::new()),
			graph: Graph::new(),
			test: PassiveRoutingTest::new(),
			sim_steps: 0,
			do_init: true
		}
	}
}

fn parse_command(input: &str) -> Command {
	//let mut iter = input.split_whitespace().skip(1);
	//let tokens = input.split_whitespace().collect::<Vec<&str>>();

	let mut tokens = Vec::new();
	for tok in input.split_whitespace() {
		tokens.push(tok.trim_matches(|c: char| (c == '\'') || (c == '"')));
	}

	let mut iter = tokens.iter().skip(1);
	let cmd = tokens.get(0).unwrap_or(&"");

	fn parse_list(numbers: Option<&&str>) -> Result<Vec<u32>, ()> {
		let mut v = Vec::<u32>::new();
		for num in numbers.unwrap_or(&"").split(",") {
			if let Ok(n) = num.parse::<u32>() {
				v.push(n);
			} else {
				return Err(());
			}
		}
		Ok(v)
	}

	//println!("input: {}", input);

	let error = Command::Error("Missing Arguments".to_string());

	match *cmd {
		"" => Command::Step(1),
		"help" => Command::Help,
		"state" => Command::State,
		"clear" => Command::Clear,
		"reset" => Command::Reset,
		"step" => {
			Command::Step(if let (Some(count),) = scan!(iter, u32) {
				count
			} else {
				1
			})
		},
		"import" => {
			if let (Some(path),) = scan!(iter, String) {
				Command::Import(path)
			} else {
				error
			}
		},
		"export" => {
			if let (Some(path),) = scan!(iter, String) {
				Command::Export(path)
			} else {
				error
			}
		},
		"add_line" => {
			if let (Some(count), Some(close)) = scan!(iter, u32, bool) {
				Command::AddLine(count, close)
			} else {
				error
			}
		},
		"add_tree" => {
			if let (Some(count), Some(intra)) = scan!(iter, u32, u32) {
				Command::AddTree(count, intra)
			} else {
				error
			}
		},
		"add_lattice4" => {
			if let (Some(x_count), Some(y_count)) = scan!(iter, u32, u32) {
				Command::AddLattice4(x_count, y_count)
			} else {
				error
			}
		},
		"add_lattice8" => {
			if let (Some(x_count), Some(y_count)) = scan!(iter, u32, u32) {
				Command::AddLattice8(x_count, y_count)
			} else {
				error
			}
		},
		"connect_in_range" => {
			if let (Some(range),) = scan!(iter, f32) {
				Command::ConnectInRange(range)
			} else {
				error
			}
		},
		"algorithm" => {
			if let (Some(algo),) = scan!(iter, String) {
				Command::Algorithm(algo)
			} else {
				Command::Algorithm("".to_string())
			}
		},
		"remove_nodes" => {
			if let Ok(ids) = parse_list(tokens.get(1)) {
				Command::RemoveNodes(ids)
			} else {
				error
			}
		}
		"connect_nodes" => {
			if let Ok(ids) = parse_list(tokens.get(1)) {
				Command::ConnectNodes(ids)
			} else {
				error
			}
		},
		"disconnect_nodes" => {
			if let Ok(ids) = parse_list(tokens.get(1)) {
				Command::DisconnectNodes(ids)
			} else {
				error
			}
		},
		"remove_unconnected" => {
			Command::RemoveUnconnected
		},
		_ => {
			Command::Error(format!("Unknown Command: {}", cmd))
		}
	}
}

fn cmd_handler(out: &mut Write, sim: &mut GlobalState, input: &str) -> Result<(), std::io::Error> {
	let state = &mut sim.sim_state;
	let mut init = false;

	println!("command: '{}'", input);

	let mut command = parse_command(input);

	match command {
		Command::Error(msg) => {
			writeln!(out, "{}", msg)?;
		},
		Command::Help => {
			writeln!(out, "help text...")?;
		},
		Command::State => {
			writeln!(out, " graph: nodes: {}, links: {}", state.graph.node_count(), state.graph.link_count())?;
			writeln!(out, " algo: {}", state.algorithm.name())?;

			writeln!(out, " steps: {}", state.sim_steps)?;
		},
		Command::Clear => {
			state.graph.clear();
			state.do_init = true;
			writeln!(out, "done")?;
		},
		Command::Reset => {
			state.test.clear();
			//state.graph.clear();
			state.sim_steps = 0;
			state.do_init = true;
		},
		Command::Step(count) => {
			let mut io = Io::new(&state.graph);
			for step in 0..count {
				state.algorithm.step(&mut io);
				state.sim_steps += 1;
			}

			writeln!(out, "done {} steps", count)?;
		},
		Command::Test => {
			//check_state(sim);
			fn run_test(out: &mut Write, test: &mut PassiveRoutingTest, graph: &Graph, algo: &Box<RoutingAlgorithm>) {
				test.clear();
				test.run_samples(graph, |p| algo.route(&p), 1000);
				writeln!(out, "{} samples:\n  arrived: {}, stretch: {}, duration: {}",
					1000,
					test.arrived(), test.stretch(),
					fmt_duration(test.duration())
				);
			}
			run_test(out, &mut state.test, &state.graph, &state.algorithm);
		},
		Command::Import(ref path) => {
			import_file(&mut state.graph, path.as_str());
			state.do_init = true;
			writeln!(out, "read {}", path)?;
		},
		Command::Export(ref path) => {
			export_file(&state.graph, Some(&*state.algorithm), path.as_str());
			writeln!(out, "wrote {}", path)?;
		},
		Command::AddLine(count, close) => {
			state.graph.add_line(count, close);
			state.do_init = true;
		},
		Command::AddTree(count, intra) => {
			state.graph.add_tree(count, intra);
			state.do_init = true;
		},
		Command::AddLattice4(x_count, y_count) => {
			state.graph.add_lattice4(x_count, y_count);
			state.do_init = true;
		},
		Command::AddLattice8(x_count, y_count) => {
			state.graph.add_lattice8(x_count, y_count);
			state.do_init = true;
		},
		Command::ConnectInRange(range) => {
			state.graph.connect_in_range(range);
			state.do_init = true;
		},
		Command::Algorithm(ref algo) => {
			match algo.as_str() {
				"" => {
					writeln!(out, "algorithm: {}", state.algorithm.name())?;
				},
				"random" => {
					state.algorithm = Box::new(RandomRouting::new());
					state.do_init = true;
				},
				"vivaldi" => {
					state.algorithm = Box::new(VivaldiRouting::new());
					state.do_init = true;
				},
				_ => {
					writeln!(out, "Unknown algorithm: {}", algo)?;
				}
			}
		},
		Command::RemoveUnconnected => {
			state.graph.remove_unconnected_nodes();
			state.do_init = true;
		},
		Command::RemoveNodes(ids) => {
			state.graph.remove_nodes(&ids);
		},
		Command::ConnectNodes(ids) => {
			state.graph.connect_nodes(&ids);
		},
		Command::DisconnectNodes(ids) => {
			state.graph.disconnect_nodes(&ids);
		}
	};

	if state.do_init {
		writeln!(out, "init {} nodes", state.graph.node_count())?;
		state.algorithm.reset(state.graph.node_count());
		state.test.clear();
		state.do_init = false;
	}

	export_file(&state.graph, Some(&*state.algorithm), "graph.json");

	Ok(())
}
<commit_msg>output adjustments<commit_after>
use std::sync::Arc;
use std::sync::Mutex;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::str::SplitWhitespace;
use std::error::Error;
use std::time::{Instant, Duration};

use sim::{Io, TestPacket, NodeMeta, RoutingAlgorithm};
use vivaldi_routing::VivaldiRouting;
use random_routing::RandomRouting;
use spring_routing::SpringRouting;
use genetic_routing::GeneticRouting;
use importer::import_file;
use exporter::export_file;

use utils::fmt_duration;
use *; //import from crate root

static CMD_SOCKET_ADDRESS : &'static str = "127.0.0.1:8011";

pub fn send_to_socket(args: &[String]) {
	use std::io::Read;
	use std::io::Write;
	use std::time::{Instant, Duration};
	use std::net::{TcpListener, TcpStream};
	use std::net::{ToSocketAddrs, SocketAddr};
	let mut buf = vec![0; 1024];

	match TcpStream::connect(CMD_SOCKET_ADDRESS) {
		Ok(mut stream) => {
			stream.set_read_timeout(Some(Duration::from_millis(100)));
			stream.write(args.join(" ").as_bytes());
			let mut i = 0;
			loop {
				if let Ok(n) = stream.read(&mut buf) {
					if n > 0 {
						if let Ok(s) = std::str::from_utf8(&buf[0..n]) {
							//println!("received {} byte: '{}'", n, s);
							print!("{}", s);
							i += 1;
						}
					} else {
						break;
					}
				} else {
					break;
				}
			}
		},
		Err(e) => {
			eprintln!("{}", e);
		}
	}
}

pub fn ext_loop(sim: Arc<Mutex<GlobalState>>) {
	use std::io::Read;
	use std::io::Write;
	use std::net::{TcpListener, TcpStream};

	let listener = TcpListener::bind(CMD_SOCKET_ADDRESS).unwrap();
	println!("Listen for commands on {}", CMD_SOCKET_ADDRESS);
	//let mut input =  vec![0u8; 512];
	let mut output = Vec::<u8>::new();

	loop {
		//input.clear();
		output.clear();
		if let Ok((mut stream, addr)) = listener.accept() {
			let mut buf = [0; 512];
			if let Ok(n) = stream.read(&mut buf) {
				if let Ok(s) = std::str::from_utf8(&buf[0..n]) {
					if let Ok(mut sim) = sim.lock() {
						cmd_handler(&mut output, &mut sim, s);
						stream.write(&output);
					}
				}
			}
		}
	}
}

pub fn cmd_loop(sim: Arc<Mutex<GlobalState>>) {
	let mut input = String::new();
	loop {
		if let Ok(_) = io::stdin().read_line(&mut input) {
			if let Ok(mut sim) = sim.lock() {
				cmd_handler(&mut io::stdout(), &mut sim, &input);
			}
		}
		input.clear();
	}
}

macro_rules! scan {
    ( $iter:expr, $( $x:ty ),+ ) => {{
        ($($iter.next().and_then(|word| word.parse::<$x>().ok()),)*)
    }}
}

#[derive(Clone)]
enum Command {
	Error(String),
	Help,
	Clear,
	State,
	Reset,
	Test,
	ConnectInRange(f32),
	RemoveUnconnected,
	Algorithm(String),
	AddLine(u32, bool),
	AddTree(u32, u32),
	AddLattice4(u32, u32),
	AddLattice8(u32, u32),
	RemoveNodes(Vec<u32>),
	ConnectNodes(Vec<u32>),
	DisconnectNodes(Vec<u32>),
	Step(u32),
	Import(String),
	Export(String)
}

pub struct SimState {
	algorithm: Box<RoutingAlgorithm>,
	graph: Graph,
	test: PassiveRoutingTest,
	sim_steps: u32,
	do_init: bool
}

impl SimState {
	pub fn new() -> Self {
		Self {
			algorithm: Box::new(RandomRouting::new()),
			graph: Graph::new(),
			test: PassiveRoutingTest::new(),
			sim_steps: 0,
			do_init: true
		}
	}
}

fn parse_command(input: &str) -> Command {
	//let mut iter = input.split_whitespace().skip(1);
	//let tokens = input.split_whitespace().collect::<Vec<&str>>();

	let mut tokens = Vec::new();
	for tok in input.split_whitespace() {
		tokens.push(tok.trim_matches(|c: char| (c == '\'') || (c == '"')));
	}

	let mut iter = tokens.iter().skip(1);
	let cmd = tokens.get(0).unwrap_or(&"");

	fn parse_list(numbers: Option<&&str>) -> Result<Vec<u32>, ()> {
		let mut v = Vec::<u32>::new();
		for num in numbers.unwrap_or(&"").split(",") {
			if let Ok(n) = num.parse::<u32>() {
				v.push(n);
			} else {
				return Err(());
			}
		}
		Ok(v)
	}

	//println!("input: {}", input);

	let error = Command::Error("Missing Arguments".to_string());

	match *cmd {
		"" => Command::Step(1),
		"help" => Command::Help,
		"state" => Command::State,
		"clear" => Command::Clear,
		"reset" => Command::Reset,
		"test" => Command::Test,
		"step" => {
			Command::Step(if let (Some(count),) = scan!(iter, u32) {
				count
			} else {
				1
			})
		},
		"import" => {
			if let (Some(path),) = scan!(iter, String) {
				Command::Import(path)
			} else {
				error
			}
		},
		"export" => {
			if let (Some(path),) = scan!(iter, String) {
				Command::Export(path)
			} else {
				error
			}
		},
		"add_line" => {
			if let (Some(count), Some(close)) = scan!(iter, u32, bool) {
				Command::AddLine(count, close)
			} else {
				error
			}
		},
		"add_tree" => {
			if let (Some(count), Some(intra)) = scan!(iter, u32, u32) {
				Command::AddTree(count, intra)
			} else {
				error
			}
		},
		"add_lattice4" => {
			if let (Some(x_count), Some(y_count)) = scan!(iter, u32, u32) {
				Command::AddLattice4(x_count, y_count)
			} else {
				error
			}
		},
		"add_lattice8" => {
			if let (Some(x_count), Some(y_count)) = scan!(iter, u32, u32) {
				Command::AddLattice8(x_count, y_count)
			} else {
				error
			}
		},
		"connect_in_range" => {
			if let (Some(range),) = scan!(iter, f32) {
				Command::ConnectInRange(range)
			} else {
				error
			}
		},
		"algorithm" => {
			if let (Some(algo),) = scan!(iter, String) {
				Command::Algorithm(algo)
			} else {
				Command::Algorithm("".to_string())
			}
		},
		"remove_nodes" => {
			if let Ok(ids) = parse_list(tokens.get(1)) {
				Command::RemoveNodes(ids)
			} else {
				error
			}
		}
		"connect_nodes" => {
			if let Ok(ids) = parse_list(tokens.get(1)) {
				Command::ConnectNodes(ids)
			} else {
				error
			}
		},
		"disconnect_nodes" => {
			if let Ok(ids) = parse_list(tokens.get(1)) {
				Command::DisconnectNodes(ids)
			} else {
				error
			}
		},
		"remove_unconnected" => {
			Command::RemoveUnconnected
		},
		_ => {
			Command::Error(format!("Unknown Command: {}", cmd))
		}
	}
}

fn cmd_handler(out: &mut Write, sim: &mut GlobalState, input: &str) -> Result<(), std::io::Error> {
	let state = &mut sim.sim_state;
	let mut init = false;

	println!("command: '{}'", input);

	let mut command = parse_command(input);

	match command {
		Command::Error(msg) => {
			writeln!(out, "{}", msg)?;
		},
		Command::Help => {
			writeln!(out, "help text...")?;
		},
		Command::State => {
			writeln!(out, " graph: nodes: {}, links: {}", state.graph.node_count(), state.graph.link_count())?;
			writeln!(out, " algo: {}", state.algorithm.name())?;

			writeln!(out, " steps: {}", state.sim_steps)?;
		},
		Command::Clear => {
			state.graph.clear();
			state.do_init = true;
			writeln!(out, "done")?;
		},
		Command::Reset => {
			state.test.clear();
			//state.graph.clear();
			state.sim_steps = 0;
			state.do_init = true;
		},
		Command::Step(count) => {
			let now = Instant::now();
			let mut io = Io::new(&state.graph);
			for step in 0..count {
				state.algorithm.step(&mut io);
				state.sim_steps += 1;
			}

			let duration = now.elapsed();

			writeln!(out, "{} steps, duration: {}", count, fmt_duration(duration))?;
		},
		Command::Test => {
			fn run_test(out: &mut Write, test: &mut PassiveRoutingTest, graph: &Graph, algo: &Box<RoutingAlgorithm>) {
				let samples = 100;
				test.clear();
				test.run_samples(graph, |p| algo.route(&p), samples);
				writeln!(out, "samples: {},  arrived: {:.1}, stretch: {}, duration: {}",
					samples,
					test.arrived(), test.stretch(),
					fmt_duration(test.duration())
				);
			}
			run_test(out, &mut state.test, &state.graph, &state.algorithm);
		},
		Command::Import(ref path) => {
			import_file(&mut state.graph, path.as_str());
			state.do_init = true;
			writeln!(out, "read {}", path)?;
		},
		Command::Export(ref path) => {
			export_file(&state.graph, Some(&*state.algorithm), path.as_str());
			writeln!(out, "wrote {}", path)?;
		},
		Command::AddLine(count, close) => {
			state.graph.add_line(count, close);
			state.do_init = true;
		},
		Command::AddTree(count, intra) => {
			state.graph.add_tree(count, intra);
			state.do_init = true;
		},
		Command::AddLattice4(x_count, y_count) => {
			state.graph.add_lattice4(x_count, y_count);
			state.do_init = true;
		},
		Command::AddLattice8(x_count, y_count) => {
			state.graph.add_lattice8(x_count, y_count);
			state.do_init = true;
		},
		Command::ConnectInRange(range) => {
			state.graph.connect_in_range(range);
			state.do_init = true;
		},
		Command::Algorithm(ref algo) => {
			match algo.as_str() {
				"" => {
					writeln!(out, "algorithm: {}", state.algorithm.name())?;
				},
				"random" => {
					state.algorithm = Box::new(RandomRouting::new());
					state.do_init = true;
				},
				"vivaldi" => {
					state.algorithm = Box::new(VivaldiRouting::new());
					state.do_init = true;
				},
				_ => {
					writeln!(out, "Unknown algorithm: {}", algo)?;
				}
			}
		},
		Command::RemoveUnconnected => {
			state.graph.remove_unconnected_nodes();
			state.do_init = true;
		},
		Command::RemoveNodes(ids) => {
			state.graph.remove_nodes(&ids);
		},
		Command::ConnectNodes(ids) => {
			state.graph.connect_nodes(&ids);
		},
		Command::DisconnectNodes(ids) => {
			state.graph.disconnect_nodes(&ids);
		}
	};

	if state.do_init {
		writeln!(out, "init {} nodes", state.graph.node_count())?;
		state.algorithm.reset(state.graph.node_count());
		state.test.clear();
		state.do_init = false;
	}

	export_file(&state.graph, Some(&*state.algorithm), "graph.json");

	Ok(())
}
<|endoftext|>


<commit_before>use memory::Memory;

const FL_CARRY: u8 = 1 << 0;
const FL_STATUS: u8 = 1 << 1;
const FL_INTERRUPT_DISABLE: u8 = 1 << 2;
const FL_BRK: u8 = 1 << 4;
const FL_OVERFLOW: u8 = 1 << 6;
const FL_SIGN: u8 = 1 << 7;

// Graciously taken from https://github.com/pcwalton/sprocketnes
static CYCLE_TABLE: [u8; 256] = [
  /*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,
  /*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,
  /*0x30*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x40*/ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,
  /*0x50*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x60*/ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,
  /*0x70*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x80*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
  /*0x90*/ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,
  /*0xA0*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
  /*0xB0*/ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,
  /*0xC0*/ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
  /*0xD0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0xE0*/ 2,6,3,8,3,3,5,5,2,2,2,2,4,4,6,6,
  /*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
];

pub struct Cpu6502 {
  registers: Registers,
  memory: Memory
}

pub struct Registers {
  pc: u16, // Program Counter
  sp: u8, // Stack Pointer
  acc: u8, // Accumulator
  irx: u8, // Index Register X
  iry: u8, // Index Register Y
  stat: u8 // Processor Status Flags
}

pub enum AddressingMode {
  Immediate,
  ZeroPage,
  ZeroPageX,
  Absolute,
  AboluteX,
  AbsoluteY,
  IndirectX,
  IndirectY
}

impl Registers {
  fn new() -> Registers {
    Registers {
      pc: 0,
      sp: 0,
      acc: 0,
      irx: 0,
      iry: 0,
      stat: 0b00010000
    }
  }

  fn get_flag(&self, mask: u8) -> bool {
    self.stat & mask != 0
  }

  fn set_flag(&mut self, mask: u8, val: bool) {
    if val {
      self.stat |= mask;
    } else {
      self.stat &= !mask;
    }
  }
}

impl Cpu6502 {
 pub fn new() -> Cpu6502 {
    Cpu6502 {
      registers: Registers::new(),
      memory: Memory::new()
    }
  }

  pub fn adc(&mut self, arg: u8, mode: AddressingMode) {
    match mode {
      AddressingMode::Immediate => {
        // Cheaply determine carry flag by casting the values to the native
        // word size and checking if the result carries over to the 9th bit.
        let res = if self.registers.get_flag(FL_CARRY) { 1 } else { 0 }
            + self.registers.acc as usize + arg as usize;

        self.registers.set_flag(FL_CARRY, res & 0x100 != 0);

        let res = res as u8;
        let acc = self.registers.acc;

        // Set the overflow flag when both operands have the same sign bit AND
        // the sign bit of the result differs from the two.
        //
        // This is a clever way of determining whether or not the result overflows
        // 8-bits and works with both signed and unsigned values.
        self.registers.set_flag(FL_OVERFLOW, (acc ^ arg) & 0x80 == 0
            && (acc ^ res) & 0x80 == 0x80);

        // TODO: Set remaining flags
      },
      _ => {
        panic!("not implemented");
      }
    }
  }
}
<commit_msg>Simplify logic for determining carry flag<commit_after>use memory::Memory;

const FL_CARRY: u8 = 1 << 0;
const FL_STATUS: u8 = 1 << 1;
const FL_INTERRUPT_DISABLE: u8 = 1 << 2;
const FL_BRK: u8 = 1 << 4;
const FL_OVERFLOW: u8 = 1 << 6;
const FL_SIGN: u8 = 1 << 7;

// Graciously taken from https://github.com/pcwalton/sprocketnes
static CYCLE_TABLE: [u8; 256] = [
  /*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,
  /*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,
  /*0x30*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x40*/ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,
  /*0x50*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x60*/ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,
  /*0x70*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0x80*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
  /*0x90*/ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,
  /*0xA0*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
  /*0xB0*/ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,
  /*0xC0*/ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
  /*0xD0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
  /*0xE0*/ 2,6,3,8,3,3,5,5,2,2,2,2,4,4,6,6,
  /*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
];

pub struct Cpu6502 {
  registers: Registers,
  memory: Memory
}

pub struct Registers {
  pc: u16, // Program Counter
  sp: u8, // Stack Pointer
  acc: u8, // Accumulator
  irx: u8, // Index Register X
  iry: u8, // Index Register Y
  stat: u8 // Processor Status Flags
}

pub enum AddressingMode {
  Immediate,
  ZeroPage,
  ZeroPageX,
  Absolute,
  AboluteX,
  AbsoluteY,
  IndirectX,
  IndirectY
}

impl Registers {
  fn new() -> Registers {
    Registers {
      pc: 0,
      sp: 0,
      acc: 0,
      irx: 0,
      iry: 0,
      stat: 0b00010000
    }
  }

  fn get_flag(&self, mask: u8) -> bool {
    self.stat & mask != 0
  }

  fn set_flag(&mut self, mask: u8, val: bool) {
    if val {
      self.stat |= mask;
    } else {
      self.stat &= !mask;
    }
  }
}

impl Cpu6502 {
 pub fn new() -> Cpu6502 {
    Cpu6502 {
      registers: Registers::new(),
      memory: Memory::new()
    }
  }

  pub fn adc(&mut self, arg: u8, mode: AddressingMode) {
    match mode {
      AddressingMode::Immediate => {
        // Cheaply determine carry flag by casting the values to the native
        // word size and checking if the result carries over to the 9th bit.
        let res = if self.registers.get_flag(FL_CARRY) { 1 } else { 0 }
            + self.registers.acc as usize + arg as usize;

        self.registers.set_flag(FL_CARRY, res & 0x100 != 0);

        let res = res as u8;
        let acc = self.registers.acc;

        // Set the overflow flag when both operands have the same sign bit AND
        // the sign bit of the result differs from the two.
        let has_overflow = (arg ^ res) & (acc ^ res) & 0x80 == 0;
        self.registers.set_flag(FL_OVERFLOW, has_overflow);

        // TODO: Set remaining flags
      },
      _ => {
        panic!("not implemented");
      }
    }
  }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]

// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]

extern crate serde_codegen_internals as internals;

#[cfg(feature = "with-syntex")]
extern crate syntex;

#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;

extern crate syn;
#[macro_use]
extern crate quote;

#[cfg(feature = "with-syntex")]
use std::path::Path;

mod bound;
mod de;
mod ser;

#[cfg(feature = "with-syntex")]
fn syntex_registry() -> syntex::Registry {
    use syntax::{ast, fold};

    /// Strip the serde attributes from the crate.
    #[cfg(feature = "with-syntex")]
    fn strip_attributes(krate: ast::Crate) -> ast::Crate {
        /// Helper folder that strips the serde attributes after the extensions have been expanded.
        struct StripAttributeFolder;

        impl fold::Folder for StripAttributeFolder {
            fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
                if attr.value.name == "serde" {
                    if let ast::MetaItemKind::List(..) = attr.value.node {
                        return None;
                    }
                }
                Some(attr)
            }

            fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
                fold::noop_fold_mac(mac, self)
            }
        }

        fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
    }

    let mut reg = syntex::Registry::new();

    reg.add_attr("feature(custom_derive)");
    reg.add_attr("feature(custom_attribute)");

    reg.add_decorator("derive_Serialize", shim::expand_derive_serialize);
    reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);

    reg.add_post_expansion_pass(strip_attributes);

    reg
}

#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
    let src = src.to_owned();

    let expand_thread = move || {
        syntex_registry().expand_str("", "", &src)
    };

    syntex::with_extra_stack(expand_thread)
}

#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
    where S: AsRef<Path>,
          D: AsRef<Path>,
{
    let src = src.as_ref().to_owned();
    let dst = dst.as_ref().to_owned();

    let expand_thread = move || {
        syntex_registry().expand("", src, dst)
    };

    syntex::with_extra_stack(expand_thread)
}

macro_rules! shim {
    ($name:ident $pkg:ident :: $func:ident) => {
        pub fn $func(
            cx: &mut ::syntax::ext::base::ExtCtxt,
            span: ::syntax::codemap::Span,
            meta_item: &::syntax::ast::MetaItem,
            annotatable: &::syntax::ext::base::Annotatable,
            push: &mut FnMut(::syntax::ext::base::Annotatable)
        ) {
            let item = match *annotatable {
                ::syntax::ext::base::Annotatable::Item(ref item) => item,
                _ => {
                    cx.span_err(
                        meta_item.span,
                        concat!("`#[derive(",
                                stringify!($name),
                                ")]` may only be applied to structs and enums"));
                    return;
                }
            };

            use syntax::{attr, ast, visit};
            struct MarkSerdeAttributesUsed;
            impl<'a> visit::Visitor<'a> for MarkSerdeAttributesUsed {
                fn visit_attribute(&mut self, attr: &ast::Attribute) {
                    if attr.value.name == "serde" {
                        if let ast::MetaItemKind::List(..) = attr.value.node {
                            attr::mark_used(attr);
                        }
                    }
                }
            }
            visit::walk_item(&mut MarkSerdeAttributesUsed, item);

            use syntax::print::pprust;
            let s = pprust::item_to_string(item);

            use {syn, $pkg};
            let syn_item = syn::parse_macro_input(&s).unwrap();
            let expanded = match $pkg::$func(&syn_item) {
                Ok(expanded) => expanded.to_string(),
                Err(msg) => {
                    cx.span_err(span, &msg);
                    return;
                }
            };

            use syntax::parse;
            let name = stringify!($name).to_string();
            let sess = cx.parse_sess;
            let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
            push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
        }
    };
}

#[cfg(feature = "with-syntex")]
mod shim {
    shim!(Serialize ser::expand_derive_serialize);
    shim!(Deserialize de::expand_derive_deserialize);
}

#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_serialize(item: &str) -> Result<quote::Tokens, String> {
    let syn_item = syn::parse_macro_input(item).unwrap();
    ser::expand_derive_serialize(&syn_item)
}

#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_deserialize(item: &str) -> Result<quote::Tokens, String> {
    let syn_item = syn::parse_macro_input(item).unwrap();
    de::expand_derive_deserialize(&syn_item)
}
<commit_msg>Remove unused #[macro_use]<commit_after>#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]

// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]

extern crate serde_codegen_internals as internals;

#[cfg(feature = "with-syntex")]
extern crate syntex;

#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;

extern crate syn;
#[macro_use]
extern crate quote;

#[cfg(feature = "with-syntex")]
use std::path::Path;

mod bound;
mod de;
mod ser;

#[cfg(feature = "with-syntex")]
fn syntex_registry() -> syntex::Registry {
    use syntax::{ast, fold};

    /// Strip the serde attributes from the crate.
    #[cfg(feature = "with-syntex")]
    fn strip_attributes(krate: ast::Crate) -> ast::Crate {
        /// Helper folder that strips the serde attributes after the extensions have been expanded.
        struct StripAttributeFolder;

        impl fold::Folder for StripAttributeFolder {
            fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
                if attr.value.name == "serde" {
                    if let ast::MetaItemKind::List(..) = attr.value.node {
                        return None;
                    }
                }
                Some(attr)
            }

            fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
                fold::noop_fold_mac(mac, self)
            }
        }

        fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
    }

    let mut reg = syntex::Registry::new();

    reg.add_attr("feature(custom_derive)");
    reg.add_attr("feature(custom_attribute)");

    reg.add_decorator("derive_Serialize", shim::expand_derive_serialize);
    reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);

    reg.add_post_expansion_pass(strip_attributes);

    reg
}

#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
    let src = src.to_owned();

    let expand_thread = move || {
        syntex_registry().expand_str("", "", &src)
    };

    syntex::with_extra_stack(expand_thread)
}

#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
    where S: AsRef<Path>,
          D: AsRef<Path>,
{
    let src = src.as_ref().to_owned();
    let dst = dst.as_ref().to_owned();

    let expand_thread = move || {
        syntex_registry().expand("", src, dst)
    };

    syntex::with_extra_stack(expand_thread)
}

macro_rules! shim {
    ($name:ident $pkg:ident :: $func:ident) => {
        pub fn $func(
            cx: &mut ::syntax::ext::base::ExtCtxt,
            span: ::syntax::codemap::Span,
            meta_item: &::syntax::ast::MetaItem,
            annotatable: &::syntax::ext::base::Annotatable,
            push: &mut FnMut(::syntax::ext::base::Annotatable)
        ) {
            let item = match *annotatable {
                ::syntax::ext::base::Annotatable::Item(ref item) => item,
                _ => {
                    cx.span_err(
                        meta_item.span,
                        concat!("`#[derive(",
                                stringify!($name),
                                ")]` may only be applied to structs and enums"));
                    return;
                }
            };

            use syntax::{attr, ast, visit};
            struct MarkSerdeAttributesUsed;
            impl<'a> visit::Visitor<'a> for MarkSerdeAttributesUsed {
                fn visit_attribute(&mut self, attr: &ast::Attribute) {
                    if attr.value.name == "serde" {
                        if let ast::MetaItemKind::List(..) = attr.value.node {
                            attr::mark_used(attr);
                        }
                    }
                }
            }
            visit::walk_item(&mut MarkSerdeAttributesUsed, item);

            use syntax::print::pprust;
            let s = pprust::item_to_string(item);

            use {syn, $pkg};
            let syn_item = syn::parse_macro_input(&s).unwrap();
            let expanded = match $pkg::$func(&syn_item) {
                Ok(expanded) => expanded.to_string(),
                Err(msg) => {
                    cx.span_err(span, &msg);
                    return;
                }
            };

            use syntax::parse;
            let name = stringify!($name).to_string();
            let sess = cx.parse_sess;
            let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
            push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
        }
    };
}

#[cfg(feature = "with-syntex")]
mod shim {
    shim!(Serialize ser::expand_derive_serialize);
    shim!(Deserialize de::expand_derive_deserialize);
}

#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_serialize(item: &str) -> Result<quote::Tokens, String> {
    let syn_item = syn::parse_macro_input(item).unwrap();
    ser::expand_derive_serialize(&syn_item)
}

#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_deserialize(item: &str) -> Result<quote::Tokens, String> {
    let syn_item = syn::parse_macro_input(item).unwrap();
    de::expand_derive_deserialize(&syn_item)
}
<|endoftext|>


<commit_before>extern crate crowbook_localize;

use crowbook_localize::{Localizer, Extractor};

fn main() {
    let str_fr = r#"
msgid "hello, {}"
msgstr "bonjour, {}"

msgid "Shit: \"{}\" went wrong;"
msgstr "Chiotte: \"{}\" est parti en live;"

msgid "kwak!"
msgstr "coin !"
"#;

    let str_es = r#"
msgid "hello, {}"
msgstr "hola, {}"

msgid "Oi!"
msgstr "¡Oi!"
"#;
    let extractor = Extractor::new();
    let mut localizer = Localizer::new(&extractor);
    localizer.add_lang("fr", str_fr).unwrap();
    localizer.add_lang("es", str_es).unwrap();
    println!("{}", localizer.generate_macro_file());
}
<commit_msg>Change crowbook_localize to crowbook_intl<commit_after>extern crate crowbook_intl;

use crowbook_intl::{Localizer, Extractor};

fn main() {
    let str_fr = r#"
msgid "hello, {}"
msgstr "bonjour, {}"

msgid "Shit: \"{}\" went wrong;"
msgstr "Chiotte: \"{}\" est parti en live;"

msgid "kwak!"
msgstr "coin !"
"#;

    let str_es = r#"
msgid "hello, {}"
msgstr "hola, {}"

msgid "Oi!"
msgstr "¡Oi!"
"#;
    let extractor = Extractor::new();
    let mut localizer = Localizer::new(&extractor);
    localizer.add_lang("fr", str_fr).unwrap();
    localizer.add_lang("es", str_es).unwrap();
    println!("{}", localizer.generate_macro_file());
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

#[macro_use]
mod commands;

use std::env;

use commands::{streaminfo, comments, seektable, picture};
use docopt::Docopt;

const USAGE: &'static str = "
Usage: metadata <command> [<args>...]
       metadata [options]

Options:
  -h, --help  Show this message.

Commands:
  streaminfo  Display stream information.
  comments    Display or export comment tags.
  seektable   Display seek table.
  picture     Export picutes.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_command: Option<Command>,
  arg_args: Vec<String>,
}

#[derive(Clone, Copy, Debug, RustcDecodable)]
enum Command {
  StreamInfo,
  Comments,
  SeekTable,
  Picture,
}

fn handle_subcommand(command: Command) {
  match command {
    Command::StreamInfo => {
      let sub_args: streaminfo::Arguments = Docopt::new(streaminfo::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      streaminfo::run(&sub_args)
    }
    Command::Comments   => {
      let sub_args: comments::Arguments = Docopt::new(comments::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      comments::run(&sub_args)
    }
    Command::SeekTable  => {
      let sub_args: seektable::Arguments = Docopt::new(seektable::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      seektable::run(&sub_args)
    }
    Command::Picture    => {
      let sub_args: picture::Arguments = Docopt::new(picture::USAGE)
        .and_then(|d| d.argv(env::args()).decode())
        .unwrap_or_else(|e| e.exit());

      picture::run(&sub_args)
    }
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.options_first(true).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(command) = args.arg_command {
    handle_subcommand(command);
  } else {
    println!("{}", USAGE);
  }
}
<commit_msg>Use `command!` macro on all subcommands<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

#[macro_use]
mod commands;

use std::env;

use commands::{streaminfo, comments, seektable, picture};
use docopt::Docopt;

const USAGE: &'static str = "
Usage: metadata <command> [<args>...]
       metadata [options]

Options:
  -h, --help  Show this message.

Commands:
  streaminfo  Display stream information.
  comments    Display or export comment tags.
  seektable   Display seek table.
  picture     Export picutes.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_command: Option<Command>,
  arg_args: Vec<String>,
}

#[derive(Clone, Copy, Debug, RustcDecodable)]
enum Command {
  StreamInfo,
  Comments,
  SeekTable,
  Picture,
}

fn handle_subcommand(command: Command) {
  match command {
    Command::StreamInfo => command!(streaminfo),
    Command::Comments   => command!(comments),
    Command::SeekTable  => command!(seektable),
    Command::Picture    => command!(picture),
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.options_first(true).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(command) = args.arg_command {
    handle_subcommand(command);
  } else {
    println!("{}", USAGE);
  }
}
<|endoftext|>


<commit_before>extern crate libc;

#[allow(non_camel_case_types)]
pub type key_serial_t = libc::int32_t;

pub static KEY_SPEC_THREAD_KEYRING:         key_serial_t = -1;
pub static KEY_SPEC_PROCESS_KEYRING:        key_serial_t = -2;
pub static KEY_SPEC_SESSION_KEYRING:        key_serial_t = -3;
pub static KEY_SPEC_USER_KEYRING:           key_serial_t = -4;
pub static KEY_SPEC_USER_SESSION_KEYRING:   key_serial_t = -5;
pub static KEY_SPEC_GROUP_KEYRING:          key_serial_t = -6;
pub static KEY_SPEC_REQKEY_AUTH_KEY:        key_serial_t = -7;

pub static KEY_REQKEY_DEFL_NO_CHANGE:               key_serial_t = -1;
pub static KEY_REQKEY_DEFL_DEFAULT:                 key_serial_t = 0;
pub static KEY_REQKEY_DEFL_THREAD_KEYRING:          key_serial_t = 1;
pub static KEY_REQKEY_DEFL_PROCESS_KEYRING:         key_serial_t = 2;
pub static KEY_REQKEY_DEFL_SESSION_KEYRING:         key_serial_t = 3;
pub static KEY_REQKEY_DEFL_USER_KEYRING:            key_serial_t = 4;
pub static KEY_REQKEY_DEFL_USER_SESSION_KEYRING:    key_serial_t = 5;
pub static KEY_REQKEY_DEFL_GROUP_KEYRING:           key_serial_t = 6;

#[allow(non_camel_case_types)]
pub type key_perm_t = libc::uint32_t;

pub static KEY_POS_VIEW:    key_perm_t = 0x01000000;     /* possessor can view a key's attributes */
pub static KEY_POS_READ:    key_perm_t = 0x02000000;     /* possessor can read key payload / view keyring */
pub static KEY_POS_WRITE:   key_perm_t = 0x04000000;     /* possessor can update key payload / add link to keyring */
pub static KEY_POS_SEARCH:  key_perm_t = 0x08000000;     /* possessor can find a key in search / search a keyring */
pub static KEY_POS_LINK:    key_perm_t = 0x10000000;     /* possessor can create a link to a key/keyring */
pub static KEY_POS_SETATTR: key_perm_t = 0x20000000;     /* possessor can set key attributes */
pub static KEY_POS_ALL:     key_perm_t = 0x3f000000;

pub static KEY_USR_VIEW:    key_perm_t = 0x00010000;     /* user permissions... */
pub static KEY_USR_READ:    key_perm_t = 0x00020000;
pub static KEY_USR_WRITE:   key_perm_t = 0x00040000;
pub static KEY_USR_SEARCH:  key_perm_t = 0x00080000;
pub static KEY_USR_LINK:    key_perm_t = 0x00100000;
pub static KEY_USR_SETATTR: key_perm_t = 0x00200000;
pub static KEY_USR_ALL:     key_perm_t = 0x003f0000;

pub static KEY_GRP_VIEW:    key_perm_t = 0x00000100;     /* group permissions... */
pub static KEY_GRP_READ:    key_perm_t = 0x00000200;
pub static KEY_GRP_WRITE:   key_perm_t = 0x00000400;
pub static KEY_GRP_SEARCH:  key_perm_t = 0x00000800;
pub static KEY_GRP_LINK:    key_perm_t = 0x00001000;
pub static KEY_GRP_SETATTR: key_perm_t = 0x00002000;
pub static KEY_GRP_ALL:     key_perm_t = 0x00003f00;

pub static KEY_OTH_VIEW:    key_perm_t = 0x00000001;     /* third party permissions... */
pub static KEY_OTH_READ:    key_perm_t = 0x00000002;
pub static KEY_OTH_WRITE:   key_perm_t = 0x00000004;
pub static KEY_OTH_SEARCH:  key_perm_t = 0x00000008;
pub static KEY_OTH_LINK:    key_perm_t = 0x00000010;
pub static KEY_OTH_SETATTR: key_perm_t = 0x00000020;
pub static KEY_OTH_ALL:     key_perm_t = 0x0000003f;

#[allow(non_camel_case_types)]
type recursive_key_scanner_t =
    extern fn(
        parent:     key_serial_t,
        key:        key_serial_t,
        desc:       *mut libc::c_char,
        desc_len:   libc::c_int,
        data:       *mut libc::c_void)
        -> libc::c_int;

#[link(name = "keyutils")]
extern {
    pub fn add_key(
        type_:          *const libc::c_char,
        description:    *const libc::c_char,
        payload:        *const libc::c_void,
        plen:           libc::size_t,
        keyring:        key_serial_t)
        -> key_serial_t;
    pub fn request_key(
        type_:          *const libc::c_char,
        description:    *const libc::c_char,
        callout_info:   *const libc::c_char,
        keyring:        key_serial_t)
        -> key_serial_t;

    pub fn keyctl_get_keyring_ID(
        id:     key_serial_t,
        create: libc::c_int)
        -> key_serial_t;
    pub fn keyctl_join_session_keyring(
        name:   *const libc::c_char)
        -> key_serial_t;
    pub fn keyctl_update(
        id:         key_serial_t,
        payload:    *const libc::c_void,
        plen:       libc::size_t)
        -> libc::c_long;
    pub fn keyctl_revoke(
        id: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_chown(
        id:     key_serial_t,
        uid:    libc::uid_t,
        gid:    libc::gid_t)
        -> libc::c_long;
    pub fn keyctl_setperm(
        id:     key_serial_t,
        perm:   key_perm_t)
        -> libc::c_long;
    pub fn keyctl_describe(
        id:     key_serial_t,
        buffer: *mut libc::c_char,
        buflen: libc::size_t)
        -> libc::c_long;
    pub fn keyctl_clear(
        ringid: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_link(
        id:     key_serial_t,
        ringid: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_unlink(
        id:     key_serial_t,
        ringid: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_search(
        ringid:         key_serial_t,
        type_:          *const libc::c_char,
        description:    *const libc::c_char,
        destringid:     key_serial_t)
        -> libc::c_long;
    pub fn keyctl_read(
        id:     key_serial_t,
        buffer: *mut libc::c_char,
        buflen: libc::size_t)
        -> libc::c_long;
    //pub fn keyctl_instantiate(
    //    id:         key_serial_t,
    //    payload:    *const libc::c_void,
    //    plen:       libc::size_t,
    //    ringid:     key_serial_t)
    //    -> libc::c_long;
    //pub fn keyctl_negate(
    //    id:         key_serial_t,
    //    timeout:    libc::c_uint,
    //    ringid:     key_serial_t)
    //    -> libc::c_long;
    pub fn keyctl_set_reqkey_keyring(
        reqkey_defl:    libc::c_int)
        -> libc::c_long;
    pub fn keyctl_set_timeout(
        key:        key_serial_t,
        timeout:    libc::c_uint)
        -> libc::c_long;
    //pub fn keyctl_assume_authority(
    //    key:    key_serial_t)
    //    -> libc::c_long;
    pub fn keyctl_get_security(
        key:    key_serial_t,
        buffer: *mut libc::c_char,
        buflen: libc::size_t)
        -> libc::c_long;
    pub fn keyctl_session_to_parent()
        -> libc::c_long;
    //pub fn keyctl_reject(
    //    id:         key_serial_t,
    //    timeout:    libc::c_uint,
    //    error:      libc::c_uint,
    //    ringid:     key_serial_t)
    //    -> libc::c_long;
    //struct iovec;
    //pub fn keyctl_instantiate_iov(
    //    id:             key_serial_t,
    //    payload_iov:    *const libc::c_void,
    //    //payload_iov:    *const struct iovec,
    //    ioc:            libc::c_uint,
    //    ringid:         key_serial_t)
    //    -> libc::c_long;
    pub fn keyctl_invalidate(
        id: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_get_persistent(
        uid:    libc::uid_t,
        id:     key_serial_t)
        -> libc::c_long;

    pub fn recursive_key_scan(
        key:    key_serial_t,
        func:   recursive_key_scanner_t,
        data:   *mut libc::c_void)
        -> libc::c_int;
    pub fn recursive_session_key_scan(
        func:   recursive_key_scanner_t,
        data:   *mut libc::c_void)
        -> libc::c_int;
    pub fn find_key_by_type_and_desc(
        type_:      *const libc::c_char,
        desc:       *const libc::c_char,
        destringid: key_serial_t)
        -> key_serial_t;
}
<commit_msg>ffi: drop the iov-using function<commit_after>extern crate libc;

#[allow(non_camel_case_types)]
pub type key_serial_t = libc::int32_t;

pub static KEY_SPEC_THREAD_KEYRING:         key_serial_t = -1;
pub static KEY_SPEC_PROCESS_KEYRING:        key_serial_t = -2;
pub static KEY_SPEC_SESSION_KEYRING:        key_serial_t = -3;
pub static KEY_SPEC_USER_KEYRING:           key_serial_t = -4;
pub static KEY_SPEC_USER_SESSION_KEYRING:   key_serial_t = -5;
pub static KEY_SPEC_GROUP_KEYRING:          key_serial_t = -6;
pub static KEY_SPEC_REQKEY_AUTH_KEY:        key_serial_t = -7;

pub static KEY_REQKEY_DEFL_NO_CHANGE:               key_serial_t = -1;
pub static KEY_REQKEY_DEFL_DEFAULT:                 key_serial_t = 0;
pub static KEY_REQKEY_DEFL_THREAD_KEYRING:          key_serial_t = 1;
pub static KEY_REQKEY_DEFL_PROCESS_KEYRING:         key_serial_t = 2;
pub static KEY_REQKEY_DEFL_SESSION_KEYRING:         key_serial_t = 3;
pub static KEY_REQKEY_DEFL_USER_KEYRING:            key_serial_t = 4;
pub static KEY_REQKEY_DEFL_USER_SESSION_KEYRING:    key_serial_t = 5;
pub static KEY_REQKEY_DEFL_GROUP_KEYRING:           key_serial_t = 6;

#[allow(non_camel_case_types)]
pub type key_perm_t = libc::uint32_t;

pub static KEY_POS_VIEW:    key_perm_t = 0x01000000;     /* possessor can view a key's attributes */
pub static KEY_POS_READ:    key_perm_t = 0x02000000;     /* possessor can read key payload / view keyring */
pub static KEY_POS_WRITE:   key_perm_t = 0x04000000;     /* possessor can update key payload / add link to keyring */
pub static KEY_POS_SEARCH:  key_perm_t = 0x08000000;     /* possessor can find a key in search / search a keyring */
pub static KEY_POS_LINK:    key_perm_t = 0x10000000;     /* possessor can create a link to a key/keyring */
pub static KEY_POS_SETATTR: key_perm_t = 0x20000000;     /* possessor can set key attributes */
pub static KEY_POS_ALL:     key_perm_t = 0x3f000000;

pub static KEY_USR_VIEW:    key_perm_t = 0x00010000;     /* user permissions... */
pub static KEY_USR_READ:    key_perm_t = 0x00020000;
pub static KEY_USR_WRITE:   key_perm_t = 0x00040000;
pub static KEY_USR_SEARCH:  key_perm_t = 0x00080000;
pub static KEY_USR_LINK:    key_perm_t = 0x00100000;
pub static KEY_USR_SETATTR: key_perm_t = 0x00200000;
pub static KEY_USR_ALL:     key_perm_t = 0x003f0000;

pub static KEY_GRP_VIEW:    key_perm_t = 0x00000100;     /* group permissions... */
pub static KEY_GRP_READ:    key_perm_t = 0x00000200;
pub static KEY_GRP_WRITE:   key_perm_t = 0x00000400;
pub static KEY_GRP_SEARCH:  key_perm_t = 0x00000800;
pub static KEY_GRP_LINK:    key_perm_t = 0x00001000;
pub static KEY_GRP_SETATTR: key_perm_t = 0x00002000;
pub static KEY_GRP_ALL:     key_perm_t = 0x00003f00;

pub static KEY_OTH_VIEW:    key_perm_t = 0x00000001;     /* third party permissions... */
pub static KEY_OTH_READ:    key_perm_t = 0x00000002;
pub static KEY_OTH_WRITE:   key_perm_t = 0x00000004;
pub static KEY_OTH_SEARCH:  key_perm_t = 0x00000008;
pub static KEY_OTH_LINK:    key_perm_t = 0x00000010;
pub static KEY_OTH_SETATTR: key_perm_t = 0x00000020;
pub static KEY_OTH_ALL:     key_perm_t = 0x0000003f;

#[allow(non_camel_case_types)]
type recursive_key_scanner_t =
    extern fn(
        parent:     key_serial_t,
        key:        key_serial_t,
        desc:       *mut libc::c_char,
        desc_len:   libc::c_int,
        data:       *mut libc::c_void)
        -> libc::c_int;

#[link(name = "keyutils")]
extern {
    pub fn add_key(
        type_:          *const libc::c_char,
        description:    *const libc::c_char,
        payload:        *const libc::c_void,
        plen:           libc::size_t,
        keyring:        key_serial_t)
        -> key_serial_t;
    pub fn request_key(
        type_:          *const libc::c_char,
        description:    *const libc::c_char,
        callout_info:   *const libc::c_char,
        keyring:        key_serial_t)
        -> key_serial_t;

    pub fn keyctl_get_keyring_ID(
        id:     key_serial_t,
        create: libc::c_int)
        -> key_serial_t;
    pub fn keyctl_join_session_keyring(
        name:   *const libc::c_char)
        -> key_serial_t;
    pub fn keyctl_update(
        id:         key_serial_t,
        payload:    *const libc::c_void,
        plen:       libc::size_t)
        -> libc::c_long;
    pub fn keyctl_revoke(
        id: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_chown(
        id:     key_serial_t,
        uid:    libc::uid_t,
        gid:    libc::gid_t)
        -> libc::c_long;
    pub fn keyctl_setperm(
        id:     key_serial_t,
        perm:   key_perm_t)
        -> libc::c_long;
    pub fn keyctl_describe(
        id:     key_serial_t,
        buffer: *mut libc::c_char,
        buflen: libc::size_t)
        -> libc::c_long;
    pub fn keyctl_clear(
        ringid: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_link(
        id:     key_serial_t,
        ringid: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_unlink(
        id:     key_serial_t,
        ringid: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_search(
        ringid:         key_serial_t,
        type_:          *const libc::c_char,
        description:    *const libc::c_char,
        destringid:     key_serial_t)
        -> libc::c_long;
    pub fn keyctl_read(
        id:     key_serial_t,
        buffer: *mut libc::c_char,
        buflen: libc::size_t)
        -> libc::c_long;
    //pub fn keyctl_instantiate(
    //    id:         key_serial_t,
    //    payload:    *const libc::c_void,
    //    plen:       libc::size_t,
    //    ringid:     key_serial_t)
    //    -> libc::c_long;
    //pub fn keyctl_negate(
    //    id:         key_serial_t,
    //    timeout:    libc::c_uint,
    //    ringid:     key_serial_t)
    //    -> libc::c_long;
    pub fn keyctl_set_reqkey_keyring(
        reqkey_defl:    libc::c_int)
        -> libc::c_long;
    pub fn keyctl_set_timeout(
        key:        key_serial_t,
        timeout:    libc::c_uint)
        -> libc::c_long;
    //pub fn keyctl_assume_authority(
    //    key:    key_serial_t)
    //    -> libc::c_long;
    pub fn keyctl_get_security(
        key:    key_serial_t,
        buffer: *mut libc::c_char,
        buflen: libc::size_t)
        -> libc::c_long;
    pub fn keyctl_session_to_parent()
        -> libc::c_long;
    //pub fn keyctl_reject(
    //    id:         key_serial_t,
    //    timeout:    libc::c_uint,
    //    error:      libc::c_uint,
    //    ringid:     key_serial_t)
    //    -> libc::c_long;
    pub fn keyctl_invalidate(
        id: key_serial_t)
        -> libc::c_long;
    pub fn keyctl_get_persistent(
        uid:    libc::uid_t,
        id:     key_serial_t)
        -> libc::c_long;

    pub fn recursive_key_scan(
        key:    key_serial_t,
        func:   recursive_key_scanner_t,
        data:   *mut libc::c_void)
        -> libc::c_int;
    pub fn recursive_session_key_scan(
        func:   recursive_key_scanner_t,
        data:   *mut libc::c_void)
        -> libc::c_int;
    pub fn find_key_by_type_and_desc(
        type_:      *const libc::c_char,
        desc:       *const libc::c_char,
        destringid: key_serial_t)
        -> key_serial_t;
}
<|endoftext|>