<commit_before>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 , Unscoped
                                 };
use core::semantic::types::*;
use core::semantic::ast::*;
use core::position::*;

use std::rc::Rc;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Unicode code point for the lambda character
const LAMBDA: &'static str = "\u{03bb}";

mod tests;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

    /// Wrap a function into a MnParser with this environment
    fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                -> MnParser<'a, 'b, I, T> {
        MnParser { env: self, parser: parser }
    }

    #[allow(dead_code)]
    fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        let function_form
            = self.name()
                  .and(self.function())
                  .map(|(name, fun)| DefForm::Function { name: name
                                                       , fun: fun });
        let top_level
            = self.name()
                  .and(self.type_annotation())
                  .and(self.expr())
                  .map(|((name, ty), body)|
                    DefForm::TopLevel { name: name
                                      , annot: ty
                                      , value: Rc::new(body) });

        self.reserved("defn").or(self.reserved("define"))
            .with(function_form.or(top_level))
            .map(Form::Define)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("if")
            .with(self.expr())
            .and(self.expr())
            .and(optional(self.expr()))
            .map(|((cond, if_clause), else_clause)|
                Form::If { condition: Rc::new(cond)
                         , if_clause: Rc::new(if_clause)
                         , else_clause: else_clause.map(Rc::new)
                         })
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("lambda")
            .or(self.reserved(LAMBDA))
            .with(self.function())
            .map(Form::Lambda)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_function(&self, input: State<I>) -> ParseResult<Function<'a, U>, I> {
        unimplemented!()
    }

    #[allow(dead_code)]
    fn parse_primitive_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.reserved("int")
                     .with(value(Primitive::IntSize))
               , self.reserved("uint")
                     .with(value(Primitive::IntSize))
               , self.reserved("float")
                     .with(value(Primitive::Float))
               , self.reserved("double")
                     .with(value(Primitive::Double))
               , self.reserved("bool")
                     .with(value(Primitive::Bool))
               , self.reserved("i8")
                     .with(value(Primitive::Int(Int::Int8)))
               , self.reserved("i16")
                     .with(value(Primitive::Int(Int::Int16)))
               , self.reserved("i32")
                    .with(value(Primitive::Int(Int::Int32)))
               , self.reserved("i64")
                     .with(value(Primitive::Int(Int::Int64)))
              , self.reserved("u8")
                    .with(value(Primitive::Uint(Int::Int8)))
              , self.reserved("u16")
                    .with(value(Primitive::Uint(Int::Int16)))
              , self.reserved("u32")
                    .with(value(Primitive::Uint(Int::Int32)))
              , self.reserved("u64")
                    .with(value(Primitive::Uint(Int::Int64)))
               ])
               .map(|primitive| Type::Prim(primitive))
               .parse_state(input)
    }

    fn raw_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('*').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Raw(Rc::new(t))))
                 .parse_state(input)
    }

    fn unique_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('@').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Unique(Rc::new(t))))
                 .parse_state(input)
    }

    fn borrow_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('&').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Borrowed(Rc::new(t))))
                 .parse_state(input)
    }
    fn parse_type(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.parser(MnEnv::parse_primitive_ty)
               , self.parser(MnEnv::raw_ptr_ty)
               , self.parser(MnEnv::unique_ptr_ty)
               , self.parser(MnEnv::borrow_ptr_ty)
               ])
            .parse_state(input)
    }

    fn parse_binding(&self, input: State<I>)
                    -> ParseResult<Unscoped<'a, Binding<'a, U>>, I> {
        let pos = input.position.clone();
        self.parser(MnEnv::parse_name)
            .and(self.type_annotation())
            .and(self.expr())
            .map(|((name, typ), value)|
                Annotated::new( Binding { name: name
                                        , typ: typ
                                        , value: Rc::new(value)
                                        }
                               , Position::from(pos)
                           ))
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_logical(&self, input: State<I>)
                    -> ParseResult<Logical<'a, U>, I> {
        let and = self.reserved("and")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

         let or = self.reserved("or")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

        and.or(or)
           .parse_state(input)
    }

    fn int_const(&'b self) -> MnParser<'a, 'b, I, Const> {
        self.parser(MnEnv::parse_int_const)
    }

    #[allow(dead_code)]
    fn parse_int_const(&self, input: State<I>) -> ParseResult<Const, I> {
        self.integer()
            .map(Const::IntConst)
            .parse_state(input)
    }

    fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {

        let binding_form =
            self.reserved("let")
                .with(many(self.parens(self.binding())))
                .and(many(self.expr()))
                .map(|(bindings, body)| LetForm::Let { bindings: bindings
                                                     , body: body });

        choice([ binding_form ])
            .map(Form::Let)
            .parse_state(input)
    }

    fn parse_name (&self, input: State<I>) -> ParseResult<Ident, I> {
        let position = input.position.clone();
        self.env.identifier::<'b>()
            .map(|name| Positional { pos: Position::from(position)
                                   , value: name })
            .parse_state(input)
    }

    fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.name()
            .and(many(self.expr()))
            .map(|(name, args)| Form::Call { fun: name, body: args })
            .parse_state(input)
    }

    fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
        let pos = Position::from(input.position.clone());
        self.env
            .parens(choice([ self.def()
                           , self.if_form()
                           , self.lambda()
                           , self.let_form()
                           , self.call()
                           ]))
            .or(self.int_const()
                    .map(Form::Constant))
            .map(|f| Annotated::new(f, pos) )
            .parse_state(input)
    }

    fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
        self.parser(MnEnv::parse_expr)
    }

    fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_def)
    }

    fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_if)
    }

    fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_let)
    }

    fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_lambda)
    }

    fn call(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_call)
    }

    fn name(&'b self) -> MnParser<'a, 'b, I, Ident> {
        self.parser(MnEnv::parse_name)
    }

    fn binding(&'b self)
              -> MnParser< 'a, 'b, I, Unscoped<'a, Binding<'a, U>>> {
        self.parser(MnEnv::parse_binding)
    }

    fn type_annotation(&'b self) -> MnParser<'a, 'b, I, types::Type> {
        self.parser(MnEnv::parse_type)
    }

    fn function(&'b self) -> MnParser<'a, 'b, I, Function<'a, U>> {
        self.parser(MnEnv::parse_function)
    }

}
pub fn parse_module<'a>(code: &'a str)
                        -> Result< Vec<Expr<'a, UnscopedState>>
                                 , ParseError<&str>>
 {
    let alpha_ext = "+-*/<=>!?:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(move |c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(move |c| alpha_ext.contains(c)))
          , reserved: [ // a number of these reserved words have no meaning yet
                        "and"               , "begin"
                      , "case"              , "cond"        , "class"
                      , "data"
                      , "define"            , "defn"        , "def"
                      , "delay"             , "fn"
                      , "do"                , "else"
                      , "if"                , "lambda"      , LAMBDA
                      , "let"               , "let*"        , "letrec"
                      , "or"
                      , "quasiquote"        , "quote"       , "unquote"
                      , "set!"              , "unquote-splicing"
                      , "i8"                , "u8"
                      , "i16"               , "u16"
                      , "i32"               , "u32"         , "f32"
                      , "i64"               , "u64"         , "f64"
                      , "int"               , "uint"        , "float"
                      , "bool"                              , "double"
                      , "ref"               , "move"        , "borrow"
                      , "trait"             , "typeclass"
                      , "instance"          , "impl"
                      ].iter().map(|x| (*x).into())
                       .collect()
        }
      , op: Identifier {
            start: satisfy(move |c| ops.contains(c))
          , rest:  satisfy(move |c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|"].iter().map(|x| (*x).into())
                                                     .collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .with(many1::<Vec<Expr<'a, U>>, _>(env.expr()))
       .parse(code)
       .map(|(e, _)| e)
}
<commit_msg>Additional reserving of words & symbols<commit_after>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 , Unscoped
                                 };
use core::semantic::types::*;
use core::semantic::ast::*;
use core::position::*;

use std::rc::Rc;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Unicode code point for the lambda character
const LAMBDA: &'static str      = "\u{03bb}";
const ARROW: &'static str       = "\u{8594}";
const FAT_ARROW: &'static str   = "\u{8685}";

mod tests;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

    /// Wrap a function into a MnParser with this environment
    fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                -> MnParser<'a, 'b, I, T> {
        MnParser { env: self, parser: parser }
    }

    #[allow(dead_code)]
    fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        let function_form
            = self.name()
                  .and(self.function())
                  .map(|(name, fun)| DefForm::Function { name: name
                                                       , fun: fun });
        let top_level
            = self.name()
                  .and(self.type_annotation())
                  .and(self.expr())
                  .map(|((name, ty), body)|
                    DefForm::TopLevel { name: name
                                      , annot: ty
                                      , value: Rc::new(body) });

        self.reserved("defn").or(self.reserved("define"))
            .with(function_form.or(top_level))
            .map(Form::Define)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("if")
            .with(self.expr())
            .and(self.expr())
            .and(optional(self.expr()))
            .map(|((cond, if_clause), else_clause)|
                Form::If { condition: Rc::new(cond)
                         , if_clause: Rc::new(if_clause)
                         , else_clause: else_clause.map(Rc::new)
                         })
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("lambda")
            .or(self.reserved(LAMBDA))
            .with(self.function())
            .map(Form::Lambda)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_function(&self, input: State<I>) -> ParseResult<Function<'a, U>, I> {
        unimplemented!()
    }

    #[allow(dead_code)]
    fn parse_primitive_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.reserved("int")
                     .with(value(Primitive::IntSize))
               , self.reserved("uint")
                     .with(value(Primitive::IntSize))
               , self.reserved("float")
                     .with(value(Primitive::Float))
               , self.reserved("double")
                     .with(value(Primitive::Double))
               , self.reserved("bool")
                     .with(value(Primitive::Bool))
               , self.reserved("i8")
                     .with(value(Primitive::Int(Int::Int8)))
               , self.reserved("i16")
                     .with(value(Primitive::Int(Int::Int16)))
               , self.reserved("i32")
                    .with(value(Primitive::Int(Int::Int32)))
               , self.reserved("i64")
                     .with(value(Primitive::Int(Int::Int64)))
              , self.reserved("u8")
                    .with(value(Primitive::Uint(Int::Int8)))
              , self.reserved("u16")
                    .with(value(Primitive::Uint(Int::Int16)))
              , self.reserved("u32")
                    .with(value(Primitive::Uint(Int::Int32)))
              , self.reserved("u64")
                    .with(value(Primitive::Uint(Int::Int64)))
               ])
               .map(|primitive| Type::Prim(primitive))
               .parse_state(input)
    }

    fn raw_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('*').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Raw(Rc::new(t))))
                 .parse_state(input)
    }

    fn unique_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('@').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Unique(Rc::new(t))))
                 .parse_state(input)
    }

    fn borrow_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('&').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Borrowed(Rc::new(t))))
                 .parse_state(input)
    }
    fn parse_type(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.parser(MnEnv::parse_primitive_ty)
               , self.parser(MnEnv::raw_ptr_ty)
               , self.parser(MnEnv::unique_ptr_ty)
               , self.parser(MnEnv::borrow_ptr_ty)
               ])
            .parse_state(input)
    }

    fn parse_binding(&self, input: State<I>)
                    -> ParseResult<Unscoped<'a, Binding<'a, U>>, I> {
        let pos = input.position.clone();
        self.parser(MnEnv::parse_name)
            .and(self.type_annotation())
            .and(self.expr())
            .map(|((name, typ), value)|
                Annotated::new( Binding { name: name
                                        , typ: typ
                                        , value: Rc::new(value)
                                        }
                               , Position::from(pos)
                           ))
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_logical(&self, input: State<I>)
                    -> ParseResult<Logical<'a, U>, I> {
        let and = self.reserved("and")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

         let or = self.reserved("or")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

        and.or(or)
           .parse_state(input)
    }

    fn int_const(&'b self) -> MnParser<'a, 'b, I, Const> {
        self.parser(MnEnv::parse_int_const)
    }

    #[allow(dead_code)]
    fn parse_int_const(&self, input: State<I>) -> ParseResult<Const, I> {
        self.integer()
            .map(Const::IntConst)
            .parse_state(input)
    }

    fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {

        let binding_form =
            self.reserved("let")
                .with(many(self.parens(self.binding())))
                .and(many(self.expr()))
                .map(|(bindings, body)| LetForm::Let { bindings: bindings
                                                     , body: body });

        choice([ binding_form ])
            .map(Form::Let)
            .parse_state(input)
    }

    fn parse_name (&self, input: State<I>) -> ParseResult<Ident, I> {
        let position = input.position.clone();
        self.env.identifier::<'b>()
            .map(|name| Positional { pos: Position::from(position)
                                   , value: name })
            .parse_state(input)
    }

    fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.name()
            .and(many(self.expr()))
            .map(|(name, args)| Form::Call { fun: name, body: args })
            .parse_state(input)
    }

    fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
        let pos = Position::from(input.position.clone());
        self.env
            .parens(choice([ self.def()
                           , self.if_form()
                           , self.lambda()
                           , self.let_form()
                           , self.call()
                           ]))
            .or(self.int_const()
                    .map(Form::Constant))
            .map(|f| Annotated::new(f, pos) )
            .parse_state(input)
    }

    fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
        self.parser(MnEnv::parse_expr)
    }

    fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_def)
    }

    fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_if)
    }

    fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_let)
    }

    fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_lambda)
    }

    fn call(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_call)
    }

    fn name(&'b self) -> MnParser<'a, 'b, I, Ident> {
        self.parser(MnEnv::parse_name)
    }

    fn binding(&'b self)
              -> MnParser< 'a, 'b, I, Unscoped<'a, Binding<'a, U>>> {
        self.parser(MnEnv::parse_binding)
    }

    fn type_annotation(&'b self) -> MnParser<'a, 'b, I, types::Type> {
        self.parser(MnEnv::parse_type)
    }

    fn function(&'b self) -> MnParser<'a, 'b, I, Function<'a, U>> {
        self.parser(MnEnv::parse_function)
    }

}
pub fn parse_module<'a>(code: &'a str)
                        -> Result< Vec<Expr<'a, UnscopedState>>
                                 , ParseError<&str>>
 {
    let alpha_ext = "+-*/<=>!:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(move |c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(move |c| alpha_ext.contains(c)))
          , reserved: [ // a number of these reserved words have no meaning yet
                        "and"               , "begin"
                      , "case"              , "cond"        , "class"
                      , "data"
                      , "define"            , "defn"        , "def"
                      , "delay"             , "fn"
                      , "do"                , "else"
                      , "if"                , "lambda"      , LAMBDA
                      , "let"               , "let*"        , "letrec"
                      , "or"
                      , "quasiquote"        , "quote"       , "unquote"
                      , "set!"              , "unquote-splicing"
                      , "struct"            , "union"
                      , "i8"                , "u8"
                      , "i16"               , "u16"
                      , "i32"               , "u32"         , "f32"
                      , "i64"               , "u64"         , "f64"
                      , "int"               , "uint"        , "float"
                      , "bool"                              , "double"
                      , "ref"               , "move"        , "borrow"
                      , "trait"             , "typeclass"
                      , "instance"          , "impl"
                      ].iter().map(|x| (*x).into())
                       .collect()
        }
      , op: Identifier {
            start: satisfy(move |c| ops.contains(c))
          , rest:  satisfy(move |c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|", ARROW, FAT_ARROW]
                .iter().map(|x| (*x).into()).collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .with(many1::<Vec<Expr<'a, U>>, _>(env.expr()))
       .parse(code)
       .map(|(e, _)| e)
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

extern crate croaring;
extern crate rand;

use croaring::Bitmap;
use rand::Rng;

// We can use "andnot" to rewind the rm_log easily by passing in a "bitmask" of
// all the subsequent pos we want to rewind.
#[test]
fn test_andnot_bitmap() {
	// bitmap:  10010011
	// bitmask: ....1111 (i.e. rewind to leave first 4 pos in place)
	// result:  1001....
	let bitmap: Bitmap = vec![1, 4, 7, 8].into_iter().collect();
	let bitmask: Bitmap = vec![5, 6, 7, 8].into_iter().collect();
	let res = bitmap.andnot(&bitmask);
	assert_eq!(res.to_vec(), vec![1, 4]);
}

// Alternatively we can use "and" to rewind the rm_log easily by passing in a
// "bitmask" of all the pos we want to keep.
#[test]
fn test_and_bitmap() {
	// bitmap:  10010011
	// bitmask: 1111.... (i.e. rewind to leave first 4 pos in place)
	// result:  1001....
	let bitmap: Bitmap = vec![1, 4, 7, 8].into_iter().collect();
	let bitmask: Bitmap = vec![1, 2, 3, 4].into_iter().collect();
	let res = bitmap.and(&bitmask);
	assert_eq!(res.to_vec(), vec![1, 4]);
}

#[test]
fn test_flip_bitmap() {
	let bitmap: Bitmap = vec![1, 2, 4].into_iter().collect();
	let res = bitmap.flip(2..4);
	assert_eq!(res.to_vec(), vec![1, 3, 4]);
}

#[test]
fn test_a_small_bitmap() {
	let bitmap: Bitmap = vec![1, 99, 1_000].into_iter().collect();
	let serialized_buffer = bitmap.serialize();

	// we can store 3 pos in a roaring bitmap in 22 bytes
	// this is compared to storing them as a vec of u64 values which would be 8 * 3
	// = 32 bytes
	assert_eq!(serialized_buffer.len(), 22);
}

#[test]
fn test_1000_inputs() {
	let mut rng = rand::thread_rng();
	let mut bitmap = Bitmap::create();
	for _ in 1..1_000 {
		let n = rng.gen_range(0, 1_000_000);
		bitmap.add(n);
	}
	let serialized_buffer = bitmap.serialize();
	println!(
		"bitmap with 1,000 (out of 1,000,000) values in it: {}",
		serialized_buffer.len()
	);
	bitmap.run_optimize();
	let serialized_buffer = bitmap.serialize();
	println!(
		"bitmap with 1,000 (out of 1,000,000) values in it (optimized): {}",
		serialized_buffer.len()
	);
}

#[test]
fn test_a_big_bitmap() {
	let mut bitmap: Bitmap = (1..1_000_000).collect();
	let serialized_buffer = bitmap.serialize();

	// we can also store 1,000 pos in 2,014 bytes
	// a vec of u64s here would be 8,000 bytes
	assert_eq!(serialized_buffer.len(), 131_208);

	// but note we can optimize this heavily to get down to 230 bytes...
	assert!(bitmap.run_optimize());
	let serialized_buffer = bitmap.serialize();
	assert_eq!(serialized_buffer.len(), 230);
}
<commit_msg>fix the comments of test bitmap (#1516)<commit_after>// Copyright 2018 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.

extern crate croaring;
extern crate rand;

use croaring::Bitmap;
use rand::Rng;

// We can use "andnot" to rewind the rm_log easily by passing in a "bitmask" of
// all the subsequent pos we want to rewind.
#[test]
fn test_andnot_bitmap() {
	// bitmap:  10010011
	// bitmask: ....1111 (i.e. rewind to leave first 4 pos in place)
	// result:  1001....
	let bitmap: Bitmap = vec![1, 4, 7, 8].into_iter().collect();
	let bitmask: Bitmap = vec![5, 6, 7, 8].into_iter().collect();
	let res = bitmap.andnot(&bitmask);
	assert_eq!(res.to_vec(), vec![1, 4]);
}

// Alternatively we can use "and" to rewind the rm_log easily by passing in a
// "bitmask" of all the pos we want to keep.
#[test]
fn test_and_bitmap() {
	// bitmap:  10010011
	// bitmask: 1111.... (i.e. rewind to leave first 4 pos in place)
	// result:  1001....
	let bitmap: Bitmap = vec![1, 4, 7, 8].into_iter().collect();
	let bitmask: Bitmap = vec![1, 2, 3, 4].into_iter().collect();
	let res = bitmap.and(&bitmask);
	assert_eq!(res.to_vec(), vec![1, 4]);
}

#[test]
fn test_flip_bitmap() {
	let bitmap: Bitmap = vec![1, 2, 4].into_iter().collect();
	let res = bitmap.flip(2..4);
	assert_eq!(res.to_vec(), vec![1, 3, 4]);
}

#[test]
fn test_a_small_bitmap() {
	let bitmap: Bitmap = vec![1, 99, 1_000].into_iter().collect();
	let serialized_buffer = bitmap.serialize();

	// we can store 3 pos in a roaring bitmap in 22 bytes
	// this is compared to storing them as a vec of u32 values which would be 4 * 3
	// = 12 bytes
	assert_eq!(serialized_buffer.len(), 22);
}

#[test]
fn test_1000_inputs() {
	let mut rng = rand::thread_rng();
	let mut bitmap = Bitmap::create();
	for _ in 1..1_000 {
		let n = rng.gen_range(0, 1_000_000);
		bitmap.add(n);
	}
	let serialized_buffer = bitmap.serialize();
	println!(
		"bitmap with 1,000 (out of 1,000,000) values in it: {}",
		serialized_buffer.len()
	);
	bitmap.run_optimize();
	let serialized_buffer = bitmap.serialize();
	println!(
		"bitmap with 1,000 (out of 1,000,000) values in it (optimized): {}",
		serialized_buffer.len()
	);
}

#[test]
fn test_a_big_bitmap() {
	let mut bitmap: Bitmap = (1..1_000_000).collect();
	let serialized_buffer = bitmap.serialize();

	// we can also store 1,000,000 pos in 131,208 bytes
	// a vec of u32s here would be 4,000,000 bytes
	assert_eq!(serialized_buffer.len(), 131_208);

	// but note we can optimize this heavily to get down to 230 bytes...
	assert!(bitmap.run_optimize());
	let serialized_buffer = bitmap.serialize();
	assert_eq!(serialized_buffer.len(), 230);
}
<|endoftext|>


<commit_before>use std::fmt;

use crate::text_format::lexer::Lexer;
use crate::text_format::lexer::LexerError;
use crate::text_format::lexer::Loc;
use crate::text_format::lexer::ParserLanguage;
use crate::text_format::lexer::StrLit;
use crate::text_format::lexer::StrLitDecodeError;
use crate::text_format::lexer::Token;
use crate::text_format::lexer::TokenWithLocation;

#[derive(Debug)]
pub enum TokenizerError {
    LexerError(LexerError),
    StrLitDecodeError(StrLitDecodeError),
    InternalError,
    IncorrectInput, // TODO: too broad
    UnexpectedEof,
    ExpectStrLit,
    ExpectIntLit,
    ExpectFloatLit,
    ExpectIdent,
    ExpectNamedIdent(String),
    ExpectChar(char),
    ExpectAnyChar(Vec<char>),
}

impl fmt::Display for TokenizerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            TokenizerError::LexerError(e) => write!(f, "{}", e),
            TokenizerError::StrLitDecodeError(e) => write!(f, "{}", e),
            TokenizerError::InternalError => write!(f, "Internal tokenizer error"),
            TokenizerError::IncorrectInput => write!(f, "Incorrect input"),
            TokenizerError::UnexpectedEof => write!(f, "Unexpected EOF"),
            TokenizerError::ExpectStrLit => write!(f, "Expecting string literal"),
            TokenizerError::ExpectIntLit => write!(f, "Expecting int literal"),
            TokenizerError::ExpectFloatLit => write!(f, "Expecting float literal"),
            TokenizerError::ExpectIdent => write!(f, "Expecting identifier"),
            TokenizerError::ExpectNamedIdent(n) => write!(f, "Expecting identifier {}", n),
            TokenizerError::ExpectChar(c) => write!(f, "Expecting char {}", c),
            TokenizerError::ExpectAnyChar(c) => write!(
                f,
                "Expecting one of: {}",
                c.iter()
                    .map(|c| format!("{}", c))
                    .collect::<Vec<String>>()
                    .join(", ")
            ),
        }
    }
}

impl std::error::Error for TokenizerError {}

pub type TokenizerResult<R> = Result<R, TokenizerError>;

impl From<LexerError> for TokenizerError {
    fn from(e: LexerError) -> Self {
        TokenizerError::LexerError(e)
    }
}

impl From<StrLitDecodeError> for TokenizerError {
    fn from(e: StrLitDecodeError) -> Self {
        TokenizerError::StrLitDecodeError(e)
    }
}

#[derive(Clone)]
pub struct Tokenizer<'a> {
    lexer: Lexer<'a>,
    next_token: Option<TokenWithLocation>,
    last_token_loc: Option<Loc>,
}

