<commit_before>//!
//! Helper to decompose a packet of binary data into multiple arbitrary data
//! structures.
//!

use std::{cast, mem};

/// An iterator that can be used to fetch typed arguments from a byte slice
pub struct ArgumentIterator<'a> {
	priv data: &'a [u8],
	priv pos: uint,
}

impl<'a> ArgumentIterator<'a> {
	/// Create a new argument iterator for the given byte slice
	pub fn new (data: &'a [u8]) -> ArgumentIterator<'a> {
		ArgumentIterator { data: data, pos: 0 }
	}

	/// Fetch a typed argument
	pub fn fetch<T> (&mut self) -> &'a T {
		let value = unsafe { cast::transmute(self.data.as_ptr().offset(self.pos as int)) };
		self.pos += mem::size_of::<T>();
		assert!(self.pos <= self.data.len(), "trying to get argument behind data");
		value
	}

	/// Fetch a (zero-terminated) string (can be non-utf8)
	pub fn fetch_str (&mut self) -> &'a [u8] {
		let start = self.pos;
		while(self.data[self.pos] != 0u8) {
			self.pos += 1
		}
		self.pos += 1;  // Eat the null terminator
		self.data.slice(start, self.pos-1)
	}

	/// Fetch a (zero-terminated) Posix path
	pub fn fetch_path (&mut self) -> PosixPath {
		PosixPath::new(self.fetch_str())
	}

	/// Fetch a slice of the remaining data
	pub fn fetch_data (&mut self) -> &'a [u8] {
		let bytes = self.data.tailn(self.pos);
		self.pos = self.data.len();
		bytes
	}
}

#[cfg(test)]
mod test {
	use super::ArgumentIterator;

	static test_data: [u8, ..12] = [0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, 0x62, 0x61, 0x7a, 0x00];
	struct test_argument_t { p1: u8, p2: u8, p3: u16 }

	#[test]
	fn generic_argument () {
		let mut it = ArgumentIterator::new(test_data);
		let arg: &test_argument_t = it.fetch();
		assert!(arg.p1 == 0x66, "argument iterator should fetch typed argument from data");
		assert!(arg.p2 == 0x6f, "argument iterator should fetch typed argument from data");
		assert!(arg.p3 == 0x006f, "argument iterator should fetch typed argument from data");
		let arg: &test_argument_t = it.fetch();
		assert!(arg.p1 == 0x62, "argument iterator should fetch typed argument from data");
		assert!(arg.p2 == 0x61, "argument iterator should fetch typed argument from data");
		assert!(arg.p3 == 0x0072, "argument iterator should fetch typed argument from data");
	}

	#[test]
	fn string_argument () {
		let mut it = ArgumentIterator::new(test_data);
		let arg = it.fetch_str();
		assert!(arg == bytes!("foo"), "argument iterator should fetch string from data");
		let arg = it.fetch_str();
		assert!(arg == bytes!("bar"), "argument iterator should fetch string from data");
	}

	#[test]
	fn path_argument () {
		let mut it = ArgumentIterator::new(test_data);
		let arg = it.fetch_path();
		assert!(arg.as_str() == Some("foo"), "argument iterator should fetch path from data");
		let arg = it.fetch_path();
		assert!(arg.as_str() == Some("bar"), "argument iterator should fetch path from data");
	}

	#[test]
	fn remaining_data_argument () {
		let mut it = ArgumentIterator::new(test_data);
		it.fetch_str();
		it.fetch_str();
		let arg = it.fetch_data();
		assert!(arg == [0x62, 0x61, 0x7a, 0x00], "argument iterator should fetch data from data");
	}

	#[test]
	fn mixed_arguments () {
		let mut it = ArgumentIterator::new(test_data);
		let arg: &test_argument_t = it.fetch();
		assert!(arg.p1 == 0x66, "argument iterator should fetch typed argument from data");
		assert!(arg.p2 == 0x6f, "argument iterator should fetch typed argument from data");
		assert!(arg.p3 == 0x006f, "argument iterator should fetch typed argument from data");
		let arg = it.fetch_str();
		assert!(arg == bytes!("bar"), "argument iterator should fetch string from data");
		let arg = it.fetch_data();
		assert!(arg == [0x62, 0x61, 0x7a, 0x00], "argument iterator should fetch data from data");
	}
}
<commit_msg>Remove unnecessary parentheses<commit_after>//!
//! Helper to decompose a packet of binary data into multiple arbitrary data
//! structures.
//!

use std::{cast, mem};

/// An iterator that can be used to fetch typed arguments from a byte slice
pub struct ArgumentIterator<'a> {
	priv data: &'a [u8],
	priv pos: uint,
}

impl<'a> ArgumentIterator<'a> {
	/// Create a new argument iterator for the given byte slice
	pub fn new (data: &'a [u8]) -> ArgumentIterator<'a> {
		ArgumentIterator { data: data, pos: 0 }
	}

	/// Fetch a typed argument
	pub fn fetch<T> (&mut self) -> &'a T {
		let value = unsafe { cast::transmute(self.data.as_ptr().offset(self.pos as int)) };
		self.pos += mem::size_of::<T>();
		assert!(self.pos <= self.data.len(), "trying to get argument behind data");
		value
	}

	/// Fetch a (zero-terminated) string (can be non-utf8)
	pub fn fetch_str (&mut self) -> &'a [u8] {
		let start = self.pos;
		while self.data[self.pos] != 0u8 {
			self.pos += 1
		}
		self.pos += 1;  // Eat the null terminator
		self.data.slice(start, self.pos-1)
	}

	/// Fetch a (zero-terminated) Posix path
	pub fn fetch_path (&mut self) -> PosixPath {
		PosixPath::new(self.fetch_str())
	}

	/// Fetch a slice of the remaining data
	pub fn fetch_data (&mut self) -> &'a [u8] {
		let bytes = self.data.tailn(self.pos);
		self.pos = self.data.len();
		bytes
	}
}

#[cfg(test)]
mod test {
	use super::ArgumentIterator;

	static test_data: [u8, ..12] = [0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, 0x62, 0x61, 0x7a, 0x00];
	struct test_argument_t { p1: u8, p2: u8, p3: u16 }

	#[test]
	fn generic_argument () {
		let mut it = ArgumentIterator::new(test_data);
		let arg: &test_argument_t = it.fetch();
		assert!(arg.p1 == 0x66, "argument iterator should fetch typed argument from data");
		assert!(arg.p2 == 0x6f, "argument iterator should fetch typed argument from data");
		assert!(arg.p3 == 0x006f, "argument iterator should fetch typed argument from data");
		let arg: &test_argument_t = it.fetch();
		assert!(arg.p1 == 0x62, "argument iterator should fetch typed argument from data");
		assert!(arg.p2 == 0x61, "argument iterator should fetch typed argument from data");
		assert!(arg.p3 == 0x0072, "argument iterator should fetch typed argument from data");
	}

	#[test]
	fn string_argument () {
		let mut it = ArgumentIterator::new(test_data);
		let arg = it.fetch_str();
		assert!(arg == bytes!("foo"), "argument iterator should fetch string from data");
		let arg = it.fetch_str();
		assert!(arg == bytes!("bar"), "argument iterator should fetch string from data");
	}

	#[test]
	fn path_argument () {
		let mut it = ArgumentIterator::new(test_data);
		let arg = it.fetch_path();
		assert!(arg.as_str() == Some("foo"), "argument iterator should fetch path from data");
		let arg = it.fetch_path();
		assert!(arg.as_str() == Some("bar"), "argument iterator should fetch path from data");
	}

	#[test]
	fn remaining_data_argument () {
		let mut it = ArgumentIterator::new(test_data);
		it.fetch_str();
		it.fetch_str();
		let arg = it.fetch_data();
		assert!(arg == [0x62, 0x61, 0x7a, 0x00], "argument iterator should fetch data from data");
	}

	#[test]
	fn mixed_arguments () {
		let mut it = ArgumentIterator::new(test_data);
		let arg: &test_argument_t = it.fetch();
		assert!(arg.p1 == 0x66, "argument iterator should fetch typed argument from data");
		assert!(arg.p2 == 0x6f, "argument iterator should fetch typed argument from data");
		assert!(arg.p3 == 0x006f, "argument iterator should fetch typed argument from data");
		let arg = it.fetch_str();
		assert!(arg == bytes!("bar"), "argument iterator should fetch string from data");
		let arg = it.fetch_data();
		assert!(arg == [0x62, 0x61, 0x7a, 0x00], "argument iterator should fetch data from data");
	}
}
<|endoftext|>


<commit_before>use std::prelude::v1::*;
use std::env::args;
use std::io;
use std::io::Write;
//use std::rand::FloatMath::*;

#[derive(Debug)]
pub enum TokenType {
    Plus,
    Minus,
    Divide,
    Multiply,
    Exponent,
    OpenParen,
    CloseParen,
    Number,
    Error
}

impl TokenType {
    pub fn to_string(&self) -> &'static str {
        match self {
            &TokenType::Plus       => "Plus",
            &TokenType::Minus      => "Minus",
            &TokenType::Divide     => "Divide",
            &TokenType::Multiply   => "Multiply",
            &TokenType::Exponent   => "Exponent",
            &TokenType::OpenParen  => "OpenParen",
            &TokenType::CloseParen => "CloseParen",
            &TokenType::Number     => "Number",
            &TokenType::Error      => "Error",
        }
    }
}

#[derive(Debug)]
pub struct Token {
    token_type: TokenType,
    contents: String
}

impl Token {
    pub fn new<S: Into<String>>(t: TokenType, s: S) -> Self {
        Token {
            token_type: t,
            contents: s.into()
        }
    }

    pub fn new_number<S: Into<String>>(number: S) -> Self {
        Token {
            token_type: TokenType::Number,
            contents: number.into()
        }
    }

    pub fn new_operator(operator: char) -> Self {
        let mut op = String::with_capacity(1);
        let op_type = match operator {
            '+' => TokenType::Plus,
            '-' => TokenType::Minus,
            '/' => TokenType::Divide,
            '*' => TokenType::Multiply,
            '^' => TokenType::Exponent,
            '(' => TokenType::OpenParen,
            ')' => TokenType::CloseParen,
            _   => unreachable!(), // TODO: should indicate error here
        };
        op.push(operator);
        Token {
            token_type: op_type,
            contents: op
        }
    }

