<commit_before>use rustc::hir::*;
use rustc::lint::*;
use syntax::codemap::{Span, Spanned};

use consts::{self, Constant};
use utils::span_lint;

/// **What it does:** Checks for multiplication by -1 as a form of negation.
///
/// **Why is this bad?** It's more readable to just negate.
///
/// **Known problems:** This only catches integers (for now)
///
/// **Example:** `x * -1`
declare_lint! {
    pub NEG_MULTIPLY,
    Warn,
    "Warns on multiplying integers with -1"
}

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

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

#[allow(match_same_arms)]
impl LateLintPass for NegMultiply {
    fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
        if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
            match (&l.node, &r.node) {
                (&ExprUnary(..), &ExprUnary(..)) => (),
                (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
                (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
                _ => (),
            }
        }
    }
}

fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
    if_let_chain!([
        let ExprLit(ref l) = lit.node,
        let Constant::Int(ref ci) = consts::lit_to_constant(&l.node),
        let Some(val) = ci.to_u64(),
        val == 1,
        cx.tcx.expr_ty(exp).is_integral()
    ], {
        span_lint(cx,
                  NEG_MULTIPLY,
                  span,
                  "Negation by multiplying with -1");
    })
}
<commit_msg>Cleanup trailing space<commit_after>use rustc::hir::*;
use rustc::lint::*;
use syntax::codemap::{Span, Spanned};

use consts::{self, Constant};
use utils::span_lint;

/// **What it does:** Checks for multiplication by -1 as a form of negation.
///
/// **Why is this bad?** It's more readable to just negate.
///
/// **Known problems:** This only catches integers (for now)
///
/// **Example:** `x * -1`
declare_lint! {
    pub NEG_MULTIPLY,
    Warn,
    "Warns on multiplying integers with -1"
}

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

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

#[allow(match_same_arms)]
impl LateLintPass for NegMultiply {
    fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
        if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
            match (&l.node, &r.node) {
                (&ExprUnary(..), &ExprUnary(..)) => (),
                (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
                (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
                _ => (),
            }
        }
    }
}

fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
    if_let_chain!([
        let ExprLit(ref l) = lit.node,
        let Constant::Int(ref ci) = consts::lit_to_constant(&l.node),
        let Some(val) = ci.to_u64(),
        val == 1,
        cx.tcx.expr_ty(exp).is_integral()
    ], {
        span_lint(cx,
                  NEG_MULTIPLY,
                  span,
                  "Negation by multiplying with -1");
    })
}
<|endoftext|>


<commit_before>use criterion::{black_box, criterion_group, criterion_main, Criterion};
use point_cloud_client::PointCloudClient;
use point_cloud_test_lib::{
    get_abb_query, get_cell_union_query, get_frustum_query, get_obb_query, make_octree,
    make_s2_cells, setup_octree_client, setup_s2_client, Arguments, SyntheticData,
};
use point_viewer::iterator::{PointLocation, PointQuery};
use tempdir::TempDir;

fn bench_octree_building_multithreaded(c: &mut Criterion) {
    let mut args = Arguments::default();
    args.num_points = 100_000;
    c.bench_function("bench_octree_building_multithreaded", |b| {
        b.iter(|| {
            let temp_dir = TempDir::new("octree").unwrap();
            make_octree(&args, temp_dir.path());
        })
    });
}

fn bench_s2_building_singlethreaded(c: &mut Criterion) {
    let mut args = Arguments::default();
    args.num_points = 100_000;
    c.bench_function("bench_s2_building_singlethreaded", |b| {
        b.iter(|| {
            let temp_dir = TempDir::new("s2").unwrap();
            make_s2_cells(&args, temp_dir.path());
        })
    });
}

fn all_query_octree(b: &mut Criterion) {
    run_bench(
        "all_query_octree",
        setup_octree_client,
        |_| PointLocation::AllPoints,
        b,
    )
}

fn all_query_s2(b: &mut Criterion) {
    run_bench(
        "all_query_s2",
        setup_s2_client,
        |_| PointLocation::AllPoints,
        b,
    )
}

fn box_query_octree(b: &mut Criterion) {
    run_bench("box_query_octree", setup_octree_client, get_abb_query, b)
}

fn box_query_s2(b: &mut Criterion) {
    run_bench("box_query_s2", setup_s2_client, get_abb_query, b)
}

fn frustum_query_octree(b: &mut Criterion) {
    run_bench(
        "frustum_query_octree",
        setup_octree_client,
        get_frustum_query,
        b,
    )
}

fn frustum_query_s2(b: &mut Criterion) {
    run_bench("frustum_query_s2", setup_s2_client, get_frustum_query, b)
}

fn obb_query_octree(b: &mut Criterion) {
    run_bench("obb_query_octree", setup_octree_client, get_obb_query, b)
}

fn obb_query_s2(b: &mut Criterion) {
    run_bench("obb_query_s2", setup_s2_client, get_obb_query, b)
}

fn cell_union_query_octree(b: &mut Criterion) {
    run_bench(
        "cell_union_query_octree",
        setup_octree_client,
        get_cell_union_query,
        b,
    )
}

fn cell_union_query_s2(b: &mut Criterion) {
    run_bench(
        "cell_union_query_s2",
        setup_s2_client,
        get_cell_union_query,
        b,
    )
}

criterion_group!(
    benches,
    bench_octree_building_multithreaded,
    bench_s2_building_singlethreaded,
    all_query_octree,
    all_query_s2,
    box_query_octree,
    box_query_s2,
    frustum_query_octree,
    frustum_query_s2,
    obb_query_octree,
    obb_query_s2,
    cell_union_query_octree,
    cell_union_query_s2,
);
criterion_main!(benches);

type SetupClientFn = fn(&Arguments) -> (PointCloudClient, SyntheticData);