impl<'a> Tokenizer<'a> {
    pub fn new(input: &'a str, comment_style: ParserLanguage) -> Tokenizer<'a> {
        Tokenizer {
            lexer: Lexer::new(input, comment_style),
            next_token: None,
            last_token_loc: None,
        }
    }

    pub fn loc(&self) -> Loc {
        // After lookahead return the location of the next token
        self.next_token
            .as_ref()
            .map(|t| t.loc.clone())
            // After token consumed return the location of that token
            .or(self.last_token_loc.clone())
            // Otherwise return the position of lexer
            .unwrap_or(self.lexer.loc)
    }

    pub fn lookahead_loc(&mut self) -> Loc {
        drop(self.lookahead());
        // TODO: does not handle EOF properly
        self.loc()
    }

    fn lookahead(&mut self) -> TokenizerResult<Option<&Token>> {
        Ok(match self.next_token {
            Some(ref token) => Some(&token.token),
            None => {
                self.next_token = self.lexer.next_token()?;
                self.last_token_loc = self.next_token.as_ref().map(|t| t.loc.clone());
                match self.next_token {
                    Some(ref token) => Some(&token.token),
                    None => None,
                }
            }
        })
    }

    pub fn lookahead_some(&mut self) -> TokenizerResult<&Token> {
        match self.lookahead()? {
            Some(token) => Ok(token),
            None => Err(TokenizerError::UnexpectedEof),
        }
    }

    fn next(&mut self) -> TokenizerResult<Option<Token>> {
        self.lookahead()?;
        Ok(self
            .next_token
            .take()
            .map(|TokenWithLocation { token, .. }| token))
    }

    pub fn next_some(&mut self) -> TokenizerResult<Token> {
        match self.next()? {
            Some(token) => Ok(token),
            None => Err(TokenizerError::UnexpectedEof),
        }
    }

    /// Can be called only after lookahead, otherwise it's error
    pub fn advance(&mut self) -> TokenizerResult<Token> {
        self.next_token
            .take()
            .map(|TokenWithLocation { token, .. }| token)
            .ok_or(TokenizerError::InternalError)
    }

    /// No more tokens
    pub fn syntax_eof(&mut self) -> TokenizerResult<bool> {
        Ok(self.lookahead()?.is_none())
    }

    pub fn next_token_if_map<P, R>(&mut self, p: P) -> TokenizerResult<Option<R>>
    where
        P: FnOnce(&Token) -> Option<R>,
    {
        self.lookahead()?;
        let v = match self.next_token {
            Some(ref token) => match p(&token.token) {
                Some(v) => v,
                None => return Ok(None),
            },
            _ => return Ok(None),
        };
        self.next_token = None;
        Ok(Some(v))
    }

    pub fn next_token_check_map<P, R, E>(&mut self, p: P) -> Result<R, E>
    where
        P: FnOnce(&Token) -> Result<R, E>,
        E: From<TokenizerError>,
    {
        self.lookahead()?;
        let r = match self.next_token {
            Some(ref token) => p(&token.token)?,
            None => return Err(TokenizerError::UnexpectedEof.into()),
        };
        self.next_token = None;
        Ok(r)
    }

    fn next_token_if<P>(&mut self, p: P) -> TokenizerResult<Option<Token>>
    where
        P: FnOnce(&Token) -> bool,
    {
        self.next_token_if_map(|token| if p(token) { Some(token.clone()) } else { None })
    }

    pub fn next_ident_if_in(&mut self, idents: &[&str]) -> TokenizerResult<Option<String>> {
        let v = match self.lookahead()? {
            Some(&Token::Ident(ref next)) => {
                if idents.into_iter().find(|&i| i == next).is_some() {
                    next.clone()
                } else {
                    return Ok(None);
                }
            }
            _ => return Ok(None),
        };
        self.advance()?;
        Ok(Some(v))
    }

    pub fn next_ident_if_eq(&mut self, word: &str) -> TokenizerResult<bool> {
        Ok(self.next_ident_if_in(&[word])? != None)
    }

    pub fn next_ident_expect_eq(&mut self, word: &str) -> TokenizerResult<()> {
        if self.next_ident_if_eq(word)? {
            Ok(())
        } else {
            Err(TokenizerError::ExpectNamedIdent(word.to_owned()))
        }
    }

    pub fn next_ident_if_eq_error(&mut self, word: &str) -> TokenizerResult<()> {
        if self.clone().next_ident_if_eq(word)? {
            return Err(TokenizerError::IncorrectInput);
        }
        Ok(())
    }

    pub fn next_symbol_if_eq(&mut self, symbol: char) -> TokenizerResult<bool> {
        Ok(self.next_token_if(|token| match token {
            &Token::Symbol(c) if c == symbol => true,
            _ => false,
        })? != None)
    }

    pub fn next_symbol_expect_eq(&mut self, symbol: char) -> TokenizerResult<()> {
        if self.lookahead_is_symbol(symbol)? {
            self.advance()?;
            Ok(())
        } else {
            Err(TokenizerError::ExpectChar(symbol))
        }
    }

    pub fn next_symbol_expect_eq_oneof(&mut self, symbols: &[char]) -> TokenizerResult<char> {
        for symbol in symbols {
            if let Ok(()) = self.next_symbol_expect_eq(*symbol) {
                return Ok(*symbol);
            }
        }
        Err(TokenizerError::ExpectAnyChar(symbols.to_owned()))
    }

    pub fn lookahead_is_str_lit(&mut self) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(&Token::StrLit(..)) => true,
            _ => false,
        })
    }

    pub fn lookahead_is_int_lit(&mut self) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(&Token::IntLit(..)) => true,
            _ => false,
        })
    }

    pub fn lookahead_is_json_number(&mut self) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(&Token::JsonNumber(..)) => true,
            _ => false,
        })
    }

    pub fn lookahead_if_symbol(&mut self) -> TokenizerResult<Option<char>> {
        Ok(match self.lookahead()? {
            Some(&Token::Symbol(c)) => Some(c),
            _ => None,
        })
    }

    pub fn lookahead_is_symbol(&mut self, symbol: char) -> TokenizerResult<bool> {
        Ok(self.lookahead_if_symbol()? == Some(symbol))
    }

    pub fn lookahead_is_ident(&mut self, ident: &str) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(Token::Ident(i)) => i == ident,
            _ => false,
        })
    }

    pub fn next_ident(&mut self) -> TokenizerResult<String> {
        self.next_token_check_map(|token| match token {
            &Token::Ident(ref ident) => Ok(ident.clone()),
            _ => Err(TokenizerError::ExpectIdent),
        })
    }

    pub fn next_str_lit(&mut self) -> TokenizerResult<StrLit> {
        self.next_token_check_map(|token| match token {
            &Token::StrLit(ref str_lit) => Ok(str_lit.clone()),
            _ => Err(TokenizerError::ExpectStrLit),
        })
    }

    pub fn next_int_lit(&mut self) -> TokenizerResult<u64> {
        self.next_token_check_map(|token| match token {
            &Token::IntLit(v) => Ok(v),
            _ => Err(TokenizerError::ExpectIntLit),
        })
    }

    pub fn next_float_lit(&mut self) -> TokenizerResult<f64> {
        self.next_token_check_map(|token| match token {
            &Token::FloatLit(v) => Ok(v),
            _ => Err(TokenizerError::ExpectFloatLit),
        })
    }
}