    pub fn to_string(&self) -> String {
        [ self.token_type.to_string(), "(", self.contents.as_str(), ")" ].join("")
    }
}

#[derive(Debug)]
pub enum ParseError {
    InvalidNumber(String),
    UnrecognizedToken(String),
    UnexpectedToken(String, &'static str),
    UnexpectedEndOfInput,
    OtherError(String),
}

#[derive(Clone,Debug)]
pub struct IntermediateResult {
    value: f64,
    tokens_read: usize,
}

impl IntermediateResult {
    fn new(value: f64, tokens_read: usize) -> Self {
        IntermediateResult {
            value: value,
            tokens_read: tokens_read,
        }
    }
}

pub trait IsOperator {
	fn is_operator(self) -> bool;
}

impl IsOperator for char {
    fn is_operator(self) -> bool {
        self == '+' ||
        self == '-' ||
        self == '*' ||
        self == '/' ||
        self == '^' ||
        self == '(' ||
        self == ')'
    }
}

// Vec<Token> -> String
// take a vector of tokens and produce a string representation of the form: TokenType(token contents) ...
// tokens_to_string([Number(3), Plus(+), Number(4)]) => "Number(3) Plus(+) Number(4)"
// tokens_to_string([Number(3), Multiple(+), Number(4), Plus(+), Number(5)]) => "Number(3) Multiple(+) Number(4) Plus(+) Number(5)"
pub fn tokens_to_string(tokens: &[Token]) -> String {
    let v: Vec<String> = tokens.iter()
          .map(|t| t.to_string())
          .collect();
    v.join(" ")
}

// String -> Vec<Token>
// purpose: take an input string and return a vector of tokens
// tokenize("3+4") => [Number(3), Plus(+), Number(4)]
// tokenize("3 * 4 + 5") => [Number(3), Multiple(+), Number(4), Plus(+), Number(5)]
// tokenize("3 + 4 / 5") => [Number(3), Plus(+), Number(4), Divide(+), Number(5)]
pub fn tokenize(input: &str) -> Result<Vec<Token>, ParseError> {
    // CONSIDER: any smarter way to guess an initial capacity?
    let mut tokens: Vec<Token> = Vec::with_capacity(25);

    // TODO: Not this. Modify to use iterator
    let chars: Vec<char> = input.chars().collect();

    let input_length = chars.len();
    let mut current_pos = 0;
    while current_pos < input_length {
        let c : char = chars[current_pos];
        if c.is_digit(10) {
            let token_string = consume_number(&chars[current_pos..]);
            current_pos += token_string.len();
            tokens.push(Token::new_number(token_string));
        } else if c.is_operator() {
            tokens.push(Token::new_operator(chars[current_pos]));
            current_pos += 1;
        } else if c.is_whitespace() {
            current_pos += 1;
        } else {
            let token_string = consume_until_new_token(&chars[current_pos..]);
            return Err(ParseError::UnrecognizedToken(token_string));
        }
    }
    Ok(tokens)
}

fn consume_number(input: &[char]) -> String {
    // CONSIDER: input.len seems a bit generous
    let mut number = String::with_capacity(input.len());
    let mut has_decimal_point = false;
    for &c in input {
        if c == '.' {
            if has_decimal_point {
                break;
            } else {
                number.push(c);
                has_decimal_point = true;
            }
        } else if c.is_digit(10) {
            number.push(c);
        } else {
            break;
        }
    }
    number
}

fn consume_until_new_token(input: &[char]) -> String {
    input.iter()
         .take_while(|c| !(c.is_whitespace() || c.is_operator() || c.is_digit(10)))
         .map(|&c| c)
         .collect()
}

// Addition and subtraction
pub fn e_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut t1 = try!(t_expr(token_list));
    let mut index = t1.tokens_read;

    while index < token_list.len() {
        match token_list[index].token_type {
            TokenType::Plus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value += t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            TokenType::Minus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value -= t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            TokenType::Number => return Err(ParseError::UnexpectedToken(token_list[index].contents.clone(),"operator")),
            _ => return break,
        };
        index = t1.tokens_read;
    }
    Ok(t1)
}

// Multiplication and division
pub fn t_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut f1 = try!(f_expr(token_list));
    let mut index = f1.tokens_read;

    while index < token_list.len() {
        match token_list[index].token_type {
            TokenType::Multiply => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                f1.value *= f2.value;
                f1.tokens_read += f2.tokens_read + 1;
            }
            TokenType::Divide => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                if f2.value == 0.0 {
                    return Err(ParseError::OtherError("Divide by zero error".to_owned()));
                } else {
                    f1.value /= f2.value;
                    f1.tokens_read += f2.tokens_read + 1;
                }
            }
            TokenType::Number => return Err(ParseError::UnexpectedToken(token_list[index].contents.clone(),"operator")),
            _ => break,
        }
        index = f1.tokens_read;
    }
    Ok(f1)
}

// Exponentiation
pub fn f_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut g1 = try!(g_expr(token_list));
    // TODO: uncomment all of this once I can figure out why powf won't work
    /*
    let mut index = g1.tokens_read;
    let token_len = token_list.len();
    while index < token_len {
        match token_list[index].token_type {
            TokenType::Exponent => {
                let f = try!(f_expr(&token_list[index+1..]));
                g1.value = g1.value.powf(f.value);
                g1.tokens_read += f.tokens_read + 1;
            }
            TokenType::Number => return Err(ParseError::UnexpectedToken(token_list[index].contents.clone(),"operator")),
            _ => break,
        }
        index = g1.tokens_read;
    }
    */
    Ok(g1)
}

// Numbers and parenthesized expressions
pub fn g_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    if !token_list.is_empty() {
        match token_list[0].token_type {
            TokenType::Number => {
                token_list[0].contents.parse::<f64>()
                    .map_err(|_| ParseError::InvalidNumber(token_list[0].contents.clone()))
                    .and_then(|num| Ok(IntermediateResult::new(num, 1)))
            }
            TokenType::Minus => {
                if token_list.len() > 1 {
                    token_list[1].contents.parse::<f64>()
                        .map_err(|_| ParseError::InvalidNumber(token_list[1].contents.clone()))
                        .and_then(|num| Ok(IntermediateResult::new(-1.0 * num, 2)))
                } else {
                    Err(ParseError::UnexpectedToken(token_list[1].contents.clone(), "number"))
                }
            }
            TokenType::OpenParen => {
                let expr = e_expr(&token_list[1..]);
                match expr {
                    Ok(ir) => {
                        let close_paren = ir.tokens_read + 1;
                        if close_paren < token_list.len() {
                            match token_list[close_paren].token_type {
                                TokenType::CloseParen => Ok(IntermediateResult::new(ir.value, close_paren+1)),
                                _ => Err(ParseError::UnexpectedToken(token_list[close_paren].contents.clone(), ")")),
                            }
                        } else {
                            Err(ParseError::OtherError("no matching close parenthesis found.".to_owned()))
                        }
                    }
                    Err(e) => Err(e),
                }
            }
            _ => Err(ParseError::UnexpectedToken(token_list[0].contents.clone(), "number"))
        }
    } else {
        Err(ParseError::UnexpectedEndOfInput)
    }
}

pub fn parse(tokens: Vec<Token>) -> Result<String, ParseError> {
    e_expr(&tokens[..]).map(|answer| answer.value.to_string())
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn simple_addition() {
        assert_eq!(tokenize("12+3").and_then(parse).unwrap(), "15");
    }

    #[test]
    fn addition() {
        assert_eq!(tokenize("12+3+5").and_then(parse).unwrap(), "20");
    }

    #[test]
    fn simple_subtraction() {
        assert_eq!(tokenize("12-3").and_then(parse).unwrap(), "9");
    }

    #[test]
    fn subtraction() {
        assert_eq!(tokenize("12-3-4").and_then(parse).unwrap(), "5");
    }

    #[test]
    fn mixed_addition_and_subtraction() {
        assert_eq!(tokenize("12+3-4+8-2-3").and_then(parse).unwrap(), "14");
    }

    #[test]
    fn simple_parentheses() {
        assert_eq!(tokenize("((3))").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("(12+(2+3))").and_then(parse).unwrap(), "17");
        assert_eq!(tokenize("12+(2+3)").and_then(parse).unwrap(), "17");
    }

    #[test]
    fn parentheses() {
        assert_eq!(tokenize("12+(2+(3+5))+4+(((6)))").and_then(parse).unwrap(), "32");
    }

    #[test]
    fn multiplication() {
        assert_eq!(tokenize("3*3").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("3*5").and_then(parse).unwrap(), "15");
        assert_eq!(tokenize("0*5").and_then(parse).unwrap(), "0");
        assert_eq!(tokenize("5*4*3*2*1").and_then(parse).unwrap(), "120");
        assert_eq!(tokenize("(5*4)*3*(2*1)").and_then(parse).unwrap(), "120");
    }

    #[test]
    fn division() {
        assert_eq!(tokenize("12/4").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("12/3").and_then(parse).unwrap(), "4");
        assert_eq!(tokenize("5/2").and_then(parse).unwrap(), "2.5");
        assert_eq!(tokenize("120/5/4/3/2").and_then(parse).unwrap(), "1");
        assert_eq!(tokenize("(120/5)/4/(3/2)").and_then(parse).unwrap(), "4");
    }

    /*
    #[test]
    fn exponentiation() {
        assert_eq!(tokenize("3^2").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("2^3^2").and_then(parse).unwrap(), "512");
        assert_eq!(tokenize("2^(2+1)^2").and_then(parse).unwrap(), "512");
    }
    */
}

fn eval(input: &str) -> String {
    match tokenize(input).and_then(parse) {
        Ok(s) => s,
        Err(e) => match e {
            ParseError::InvalidNumber(s) => ["Invalid number: ", s.as_str() ].join(""),
            ParseError::UnrecognizedToken(s) => ["Unrecognized token: ", s.as_str()].join(""),
            ParseError::UnexpectedToken(found, expected) => ["Unexpected token: expected [", expected, "] but found '", found.as_str(), "'"].join(""),
            ParseError::UnexpectedEndOfInput => "Error: Unexpected end of input.".to_owned(),
            ParseError::OtherError(s) => s,
        }
    }
}