fn run_bench<F>(name: &'static str, gen_client: SetupClientFn, gen_location: F, c: &mut Criterion)
where
    F: FnOnce(SyntheticData) -> PointLocation,
{
    let args = Arguments::default();
    let (client, data) = gen_client(&args);
    let query = PointQuery {
        attributes: vec!["color"],
        location: gen_location(data),
        ..Default::default()
    };
    c.bench_function(name, |b| {
        b.iter(|| {
            let res = client.for_each_point_data(&query, |batch| {
                black_box(batch);
                Ok(())
            });
            assert!(res.is_ok());
        })
    });
}
<commit_msg>Fix benchmark (#456)<commit_after>use criterion::{black_box, criterion_group, criterion_main, Criterion};
use point_cloud_client::PointCloudClient;
use point_cloud_test_lib::queries::*;
use point_cloud_test_lib::{
    make_octree, make_s2_cells, setup_octree_client, setup_s2_client, Arguments, SyntheticData,
};
use point_viewer::iterator::{PointLocation, PointQuery};
use tempdir::TempDir;

fn bench_octree_building_multithreaded(c: &mut Criterion) {
    let mut args = Arguments::default();
    args.num_points = 100_000;
    c.bench_function("bench_octree_building_multithreaded", |b| {
        b.iter(|| {
            let temp_dir = TempDir::new("octree").unwrap();
            make_octree(&args, temp_dir.path());
        })
    });
}

fn bench_s2_building_singlethreaded(c: &mut Criterion) {
    let mut args = Arguments::default();
    args.num_points = 100_000;
    c.bench_function("bench_s2_building_singlethreaded", |b| {
        b.iter(|| {
            let temp_dir = TempDir::new("s2").unwrap();
            make_s2_cells(&args, temp_dir.path());
        })
    });
}

fn all_query_octree(b: &mut Criterion) {
    run_bench(
        "all_query_octree",
        setup_octree_client,
        |_| PointLocation::AllPoints,
        b,
    )
}

fn all_query_s2(b: &mut Criterion) {
    run_bench(
        "all_query_s2",
        setup_s2_client,
        |_| PointLocation::AllPoints,
        b,
    )
}

fn box_query_octree(b: &mut Criterion) {
    run_bench("box_query_octree", setup_octree_client, get_aabb_query, b)
}

fn box_query_s2(b: &mut Criterion) {
    run_bench("box_query_s2", setup_s2_client, get_aabb_query, b)
}

fn frustum_query_octree(b: &mut Criterion) {
    run_bench(
        "frustum_query_octree",
        setup_octree_client,
        get_frustum_query,
        b,
    )
}

fn frustum_query_s2(b: &mut Criterion) {
    run_bench("frustum_query_s2", setup_s2_client, get_frustum_query, b)
}

fn obb_query_octree(b: &mut Criterion) {
    run_bench("obb_query_octree", setup_octree_client, get_obb_query, b)
}

fn obb_query_s2(b: &mut Criterion) {
    run_bench("obb_query_s2", setup_s2_client, get_obb_query, b)
}

fn cell_union_query_octree(b: &mut Criterion) {
    run_bench(
        "cell_union_query_octree",
        setup_octree_client,
        get_cell_union_query,
        b,
    )
}

fn cell_union_query_s2(b: &mut Criterion) {
    run_bench(
        "cell_union_query_s2",
        setup_s2_client,
        get_cell_union_query,
        b,
    )
}

criterion_group!(
    benches,
    bench_octree_building_multithreaded,
    bench_s2_building_singlethreaded,
    all_query_octree,
    all_query_s2,
    box_query_octree,
    box_query_s2,
    frustum_query_octree,
    frustum_query_s2,
    obb_query_octree,
    obb_query_s2,
    cell_union_query_octree,
    cell_union_query_s2,
);
criterion_main!(benches);

type SetupClientFn = fn(&Arguments) -> (PointCloudClient, SyntheticData);

fn run_bench<F>(name: &'static str, gen_client: SetupClientFn, gen_location: F, c: &mut Criterion)
where
    F: FnOnce(SyntheticData) -> PointLocation,
{
    let args = Arguments::default();
    let (client, data) = gen_client(&args);
    let query = PointQuery {
        attributes: vec!["color"],
        location: gen_location(data),
        ..Default::default()
    };
    c.bench_function(name, |b| {
        b.iter(|| {
            let res = client.for_each_point_data(&query, |batch| {
                black_box(batch);
                Ok(())
            });
            assert!(res.is_ok());
        })
    });
}
<|endoftext|>


<commit_before>use ast::*;
use bytecode::*;

fn stack_alloc(func: &mut ByteCodeFunction, typ: &Type, name: Option<&str>) -> Var
{
    match name
    {
        Some(n) => {
            let var = Var::named(n, typ.clone());
            func.add_named_var(var.clone());
            if *typ != Type::Void {
                func.add(Instruction::StackAlloc(var.clone()));
            }
            var
        },
        None => {
            let var = func.new_var(typ.clone());
            if *typ != Type::Void {
                func.add(Instruction::StackAlloc(var.clone()));
            }
            var
        }
    }
}

fn get_dst(func: &mut ByteCodeFunction, typ: &Type) -> Var
{
    assert!(*typ != Type::Unknown);
    if let Some(dst) = func.get_destination() {
        if dst.typ != *typ {
            panic!("Internal compiler error: dst.typ ({}) != *typ ({}) in get_dst", dst.typ, typ);
        }
        return dst;
    }

    stack_alloc(func, typ, None)
}

fn array_lit_to_bc(func: &mut ByteCodeFunction, a: &ArrayLiteral, dst: &Var)
{
    let vars = a.elements.iter()
        .map(|e| to_bc(func, e))
        .collect();

    func.add(store_lit_instr(dst, ByteCodeLiteral::Array(vars)));
}

fn call_to_bc(func: &mut ByteCodeFunction, c: &Call, self_arg: Option<Var>) -> Var
{
    let dst = get_dst(func, &c.return_type);
    func.push_destination(None);
    let mut args = Vec::new();
    if let Some(s) = self_arg {
        args.push(s);
    }

    args.extend(c.args.iter().map(|arg| to_bc(func, arg)));
    func.pop_destination();
    func.add(call_instr(&dst, &c.callee.name, args));
    dst
}

fn struct_initializer_to_bc(func: &mut ByteCodeFunction, si: &StructInitializer, dst: &Var)
{
    let init_members = |func: &mut ByteCodeFunction, si: &StructInitializer, dst: &Var| {
        for (idx, expr) in si.member_initializers.iter().enumerate() {
            let v = to_bc(func, expr);
            let member_ptr = get_dst(func, &ptr_type(v.typ.clone()));
            func.add(load_member_instr(&member_ptr, dst, idx));
            func.add(store_instr(&member_ptr, &v));
        }
    };

    if let Type::Sum(ref st) = dst.typ {
        let idx = st.index_of(&si.struct_name).expect("Internal Compiler Error: cannot determine index of sum type case");
        func.add(set_prop_instr(dst, ByteCodeProperty::SumTypeIndex, idx));

        let struct_ptr = func.new_var(ptr_type(st.cases[idx].typ.clone()));
        func.add(load_member_instr(&struct_ptr, &dst, idx));
        init_members(func, si, &struct_ptr);
    } else {
        init_members(func, si, dst);
    }
}

fn block_to_bc(func: &mut ByteCodeFunction, b: &Block) -> Option<Var>
{
    let do_block = |func: &mut ByteCodeFunction, b: &Block| {
        for (idx, e) in b.expressions.iter().enumerate() {
            if idx == b.expressions.len() - 1 {
                expr_to_bc(func, e);
            } else {
                func.push_destination(None);
                expr_to_bc(func, e);
                func.pop_destination();
            }
        }
    };

    if b.typ != Type::Void {
        let dst = get_dst(func, &b.typ);
        func.push_destination(Some(dst.clone()));
        do_block(func, b);
        func.pop_destination();
        Some(dst)
    } else {
        func.push_destination(None);
        do_block(func, b);
        func.pop_destination();
        None
    }
}

fn add_struct_pattern_bindings(p: &StructPattern, struct_var: &Var, func: &mut ByteCodeFunction)
{
    for (idx, name) in p.bindings.iter().enumerate() {
        if name != "_" {
            let v = Var::named(name, ptr_type(p.types[idx].clone()));
            func.add(load_member_instr(&v, struct_var, idx));
            func.add_named_var(v);
        }
    }
}

fn add_binding(func: &mut ByteCodeFunction, b: &LetBinding)
{
    match b.binding_type
    {
        LetBindingType::Name(ref name) => {
            let dst = stack_alloc(func, &b.typ, Some(name));
            func.push_destination(Some(dst));
            expr_to_bc(func, &b.init);
            func.pop_destination();
        },

        LetBindingType::Struct(ref s) => {
            let dst = stack_alloc(func, &b.typ, None);
            func.push_destination(Some(dst.clone()));
            expr_to_bc(func, &b.init);
            add_struct_pattern_bindings(s, &dst, func);
            func.pop_destination();
        },
    }
}

fn let_to_bc(func: &mut ByteCodeFunction, l: &LetExpression) -> Option<Var>
{
    let dst = get_dst(func, &l.typ);
    func.push_scope();
    for b in &l.bindings{
        add_binding(func, b);
    }

    func.push_destination(Some(dst.clone()));
    to_bc(func, &l.expression);
    func.pop_destination();
    func.pop_scope();
    Some(dst)
}

fn to_bc(func: &mut ByteCodeFunction, expr: &Expression) -> Var
{
    expr_to_bc(func, expr).expect("Expression must return a value")
}

fn expr_to_bc(func: &mut ByteCodeFunction, expr: &Expression) -> Option<Var>
{
    match *expr
    {
        Expression::UnaryOp(ref u) => {
            func.push_destination(None);
            let v = to_bc(func, &u.expression);
            func.pop_destination();
            let dst = get_dst(func, &u.typ);
            func.add(unary_op_instr(&dst, u.operator, v));
            Some(dst)
        },

        Expression::BinaryOp(ref op) => {
            func.push_destination(None);
            let l = to_bc(func, &op.left);
            let r = to_bc(func, &op.right);
            func.pop_destination();
            let dst = get_dst(func, &op.typ);
            func.add(binary_op_instr(&dst, op.operator, l, r));
            Some(dst)
        },

        Expression::Literal(Literal::Int(_, v)) => {
            let dst = get_dst(func, &Type::Int);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Int(v)));
            Some(dst)
        },

        Expression::Literal(Literal::Float(_, ref v_str)) => {
            let dst = get_dst(func, &Type::Float);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Float(v_str.clone())));
            Some(dst)
        },

        Expression::Literal(Literal::String(_, ref s))  => {
            let dst = get_dst(func, &string_type());
            func.add(store_lit_instr(&dst, ByteCodeLiteral::String(s.clone())));
            Some(dst)
        },

        Expression::Literal(Literal::Bool(_, v)) => {
            let dst = get_dst(func, &Type::Bool);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Bool(v)));
            Some(dst)
        },

        Expression::Literal(Literal::Char(_, v)) => {
            let dst = get_dst(func, &Type::Char);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Char(v)));
            Some(dst)
        },

        Expression::Literal(Literal::Array(ref a)) => {
            let dst = get_dst(func, &a.array_type);
            func.push_destination(None);
            array_lit_to_bc(func, a, &dst);
            func.pop_destination();
            Some(dst)
        },

        Expression::Call(ref c) => {
            Some(call_to_bc(func, c, None))
        },

        Expression::StructInitializer(ref si) => {
            let dst = get_dst(func, &si.typ);
            func.push_destination(None);
            struct_initializer_to_bc(func, si, &dst);
            func.pop_destination();
            Some(dst)
        },

        Expression::Block(ref b) => {
            block_to_bc(func, b)
        },

        Expression::Let(ref l) => {
            let_to_bc(func, l)
        },

        Expression::LetBindings(ref l) => {
            for b in &l.bindings {
                add_binding(func, b);
            }
            None
        },

        /*
        Expression::NameRef(ref nr) => {
            name_ref_to_bc(func, nr)
        },

        Expression::MemberAccess(ref sma) => {
            let dst = get_dst(func, &sma.typ);
            member_access_to_bc(func, sma, &dst);
            Some(dst)
        },

        Expression::Match(ref m) => {
            Some(match_to_bc(func, m))
        },

        Expression::If(ref i) => {
            let match_expr = i.to_match();
            Some(match_to_bc(func, &match_expr))
        },

        Expression::Lambda(ref l) => {
            let lambda = func_to_bc(&l.sig, &l.expr);
            func.lambdas.push(lambda);
            let dst = get_dst(func, &l.sig.get_type());
            add_set(func, ByteCodeExpression::Func(l.sig.name.clone()), &dst);
            Some(dst)
        },

        Expression::New(ref n) => {
            let dst = get_dst(func, &n.typ);
            let inner_type = n.typ.get_element_type().expect("Empty inner type of new expression");
            add_set(func, ByteCodeExpression::HeapAlloc(inner_type), &dst);
            expr_to_bc(func, &n.inner);
            Some(dst)
        },

        Expression::Delete(ref d) => {
            let to_delete = to_bc(func, &d.inner);
            func.add(Instruction::Delete(to_delete));
            None
        },
        Expression::ArrayGenerator(ref _a) => panic!("NYI"),
        */

        _ => {
            panic!("NYI");
        },
    }
}