#[cfg(test)]
mod test {

    use super::*;

    fn tokenize<P, R>(input: &str, what: P) -> R
    where
        P: FnOnce(&mut Tokenizer) -> TokenizerResult<R>,
    {
        let mut tokenizer = Tokenizer::new(input, ParserLanguage::Proto);
        let r = what(&mut tokenizer).expect(&format!("parse failed at {}", tokenizer.loc()));
        let eof = tokenizer
            .syntax_eof()
            .expect(&format!("check eof failed at {}", tokenizer.loc()));
        assert!(eof, "{}", tokenizer.loc());
        r
    }

    #[test]
    fn test_ident() {
        let msg = r#"  aabb_c  "#;
        let mess = tokenize(msg, |p| p.next_ident().map(|s| s.to_owned()));
        assert_eq!("aabb_c", mess);
    }

    #[test]
    fn test_str_lit() {
        let msg = r#"  "a\nb"  "#;
        let mess = tokenize(msg, |p| p.next_str_lit());
        assert_eq!(
            StrLit {
                escaped: r#"a\nb"#.to_owned()
            },
            mess
        );
    }
}
<commit_msg>Use thiserror for TokenizerError<commit_after>use crate::text_format::lexer::Lexer;
use crate::text_format::lexer::LexerError;
use crate::text_format::lexer::Loc;
use crate::text_format::lexer::ParserLanguage;
use crate::text_format::lexer::StrLit;
use crate::text_format::lexer::StrLitDecodeError;
use crate::text_format::lexer::Token;
use crate::text_format::lexer::TokenWithLocation;