fn main() {
    let args = args();
    if args.len() > 1 {
        let input: Vec<String> = args.skip(1).collect();
        println!("{}", eval(&input.join("")));
    } else {
        let mut stdout = io::stdout();
        let mut stdin = io::stdin();
        loop {
            print!("[]> ");
            stdout.flush();
            let mut input = String::new();
            stdin.read_line(&mut input)
                 .expect("Error reading input");
            match input.trim() {
                "exit" => break,
                s => println!("{}", eval(s)),
            }
        }
    }
}
<commit_msg>Add IO locking, and do some clean up.<commit_after>#![deny(warnings)]

extern crate coreutils;
use coreutils::extra::OptionalExt;
use std::env::args;
use std::io;
use std::io::Write;
//use std::rand::FloatMath::*;

#[derive(Debug,Copy,Clone)]
pub enum TokenType {
    Plus,
    Minus,
    Divide,
    Multiply,
    Exponent,
    OpenParen,
    CloseParen,
    Number,
    Error
}

impl TokenType {
    pub fn to_string(&self) -> &'static str {
        match self {
            &TokenType::Plus       => "Plus",
            &TokenType::Minus      => "Minus",
            &TokenType::Divide     => "Divide",
            &TokenType::Multiply   => "Multiply",
            &TokenType::Exponent   => "Exponent",
            &TokenType::OpenParen  => "OpenParen",
            &TokenType::CloseParen => "CloseParen",
            &TokenType::Number     => "Number",
            &TokenType::Error      => "Error",
        }
    }
}

#[derive(Debug)]
pub struct Token {
    token_type: TokenType,
    contents: String
}

impl Token {
    pub fn new<S: Into<String>>(t: TokenType, s: S) -> Self {
        Token {
            token_type: t,
            contents: s.into()
        }
    }

    pub fn new_number<S: Into<String>>(number: S) -> Self {
        Token {
            token_type: TokenType::Number,
            contents: number.into()
        }
    }

    pub fn new_operator(operator: char) -> Self {
        let mut op = String::with_capacity(1);
        let op_type = match operator {
            '+' => TokenType::Plus,
            '-' => TokenType::Minus,
            '/' => TokenType::Divide,
            '*' => TokenType::Multiply,
            '^' => TokenType::Exponent,
            '(' => TokenType::OpenParen,
            ')' => TokenType::CloseParen,
            _   => coreutils::extra::fail("Invalid token", &mut io::stderr())
        };
        op.push(operator);
        Token {
            token_type: op_type,
            contents: op
        }
    }

    pub fn to_string(&self) -> String {
        [ self.token_type.to_string(), "(", self.contents.as_str(), ")" ].join("")
    }
}

#[derive(Debug,  Clone)]
pub enum ParseError {
    InvalidNumber(String),
    UnrecognizedToken(String),
    UnexpectedToken(String, &'static str),
    UnexpectedEndOfInput,
    OtherError(String),
}

#[derive(Clone,Debug)]
pub struct IntermediateResult {
    value: f64,
    tokens_read: usize,
}

impl IntermediateResult {
    fn new(value: f64, tokens_read: usize) -> Self {
        IntermediateResult {
            value: value,
            tokens_read: tokens_read,
        }
    }
}

pub trait IsOperator {
    fn is_operator(self) -> bool;
}

impl IsOperator for char {
    fn is_operator(self) -> bool {
        self == '+' ||
        self == '-' ||
        self == '*' ||
        self == '/' ||
        self == '^' ||
        self == '(' ||
        self == ')'
    }
}

// Vec<Token> -> String
// take a vector of tokens and produce a string representation of the form: TokenType(token contents) ...
// tokens_to_string([Number(3), Plus(+), Number(4)]) => "Number(3) Plus(+) Number(4)"
// tokens_to_string([Number(3), Multiple(+), Number(4), Plus(+), Number(5)]) => "Number(3) Multiple(+) Number(4) Plus(+) Number(5)"
pub fn tokens_to_string(tokens: &[Token]) -> String {
    let v: Vec<String> = tokens.iter()
          .map(|t| t.to_string())
          .collect();
    v.join(" ")
}

// String -> Vec<Token>
// purpose: take an input string and return a vector of tokens
// tokenize("3+4") => [Number(3), Plus(+), Number(4)]
// tokenize("3 * 4 + 5") => [Number(3), Multiple(+), Number(4), Plus(+), Number(5)]
// tokenize("3 + 4 / 5") => [Number(3), Plus(+), Number(4), Divide(+), Number(5)]
pub fn tokenize(input: &str) -> Result<Vec<Token>, ParseError> {
    // CONSIDER: any smarter way to guess an initial capacity?
    let mut tokens: Vec<Token> = Vec::with_capacity(25);

    // TODO: Not this. Modify to use iterator
    let chars: Vec<char> = input.chars().collect();

    let input_length = chars.len();
    let mut current_pos = 0;
    while current_pos < input_length {
        let c : char = chars[current_pos];
        if c.is_digit(10) {
            let token_string = consume_number(&chars[current_pos..]);
            current_pos += token_string.len();
            tokens.push(Token::new_number(token_string));
        } else if c.is_operator() {
            tokens.push(Token::new_operator(chars[current_pos]));
            current_pos += 1;
        } else if c.is_whitespace() {
            current_pos += 1;
        } else {
            let token_string = consume_until_new_token(&chars[current_pos..]);
            return Err(ParseError::UnrecognizedToken(token_string));
        }
    }
    Ok(tokens)
}

fn consume_number(input: &[char]) -> String {
    // CONSIDER: input.len seems a bit generous
    let mut number = String::with_capacity(input.len());
    let mut has_decimal_point = false;
    for &c in input {
        if c == '.' {
            if has_decimal_point {
                break;
            } else {
                number.push(c);
                has_decimal_point = true;
            }
        } else if c.is_digit(10) {
            number.push(c);
        } else {
            break;
        }
    }
    number
}

fn consume_until_new_token(input: &[char]) -> String {
    input.iter()
         .take_while(|c| !(c.is_whitespace() || c.is_operator() || c.is_digit(10)))
         .map(|&c| c)
         .collect()
}

// Addition and subtraction
pub fn e_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut t1 = try!(t_expr(token_list));
    let mut index = t1.tokens_read;

    while index < token_list.len() {
        match token_list[index].token_type {
            TokenType::Plus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value += t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            TokenType::Minus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value -= t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            TokenType::Number => return Err(ParseError::UnexpectedToken(token_list[index].contents.clone(),"operator")),
            _ => return break,
        };
        index = t1.tokens_read;
    }
    Ok(t1)
}

// Multiplication and division
pub fn t_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut f1 = try!(f_expr(token_list));
    let mut index = f1.tokens_read;

    while index < token_list.len() {
        match token_list[index].token_type {
            TokenType::Multiply => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                f1.value *= f2.value;
                f1.tokens_read += f2.tokens_read + 1;
            }
            TokenType::Divide => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                if f2.value == 0.0 {
                    return Err(ParseError::OtherError("Divide by zero error".to_owned()));
                } else {
                    f1.value /= f2.value;
                    f1.tokens_read += f2.tokens_read + 1;
                }
            }
            TokenType::Number => return Err(ParseError::UnexpectedToken(token_list[index].contents.clone(),"operator")),
            _ => break,
        }
        index = f1.tokens_read;
    }
    Ok(f1)
}

// Exponentiation
pub fn f_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let g1 = try!(g_expr(token_list));
    // TODO: uncomment all of this once I can figure out why powf won't work
    /*
    let mut g1 = try!(g_expr(token_list));
    let mut index = g1.tokens_read;
    let token_len = token_list.len();
    while index < token_len {
        match token_list[index].token_type {
            TokenType::Exponent => {
                let f = try!(f_expr(&token_list[index+1..]));
                g1.value = g1.value.powf(f.value);
                g1.tokens_read += f.tokens_read + 1;
            }
            TokenType::Number => return Err(ParseError::UnexpectedToken(token_list[index].contents.clone(),"operator")),
            _ => break,
        }
        index = g1.tokens_read;
    }
    */
    Ok(g1)
}

// Numbers and parenthesized expressions
pub fn g_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    if !token_list.is_empty() {
        match token_list[0].token_type {
            TokenType::Number => {
                token_list[0].contents.parse::<f64>()
                    .map_err(|_| ParseError::InvalidNumber(token_list[0].contents.clone()))
                    .and_then(|num| Ok(IntermediateResult::new(num, 1)))
            }
            TokenType::Minus => {
                if token_list.len() > 1 {
                    token_list[1].contents.parse::<f64>()
                        .map_err(|_| ParseError::InvalidNumber(token_list[1].contents.clone()))
                        .and_then(|num| Ok(IntermediateResult::new(-1.0 * num, 2)))
                } else {
                    Err(ParseError::UnexpectedToken(token_list[1].contents.clone(), "number"))
                }
            }
            TokenType::OpenParen => {
                let expr = e_expr(&token_list[1..]);
                match expr {
                    Ok(ir) => {
                        let close_paren = ir.tokens_read + 1;
                        if close_paren < token_list.len() {
                            match token_list[close_paren].token_type {
                                TokenType::CloseParen => Ok(IntermediateResult::new(ir.value, close_paren+1)),
                                _ => Err(ParseError::UnexpectedToken(token_list[close_paren].contents.clone(), ")")),
                            }
                        } else {
                            Err(ParseError::OtherError("no matching close parenthesis found.".to_owned()))
                        }
                    }
                    Err(e) => Err(e),
                }
            }
            _ => Err(ParseError::UnexpectedToken(token_list[0].contents.clone(), "number"))
        }
    } else {
        Err(ParseError::UnexpectedEndOfInput)
    }
}