fn func_to_bc(sig: &FunctionSignature, expression: &Expression) -> ByteCodeFunction
{
    let mut llfunc = ByteCodeFunction::new(&sig);
    match expr_to_bc(&mut llfunc, &expression)
    {
        Some(var) => {
            llfunc.add(ret_instr(&var));
        },

        None => {
            llfunc.add(Instruction::ReturnVoid);
        }
    }
    llfunc
}

pub fn compile_to_byte_code(md: &Module) -> ByteCodeModule
{
    let mut ll_mod = ByteCodeModule{
        name: md.name.clone(),
        functions: Vec::new(),
    };

    for func in md.externals.values() {
        ll_mod.functions.push(ByteCodeFunction::new(&func.sig));
    }

    for func in md.functions.values() {
        if !func.is_generic() {
            ll_mod.functions.push(func_to_bc(&func.sig, &func.expression));
        }
    }

    ll_mod
}
<commit_msg>bytecode refactoring: new and delete<commit_after>use ast::*;
use bytecode::*;

fn stack_alloc(func: &mut ByteCodeFunction, typ: &Type, name: Option<&str>) -> Var
{
    match name
    {
        Some(n) => {
            let var = Var::named(n, typ.clone());
            func.add_named_var(var.clone());
            if *typ != Type::Void {
                func.add(Instruction::StackAlloc(var.clone()));
            }
            var
        },
        None => {
            let var = func.new_var(typ.clone());
            if *typ != Type::Void {
                func.add(Instruction::StackAlloc(var.clone()));
            }
            var
        }
    }
}

fn get_dst(func: &mut ByteCodeFunction, typ: &Type) -> Var
{
    assert!(*typ != Type::Unknown);
    if let Some(dst) = func.get_destination() {
        if dst.typ != *typ {
            panic!("Internal compiler error: dst.typ ({}) != *typ ({}) in get_dst", dst.typ, typ);
        }
        return dst;
    }

    stack_alloc(func, typ, None)
}

fn array_lit_to_bc(func: &mut ByteCodeFunction, a: &ArrayLiteral, dst: &Var)
{
    let vars = a.elements.iter()
        .map(|e| to_bc(func, e))
        .collect();

    func.add(store_lit_instr(dst, ByteCodeLiteral::Array(vars)));
}

fn call_to_bc(func: &mut ByteCodeFunction, c: &Call, self_arg: Option<Var>) -> Var
{
    let dst = get_dst(func, &c.return_type);
    func.push_destination(None);
    let mut args = Vec::new();
    if let Some(s) = self_arg {
        args.push(s);
    }

    args.extend(c.args.iter().map(|arg| to_bc(func, arg)));
    func.pop_destination();
    func.add(call_instr(&dst, &c.callee.name, args));
    dst
}

fn struct_initializer_to_bc(func: &mut ByteCodeFunction, si: &StructInitializer, dst: &Var)
{
    let init_members = |func: &mut ByteCodeFunction, si: &StructInitializer, dst: &Var| {
        for (idx, expr) in si.member_initializers.iter().enumerate() {
            let v = to_bc(func, expr);
            let member_ptr = get_dst(func, &ptr_type(v.typ.clone()));
            func.add(load_member_instr(&member_ptr, dst, idx));
            func.add(store_instr(&member_ptr, &v));
        }
    };

    if let Type::Sum(ref st) = dst.typ {
        let idx = st.index_of(&si.struct_name).expect("Internal Compiler Error: cannot determine index of sum type case");
        func.add(set_prop_instr(dst, ByteCodeProperty::SumTypeIndex, idx));

        let struct_ptr = func.new_var(ptr_type(st.cases[idx].typ.clone()));
        func.add(load_member_instr(&struct_ptr, &dst, idx));
        init_members(func, si, &struct_ptr);
    } else {
        init_members(func, si, dst);
    }
}

fn block_to_bc(func: &mut ByteCodeFunction, b: &Block) -> Option<Var>
{
    let do_block = |func: &mut ByteCodeFunction, b: &Block| {
        for (idx, e) in b.expressions.iter().enumerate() {
            if idx == b.expressions.len() - 1 {
                expr_to_bc(func, e);
            } else {
                func.push_destination(None);
                expr_to_bc(func, e);
                func.pop_destination();
            }
        }
    };

    if b.typ != Type::Void {
        let dst = get_dst(func, &b.typ);
        func.push_destination(Some(dst.clone()));
        do_block(func, b);
        func.pop_destination();
        Some(dst)
    } else {
        func.push_destination(None);
        do_block(func, b);
        func.pop_destination();
        None
    }
}

fn add_struct_pattern_bindings(p: &StructPattern, struct_var: &Var, func: &mut ByteCodeFunction)
{
    for (idx, name) in p.bindings.iter().enumerate() {
        if name != "_" {
            let v = Var::named(name, ptr_type(p.types[idx].clone()));
            func.add(load_member_instr(&v, struct_var, idx));
            func.add_named_var(v);
        }
    }
}

fn add_binding(func: &mut ByteCodeFunction, b: &LetBinding)
{
    match b.binding_type
    {
        LetBindingType::Name(ref name) => {
            let dst = stack_alloc(func, &b.typ, Some(name));
            func.push_destination(Some(dst));
            expr_to_bc(func, &b.init);
            func.pop_destination();
        },

        LetBindingType::Struct(ref s) => {
            let dst = stack_alloc(func, &b.typ, None);
            func.push_destination(Some(dst.clone()));
            expr_to_bc(func, &b.init);
            add_struct_pattern_bindings(s, &dst, func);
            func.pop_destination();
        },
    }
}

fn let_to_bc(func: &mut ByteCodeFunction, l: &LetExpression) -> Option<Var>
{
    let dst = get_dst(func, &l.typ);
    func.push_scope();
    for b in &l.bindings{
        add_binding(func, b);
    }

    func.push_destination(Some(dst.clone()));
    to_bc(func, &l.expression);
    func.pop_destination();
    func.pop_scope();
    Some(dst)
}

fn to_bc(func: &mut ByteCodeFunction, expr: &Expression) -> Var
{
    expr_to_bc(func, expr).expect("Expression must return a value")
}