#[derive(Debug, thiserror::Error)]
pub enum TokenizerError {
    #[error(transparent)]
    LexerError(#[from] LexerError),
    #[error(transparent)]
    StrLitDecodeError(#[from] StrLitDecodeError),
    #[error("Internal tokenizer error")]
    InternalError,
    // TODO: too broad
    #[error("Incorrect input")]
    IncorrectInput,
    #[error("Unexpected end of input")]
    UnexpectedEof,
    #[error("Expecting string literal")]
    ExpectStrLit,
    #[error("Expecting int literal")]
    ExpectIntLit,
    #[error("Expecting float literal")]
    ExpectFloatLit,
    #[error("Expecting identifier")]
    ExpectIdent,
    #[error("Expecting identifier `{}`", .0)]
    ExpectNamedIdent(String),
    #[error("Expecting char `{}`", .0)]
    ExpectChar(char),
    #[error("Expecting any char of: {}", .0.iter().map(|c| format!("`{}`", c)).collect::<Vec<_>>().join(", "))]
    ExpectAnyChar(Vec<char>),
}

pub type TokenizerResult<R> = Result<R, TokenizerError>;

#[derive(Clone)]
pub struct Tokenizer<'a> {
    lexer: Lexer<'a>,
    next_token: Option<TokenWithLocation>,
    last_token_loc: Option<Loc>,
}

impl<'a> Tokenizer<'a> {
    pub fn new(input: &'a str, comment_style: ParserLanguage) -> Tokenizer<'a> {
        Tokenizer {
            lexer: Lexer::new(input, comment_style),
            next_token: None,
            last_token_loc: None,
        }
    }

    pub fn loc(&self) -> Loc {
        // After lookahead return the location of the next token
        self.next_token
            .as_ref()
            .map(|t| t.loc.clone())
            // After token consumed return the location of that token
            .or(self.last_token_loc.clone())
            // Otherwise return the position of lexer
            .unwrap_or(self.lexer.loc)
    }

    pub fn lookahead_loc(&mut self) -> Loc {
        drop(self.lookahead());
        // TODO: does not handle EOF properly
        self.loc()
    }

    fn lookahead(&mut self) -> TokenizerResult<Option<&Token>> {
        Ok(match self.next_token {
            Some(ref token) => Some(&token.token),
            None => {
                self.next_token = self.lexer.next_token()?;
                self.last_token_loc = self.next_token.as_ref().map(|t| t.loc.clone());
                match self.next_token {
                    Some(ref token) => Some(&token.token),
                    None => None,
                }
            }
        })
    }

    pub fn lookahead_some(&mut self) -> TokenizerResult<&Token> {
        match self.lookahead()? {
            Some(token) => Ok(token),
            None => Err(TokenizerError::UnexpectedEof),
        }
    }

    fn next(&mut self) -> TokenizerResult<Option<Token>> {
        self.lookahead()?;
        Ok(self
            .next_token
            .take()
            .map(|TokenWithLocation { token, .. }| token))
    }

    pub fn next_some(&mut self) -> TokenizerResult<Token> {
        match self.next()? {
            Some(token) => Ok(token),
            None => Err(TokenizerError::UnexpectedEof),
        }
    }

    /// Can be called only after lookahead, otherwise it's error
    pub fn advance(&mut self) -> TokenizerResult<Token> {
        self.next_token
            .take()
            .map(|TokenWithLocation { token, .. }| token)
            .ok_or(TokenizerError::InternalError)
    }

    /// No more tokens
    pub fn syntax_eof(&mut self) -> TokenizerResult<bool> {
        Ok(self.lookahead()?.is_none())
    }

    pub fn next_token_if_map<P, R>(&mut self, p: P) -> TokenizerResult<Option<R>>
    where
        P: FnOnce(&Token) -> Option<R>,
    {
        self.lookahead()?;
        let v = match self.next_token {
            Some(ref token) => match p(&token.token) {
                Some(v) => v,
                None => return Ok(None),
            },
            _ => return Ok(None),
        };
        self.next_token = None;
        Ok(Some(v))
    }

    pub fn next_token_check_map<P, R, E>(&mut self, p: P) -> Result<R, E>
    where
        P: FnOnce(&Token) -> Result<R, E>,
        E: From<TokenizerError>,
    {
        self.lookahead()?;
        let r = match self.next_token {
            Some(ref token) => p(&token.token)?,
            None => return Err(TokenizerError::UnexpectedEof.into()),
        };
        self.next_token = None;
        Ok(r)
    }

    fn next_token_if<P>(&mut self, p: P) -> TokenizerResult<Option<Token>>
    where
        P: FnOnce(&Token) -> bool,
    {
        self.next_token_if_map(|token| if p(token) { Some(token.clone()) } else { None })
    }

    pub fn next_ident_if_in(&mut self, idents: &[&str]) -> TokenizerResult<Option<String>> {
        let v = match self.lookahead()? {
            Some(&Token::Ident(ref next)) => {
                if idents.into_iter().find(|&i| i == next).is_some() {
                    next.clone()
                } else {
                    return Ok(None);
                }
            }
            _ => return Ok(None),
        };
        self.advance()?;
        Ok(Some(v))
    }

    pub fn next_ident_if_eq(&mut self, word: &str) -> TokenizerResult<bool> {
        Ok(self.next_ident_if_in(&[word])? != None)
    }

    pub fn next_ident_expect_eq(&mut self, word: &str) -> TokenizerResult<()> {
        if self.next_ident_if_eq(word)? {
            Ok(())
        } else {
            Err(TokenizerError::ExpectNamedIdent(word.to_owned()))
        }
    }

    pub fn next_ident_if_eq_error(&mut self, word: &str) -> TokenizerResult<()> {
        if self.clone().next_ident_if_eq(word)? {
            return Err(TokenizerError::IncorrectInput);
        }
        Ok(())
    }

    pub fn next_symbol_if_eq(&mut self, symbol: char) -> TokenizerResult<bool> {
        Ok(self.next_token_if(|token| match token {
            &Token::Symbol(c) if c == symbol => true,
            _ => false,
        })? != None)
    }

    pub fn next_symbol_expect_eq(&mut self, symbol: char) -> TokenizerResult<()> {
        if self.lookahead_is_symbol(symbol)? {
            self.advance()?;
            Ok(())
        } else {
            Err(TokenizerError::ExpectChar(symbol))
        }
    }

    pub fn next_symbol_expect_eq_oneof(&mut self, symbols: &[char]) -> TokenizerResult<char> {
        for symbol in symbols {
            if let Ok(()) = self.next_symbol_expect_eq(*symbol) {
                return Ok(*symbol);
            }
        }
        Err(TokenizerError::ExpectAnyChar(symbols.to_owned()))
    }

    pub fn lookahead_is_str_lit(&mut self) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(&Token::StrLit(..)) => true,
            _ => false,
        })
    }

    pub fn lookahead_is_int_lit(&mut self) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(&Token::IntLit(..)) => true,
            _ => false,
        })
    }

    pub fn lookahead_is_json_number(&mut self) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(&Token::JsonNumber(..)) => true,
            _ => false,
        })
    }

    pub fn lookahead_if_symbol(&mut self) -> TokenizerResult<Option<char>> {
        Ok(match self.lookahead()? {
            Some(&Token::Symbol(c)) => Some(c),
            _ => None,
        })
    }

    pub fn lookahead_is_symbol(&mut self, symbol: char) -> TokenizerResult<bool> {
        Ok(self.lookahead_if_symbol()? == Some(symbol))
    }

    pub fn lookahead_is_ident(&mut self, ident: &str) -> TokenizerResult<bool> {
        Ok(match self.lookahead()? {
            Some(Token::Ident(i)) => i == ident,
            _ => false,
        })
    }

    pub fn next_ident(&mut self) -> TokenizerResult<String> {
        self.next_token_check_map(|token| match token {
            &Token::Ident(ref ident) => Ok(ident.clone()),
            _ => Err(TokenizerError::ExpectIdent),
        })
    }

    pub fn next_str_lit(&mut self) -> TokenizerResult<StrLit> {
        self.next_token_check_map(|token| match token {
            &Token::StrLit(ref str_lit) => Ok(str_lit.clone()),
            _ => Err(TokenizerError::ExpectStrLit),
        })
    }

    pub fn next_int_lit(&mut self) -> TokenizerResult<u64> {
        self.next_token_check_map(|token| match token {
            &Token::IntLit(v) => Ok(v),
            _ => Err(TokenizerError::ExpectIntLit),
        })
    }

    pub fn next_float_lit(&mut self) -> TokenizerResult<f64> {
        self.next_token_check_map(|token| match token {
            &Token::FloatLit(v) => Ok(v),
            _ => Err(TokenizerError::ExpectFloatLit),
        })
    }
}

