<commit_before>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

#![experimental]

use registry::{Registry, Ns};
use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::ptr::P;

pub struct GlobalGenerator;

impl super::Generator for GlobalGenerator {
    fn write(&self, ecx: &ExtCtxt, registry: &Registry, ns: Ns) -> Vec<P<ast::Item>> {
        let mut result = Vec::new();
        result.push(write_header(ecx));
        result.push(write_type_aliases(ecx, &ns));
        result.push_all_move(write_enums(ecx, registry));
        result.push_all_move(write_fns(ecx, registry));
        result.push_all_move(write_fnptr_struct_def(ecx));
        result.push(write_ptrs(ecx, registry));
        result.push_all_move(write_fn_mods(ecx, registry, &ns));
        result.push(write_failing_fns(ecx, registry));
        result.push(write_load_fn(ecx, registry));
        result
    }
}

fn write_header(ecx: &ExtCtxt) -> P<ast::Item> {
    (quote_item!(ecx,
        mod __gl_imports {
            extern crate libc;
            pub use std::mem;
        }
    )).unwrap()
}

fn write_type_aliases(ecx: &ExtCtxt, ns: &Ns) -> P<ast::Item> {
    let aliases = super::gen_type_aliases(ecx, ns);

    (quote_item!(ecx,
        #[stable]
        pub mod types {
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]
            #![allow(dead_code)]

            $aliases
        }
    )).unwrap()
}

fn write_enums(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.enum_iter().map(|e| {
        super::gen_enum_item(ecx, e, "types::")
    }).collect()
}

fn write_fns(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        use syntax::ext::quote::rt::ToSource;

        ecx.parse_item(if c.is_safe {
            format!(
                "#[allow(non_snake_case)] #[allow(unused_variable)] #[allow(dead_code)]
                #[inline] #[unstable] pub fn {name}({params}) -> {return_suffix} {{ \
                    unsafe {{ \
                        __gl_imports::mem::transmute::<_, extern \"system\" fn({types}) -> {return_suffix}>\
                            (storage::{name}.f)({idents}) \
                    }} \
                }}",
                name = c.proto.ident,
                params = super::gen_parameters(ecx, c).move_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
                types = super::gen_parameters(ecx, c).move_iter().map(|p| p.ty.to_source()).collect::<Vec<String>>().connect(", "),
                return_suffix = super::gen_return_type(ecx, c).to_source(),
                idents = super::gen_parameters(ecx, c).move_iter().map(|p| p.pat.to_source()).collect::<Vec<String>>().connect(", "),
            )
        } else {
            format!(
                "#[allow(non_snake_case)] #[allow(unused_variable)] #[allow(dead_code)]
                #[inline] #[unstable] pub unsafe fn {name}({typed_params}) -> {return_suffix} {{ \
                    __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\
                        (storage::{name}.f)({idents}) \
                }}",
                name = c.proto.ident,
                typed_params = super::gen_parameters(ecx, c).move_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
                return_suffix = super::gen_return_type(ecx, c).to_source(),
                idents = super::gen_parameters(ecx, c).move_iter().map(|p| p.pat.to_source()).collect::<Vec<String>>().connect(", "),
            )
        })
    }).collect()
}

fn write_fnptr_struct_def(ecx: &ExtCtxt) -> Vec<P<ast::Item>> {
    vec![
        (quote_item!(ecx,
            pub struct FnPtr {
                f: *const __gl_imports::libc::c_void,
                is_loaded: bool,
            }
        )).unwrap(),

        (quote_item!(ecx,
            impl FnPtr {
                pub fn new(ptr: *const __gl_imports::libc::c_void, failing_fn: *const __gl_imports::libc::c_void) -> FnPtr {
                    if ptr.is_null() {
                        FnPtr { f: failing_fn, is_loaded: false }
                    } else {
                        FnPtr { f: ptr, is_loaded: true }
                    }
                }
            }
        )).unwrap()
    ]
}

fn write_ptrs(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    let storages = registry.cmd_iter().map(|c| {
        let name = ecx.ident_of(c.proto.ident.as_slice());

        (quote_item!(ecx,
            pub static mut $name: FnPtr = FnPtr {
                f: failing::$name as *const libc::c_void,
                is_loaded: false
            };
        )).unwrap()
    }).collect::<Vec<P<ast::Item>>>();

    (quote_item!(ecx,
        mod storage {
            #![allow(non_snake_case)]
            use super::__gl_imports::libc;
            use super::failing;
            use super::FnPtr;

            $storages
        }
    )).unwrap()
}

fn write_fn_mods(ecx: &ExtCtxt, registry: &Registry, ns: &Ns) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        let fnname = ecx.ident_of(c.proto.ident.as_slice());
        let symbol = super::gen_symbol_name(ns, c);
        let symbol = symbol.as_slice();

        (quote_item!(ecx,
            #[unstable]
            #[allow(non_snake_case)]
            pub mod $fnname {
                use super::{failing, storage};
                use super::FnPtr;

                #[inline]
                #[allow(dead_code)]
                pub fn is_loaded() -> bool {
                    unsafe { storage::$fnname.is_loaded }
                }

                #[allow(dead_code)]
                pub fn load_with(loadfn: |symbol: &str| -> *const super::__gl_imports::libc::c_void) {
                    unsafe {
                        storage::$fnname = FnPtr::new(loadfn($symbol),
                            failing::$fnname as *const super::__gl_imports::libc::c_void)
                    }
                }
            }
        )).unwrap()
    }).collect()

    // TODO: this is a reliquate from an old code, I have no idea what it does
    // for c in self.registry.cmd_iter() {
    //     self.write_line(format!(
    //         "pub mod {name} {{ \
    //             #[inline] \
    //             pub fn is_loaded() -> bool {{ \
    //                 unsafe {{ ::storage::{name}.is_loaded }} \
    //             }} \
    //         }}",
    //         name = c.proto.ident,
    //     ).as_slice());
    // }
}

fn write_failing_fns(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    use syntax::ext::quote::rt::ToSource;

    ecx.parse_item(format!(
        "mod failing {{
            use super::types;
            use super::__gl_imports;

            {functions}
        }}",

        functions = registry.cmd_iter().map(|c| {
            format!(
                "#[allow(non_snake_case)] #[allow(unused_variable)] #[allow(dead_code)]
                pub extern \"system\" fn {name}({params}) -> {return_suffix} {{ \
                    fail!(\"`{name}` was not loaded\") \
                }}",
                name = c.proto.ident,
                params = super::gen_parameters(ecx, c).move_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
                return_suffix = super::gen_return_type(ecx, c).to_source()
            )
        }).collect::<Vec<String>>().connect("\n")
    ))
}