pub fn parse(tokens: Vec<Token>) -> Result<String, ParseError> {
    e_expr(&tokens[..]).map(|answer| answer.value.to_string())
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn simple_addition() {
        assert_eq!(tokenize("12+3").and_then(parse).unwrap(), "15");
    }

    #[test]
    fn addition() {
        assert_eq!(tokenize("12+3+5").and_then(parse).unwrap(), "20");
    }

    #[test]
    fn simple_subtraction() {
        assert_eq!(tokenize("12-3").and_then(parse).unwrap(), "9");
    }

    #[test]
    fn subtraction() {
        assert_eq!(tokenize("12-3-4").and_then(parse).unwrap(), "5");
    }

    #[test]
    fn mixed_addition_and_subtraction() {
        assert_eq!(tokenize("12+3-4+8-2-3").and_then(parse).unwrap(), "14");
    }

    #[test]
    fn simple_parentheses() {
        assert_eq!(tokenize("((3))").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("(12+(2+3))").and_then(parse).unwrap(), "17");
        assert_eq!(tokenize("12+(2+3)").and_then(parse).unwrap(), "17");
    }

    #[test]
    fn parentheses() {
        assert_eq!(tokenize("12+(2+(3+5))+4+(((6)))").and_then(parse).unwrap(), "32");
    }

    #[test]
    fn multiplication() {
        assert_eq!(tokenize("3*3").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("3*5").and_then(parse).unwrap(), "15");
        assert_eq!(tokenize("0*5").and_then(parse).unwrap(), "0");
        assert_eq!(tokenize("5*4*3*2*1").and_then(parse).unwrap(), "120");
        assert_eq!(tokenize("(5*4)*3*(2*1)").and_then(parse).unwrap(), "120");
    }

    #[test]
    fn division() {
        assert_eq!(tokenize("12/4").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("12/3").and_then(parse).unwrap(), "4");
        assert_eq!(tokenize("5/2").and_then(parse).unwrap(), "2.5");
        assert_eq!(tokenize("120/5/4/3/2").and_then(parse).unwrap(), "1");
        assert_eq!(tokenize("(120/5)/4/(3/2)").and_then(parse).unwrap(), "4");
    }

    /*
    #[test]
    fn exponentiation() {
        assert_eq!(tokenize("3^2").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("2^3^2").and_then(parse).unwrap(), "512");
        assert_eq!(tokenize("2^(2+1)^2").and_then(parse).unwrap(), "512");
    }
    */
}

fn eval(input: &str) -> String {
    match tokenize(input).and_then(parse) {
        Ok(s) => s,
        Err(e) => match e {
            ParseError::InvalidNumber(s) => ["Invalid number: ", s.as_str() ].join(""),
            ParseError::UnrecognizedToken(s) => ["Unrecognized token: ", s.as_str()].join(""),
            ParseError::UnexpectedToken(found, expected) => ["Unexpected token: expected [", expected, "] but found '", found.as_str(), "'"].join(""),
            ParseError::UnexpectedEndOfInput => "Error: Unexpected end of input.".to_owned(),
            ParseError::OtherError(s) => s,
        }
    }
}