fn expr_to_bc(func: &mut ByteCodeFunction, expr: &Expression) -> Option<Var>
{
    match *expr
    {
        Expression::UnaryOp(ref u) => {
            func.push_destination(None);
            let v = to_bc(func, &u.expression);
            func.pop_destination();
            let dst = get_dst(func, &u.typ);
            func.add(unary_op_instr(&dst, u.operator, v));
            Some(dst)
        },

        Expression::BinaryOp(ref op) => {
            func.push_destination(None);
            let l = to_bc(func, &op.left);
            let r = to_bc(func, &op.right);
            func.pop_destination();
            let dst = get_dst(func, &op.typ);
            func.add(binary_op_instr(&dst, op.operator, l, r));
            Some(dst)
        },

        Expression::Literal(Literal::Int(_, v)) => {
            let dst = get_dst(func, &Type::Int);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Int(v)));
            Some(dst)
        },

        Expression::Literal(Literal::Float(_, ref v_str)) => {
            let dst = get_dst(func, &Type::Float);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Float(v_str.clone())));
            Some(dst)
        },

        Expression::Literal(Literal::String(_, ref s))  => {
            let dst = get_dst(func, &string_type());
            func.add(store_lit_instr(&dst, ByteCodeLiteral::String(s.clone())));
            Some(dst)
        },

        Expression::Literal(Literal::Bool(_, v)) => {
            let dst = get_dst(func, &Type::Bool);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Bool(v)));
            Some(dst)
        },

        Expression::Literal(Literal::Char(_, v)) => {
            let dst = get_dst(func, &Type::Char);
            func.add(store_lit_instr(&dst, ByteCodeLiteral::Char(v)));
            Some(dst)
        },

        Expression::Literal(Literal::Array(ref a)) => {
            let dst = get_dst(func, &a.array_type);
            func.push_destination(None);
            array_lit_to_bc(func, a, &dst);
            func.pop_destination();
            Some(dst)
        },

        Expression::Call(ref c) => {
            Some(call_to_bc(func, c, None))
        },

        Expression::StructInitializer(ref si) => {
            let dst = get_dst(func, &si.typ);
            func.push_destination(None);
            struct_initializer_to_bc(func, si, &dst);
            func.pop_destination();
            Some(dst)
        },

        Expression::Block(ref b) => {
            block_to_bc(func, b)
        },

        Expression::Let(ref l) => {
            let_to_bc(func, l)
        },

        Expression::LetBindings(ref l) => {
            for b in &l.bindings {
                add_binding(func, b);
            }
            None
        },

        Expression::New(ref n) => {
            let dst = get_dst(func, &n.typ);
            func.add(Instruction::HeapAlloc(dst.clone()));
            func.push_destination(Some(dst.clone()));
            expr_to_bc(func, &n.inner);
            func.pop_destination();
            Some(dst)
        },

        Expression::Delete(ref d) => {
            let to_delete = to_bc(func, &d.inner);
            func.add(Instruction::Delete(to_delete));
            None
        },

        /*
        Expression::NameRef(ref nr) => {
            name_ref_to_bc(func, nr)
        },

        Expression::MemberAccess(ref sma) => {
            let dst = get_dst(func, &sma.typ);
            member_access_to_bc(func, sma, &dst);
            Some(dst)
        },

        Expression::Match(ref m) => {
            Some(match_to_bc(func, m))
        },

        Expression::If(ref i) => {
            let match_expr = i.to_match();
            Some(match_to_bc(func, &match_expr))
        },

        Expression::Lambda(ref l) => {
            let lambda = func_to_bc(&l.sig, &l.expr);
            func.lambdas.push(lambda);
            let dst = get_dst(func, &l.sig.get_type());
            add_set(func, ByteCodeExpression::Func(l.sig.name.clone()), &dst);
            Some(dst)
        },

        Expression::ArrayGenerator(ref _a) => panic!("NYI"),
        */

        _ => {
            panic!("NYI");
        },
    }
}

fn func_to_bc(sig: &FunctionSignature, expression: &Expression) -> ByteCodeFunction
{
    let mut llfunc = ByteCodeFunction::new(&sig);
    match expr_to_bc(&mut llfunc, &expression)
    {
        Some(var) => {
            llfunc.add(ret_instr(&var));
        },

        None => {
            llfunc.add(Instruction::ReturnVoid);
        }
    }
    llfunc
}

pub fn compile_to_byte_code(md: &Module) -> ByteCodeModule
{
    let mut ll_mod = ByteCodeModule{
        name: md.name.clone(),
        functions: Vec::new(),
    };

    for func in md.externals.values() {
        ll_mod.functions.push(ByteCodeFunction::new(&func.sig));
    }

    for func in md.functions.values() {
        if !func.is_generic() {
            ll_mod.functions.push(func_to_bc(&func.sig, &func.expression));
        }
    }

    ll_mod
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use ffi;
use LuaContext;

use AsLua;
use AsMutLua;
use Push;
use PushGuard;
use LuaRead;

/// Represents a table stored in the Lua context.
///
/// Loading this type mutably borrows the Lua context.
pub struct LuaTable<L> {
    table: L,
    index: i32
}

unsafe impl<L> AsLua for LuaTable<L> where L: AsLua {
    fn as_lua(&self) -> LuaContext {
        self.table.as_lua()
    }
}

unsafe impl<L> AsMutLua for LuaTable<L> where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.table.as_mut_lua()
    }
}

impl<L> LuaRead<L> for LuaTable<L> where L: AsMutLua {
    fn lua_read_at_position(mut lua: L, index: i32) -> Result<LuaTable<L>, L> {
        assert!(index < 0); // FIXME:
        if unsafe { ffi::lua_istable(lua.as_mut_lua().0, index) } {
            Ok(LuaTable { table: lua, index: index })
        } else {
            Err(lua)
        }
    }
}

/// Iterator that enumerates the content of a Lua table.
// while the LuaTableIterator is active, the current key is constantly pushed over the table
pub struct LuaTableIterator<'t, L: 't, K, V> where L: AsMutLua {
    table: &'t mut LuaTable<L>,
    finished: bool,     // if true, the key is not on the stack anymore
    marker: PhantomData<(K, V)>,
}

unsafe impl<'t, L, K, V> AsLua for LuaTableIterator<'t, L, K, V> where L: AsMutLua {
    fn as_lua(&self) -> LuaContext {
        self.table.as_lua()
    }
}

unsafe impl<'t, L, K, V> AsMutLua for LuaTableIterator<'t, L, K, V> where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.table.as_mut_lua()
    }
}

impl<L> LuaTable<L> where L: AsMutLua {
    /// Destroys the LuaTable and returns its inner Lua context. Useful when it takes Lua by value.
    pub fn into_inner(self) -> L {
        self.table
    }

    /// Iterates over the elements inside the table.
    pub fn iter<K, V>(&mut self) -> LuaTableIterator<L, K, V> {
        unsafe { ffi::lua_pushnil(self.table.as_mut_lua().0) };

        LuaTableIterator {
            table: self,
            finished: false,
            marker: PhantomData,
        }
    }

    /// Loads a value in the table given its index.
    pub fn get<'a, R, I>(&'a mut self, index: I) -> Option<R>
                         where R: LuaRead<PushGuard<&'a mut LuaTable<L>>>,
                               I: for<'b> Push<&'b mut &'a mut LuaTable<L>>
    {
        let mut me = self;
        index.push_to_lua(&mut me).forget();
        unsafe { ffi::lua_gettable(me.as_mut_lua().0, -1 + me.index); }
        if unsafe { ffi::lua_isnil(me.as_lua().0, -1) } {
            let _guard = PushGuard { lua: me, size: 1 };
            return None;
        }
        let guard = PushGuard { lua: me, size: 1 };
        LuaRead::lua_read(guard).ok()
    }

    /// Loads a value in the table, with the result capturing the table by value.
    pub fn into_get<'a, R, I>(self, index: I) -> Result<R, PushGuard<Self>>
        where R: LuaRead<PushGuard<LuaTable<L>>>,
              I: for<'b> Push<&'b mut LuaTable<L>>
    {
        let mut me = self;
        index.push_to_lua(&mut me).forget();
        unsafe { ffi::lua_gettable(me.as_mut_lua().0, -1 + me.index); }
        let is_nil = unsafe { ffi::lua_isnil(me.as_mut_lua().0, -1) };
        let guard = PushGuard { lua: me, size: 1 };
        if is_nil {
            Err(guard)
        } else {
            LuaRead::lua_read(guard)
        }
    }

    /// Inserts or modifies an elements of the table.
    pub fn set<'s, I, V>(&'s mut self, index: I, value: V)
                         where I: for<'a> Push<&'a mut &'s mut LuaTable<L>>,
                               V: for<'a> Push<&'a mut &'s mut LuaTable<L>>
    {
        let mut me = self;
        index.push_to_lua(&mut me).forget();
        value.push_to_lua(&mut me).forget();
        unsafe { ffi::lua_settable(me.as_mut_lua().0, -2 + me.index); }
    }

    /// Inserts an empty array, then loads it.
    pub fn empty_array<'s, I>(&'s mut self, index: I) -> LuaTable<PushGuard<&'s mut LuaTable<L>>>
                              where I: for<'a> Push<&'a mut &'s mut LuaTable<L>> + Clone
    {
        // TODO: cleaner implementation
        let mut me = self;
        index.clone().push_to_lua(&mut me).forget();
        Vec::<u8>::with_capacity(0).push_to_lua(&mut me).forget();
        unsafe { ffi::lua_settable(me.as_mut_lua().0, -2 + me.index); }

        me.get(index).unwrap()
    }

    /// Obtains or create the metatable of the table.
    pub fn get_or_create_metatable(mut self) -> LuaTable<PushGuard<L>> {
        let result = unsafe { ffi::lua_getmetatable(self.table.as_mut_lua().0, self.index) };

        if result == 0 {
            unsafe {
                ffi::lua_newtable(self.table.as_mut_lua().0);
                ffi::lua_setmetatable(self.table.as_mut_lua().0, -1 + self.index);
                let r = ffi::lua_getmetatable(self.table.as_mut_lua().0, self.index);
                assert!(r != 0);
            }
        }

        LuaTable {
            table: PushGuard { lua: self.table, size: 1 },
            index: -1 // After creating the metatable, it will be on top of the stack.
        }
    }
}