fn write_load_fn(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    let loadings = registry.cmd_iter().map(|c| {
        let cmd_name = ecx.ident_of(c.proto.ident.as_slice());
        quote_stmt!(ecx, $cmd_name::load_with(|s| loadfn(s));)
    }).collect::<Vec<P<ast::Stmt>>>();

    (quote_item!(ecx,
        /// Load each OpenGL symbol using a custom load function. This allows for the
        /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`.
        /// ~~~ignore
        /// gl::load_with(|s| glfw.get_proc_address(s));
        /// ~~~
        #[unstable]
        #[allow(dead_code)]
        pub fn load_with(loadfn: |symbol: &str| -> *const __gl_imports::libc::c_void) {
            $loadings
        }
    )).unwrap()
}
<commit_msg>Partially ASTify write_failing_fns<commit_after>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

#![experimental]

use registry::{Registry, Ns};
use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::ptr::P;

pub struct GlobalGenerator;

impl super::Generator for GlobalGenerator {
    fn write(&self, ecx: &ExtCtxt, registry: &Registry, ns: Ns) -> Vec<P<ast::Item>> {
        let mut result = Vec::new();
        result.push(write_header(ecx));
        result.push(write_type_aliases(ecx, &ns));
        result.push_all_move(write_enums(ecx, registry));
        result.push_all_move(write_fns(ecx, registry));
        result.push_all_move(write_fnptr_struct_def(ecx));
        result.push(write_ptrs(ecx, registry));
        result.push_all_move(write_fn_mods(ecx, registry, &ns));
        result.push(write_failing_fns(ecx, registry));
        result.push(write_load_fn(ecx, registry));
        result
    }
}

fn write_header(ecx: &ExtCtxt) -> P<ast::Item> {
    (quote_item!(ecx,
        mod __gl_imports {
            extern crate libc;
            pub use std::mem;
        }
    )).unwrap()
}

fn write_type_aliases(ecx: &ExtCtxt, ns: &Ns) -> P<ast::Item> {
    let aliases = super::gen_type_aliases(ecx, ns);

    (quote_item!(ecx,
        #[stable]
        pub mod types {
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]
            #![allow(dead_code)]

            $aliases
        }
    )).unwrap()
}

fn write_enums(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.enum_iter().map(|e| {
        super::gen_enum_item(ecx, e, "types::")
    }).collect()
}

fn write_fns(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        use syntax::ext::quote::rt::ToSource;

        ecx.parse_item(if c.is_safe {
            format!(
                "#[allow(non_snake_case)] #[allow(unused_variable)] #[allow(dead_code)]
                #[inline] #[unstable] pub fn {name}({params}) -> {return_suffix} {{ \
                    unsafe {{ \
                        __gl_imports::mem::transmute::<_, extern \"system\" fn({types}) -> {return_suffix}>\
                            (storage::{name}.f)({idents}) \
                    }} \
                }}",
                name = c.proto.ident,
                params = super::gen_parameters(ecx, c).move_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
                types = super::gen_parameters(ecx, c).move_iter().map(|p| p.ty.to_source()).collect::<Vec<String>>().connect(", "),
                return_suffix = super::gen_return_type(ecx, c).to_source(),
                idents = super::gen_parameters(ecx, c).move_iter().map(|p| p.pat.to_source()).collect::<Vec<String>>().connect(", "),
            )
        } else {
            format!(
                "#[allow(non_snake_case)] #[allow(unused_variable)] #[allow(dead_code)]
                #[inline] #[unstable] pub unsafe fn {name}({typed_params}) -> {return_suffix} {{ \
                    __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\
                        (storage::{name}.f)({idents}) \
                }}",
                name = c.proto.ident,
                typed_params = super::gen_parameters(ecx, c).move_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
                return_suffix = super::gen_return_type(ecx, c).to_source(),
                idents = super::gen_parameters(ecx, c).move_iter().map(|p| p.pat.to_source()).collect::<Vec<String>>().connect(", "),
            )
        })
    }).collect()
}

fn write_fnptr_struct_def(ecx: &ExtCtxt) -> Vec<P<ast::Item>> {
    vec![
        (quote_item!(ecx,
            pub struct FnPtr {
                f: *const __gl_imports::libc::c_void,
                is_loaded: bool,
            }
        )).unwrap(),

        (quote_item!(ecx,
            impl FnPtr {
                pub fn new(ptr: *const __gl_imports::libc::c_void, failing_fn: *const __gl_imports::libc::c_void) -> FnPtr {
                    if ptr.is_null() {
                        FnPtr { f: failing_fn, is_loaded: false }
                    } else {
                        FnPtr { f: ptr, is_loaded: true }
                    }
                }
            }
        )).unwrap()
    ]
}

fn write_ptrs(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    let storages = registry.cmd_iter().map(|c| {
        let name = ecx.ident_of(c.proto.ident.as_slice());

        (quote_item!(ecx,
            pub static mut $name: FnPtr = FnPtr {
                f: failing::$name as *const libc::c_void,
                is_loaded: false
            };
        )).unwrap()
    }).collect::<Vec<P<ast::Item>>>();

    (quote_item!(ecx,
        mod storage {
            #![allow(non_snake_case)]
            use super::__gl_imports::libc;
            use super::failing;
            use super::FnPtr;

            $storages
        }
    )).unwrap()
}

fn write_fn_mods(ecx: &ExtCtxt, registry: &Registry, ns: &Ns) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        let fnname = ecx.ident_of(c.proto.ident.as_slice());
        let symbol = super::gen_symbol_name(ns, c);
        let symbol = symbol.as_slice();

        (quote_item!(ecx,
            #[unstable]
            #[allow(non_snake_case)]
            pub mod $fnname {
                use super::{failing, storage};
                use super::FnPtr;

                #[inline]
                #[allow(dead_code)]
                pub fn is_loaded() -> bool {
                    unsafe { storage::$fnname.is_loaded }
                }

                #[allow(dead_code)]
                pub fn load_with(loadfn: |symbol: &str| -> *const super::__gl_imports::libc::c_void) {
                    unsafe {
                        storage::$fnname = FnPtr::new(loadfn($symbol),
                            failing::$fnname as *const super::__gl_imports::libc::c_void)
                    }
                }
            }
        )).unwrap()
    }).collect()

    // TODO: this is a reliquate from an old code, I have no idea what it does
    // for c in self.registry.cmd_iter() {
    //     self.write_line(format!(
    //         "pub mod {name} {{ \
    //             #[inline] \
    //             pub fn is_loaded() -> bool {{ \
    //                 unsafe {{ ::storage::{name}.is_loaded }} \
    //             }} \
    //         }}",
    //         name = c.proto.ident,
    //     ).as_slice());
    // }
}

fn write_failing_fns(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    use syntax::ext::quote::rt::ToSource;

    let functions = registry.cmd_iter().map(|c| {
        ecx.parse_item(format!(
            "#[allow(non_snake_case)] #[allow(unused_variable)] #[allow(dead_code)]
            pub extern \"system\" fn {name}({params}) -> {return_suffix} {{ \
                fail!(\"`{name}` was not loaded\") \
            }}",
            name = c.proto.ident,
            params = super::gen_parameters(ecx, c).move_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
            return_suffix = super::gen_return_type(ecx, c).to_source()
        ))
    }).collect::<Vec<P<ast::Item>>>();

    (quote_item!(ecx,
        mod failing {
            use super::types;
            use super::__gl_imports;

            $functions
        }
    )).unwrap()
}

fn write_load_fn(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    let loadings = registry.cmd_iter().map(|c| {
        let cmd_name = ecx.ident_of(c.proto.ident.as_slice());
        quote_stmt!(ecx, $cmd_name::load_with(|s| loadfn(s));)
    }).collect::<Vec<P<ast::Stmt>>>();

    (quote_item!(ecx,
        /// Load each OpenGL symbol using a custom load function. This allows for the
        /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`.
        /// ~~~ignore
        /// gl::load_with(|s| glfw.get_proc_address(s));
        /// ~~~
        #[unstable]
        #[allow(dead_code)]
        pub fn load_with(loadfn: |symbol: &str| -> *const __gl_imports::libc::c_void) {
            $loadings
        }
    )).unwrap()
}
<|endoftext|>


<commit_before>pub trait Histogram {

    //TODO should be default impl of this trait
    fn record_single_value(&self, value: i64) -> Result<(), String>;

    //TODO should be default impl of this trait
    fn counts_array_index(&self, value: i64) -> Result<i32, String>;

    //TODO should be default impl of this trait
    fn get_bucket_index(&self, value: i64) -> i32;

    //TODO should be default impl of this trait
    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32;

}

pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: i32,
    pub sub_bucket_mask: i64,
    pub unit_magnitude: i32,
}

impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0
        }
    }
}

impl Histogram for SimpleHdrHistogram {

    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32 {
        0
    }

    fn get_bucket_index(&self, value: i64) -> i32 {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - valueOrred.leading_zeros() as i32
    }

    fn record_single_value(&self, value: i64) -> Result<(), String> {

        let counts_index = self.counts_array_index(value);

        if true {
            Ok(())
        } else {
            Err(String::from("Could not record single value"))
        }

    }

    fn counts_array_index(&self, value: i64) -> Result<i32, String> {

        if (value < 0) {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            Ok(0)
        }
    }
}

#[test]
fn can_record_single_value() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}<commit_msg>sub bucket index shift<commit_after>pub trait Histogram {

    //TODO should be default impl of this trait
    fn record_single_value(&self, value: i64) -> Result<(), String>;

    //TODO should be default impl of this trait
    fn counts_array_index(&self, value: i64) -> Result<i32, String>;

    //TODO should be default impl of this trait
    fn get_bucket_index(&self, value: i64) -> i32;

    //TODO should be default impl of this trait
    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32;

}

pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: i32,
    pub sub_bucket_mask: i64,
    pub unit_magnitude: i32,
}

impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0
        }
    }
}

impl Histogram for SimpleHdrHistogram {

    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32 {
        let sum = bucket_index + self.unit_magnitude;
        sum.rotate_right(1)
    }

    fn get_bucket_index(&self, value: i64) -> i32 {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - valueOrred.leading_zeros() as i32
    }

    fn record_single_value(&self, value: i64) -> Result<(), String> {

        let counts_index = self.counts_array_index(value);

        if true {
            Ok(())
        } else {
            Err(String::from("Could not record single value"))
        }

    }

    fn counts_array_index(&self, value: i64) -> Result<i32, String> {

        if (value < 0) {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            Ok(0)
        }
    }
}

#[test]
fn can_record_single_value() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}<|endoftext|>


<commit_before>pub trait Histogram {

    //TODO should be default impl of this trait
    fn record_single_value(&self, value: i64) -> Result<(), String>;

    //TODO should be default impl of this trait
    fn counts_array_index(&self, value: i64) -> Result<i32, String>;

    //TODO should be default impl of this trait
    fn get_bucket_index(&self, value: i64) -> i32;

    //TODO should be default impl of this trait
    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32;

}

pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: i32,
    pub sub_bucket_mask: i64,
    pub unit_magnitude: i32,
}

impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0
        }
    }
}

impl Histogram for SimpleHdrHistogram {

    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32 {
        let sum = bucket_index + self.unit_magnitude;
        sum.rotate_right(1)
    }

    fn get_bucket_index(&self, value: i64) -> i32 {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - valueOrred.leading_zeros() as i32
    }

    fn record_single_value(&self, value: i64) -> Result<(), String> {

        let counts_index = self.counts_array_index(value);

        if true {
            Ok(())
        } else {
            Err(String::from("Could not record single value"))
        }

    }

    fn counts_array_index(&self, value: i64) -> Result<i32, String> {

        if (value < 0) {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            Ok(0)
        }
    }
}

#[test]
fn can_record_single_value() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}<commit_msg>fix shift<commit_after>pub trait Histogram {

    //TODO should be default impl of this trait
    fn record_single_value(&self, value: i64) -> Result<(), String>;

    //TODO should be default impl of this trait
    fn counts_array_index(&self, value: i64) -> Result<i32, String>;

    //TODO should be default impl of this trait
    fn get_bucket_index(&self, value: i64) -> i32;

    //TODO should be default impl of this trait
    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32;

}

pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: i32,
    pub sub_bucket_mask: i64,
    pub unit_magnitude: i32,
}

impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0
        }
    }
}

impl Histogram for SimpleHdrHistogram {

    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32 {
        let sum = bucket_index + self.unit_magnitude;
        value.rotate_right(sum as u32) as i32
    }

    fn get_bucket_index(&self, value: i64) -> i32 {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - valueOrred.leading_zeros() as i32
    }

    fn record_single_value(&self, value: i64) -> Result<(), String> {

        let counts_index = self.counts_array_index(value);

        if true {
            Ok(())
        } else {
            Err(String::from("Could not record single value"))
        }

    }

    fn counts_array_index(&self, value: i64) -> Result<i32, String> {

        if (value < 0) {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            Ok(0)
        }
    }
}

#[test]
fn can_record_single_value() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}<|endoftext|>


<commit_before>use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::fmt;
use std::io::{BufWriter, Bytes, Result, Write};

use super::nodes::{self, *};
use super::typ::*;

macro_rules! iwrite {
    ($self: ident, $($arg:tt)*) => (
        $self.writeln(format_args!($($arg)*))
    );
}

macro_rules! lnwrite {
    ($self: ident, $($arg:tt)*) => (
        $self.writeln(format_args!($($arg)*))
    );
}

pub struct PrinterOptions {
    pub print_pointers: bool,
}

impl Default for PrinterOptions {
    fn default() -> Self {
        Self {
            print_pointers: false,
        }
    }
}

pub struct Printer<O: Write> {
    output: RefCell<O>,
    indent: Cell<u8>,
    print_pointers: bool,
}

impl<O: Write> Printer<O> {
    pub fn new(output: O) -> Self {
        Self::new_with_options(output, PrinterOptions::default())
    }

    pub fn new_with_options(output: O, options: PrinterOptions) -> Self {
        Self {
            output: RefCell::new(output),
            indent: Cell::new(0),
            print_pointers: options.print_pointers,
        }
    }

    fn indented<F: FnOnce(&Self) -> Result<()>>(&self, inner: F) -> Result<()> {
        self.indented_steps(1, inner)
    }

    fn indented_steps<F: FnOnce(&Self) -> Result<()>>(&self, steps: u8, inner: F) -> Result<()> {
        let previous = self.indent.take();
        self.indent.set(previous + (2 * steps));
        let result = inner(self);
        self.indent.set(previous);
        result
    }

    pub fn print_module(&self, module: &Module) -> Result<()> {
        self.write("module {")?;
        self.indented(|this| {
            for statement in module.statements.iter() {
                use ModuleStatement::*;
                match statement {
                    Func(func) => self.print_func(func)?,
                }
            }
            Ok(())
        })?;
        self.lnwrite("}\n")?;
        Ok(())
    }

    fn print_func(&self, func: &nodes::Func) -> Result<()> {
        self.lnwrite(format!("func {}(", func.name))?;
        if !func.arguments.is_empty() {
            self.write("\n")?;
            self.indented(|this| {
                for argument in func.arguments.iter() {
                    this.iwrite(format!("{}: ", argument.name))?;
                    this.write_type(&argument.typ, true)?;
                    this.write(",\n")?;
                }
                Ok(())
            })?;
            self.iwrite("): ")?;
        } else {
            self.write("): ")?;
        }
        let retrn = match &func.typ {
            Type::Func(func) => func.retrn.borrow(),
            other @ _ => unreachable!("Func node has non-Func type: {:?}", other),
        };
        self.write_type(&retrn, false)?;
        self.write(" ")?;
        match &func.body {
            FuncBody::Block(block) => self.print_block(block, false),
        }
    }

    fn write_type(&self, typ: &Type, with_children: bool) -> Result<()> {
        self.write_recursive_type(typ, with_children, &mut HashSet::new())
    }

    // Write type recursively with guards against infinite recursion.
    fn write_recursive_type(
        &self,
        typ: &Type,
        with_children: bool,
        tracker: &mut HashSet<usize>,
    ) -> Result<()> {
        // True if we're writing a type we've written before.
        let recursive = !tracker.insert(typ.id());

        match typ {
            Type::Func(func) => {
                self.write(format!(
                    "{}#{}(",
                    func.name.clone().unwrap_or("".to_string()),
                    func.id
                ))?;
                let arguments = func.arguments.borrow();
                if !arguments.is_empty() {
                    if with_children {
                        for argument in arguments.iter() {
                            self.indented(|this1| {
                                this1.lnwrite("")?;
                                this1.write_recursive_type(argument, true, tracker)?;
                                this1.write(",")
                            })?;
                        }
                        self.lnwrite("): ")?;
                    } else {
                        self.write(format!("{}): ", arguments.len()))?;
                    }
                } else {
                    self.write("): ")?;
                }
                self.write_recursive_type(&func.retrn.borrow(), true, tracker)?;
                self.write_pointer(&**func)
            }
            Type::Object(object) => {
                self.write(format!("{}", object.class.name()))?;
                self.write_pointer(&**object)
            }
            Type::Generic(outer) => {
                let generic = outer.borrow();
                self.write(format!("${}", generic.id))?;
                if generic.has_constrains() && with_children && !recursive {
                    self.write("(")?;
                    self.indented(|this| this.write_constraints(&generic.constraints, tracker))?;
                    self.write(")")?;
                }
                self.write_pointer(&**outer)
            }
            Type::Tuple(tuple) => self.write(format!("({})", tuple.members.len())),
            Type::Variable(variable) => {
                let variable = &*variable.borrow();
                match variable {
                    Variable::Substitute { substitute, .. } => {
                        self.write("S(")?;
                        if recursive {
                            self.write("...")?;
                        } else {
                            self.write_type(&*substitute, with_children)?;
                        }
                        self.write(")")?;
                    }
                    Variable::Unbound { id, .. } => {
                        self.write(format!("U({})", id))?;
                    }
                    Variable::Generic { generic, .. } => {
                        self.write("G(")?;
                        self.write(format!("{}", generic.id))?;
                        if with_children && !recursive {
                            self.indented(|this| {
                                this.write_constraints(&generic.constraints, tracker)
                            })?;
                        }
                        self.write(")")?;
                    }
                }
                self.write_pointer(variable)
            }
            _ => unreachable!("Cannot print type: {:?}", typ),
        }
    }

    fn write_constraints(
        &self,
        constraints: &Vec<GenericConstraint>,
        tracker: &mut HashSet<usize>,
    ) -> Result<()> {
        if constraints.is_empty() {
            return Ok(());
        }
        self.lnwrite("where")?;
        self.indented(|this1| {
            for constraint in constraints {
                use GenericConstraint::*;
                match constraint {
                    Property(property) => {
                        this1.lnwrite(format!("{}: ", property.name))?;
                        this1.write_recursive_type(&property.typ, true, tracker)?;
                    }
                    Callable(callable) => {
                        if callable.arguments.is_empty() {
                            this1.lnwrite("(): ")?;
                        } else {
                            this1.lnwrite("(\n")?;
                            for argument in callable.arguments.iter() {
                                this1.indented(|this2| {
                                    this2.iwrite("")?;
                                    this2.write_recursive_type(argument, true, tracker)?;
                                    this2.write(",")
                                })?;
                            }
                            this1.lnwrite("): ")?;
                        }
                        this1.write_recursive_type(&callable.retrn, true, tracker)?;
                    }
                }
            }
            Ok(())
        })
    }