fn main() {
    let args = args();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();
    if args.len() > 1 {
        let input: Vec<String> = args.skip(1).collect();
        println!("{}", eval(&input.join("")));
    } else {
        let prompt = "[]> ".as_bytes();
        loop {
            stdout.write(prompt).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                       .try(&mut stderr);
            match input.trim() {
                "exit" => break,
                s => {
                    stdout.write(eval(s).as_bytes()).try(&mut stderr);
                    stdout.write("\n".as_bytes()).try(&mut stderr);
                    stdout.flush().try(&mut stderr);
                },
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the binary of a Grin peer-to-peer node.

extern crate clap;
extern crate daemonize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate serde;
extern crate serde_json;
extern crate blake2_rfc as blake2;

extern crate grin_api as api;
extern crate grin_grin as grin;
extern crate grin_wallet as wallet;
extern crate grin_config as config;
extern crate secp256k1zkp as secp;

use std::env;
use std::thread;
use std::io::Read;
use std::fs::File;
use std::time::Duration;

use clap::{Arg, App, SubCommand, ArgMatches};
use daemonize::Daemonize;

use secp::Secp256k1;

use wallet::WalletConfig;

use config::{GlobalConfig, ConfigError};

fn start_from_config_file(mut global_config:GlobalConfig){
	info!("Starting the Grin server from configuration file at {}", global_config.config_file_path.unwrap().to_str().unwrap());
	grin::Server::start(global_config.members.as_mut().unwrap().server.clone()).unwrap();
	loop {
		thread::sleep(Duration::from_secs(60));
	}
}

fn main() {
	env_logger::init().unwrap();

	let args = App::new("Grin")
    .version("0.1")
    .author("The Grin Team")
    .about("Lightweight implementation of the MimbleWimble protocol.")

    // specification of all the server commands and options
    .subcommand(SubCommand::with_name("server")
                .about("Control the Grin server")
                .arg(Arg::with_name("port")
                     .short("p")
                     .long("port")
                     .help("Port to start the P2P server on")
                     .takes_value(true))
				.arg(Arg::with_name("api_port")
                     .short("a")
                     .long("api_port")
                     .help("Port on which to start the api server (e.g. transaction pool api)")
                     .takes_value(true))
                .arg(Arg::with_name("seed")
                     .short("s")
                     .long("seed")
                     .help("Override seed node(s) to connect to")
                     .takes_value(true)
                     .multiple(true))
                .arg(Arg::with_name("mine")
                     .short("m")
                     .long("mine")
                     .help("Starts the debugging mining loop"))
				.arg(Arg::with_name("wallet_url")
                     .short("w")
                     .long("wallet_url")
                     .help("A listening wallet receiver to which mining rewards will be sent")
					 .takes_value(true))
                .subcommand(SubCommand::with_name("start")
                            .about("Start the Grin server as a daemon"))
                .subcommand(SubCommand::with_name("stop")
                            .about("Stop the Grin server daemon"))
                .subcommand(SubCommand::with_name("run")
                            .about("Run the Grin server in this console")))

    // specification of all the client commands and options
    .subcommand(SubCommand::with_name("client")
                .about("Communicates with the Grin server")
                .subcommand(SubCommand::with_name("status")
                            .about("current status of the Grin chain")))

    // specification of the wallet commands and options
    .subcommand(SubCommand::with_name("wallet")
                .about("Wallet software for Grin")
                .arg(Arg::with_name("pass")
                     .short("p")
                     .long("pass")
                     .help("Wallet passphrase used to generate the private key seed")
                     .takes_value(true))
				.arg(Arg::with_name("data_dir")
                     .short("dd")
                     .long("data_dir")
                     .help("Directory in which to store wallet files (defaults to current directory)")
                     .takes_value(true))
				.arg(Arg::with_name("port")
                     .short("r")
                     .long("port")
                     .help("Port on which to run the wallet receiver when in receiver mode")
                     .takes_value(true))
				.arg(Arg::with_name("api_server_address")
                     .short("a")
                     .long("api_server_address")
                     .help("The api address of a running node on which to check inputs and post transactions")
                     .takes_value(true))
                .subcommand(SubCommand::with_name("receive")
                            .about("Run the wallet in receiving mode. If an input file is provided, will process it, otherwise runs in server mode waiting for send requests.")
                            .arg(Arg::with_name("input")
                                 .help("Partial transaction to receive, expects as a JSON file.")
                                 .short("i")
                                 .long("input")
                                 .takes_value(true)))
                .subcommand(SubCommand::with_name("send")
                            .about("Builds a transaction to send someone some coins. By default, the transaction will just be printed to stdout. If a destination is provided, the command will attempt to contact the receiver at that address and send the transaction directly.")
                            .arg(Arg::with_name("amount")
                                 .help("Amount to send in the smallest denomination")
                                 .index(1))
                            .arg(Arg::with_name("dest")
                                 .help("Send the transaction to the provided server")
                                 .short("d")
                                 .long("dest")
                                 .takes_value(true))))
    .get_matches();

	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			server_command(server_args);
		}

		// client commands and options
		("client", Some(client_args)) => {
			match client_args.subcommand() {
				("status", _) => {
					println!("status info...");
				}
				_ => panic!("Unknown client command, use 'grin help client' for details"),
			}
		}

		// client commands and options
		("wallet", Some(wallet_args)) => {
			wallet_command(wallet_args);
		}

		//If nothing is specified, try to load up and use a config file instead
		//this should possibly become the way to configure most things
		//with most command line options being phased out
		_ => {
				//This will return a global config object,
				//which will either contain defaults for all
				//of the config structures or a configuration
				//read from a config file

				let mut global_config = GlobalConfig::new(None);
				match global_config {
					Ok(gc) => {
						if (gc.using_config_file){
							start_from_config_file(gc);
						} else {
							//won't attempt to just start with defaults,
							//and will reject
							println!("Unknown command, and no configuration file was found.");
							println!("Use 'grin help' for a list of all commands.");
						}
					}
					Err(e) => {
						println!("{}", e);
					}
				}

		}
	}
}

/// Handles the server part of the command line, mostly running, starting and
/// stopping the Grin blockchain server. Processes all the command line
/// arguments
/// to build a proper configuration and runs Grin with that configuration.
fn server_command(server_args: &ArgMatches) {
	info!("Starting the Grin server...");

	// just get defaults from the global config
	let mut server_config = GlobalConfig::default().members.unwrap().server;

	if let Some(port) = server_args.value_of("port") {
		server_config.p2p_config.as_mut().unwrap().port = port.parse().unwrap();
	}

	if let Some(api_port) = server_args.value_of("api_port") {
		let default_ip = "127.0.0.1";
		server_config.api_http_addr = format!("{}:{}", default_ip, api_port);
	}

	if server_args.is_present("mine") {
		server_config.mining_config.as_mut().unwrap().enable_mining = true;
	}

	if let Some(wallet_url) = server_args.value_of("wallet_url") {
		server_config.mining_config.as_mut().unwrap().wallet_receiver_url = wallet_url.to_string();
	}

	if let Some(seeds) = server_args.values_of("seed") {
		server_config.seeding_type = grin::Seeding::List;
		server_config.seeds = Some(seeds.map(|s| s.to_string()).collect());
	}

	/*let mut sc = GlobalConfig::default();
	sc.members.as_mut().unwrap().server = server_config.clone();
	println!("{}", sc.ser_config().unwrap());*/

	// start the server in the different run modes (interactive or daemon)
	match server_args.subcommand() {
		("run", _) => {
			grin::Server::start(server_config).unwrap();
			loop {
				thread::sleep(Duration::from_secs(60));
			}
		}
		("start", _) => {
			let daemonize = Daemonize::new()
				.pid_file("/tmp/grin.pid")
				.chown_pid_file(true)
				.privileged_action(move || {
					grin::Server::start(server_config.clone()).unwrap();
					loop {
						thread::sleep(Duration::from_secs(60));
					}
				});
			match daemonize.start() {
				Ok(_) => info!("Grin server succesfully started."),
				Err(e) => error!("Error starting: {}", e),
			}
		}
		("stop", _) => println!("TODO, just 'kill $pid' for now."),
		_ => panic!("Unknown server command, use 'grin help server' for details"),
	}
}

fn wallet_command(wallet_args: &ArgMatches) {
	let hd_seed = wallet_args.value_of("pass").expect("Wallet passphrase required.");

	// TODO do something closer to BIP39, eazy solution right now
  let seed = blake2::blake2b::blake2b(32, &[], hd_seed.as_bytes());

	let s = Secp256k1::new();
	let key = wallet::ExtendedKey::from_seed(&s, seed.as_bytes())
		.expect("Error deriving extended key from seed.");

	let default_ip = "127.0.0.1";
	let mut addr = format!("{}:13416", default_ip);

	let mut wallet_config = WalletConfig::default();
	if let Some(port) = wallet_args.value_of("port") {
		addr = format!("{}:{}", default_ip, port);
		wallet_config.api_http_addr = format!("http://{}", addr).to_string();
	}

	if let Some(dir) = wallet_args.value_of("dir") {
		wallet_config.data_file_dir = dir.to_string().clone();
	}

	if let Some(sa) = wallet_args.value_of("api_server_address") {
		wallet_config.check_node_api_http_addr = sa.to_string().clone();
	}

	match wallet_args.subcommand() {

		("receive", Some(receive_args)) => {
			if let Some(f) = receive_args.value_of("input") {
				let mut file = File::open(f).expect("Unable to open transaction file.");
				let mut contents = String::new();
				file.read_to_string(&mut contents).expect("Unable to read transaction file.");
				wallet::receive_json_tx(&wallet_config, &key, contents.as_str()).unwrap();
			} else {
				info!("Starting the Grin wallet receiving daemon at {}...",
				      wallet_config.api_http_addr);
				let mut apis = api::ApiServer::new("/v1".to_string());
				apis.register_endpoint("/receive".to_string(),
				                       wallet::WalletReceiver {
					                       key: key,
					                       config: wallet_config,
				                       });
				apis.start(addr).unwrap_or_else(|e| {
					error!("Failed to start Grin wallet receiver: {}.", e);
				});
			}
		}
		("send", Some(send_args)) => {
			let amount = send_args.value_of("amount")
				.expect("Amount to send required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let mut dest = "stdout";
			if let Some(d) = send_args.value_of("dest") {
				dest = d;
			}
			wallet::issue_send_tx(&wallet_config, &key, amount, dest.to_string()).unwrap();
		}
		_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
	}
}

<commit_msg>Minor warnings cleanup, rustfmt<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the binary of a Grin peer-to-peer node.

extern crate clap;
extern crate daemonize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate serde;
extern crate serde_json;
extern crate blake2_rfc as blake2;

extern crate grin_api as api;
extern crate grin_grin as grin;
extern crate grin_wallet as wallet;
extern crate grin_config as config;
extern crate secp256k1zkp as secp;

use std::thread;
use std::io::Read;
use std::fs::File;
use std::time::Duration;

use clap::{Arg, App, SubCommand, ArgMatches};
use daemonize::Daemonize;

use secp::Secp256k1;

use config::GlobalConfig;
use wallet::WalletConfig;

fn start_from_config_file(mut global_config: GlobalConfig) {
	info!(
		"Starting the Grin server from configuration file at {}",
		global_config.config_file_path.unwrap().to_str().unwrap()
	);
	grin::Server::start(global_config.members.as_mut().unwrap().server.clone()).unwrap();
	loop {
		thread::sleep(Duration::from_secs(60));
	}
}

fn main() {
	env_logger::init().unwrap();

	let args = App::new("Grin")
    .version("0.1")
    .author("The Grin Team")
    .about("Lightweight implementation of the MimbleWimble protocol.")

    // specification of all the server commands and options
    .subcommand(SubCommand::with_name("server")
                .about("Control the Grin server")
                .arg(Arg::with_name("port")
                     .short("p")
                     .long("port")
                     .help("Port to start the P2P server on")
                     .takes_value(true))
				.arg(Arg::with_name("api_port")
                     .short("a")
                     .long("api_port")
                     .help("Port on which to start the api server (e.g. transaction pool api)")
                     .takes_value(true))
                .arg(Arg::with_name("seed")
                     .short("s")
                     .long("seed")
                     .help("Override seed node(s) to connect to")
                     .takes_value(true)
                     .multiple(true))
                .arg(Arg::with_name("mine")
                     .short("m")
                     .long("mine")
                     .help("Starts the debugging mining loop"))
				.arg(Arg::with_name("wallet_url")
                     .short("w")
                     .long("wallet_url")
                     .help("A listening wallet receiver to which mining rewards will be sent")
					 .takes_value(true))
                .subcommand(SubCommand::with_name("start")
                            .about("Start the Grin server as a daemon"))
                .subcommand(SubCommand::with_name("stop")
                            .about("Stop the Grin server daemon"))
                .subcommand(SubCommand::with_name("run")
                            .about("Run the Grin server in this console")))

    // specification of all the client commands and options
    .subcommand(SubCommand::with_name("client")
                .about("Communicates with the Grin server")
                .subcommand(SubCommand::with_name("status")
                            .about("current status of the Grin chain")))

    // specification of the wallet commands and options
    .subcommand(SubCommand::with_name("wallet")
                .about("Wallet software for Grin")
                .arg(Arg::with_name("pass")
                     .short("p")
                     .long("pass")
                     .help("Wallet passphrase used to generate the private key seed")
                     .takes_value(true))
				.arg(Arg::with_name("data_dir")
                     .short("dd")
                     .long("data_dir")
                     .help("Directory in which to store wallet files (defaults to current directory)")
                     .takes_value(true))
				.arg(Arg::with_name("port")
                     .short("r")
                     .long("port")
                     .help("Port on which to run the wallet receiver when in receiver mode")
                     .takes_value(true))
				.arg(Arg::with_name("api_server_address")
                     .short("a")
                     .long("api_server_address")
                     .help("The api address of a running node on which to check inputs and post transactions")
                     .takes_value(true))
                .subcommand(SubCommand::with_name("receive")
                            .about("Run the wallet in receiving mode. If an input file is provided, will process it, otherwise runs in server mode waiting for send requests.")
                            .arg(Arg::with_name("input")
                                 .help("Partial transaction to receive, expects as a JSON file.")
                                 .short("i")
                                 .long("input")
                                 .takes_value(true)))
                .subcommand(SubCommand::with_name("send")
                            .about("Builds a transaction to send someone some coins. By default, the transaction will just be printed to stdout. If a destination is provided, the command will attempt to contact the receiver at that address and send the transaction directly.")
                            .arg(Arg::with_name("amount")
                                 .help("Amount to send in the smallest denomination")
                                 .index(1))
                            .arg(Arg::with_name("dest")
                                 .help("Send the transaction to the provided server")
                                 .short("d")
                                 .long("dest")
                                 .takes_value(true))))
    .get_matches();

	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			server_command(server_args);
		}

		// client commands and options
		("client", Some(client_args)) => {
			match client_args.subcommand() {
				("status", _) => {
					println!("status info...");
				}
				_ => panic!("Unknown client command, use 'grin help client' for details"),
			}
		}

		// client commands and options
		("wallet", Some(wallet_args)) => {
			wallet_command(wallet_args);
		}

		// If nothing is specified, try to load up and use a config file instead
		// this should possibly become the way to configure most things
		// with most command line options being phased out
		_ => {
			// This will return a global config object,
			// which will either contain defaults for all
			// of the config structures or a configuration
			// read from a config file

			let global_config = GlobalConfig::new(None);
			match global_config {
				Ok(gc) => {
					if gc.using_config_file {
						start_from_config_file(gc);
					} else {
						// won't attempt to just start with defaults,
						// and will reject
						println!("Unknown command, and no configuration file was found.");
						println!("Use 'grin help' for a list of all commands.");
					}
				}
				Err(e) => {
					println!("{}", e);
				}
			}

		}
	}
}

/// Handles the server part of the command line, mostly running, starting and
/// stopping the Grin blockchain server. Processes all the command line
/// arguments
/// to build a proper configuration and runs Grin with that configuration.
fn server_command(server_args: &ArgMatches) {
	info!("Starting the Grin server...");

	// just get defaults from the global config
	let mut server_config = GlobalConfig::default().members.unwrap().server;

	if let Some(port) = server_args.value_of("port") {
		server_config.p2p_config.as_mut().unwrap().port = port.parse().unwrap();
	}

	if let Some(api_port) = server_args.value_of("api_port") {
		let default_ip = "127.0.0.1";
		server_config.api_http_addr = format!("{}:{}", default_ip, api_port);
	}

	if server_args.is_present("mine") {
		server_config.mining_config.as_mut().unwrap().enable_mining = true;
	}

	if let Some(wallet_url) = server_args.value_of("wallet_url") {
		server_config
			.mining_config
			.as_mut()
			.unwrap()
			.wallet_receiver_url = wallet_url.to_string();
	}

	if let Some(seeds) = server_args.values_of("seed") {
		server_config.seeding_type = grin::Seeding::List;
		server_config.seeds = Some(seeds.map(|s| s.to_string()).collect());
	}

	/*let mut sc = GlobalConfig::default();
	sc.members.as_mut().unwrap().server = server_config.clone();
	println!("{}", sc.ser_config().unwrap());*/

	// start the server in the different run modes (interactive or daemon)
	match server_args.subcommand() {
		("run", _) => {
			grin::Server::start(server_config).unwrap();
			loop {
				thread::sleep(Duration::from_secs(60));
			}
		}
		("start", _) => {
			let daemonize = Daemonize::new()
				.pid_file("/tmp/grin.pid")
				.chown_pid_file(true)
				.privileged_action(move || {
					grin::Server::start(server_config.clone()).unwrap();
					loop {
						thread::sleep(Duration::from_secs(60));
					}
				});
			match daemonize.start() {
				Ok(_) => info!("Grin server succesfully started."),
				Err(e) => error!("Error starting: {}", e),
			}
		}
		("stop", _) => println!("TODO, just 'kill $pid' for now."),
		_ => panic!("Unknown server command, use 'grin help server' for details"),
	}
}

fn wallet_command(wallet_args: &ArgMatches) {
	let hd_seed = wallet_args.value_of("pass").expect(
		"Wallet passphrase required.",
	);

	// TODO do something closer to BIP39, eazy solution right now
	let seed = blake2::blake2b::blake2b(32, &[], hd_seed.as_bytes());

	let s = Secp256k1::new();
	let key = wallet::ExtendedKey::from_seed(&s, seed.as_bytes()).expect(
		"Error deriving extended key from seed.",
	);

	let default_ip = "127.0.0.1";
	let mut addr = format!("{}:13416", default_ip);

	let mut wallet_config = WalletConfig::default();
	if let Some(port) = wallet_args.value_of("port") {
		addr = format!("{}:{}", default_ip, port);
		wallet_config.api_http_addr = format!("http://{}", addr).to_string();
	}

	if let Some(dir) = wallet_args.value_of("dir") {
		wallet_config.data_file_dir = dir.to_string().clone();
	}

	if let Some(sa) = wallet_args.value_of("api_server_address") {
		wallet_config.check_node_api_http_addr = sa.to_string().clone();
	}

	match wallet_args.subcommand() {

		("receive", Some(receive_args)) => {
			if let Some(f) = receive_args.value_of("input") {
				let mut file = File::open(f).expect("Unable to open transaction file.");
				let mut contents = String::new();
				file.read_to_string(&mut contents).expect(
					"Unable to read transaction file.",
				);
				wallet::receive_json_tx(&wallet_config, &key, contents.as_str()).unwrap();
			} else {
				info!(
					"Starting the Grin wallet receiving daemon at {}...",
					wallet_config.api_http_addr
				);
				let mut apis = api::ApiServer::new("/v1".to_string());
				apis.register_endpoint(
					"/receive".to_string(),
					wallet::WalletReceiver {
						key: key,
						config: wallet_config,
					},
				);
				apis.start(addr).unwrap_or_else(|e| {
					error!("Failed to start Grin wallet receiver: {}.", e);
				});
			}
		}
		("send", Some(send_args)) => {
			let amount = send_args
				.value_of("amount")
				.expect("Amount to send required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let mut dest = "stdout";
			if let Some(d) = send_args.value_of("dest") {
				dest = d;
			}
			wallet::issue_send_tx(&wallet_config, &key, amount, dest.to_string()).unwrap();
		}
		_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
	}
}
<|endoftext|>


<commit_before>//! Thread pool for blocking operations

use std::fmt;

use derive_more::Display;
use futures::sync::oneshot;
use futures::{Async, Future, Poll};
use parking_lot::Mutex;
use threadpool::ThreadPool;

use crate::ResponseError;

/// Env variable for default cpu pool size
const ENV_CPU_POOL_VAR: &str = "ACTIX_CPU_POOL";

lazy_static::lazy_static! {
    pub(crate) static ref DEFAULT_POOL: Mutex<ThreadPool> = {
        let default = match std::env::var(ENV_CPU_POOL_VAR) {
            Ok(val) => {
                if let Ok(val) = val.parse() {
                    val
                } else {
                    log::error!("Can not parse ACTIX_CPU_POOL value");
                    num_cpus::get() * 5
                }
            }
            Err(_) => num_cpus::get() * 5,
        };
        Mutex::new(
            threadpool::Builder::new()
                .thread_name("actix-web".to_owned())
                .num_threads(default)
                .build(),
        )
    };
}

thread_local! {
    static POOL: ThreadPool = {
        DEFAULT_POOL.lock().clone()
    };
}

#[derive(Debug, Display)]
pub enum BlockingError<E: fmt::Debug> {
    #[display(fmt = "{:?}", _0)]
    Error(E),
    #[display(fmt = "Thread pool is gone")]
    Canceled,
}

impl<E: fmt::Debug> ResponseError for BlockingError<E> {}

/// Execute blocking function on a thread pool, returns future that resolves
/// to result of the function execution.
pub fn run<F, I, E>(f: F) -> CpuFuture<I, E>
where
    F: FnOnce() -> Result<I, E> + Send + 'static,
    I: Send + 'static,
    E: Send + fmt::Debug + 'static,
{
    let (tx, rx) = oneshot::channel();
    POOL.with(|pool| {
        pool.execute(move || {
            let _ = tx.send(f());
        })
    });

    CpuFuture { rx }
}

pub struct CpuFuture<I, E> {
    rx: oneshot::Receiver<Result<I, E>>,
}

impl<I, E: fmt::Debug> Future for CpuFuture<I, E> {
    type Item = I;
    type Error = BlockingError<E>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let res =
            futures::try_ready!(self.rx.poll().map_err(|_| BlockingError::Canceled));
        match res {
            Ok(val) => Ok(Async::Ready(val)),
            Err(err) => Err(BlockingError::Error(err)),
        }
    }
}
<commit_msg>do not execute blocking fn if result is not required<commit_after>//! Thread pool for blocking operations

use std::fmt;

use derive_more::Display;
use futures::sync::oneshot;
use futures::{Async, Future, Poll};
use parking_lot::Mutex;
use threadpool::ThreadPool;

use crate::ResponseError;

/// Env variable for default cpu pool size
const ENV_CPU_POOL_VAR: &str = "ACTIX_CPU_POOL";

lazy_static::lazy_static! {
    pub(crate) static ref DEFAULT_POOL: Mutex<ThreadPool> = {
        let default = match std::env::var(ENV_CPU_POOL_VAR) {
            Ok(val) => {
                if let Ok(val) = val.parse() {
                    val
                } else {
                    log::error!("Can not parse ACTIX_CPU_POOL value");
                    num_cpus::get() * 5
                }
            }
            Err(_) => num_cpus::get() * 5,
        };
        Mutex::new(
            threadpool::Builder::new()
                .thread_name("actix-web".to_owned())
                .num_threads(default)
                .build(),
        )
    };
}

thread_local! {
    static POOL: ThreadPool = {
        DEFAULT_POOL.lock().clone()
    };
}

/// Blocking operation execution error
#[derive(Debug, Display)]
pub enum BlockingError<E: fmt::Debug> {
    #[display(fmt = "{:?}", _0)]
    Error(E),
    #[display(fmt = "Thread pool is gone")]
    Canceled,
}

impl<E: fmt::Debug> ResponseError for BlockingError<E> {}

/// Execute blocking function on a thread pool, returns future that resolves
/// to result of the function execution.
pub fn run<F, I, E>(f: F) -> CpuFuture<I, E>
where
    F: FnOnce() -> Result<I, E> + Send + 'static,
    I: Send + 'static,
    E: Send + fmt::Debug + 'static,
{
    let (tx, rx) = oneshot::channel();
    POOL.with(|pool| {
        pool.execute(move || {
            if !tx.is_canceled() {
                let _ = tx.send(f());
            }
        })
    });

    CpuFuture { rx }
}

/// Blocking operation completion future. It resolves with results
/// of blocking function execution.
pub struct CpuFuture<I, E> {
    rx: oneshot::Receiver<Result<I, E>>,
}

impl<I, E: fmt::Debug> Future for CpuFuture<I, E> {
    type Item = I;
    type Error = BlockingError<E>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let res =
            futures::try_ready!(self.rx.poll().map_err(|_| BlockingError::Canceled));
        match res {
            Ok(val) => Ok(Async::Ready(val)),
            Err(err) => Err(BlockingError::Error(err)),
        }
    }
}
<|endoftext|>