impl<'t, L, K, V> Iterator for LuaTableIterator<'t, L, K, V>
                  where L: AsMutLua + 't,
                        K: for<'i, 'j> LuaRead<&'i mut &'j mut LuaTableIterator<'t, L, K, V>> + 'static,
                        V: for<'i, 'j> LuaRead<&'i mut &'j mut LuaTableIterator<'t, L, K, V>> + 'static
{
    type Item = Option<(K, V)>;

    fn next(&mut self) -> Option<Option<(K,V)>> {
        if self.finished {
            return None;
        }

        // this call pushes the next key and value on the stack
        if unsafe { ffi::lua_next(self.table.as_mut_lua().0, -1 + self.table.index) } == 0 {
            self.finished = true;
            return None;
        }

        let mut me = self;
        let key = LuaRead::lua_read_at_position(&mut me, -2).ok();
        let value = LuaRead::lua_read_at_position(&mut me, -1).ok();

        // removing the value, leaving only the key on the top of the stack
        unsafe { ffi::lua_pop(me.table.as_mut_lua().0, 1) };

        //
        if key.is_none() || value.is_none() {
            Some(None)
        } else {
            Some(Some((key.unwrap(), value.unwrap())))
        }
    }
}

impl<'t, L, K, V> Drop for LuaTableIterator<'t, L, K, V> where L: AsMutLua + 't {
    fn drop(&mut self) {
        if !self.finished {
            unsafe { ffi::lua_pop(self.table.table.as_mut_lua().0, 1) }
        }
    }
}
<commit_msg>allow tables to be loaded from positive stack indices<commit_after>use std::marker::PhantomData;

use ffi;
use LuaContext;

use AsLua;
use AsMutLua;
use Push;
use PushGuard;
use LuaRead;

/// Represents a table stored in the Lua context.
///
/// Loading this type mutably borrows the Lua context.
pub struct LuaTable<L> {
    table: L,
    index: i32
}
impl<L> LuaTable<L> {
    /// Return the index on the stack of this table, assuming -(offset - 1)
    /// items have been pushed to the stack since it was loaded.
    fn offset(&self, offset: i32) -> i32 {
        if self.index < 0 {
            // If this table was indexed from the top of the stack, its current
            // index will have been pushed down by the newly-pushed items.
            self.index + offset
        } else {
            // If this table was indexed from the bottom of the stack, its
            // current position will be unchanged.
            self.index
        }
    }
}

unsafe impl<L> AsLua for LuaTable<L> where L: AsLua {
    fn as_lua(&self) -> LuaContext {
        self.table.as_lua()
    }
}

unsafe impl<L> AsMutLua for LuaTable<L> where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.table.as_mut_lua()
    }
}

impl<L> LuaRead<L> for LuaTable<L> where L: AsMutLua {
    fn lua_read_at_position(mut lua: L, index: i32) -> Result<LuaTable<L>, L> {
        if unsafe { ffi::lua_istable(lua.as_mut_lua().0, index) } {
            Ok(LuaTable { table: lua, index: index })
        } else {
            Err(lua)
        }
    }
}

/// Iterator that enumerates the content of a Lua table.
// while the LuaTableIterator is active, the current key is constantly pushed over the table
pub struct LuaTableIterator<'t, L: 't, K, V> where L: AsMutLua {
    table: &'t mut LuaTable<L>,
    finished: bool,     // if true, the key is not on the stack anymore
    marker: PhantomData<(K, V)>,
}

unsafe impl<'t, L, K, V> AsLua for LuaTableIterator<'t, L, K, V> where L: AsMutLua {
    fn as_lua(&self) -> LuaContext {
        self.table.as_lua()
    }
}

unsafe impl<'t, L, K, V> AsMutLua for LuaTableIterator<'t, L, K, V> where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.table.as_mut_lua()
    }
}

impl<L> LuaTable<L> where L: AsMutLua {
    /// Destroys the LuaTable and returns its inner Lua context. Useful when it takes Lua by value.
    pub fn into_inner(self) -> L {
        self.table
    }

    /// Iterates over the elements inside the table.
    pub fn iter<K, V>(&mut self) -> LuaTableIterator<L, K, V> {
        unsafe { ffi::lua_pushnil(self.table.as_mut_lua().0) };

        LuaTableIterator {
            table: self,
            finished: false,
            marker: PhantomData,
        }
    }

    /// Loads a value in the table given its index.
    pub fn get<'a, R, I>(&'a mut self, index: I) -> Option<R>
                         where R: LuaRead<PushGuard<&'a mut LuaTable<L>>>,
                               I: for<'b> Push<&'b mut &'a mut LuaTable<L>>
    {
        let mut me = self;
        index.push_to_lua(&mut me).forget();
        unsafe { ffi::lua_gettable(me.as_mut_lua().0, me.offset(-1)); }
        if unsafe { ffi::lua_isnil(me.as_lua().0, -1) } {
            let _guard = PushGuard { lua: me, size: 1 };
            return None;
        }
        let guard = PushGuard { lua: me, size: 1 };
        LuaRead::lua_read(guard).ok()
    }

    /// Loads a value in the table, with the result capturing the table by value.
    pub fn into_get<'a, R, I>(self, index: I) -> Result<R, PushGuard<Self>>
        where R: LuaRead<PushGuard<LuaTable<L>>>,
              I: for<'b> Push<&'b mut LuaTable<L>>
    {
        let mut me = self;
        index.push_to_lua(&mut me).forget();
        unsafe { ffi::lua_gettable(me.as_mut_lua().0, me.offset(-1)); }
        let is_nil = unsafe { ffi::lua_isnil(me.as_mut_lua().0, -1) };
        let guard = PushGuard { lua: me, size: 1 };
        if is_nil {
            Err(guard)
        } else {
            LuaRead::lua_read(guard)
        }
    }

    /// Inserts or modifies an elements of the table.
    pub fn set<'s, I, V>(&'s mut self, index: I, value: V)
                         where I: for<'a> Push<&'a mut &'s mut LuaTable<L>>,
                               V: for<'a> Push<&'a mut &'s mut LuaTable<L>>
    {
        let mut me = self;
        index.push_to_lua(&mut me).forget();
        value.push_to_lua(&mut me).forget();
        unsafe { ffi::lua_settable(me.as_mut_lua().0, me.offset(-2)); }
    }

    /// Inserts an empty array, then loads it.
    pub fn empty_array<'s, I>(&'s mut self, index: I) -> LuaTable<PushGuard<&'s mut LuaTable<L>>>
                              where I: for<'a> Push<&'a mut &'s mut LuaTable<L>> + Clone
    {
        // TODO: cleaner implementation
        let mut me = self;
        index.clone().push_to_lua(&mut me).forget();
        Vec::<u8>::with_capacity(0).push_to_lua(&mut me).forget();
        unsafe { ffi::lua_settable(me.as_mut_lua().0, me.offset(-2)); }

        me.get(index).unwrap()
    }

    /// Obtains or create the metatable of the table.
    pub fn get_or_create_metatable(mut self) -> LuaTable<PushGuard<L>> {
        let result = unsafe { ffi::lua_getmetatable(self.table.as_mut_lua().0, self.index) };

        if result == 0 {
            unsafe {
                ffi::lua_newtable(self.table.as_mut_lua().0);
                ffi::lua_setmetatable(self.table.as_mut_lua().0, self.offset(-1));
                let r = ffi::lua_getmetatable(self.table.as_mut_lua().0, self.index);
                assert!(r != 0);
            }
        }

        LuaTable {
            table: PushGuard { lua: self.table, size: 1 },
            index: -1 // After creating the metatable, it will be on top of the stack.
        }
    }
}