    fn print_var(&self, var: &Var, first: bool) -> Result<()> {
        let opener = format!("var {}: ", &var.name.name);
        if first {
            self.iwrite(opener)?;
        } else {
            self.lnwrite(opener)?;
        }
        self.write_type(&var.typ, true)?;
        if let Some(initializer) = &var.initializer {
            self.indented(|this| {
                this.write(" =")?;
                this.print_expression(initializer)
            })?;
        }
        Ok(())
    }

    fn print_block(&self, block: &Block, initial_indent: bool) -> Result<()> {
        let opener = "{";
        if initial_indent {
            self.iwrite(opener)?;
        } else {
            self.write(opener)?;
        }

        self.indented(|this| {
            let last_index = block.statements.len().checked_sub(1).unwrap_or(0);
            for statement in block.statements.iter() {
                use BlockStatement::*;
                match statement {
                    Expression(expression) => {
                        self.print_expression(expression)?;
                    }
                    Func(func) => self.print_func(func)?,
                    Var(var) => self.print_var(var, false)?,
                }
            }
            Ok(())
        })?;
        self.write("\n")?;
        self.iwrite("}")
    }

    fn print_expression(&self, expression: &Expression) -> Result<()> {
        use Expression::*;
        match expression {
            Closure(closure) => self.print_closure(closure),
            Identifier(identifier) => self.print_identifier(identifier),
            Infix(infix) => self.print_infix(infix),
            LiteralInt(literal) => self.lnwrite(format!("{}", literal.value)),
            PostfixCall(call) => self.print_postfix_call(call, 0).map(|_| ()),
            PostfixProperty(property) => self.print_postfix_property(property, 0).map(|_| ()),
        }
    }

    fn print_closure(&self, closure: &Closure) -> Result<()> {
        self.lnwrite("Closure(")?;
        if !closure.arguments.is_empty() {
            self.write("\n")?;
            self.indented(|this| {
                for argument in closure.arguments.iter() {
                    this.iwrite(format!("{}: ", argument.name))?;
                    this.write_type(&argument.typ, true)?;
                    this.write(",\n")?;
                }
                Ok(())
            })?;
        }
        self.iwrite("): ")?;
        let retrn = match &closure.typ {
            Type::Func(func) => func.retrn.borrow(),
            other @ _ => unreachable!("Closure node has non-Func type: {:?}", other),
        };
        self.write_type(&retrn, false)?;
        self.write(" ")?;
        match &*closure.body {
            ClosureBody::Block(block) => self.print_block(block, false),
            ClosureBody::Expression(expression) => self.indented(|this| {
                this.write("(")?;
                this.print_expression(expression)?;
                this.write(")")
            }),
        }
    }

    fn print_identifier(&self, identifier: &Identifier) -> Result<()> {
        self.lnwrite(format!("Identifier({}): ", identifier.name.name))?;
        self.write_type(&identifier.typ, false)
    }

    fn print_infix(&self, infix: &Infix) -> Result<()> {
        self.lnwrite("Infix(")?;
        self.indented(|this1| {
            this1.lnwrite("lhs:")?;
            this1.indented(|this2| this2.print_expression(&infix.lhs))?;
            this1.lnwrite(format!("op: {}", infix.op.to_string()))?;
            this1.lnwrite(format!("rhs:"))?;
            this1.indented(|this2| this2.print_expression(&infix.rhs))
        })?;
        self.write(")")
    }

    fn is_postfix(&self, expression: &Expression) -> bool {
        use Expression::*;
        match expression {
            PostfixProperty(_) => true,
            _ => false,
        }
    }

    fn print_postfix_call(&self, call: &PostfixCall, current: u8) -> Result<u8> {
        let max = self.print_postfix_target(&*call.target, current)?;
        // Have a +1 so that we always indent at least one step.
        self.indented_steps(max - current + 1, |this1| {
            this1.lnwrite(format!("Call("))?;
            if !call.arguments.is_empty() {
                for argument in call.arguments.iter() {
                    this1.indented(|this2| {
                        this2.print_expression(argument)?;
                        this2.write(",")
                    })?;
                }
            }
            this1.write("): ")?;
            this1.write_type(&call.typ, false)
        })?;
        Ok(max)
    }

    fn print_postfix_property(&self, property: &PostfixProperty, current: u8) -> Result<u8> {
        let max = self.print_postfix_target(&*property.target, current)?;
        self.indented_steps(max - current + 1, |this| {
            this.lnwrite(format!("Property({}): ", property.property.name))?;
            this.write_type(&property.typ, false)
        })?;
        Ok(max)
    }

    fn print_postfix_target(&self, target: &Expression, current: u8) -> Result<u8> {
        match target {
            // Links in the chain
            Expression::PostfixCall(target) => self.print_postfix_call(target, current + 1),
            Expression::PostfixProperty(target) => self.print_postfix_property(target, current + 1),
            // Tail of the chain
            other @ _ => {
                self.print_expression(other)?;
                Ok(current)
            }
        }
    }

    /// Write a string.
    fn write<S: AsRef<str>>(&self, string: S) -> Result<()> {
        self.write_output(string.as_ref().as_bytes())
    }

    /// Write indentation and then a string.
    fn iwrite<S: AsRef<str>>(&self, string: S) -> Result<()> {
        let indented = " ".repeat(self.indent.get() as usize);
        self.write_output(indented.as_bytes())
            .and_then(|_| self.write_output(string.as_ref().as_bytes()))
            .map(|_| ())
    }

    /// Write a newline, indentation, and then a string.
    fn lnwrite<S: AsRef<str>>(&self, string: S) -> Result<()> {
        let indented = " ".repeat(self.indent.get() as usize);
        self.write_output("\n".as_bytes())
            .and_then(|_| self.write_output(indented.as_bytes()))
            .and_then(|_| self.write_output(string.as_ref().as_bytes()))
    }

    fn write_output(&self, bytes: &[u8]) -> Result<()> {
        let mut output = self.output.borrow_mut();
        output.write(bytes).map(|_| ())
    }

    fn write_pointer<P>(&self, ptr: *const P) -> Result<()> {
        if !self.print_pointers {
            return Ok(());
        }
        self.write(format!(" @ {:p}", ptr))
    }

    // fn write_output(&self, bytes: &[u8]) -> Result<()> {
    //     let result = if let Some(buffer) = &mut *self.buffer.borrow_mut() {
    //         buffer.write(bytes)
    //     } else {
    //         let mut output = self.output.borrow_mut();
    //         output.write(bytes)
    //     };
    //     result.map(|_| ())
    // }
    //
    // fn buffer<F: FnOnce(&Self) -> Result<()>>(&self, inner: F) -> Result<Vec<u8>> {
    //     {
    //         let mut buffer = self.buffer.borrow_mut();
    //         *buffer = Some(vec![]);
    //     }
    //     inner(self)?;
    //     let buffer = self.buffer.replace(None);
    //     Ok(buffer.unwrap())
    // }
}
<commit_msg>Revise printer to produce more complete (but less compact) output<commit_after>use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::fmt;
use std::io::{BufWriter, Bytes, Result, Write};

use super::nodes::{self, *};
use super::typ::*;

macro_rules! iwrite {
    ($self: ident, $($arg:tt)*) => (
        $self.iwrite(format!($($arg)*))
    );
}

macro_rules! writeln {
    ($self: ident, $($arg:tt)*) => (
        $self.writeln(format!($($arg)*))
    );
}

pub struct PrinterOptions {
    pub print_pointers: bool,
}

impl Default for PrinterOptions {
    fn default() -> Self {
        Self {
            print_pointers: false,
        }
    }
}

pub struct Printer<O: Write> {
    output: RefCell<O>,
    indent: Cell<u8>,
    print_pointers: bool,
}

impl<O: Write> Printer<O> {
    pub fn new(output: O) -> Self {
        Self::new_with_options(output, PrinterOptions::default())
    }

    pub fn new_with_options(output: O, options: PrinterOptions) -> Self {
        Self {
            output: RefCell::new(output),
            indent: Cell::new(0),
            print_pointers: options.print_pointers,
        }
    }

    fn indented<F: FnOnce(&Self) -> Result<()>>(&self, inner: F) -> Result<()> {
        self.indented_steps(1, inner)
    }

    fn indented_steps<F: FnOnce(&Self) -> Result<()>>(&self, steps: u8, inner: F) -> Result<()> {
        let previous = self.indent.take();
        self.indent.set(previous + (2 * steps));
        let result = inner(self);
        self.indent.set(previous);
        result
    }

    pub fn print_module(&self, module: &Module) -> Result<()> {
        self.writeln("Module {")?;
        self.indented(|this| {
            for statement in module.statements.iter() {
                use ModuleStatement::*;
                match statement {
                    Func(func) => self.print_func(func)?,
                }
            }
            Ok(())
        })?;
        self.writeln("}")?;
        Ok(())
    }