<commit_before>use ast::{Ast, AstTrait};
use token::{Type, Token, TokenTrait};
use eval::{Scope, Func};
use std::borrow::Borrow;

pub enum EvalResult<T: AstTrait> {
    Push(T),
    Insert(T),
    Ignore,
    Error
}

impl<T: AstTrait> EvalResult<T> {
    pub fn unwrap_push(self) -> T {
        match self {
            EvalResult::Push(res) => res,
            _ => panic!()
        }
    }

    pub fn unwrap_insert(self) -> T {
        match self {
            EvalResult::Insert(res) => res,
            _ => panic!()
        }
    }

    pub fn is_insert(&self) -> bool {
        match *self {
            EvalResult::Insert(_) => true,
            _ => false
        }
    }

    pub fn is_push(&self) -> bool {
        match *self {
            EvalResult::Push(_) => true,
            _ => false
        }
    }

    pub fn is_error(&self) -> bool {
        match *self {
            EvalResult::Error => true,
            _ => false
        }
    }

    pub fn is_ignore(&self) -> bool {
        match *self {
            EvalResult::Ignore => true,
            _ => false
        }
    }
}

pub enum SetEval<T: AstTrait> {
    Skip(T),
    Remove(T),
    Other(T),
    Error
}

impl<T: AstTrait> SetEval<T> {
    pub fn is_skip(&self) -> bool {
        match *self {
            SetEval::Skip(_) => true,
            _ => false
        }
    }

    pub fn is_remove(&self) -> bool {
        match *self {
            SetEval::Remove(_) => true,
            _ => false
        }
    }

    pub fn is_other(&self) -> bool {
        match *self {
            SetEval::Other(_) => true,
            _ => false
        }
    }

    pub fn is_error(&self) -> bool {
        match *self {
            SetEval::Error => true,
            _ => false
        }
    }

    pub fn unwrap_skip(self) -> T {
        match self {
            SetEval::Skip(t) => t,
            _ => panic!()
        }
    }

    pub fn unwrap_remove(self) -> T {
        match self {
            SetEval::Remove(t) => t,
            _ => panic!()
        }
    }

    pub fn unwrap_other(self) -> T {
        match self {
            SetEval::Other(t) => t,
            _ => panic!()
        }
    }
}

fn print(mut ast: Ast) -> EvalResult<Ast> {
    for child in ast.dump_children().into_iter() {
        print!("{}", child.node_val.unwrap().get_lexed());
    }
    EvalResult::Ignore
}

fn println(mut ast: Ast) -> EvalResult<Ast> {
    for child in ast.dump_children().into_iter() {
        println!("{}", child.node_val.unwrap().get_lexed());
    }
    EvalResult::Ignore
}

fn add(mut ast: Ast) -> EvalResult<Ast> {
    let mut int: i64 = 0;
    let mut double: f64 = 0.0;
    for child in ast.dump_children().into_iter() {
        let child_val = child.node_val.unwrap().get_lexed();
        match child_val.parse::<i64>() {
            Ok(val) => int += val,
            _ => {
                match child_val.parse::<f64>() {
                    Ok(val) => double += val,
                    _ => return EvalResult::Error
                }
            }
        }
    }
    ast.node_val = Some(match double == 0.0 {
        true => Token::new_preset(int.to_string(), Type::Number),
        false => Token::new_preset((double + int as f64).to_string(), Type::Number)
    });
    EvalResult::Push(ast)
}