#[cfg(test)]
mod test {

    use super::*;

    fn tokenize<P, R>(input: &str, what: P) -> R
    where
        P: FnOnce(&mut Tokenizer) -> TokenizerResult<R>,
    {
        let mut tokenizer = Tokenizer::new(input, ParserLanguage::Proto);
        let r = what(&mut tokenizer).expect(&format!("parse failed at {}", tokenizer.loc()));
        let eof = tokenizer
            .syntax_eof()
            .expect(&format!("check eof failed at {}", tokenizer.loc()));
        assert!(eof, "{}", tokenizer.loc());
        r
    }

    #[test]
    fn test_ident() {
        let msg = r#"  aabb_c  "#;
        let mess = tokenize(msg, |p| p.next_ident().map(|s| s.to_owned()));
        assert_eq!("aabb_c", mess);
    }

    #[test]
    fn test_str_lit() {
        let msg = r#"  "a\nb"  "#;
        let mess = tokenize(msg, |p| p.next_str_lit());
        assert_eq!(
            StrLit {
                escaped: r#"a\nb"#.to_owned()
            },
            mess
        );
    }
}
<|endoftext|>


<commit_before>//! [PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-pushrules-scope-kind-ruleid)

use ruma_api::ruma_api;
use ruma_common::push::{Action, PushCondition};

use super::RuleKind;

ruma_api! {
    metadata: {
        description: "This endpoint allows the creation, modification and deletion of pushers for this user ID.",
        method: PUT,
        name: "set_pushrule",
        path: "/_matrix/client/r0/pushrules/:scope/:kind/:rule_id",
        rate_limited: true,
        authentication: AccessToken,
    }

    request: {
        /// The scope to set the rule in. 'global' to specify global rules.
        #[ruma_api(path)]
        pub scope: &'a str,

        /// The kind of rule
        #[ruma_api(path)]
        pub kind: RuleKind,

        /// The identifier for the rule.
        #[ruma_api(path)]
        pub rule_id: &'a str,

        /// Use 'before' with a rule_id as its value to make the new rule the next-most important
        /// rule with respect to the given user defined rule.
        #[ruma_api(query)]
        pub before: Option<&'a str>,

        /// This makes the new rule the next-less important rule relative to the given user defined
        /// rule.
        #[ruma_api(query)]
        pub after: Option<&'a str>,

        /// The actions to perform when this rule is matched.
        pub actions: Vec<Action>,

        /// The conditions that must hold true for an event in order for a rule to be applied to an
        /// event. A rule with no conditions always matches. Only applicable to underride and
        /// override rules, empty Vec otherwise.
        #[serde(default)]
        pub conditions: Vec<PushCondition>,

        /// The glob-style pattern to match against. Only applicable to content rules.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub pattern: Option<&'a str>,
    }

    #[derive(Default)]
    response: {}

    error: crate::Error
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given scope, rule kind, rule ID and actions.
    pub fn new(scope: &'a str, kind: RuleKind, rule_id: &'a str, actions: Vec<Action>) -> Self {
        Self {
            scope,
            kind,
            rule_id,
            before: None,
            after: None,
            actions,
            conditions: Vec::new(),
            pattern: None,
        }
    }
}

impl Response {
    /// Creates an empty `Response`.
    pub fn new() -> Self {
        Self
    }
}
<commit_msg>Bring set_pushrule in line with API conventions<commit_after>//! [PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-pushrules-scope-kind-ruleid)

use ruma_api::ruma_api;
use ruma_common::push::{Action, PushCondition};

use super::RuleKind;

ruma_api! {
    metadata: {
        description: "This endpoint allows the creation, modification and deletion of pushers for this user ID.",
        method: PUT,
        name: "set_pushrule",
        path: "/_matrix/client/r0/pushrules/:scope/:kind/:rule_id",
        rate_limited: true,
        authentication: AccessToken,
    }

    request: {
        /// The scope to set the rule in. 'global' to specify global rules.
        #[ruma_api(path)]
        pub scope: &'a str,

        /// The kind of rule
        #[ruma_api(path)]
        pub kind: RuleKind,

        /// The identifier for the rule.
        #[ruma_api(path)]
        pub rule_id: &'a str,

        /// Use 'before' with a rule_id as its value to make the new rule the next-most important
        /// rule with respect to the given user defined rule.
        #[ruma_api(query)]
        pub before: Option<&'a str>,

        /// This makes the new rule the next-less important rule relative to the given user defined
        /// rule.
        #[ruma_api(query)]
        pub after: Option<&'a str>,

        /// The actions to perform when this rule is matched.
        pub actions: &'a [Action],

        /// The conditions that must hold true for an event in order for a rule to be applied to an
        /// event. A rule with no conditions always matches. Only applicable to underride and
        /// override rules, empty Vec otherwise.
        #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
        pub conditions: &'a [PushCondition],

        /// The glob-style pattern to match against. Only applicable to content rules.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub pattern: Option<&'a str>,
    }

    #[derive(Default)]
    response: {}

    error: crate::Error
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given scope, rule kind, rule ID and actions.
    pub fn new(scope: &'a str, kind: RuleKind, rule_id: &'a str, actions: &'a [Action]) -> Self {
        Self {
            scope,
            kind,
            rule_id,
            before: None,
            after: None,
            actions,
            conditions: &[],
            pattern: None,
        }
    }
}

impl Response {
    /// Creates an empty `Response`.
    pub fn new() -> Self {
        Self
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool
}
<commit_msg>Example of struct initialization and field access<commit_after>fn main() {
    let mut user_instance = User {
        username: String::from("userrrr"),
        email: String::from("mail@mail.com"),
        sign_in_count: 0,
        active: true
    };

    user_instance.sign_in_count = 1;

    println!("User sign in count: {}", user_instance.sign_in_count);
}

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool
}
<|endoftext|>


<commit_before>use specs::prelude::*;
use engine::components::{FactionId, Hp, UnitTypeTag};
use engine::resources::{ReplayMode, Reward, RtsState, Skip, SkyCollisionWorld, Terminal,
                        UnitTypeMap, STATE_SCALE, STATE_SIZE};
use ndarray::Array3;

#[derive(SystemData)]
pub struct StateBuildSystemData<'a> {
    hp: ReadStorage<'a, Hp>,
    faction: ReadStorage<'a, FactionId>,
    collision_sys: Fetch<'a, SkyCollisionWorld>,
    tag: ReadStorage<'a, UnitTypeTag>,
    unit_types: Fetch<'a, UnitTypeMap>,
    terminal: Fetch<'a, Terminal>,
    skip: Fetch<'a, Skip>,
    replay_mode: Fetch<'a, ReplayMode>,

    state: FetchMut<'a, RtsState>,
    reward: FetchMut<'a, Reward>,
}

pub struct StateBuildSystem {
    state_cache: Array3<f64>,
}

impl StateBuildSystem {
    pub fn new() -> Self {
        StateBuildSystem {
            state_cache: Array3::zeros([STATE_SIZE, STATE_SIZE, 4]),
        }
    }
}

impl<'a> System<'a> for StateBuildSystem {
    type SystemData = StateBuildSystemData<'a>;