impl<'t, L, K, V> Iterator for LuaTableIterator<'t, L, K, V>
                  where L: AsMutLua + 't,
                        K: for<'i, 'j> LuaRead<&'i mut &'j mut LuaTableIterator<'t, L, K, V>> + 'static,
                        V: for<'i, 'j> LuaRead<&'i mut &'j mut LuaTableIterator<'t, L, K, V>> + 'static
{
    type Item = Option<(K, V)>;

    fn next(&mut self) -> Option<Option<(K,V)>> {
        if self.finished {
            return None;
        }

        // this call pushes the next key and value on the stack
        if unsafe { ffi::lua_next(self.table.as_mut_lua().0, self.table.offset(-1)) } == 0 {
            self.finished = true;
            return None;
        }

        let mut me = self;
        let key = LuaRead::lua_read_at_position(&mut me, -2).ok();
        let value = LuaRead::lua_read_at_position(&mut me, -1).ok();

        // removing the value, leaving only the key on the top of the stack
        unsafe { ffi::lua_pop(me.table.as_mut_lua().0, 1) };

        //
        if key.is_none() || value.is_none() {
            Some(None)
        } else {
            Some(Some((key.unwrap(), value.unwrap())))
        }
    }
}

impl<'t, L, K, V> Drop for LuaTableIterator<'t, L, K, V> where L: AsMutLua + 't {
    fn drop(&mut self) {
        if !self.finished {
            unsafe { ffi::lua_pop(self.table.table.as_mut_lua().0, 1) }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
//! scope.
//!
//! # Examples
//!
//! Creating a box:
//!
//! ```
//! let x = Box::new(5);
//! ```
//!
//! Creating a recursive data structure:
//!
//! ```
//! #[derive(Debug)]
//! enum List<T> {
//!     Cons(T, Box<List<T>>),
//!     Nil,
//! }
//!
//! fn main() {
//!     let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
//!     println!("{:?}", list);
//! }
//! ```
//!
//! This will print `Cons(1, Box(Cons(2, Box(Nil))))`.
//!
//! Recursive structures must be boxed, because if the definition of `Cons` looked like this:
//!
//! ```rust,ignore
//! Cons(T, List<T>),
//! ```
//!
//! It wouldn't work. This is because the size of a `List` depends on how many elements are in the
//! list, and so we don't know how much memory to allocate for a `Cons`. By introducing a `Box`,
//! which has a defined size, we know how big `Cons` needs to be.

#![stable(feature = "rust1", since = "1.0.0")]

use core::prelude::*;

use core::any::Any;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::{Unique};
use core::raw::{TraitObject};

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```
/// # #![feature(alloc)]
/// #![feature(box_syntax)]
/// use std::boxed::HEAP;
///
/// fn main() {
///     let foo = box(HEAP) 5;
///     let foo = box 5;
/// }
/// ```
#[lang = "exchange_heap"]
#[unstable(feature = "alloc",
           reason = "may be renamed; uncertain about custom allocator design")]
pub static HEAP: () = ();

/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
#[lang = "owned_box"]
#[stable(feature = "rust1", since = "1.0.0")]
#[fundamental]
pub struct Box<T>(Unique<T>);

impl<T> Box<T> {
    /// Allocates memory on the heap and then moves `x` into it.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline(always)]
    pub fn new(x: T) -> Box<T> {
        box x
    }
}

impl<T : ?Sized> Box<T> {
    /// Constructs a box from the raw pointer.
    ///
    /// After this function call, pointer is owned by resulting box.
    /// In particular, it means that `Box` destructor calls destructor
    /// of `T` and releases memory. Since the way `Box` allocates and
    /// releases memory is unspecified, the only valid pointer to pass
    /// to this function is the one taken from another `Box` with
    /// `boxed::into_raw` function.
    ///
    /// Function is unsafe, because improper use of this function may
    /// lead to memory problems like double-free, for example if the
    /// function is called twice on the same raw pointer.
    #[unstable(feature = "alloc",
               reason = "may be renamed or moved out of Box scope")]
    #[inline]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        mem::transmute(raw)
    }
}

/// Consumes the `Box`, returning the wrapped raw pointer.
///
/// After call to this function, caller is responsible for the memory
/// previously managed by `Box`, in particular caller should properly
/// destroy `T` and release memory. The proper way to do it is to
/// convert pointer back to `Box` with `Box::from_raw` function, because
/// `Box` does not specify, how memory is allocated.
///
/// Function is unsafe, because result of this function is no longer
/// automatically managed that may lead to memory or other resource
/// leak.
///
/// # Examples
/// ```
/// # #![feature(alloc)]
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// let raw = unsafe { boxed::into_raw(seventeen) };
/// let boxed_again = unsafe { Box::from_raw(raw) };
/// ```
#[unstable(feature = "alloc",
           reason = "may be renamed")]