    fn print_func(&self, func: &nodes::Func) -> Result<()> {
        self.writeln("Func {")?;
        self.indented(|_| {
            writeln!(self, "name: {}", func.name)?;
            self.iwrite("arguments: [")?;
            if !func.arguments.is_empty() {
                self.write("\n")?;
                self.indented(|_| {
                    for argument in func.arguments.iter() {
                        iwrite!(self, "{}: ", argument.name)?;
                        self.write_type(&argument.typ, true)?;
                        self.write("\n")?;
                    }
                    Ok(())
                })?;
                self.writeln("]")?;
            } else {
                self.write("]\n")?;
            }
            // TODO: Body
            self.iwrite("typ: ")?;
            self.write_type(&func.typ, true)?;
            self.write("\n")?;
            self.writeln("body:")?;
            self.indented(|_| match &func.body {
                FuncBody::Block(block) => self.print_block(block),
            })?;
            Ok(())
        })?;
        self.writeln("}")
    }

    fn write_type(&self, typ: &Type, with_children: bool) -> Result<()> {
        self.write_recursive_type(typ, with_children, &mut HashSet::new())
    }

    // Write type recursively with guards against infinite recursion.
    fn write_recursive_type(
        &self,
        typ: &Type,
        with_children: bool,
        tracker: &mut HashSet<usize>,
    ) -> Result<()> {
        // True if we're writing a type we've written before.
        let recursive = !tracker.insert(typ.id());

        match typ {
            Type::Func(func) => {
                self.write(format!(
                    "{}#{}(",
                    func.name.clone().unwrap_or("".to_string()),
                    func.id
                ))?;
                let arguments = func.arguments.borrow();
                if !arguments.is_empty() {
                    if with_children {
                        for argument in arguments.iter() {
                            self.indented(|this1| {
                                this1.lnwrite("")?;
                                this1.write_recursive_type(argument, true, tracker)?;
                                this1.write(",")
                            })?;
                        }
                        self.lnwrite("): ")?;
                    } else {
                        self.write(format!("{}): ", arguments.len()))?;
                    }
                } else {
                    self.write("): ")?;
                }
                self.write_recursive_type(&func.retrn.borrow(), true, tracker)?;
                self.write_pointer(&**func)
            }
            Type::Object(object) => {
                self.write(format!("{}", object.class.name()))?;
                self.write_pointer(&**object)
            }
            Type::Generic(outer) => {
                let generic = outer.borrow();
                self.write(format!("${}", generic.id))?;
                if generic.has_constrains() && with_children && !recursive {
                    self.write("(")?;
                    self.indented(|this| this.write_constraints(&generic.constraints, tracker))?;
                    self.write(")")?;
                }
                self.write_pointer(&**outer)
            }
            Type::Tuple(tuple) => self.write(format!("({})", tuple.members.len())),
            Type::Variable(variable) => {
                let variable = &*variable.borrow();
                match variable {
                    Variable::Substitute { substitute, .. } => {
                        self.write("S(")?;
                        if recursive {
                            self.write("...")?;
                        } else {
                            self.write_type(&*substitute, with_children)?;
                        }
                        self.write(")")?;
                    }
                    Variable::Unbound { id, .. } => {
                        self.write(format!("U({})", id))?;
                    }
                    Variable::Generic { generic, .. } => {
                        self.write("G(")?;
                        self.write(format!("{}", generic.id))?;
                        if with_children && !recursive {
                            self.indented(|this| {
                                this.write_constraints(&generic.constraints, tracker)
                            })?;
                        }
                        self.write(")")?;
                    }
                }
                self.write_pointer(variable)
            }
            _ => unreachable!("Cannot print type: {:?}", typ),
        }
    }

    fn write_constraints(
        &self,
        constraints: &Vec<GenericConstraint>,
        tracker: &mut HashSet<usize>,
    ) -> Result<()> {
        if constraints.is_empty() {
            return Ok(());
        }
        self.lnwrite("where")?;
        self.indented(|this1| {
            for constraint in constraints {
                use GenericConstraint::*;
                match constraint {
                    Property(property) => {
                        this1.lnwrite(format!("{}: ", property.name))?;
                        this1.write_recursive_type(&property.typ, true, tracker)?;
                    }
                    Callable(callable) => {
                        if callable.arguments.is_empty() {
                            this1.lnwrite("(): ")?;
                        } else {
                            this1.lnwrite("(\n")?;
                            for argument in callable.arguments.iter() {
                                this1.indented(|this2| {
                                    this2.iwrite("")?;
                                    this2.write_recursive_type(argument, true, tracker)?;
                                    this2.write(",")
                                })?;
                            }
                            this1.lnwrite("): ")?;
                        }
                        this1.write_recursive_type(&callable.retrn, true, tracker)?;
                    }
                }
            }
            Ok(())
        })
    }

    fn print_var(&self, var: &Var, first: bool) -> Result<()> {
        let opener = format!("var {}: ", &var.name.name);
        if first {
            self.iwrite(opener)?;
        } else {
            self.lnwrite(opener)?;
        }
        self.write_type(&var.typ, true)?;
        if let Some(initializer) = &var.initializer {
            self.indented(|this| {
                this.write(" =")?;
                this.print_expression(initializer)
            })?;
        }
        Ok(())
    }

    fn print_block(&self, block: &Block) -> Result<()> {
        self.iwrite("Block {")?;
        if block.statements.is_empty() {
            return self.write("}\n");
        }
        self.write("\n")?;
        self.indented(|_| {
            let last_index = block.statements.len().checked_sub(1).unwrap_or(0);
            for statement in block.statements.iter() {
                use BlockStatement::*;
                match statement {
                    Expression(expression) => {
                        self.print_expression(expression)?;
                    }
                    Func(func) => self.print_func(func)?,
                    Var(var) => self.print_var(var, false)?,
                }
            }
            Ok(())
        })?;
        self.writeln("}")
    }

    fn print_expression(&self, expression: &Expression) -> Result<()> {
        use Expression::*;
        match expression {
            Closure(closure) => self.print_closure(closure),
            Identifier(identifier) => self.print_identifier(identifier),
            Infix(infix) => self.print_infix(infix),
            LiteralInt(literal) => self.print_literal_int(literal),
            PostfixCall(call) => self.print_postfix_call(call),
            PostfixProperty(property) => self.print_postfix_property(property),
        }
    }

    fn print_closure(&self, closure: &Closure) -> Result<()> {
        self.writeln("Closure {")?;
        self.indented(|_| {
            self.iwrite("arguments: [")?;
            if !closure.arguments.is_empty() {
                self.write("\n")?;
                self.indented(|_| {
                    for argument in closure.arguments.iter() {
                        self.iwrite(format!("{}: ", argument.name))?;
                        self.write_type(&argument.typ, true)?;
                        self.write("\n")?;
                    }
                    Ok(())
                })?;
                self.writeln("]")?;
            } else {
                self.write("]\n")?;
            }
            self.writeln("body:")?;
            self.indented(|_| match &*closure.body {
                ClosureBody::Block(block) => self.print_block(block),
                ClosureBody::Expression(expression) => self.print_expression(expression),
            })?;
            self.iwrite("typ: ")?;
            self.write_type(&closure.typ, false)?;
            self.write("\n")
        })?;
        self.writeln("}")
    }

    fn print_literal_int(&self, literal: &LiteralInt) -> Result<()> {
        self.writeln("LiteralInt {")?;
        self.indented(|_| {
            writeln!(self, "value: {}", literal.value)?;
            self.iwrite("typ: ")?;
            self.write_type(&literal.typ, false)?;
            self.write("\n")
        })?;
        self.writeln("}")
    }

    fn print_identifier(&self, identifier: &Identifier) -> Result<()> {
        self.writeln("Identifier {")?;
        self.indented(|_| {
            writeln!(self, "name: {}", identifier.name.name)?;
            self.iwrite("typ: ")?;
            self.write_type(&identifier.typ, true)?;
            self.write("\n")
        })?;
        self.writeln("}")
    }

    fn print_infix(&self, infix: &Infix) -> Result<()> {
        self.writeln("Infix {")?;
        self.indented(|_| {
            self.writeln("lhs:")?;
            self.indented(|_| self.print_expression(&infix.lhs))?;
            writeln!(self, "op: {}", infix.op.to_string())?;
            self.writeln("rhs:")?;
            self.indented(|_| self.print_expression(&infix.rhs))?;
            self.iwrite("typ: ")?;
            self.write_type(&infix.typ, false)?;
            self.write("\n")
        })?;
        self.writeln("}")
    }