    fn run(&mut self, mut sys_data: Self::SystemData) {
        use nalgebra::Point2;
        use ncollide::world::CollisionGroups;
        use engine::resources::COLLISION_SCALE;
        use std::mem;

        if sys_data.skip.0 || sys_data.replay_mode.0 {
            return;
        }

        let c_world = &*sys_data.collision_sys;

        let mut c_group = CollisionGroups::new();
        for i in 0..15 {
            c_group.modify_membership(i, true);
        }

        /* This is probably speed uppable using the Dead and Moved marker components */
        for i in 0..STATE_SIZE {
            for j in 0..STATE_SIZE {
                let pt = Point2::new(
                    ((i * STATE_SCALE) as f64) / COLLISION_SCALE,
                    ((j * STATE_SCALE) as f64) / COLLISION_SCALE,
                );
                let intersection = c_world.interferences_with_point(&pt, &c_group);

                if let Some(collider) = intersection.filter(|v| !v.data().detector).next() {
                    let entity = collider.data().e;
                    // Need to offset by 1 because the default is 0
                    self.state_cache[(i, j, 0)] = (entity.id() + 1) as f64;
                    self.state_cache[(i, j, 1)] = sys_data.hp.get(entity).unwrap().curr_hp as f64;

                    let u_type = sys_data
                        .unit_types
                        .typ_ids
                        .get(&sys_data.tag.get(entity).unwrap().0)
                        .unwrap();
                    self.state_cache[(i, j, 2)] = (*u_type + 1) as f64;
                    self.state_cache[(i, j, 3)] =
                        (sys_data.faction.get(entity).unwrap().0 + 1) as f64;
                } else {
                    for k in 0..4 {
                        self.state_cache[(i, j, k)] = 0.0;
                    }
                }
            }
        }

        let old_state = mem::replace(&mut sys_data.state.0.features, vec![]);
        let new_cache = Array3::from_shape_vec([STATE_SIZE, STATE_SIZE, 4], old_state).unwrap();

        sys_data.state.0.features = mem::replace(&mut self.state_cache, new_cache).into_raw_vec();

        mem::swap(&mut sys_data.state.0.typed_reward, &mut sys_data.reward.0);
        sys_data.reward.0.clear();
        sys_data.state.0.terminal = sys_data.terminal.0;

        sys_data.state.0.reward = Some(
            sys_data
                .state
                .0
                .typed_reward
                .values()
                .fold(0.0, |acc, v| acc + v),
        );
    }
}
<commit_msg>Replay communication fix<commit_after>use specs::prelude::*;
use engine::components::{FactionId, Hp, UnitTypeTag};
use engine::resources::{ReplayMode, Reward, RtsState, Skip, SkyCollisionWorld, Terminal,
                        UnitTypeMap, STATE_SCALE, STATE_SIZE};
use ndarray::Array3;

#[derive(SystemData)]
pub struct StateBuildSystemData<'a> {
    hp: ReadStorage<'a, Hp>,
    faction: ReadStorage<'a, FactionId>,
    collision_sys: Fetch<'a, SkyCollisionWorld>,
    tag: ReadStorage<'a, UnitTypeTag>,
    unit_types: Fetch<'a, UnitTypeMap>,
    terminal: Fetch<'a, Terminal>,
    skip: Fetch<'a, Skip>,
    replay_mode: Fetch<'a, ReplayMode>,

    state: FetchMut<'a, RtsState>,
    reward: FetchMut<'a, Reward>,
}

pub struct StateBuildSystem {
    state_cache: Array3<f64>,
}

impl StateBuildSystem {
    pub fn new() -> Self {
        StateBuildSystem {
            state_cache: Array3::zeros([STATE_SIZE, STATE_SIZE, 4]),
        }
    }
}

impl<'a> System<'a> for StateBuildSystem {
    type SystemData = StateBuildSystemData<'a>;

    fn run(&mut self, mut sys_data: Self::SystemData) {
        use nalgebra::Point2;
        use ncollide::world::CollisionGroups;
        use engine::resources::COLLISION_SCALE;
        use std::mem;

        if sys_data.replay_mode.0 {
            sys_data.reward.0.clear();
        }

        if sys_data.skip.0 || sys_data.replay_mode.0 {
            return;
        }

        let c_world = &*sys_data.collision_sys;

        let mut c_group = CollisionGroups::new();
        for i in 0..15 {
            c_group.modify_membership(i, true);
        }

        /* This is probably speed uppable using the Dead and Moved marker components */
        for i in 0..STATE_SIZE {
            for j in 0..STATE_SIZE {
                let pt = Point2::new(
                    ((i * STATE_SCALE) as f64) / COLLISION_SCALE,
                    ((j * STATE_SCALE) as f64) / COLLISION_SCALE,
                );
                let intersection = c_world.interferences_with_point(&pt, &c_group);

                if let Some(collider) = intersection.filter(|v| !v.data().detector).next() {
                    let entity = collider.data().e;
                    // Need to offset by 1 because the default is 0
                    self.state_cache[(i, j, 0)] = (entity.id() + 1) as f64;
                    self.state_cache[(i, j, 1)] = sys_data.hp.get(entity).unwrap().curr_hp as f64;

                    let u_type = sys_data
                        .unit_types
                        .typ_ids
                        .get(&sys_data.tag.get(entity).unwrap().0)
                        .unwrap();
                    self.state_cache[(i, j, 2)] = (*u_type + 1) as f64;
                    self.state_cache[(i, j, 3)] =
                        (sys_data.faction.get(entity).unwrap().0 + 1) as f64;
                } else {
                    for k in 0..4 {
                        self.state_cache[(i, j, k)] = 0.0;
                    }
                }
            }
        }

        let old_state = mem::replace(&mut sys_data.state.0.features, vec![]);
        let new_cache = Array3::from_shape_vec([STATE_SIZE, STATE_SIZE, 4], old_state).unwrap();

        sys_data.state.0.features = mem::replace(&mut self.state_cache, new_cache).into_raw_vec();

        mem::swap(&mut sys_data.state.0.typed_reward, &mut sys_data.reward.0);
        sys_data.reward.0.clear();
        sys_data.state.0.terminal = sys_data.terminal.0;

        sys_data.state.0.reward = Some(
            sys_data
                .state
                .0
                .typed_reward
                .values()
                .fold(0.0, |acc, v| acc + v),
        );
    }
}
<|endoftext|>


<commit_before>//! Global descriptor table

use core::mem;
use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::{self, SegmentSelector};
use x86::task::{self, TaskStateSegment};

pub const GDT_NULL: usize = 0;
pub const GDT_KERNEL_CODE: usize = 1;
pub const GDT_KERNEL_DATA: usize = 2;
pub const GDT_KERNEL_TLS: usize = 3;
pub const GDT_USER_CODE: usize = 4;
pub const GDT_USER_DATA: usize = 5;
pub const GDT_USER_TLS: usize = 6;
pub const GDT_TSS: usize = 7;
pub const GDT_TSS_HIGH: usize = 8;

pub const GDT_A_PRESENT: u8 = 1 << 7;
pub const GDT_A_RING_0: u8 = 0 << 5;
pub const GDT_A_RING_1: u8 = 1 << 5;
pub const GDT_A_RING_2: u8 = 2 << 5;
pub const GDT_A_RING_3: u8 = 3 << 5;
pub const GDT_A_SYSTEM: u8 = 1 << 4;
pub const GDT_A_EXECUTABLE: u8 = 1 << 3;
pub const GDT_A_CONFORMING: u8 = 1 << 2;
pub const GDT_A_PRIVILEGE: u8 = 1 << 1;
pub const GDT_A_DIRTY: u8 = 1;

pub const GDT_A_TSS_AVAIL: u8 = 0x9;
pub const GDT_A_TSS_BUSY: u8 = 0xB;

pub const GDT_F_PAGE_SIZE: u8 = 1 << 7;
pub const GDT_F_PROTECTED_MODE: u8 = 1 << 6;
pub const GDT_F_LONG_MODE: u8 = 1 << 5;

static mut INIT_GDTR: DescriptorTablePointer = DescriptorTablePointer {
    limit: 0,
    base: 0
};

static mut INIT_GDT: [GdtEntry; 4] = [
    // Null
    GdtEntry::new(0, 0, 0, 0),
    // Kernel code
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel data
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel TLS
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE)
];

#[thread_local]
pub static mut GDTR: DescriptorTablePointer = DescriptorTablePointer {
    limit: 0,
    base: 0
};

#[thread_local]
pub static mut GDT: [GdtEntry; 9] = [
    // Null
    GdtEntry::new(0, 0, 0, 0),
    // Kernel code
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel data
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel TLS
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // User code
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // User data
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    //TODO: User TLS
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // TSS
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0),
    // TSS must be 16 bytes long, twice the normal size
    GdtEntry::new(0, 0, 0, 0),
];

#[thread_local]
pub static mut TSS: TaskStateSegment = TaskStateSegment {
    reserved: 0,
    rsp: [0; 3],
    reserved2: 0,
    ist: [0; 7],
    reserved3: 0,
    reserved4: 0,
    iomap_base: 0xFFFF
};

/// Initialize GDT
pub unsafe fn init(tcb_offset: usize, stack_offset: usize) {
    // Setup the initial GDT with TLS, so we can setup the TLS GDT (a little confusing)
    // This means that each CPU will have its own GDT, but we only need to define it once as a thread local
    INIT_GDTR.limit = (INIT_GDT.len() * mem::size_of::<GdtEntry>() - 1) as u16;
    INIT_GDTR.base = INIT_GDT.as_ptr() as u64;

    // Set the TLS segment to the offset of the Thread Control Block
    INIT_GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32);

    // Load the initial GDT, before we have access to thread locals
    dtables::lgdt(&INIT_GDTR);

    // Load the segment descriptors
    segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16));
    segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16));
    segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16));

    // Now that we have access to thread locals, setup the AP's individual GDT
    GDTR.limit = (GDT.len() * mem::size_of::<GdtEntry>() - 1) as u16;
    GDTR.base = GDT.as_ptr() as u64;

    // Set the TLS segment to the offset of the Thread Control Block
    GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32);

    // We can now access our TSS, which is a thread local
    GDT[GDT_TSS].set_offset(&TSS as *const _ as u32);
    GDT[GDT_TSS].set_limit(mem::size_of::<TaskStateSegment>() as u32);

    // Set the stack pointer when coming back from userspace
    TSS.rsp[0] = stack_offset as u64;

    // Load the new GDT, which is correctly located in thread local storage
    dtables::lgdt(&GDTR);

    // Reload the segment descriptors
    segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16));
    segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16));
    segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16));

    // Load the task register
    task::load_ltr(SegmentSelector::new(GDT_TSS as u16));
}