fn set(mut ast: Ast, scope: &mut Scope) -> EvalResult<Ast> {
    let mut children = ast.dump_children();
    let name = children.remove(0).get_child(0).unwrap().node_val.unwrap().get_lexed();
    if {
        match scope.find_func(&name) {
            Some(func_option) => {
                func_option.reset(children.remove(0).get_child(0).unwrap(), children.remove(0).get_child(0).unwrap());
                false
            },
            None => true
        }
    } {
        scope.insert_func_no_search(Func::new(name, children.remove(0), children.remove(0)));
    }
    EvalResult::Ignore
}

fn let_eval(mut ast: Ast, scope: &mut Scope) -> EvalResult<Ast> {
    let mut children = ast.dump_children();
    let name = children.remove(0).get_child(0).unwrap().node_val.unwrap().get_lexed();
    if {
        match scope.find_func(&name) {
            Some(func_option) => {
                func_option.reset(Ast::new_null(), children.remove(0).get_child(0).unwrap());
                false
            },
            None => true
        }
    } {
        scope.insert_func_no_search(Func::new(name, Ast::new_null(), children.remove(0)));
    }
    EvalResult::Ignore
}

pub fn evaluate_set_funcs(mut ast: Ast) -> SetEval<Ast> {
    match ast.get_child(0) {
        Some(mut child) => {
            let mut node = child.node_val.unwrap();
            match node.get_lexed().borrow() {
                "set" => {
                    node.set_lexed("seteval".to_string());
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    SetEval::Skip(ast)
                },
                "let" => {
                    node.set_lexed("leteval".to_string());
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    SetEval::Skip(ast)
                }
                "name" => SetEval::Remove(ast),
                "params" => SetEval::Remove(ast),
                "body" => SetEval::Remove(ast.get_child(0).unwrap()),
                _ => {
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    SetEval::Other(ast)
                }
            }
        },
        None => SetEval::Error
    }
}

pub fn evaluate_set(mut ast: Ast, scope: &mut Scope) -> EvalResult<Ast> {
    match ast.get_child(0) {
        Some(mut child) => {
            let node = child.node_val.unwrap();
            match node.get_lexed().borrow() {
                "seteval" => set(ast, scope),
                "leteval" => let_eval(ast, scope),
                _ => {
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    EvalResult::Insert(ast)
                }
            }
        },
        None => EvalResult::Error
    }
}

pub fn evaluate_builtin(mut ast: Ast) -> EvalResult<Ast> {
    match ast.get_child(0) {
        Some(mut child) => {
            let node = child.node_val.unwrap();
            child.node_val = Some(node);
            match child.node_val.unwrap().get_lexed().borrow() {
                "print" => print(ast),
                "println" => println(ast),
                "add" => add(ast),
                _ => EvalResult::Ignore
            }
        },
        None => EvalResult::Error
    }
}

pub fn generate_let_ast(tok: Token, ast: Ast) -> Ast {
    let mut func_ast = Ast::new(Token::new_preset('('.to_string(), Type::Oparen));
    func_ast.push_child(Ast::new(Token::new_preset("let".to_string(), Type::Func)));
    func_ast.push_child({
        let mut func_name = Ast::new(Token::new_preset('('.to_string(), Type::Oparen));
        func_name.push_child(Ast::new(Token::new_preset("name".to_string(), Type::Func)));
        func_name.push_child(Ast::new(tok));
        func_name
    });
    func_ast.push_child({
        let mut func_body = Ast::new(Token::new_preset('('.to_string(), Type::Oparen));
        func_body.push_child(Ast::new(Token::new_preset("body".to_string(), Type::Func)));
        func_body.push_child(ast);
        func_body
    });
    func_ast
}
<commit_msg>added the rest of the basic arithmetic operations. I need to add mod<commit_after>use ast::{Ast, AstTrait};
use token::{Type, Token, TokenTrait};
use eval::{Scope, Func};
use std::borrow::Borrow;

pub enum EvalResult<T: AstTrait> {
    Push(T),
    Insert(T),
    Ignore,
    Error
}

impl<T: AstTrait> EvalResult<T> {
    pub fn unwrap_push(self) -> T {
        match self {
            EvalResult::Push(res) => res,
            _ => panic!()
        }
    }

    pub fn unwrap_insert(self) -> T {
        match self {
            EvalResult::Insert(res) => res,
            _ => panic!()
        }
    }

    pub fn is_insert(&self) -> bool {
        match *self {
            EvalResult::Insert(_) => true,
            _ => false
        }
    }

    pub fn is_push(&self) -> bool {
        match *self {
            EvalResult::Push(_) => true,
            _ => false
        }
    }

    pub fn is_error(&self) -> bool {
        match *self {
            EvalResult::Error => true,
            _ => false
        }
    }

    pub fn is_ignore(&self) -> bool {
        match *self {
            EvalResult::Ignore => true,
            _ => false
        }
    }
}

pub enum SetEval<T: AstTrait> {
    Skip(T),
    Remove(T),
    Other(T),
    Error
}

impl<T: AstTrait> SetEval<T> {
    pub fn is_skip(&self) -> bool {
        match *self {
            SetEval::Skip(_) => true,
            _ => false
        }
    }

    pub fn is_remove(&self) -> bool {
        match *self {
            SetEval::Remove(_) => true,
            _ => false
        }
    }

    pub fn is_other(&self) -> bool {
        match *self {
            SetEval::Other(_) => true,
            _ => false
        }
    }

    pub fn is_error(&self) -> bool {
        match *self {
            SetEval::Error => true,
            _ => false
        }
    }

    pub fn unwrap_skip(self) -> T {
        match self {
            SetEval::Skip(t) => t,
            _ => panic!()
        }
    }

    pub fn unwrap_remove(self) -> T {
        match self {
            SetEval::Remove(t) => t,
            _ => panic!()
        }
    }

    pub fn unwrap_other(self) -> T {
        match self {
            SetEval::Other(t) => t,
            _ => panic!()
        }
    }
}

fn print(mut ast: Ast) -> EvalResult<Ast> {
    for child in ast.dump_children().into_iter() {
        print!("{}", child.node_val.unwrap().get_lexed());
    }
    EvalResult::Ignore
}

fn println(mut ast: Ast) -> EvalResult<Ast> {
    for child in ast.dump_children().into_iter() {
        println!("{}", child.node_val.unwrap().get_lexed());
    }
    EvalResult::Ignore
}

fn add(mut ast: Ast) -> EvalResult<Ast> {
    if ast.child_count() > 0 {
        let mut int: i64 = 0;
        let mut double: f64 = 0.0;
        for child in ast.dump_children().into_iter() {
            let child_val = child.node_val.unwrap().get_lexed();
            match child_val.parse::<i64>() {
                Ok(val) => int += val,
                _ => {
                    match child_val.parse::<f64>() {
                        Ok(val) => double += val,
                        _ => return EvalResult::Error
                    }
                }
            }
        }
        ast.node_val = Some(match double == 0.0 {
            true => Token::new_preset(int.to_string(), Type::Number),
            false => Token::new_preset((double + int as f64).to_string(), Type::Number)
        });
        EvalResult::Push(ast)

    } else {
        EvalResult::Error
    }
}

fn sub(mut ast: Ast) -> EvalResult<Ast> {
    if ast.child_count() > 0 {
        let mut int: i64 = 0;
        let mut double: f64 = 0.0;

        let mut children = ast.dump_children();
        let first = children.remove(0).node_val.unwrap().get_lexed();
        match first.parse::<i64>() {
            Ok(val) => int = val,
            _ => {
                match first.parse::<f64>() {
                    Ok(val) => double = val,
                    _ => return EvalResult::Error
                }
            }
        }

        for child in children.into_iter() {
            let child_val = child.node_val.unwrap().get_lexed();
            match child_val.parse::<i64>() {
                Ok(val) => int -= val,
                _ => {
                    match child_val.parse::<f64>() {
                        Ok(val) => double -= val,
                        _ => return EvalResult::Error
                    }
                }
            }
        }
        ast.node_val = Some(match double == 0.0 {
            true => Token::new_preset(int.to_string(), Type::Number),
            false => Token::new_preset((double + int as f64).to_string(), Type::Number)
        });
        EvalResult::Push(ast)
    } else {
        EvalResult::Error
    }
}

fn mult(mut ast: Ast) -> EvalResult<Ast> {
    if ast.child_count() > 0 {
        let mut int: i64 = 1;
        let mut double: f64 = 1.0;

        for child in ast.dump_children().into_iter() {
            let child_val = child.node_val.unwrap().get_lexed();
            match child_val.parse::<i64>() {
                Ok(val) => int *= val,
                _ => {
                    match child_val.parse::<f64>() {
                        Ok(val) => double *= val,
                        _ => return EvalResult::Error
                    }
                }
            }
        }
        ast.node_val = Some(match double == 1.0 {
            true => Token::new_preset(int.to_string(), Type::Number),
            false => Token::new_preset((double * int as f64).to_string(), Type::Number)
        });
        EvalResult::Push(ast)
    } else {
        EvalResult::Error
    }
}

fn div(mut ast: Ast) -> EvalResult<Ast> {
    if ast.child_count() > 0 {
        let mut int: i64 = 1;
        let mut double: f64 = 1.0;
        let mut is_int = true;

        let mut children = ast.dump_children();
        let first = children.remove(0).node_val.unwrap().get_lexed();
        match first.parse::<i64>() {
            Ok(val) => int = val,
            _ => {
                match first.parse::<f64>() {
                    Ok(val) => {
                        double = val;
                        is_int = !is_int;
                    },
                    _ => return EvalResult::Error
                }
            }
        }

        for child in children.into_iter() {
            let child_val = child.node_val.unwrap().get_lexed();
            match child_val.parse::<i64>() {
                Ok(val) => {
                    if is_int {
                        int /= val;
                    } else {
                        double /= val as f64;
                    }
                },
                _ => {
                    match child_val.parse::<f64>() {
                        Ok(val) => {
                            if is_int {
                                is_int = !is_int;
                                double = int as f64;
                            }
                            double /= val;
                        },
                        _ => return EvalResult::Error
                    }
                }
            }
        }
        ast.node_val = Some(match is_int {
            true => Token::new_preset(int.to_string(), Type::Number),
            false => Token::new_preset(double.to_string(), Type::Number)
        });
        EvalResult::Push(ast)
    } else {
        EvalResult::Error
    }
}