    fn print_postfix_call(&self, call: &PostfixCall) -> Result<()> {
        self.writeln("PostfixCall {")?;
        self.indented(|_| {
            self.writeln("target:")?;
            self.indented(|_| self.print_expression(&call.target))?;
            self.iwrite("arguments: [")?;
            if !call.arguments.is_empty() {
                self.write("\n")?;
                self.indented(|_| {
                    for argument in call.arguments.iter() {
                        self.print_expression(argument)?;
                    }
                    Ok(())
                })?;
                self.writeln("]")?;
            } else {
                self.write("]\n")?;
            }
            self.iwrite("typ: ")?;
            self.write_type(&call.typ, true)?;
            self.write("\n")
        })?;
        self.writeln("}")
    }

    fn print_postfix_property(&self, property: &PostfixProperty) -> Result<()> {
        self.writeln("PostfixCall {")?;
        self.indented(|_| {
            self.writeln("target:")?;
            self.indented(|_| self.print_expression(&property.target))?;
            writeln!(self, "property: {}", property.property.name)?;
            self.iwrite("typ: ")?;
            self.write_type(&property.typ, true)?;
            self.write("\n")
        })?;
        self.writeln("}")
    }

    /// Write a string.
    fn write<S: AsRef<str>>(&self, string: S) -> Result<()> {
        self.write_output(string.as_ref().as_bytes())
    }

    /// Write indentation and then a string.
    fn iwrite<S: AsRef<str>>(&self, string: S) -> Result<()> {
        let indented = " ".repeat(self.indent.get() as usize);
        self.write_output(indented.as_bytes())
            .and_then(|_| self.write_output(string.as_ref().as_bytes()))
            .map(|_| ())
    }

    /// Write a newline, indentation, and then a string.
    fn lnwrite<S: AsRef<str>>(&self, string: S) -> Result<()> {
        let indented = " ".repeat(self.indent.get() as usize);
        self.write_output("\n".as_bytes())
            .and_then(|_| self.write_output(indented.as_bytes()))
            .and_then(|_| self.write_output(string.as_ref().as_bytes()))
    }

    /// Write indentation, a string, and then a newline.
    fn writeln<S: AsRef<str>>(&self, string: S) -> Result<()> {
        let indented = " ".repeat(self.indent.get() as usize);
        self.write_output(indented.as_bytes())
            .and_then(|_| self.write_output(string.as_ref().as_bytes()))
            .and_then(|_| self.write_output("\n".as_bytes()))
    }

    fn write_output(&self, bytes: &[u8]) -> Result<()> {
        let mut output = self.output.borrow_mut();
        output.write(bytes).map(|_| ())
    }

    fn write_pointer<P>(&self, ptr: *const P) -> Result<()> {
        if !self.print_pointers {
            return Ok(());
        }
        self.write(format!(" @ {:p}", ptr))
    }

    // fn write_output(&self, bytes: &[u8]) -> Result<()> {
    //     let result = if let Some(buffer) = &mut *self.buffer.borrow_mut() {
    //         buffer.write(bytes)
    //     } else {
    //         let mut output = self.output.borrow_mut();
    //         output.write(bytes)
    //     };
    //     result.map(|_| ())
    // }
    //
    // fn buffer<F: FnOnce(&Self) -> Result<()>>(&self, inner: F) -> Result<Vec<u8>> {
    //     {
    //         let mut buffer = self.buffer.borrow_mut();
    //         *buffer = Some(vec![]);
    //     }
    //     inner(self)?;
    //     let buffer = self.buffer.replace(None);
    //     Ok(buffer.unwrap())
    // }
}
<|endoftext|>


<commit_before>use consts::{constant_simple, Constant};
use rustc::hir::*;
use rustc::lint::*;
use rustc_const_math::ConstInt;
use syntax::codemap::Span;
use utils::{in_macro, snippet, span_lint};

/// **What it does:** Checks for identity operations, e.g. `x + 0`.
///
/// **Why is this bad?** This code can be removed without changing the
/// meaning. So it just obscures what's going on. Delete it mercilessly.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// x / 1 + 0 * 1 - 0 | 0
/// ```
declare_lint! {
    pub IDENTITY_OP,
    Warn,
    "using identity operations, e.g. `x + 0` or `y / 1`"
}

#[derive(Copy, Clone)]
pub struct IdentityOp;

impl LintPass for IdentityOp {
    fn get_lints(&self) -> LintArray {
        lint_array!(IDENTITY_OP)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if in_macro(e.span) {
            return;
        }
        if let ExprBinary(ref cmp, ref left, ref right) = e.node {
            match cmp.node {
                BiAdd | BiBitOr | BiBitXor => {
                    check(cx, left, 0, e.span, right.span);
                    check(cx, right, 0, e.span, left.span);
                },
                BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span),
                BiMul => {
                    check(cx, left, 1, e.span, right.span);
                    check(cx, right, 1, e.span, left.span);
                },
                BiDiv => check(cx, right, 1, e.span, left.span),
                BiBitAnd => {
                    check(cx, left, -1, e.span, right.span);
                    check(cx, right, -1, e.span, left.span);
                },
                _ => (),
            }
        }
    }
}

fn no_zeros(v: &ConstInt) -> bool {
    match *v {
        ConstInt::I8(i) => i.count_zeros() == 0,
        ConstInt::I16(i) => i.count_zeros() == 0,
        ConstInt::I32(i) => i.count_zeros() == 0,
        ConstInt::I64(i) => i.count_zeros() == 0,
        ConstInt::I128(i) => i.count_zeros() == 0,
        ConstInt::U8(i) => i.count_zeros() == 0,
        ConstInt::U16(i) => i.count_zeros() == 0,
        ConstInt::U32(i) => i.count_zeros() == 0,
        ConstInt::U64(i) => i.count_zeros() == 0,
        ConstInt::U128(i) => i.count_zeros() == 0,
        _ => false
    }
}

#[allow(cast_possible_wrap)]
fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
    if let Some(Constant::Int(v)) = constant_simple(cx, e) {
        if match m {
            0 => v.to_u128_unchecked() == 0,
            -1 => no_zeros(&v),
            1 => v.to_u128_unchecked() == 1,
            _ => unreachable!(),
        } {
            span_lint(
                cx,
                IDENTITY_OP,
                span,
                &format!(
                    "the operation is ineffective. Consider reducing it to `{}`",
                    snippet(cx, arg, "..")
                ),
            );
        }
    }
}
<commit_msg>Simplify checking for all ones in int<commit_after>use consts::{constant_simple, Constant};
use rustc::hir::*;
use rustc::lint::*;
use rustc_const_math::ConstInt;
use syntax::codemap::Span;
use utils::{in_macro, snippet, span_lint};

/// **What it does:** Checks for identity operations, e.g. `x + 0`.
///
/// **Why is this bad?** This code can be removed without changing the
/// meaning. So it just obscures what's going on. Delete it mercilessly.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// x / 1 + 0 * 1 - 0 | 0
/// ```
declare_lint! {
    pub IDENTITY_OP,
    Warn,
    "using identity operations, e.g. `x + 0` or `y / 1`"
}

#[derive(Copy, Clone)]
pub struct IdentityOp;

impl LintPass for IdentityOp {
    fn get_lints(&self) -> LintArray {
        lint_array!(IDENTITY_OP)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if in_macro(e.span) {
            return;
        }
        if let ExprBinary(ref cmp, ref left, ref right) = e.node {
            match cmp.node {
                BiAdd | BiBitOr | BiBitXor => {
                    check(cx, left, 0, e.span, right.span);
                    check(cx, right, 0, e.span, left.span);
                },
                BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span),
                BiMul => {
                    check(cx, left, 1, e.span, right.span);
                    check(cx, right, 1, e.span, left.span);
                },
                BiDiv => check(cx, right, 1, e.span, left.span),
                BiBitAnd => {
                    check(cx, left, -1, e.span, right.span);
                    check(cx, right, -1, e.span, left.span);
                },
                _ => (),
            }
        }
    }
}

fn all_ones(v: &ConstInt) -> bool {
    match *v {
        ConstInt::I8(i) => i == !0,
        ConstInt::I16(i) => i == !0,
        ConstInt::I32(i) => i == !0,
        ConstInt::I64(i) => i == !0,
        ConstInt::I128(i) => i == !0,
        ConstInt::U8(i) => i == !0,
        ConstInt::U16(i) => i == !0,
        ConstInt::U32(i) => i == !0,
        ConstInt::U64(i) => i == !0,
        ConstInt::U128(i) => i == !0,
        _ => false
    }
}

#[allow(cast_possible_wrap)]
fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
    if let Some(Constant::Int(v)) = constant_simple(cx, e) {
        if match m {
            0 => v.to_u128_unchecked() == 0,
            -1 => all_ones(&v),
            1 => v.to_u128_unchecked() == 1,
            _ => unreachable!(),
        } {
            span_lint(
                cx,
                IDENTITY_OP,
                span,
                &format!(
                    "the operation is ineffective. Consider reducing it to `{}`",
                    snippet(cx, arg, "..")
                ),
            );
        }
    }
}
<|endoftext|>