#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct GdtEntry {
    pub limitl: u16,
    pub offsetl: u16,
    pub offsetm: u8,
    pub access: u8,
    pub flags_limith: u8,
    pub offseth: u8
}

impl GdtEntry {
    pub const fn new(offset: u32, limit: u32, access: u8, flags: u8) -> Self {
        GdtEntry {
            limitl: limit as u16,
            offsetl: offset as u16,
            offsetm: (offset >> 16) as u8,
            access: access,
            flags_limith: flags & 0xF0 | ((limit >> 16) as u8) & 0x0F,
            offseth: (offset >> 24) as u8
        }
    }

    pub fn set_offset(&mut self, offset: u32) {
        self.offsetl = offset as u16;
        self.offsetm = (offset >> 16) as u8;
        self.offseth = (offset >> 24) as u8;
    }

    pub fn set_limit(&mut self, limit: u32) {
        self.limitl = limit as u16;
        self.flags_limith = self.flags_limith & 0xF0 | ((limit >> 16) as u8) & 0x0F;
    }
}
<commit_msg>Remove user TLS<commit_after>//! Global descriptor table

use core::mem;
use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::{self, SegmentSelector};
use x86::task::{self, TaskStateSegment};

pub const GDT_NULL: usize = 0;
pub const GDT_KERNEL_CODE: usize = 1;
pub const GDT_KERNEL_DATA: usize = 2;
pub const GDT_KERNEL_TLS: usize = 3;
pub const GDT_USER_CODE: usize = 4;
pub const GDT_USER_DATA: usize = 5;
pub const GDT_TSS: usize = 6;
pub const GDT_TSS_HIGH: usize = 7;

pub const GDT_A_PRESENT: u8 = 1 << 7;
pub const GDT_A_RING_0: u8 = 0 << 5;
pub const GDT_A_RING_1: u8 = 1 << 5;
pub const GDT_A_RING_2: u8 = 2 << 5;
pub const GDT_A_RING_3: u8 = 3 << 5;
pub const GDT_A_SYSTEM: u8 = 1 << 4;
pub const GDT_A_EXECUTABLE: u8 = 1 << 3;
pub const GDT_A_CONFORMING: u8 = 1 << 2;
pub const GDT_A_PRIVILEGE: u8 = 1 << 1;
pub const GDT_A_DIRTY: u8 = 1;

pub const GDT_A_TSS_AVAIL: u8 = 0x9;
pub const GDT_A_TSS_BUSY: u8 = 0xB;

pub const GDT_F_PAGE_SIZE: u8 = 1 << 7;
pub const GDT_F_PROTECTED_MODE: u8 = 1 << 6;
pub const GDT_F_LONG_MODE: u8 = 1 << 5;

static mut INIT_GDTR: DescriptorTablePointer = DescriptorTablePointer {
    limit: 0,
    base: 0
};

static mut INIT_GDT: [GdtEntry; 4] = [
    // Null
    GdtEntry::new(0, 0, 0, 0),
    // Kernel code
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel data
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel TLS
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE)
];

#[thread_local]
pub static mut GDTR: DescriptorTablePointer = DescriptorTablePointer {
    limit: 0,
    base: 0
};

#[thread_local]
pub static mut GDT: [GdtEntry; 8] = [
    // Null
    GdtEntry::new(0, 0, 0, 0),
    // Kernel code
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel data
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // Kernel TLS
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // User code
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // User data
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
    // TSS
    GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0),
    // TSS must be 16 bytes long, twice the normal size
    GdtEntry::new(0, 0, 0, 0),
];

#[thread_local]
pub static mut TSS: TaskStateSegment = TaskStateSegment {
    reserved: 0,
    rsp: [0; 3],
    reserved2: 0,
    ist: [0; 7],
    reserved3: 0,
    reserved4: 0,
    iomap_base: 0xFFFF
};

/// Initialize GDT
pub unsafe fn init(tcb_offset: usize, stack_offset: usize) {
    // Setup the initial GDT with TLS, so we can setup the TLS GDT (a little confusing)
    // This means that each CPU will have its own GDT, but we only need to define it once as a thread local
    INIT_GDTR.limit = (INIT_GDT.len() * mem::size_of::<GdtEntry>() - 1) as u16;
    INIT_GDTR.base = INIT_GDT.as_ptr() as u64;

    // Set the TLS segment to the offset of the Thread Control Block
    INIT_GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32);

    // Load the initial GDT, before we have access to thread locals
    dtables::lgdt(&INIT_GDTR);

    // Load the segment descriptors
    segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16));
    segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16));
    segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16));

    // Now that we have access to thread locals, setup the AP's individual GDT
    GDTR.limit = (GDT.len() * mem::size_of::<GdtEntry>() - 1) as u16;
    GDTR.base = GDT.as_ptr() as u64;

    // Set the TLS segment to the offset of the Thread Control Block
    GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32);

    // We can now access our TSS, which is a thread local
    GDT[GDT_TSS].set_offset(&TSS as *const _ as u32);
    GDT[GDT_TSS].set_limit(mem::size_of::<TaskStateSegment>() as u32);

    // Set the stack pointer when coming back from userspace
    TSS.rsp[0] = stack_offset as u64;

    // Load the new GDT, which is correctly located in thread local storage
    dtables::lgdt(&GDTR);

    // Reload the segment descriptors
    segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16));
    segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16));
    segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
    segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16));

    // Load the task register
    task::load_ltr(SegmentSelector::new(GDT_TSS as u16));
}

#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct GdtEntry {
    pub limitl: u16,
    pub offsetl: u16,
    pub offsetm: u8,
    pub access: u8,
    pub flags_limith: u8,
    pub offseth: u8
}

impl GdtEntry {
    pub const fn new(offset: u32, limit: u32, access: u8, flags: u8) -> Self {
        GdtEntry {
            limitl: limit as u16,
            offsetl: offset as u16,
            offsetm: (offset >> 16) as u8,
            access: access,
            flags_limith: flags & 0xF0 | ((limit >> 16) as u8) & 0x0F,
            offseth: (offset >> 24) as u8
        }
    }

    pub fn set_offset(&mut self, offset: u32) {
        self.offsetl = offset as u16;
        self.offsetm = (offset >> 16) as u8;
        self.offseth = (offset >> 24) as u8;
    }