fn set(mut ast: Ast, scope: &mut Scope) -> EvalResult<Ast> {
    let mut children = ast.dump_children();
    let name = children.remove(0).get_child(0).unwrap().node_val.unwrap().get_lexed();
    if {
        match scope.find_func(&name) {
            Some(func_option) => {
                func_option.reset(children.remove(0).get_child(0).unwrap(), children.remove(0).get_child(0).unwrap());
                false
            },
            None => true
        }
    } {
        scope.insert_func_no_search(Func::new(name, children.remove(0), children.remove(0)));
    }
    EvalResult::Ignore
}

fn let_eval(mut ast: Ast, scope: &mut Scope) -> EvalResult<Ast> {
    let mut children = ast.dump_children();
    let name = children.remove(0).get_child(0).unwrap().node_val.unwrap().get_lexed();
    if {
        match scope.find_func(&name) {
            Some(func_option) => {
                func_option.reset(Ast::new_null(), children.remove(0).get_child(0).unwrap());
                false
            },
            None => true
        }
    } {
        scope.insert_func_no_search(Func::new(name, Ast::new_null(), children.remove(0)));
    }
    EvalResult::Ignore
}

pub fn evaluate_set_funcs(mut ast: Ast) -> SetEval<Ast> {
    match ast.get_child(0) {
        Some(mut child) => {
            let mut node = child.node_val.unwrap();
            match node.get_lexed().borrow() {
                "set" => {
                    node.set_lexed("seteval".to_string());
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    SetEval::Skip(ast)
                },
                "let" => {
                    node.set_lexed("leteval".to_string());
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    SetEval::Skip(ast)
                }
                "name" => SetEval::Remove(ast),
                "params" => SetEval::Remove(ast),
                "body" => SetEval::Remove(ast.get_child(0).unwrap()),
                _ => {
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    SetEval::Other(ast)
                }
            }
        },
        None => SetEval::Error
    }
}

pub fn evaluate_set(mut ast: Ast, scope: &mut Scope) -> EvalResult<Ast> {
    match ast.get_child(0) {
        Some(mut child) => {
            let node = child.node_val.unwrap();
            match node.get_lexed().borrow() {
                "seteval" => set(ast, scope),
                "leteval" => let_eval(ast, scope),
                _ => {
                    child.node_val = Some(node);
                    ast.insert_child(child, 0);
                    EvalResult::Insert(ast)
                }
            }
        },
        None => EvalResult::Error
    }
}

pub fn evaluate_builtin(mut ast: Ast) -> EvalResult<Ast> {
    match ast.get_child(0) {
        Some(mut child) => {
            let node = child.node_val.unwrap();
            child.node_val = Some(node);
            match child.node_val.unwrap().get_lexed().borrow() {
                "print" => print(ast),
                "println" => println(ast),
                "add" => add(ast),
                "sub" => sub(ast),
                "mult" => mult(ast),
                "div" => div(ast),
                _ => EvalResult::Ignore
            }
        },
        None => EvalResult::Error
    }
}

pub fn generate_let_ast(tok: Token, ast: Ast) -> Ast {
    let mut func_ast = Ast::new(Token::new_preset('('.to_string(), Type::Oparen));
    func_ast.push_child(Ast::new(Token::new_preset("let".to_string(), Type::Func)));
    func_ast.push_child({
        let mut func_name = Ast::new(Token::new_preset('('.to_string(), Type::Oparen));
        func_name.push_child(Ast::new(Token::new_preset("name".to_string(), Type::Func)));
        func_name.push_child(Ast::new(tok));
        func_name
    });
    func_ast.push_child({
        let mut func_body = Ast::new(Token::new_preset('('.to_string(), Type::Oparen));
        func_body.push_child(Ast::new(Token::new_preset("body".to_string(), Type::Func)));
        func_body.push_child(ast);
        func_body
    });
    func_ast
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate capstone_rust;

use self::capstone_rust::capstone;
use self::capstone_rust::capstone_sys::{x86_insn, x86_insn_group};
use std::fmt;
use super::address::Address;
use super::instruction::Instruction;

/// A representation of an eBPF instruction.
#[derive(Debug)]
pub struct CapstoneInstruction {
    insn: capstone::Instr,
}

fn is_group_match<F>(i: &capstone::Instr, predicate: F) -> bool
where
    F: Fn(&&u32) -> bool,
{
    match i.detail {
        None => false,
        Some(ref detail) => {
            match i.id {
                capstone::InstrIdArch::X86(_) => {
                    match detail.groups.iter().find(predicate) {
                        Some(_) => true,
                        None => false,
                    }
                }
                _ => unimplemented!(),
            }
        }
    }
}

impl Instruction for CapstoneInstruction {
    fn address(&self) -> Address {
        Address::new(self.insn.address)
    }

    fn comment(&self) -> Option<String> {
        None
    }

    fn mnemonic(&self) -> &str {
        &*self.insn.mnemonic
    }

    fn cycle_count(&self) -> Option<u32> {
        None
    }

    fn is_call(&self) -> bool {
        is_group_match(&self.insn, |&&x| x == x86_insn_group::X86_GRP_CALL.as_int())
    }

    fn is_local_conditional_jump(&self) -> bool {
        self.is_local_jump() &&
            match self.insn.id {
                capstone::InstrIdArch::X86(x86_insn::X86_INS_JMP) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LOOP) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LOOPE) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LOOPNE) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_XBEGIN) |
                capstone::InstrIdArch::X86(_) => true,
                _ => unimplemented!(),
            }
    }

    fn is_local_jump(&self) -> bool {
        is_group_match(&self.insn, |&&x| x == x86_insn_group::X86_GRP_JUMP.as_int()) &&
            match self.insn.id {
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LJMP) => false,
                capstone::InstrIdArch::X86(_) => true,
                _ => unimplemented!(),
            }
    }

    fn is_return(&self) -> bool {
        is_group_match(&self.insn, |&&x| x == x86_insn_group::X86_GRP_RET.as_int())
    }

    fn target_address(&self) -> Option<Address> {
        None
    }
}

impl fmt::Display for CapstoneInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.insn.mnemonic, self.insn.op_str)
    }
}

#[cfg(test)]
mod tests {
    use capstone_rust::capstone as cs;
    use super::CapstoneInstruction;
    use super::super::{Address, Function, Symbol};

    #[test]
    fn test() {
        let code = &[0x55, 0x48, 0x8b, 0x05, 0xb8, 0x13, 0x00, 0x00];

        let dec = cs::Capstone::new(cs::cs_arch::CS_ARCH_X86, cs::cs_mode::CS_MODE_32).unwrap();
        let buf = dec.disasm(code, 0, 0).unwrap();
        let is = buf.iter()
            .map(|insn| CapstoneInstruction { insn })
            .collect::<Vec<_>>();
        let f = Function::new(Symbol::new(Address::new(100000), Some("test")), is);

        assert!(f.control_flow_graph.entry_block.is_some());
    }
}
<commit_msg>capstone: Fix compilation error in tests.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate capstone_rust;

use self::capstone_rust::capstone;
use self::capstone_rust::capstone_sys::{x86_insn, x86_insn_group};
use std::fmt;
use super::address::Address;
use super::instruction::Instruction;

/// A representation of an eBPF instruction.
#[derive(Debug)]
pub struct CapstoneInstruction {
    insn: capstone::Instr,
}

fn is_group_match<F>(i: &capstone::Instr, predicate: F) -> bool
where
    F: Fn(&&u32) -> bool,
{
    match i.detail {
        None => false,
        Some(ref detail) => {
            match i.id {
                capstone::InstrIdArch::X86(_) => {
                    match detail.groups.iter().find(predicate) {
                        Some(_) => true,
                        None => false,
                    }
                }
                _ => unimplemented!(),
            }
        }
    }
}

impl Instruction for CapstoneInstruction {
    fn address(&self) -> Address {
        Address::new(self.insn.address)
    }

    fn comment(&self) -> Option<String> {
        None
    }

    fn mnemonic(&self) -> &str {
        &*self.insn.mnemonic
    }

    fn cycle_count(&self) -> Option<u32> {
        None
    }

    fn is_call(&self) -> bool {
        is_group_match(&self.insn, |&&x| x == x86_insn_group::X86_GRP_CALL.as_int())
    }

    fn is_local_conditional_jump(&self) -> bool {
        self.is_local_jump() &&
            match self.insn.id {
                capstone::InstrIdArch::X86(x86_insn::X86_INS_JMP) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LOOP) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LOOPE) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LOOPNE) |
                capstone::InstrIdArch::X86(x86_insn::X86_INS_XBEGIN) |
                capstone::InstrIdArch::X86(_) => true,
                _ => unimplemented!(),
            }
    }

    fn is_local_jump(&self) -> bool {
        is_group_match(&self.insn, |&&x| x == x86_insn_group::X86_GRP_JUMP.as_int()) &&
            match self.insn.id {
                capstone::InstrIdArch::X86(x86_insn::X86_INS_LJMP) => false,
                capstone::InstrIdArch::X86(_) => true,
                _ => unimplemented!(),
            }
    }

    fn is_return(&self) -> bool {
        is_group_match(&self.insn, |&&x| x == x86_insn_group::X86_GRP_RET.as_int())
    }

    fn target_address(&self) -> Option<Address> {
        None
    }
}

impl fmt::Display for CapstoneInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.insn.mnemonic, self.insn.op_str)
    }
}

#[cfg(test)]
mod tests {
    use capstone::capstone_rust::capstone as cs;
    use super::CapstoneInstruction;
    use super::super::{Address, Function, Symbol};

    #[test]
    fn test() {
        let code = &[0x55, 0x48, 0x8b, 0x05, 0xb8, 0x13, 0x00, 0x00];

        let dec = cs::Capstone::new(cs::cs_arch::CS_ARCH_X86, cs::cs_mode::CS_MODE_32).unwrap();
        let buf = dec.disasm(code, 0, 0).unwrap();
        let is = buf.iter()
            .map(|insn| CapstoneInstruction { insn })
            .collect::<Vec<_>>();
        let f = Function::new(Symbol::new(Address::new(100000), Some("test")), is);

        assert!(f.control_flow_graph.entry_block.is_some());
    }
}
<|endoftext|>