#[inline]
pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
    mem::transmute(b)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<T> { box Default::default() }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Box<T> {
    /// Returns a new box with a `clone()` of this box's contents.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let y = x.clone();
    /// ```
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Copies `source`'s contents into `self` without creating a new allocation.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![feature(alloc, core)]
    /// let x = Box::new(5);
    /// let mut y = Box::new(10);
    ///
    /// y.clone_from(&x);
    ///
    /// assert_eq!(*y, 5);
    /// ```
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

impl Box<Any> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let raw = into_raw(self);
                let to: TraitObject =
                    mem::transmute::<*mut Any, TraitObject>(raw);

                // Extract the data pointer
                Ok(Box::from_raw(to.data as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

impl Box<Any + Send> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
        <Box<Any>>::downcast(self).map_err(|s| unsafe {
            // reapply the Send marker
            mem::transmute::<Box<Any>, Box<Any + Send>>(s)
        })
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Pointer for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Uniq directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &**self;
        fmt::Pointer::fmt(&ptr, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
    type Target = T;

    fn deref(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for Box<T> {
    fn deref_mut(&mut self) -> &mut T { &mut **self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for Box<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> { (**self).next() }
    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
    fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}

/// `FnBox` is a version of the `FnOnce` intended for use with boxed
/// closure objects. The idea is that where one would normally store a
/// `Box<FnOnce()>` in a data structure, you should use
/// `Box<FnBox()>`. The two traits behave essentially the same, except
/// that a `FnBox` closure can only be called if it is boxed. (Note
/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
/// closures become directly usable.)
///
/// ### Example
///
/// Here is a snippet of code which creates a hashmap full of boxed
/// once closures and then removes them one by one, calling each
/// closure as it is removed. Note that the type of the closures
/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
/// -> i32>`.
///
/// ```
/// #![feature(core)]
///
/// use std::boxed::FnBox;
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
///     let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
///     map.insert(1, Box::new(|| 22));
///     map.insert(2, Box::new(|| 44));
///     map
/// }
///
/// fn main() {
///     let mut map = make_map();
///     for i in &[1, 2] {
///         let f = map.remove(&i).unwrap();
///         assert_eq!(f(), i * 22);
///     }
/// }
/// ```
#[rustc_paren_sugar]
#[unstable(feature = "core", reason = "Newly introduced")]
pub trait FnBox<A> {
    type Output;

    fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

impl<A,F> FnBox<A> for F
    where F: FnOnce<A>
{
    type Output = F::Output;

    fn call_box(self: Box<F>, args: A) -> F::Output {
        self.call_once(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}
<commit_msg>Update with correct output.<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
//! scope.
//!
//! # Examples
//!
//! Creating a box:
//!
//! ```
//! let x = Box::new(5);
//! ```
//!
//! Creating a recursive data structure:
//!
//! ```
//! #[derive(Debug)]
//! enum List<T> {
//!     Cons(T, Box<List<T>>),
//!     Nil,
//! }
//!
//! fn main() {
//!     let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
//!     println!("{:?}", list);
//! }
//! ```
//!
//! This will print `Cons(1, Cons(2, Nil))`.
//!
//! Recursive structures must be boxed, because if the definition of `Cons` looked like this:
//!
//! ```rust,ignore
//! Cons(T, List<T>),
//! ```
//!
//! It wouldn't work. This is because the size of a `List` depends on how many elements are in the
//! list, and so we don't know how much memory to allocate for a `Cons`. By introducing a `Box`,
//! which has a defined size, we know how big `Cons` needs to be.

#![stable(feature = "rust1", since = "1.0.0")]

use core::prelude::*;

use core::any::Any;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::{Unique};
use core::raw::{TraitObject};

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```
/// # #![feature(alloc)]
/// #![feature(box_syntax)]
/// use std::boxed::HEAP;
///
/// fn main() {
///     let foo = box(HEAP) 5;
///     let foo = box 5;
/// }
/// ```
#[lang = "exchange_heap"]
#[unstable(feature = "alloc",
           reason = "may be renamed; uncertain about custom allocator design")]
pub static HEAP: () = ();

/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
#[lang = "owned_box"]
#[stable(feature = "rust1", since = "1.0.0")]
#[fundamental]
pub struct Box<T>(Unique<T>);

impl<T> Box<T> {
    /// Allocates memory on the heap and then moves `x` into it.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline(always)]
    pub fn new(x: T) -> Box<T> {
        box x
    }
}

impl<T : ?Sized> Box<T> {
    /// Constructs a box from the raw pointer.
    ///
    /// After this function call, pointer is owned by resulting box.
    /// In particular, it means that `Box` destructor calls destructor
    /// of `T` and releases memory. Since the way `Box` allocates and
    /// releases memory is unspecified, the only valid pointer to pass
    /// to this function is the one taken from another `Box` with
    /// `boxed::into_raw` function.
    ///
    /// Function is unsafe, because improper use of this function may
    /// lead to memory problems like double-free, for example if the
    /// function is called twice on the same raw pointer.
    #[unstable(feature = "alloc",
               reason = "may be renamed or moved out of Box scope")]
    #[inline]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        mem::transmute(raw)
    }
}

/// Consumes the `Box`, returning the wrapped raw pointer.
///
/// After call to this function, caller is responsible for the memory
/// previously managed by `Box`, in particular caller should properly
/// destroy `T` and release memory. The proper way to do it is to
/// convert pointer back to `Box` with `Box::from_raw` function, because
/// `Box` does not specify, how memory is allocated.
///
/// Function is unsafe, because result of this function is no longer
/// automatically managed that may lead to memory or other resource
/// leak.
///
/// # Examples
/// ```
/// # #![feature(alloc)]
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// let raw = unsafe { boxed::into_raw(seventeen) };
/// let boxed_again = unsafe { Box::from_raw(raw) };
/// ```
#[unstable(feature = "alloc",
           reason = "may be renamed")]
#[inline]
pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
    mem::transmute(b)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<T> { box Default::default() }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Box<T> {
    /// Returns a new box with a `clone()` of this box's contents.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let y = x.clone();
    /// ```
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Copies `source`'s contents into `self` without creating a new allocation.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![feature(alloc, core)]
    /// let x = Box::new(5);
    /// let mut y = Box::new(10);
    ///
    /// y.clone_from(&x);
    ///
    /// assert_eq!(*y, 5);
    /// ```
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

impl Box<Any> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let raw = into_raw(self);
                let to: TraitObject =
                    mem::transmute::<*mut Any, TraitObject>(raw);

                // Extract the data pointer
                Ok(Box::from_raw(to.data as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

impl Box<Any + Send> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
        <Box<Any>>::downcast(self).map_err(|s| unsafe {
            // reapply the Send marker
            mem::transmute::<Box<Any>, Box<Any + Send>>(s)
        })
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Pointer for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Uniq directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &**self;
        fmt::Pointer::fmt(&ptr, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
    type Target = T;

    fn deref(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for Box<T> {
    fn deref_mut(&mut self) -> &mut T { &mut **self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for Box<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> { (**self).next() }
    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
    fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}

/// `FnBox` is a version of the `FnOnce` intended for use with boxed
/// closure objects. The idea is that where one would normally store a
/// `Box<FnOnce()>` in a data structure, you should use
/// `Box<FnBox()>`. The two traits behave essentially the same, except
/// that a `FnBox` closure can only be called if it is boxed. (Note
/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
/// closures become directly usable.)
///
/// ### Example
///
/// Here is a snippet of code which creates a hashmap full of boxed
/// once closures and then removes them one by one, calling each
/// closure as it is removed. Note that the type of the closures
/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
/// -> i32>`.
///
/// ```
/// #![feature(core)]
///
/// use std::boxed::FnBox;
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
///     let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
///     map.insert(1, Box::new(|| 22));
///     map.insert(2, Box::new(|| 44));
///     map
/// }
///
/// fn main() {
///     let mut map = make_map();
///     for i in &[1, 2] {
///         let f = map.remove(&i).unwrap();
///         assert_eq!(f(), i * 22);
///     }
/// }
/// ```
#[rustc_paren_sugar]
#[unstable(feature = "core", reason = "Newly introduced")]
pub trait FnBox<A> {
    type Output;

    fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

impl<A,F> FnBox<A> for F
    where F: FnOnce<A>
{
    type Output = F::Output;

    fn call_box(self: Box<F>, args: A) -> F::Output {
        self.call_once(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The `ToStr` trait for converting to strings

*/

use str;
use str::OwnedStr;
use hashmap::HashMap;
use hashmap::HashSet;
use container::Map;
use hash::Hash;
use cmp::Eq;

pub trait ToStr {
    fn to_str(&self) -> ~str;
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait ToStrConsume {
    // Cosume and convert to a string.
    fn to_str_consume(self) -> ~str;
}

impl ToStr for bool {
    #[inline(always)]
    fn to_str(&self) -> ~str { ::bool::to_str(*self) }
}
impl ToStr for () {
    #[inline(always)]
    fn to_str(&self) -> ~str { ~"()" }
}

impl<A:ToStr> ToStr for (A,) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        match *self {
            (ref a,) => {
                ~"(" + a.to_str() + ~", " + ~")"
            }
        }
    }
}

impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{", first = true;
        for self.each |key, value| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(key.to_str());
            acc.push_str(": ");
            acc.push_str(value.to_str());
        }
        acc.push_char('}');
        acc
    }
}

impl<A:ToStr,B:ToStr> ToStr for (A, B) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b) = self;
        match *self {
            (ref a, ref b) => {
                ~"(" + a.to_str() + ~", " + b.to_str() + ~")"
            }
        }
    }
}

impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b, ref c) = self;
        match *self {
            (ref a, ref b, ref c) => {
                fmt!("(%s, %s, %s)",
                    (*a).to_str(),
                    (*b).to_str(),
                    (*c).to_str()
                )
            }
        }
    }
}

impl<'self,A:ToStr> ToStr for &'self [A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for ~[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for @[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

#[cfg(test)]
#[allow(non_implicitly_copyable_typarams)]
mod tests {
    use hashmap::HashMap;
    #[test]
    fn test_simple_types() {
        assert!(1i.to_str() == ~"1");
        assert!((-1i).to_str() == ~"-1");
        assert!(200u.to_str() == ~"200");
        assert!(2u8.to_str() == ~"2");
        assert!(true.to_str() == ~"true");
        assert!(false.to_str() == ~"false");
        assert!(().to_str() == ~"()");
        assert!((~"hi").to_str() == ~"hi");
        assert!((@"hi").to_str() == ~"hi");
    }

    #[test]
    fn test_tuple_types() {
        assert!((1, 2).to_str() == ~"(1, 2)");
        assert!((~"a", ~"b", false).to_str() == ~"(a, b, false)");
        assert!(((), ((), 100)).to_str() == ~"((), ((), 100))");
    }

    #[test]
    fn test_vectors() {
        let x: ~[int] = ~[];
        assert!(x.to_str() == ~"[]");
        assert!((~[1]).to_str() == ~"[1]");
        assert!((~[1, 2, 3]).to_str() == ~"[1, 2, 3]");
        assert!((~[~[], ~[1], ~[1, 1]]).to_str() ==
               ~"[[], [1], [1, 1]]");
    }

    #[test]
    fn test_hashmap() {
        let mut table: HashMap<int, int> = HashMap::new();
        let empty: HashMap<int, int> = HashMap::new();

        table.insert(3, 4);
        table.insert(1, 2);

        let table_str = table.to_str();

        assert!(table_str == ~"{1: 2, 3: 4}" || table_str == ~"{3: 4, 1: 2}");
        assert!(empty.to_str() == ~"{}");
    }
}<commit_msg>Add str representation for HashSet.<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The `ToStr` trait for converting to strings

*/

use str;
use str::OwnedStr;
use hashmap::HashMap;
use hashmap::HashSet;
use container::Map;
use hash::Hash;
use cmp::Eq;

pub trait ToStr {
    fn to_str(&self) -> ~str;
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait ToStrConsume {
    // Cosume and convert to a string.
    fn to_str_consume(self) -> ~str;
}

impl ToStr for bool {
    #[inline(always)]
    fn to_str(&self) -> ~str { ::bool::to_str(*self) }
}
impl ToStr for () {
    #[inline(always)]
    fn to_str(&self) -> ~str { ~"()" }
}

impl<A:ToStr> ToStr for (A,) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        match *self {
            (ref a,) => {
                ~"(" + a.to_str() + ~", " + ~")"
            }
        }
    }
}

impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{", first = true;
        for self.each |key, value| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(key.to_str());
            acc.push_str(": ");
            acc.push_str(value.to_str());
        }
        acc.push_char('}');
        acc
    }
}

impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
    #[inline(always)]
    fn to_str(&self) -> ~str {
    let mut acc = ~"{", first = true;
    for self.each |element| {
        if first {
            first = false;
        }
        else {
            acc.push_str(", ");
        }
        acc.push_str(element.to_str());
    }
    acc.push_char('}');
    acc
    }
}

impl<A:ToStr,B:ToStr> ToStr for (A, B) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b) = self;
        match *self {
            (ref a, ref b) => {
                ~"(" + a.to_str() + ~", " + b.to_str() + ~")"
            }
        }
    }
}

impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b, ref c) = self;
        match *self {
            (ref a, ref b, ref c) => {
                fmt!("(%s, %s, %s)",
                    (*a).to_str(),
                    (*b).to_str(),
                    (*c).to_str()
                )
            }
        }
    }
}

impl<'self,A:ToStr> ToStr for &'self [A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for ~[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for @[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

#[cfg(test)]
#[allow(non_implicitly_copyable_typarams)]
mod tests {
    use hashmap::HashMap;
    #[test]
    fn test_simple_types() {
        assert!(1i.to_str() == ~"1");
        assert!((-1i).to_str() == ~"-1");
        assert!(200u.to_str() == ~"200");
        assert!(2u8.to_str() == ~"2");
        assert!(true.to_str() == ~"true");
        assert!(false.to_str() == ~"false");
        assert!(().to_str() == ~"()");
        assert!((~"hi").to_str() == ~"hi");
        assert!((@"hi").to_str() == ~"hi");
    }

    #[test]
    fn test_tuple_types() {
        assert!((1, 2).to_str() == ~"(1, 2)");
        assert!((~"a", ~"b", false).to_str() == ~"(a, b, false)");
        assert!(((), ((), 100)).to_str() == ~"((), ((), 100))");
    }

    #[test]
    fn test_vectors() {
        let x: ~[int] = ~[];
        assert!(x.to_str() == ~"[]");
        assert!((~[1]).to_str() == ~"[1]");
        assert!((~[1, 2, 3]).to_str() == ~"[1, 2, 3]");
        assert!((~[~[], ~[1], ~[1, 1]]).to_str() ==
               ~"[[], [1], [1, 1]]");
    }

    #[test]
    fn test_hashmap() {
        let mut table: HashMap<int, int> = HashMap::new();
        let empty: HashMap<int, int> = HashMap::new();

        table.insert(3, 4);
        table.insert(1, 2);

        let table_str = table.to_str();

        assert!(table_str == ~"{1: 2, 3: 4}" || table_str == ~"{3: 4, 1: 2}");
        assert!(empty.to_str() == ~"{}");
    }
}<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust prelude
//!
//! Because `std` is required by most serious Rust software, it is
//! imported at the topmost level of every crate by default, as if the
//! first line of each crate was
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! This means that the contents of std can be accessed from any context
//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`,
//! etc.
//!
//! Additionally, `std` contains a `prelude` module that reexports many of the
//! most common traits, types and functions. The contents of the prelude are
//! imported into every *module* by default.  Implicitly, all modules behave as if
//! they contained the following prologue:
//!
//! ```ignore
//! use std::prelude::*;
//! ```
//!
//! The prelude is primarily concerned with exporting *traits* that are so
//! pervasive that it would be obnoxious to import for every use, particularly
//! those that define methods on primitive types. It does include a few
//! particularly useful standalone functions, like `from_str`, `range`, and
//! `drop`, `spawn`, and `channel`.

#![experimental]

// Reexported core operators
#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync};
#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
#[doc(no_inline)] pub use ops::{Shl, Shr};
#[doc(no_inline)] pub use ops::{Index, IndexMut};
#[doc(no_inline)] pub use ops::{Slice, SliceMut};
#[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce};
#[doc(no_inline)] pub use option::{Option, Some, None};
#[doc(no_inline)] pub use result::{Result, Ok, Err};

// Reexported functions
#[doc(no_inline)] pub use from_str::from_str;
#[doc(no_inline)] pub use iter::range;
#[doc(no_inline)] pub use mem::drop;

// Reexported types and traits

#[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
#[doc(no_inline)] pub use ascii::IntoBytes;
#[doc(no_inline)] pub use c_str::ToCStr;
#[doc(no_inline)] pub use char::{Char, UnicodeChar};
#[doc(no_inline)] pub use clone::Clone;
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
#[doc(no_inline)] pub use collections::{Collection, Mutable, Map, MutableMap, MutableSeq};
#[doc(no_inline)] pub use collections::{Set, MutableSet};
#[doc(no_inline)] pub use iter::{FromIterator, Extendable, ExactSize};
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
#[doc(no_inline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
#[doc(no_inline)] pub use boxed::Box;
#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
#[doc(no_inline)] pub use ptr::RawPtr;
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrSlice};
#[doc(no_inline)] pub use to_string::{ToString, IntoStr};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
#[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice};
#[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice};
#[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
#[doc(no_inline)] pub use slice::{AsSlice, VectorVector, BoxedSlice};
#[doc(no_inline)] pub use slice::MutableSliceAllocating;
#[doc(no_inline)] pub use string::String;
#[doc(no_inline)] pub use vec::Vec;

// Reexported runtime types
#[doc(no_inline)] pub use comm::{sync_channel, channel};
#[doc(no_inline)] pub use comm::{SyncSender, Sender, Receiver};
#[doc(no_inline)] pub use task::spawn;
<commit_msg>rollup merge of #18393 : aochagavia/prelude<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust prelude
//!
//! Because `std` is required by most serious Rust software, it is
//! imported at the topmost level of every crate by default, as if the
//! first line of each crate was
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! This means that the contents of std can be accessed from any context
//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`,
//! etc.
//!
//! Additionally, `std` contains a `prelude` module that reexports many of the
//! most common traits, types and functions. The contents of the prelude are
//! imported into every *module* by default.  Implicitly, all modules behave as if
//! they contained the following prologue:
//!
//! ```ignore
//! use std::prelude::*;
//! ```
//!
//! The prelude is primarily concerned with exporting *traits* that are so
//! pervasive that it would be obnoxious to import for every use, particularly
//! those that define methods on primitive types. It does include a few
//! particularly useful standalone functions, like `from_str`, `range`, and
//! `drop`, `spawn`, and `channel`.

#![experimental]

// Reexported core operators
#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync};
#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
#[doc(no_inline)] pub use ops::{Shl, Shr};
#[doc(no_inline)] pub use ops::{Index, IndexMut};
#[doc(no_inline)] pub use ops::{Slice, SliceMut};
#[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce};
#[doc(no_inline)] pub use option::{Option, Some, None};
#[doc(no_inline)] pub use result::{Result, Ok, Err};

// Reexported functions
#[doc(no_inline)] pub use from_str::from_str;
#[doc(no_inline)] pub use iter::range;
#[doc(no_inline)] pub use mem::drop;

// Reexported types and traits

#[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
#[doc(no_inline)] pub use ascii::IntoBytes;
#[doc(no_inline)] pub use c_str::ToCStr;
#[doc(no_inline)] pub use char::{Char, UnicodeChar};
#[doc(no_inline)] pub use clone::Clone;
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
#[doc(no_inline)] pub use collections::{Collection, Mutable, Map, MutableMap, MutableSeq};
#[doc(no_inline)] pub use collections::{Set, MutableSet};
#[doc(no_inline)] pub use iter::{FromIterator, Extendable, ExactSize};
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
#[doc(no_inline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
#[doc(no_inline)] pub use boxed::Box;
#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
#[doc(no_inline)] pub use ptr::{RawPtr, RawMutPtr};
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrSlice};
#[doc(no_inline)] pub use to_string::{ToString, IntoStr};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
#[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice};
#[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice};
#[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
#[doc(no_inline)] pub use slice::{AsSlice, VectorVector, BoxedSlice};
#[doc(no_inline)] pub use slice::MutableSliceAllocating;
#[doc(no_inline)] pub use string::String;
#[doc(no_inline)] pub use vec::Vec;

// Reexported runtime types
#[doc(no_inline)] pub use comm::{sync_channel, channel};
#[doc(no_inline)] pub use comm::{SyncSender, Sender, Receiver};
#[doc(no_inline)] pub use task::spawn;
<|endoftext|>