<commit_before>// Note: More specifically this lint is largely inspired (aka copied) from
// *rustc*'s
// [`missing_doc`].
//
// [`missing_doc`]: https://github.com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin.rs#L246
//

use crate::utils::span_lint;
use if_chain::if_chain;
use rustc::hir;
use rustc::impl_lint_pass;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use rustc_session::declare_tool_lint;
use syntax::ast::{self, MetaItem, MetaItemKind};
use syntax::attr;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Warns if there is missing doc for any documentable item
    /// (public or private).
    ///
    /// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS`
    /// allowed-by-default lint for
    /// public members, but has no way to enforce documentation of private items.
    /// This lint fixes that.
    ///
    /// **Known problems:** None.
    pub MISSING_DOCS_IN_PRIVATE_ITEMS,
    restriction,
    "detects missing documentation for public and private members"
}

pub struct MissingDoc {
    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,
}

impl ::std::default::Default for MissingDoc {
    #[must_use]
    fn default() -> Self {
        Self::new()
    }
}

impl MissingDoc {
    #[must_use]
    pub fn new() -> Self {
        Self {
            doc_hidden_stack: vec![false],
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    fn has_include(meta: Option<MetaItem>) -> bool {
        if_chain! {
            if let Some(meta) = meta;
            if let MetaItemKind::List(list) = meta.kind;
            if let Some(meta) = list.get(0);
            if let Some(name) = meta.ident();
            then {
                name.as_str() == "include"
            } else {
                false
            }
        }
    }

    fn check_missing_docs_attrs(
        &self,
        cx: &LateContext<'_, '_>,
        attrs: &[ast::Attribute],
        sp: Span,
        desc: &'static str,
    ) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // `#[doc(hidden)]` disables missing_docs check.
        if self.doc_hidden() {
            return;
        }

        if sp.from_expansion() {
            return;
        }

        let has_doc = attrs
            .iter()
            .any(|a| a.check_name(sym!(doc)) && (a.is_value_str() || Self::has_include(a.meta())));
        if !has_doc {
            span_lint(
                cx,
                MISSING_DOCS_IN_PRIVATE_ITEMS,
                sp,
                &format!("missing documentation for {}", desc),
            );
        }
    }
}

impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
    fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
        let doc_hidden = self.doc_hidden()
            || attrs.iter().any(|attr| {
                attr.check_name(sym!(doc))
                    && match attr.meta_item_list() {
                        None => false,
                        Some(l) => attr::list_contains_name(&l[..], sym!(hidden)),
                    }
            });
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate<'_>) {
        self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate");
    }

    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) {
        let desc = match it.kind {
            hir::ItemKind::Const(..) => "a constant",
            hir::ItemKind::Enum(..) => "an enum",
            hir::ItemKind::Fn(..) => {
                // ignore main()
                if it.ident.name == sym!(main) {
                    let def_id = cx.tcx.hir().local_def_id(it.hir_id);
                    let def_key = cx.tcx.hir().def_key(def_id);
                    if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
                        return;
                    }
                }
                "a function"
            },
            hir::ItemKind::Mod(..) => "a module",
            hir::ItemKind::Static(..) => "a static",
            hir::ItemKind::Struct(..) => "a struct",
            hir::ItemKind::Trait(..) => "a trait",
            hir::ItemKind::TraitAlias(..) => "a trait alias",
            hir::ItemKind::TyAlias(..) => "a type alias",
            hir::ItemKind::Union(..) => "a union",
            hir::ItemKind::OpaqueTy(..) => "an existential type",
            hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod(..)
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::Impl(..)
            | hir::ItemKind::Use(..) => return,
        };

        self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
        let desc = match trait_item.kind {
            hir::TraitItemKind::Const(..) => "an associated constant",
            hir::TraitItemKind::Method(..) => "a trait method",
            hir::TraitItemKind::Type(..) => "an associated type",
        };

        self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
        // If the method is an impl for a trait, don't doc.
        let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
        match cx.tcx.associated_item(def_id).container {
            ty::TraitContainer(_) => return,
            ty::ImplContainer(cid) => {
                if cx.tcx.impl_trait_ref(cid).is_some() {
                    return;
                }
            },
        }

        let desc = match impl_item.kind {
            hir::ImplItemKind::Const(..) => "an associated constant",
            hir::ImplItemKind::Method(..) => "a method",
            hir::ImplItemKind::TyAlias(_) => "an associated type",
            hir::ImplItemKind::OpaqueTy(_) => "an existential type",
        };
        self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
    }

    fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, sf: &'tcx hir::StructField<'_>) {
        if !sf.is_positional() {
            self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field");
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, v: &'tcx hir::Variant<'_>) {
        self.check_missing_docs_attrs(cx, &v.attrs, v.span, "a variant");
    }
}
<commit_msg>Rustup to rust-lang/rust#67151<commit_after>// Note: More specifically this lint is largely inspired (aka copied) from
// *rustc*'s
// [`missing_doc`].
//
// [`missing_doc`]: https://github.com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin.rs#L246
//

use crate::utils::span_lint;
use if_chain::if_chain;
use rustc::hir;
use rustc::impl_lint_pass;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use rustc_session::declare_tool_lint;
use syntax::ast::{self, MetaItem, MetaItemKind};
use syntax::attr;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Warns if there is missing doc for any documentable item
    /// (public or private).
    ///
    /// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS`
    /// allowed-by-default lint for
    /// public members, but has no way to enforce documentation of private items.
    /// This lint fixes that.
    ///
    /// **Known problems:** None.
    pub MISSING_DOCS_IN_PRIVATE_ITEMS,
    restriction,
    "detects missing documentation for public and private members"
}

pub struct MissingDoc {
    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,
}

impl ::std::default::Default for MissingDoc {
    #[must_use]
    fn default() -> Self {
        Self::new()
    }
}

impl MissingDoc {
    #[must_use]
    pub fn new() -> Self {
        Self {
            doc_hidden_stack: vec![false],
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    fn has_include(meta: Option<MetaItem>) -> bool {
        if_chain! {
            if let Some(meta) = meta;
            if let MetaItemKind::List(list) = meta.kind;
            if let Some(meta) = list.get(0);
            if let Some(name) = meta.ident();
            then {
                name.as_str() == "include"
            } else {
                false
            }
        }
    }

    fn check_missing_docs_attrs(
        &self,
        cx: &LateContext<'_, '_>,
        attrs: &[ast::Attribute],
        sp: Span,
        desc: &'static str,
    ) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // `#[doc(hidden)]` disables missing_docs check.
        if self.doc_hidden() {
            return;
        }

        if sp.from_expansion() {
            return;
        }

        let has_doc = attrs
            .iter()
            .any(|a| a.is_doc_comment() || a.doc_str().is_some() || a.is_value_str() || Self::has_include(a.meta()));
        if !has_doc {
            span_lint(
                cx,
                MISSING_DOCS_IN_PRIVATE_ITEMS,
                sp,
                &format!("missing documentation for {}", desc),
            );
        }
    }
}

impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
    fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
        let doc_hidden = self.doc_hidden()
            || attrs.iter().any(|attr| {
                attr.check_name(sym!(doc))
                    && match attr.meta_item_list() {
                        None => false,
                        Some(l) => attr::list_contains_name(&l[..], sym!(hidden)),
                    }
            });
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate<'_>) {
        self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate");
    }

    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) {
        let desc = match it.kind {
            hir::ItemKind::Const(..) => "a constant",
            hir::ItemKind::Enum(..) => "an enum",
            hir::ItemKind::Fn(..) => {
                // ignore main()
                if it.ident.name == sym!(main) {
                    let def_id = cx.tcx.hir().local_def_id(it.hir_id);
                    let def_key = cx.tcx.hir().def_key(def_id);
                    if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
                        return;
                    }
                }
                "a function"
            },
            hir::ItemKind::Mod(..) => "a module",
            hir::ItemKind::Static(..) => "a static",
            hir::ItemKind::Struct(..) => "a struct",
            hir::ItemKind::Trait(..) => "a trait",
            hir::ItemKind::TraitAlias(..) => "a trait alias",
            hir::ItemKind::TyAlias(..) => "a type alias",
            hir::ItemKind::Union(..) => "a union",
            hir::ItemKind::OpaqueTy(..) => "an existential type",
            hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod(..)
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::Impl(..)
            | hir::ItemKind::Use(..) => return,
        };

        self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
        let desc = match trait_item.kind {
            hir::TraitItemKind::Const(..) => "an associated constant",
            hir::TraitItemKind::Method(..) => "a trait method",
            hir::TraitItemKind::Type(..) => "an associated type",
        };

        self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
        // If the method is an impl for a trait, don't doc.
        let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
        match cx.tcx.associated_item(def_id).container {
            ty::TraitContainer(_) => return,
            ty::ImplContainer(cid) => {
                if cx.tcx.impl_trait_ref(cid).is_some() {
                    return;
                }
            },
        }

        let desc = match impl_item.kind {
            hir::ImplItemKind::Const(..) => "an associated constant",
            hir::ImplItemKind::Method(..) => "a method",
            hir::ImplItemKind::TyAlias(_) => "an associated type",
            hir::ImplItemKind::OpaqueTy(_) => "an existential type",
        };
        self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
    }

    fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, sf: &'tcx hir::StructField<'_>) {
        if !sf.is_positional() {
            self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field");
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, v: &'tcx hir::Variant<'_>) {
        self.check_missing_docs_attrs(cx, &v.attrs, v.span, "a variant");
    }
}
<|endoftext|>