    pub fn set_limit(&mut self, limit: u32) {
        self.limitl = limit as u16;
        self.flags_limith = self.flags_limith & 0xF0 | ((limit >> 16) as u8) & 0x0F;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

// FIXME Remove after 1.0
#![feature(slice_extras)]

extern crate pnet;
extern crate time;

use pnet::datalink::{datalink_channel};
use pnet::datalink::DataLinkChannelType::Layer2;
use pnet::util::{NetworkInterface, get_network_interfaces};

use std::env;

fn main() {
    let iface_name = env::args().nth(1).unwrap();
    let interface_names_match = |iface: &NetworkInterface| iface.name == iface_name;

    // Find the network interface with the provided name
    let interfaces = get_network_interfaces();
    let interface = interfaces.into_iter()
                              .filter(interface_names_match)
                              .next()
                              .unwrap();

    // Create a channel to receive on
    let (_, mut rx) = match datalink_channel(&interface, 0, 4096, Layer2) {
        Ok((tx, rx)) => (tx, rx),
        Err(e) => panic!("rs_benchmark: unable to create channel: {}", e)
    };

    let mut i = 0usize;
    let mut timestamps = Vec::with_capacity(201);
    timestamps.push(time::precise_time_ns() / 1_000);

    let mut iter = rx.iter();
    loop {
        match iter.next() {
            Ok(_) => {
                i += 1;
                if i == 1_000_000 {
                    timestamps.push(time::precise_time_ns() / 1_000);
                    if timestamps.len() == 201 {
                        break;
                    }
                    i = 0;
                }
            },
            Err(e) => {
                println!("rs_benchmark: unable to receive packet: {}", e);
            }
        }
    }

    // We received 1_000_000 packets in ((b - a) * 1_000_000) seconds.
    for (a, b) in timestamps.iter().zip(timestamps.tail().iter()) {
        println!("{}", *b - *a);
    }
}

<commit_msg>Fixed bench on nightly<commit_after>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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 pnet;
extern crate time;

use pnet::datalink::{datalink_channel};
use pnet::datalink::DataLinkChannelType::Layer2;
use pnet::util::{NetworkInterface, get_network_interfaces};

use std::env;

fn main() {
    let iface_name = env::args().nth(1).unwrap();
    let interface_names_match = |iface: &NetworkInterface| iface.name == iface_name;

    // Find the network interface with the provided name
    let interfaces = get_network_interfaces();
    let interface = interfaces.into_iter()
                              .filter(interface_names_match)
                              .next()
                              .unwrap();

    // Create a channel to receive on
    let (_, mut rx) = match datalink_channel(&interface, 0, 4096, Layer2) {
        Ok((tx, rx)) => (tx, rx),
        Err(e) => panic!("rs_benchmark: unable to create channel: {}", e)
    };

    let mut i = 0usize;
    let mut timestamps = Vec::with_capacity(201);
    timestamps.push(time::precise_time_ns() / 1_000);

    let mut iter = rx.iter();
    loop {
        match iter.next() {
            Ok(_) => {
                i += 1;
                if i == 1_000_000 {
                    timestamps.push(time::precise_time_ns() / 1_000);
                    if timestamps.len() == 201 {
                        break;
                    }
                    i = 0;
                }
            },
            Err(e) => {
                println!("rs_benchmark: unable to receive packet: {}", e);
            }
        }
    }

    // We received 1_000_000 packets in ((b - a) * 1_000_000) seconds.
    for (a, b) in timestamps.iter().zip(timestamps.iter().skip(1)) {
        println!("{}", *b - *a);
    }
}

<|endoftext|>


<commit_before>#![feature(test)]
extern crate adapton;
extern crate test;
use self::test::Bencher;
use adapton::trie::*;
use adapton::engine::*;

// The code that we want to compare/measure under naive versus DCG engines:
fn doit(v: Vec<usize>, t: Trie<usize>) -> Trie<usize> {
    v.into_iter().fold(t, |acc, i| {
        let t = Trie::art(cell(name_of_usize(i), acc));
        let t = Trie::name(name_of_usize(i), t);
        Trie::extend(name_of_usize(i), t, i)
    })
}

fn bench_naive_add_dups() {
    init_naive();
    let mut naive_input: Trie<usize> = SetIntro::empty();
    let mut v = Vec::new();

    let mut ones = vec![1;100];
    let mut twos = vec![2;100];
    let mut threes = vec![3;100];
    twos.append(&mut threes);
    ones.append(&mut twos);
    for i in ones.iter() {
        v.push(*i);
        naive_input = doit(v.clone(), naive_input.clone())
    }
}

fn bench_dcg_add_dups() {
    init_dcg();
    let mut dcg_input: Trie<usize> = SetIntro::empty();
    let mut v = Vec::new();

    let mut ones = vec![1;100];
    let mut twos = vec![2;100];
    let mut threes = vec![3;100];
    twos.append(&mut threes);
    ones.append(&mut twos);
    for i in ones.iter() {
        v.push(*i);
        dcg_input = doit(v.clone(), dcg_input.clone())
    }
}

#[bench]
fn benchmark_naive_trie(b: &mut Bencher) {
    b.iter(|| bench_naive_add_dups())
}

#[bench]
fn benchmark_dcg_trie(b: &mut Bencher) {
    b.iter(|| bench_dcg_add_dups())
}
<commit_msg>Add fold sum over trie benchmark. Currently overflows stack<commit_after>#![feature(test)]
extern crate adapton;
extern crate test;
use self::test::Bencher;
use adapton::trie::*;
use adapton::engine::*;
use std::rc::Rc;

mod add_dups {
    use super::*;

    // The code that we want to compare/measure under naive versus DCG engines:
    fn doit(v: Vec<usize>, t: Trie<usize>) -> Trie<usize> {
        v.into_iter().fold(t, |acc, i| {
            let t = Trie::art(cell(name_of_usize(i), acc));
            let t = Trie::name(name_of_usize(i), t);
            Trie::extend(name_unit(), t, i)
        })
    }

    fn bench_naive_add_dups() {
        init_naive();
        let mut naive_input: Trie<usize> = SetIntro::empty();
        let mut v = Vec::new();

        let mut ones = vec![1;5];
        let mut twos = vec![2;5];
        let mut threes = vec![3;5];
        twos.append(&mut threes);
        ones.append(&mut twos);
        for i in ones.iter() {
            v.push(*i);
            naive_input = doit(v.clone(), naive_input.clone());
            let _ = SetElim::mem(&naive_input, i);
        }
    }

    fn bench_dcg_add_dups() {
        init_dcg();
        let mut dcg_input: Trie<usize> = SetIntro::empty();
        let mut v = Vec::new();

        let mut ones = vec![1;5];
        let mut twos = vec![2;5];
        let mut threes = vec![3;5];
        twos.append(&mut threes);
        ones.append(&mut twos);
        for i in ones.iter() {
            v.push(*i);
            dcg_input = doit(v.clone(), dcg_input.clone());
            let _ = SetElim::mem(&dcg_input, i);
        }
    }

    #[bench]
    fn benchmark_naive_trie(b: &mut Bencher) {
        b.iter(|| bench_naive_add_dups())
    }

    #[bench]
    fn benchmark_dcg_trie(b: &mut Bencher) {
        b.iter(|| bench_dcg_add_dups())
    }
}

mod sum_fold {
    use super::*;

    // The code that we want to compare/measure under naive versus DCG engines:
    fn doit(t: Trie<usize>) -> usize {
        SetElim::fold(t, 0, Rc::new(|i, acc| i + acc))
    }

    fn push_input(i: usize, t: Trie<usize>) -> Trie<usize> {
        // let t = Trie::art(cell(name_of_usize(i), t));
        // let t = Trie::name(name_of_usize(i), t);
        Trie::extend(name_unit(), t, i)
    }

    fn bench_naive_fold() {
        init_naive();
        let mut naive_input: Trie<usize> = SetIntro::empty();

        for i in vec![1,2,3,4,5,6,7,8,9].iter() {
            naive_input = push_input(*i, naive_input);
            let _ = doit(naive_input.clone());
        }
    }

    fn bench_dcg_fold() {
        init_dcg();
        let mut dcg_input: Trie<usize> = SetIntro::empty();

        for i in vec![1,2,3,4,5,6,7,8,9].iter() {
            dcg_input = push_input(*i, dcg_input);
            let _ = doit(dcg_input.clone());
        }
    }

    #[bench]
    fn benchmark_naive_trie(b: &mut Bencher) {
        b.iter(|| bench_naive_fold())
    }

    #[bench]
    fn benchmark_dcg_trie(b: &mut Bencher) {
        b.iter(|| bench_dcg_fold())
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#[feature(globs)];
#[feature(macro_rules)];

#[link(name = "capnproto-rust-benchmark", vers = "alpha", author = "dwrensha")];

#[crate_type = "bin"];

extern mod capnprust;

pub mod common;

pub mod carsales_capnp;
pub mod carsales;

pub mod catrank_capnp;
pub mod catrank;

pub mod eval_capnp;
pub mod eval;

macro_rules! passByObject(
    ( $testcase:ident, $iters:expr ) => ({
            let mut rng = ~common::FastRand::new();
            for _ in range(0, $iters) {
                let messageReq = capnprust::message::MessageBuilder::new_default();
                let messageRes = capnprust::message::MessageBuilder::new_default();

                let request = messageReq.initRoot::<$testcase::RequestBuilder>();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                let expected = $testcase::setupRequest(rng, request);

                do request.asReader |requestReader| {
                    $testcase::handleRequest(requestReader, response);
                }

                do response.asReader |responseReader| {
                    if (! $testcase::checkResponse(responseReader, expected)) {
                        println("Incorrect response.");
                    }
                }

                messageReq.release();
                messageRes.release();
            }
        });
    )

macro_rules! doTestcase(
    ( $testcase:ident, $mode:expr, $reuse:expr, $compression:expr, $iters:expr ) => ({
            match $mode {
                ~"object" => passByObject!($testcase, $iters),
                s => fail!("unrecognized mode: {}", s)
            }
        });
    )

pub fn main () {

    let args = std::os::args();

    if (args.len() != 6) {
        println!("USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT", args[0]);
        return;
    }

    let iters = match from_str::<u64>(args[5]) {
        Some (n) => n,
        None => {
            println!("Could not parse a u64 from: {}", args[5]);
            return;
        }
    };

/* TODO use std::run
    unsafe {
        let child = funcs::posix88::unistd::fork();
        if (child == 0 ) {
            printfln!("%s", "Hello world. I am the child and client.");
        } else {
            printfln!("%s", "Hello world. I am the parent and server.");
        }
    }
*/

    match args[1] {
        ~"carsales" => doTestcase!(carsales, args[2], args[3], args[4], iters),
        ~"catrank" => doTestcase!(catrank, args[2], args[3], args[4], iters),
        ~"eval" => doTestcase!(eval, args[2], args[3], args[4], iters),
        s => fail!("unrecognized test case: {}", s)
    }

}
<commit_msg>stub for passByBytes<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#[feature(globs)];
#[feature(macro_rules)];

#[link(name = "capnproto-rust-benchmark", vers = "alpha", author = "dwrensha")];

#[crate_type = "bin"];

extern mod capnprust;

pub mod common;

pub mod carsales_capnp;
pub mod carsales;

pub mod catrank_capnp;
pub mod catrank;

pub mod eval_capnp;
pub mod eval;

macro_rules! passByObject(
    ( $testcase:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let messageReq = capnprust::message::MessageBuilder::new_default();
                let messageRes = capnprust::message::MessageBuilder::new_default();

                let request = messageReq.initRoot::<$testcase::RequestBuilder>();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                let expected = $testcase::setupRequest(&mut rng, request);

                do request.asReader |requestReader| {
                    $testcase::handleRequest(requestReader, response);
                }

                do response.asReader |responseReader| {
                    if (! $testcase::checkResponse(responseReader, expected)) {
                        println("Incorrect response.");
                    }
                }

                messageReq.release();
                messageRes.release();
            }
        });
    )

macro_rules! passByBytes(
    ( $testcase:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let messageReq = capnprust::message::MessageBuilder::new_default();
                let messageRes = capnprust::message::MessageBuilder::new_default();

                let request = messageReq.initRoot::<$testcase::RequestBuilder>();
                let _response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                let _expected = $testcase::setupRequest(&mut rng, request);
                fail!("unimplemented");
            }
        });
    )

macro_rules! passByPipe(
    ( $testcase:ident, $iters:expr) => ({
            fail!("unimplemented");
        });
    )

macro_rules! doTestcase(
    ( $testcase:ident, $mode:expr, $reuse:expr, $compression:expr, $iters:expr ) => ({
            match $mode {
                ~"object" => passByObject!($testcase, $iters),
                ~"bytes" => passByBytes!($testcase, $iters),
                s => fail!("unrecognized mode: {}", s)
            }
        });
    )

pub fn main () {

    let args = std::os::args();

    if (args.len() != 6) {
        println!("USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT", args[0]);
        return;
    }

    let iters = match from_str::<u64>(args[5]) {
        Some (n) => n,
        None => {
            println!("Could not parse a u64 from: {}", args[5]);
            return;
        }
    };

    match args[1] {
        ~"carsales" => doTestcase!(carsales, args[2], args[3], args[4], iters),
        ~"catrank" => doTestcase!(catrank, args[2], args[3], args[4], iters),
        ~"eval" => doTestcase!(eval, args[2], args[3], args[4], iters),
        s => fail!("unrecognized test case: {}", s)
    }
}
<|endoftext|>