<commit_before>// This defines the amd64 target for UEFI systems as described in the UEFI specification. See the
// uefi-base module for generic UEFI options. On x86_64 systems (mostly called "x64" in the spec)
// UEFI systems always run in long-mode, have the interrupt-controller pre-configured and force a
// single-CPU execution.
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.

use crate::spec::{CodeModel, Target};

pub fn target() -> Target {
    let mut base = super::uefi_msvc_base::opts();
    base.cpu = "x86-64".to_string();
    base.max_atomic_width = Some(64);

    // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
    // enable these CPU features explicitly before their first use, otherwise their instructions
    // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE
    // instruction sets, so this must be done by the firmware. However, existing firmware is known
    // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
    // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
    // far.
    // If you initialize FP units yourself, you can override these flags with custom linker
    // arguments, thus giving you access to full MMX/SSE acceleration.
    base.features = "-mmx,-sse,+soft-float".to_string();

    // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell
    // LLVM to expect code to reference any address in the address-space. The "large" code-model
    // places no locality-restrictions, so it fits well here.
    base.code_model = Some(CodeModel::Large);

    Target {
        llvm_target: "x86_64-unknown-windows".to_string(),
        pointer_width: 64,
        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
            .to_string(),
        arch: "x86_64".to_string(),

        options: base,
    }
}
<commit_msg>Use small code model for UEFI targets<commit_after>// This defines the amd64 target for UEFI systems as described in the UEFI specification. See the
// uefi-base module for generic UEFI options. On x86_64 systems (mostly called "x64" in the spec)
// UEFI systems always run in long-mode, have the interrupt-controller pre-configured and force a
// single-CPU execution.
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.

use crate::spec::Target;

pub fn target() -> Target {
    let mut base = super::uefi_msvc_base::opts();
    base.cpu = "x86-64".to_string();
    base.max_atomic_width = Some(64);

    // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
    // enable these CPU features explicitly before their first use, otherwise their instructions
    // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE
    // instruction sets, so this must be done by the firmware. However, existing firmware is known
    // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
    // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
    // far.
    //
    // If you initialize FP units yourself, you can override these flags with custom linker
    // arguments, thus giving you access to full MMX/SSE acceleration.
    base.features = "-mmx,-sse,+soft-float".to_string();

    Target {
        llvm_target: "x86_64-unknown-windows".to_string(),
        pointer_width: 64,
        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
            .to_string(),
        arch: "x86_64".to_string(),

        options: base,
    }
}
<|endoftext|>


<commit_before><commit_msg>client-api: Fix broken create_backup::Request deserialization<commit_after><|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::probe::Handle;

use differential_dataflow::input::Input;
use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::lattice::Lattice;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: u32 = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: u32 = std::env::args().nth(4).unwrap().parse().unwrap();
    let inspect: bool = std::env::args().nth(5).unwrap() == "inspect";

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(6), move |worker| {

        let timer = ::std::time::Instant::now();

        // define BFS dataflow; return handles to roots and edges inputs
        let mut probe = Handle::new();
        let (mut roots, mut graph) = worker.dataflow(|scope| {

            let (root_input, roots) = scope.new_collection();
            let (edge_input, graph) = scope.new_collection();

            let mut result = bfs(&graph, &roots);

            if !inspect {
                result = result.filter(|_| false);
            }

            result.map(|(_,l)| l)
                  .consolidate()
                  .inspect(|x| println!("\t{:?}", x))
                  .probe_with(&mut probe);

            (root_input, edge_input)
        });

        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        roots.insert(0);
        roots.close();

        println!("performing BFS on {} nodes, {} edges:", nodes, edges);

        if worker.index() == 0 {

            // trickle edges in to dataflow
            for _ in 0..(edges/1000) {
                for _ in 0..1000 {
                    graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                }
                worker.step();
            }
            for _ in 0.. (edges % 1000) {
                graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
            }
        }

        println!("loaded; elapsed: {:?}", timer.elapsed());

        graph.advance_to(1);
        worker.step_while(|| probe.less_than(graph.time()));

        for round in 0 .. rounds {
            for element in 0 .. batch {
                if worker.index() == 0 {
                    graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                    graph.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                }
                graph.advance_to(2 + round * batch + element);
            }
            graph.flush();

            let timer = ::std::time::Instant::now();
            worker.step_while(|| probe.less_than(&graph.time()));

            if worker.index() == 0 {
                let elapsed = timer.elapsed();
                println!("{:?}:\t{}", round, elapsed.as_secs() * 1000000000 + (elapsed.subsec_nanos() as u64));
            }
        }
        println!("finished; elapsed: {:?}", timer.elapsed());
    }).unwrap();
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn bfs<G: Scope>(edges: &Collection<G, Edge>, roots: &Collection<G, Node>) -> Collection<G, (Node, u32)>
where G::Timestamp: Lattice+Ord {

    // initialize roots as reaching themselves at distance 0
    let nodes = roots.map(|x| (x, 0));

    // repeatedly update minimal distances each node can be reached from each root
    nodes.iterate(|inner| {

        let edges = edges.enter(&inner.scope());
        let nodes = nodes.enter(&inner.scope());

        inner.join_map_u(&edges, |_k,l,d| (*d, l+1))
             .concat(&nodes)
             .group_u(|_, s, t| t.push((s[0].0, 1)))
     })
}<commit_msg>examples/bfs: flush graph input after advancing to time=1<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::probe::Handle;

use differential_dataflow::input::Input;
use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::lattice::Lattice;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: u32 = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: u32 = std::env::args().nth(4).unwrap().parse().unwrap();
    let inspect: bool = std::env::args().nth(5).unwrap() == "inspect";

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(6), move |worker| {

        let timer = ::std::time::Instant::now();

        // define BFS dataflow; return handles to roots and edges inputs
        let mut probe = Handle::new();
        let (mut roots, mut graph) = worker.dataflow(|scope| {

            let (root_input, roots) = scope.new_collection();
            let (edge_input, graph) = scope.new_collection();

            let mut result = bfs(&graph, &roots);

            if !inspect {
                result = result.filter(|_| false);
            }

            result.map(|(_,l)| l)
                  .consolidate()
                  .inspect(|x| println!("\t{:?}", x))
                  .probe_with(&mut probe);

            (root_input, edge_input)
        });

        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        roots.insert(0);
        roots.close();

        println!("performing BFS on {} nodes, {} edges:", nodes, edges);

        if worker.index() == 0 {

            // trickle edges in to dataflow
            for _ in 0..(edges/1000) {
                for _ in 0..1000 {
                    graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                }
                worker.step();
            }
            for _ in 0.. (edges % 1000) {
                graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
            }
        }

        println!("loaded; elapsed: {:?}", timer.elapsed());

        graph.advance_to(1);
        graph.flush();
        worker.step_while(|| probe.less_than(graph.time()));

        for round in 0 .. rounds {
            for element in 0 .. batch {
                if worker.index() == 0 {
                    graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                    graph.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                }
                graph.advance_to(2 + round * batch + element);
            }
            graph.flush();

            let timer = ::std::time::Instant::now();
            worker.step_while(|| probe.less_than(&graph.time()));

            if worker.index() == 0 {
                let elapsed = timer.elapsed();
                println!("{:?}:\t{}", round, elapsed.as_secs() * 1000000000 + (elapsed.subsec_nanos() as u64));
            }
        }
        println!("finished; elapsed: {:?}", timer.elapsed());
    }).unwrap();
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn bfs<G: Scope>(edges: &Collection<G, Edge>, roots: &Collection<G, Node>) -> Collection<G, (Node, u32)>
where G::Timestamp: Lattice+Ord {

    // initialize roots as reaching themselves at distance 0
    let nodes = roots.map(|x| (x, 0));

    // repeatedly update minimal distances each node can be reached from each root
    nodes.iterate(|inner| {

        let edges = edges.enter(&inner.scope());
        let nodes = nodes.enter(&inner.scope());

        inner.join_map_u(&edges, |_k,l,d| (*d, l+1))
             .concat(&nodes)
             .group_u(|_, s, t| t.push((s[0].0, 1)))
     })
}<|endoftext|>