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

use arena::TypedArena;
use llvm::{self, ValueRef, get_params};
use rustc::hir::def_id::DefId;
use abi::{Abi, FnType};
use attributes;
use base::*;
use callee::{self, Callee};
use common::*;
use debuginfo::{DebugLoc};
use declare;
use monomorphize::{Instance};
use value::Value;
use rustc::ty::{self, Ty, TyCtxt};

use rustc::hir;

fn get_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           closure_id: DefId,
                           fn_ty: Ty<'tcx>)
                           -> Ty<'tcx> {
    match tcx.closure_kind(closure_id) {
        ty::ClosureKind::Fn => {
            tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), fn_ty)
        }
        ty::ClosureKind::FnMut => {
            tcx.mk_mut_ref(tcx.mk_region(ty::ReErased), fn_ty)
        }
        ty::ClosureKind::FnOnce => fn_ty,
    }
}

/// Returns the LLVM function declaration for a closure, creating it if
/// necessary. If the ID does not correspond to a closure ID, returns None.
fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                               closure_id: DefId,
                                               substs: ty::ClosureSubsts<'tcx>)
                                               -> ValueRef {
    // Normalize type so differences in regions and typedefs don't cause
    // duplicate declarations
    let tcx = ccx.tcx();
    let substs = tcx.erase_regions(&substs);
    let instance = Instance::new(closure_id, substs.func_substs);

    if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
        debug!("get_or_create_closure_declaration(): found closure {:?}: {:?}",
               instance, Value(llfn));
        return llfn;
    }

    let symbol = instance.symbol_name(ccx.shared());

    // Compute the rust-call form of the closure call method.
    let sig = &tcx.closure_type(closure_id, substs).sig;
    let sig = tcx.erase_late_bound_regions(sig);
    let sig = tcx.normalize_associated_type(&sig);
    let closure_type = tcx.mk_closure_from_closure_substs(closure_id, substs);
    let function_type = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: hir::Unsafety::Normal,
        abi: Abi::RustCall,
        sig: ty::Binder(ty::FnSig {
            inputs: Some(get_self_type(tcx, closure_id, closure_type))
                        .into_iter().chain(sig.inputs).collect(),
            output: sig.output,
            variadic: false
        })
    }));
    let llfn = declare::declare_fn(ccx, &symbol, function_type);

    attributes::set_frame_pointer_elimination(ccx, llfn);

    debug!("get_or_create_declaration_if_closure(): inserting new \
            closure {:?}: {:?}",
           instance, Value(llfn));

    // NOTE: We do *not* store llfn in the ccx.instances() map here,
    //       that is only done, when the closures body is translated.

    llfn
}

pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                            closure_def_id: DefId,
                                            closure_substs: ty::ClosureSubsts<'tcx>) {
    // (*) Note that in the case of inlined functions, the `closure_def_id` will be the
    // defid of the closure in its original crate, whereas `id` will be the id of the local
    // inlined copy.
    debug!("trans_closure_body_via_mir(closure_def_id={:?}, closure_substs={:?})",
           closure_def_id, closure_substs);

    let tcx = ccx.tcx();
    let _icx = push_ctxt("closure::trans_closure_expr");

    let param_substs = closure_substs.func_substs;
    let instance = Instance::new(closure_def_id, param_substs);

    // If we have not done so yet, translate this closure's body
    if  !ccx.instances().borrow().contains_key(&instance) {
        let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);

        unsafe {
            if ccx.sess().target.target.options.allows_weak_linkage {
                llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::WeakODRLinkage);
                llvm::SetUniqueComdat(ccx.llmod(), llfn);
            } else {
                llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage);
            }
        }

        // set an inline hint for all closures
        attributes::inline(llfn, attributes::InlineAttr::Hint);

        // Get the type of this closure. Use the current `param_substs` as
        // the closure substitutions. This makes sense because the closure
        // takes the same set of type arguments as the enclosing fn, and
        // this function (`trans_closure`) is invoked at the point
        // of the closure expression.

        let sig = &tcx.closure_type(closure_def_id, closure_substs).sig;
        let sig = tcx.erase_late_bound_regions(sig);
        let sig = tcx.normalize_associated_type(&sig);

        let closure_type = tcx.mk_closure_from_closure_substs(closure_def_id,
                                                              closure_substs);
        let sig = ty::FnSig {
            inputs: Some(get_self_type(tcx, closure_def_id, closure_type))
                        .into_iter().chain(sig.inputs).collect(),
            output: sig.output,
            variadic: false
        };

        trans_closure(ccx,
                      llfn,
                      Instance::new(closure_def_id, param_substs),
                      &sig,
                      Abi::RustCall);

        ccx.instances().borrow_mut().insert(instance, llfn);
    }
}

pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
                                      closure_def_id: DefId,
                                      substs: ty::ClosureSubsts<'tcx>,
                                      method_instance: Instance<'tcx>,
                                      trait_closure_kind: ty::ClosureKind)
                                      -> ValueRef
{
    // If this is a closure, redirect to it.
    let llfn = get_or_create_closure_declaration(ccx, closure_def_id, substs);

    // If weak linkage is not allowed, we have to make sure that a local,
    // private copy of the closure is available in this codegen unit
    if !ccx.sess().target.target.options.allows_weak_linkage &&
       !ccx.sess().opts.single_codegen_unit() {

        trans_closure_body_via_mir(ccx, closure_def_id, substs);
    }

    // If the closure is a Fn closure, but a FnOnce is needed (etc),
    // then adapt the self type
    let llfn_closure_kind = ccx.tcx().closure_kind(closure_def_id);

    let _icx = push_ctxt("trans_closure_adapter_shim");

    debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
           trait_closure_kind={:?}, llfn={:?})",
           llfn_closure_kind, trait_closure_kind, Value(llfn));

    match (llfn_closure_kind, trait_closure_kind) {
        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
        (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
        (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
            // No adapter needed.
            llfn
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
            // `fn(&mut self, ...)`. In fact, at trans time, these are
            // basically the same thing, so we can just return llfn.
            llfn
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
        (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
            // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
            // self, ...)`.  We want a `fn(self, ...)`. We can produce
            // this by doing something like:
            //
            //     fn call_once(self, ...) { call_mut(&self, ...) }
            //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
            //
            // These are both the same at trans time.
            trans_fn_once_adapter_shim(ccx, closure_def_id, substs, method_instance, llfn)
        }
        _ => {
            bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
                 llfn_closure_kind,
                 trait_closure_kind);
        }
    }
}

fn trans_fn_once_adapter_shim<'a, 'tcx>(
    ccx: &'a CrateContext<'a, 'tcx>,
    closure_def_id: DefId,
    substs: ty::ClosureSubsts<'tcx>,
    method_instance: Instance<'tcx>,
    llreffn: ValueRef)
    -> ValueRef
{
    debug!("trans_fn_once_adapter_shim(closure_def_id={:?}, substs={:?}, llreffn={:?})",
           closure_def_id, substs, Value(llreffn));

    let tcx = ccx.tcx();

    // Find a version of the closure type. Substitute static for the
    // region since it doesn't really matter.
    let closure_ty = tcx.mk_closure_from_closure_substs(closure_def_id, substs);
    let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty);

    // Make a version with the type of by-ref closure.
    let ty::ClosureTy { unsafety, abi, mut sig } =
        tcx.closure_type(closure_def_id, substs);
    sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
    let llref_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: unsafety,
        abi: abi,
        sig: sig.clone()
    }));
    debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
           llref_fn_ty);

    // Make a version of the closure type with the same arguments, but
    // with argument #0 being by value.
    assert_eq!(abi, Abi::RustCall);
    sig.0.inputs[0] = closure_ty;

    let sig = tcx.erase_late_bound_regions(&sig);
    let sig = tcx.normalize_associated_type(&sig);
    let fn_ty = FnType::new(ccx, abi, &sig, &[]);

    let llonce_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: unsafety,
        abi: abi,
        sig: ty::Binder(sig)
    }));

    // Create the by-value helper.
    let function_name = method_instance.symbol_name(ccx.shared());
    let lloncefn = declare::declare_fn(ccx, &function_name, llonce_fn_ty);
    attributes::set_frame_pointer_elimination(ccx, lloncefn);

    let (block_arena, fcx): (TypedArena<_>, FunctionContext);
    block_arena = TypedArena::new();
    fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None, &block_arena);
    let mut bcx = fcx.init(false);

    // the first argument (`self`) will be the (by value) closure env.

    let mut llargs = get_params(fcx.llfn);
    let mut self_idx = fcx.fn_ty.ret.is_indirect() as usize;
    let env_arg = &fcx.fn_ty.args[0];
    let llenv = if env_arg.is_indirect() {
        llargs[self_idx]
    } else {
        let scratch = alloc_ty(bcx, closure_ty, "self");
        let mut llarg_idx = self_idx;
        env_arg.store_fn_arg(&bcx.build(), &mut llarg_idx, scratch);
        scratch
    };

    debug!("trans_fn_once_adapter_shim: env={:?}", Value(llenv));
    // Adjust llargs such that llargs[self_idx..] has the call arguments.
    // For zero-sized closures that means sneaking in a new argument.
    if env_arg.is_ignore() {
        if self_idx > 0 {
            self_idx -= 1;
            llargs[self_idx] = llenv;
        } else {
            llargs.insert(0, llenv);
        }
    } else {
        llargs[self_idx] = llenv;
    }

    let dest = fcx.llretslotptr.get();

    let callee = Callee {
        data: callee::Fn(llreffn),
        ty: llref_fn_ty
    };

    // Call the by-ref closure body with `self` in a cleanup scope,
    // to drop `self` when the body returns, or in case it unwinds.
    let self_scope = fcx.push_custom_cleanup_scope();
    fcx.schedule_drop_mem(self_scope, llenv, closure_ty);

    bcx = callee.call(bcx, DebugLoc::None, &llargs[self_idx..], dest).bcx;

    fcx.pop_and_trans_custom_cleanup_scope(bcx, self_scope);

    fcx.finish(bcx, DebugLoc::None);

    lloncefn
}
<commit_msg>Assign internal linkage to autogenerated FnOnce::call_once() instances.<commit_after>// Copyright 2012-2014 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.

use arena::TypedArena;
use llvm::{self, ValueRef, get_params};
use rustc::hir::def_id::DefId;
use abi::{Abi, FnType};
use attributes;
use base::*;
use callee::{self, Callee};
use common::*;
use debuginfo::{DebugLoc};
use declare;
use monomorphize::{Instance};
use value::Value;
use rustc::ty::{self, Ty, TyCtxt};

use rustc::hir;

fn get_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           closure_id: DefId,
                           fn_ty: Ty<'tcx>)
                           -> Ty<'tcx> {
    match tcx.closure_kind(closure_id) {
        ty::ClosureKind::Fn => {
            tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), fn_ty)
        }
        ty::ClosureKind::FnMut => {
            tcx.mk_mut_ref(tcx.mk_region(ty::ReErased), fn_ty)
        }
        ty::ClosureKind::FnOnce => fn_ty,
    }
}

/// Returns the LLVM function declaration for a closure, creating it if
/// necessary. If the ID does not correspond to a closure ID, returns None.
fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                               closure_id: DefId,
                                               substs: ty::ClosureSubsts<'tcx>)
                                               -> ValueRef {
    // Normalize type so differences in regions and typedefs don't cause
    // duplicate declarations
    let tcx = ccx.tcx();
    let substs = tcx.erase_regions(&substs);
    let instance = Instance::new(closure_id, substs.func_substs);

    if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
        debug!("get_or_create_closure_declaration(): found closure {:?}: {:?}",
               instance, Value(llfn));
        return llfn;
    }

    let symbol = instance.symbol_name(ccx.shared());

    // Compute the rust-call form of the closure call method.
    let sig = &tcx.closure_type(closure_id, substs).sig;
    let sig = tcx.erase_late_bound_regions(sig);
    let sig = tcx.normalize_associated_type(&sig);
    let closure_type = tcx.mk_closure_from_closure_substs(closure_id, substs);
    let function_type = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: hir::Unsafety::Normal,
        abi: Abi::RustCall,
        sig: ty::Binder(ty::FnSig {
            inputs: Some(get_self_type(tcx, closure_id, closure_type))
                        .into_iter().chain(sig.inputs).collect(),
            output: sig.output,
            variadic: false
        })
    }));
    let llfn = declare::declare_fn(ccx, &symbol, function_type);

    attributes::set_frame_pointer_elimination(ccx, llfn);

    debug!("get_or_create_declaration_if_closure(): inserting new \
            closure {:?}: {:?}",
           instance, Value(llfn));

    // NOTE: We do *not* store llfn in the ccx.instances() map here,
    //       that is only done, when the closures body is translated.

    llfn
}

pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                            closure_def_id: DefId,
                                            closure_substs: ty::ClosureSubsts<'tcx>) {
    // (*) Note that in the case of inlined functions, the `closure_def_id` will be the
    // defid of the closure in its original crate, whereas `id` will be the id of the local
    // inlined copy.
    debug!("trans_closure_body_via_mir(closure_def_id={:?}, closure_substs={:?})",
           closure_def_id, closure_substs);

    let tcx = ccx.tcx();
    let _icx = push_ctxt("closure::trans_closure_expr");

    let param_substs = closure_substs.func_substs;
    let instance = Instance::new(closure_def_id, param_substs);

    // If we have not done so yet, translate this closure's body
    if  !ccx.instances().borrow().contains_key(&instance) {
        let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);

        unsafe {
            if ccx.sess().target.target.options.allows_weak_linkage {
                llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::WeakODRLinkage);
                llvm::SetUniqueComdat(ccx.llmod(), llfn);
            } else {
                llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage);
            }
        }

        // set an inline hint for all closures
        attributes::inline(llfn, attributes::InlineAttr::Hint);

        // Get the type of this closure. Use the current `param_substs` as
        // the closure substitutions. This makes sense because the closure
        // takes the same set of type arguments as the enclosing fn, and
        // this function (`trans_closure`) is invoked at the point
        // of the closure expression.

        let sig = &tcx.closure_type(closure_def_id, closure_substs).sig;
        let sig = tcx.erase_late_bound_regions(sig);
        let sig = tcx.normalize_associated_type(&sig);

        let closure_type = tcx.mk_closure_from_closure_substs(closure_def_id,
                                                              closure_substs);
        let sig = ty::FnSig {
            inputs: Some(get_self_type(tcx, closure_def_id, closure_type))
                        .into_iter().chain(sig.inputs).collect(),
            output: sig.output,
            variadic: false
        };

        trans_closure(ccx,
                      llfn,
                      Instance::new(closure_def_id, param_substs),
                      &sig,
                      Abi::RustCall);

        ccx.instances().borrow_mut().insert(instance, llfn);
    }
}

pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
                                      closure_def_id: DefId,
                                      substs: ty::ClosureSubsts<'tcx>,
                                      method_instance: Instance<'tcx>,
                                      trait_closure_kind: ty::ClosureKind)
                                      -> ValueRef
{
    // If this is a closure, redirect to it.
    let llfn = get_or_create_closure_declaration(ccx, closure_def_id, substs);

    // If weak linkage is not allowed, we have to make sure that a local,
    // private copy of the closure is available in this codegen unit
    if !ccx.sess().target.target.options.allows_weak_linkage &&
       !ccx.sess().opts.single_codegen_unit() {

        trans_closure_body_via_mir(ccx, closure_def_id, substs);
    }

    // If the closure is a Fn closure, but a FnOnce is needed (etc),
    // then adapt the self type
    let llfn_closure_kind = ccx.tcx().closure_kind(closure_def_id);

    let _icx = push_ctxt("trans_closure_adapter_shim");

    debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
           trait_closure_kind={:?}, llfn={:?})",
           llfn_closure_kind, trait_closure_kind, Value(llfn));

    match (llfn_closure_kind, trait_closure_kind) {
        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
        (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
        (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
            // No adapter needed.
            llfn
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
            // `fn(&mut self, ...)`. In fact, at trans time, these are
            // basically the same thing, so we can just return llfn.
            llfn
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
        (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
            // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
            // self, ...)`.  We want a `fn(self, ...)`. We can produce
            // this by doing something like:
            //
            //     fn call_once(self, ...) { call_mut(&self, ...) }
            //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
            //
            // These are both the same at trans time.
            trans_fn_once_adapter_shim(ccx, closure_def_id, substs, method_instance, llfn)
        }
        _ => {
            bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
                 llfn_closure_kind,
                 trait_closure_kind);
        }
    }
}

fn trans_fn_once_adapter_shim<'a, 'tcx>(
    ccx: &'a CrateContext<'a, 'tcx>,
    closure_def_id: DefId,
    substs: ty::ClosureSubsts<'tcx>,
    method_instance: Instance<'tcx>,
    llreffn: ValueRef)
    -> ValueRef
{
    debug!("trans_fn_once_adapter_shim(closure_def_id={:?}, substs={:?}, llreffn={:?})",
           closure_def_id, substs, Value(llreffn));

    let tcx = ccx.tcx();

    // Find a version of the closure type. Substitute static for the
    // region since it doesn't really matter.
    let closure_ty = tcx.mk_closure_from_closure_substs(closure_def_id, substs);
    let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty);

    // Make a version with the type of by-ref closure.
    let ty::ClosureTy { unsafety, abi, mut sig } =
        tcx.closure_type(closure_def_id, substs);
    sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
    let llref_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: unsafety,
        abi: abi,
        sig: sig.clone()
    }));
    debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
           llref_fn_ty);

    // Make a version of the closure type with the same arguments, but
    // with argument #0 being by value.
    assert_eq!(abi, Abi::RustCall);
    sig.0.inputs[0] = closure_ty;

    let sig = tcx.erase_late_bound_regions(&sig);
    let sig = tcx.normalize_associated_type(&sig);
    let fn_ty = FnType::new(ccx, abi, &sig, &[]);

    let llonce_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: unsafety,
        abi: abi,
        sig: ty::Binder(sig)
    }));

    // Create the by-value helper.
    let function_name = method_instance.symbol_name(ccx.shared());
    let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
    attributes::set_frame_pointer_elimination(ccx, lloncefn);

    let (block_arena, fcx): (TypedArena<_>, FunctionContext);
    block_arena = TypedArena::new();
    fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None, &block_arena);
    let mut bcx = fcx.init(false);

    // the first argument (`self`) will be the (by value) closure env.

    let mut llargs = get_params(fcx.llfn);
    let mut self_idx = fcx.fn_ty.ret.is_indirect() as usize;
    let env_arg = &fcx.fn_ty.args[0];
    let llenv = if env_arg.is_indirect() {
        llargs[self_idx]
    } else {
        let scratch = alloc_ty(bcx, closure_ty, "self");
        let mut llarg_idx = self_idx;
        env_arg.store_fn_arg(&bcx.build(), &mut llarg_idx, scratch);
        scratch
    };

    debug!("trans_fn_once_adapter_shim: env={:?}", Value(llenv));
    // Adjust llargs such that llargs[self_idx..] has the call arguments.
    // For zero-sized closures that means sneaking in a new argument.
    if env_arg.is_ignore() {
        if self_idx > 0 {
            self_idx -= 1;
            llargs[self_idx] = llenv;
        } else {
            llargs.insert(0, llenv);
        }
    } else {
        llargs[self_idx] = llenv;
    }

    let dest = fcx.llretslotptr.get();

    let callee = Callee {
        data: callee::Fn(llreffn),
        ty: llref_fn_ty
    };

    // Call the by-ref closure body with `self` in a cleanup scope,
    // to drop `self` when the body returns, or in case it unwinds.
    let self_scope = fcx.push_custom_cleanup_scope();
    fcx.schedule_drop_mem(self_scope, llenv, closure_ty);

    bcx = callee.call(bcx, DebugLoc::None, &llargs[self_idx..], dest).bcx;

    fcx.pop_and_trans_custom_cleanup_scope(bcx, self_scope);

    fcx.finish(bcx, DebugLoc::None);

    lloncefn
}
<|endoftext|>


<commit_before>

/// Object describing the amount of information required when reading a postings.
///
/// Since decoding information is not free, this makes it possible to
/// avoid this extra cost when the information is not required.
/// For instance, positions are useful when running phrase queries
/// but useless in other queries.
#[derive(Clone, Copy)]
pub enum SegmentPostingsOption {
    /// Only the doc ids are decoded
    NoFreq,
    /// DocIds and term frequencies are decoded
    Freq,
    /// DocIds, term frequencies and positions will be decoded.
    FreqAndPositions,
}
<commit_msg>issue/57 Added Debug to SegmentPostingsOption<commit_after>

/// Object describing the amount of information required when reading a postings.
///
/// Since decoding information is not free, this makes it possible to
/// avoid this extra cost when the information is not required.
/// For instance, positions are useful when running phrase queries
/// but useless in other queries.
#[derive(Clone, Copy, Debug)]
pub enum SegmentPostingsOption {
    /// Only the doc ids are decoded
    NoFreq,
    /// DocIds and term frequencies are decoded
    Freq,
    /// DocIds, term frequencies and positions will be decoded.
    FreqAndPositions,
}
<|endoftext|>


<commit_before>#![cfg(target_os = "emscripten")]

use std::ffi::CString;

use {Api, ContextError, CreationError, GlAttributes, PixelFormat, PixelFormatRequirements};

use winit;

mod ffi;

pub struct Context {
    context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE,
}

impl Context {
    #[inline]
    pub fn new(
        window_builder: winit::WindowBuilder,
        events_loop: &winit::EventsLoop,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Context>,
    ) -> Result<(winit::Window, Self), CreationError>
    {
        let window = window_builder.build(events_loop)?;

        // getting the default values of attributes
        let mut attributes = unsafe {
            use std::mem;
            let mut attributes: ffi::EmscriptenWebGLContextAttributes = mem::uninitialized();
            ffi::emscripten_webgl_init_context_attributes(&mut attributes);
            attributes
        };

        // setting the attributes
        // FIXME:
        /*match builder.opengl.version {
            Some((major, minor)) => {
                attributes.majorVersion = major as libc::c_int;
                attributes.minorVersion = minor as libc::c_int;
            },
            None => ()
        };*/

        // creating the context
        let context = unsafe {
            use std::{mem, ptr};
            // TODO: correct first parameter based on the window
            let context = ffi::emscripten_webgl_create_context(ptr::null(), &attributes);
            if context <= 0 {
                return Err(CreationError::OsError(format!("Error while calling emscripten_webgl_create_context: {}",
                    error_to_str(mem::transmute(context)))));
            }
            context
        };

        // TODO: emscripten_set_webglcontextrestored_callback

        let ctxt = Context {
            context: context
        };

        Ok((window, ctxt))
    }

    #[inline]
    pub fn resize(&self, width: u32, height: u32) {
        // TODO: ?
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        // TOOD: check if == EMSCRIPTEN_RESULT
        ffi::emscripten_webgl_make_context_current(self.context);
        Ok(())
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        unsafe {
            ffi::emscripten_webgl_get_current_context() == self.context
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        let addr = CString::new(addr).unwrap();

        unsafe {
            // FIXME: if `as_ptr()` is used, then wrong data is passed to emscripten
            ffi::emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        Ok(())
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        Api::WebGl
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        // FIXME: this is a dummy pixel format
        PixelFormat {
            hardware_accelerated: true,
            color_bits: 24,
            alpha_bits: 8,
            depth_bits: 24,
            stencil_bits: 8,
            stereoscopy: false,
            double_buffer: true,
            multisampling: None,
            srgb: true,
        }
    }

    #[inline]
    pub unsafe fn raw_handle(&self) -> ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE {
        self.context
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            ffi::emscripten_webgl_destroy_context(self.context);
        }
    }
}

#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

pub struct HeadlessContext {
    context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE,
}

impl HeadlessContext {
    pub fn new(dimensions: (u32, u32), pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&HeadlessContext>,
               _: &PlatformSpecificHeadlessBuilderAttributes)
               -> Result<HeadlessContext, CreationError>
    {
        unimplemented!()
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        // TOOD: check if == EMSCRIPTEN_RESULT
        ffi::emscripten_webgl_make_context_current(self.context);
        Ok(())
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        unsafe {
            ffi::emscripten_webgl_get_current_context() == self.context
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        let addr = CString::new(addr).unwrap();

        unsafe {
            // FIXME: if `as_ptr()` is used, then wrong data is passed to emscripten
            ffi::emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        Ok(())
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        Api::WebGl
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        unimplemented!()
    }

    #[inline]
    pub unsafe fn raw_handle(&self) -> ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE {
        self.context
    }
}

fn error_to_str(code: ffi::EMSCRIPTEN_RESULT) -> &'static str {
    match code {
        ffi::EMSCRIPTEN_RESULT_SUCCESS | ffi::EMSCRIPTEN_RESULT_DEFERRED
            => "Internal error in the library (success detected as failure)",

        ffi::EMSCRIPTEN_RESULT_NOT_SUPPORTED => "Not supported",
        ffi::EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED => "Failed not deferred",
        ffi::EMSCRIPTEN_RESULT_INVALID_TARGET => "Invalid target",
        ffi::EMSCRIPTEN_RESULT_UNKNOWN_TARGET => "Unknown target",
        ffi::EMSCRIPTEN_RESULT_INVALID_PARAM => "Invalid parameter",
        ffi::EMSCRIPTEN_RESULT_FAILED => "Failed",
        ffi::EMSCRIPTEN_RESULT_NO_DATA => "No data",

        _ => "Undocumented error"
    }
}
<commit_msg>Request Emscripten GL version (#962)<commit_after>#![cfg(target_os = "emscripten")]

use std::ffi::CString;

use {Api, ContextError, CreationError, GlAttributes, GlRequest};
use {PixelFormat, PixelFormatRequirements};

use winit;

mod ffi;

pub struct Context {
    context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE,
}

impl Context {
    #[inline]
    pub fn new(
        window_builder: winit::WindowBuilder,
        events_loop: &winit::EventsLoop,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Context>,
    ) -> Result<(winit::Window, Self), CreationError>
    {
        let window = window_builder.build(events_loop)?;

        // getting the default values of attributes
        let mut attributes = unsafe {
            use std::mem;
            let mut attributes: ffi::EmscriptenWebGLContextAttributes = mem::uninitialized();
            ffi::emscripten_webgl_init_context_attributes(&mut attributes);
            attributes
        };

        // setting the attributes
        if let GlRequest::Specific(Api::WebGl, (major, minor)) = gl_attr.version {
            attributes.majorVersion = major as _;
            attributes.minorVersion = minor as _;
        }

        // creating the context
        let context = unsafe {
            use std::{mem, ptr};
            // TODO: correct first parameter based on the window
            let context = ffi::emscripten_webgl_create_context(ptr::null(), &attributes);
            if context <= 0 {
                return Err(CreationError::OsError(format!("Error while calling emscripten_webgl_create_context: {}",
                    error_to_str(mem::transmute(context)))));
            }
            context
        };

        // TODO: emscripten_set_webglcontextrestored_callback

        let ctxt = Context {
            context: context
        };

        Ok((window, ctxt))
    }

    #[inline]
    pub fn resize(&self, width: u32, height: u32) {
        // TODO: ?
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        // TOOD: check if == EMSCRIPTEN_RESULT
        ffi::emscripten_webgl_make_context_current(self.context);
        Ok(())
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        unsafe {
            ffi::emscripten_webgl_get_current_context() == self.context
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        let addr = CString::new(addr).unwrap();

        unsafe {
            // FIXME: if `as_ptr()` is used, then wrong data is passed to emscripten
            ffi::emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        Ok(())
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        Api::WebGl
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        // FIXME: this is a dummy pixel format
        PixelFormat {
            hardware_accelerated: true,
            color_bits: 24,
            alpha_bits: 8,
            depth_bits: 24,
            stencil_bits: 8,
            stereoscopy: false,
            double_buffer: true,
            multisampling: None,
            srgb: true,
        }
    }

    #[inline]
    pub unsafe fn raw_handle(&self) -> ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE {
        self.context
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            ffi::emscripten_webgl_destroy_context(self.context);
        }
    }
}

#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

pub struct HeadlessContext {
    context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE,
}

impl HeadlessContext {
    pub fn new(dimensions: (u32, u32), pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&HeadlessContext>,
               _: &PlatformSpecificHeadlessBuilderAttributes)
               -> Result<HeadlessContext, CreationError>
    {
        unimplemented!()
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        // TOOD: check if == EMSCRIPTEN_RESULT
        ffi::emscripten_webgl_make_context_current(self.context);
        Ok(())
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        unsafe {
            ffi::emscripten_webgl_get_current_context() == self.context
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        let addr = CString::new(addr).unwrap();

        unsafe {
            // FIXME: if `as_ptr()` is used, then wrong data is passed to emscripten
            ffi::emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        Ok(())
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        Api::WebGl
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        unimplemented!()
    }

    #[inline]
    pub unsafe fn raw_handle(&self) -> ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE {
        self.context
    }
}

fn error_to_str(code: ffi::EMSCRIPTEN_RESULT) -> &'static str {
    match code {
        ffi::EMSCRIPTEN_RESULT_SUCCESS | ffi::EMSCRIPTEN_RESULT_DEFERRED
            => "Internal error in the library (success detected as failure)",

        ffi::EMSCRIPTEN_RESULT_NOT_SUPPORTED => "Not supported",
        ffi::EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED => "Failed not deferred",
        ffi::EMSCRIPTEN_RESULT_INVALID_TARGET => "Invalid target",
        ffi::EMSCRIPTEN_RESULT_UNKNOWN_TARGET => "Unknown target",
        ffi::EMSCRIPTEN_RESULT_INVALID_PARAM => "Invalid parameter",
        ffi::EMSCRIPTEN_RESULT_FAILED => "Failed",
        ffi::EMSCRIPTEN_RESULT_NO_DATA => "No data",

        _ => "Undocumented error"
    }
}
<|endoftext|>


<commit_before>extern crate num_traits;

use integeriser::{HashIntegeriser, Integeriser};
use num_traits::{One, Zero};
use recognisable::{self, Configuration, Instruction, Item, Recognisable, Transition};
use recognisable::automaton::Automaton;
use std::collections::{BinaryHeap, HashMap};
use std::fmt;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::ops::{AddAssign, Mul, MulAssign};
use std::rc::Rc;
use std::slice::Iter;
use std::vec::Vec;
use util::integerisable::{Integerisable1, Integerisable2};
use util::push_down::Pushdown;

mod from_cfg;

pub use self::from_cfg::*;

type TransitionMap
    = HashMap<A, BinaryHeap<Transition<PushDownInstruction, T, W>>>;

/// Automaton with storage type `PushDown<A>`, terminals of type `T` and weights of type `W`.
#[derive(Debug, Clone)]
pub struct PushDownAutomaton
    where A: Clone + Hash + Ord,
          T: Eq + Hash,
          W: Ord,
{
    a_integeriser: HashIntegeriser,
    t_integeriser: HashIntegeriser<T>,
    transitions: Rc<TransitionMap<usize, usize, W>>,
    initial: PushDown<usize>,
}

/// Instruction on `PushDown<A>`s.
#[derive(PartialEq, Eq, Clone, Debug, Hash, PartialOrd, Ord)]
pub enum PushDownInstruction {
    Replace { current_val: Vec, new_val: Vec },
}

impl PushDownInstruction {
    fn map<F, B>(&self, f: &F) -> PushDownInstruction
        where F: Fn(&A) -> B
    {
        match *self {
            PushDownInstruction::Replace { ref current_val, ref new_val } =>
                PushDownInstruction::Replace {
                    current_val: current_val.iter().map(f).collect(),
                    new_val: new_val.iter().map(f).collect(),
                },
        }
    }

    fn map_mut<F, B>(&self, f: &mut F) -> PushDownInstruction
        where F: FnMut(&A) -> B
    {
        match *self {
            PushDownInstruction::Replace { ref current_val, ref new_val } => {
                PushDownInstruction::Replace {
                    current_val: map_vec_mut(current_val, f),
                    new_val: map_vec_mut(new_val, f),
                }
            },
        }
    }
}

fn map_vec_mut(v: &Vec, f: &mut F) -> Vec
    where F: FnMut(&A) -> B
{
    let mut res = Vec::new();
    for a in v {
        res.push(f(a));
    }
    res
}

impl Integerisable1 for PushDownInstruction {
    type AInt = PushDownInstruction<usize>;
    type I = HashIntegeriser;

    fn integerise(&self, integeriser: &mut Self::I) -> Self::AInt {
        self.map_mut(&mut |a| integeriser.integerise(a.clone()))
    }

    fn un_integerise(v: &Self::AInt, integeriser: &Self::I) -> Self {
        v.map(&|i| integeriser.find_value(*i).unwrap().clone())
    }
}

/// Stack with Elements of type `A`
#[derive(PartialEq, Eq, Debug, Clone, Hash, PartialOrd, Ord)]
pub struct PushDown {
    elements: Vec,
    empty: A,
}

impl PushDownAutomaton
    where A: Clone + Hash + Ord + PartialEq,
          T: Clone + Eq + Hash + Ord,
          W: AddAssign + Clone + Eq + Ord + Zero,
{
    pub fn new<It>(transitions: It, initial: PushDown) -> Self
        where It: IntoIterator<Item=Transition<PushDownInstruction, T, W>>
    {
        let mut a_inter = HashIntegeriser::new();
        let mut t_inter = HashIntegeriser::new();
        let init = initial.integerise(&mut a_inter);
        let mut transition_map = HashMap::new();

        for t in transitions.into_iter().map(|t| t.integerise(&mut t_inter, &mut a_inter)) {
            match t.instruction {
                PushDownInstruction::Replace { ref current_val, .. } => {
                    let a = current_val.first().unwrap().clone();
                    *transition_map
                        .entry(a)
                        .or_insert(HashMap::new())
                        .entry((t.word, t.instruction.clone()))
                        .or_insert(W::zero()) += t.weight;
                },
            }
        }

        let f = |(k, hm): (_, HashMap<_, _>)| (k, hm.into_iter()
            .map(|((w, i), wt)| Transition {word: w, instruction: i, weight: wt}).collect());

        PushDownAutomaton {
            a_integeriser: a_inter,
            t_integeriser: t_inter,
            transitions: Rc::new(transition_map.into_iter().map(f).collect()),
            initial: init,
        }
    }
}

impl PushDownAutomaton
    where A: Clone + Hash + Ord,
          T: Clone + Hash + Eq + Ord,
          W: Clone + Ord,
{
    pub fn list_transitions<'a>(&'a self)
                                -> Box<Iterator<Item=Transition<PushDownInstruction, T, W>> + 'a>
    {
        Box::new(
            self.transitions.values()
                .flat_map(
                    move |h| h.iter()
                        .map(move |t| Transition::un_integerise(t,
                                                                &self.t_integeriser,
                                                                &self.a_integeriser))
                )
        )
    }
}

impl Instruction for PushDownInstruction
    where A: Ord + PartialEq + Clone + Hash
{
    type Storage = PushDown;

    fn apply(&self, p: PushDown) -> Vec<PushDown> {
        match *self {
            PushDownInstruction::Replace {ref current_val, ref new_val} =>
                p.replace(current_val, new_val).ok().into_iter().collect(),
        }
    }
}

impl Automaton<T, W> for PushDownAutomaton
    where A: Ord + PartialEq + Clone + Hash,
          T: Clone + Eq + Hash + Ord,
          W: AddAssign + Clone + MulAssign + One + Ord + Zero,
{
    type Key = usize;
    type I = PushDownInstruction;
    type IInt = PushDownInstruction<usize>;
    type TInt = usize;

    fn extract_key(c: &Configuration<PushDown<usize>, usize, W>) -> &usize {
        if c.storage.is_bottom() {
            &c.storage.empty
        } else {
            c.storage.current_symbol()
        }
    }

    fn from_transitions<It>(transitions: It, initial: PushDown) -> Self
        where It: IntoIterator<Item=Transition<PushDownInstruction, T, W>>
    {
        PushDownAutomaton::new(transitions, initial)
    }

    fn transitions<'a>(&'a self)
                       -> Box<Iterator<Item=Transition<PushDownInstruction, T, W>> + 'a>
    {
        self.list_transitions()
    }

    fn initial(&self) -> PushDown {
        Integerisable1::un_integerise(&self.initial, &self.a_integeriser)
    }

    fn transition_map(&self) -> Rc<TransitionMap<usize, usize, W>> {
        self.transitions.clone()
    }

    fn initial_int(&self) -> PushDown<usize> {
        self.initial.clone()
    }

    fn is_terminal(c: &Configuration<PushDown<usize>, usize, W>) -> bool {
        c.word.is_empty() && c.storage.is_bottom()
    }

    fn item_map(&self, i: &Item<PushDown<usize>, PushDownInstruction<usize>, usize, W>)
                -> Item<PushDown, PushDownInstruction, T, W> {
        match *i {
            (Configuration { ref word, ref storage, ref weight }, ref pd) => {
                let pd_vec: Vec<_>
                    = pd.clone().into();
                let pd_unint: Vec<_>
                    = pd_vec.iter().map(
                        |t| Integerisable2::un_integerise(t,
                                                          &self.t_integeriser,
                                                          &self.a_integeriser))
                            .collect();
                (
                    Configuration {
                        word: word
                            .iter()
                            .map(|t| self.t_integeriser.find_value(*t).unwrap().clone())
                            .collect(),
                        storage: Integerisable1::un_integerise(storage, &self.a_integeriser),
                        weight: weight.clone(),
                    },
                    Pushdown::from(pd_unint.as_slice())
                )
            }
        }
    }

    fn terminal_to_int(&self, t: &T) -> usize {
        self.t_integeriser.find_key(t).unwrap()
    }
}

impl Recognisable<T, W> for PushDownAutomaton
    where A: Ord + PartialEq + Debug + Clone + Hash,
          T: Clone + Debug + Eq + Hash + Ord,
          W: AddAssign + One + Mul<Output=W> + MulAssign + Clone + Copy + Debug + Eq + Ord + Zero,
{
    type Parse = Item<PushDown, PushDownInstruction, T, W>;

    fn recognise<'a>(&'a self, word: Vec<T>) -> Box<Iterator<Item=Self::Parse> + 'a> {
        Box::new(recognisable::automaton::recognise(self, word))
    }

    fn recognise_beam_search<'a>(&'a self, beam: usize, word: Vec<T>) -> Box<Iterator<Item=Self::Parse> + 'a> {
        Box::new(recognisable::automaton::recognise_beam(self, beam, word))
    }
}

impl PushDown {
    pub fn empty(&self) -> &A {
        &self.empty
    }
    pub fn current_symbol(&self) -> &A {
        self.elements.last().unwrap()
    }

    /// Checks whether stack is empty.
    pub fn is_bottom(&self) -> bool {
        self.elements.len() == 1
    }

    pub fn iter(&self) -> Iter {
        self.elements.iter()
    }

    pub fn map<F, B>(&self, f: &F) -> PushDown
        where F: Fn(&A) -> B,
    {
        PushDown {
            empty: f(&self.empty),
            elements: self.elements.iter().map(f).collect(),
        }
    }

    pub fn map_mut<F, B>(&self, f: &mut F) -> PushDown
        where F: FnMut(&A) -> B,
    {
        PushDown {
            empty: f(&self.empty),
            elements: self.elements.iter().map(f).collect(),
        }
    }
}

impl Integerisable1 for PushDown {
    type AInt = PushDown<usize>;
    type I = HashIntegeriser;

    fn integerise(&self, integeriser: &mut Self::I) -> Self::AInt {
        self.map_mut(&mut |v| integeriser.integerise(v.clone()))
    }

    fn un_integerise(aint: &Self::AInt, integeriser: &Self::I) -> Self {
        aint.map(&|i| integeriser.find_value(*i).unwrap().clone())
    }
}

impl PushDown
    where A: Clone
{
    pub fn from_vec(vec: Vec) -> PushDown {
        PushDown {
            empty: vec[0].clone(),
            elements: vec,
        }
    }

    /// New `PushDown<A>` with empty-symbol of type `A` and initial symbol of type `A`
    pub fn new(a: A, empty: A) -> PushDown {
        PushDown::from_vec(vec![empty, a])
    }
}

impl PushDown
    where A: Clone + Ord
{
    /// Operations for Instructions:
    /// Replaces the uppermost elements with the given elements.
    /// TODO cur_sym ist given in reverse order.
    pub fn replace(mut self, cur_sym: &[A],  new_sym: &[A]) -> Result<Self, Self> {
        let mut new_cur_sym = cur_sym.to_vec(); //
        new_cur_sym.reverse();                  // TODO remove this

        if self.elements.ends_with(&new_cur_sym) {
            let n = self.elements.len();
            self.elements.truncate(n - cur_sym.len());
            self.elements.append(&mut new_sym.to_vec());
            Ok(self)
        } else {
            Err(self)
        }
    }
}

impl Display for PushDown
    where A: Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = String::new();
        let mut iter1 = self.elements.iter().peekable();

        while let Some(nt) = iter1.next() {
            buffer.push_str(format!("{}", nt).as_str());
            if iter1.peek().is_some() {
                buffer.push_str(" ");
            }
        }
        write!(f, "stack: [{}], empty:{}", buffer, self.empty)
    }
}

impl Display for PushDownInstruction
    where A: Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            PushDownInstruction::Replace { ref current_val, ref new_val} => {
                let mut buffer1 = "".to_string();
                let mut buffer2 = "".to_string();

                let mut iter1 = current_val.iter().peekable();
                let mut iter2 = new_val.iter().peekable();

                while let Some(nt) = iter1.next() {
                    buffer1.push_str(format!("\"{}\"", nt).as_str());
                    if iter1.peek().is_some() {
                        buffer1.push_str(", ");
                    }
                }

                while let Some(nt) = iter2.next() {
                    buffer2.push_str(format!("\"{}\"", nt).as_str());
                    if iter2.peek().is_some() {
                        buffer2.push_str(", ");
                    }
                }
                write!(f, "(Replace {} // {})", buffer1, buffer2)
            }
        }
    }
}

impl Display for PushDownAutomaton
    where A: Clone + Display + Hash + Ord,
          T: Clone + Debug + Display + Eq + Hash + Ord,
          W: Clone + Display + Ord,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut formatted_transitions = String::new();
        for t in self.list_transitions() {
            formatted_transitions.push_str(&t.to_string());
            formatted_transitions.push_str("\n");
        }
        write!(f, "initial: {}\n\n{}", self.initial.current_symbol(), formatted_transitions)
    }
}
<commit_msg>src/push_down_automaton/mod.rs: fixed pretty printer<commit_after>extern crate num_traits;

use integeriser::{HashIntegeriser, Integeriser};
use num_traits::{One, Zero};
use recognisable::{self, Configuration, Instruction, Item, Recognisable, Transition};
use recognisable::automaton::Automaton;
use std::collections::{BinaryHeap, HashMap};
use std::fmt;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::ops::{AddAssign, Mul, MulAssign};
use std::rc::Rc;
use std::slice::Iter;
use std::vec::Vec;
use util::integerisable::{Integerisable1, Integerisable2};
use util::push_down::Pushdown;

mod from_cfg;

pub use self::from_cfg::*;

type TransitionMap
    = HashMap<A, BinaryHeap<Transition<PushDownInstruction, T, W>>>;

/// Automaton with storage type `PushDown<A>`, terminals of type `T` and weights of type `W`.
#[derive(Debug, Clone)]
pub struct PushDownAutomaton
    where A: Clone + Hash + Ord,
          T: Eq + Hash,
          W: Ord,
{
    a_integeriser: HashIntegeriser,
    t_integeriser: HashIntegeriser<T>,
    transitions: Rc<TransitionMap<usize, usize, W>>,
    initial: PushDown<usize>,
}

/// Instruction on `PushDown<A>`s.
#[derive(PartialEq, Eq, Clone, Debug, Hash, PartialOrd, Ord)]
pub enum PushDownInstruction {
    Replace { current_val: Vec, new_val: Vec },
}

impl PushDownInstruction {
    fn map<F, B>(&self, f: &F) -> PushDownInstruction
        where F: Fn(&A) -> B
    {
        match *self {
            PushDownInstruction::Replace { ref current_val, ref new_val } =>
                PushDownInstruction::Replace {
                    current_val: current_val.iter().map(f).collect(),
                    new_val: new_val.iter().map(f).collect(),
                },
        }
    }

    fn map_mut<F, B>(&self, f: &mut F) -> PushDownInstruction
        where F: FnMut(&A) -> B
    {
        match *self {
            PushDownInstruction::Replace { ref current_val, ref new_val } => {
                PushDownInstruction::Replace {
                    current_val: map_vec_mut(current_val, f),
                    new_val: map_vec_mut(new_val, f),
                }
            },
        }
    }
}

fn map_vec_mut(v: &Vec, f: &mut F) -> Vec
    where F: FnMut(&A) -> B
{
    let mut res = Vec::new();
    for a in v {
        res.push(f(a));
    }
    res
}

impl Integerisable1 for PushDownInstruction {
    type AInt = PushDownInstruction<usize>;
    type I = HashIntegeriser;

    fn integerise(&self, integeriser: &mut Self::I) -> Self::AInt {
        self.map_mut(&mut |a| integeriser.integerise(a.clone()))
    }

    fn un_integerise(v: &Self::AInt, integeriser: &Self::I) -> Self {
        v.map(&|i| integeriser.find_value(*i).unwrap().clone())
    }
}

/// Stack with Elements of type `A`
#[derive(PartialEq, Eq, Debug, Clone, Hash, PartialOrd, Ord)]
pub struct PushDown {
    elements: Vec,
    empty: A,
}

impl PushDownAutomaton
    where A: Clone + Hash + Ord + PartialEq,
          T: Clone + Eq + Hash + Ord,
          W: AddAssign + Clone + Eq + Ord + Zero,
{
    pub fn new<It>(transitions: It, initial: PushDown) -> Self
        where It: IntoIterator<Item=Transition<PushDownInstruction, T, W>>
    {
        let mut a_inter = HashIntegeriser::new();
        let mut t_inter = HashIntegeriser::new();
        let init = initial.integerise(&mut a_inter);
        let mut transition_map = HashMap::new();

        for t in transitions.into_iter().map(|t| t.integerise(&mut t_inter, &mut a_inter)) {
            match t.instruction {
                PushDownInstruction::Replace { ref current_val, .. } => {
                    let a = current_val.first().unwrap().clone();
                    *transition_map
                        .entry(a)
                        .or_insert(HashMap::new())
                        .entry((t.word, t.instruction.clone()))
                        .or_insert(W::zero()) += t.weight;
                },
            }
        }

        let f = |(k, hm): (_, HashMap<_, _>)| (k, hm.into_iter()
            .map(|((w, i), wt)| Transition {word: w, instruction: i, weight: wt}).collect());

        PushDownAutomaton {
            a_integeriser: a_inter,
            t_integeriser: t_inter,
            transitions: Rc::new(transition_map.into_iter().map(f).collect()),
            initial: init,
        }
    }
}

impl PushDownAutomaton
    where A: Clone + Hash + Ord,
          T: Clone + Hash + Eq + Ord,
          W: Clone + Ord,
{
    pub fn list_transitions<'a>(&'a self)
                                -> Box<Iterator<Item=Transition<PushDownInstruction, T, W>> + 'a>
    {
        Box::new(
            self.transitions.values()
                .flat_map(
                    move |h| h.iter()
                        .map(move |t| Transition::un_integerise(t,
                                                                &self.t_integeriser,
                                                                &self.a_integeriser))
                )
        )
    }
}

impl Instruction for PushDownInstruction
    where A: Ord + PartialEq + Clone + Hash
{
    type Storage = PushDown;

    fn apply(&self, p: PushDown) -> Vec<PushDown> {
        match *self {
            PushDownInstruction::Replace {ref current_val, ref new_val} =>
                p.replace(current_val, new_val).ok().into_iter().collect(),
        }
    }
}

impl Automaton<T, W> for PushDownAutomaton
    where A: Ord + PartialEq + Clone + Hash,
          T: Clone + Eq + Hash + Ord,
          W: AddAssign + Clone + MulAssign + One + Ord + Zero,
{
    type Key = usize;
    type I = PushDownInstruction;
    type IInt = PushDownInstruction<usize>;
    type TInt = usize;

    fn extract_key(c: &Configuration<PushDown<usize>, usize, W>) -> &usize {
        if c.storage.is_bottom() {
            &c.storage.empty
        } else {
            c.storage.current_symbol()
        }
    }

    fn from_transitions<It>(transitions: It, initial: PushDown) -> Self
        where It: IntoIterator<Item=Transition<PushDownInstruction, T, W>>
    {
        PushDownAutomaton::new(transitions, initial)
    }

    fn transitions<'a>(&'a self)
                       -> Box<Iterator<Item=Transition<PushDownInstruction, T, W>> + 'a>
    {
        self.list_transitions()
    }

    fn initial(&self) -> PushDown {
        Integerisable1::un_integerise(&self.initial, &self.a_integeriser)
    }

    fn transition_map(&self) -> Rc<TransitionMap<usize, usize, W>> {
        self.transitions.clone()
    }

    fn initial_int(&self) -> PushDown<usize> {
        self.initial.clone()
    }

    fn is_terminal(c: &Configuration<PushDown<usize>, usize, W>) -> bool {
        c.word.is_empty() && c.storage.is_bottom()
    }

    fn item_map(&self, i: &Item<PushDown<usize>, PushDownInstruction<usize>, usize, W>)
                -> Item<PushDown, PushDownInstruction, T, W> {
        match *i {
            (Configuration { ref word, ref storage, ref weight }, ref pd) => {
                let pd_vec: Vec<_>
                    = pd.clone().into();
                let pd_unint: Vec<_>
                    = pd_vec.iter().map(
                        |t| Integerisable2::un_integerise(t,
                                                          &self.t_integeriser,
                                                          &self.a_integeriser))
                            .collect();
                (
                    Configuration {
                        word: word
                            .iter()
                            .map(|t| self.t_integeriser.find_value(*t).unwrap().clone())
                            .collect(),
                        storage: Integerisable1::un_integerise(storage, &self.a_integeriser),
                        weight: weight.clone(),
                    },
                    Pushdown::from(pd_unint.as_slice())
                )
            }
        }
    }

    fn terminal_to_int(&self, t: &T) -> usize {
        self.t_integeriser.find_key(t).unwrap()
    }
}

impl Recognisable<T, W> for PushDownAutomaton
    where A: Ord + PartialEq + Debug + Clone + Hash,
          T: Clone + Debug + Eq + Hash + Ord,
          W: AddAssign + One + Mul<Output=W> + MulAssign + Clone + Copy + Debug + Eq + Ord + Zero,
{
    type Parse = Item<PushDown, PushDownInstruction, T, W>;

    fn recognise<'a>(&'a self, word: Vec<T>) -> Box<Iterator<Item=Self::Parse> + 'a> {
        Box::new(recognisable::automaton::recognise(self, word))
    }

    fn recognise_beam_search<'a>(&'a self, beam: usize, word: Vec<T>) -> Box<Iterator<Item=Self::Parse> + 'a> {
        Box::new(recognisable::automaton::recognise_beam(self, beam, word))
    }
}

impl PushDown {
    pub fn empty(&self) -> &A {
        &self.empty
    }
    pub fn current_symbol(&self) -> &A {
        self.elements.last().unwrap()
    }

    /// Checks whether stack is empty.
    pub fn is_bottom(&self) -> bool {
        self.elements.len() == 1
    }

    pub fn iter(&self) -> Iter {
        self.elements.iter()
    }

    pub fn map<F, B>(&self, f: &F) -> PushDown
        where F: Fn(&A) -> B,
    {
        PushDown {
            empty: f(&self.empty),
            elements: self.elements.iter().map(f).collect(),
        }
    }

    pub fn map_mut<F, B>(&self, f: &mut F) -> PushDown
        where F: FnMut(&A) -> B,
    {
        PushDown {
            empty: f(&self.empty),
            elements: self.elements.iter().map(f).collect(),
        }
    }
}

impl Integerisable1 for PushDown {
    type AInt = PushDown<usize>;
    type I = HashIntegeriser;

    fn integerise(&self, integeriser: &mut Self::I) -> Self::AInt {
        self.map_mut(&mut |v| integeriser.integerise(v.clone()))
    }

    fn un_integerise(aint: &Self::AInt, integeriser: &Self::I) -> Self {
        aint.map(&|i| integeriser.find_value(*i).unwrap().clone())
    }
}

impl PushDown
    where A: Clone
{
    pub fn from_vec(vec: Vec) -> PushDown {
        PushDown {
            empty: vec[0].clone(),
            elements: vec,
        }
    }

    /// New `PushDown<A>` with empty-symbol of type `A` and initial symbol of type `A`
    pub fn new(a: A, empty: A) -> PushDown {
        PushDown::from_vec(vec![empty, a])
    }
}

impl PushDown
    where A: Clone + Ord
{
    /// Operations for Instructions:
    /// Replaces the uppermost elements with the given elements.
    /// TODO cur_sym ist given in reverse order.
    pub fn replace(mut self, cur_sym: &[A],  new_sym: &[A]) -> Result<Self, Self> {
        let mut new_cur_sym = cur_sym.to_vec(); //
        new_cur_sym.reverse();                  // TODO remove this

        if self.elements.ends_with(&new_cur_sym) {
            let n = self.elements.len();
            self.elements.truncate(n - cur_sym.len());
            self.elements.append(&mut new_sym.to_vec());
            Ok(self)
        } else {
            Err(self)
        }
    }
}

impl Display for PushDown
    where A: Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = String::new();
        let mut iter1 = self.elements.iter().peekable();

        while let Some(nt) = iter1.next() {
            buffer.push_str(format!("{}", nt).as_str());
            if iter1.peek().is_some() {
                buffer.push_str(" ");
            }
        }
        write!(f, "stack: [{}], empty:{}", buffer, self.empty)
    }
}

impl Display for PushDownInstruction
    where A: Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            PushDownInstruction::Replace { ref current_val, ref new_val} => {
                let mut buffer1 = "".to_string();
                let mut buffer2 = "".to_string();

                let mut iter1 = current_val.iter().peekable();
                let mut iter2 = new_val.iter().peekable();

                while let Some(nt) = iter1.next() {
                    buffer1.push_str(format!("\"{}\"", nt).as_str());
                    if iter1.peek().is_some() {
                        buffer1.push_str(", ");
                    }
                }

                while let Some(nt) = iter2.next() {
                    buffer2.push_str(format!("\"{}\"", nt).as_str());
                    if iter2.peek().is_some() {
                        buffer2.push_str(", ");
                    }
                }
                write!(f, "(Replace {} // {})", buffer1, buffer2)
            }
        }
    }
}

impl Display for PushDownAutomaton
    where A: Clone + Display + Hash + Ord + PartialEq,
          T: Clone + Debug + Display + Eq + Hash + Ord,
          W: AddAssign + Clone + Display + MulAssign + One + Ord + Zero,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut formatted_transitions = String::new();
        for t in self.list_transitions() {
            formatted_transitions.push_str(&t.to_string());
            formatted_transitions.push_str("\n");
        }
        write!(f,
               "initial: {}\n\n{}",
               self.initial(),
               formatted_transitions
        )
    }
}
<|endoftext|>


<commit_before>//! [GET /_matrix/client/r0/account/3pid](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-account-3pid)

use std::time::SystemTime;

use ruma_api::ruma_api;
use serde::{Deserialize, Serialize};

use crate::r0::thirdparty::Medium;

ruma_api! {
    metadata {
        description: "Get a list of 3rd party contacts associated with the user's account.",
        method: GET,
        name: "get_contacts",
        path: "/_matrix/client/r0/account/3pid",
        rate_limited: false,
        requires_authentication: true,
    }

    request {}

    response {
        /// A list of third party identifiers the homeserver has associated with the user's
        /// account.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub threepids: Vec<ThirdPartyIdentifier>,
    }

    error: crate::Error
}

/// An identifier external to Matrix.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(test, derive(PartialEq))]
pub struct ThirdPartyIdentifier {
    /// The third party identifier address.
    pub address: String,
    /// The medium of third party identifier.
    pub medium: Medium,
    /// The time when the identifier was validated by the identity server.
    #[serde(with = "crate::serde::time::ms_since_unix_epoch")]
    pub validated_at: SystemTime,
    /// The time when the homeserver associated the third party identifier with the user.
    #[serde(with = "crate::serde::time::ms_since_unix_epoch")]
    pub added_at: SystemTime,
}

#[cfg(test)]
mod tests {
    use std::time::{Duration, UNIX_EPOCH};

    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::{Medium, ThirdPartyIdentifier};

    #[test]
    fn third_party_identifier_serde() {
        let third_party_id = ThirdPartyIdentifier {
            address: "monkey@banana.island".into(),
            medium: Medium::Email,
            validated_at: UNIX_EPOCH + Duration::from_millis(1_535_176_800_000),
            added_at: UNIX_EPOCH + Duration::from_millis(1_535_336_848_756),
        };

        let third_party_id_serialized = json!({
            "medium": "email",
            "address": "monkey@banana.island",
            "validated_at": 1_535_176_800_000u64,
            "added_at": 1_535_336_848_756u64
        });

        assert_eq!(
            to_json_value(third_party_id.clone()).unwrap(),
            third_party_id_serialized.clone()
        );
        assert_eq!(
            third_party_id,
            from_json_value(third_party_id_serialized).unwrap()
        );
    }
}
<commit_msg>Fix redundant clone<commit_after>//! [GET /_matrix/client/r0/account/3pid](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-account-3pid)

use std::time::SystemTime;

use ruma_api::ruma_api;
use serde::{Deserialize, Serialize};

use crate::r0::thirdparty::Medium;

ruma_api! {
    metadata {
        description: "Get a list of 3rd party contacts associated with the user's account.",
        method: GET,
        name: "get_contacts",
        path: "/_matrix/client/r0/account/3pid",
        rate_limited: false,
        requires_authentication: true,
    }

    request {}

    response {
        /// A list of third party identifiers the homeserver has associated with the user's
        /// account.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub threepids: Vec<ThirdPartyIdentifier>,
    }

    error: crate::Error
}

/// An identifier external to Matrix.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(test, derive(PartialEq))]
pub struct ThirdPartyIdentifier {
    /// The third party identifier address.
    pub address: String,
    /// The medium of third party identifier.
    pub medium: Medium,
    /// The time when the identifier was validated by the identity server.
    #[serde(with = "crate::serde::time::ms_since_unix_epoch")]
    pub validated_at: SystemTime,
    /// The time when the homeserver associated the third party identifier with the user.
    #[serde(with = "crate::serde::time::ms_since_unix_epoch")]
    pub added_at: SystemTime,
}

#[cfg(test)]
mod tests {
    use std::time::{Duration, UNIX_EPOCH};

    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::{Medium, ThirdPartyIdentifier};

    #[test]
    fn third_party_identifier_serde() {
        let third_party_id = ThirdPartyIdentifier {
            address: "monkey@banana.island".into(),
            medium: Medium::Email,
            validated_at: UNIX_EPOCH + Duration::from_millis(1_535_176_800_000),
            added_at: UNIX_EPOCH + Duration::from_millis(1_535_336_848_756),
        };

        let third_party_id_serialized = json!({
            "medium": "email",
            "address": "monkey@banana.island",
            "validated_at": 1_535_176_800_000u64,
            "added_at": 1_535_336_848_756u64
        });

        assert_eq!(
            to_json_value(third_party_id.clone()).unwrap(),
            third_party_id_serialized
        );
        assert_eq!(
            third_party_id,
            from_json_value(third_party_id_serialized).unwrap()
        );
    }
}
<|endoftext|>


<commit_before>//! Example of decoding from another text encoding on-the-fly while reading.
//! In this case, we're decoding from ISO/IEC 8859-1, which conveniently
//! happens to map 1-to-1 to the first 256 unicode scalar values.

extern crate ropey;

use std::fs::File;
use std::io;
use std::io::Read;

use ropey::RopeBuilder;

fn main() {
    // Get filepath from commandline
    let filepath = if std::env::args().count() > 1 {
        std::env::args().nth(1).unwrap()
    } else {
        println!(
            "You must pass a filepath!  Only recieved {} arguments.",
            std::env::args().count()
        );
        panic!()
    };

    // Get everything set up to begin reading and decoding.
    let mut buf = vec![0u8; 1 << 14]; // Buffer for raw bytes.
    let mut buf_str = String::with_capacity(1 << 14); // Buffer for decoded utf8.
    let mut builder = RopeBuilder::new();
    let mut file = io::BufReader::new(File::open(&filepath).unwrap());

    // Read the data in chunks, decoding and appending to the rope builder
    // as we go.
    // (Note: in real code you should handle errors from the reader!)
    while let Ok(n) = file.read(&mut buf) {
        if n == 0 {
            break;
        }

        // Decode and append the chunk to the rope builder.
        buf_str.clear();
        for &byte in &buf[..n] {
            buf_str.push(byte as char);
        }
        builder.append(&buf_str);
    }

    // Build rope.
    let _rope = builder.finish();
}
<commit_msg>Use STDERR instead of STDOUT for error output<commit_after>//! Example of decoding from another text encoding on-the-fly while reading.
//! In this case, we're decoding from ISO/IEC 8859-1, which conveniently
//! happens to map 1-to-1 to the first 256 unicode scalar values.

extern crate ropey;

use std::fs::File;
use std::io;
use std::io::Read;

use ropey::RopeBuilder;

fn main() {
    // Get filepath from commandline
    let filepath = if std::env::args().count() > 1 {
        std::env::args().nth(1).unwrap()
    } else {
        eprintln!(
            "You must pass a filepath!  Only recieved {} arguments.",
            std::env::args().count()
        );
        panic!()
    };

    // Get everything set up to begin reading and decoding.
    let mut buf = vec![0u8; 1 << 14]; // Buffer for raw bytes.
    let mut buf_str = String::with_capacity(1 << 14); // Buffer for decoded utf8.
    let mut builder = RopeBuilder::new();
    let mut file = io::BufReader::new(File::open(&filepath).unwrap());

    // Read the data in chunks, decoding and appending to the rope builder
    // as we go.
    // (Note: in real code you should handle errors from the reader!)
    while let Ok(n) = file.read(&mut buf) {
        if n == 0 {
            break;
        }

        // Decode and append the chunk to the rope builder.
        buf_str.clear();
        for &byte in &buf[..n] {
            buf_str.push(byte as char);
        }
        builder.append(&buf_str);
    }

    // Build rope.
    let _rope = builder.finish();
}
<|endoftext|>


<commit_before>#![feature(box_patterns)]

use std::fs::File;
use std::fmt::Debug;

extern crate query_planner;
use query_planner::rel::*;
use query_planner::exec::*;

fn main() {

    // define schema for data source (csv file)
    let schema = TupleType {
        columns: vec![
            ColumnMeta { name: String::from("id"), data_type: DataType::UnsignedLong, nullable: false },
            ColumnMeta { name: String::from("name"), data_type: DataType::String, nullable: false }
        ]
    };

    let csv_file = Rel::CsvFile { filename: "test/people.csv".to_string(), schema };

    // create simple filter expression for "id = 2"
    let filter_expr = Rex::BinaryExpr {
        left: Box::new(Rex::TupleValue(0)),
        op: Operator::Eq,
        right: Box::new(Rex::Literal(Value::UnsignedLong(2)))
    };

    // create the selection part of the relational plan, referencing the filter expression
    let selection = Rel::Selection { expr: filter_expr, input: Box::new(csv_file) };

    //TODO: create an execution plan
//    let execution_plan = execute(&selection).unwrap();
//
//    // get iterator over data
//    {
//        let it = execution_plan.scan();
//
//        it.for_each(|t| {
//            println!("{:?}", t);
//        });
//    }

//    for &tuple in &it.as_ref() {
//        println!("{:?}", tuple);
//    }

}
<commit_msg>update example<commit_after>#![feature(box_patterns)]

use std::fs::File;
use std::fmt::Debug;

extern crate query_planner;
use query_planner::rel::*;

extern crate serde_json;

fn main() {

    // define schema for data source (csv file)
    let schema = TupleType {
        columns: vec![
            ColumnMeta { name: String::from("id"), data_type: DataType::UnsignedLong, nullable: false },
            ColumnMeta { name: String::from("name"), data_type: DataType::String, nullable: false }
        ]
    };

    let csv_file = Rel::CsvFile { filename: "test/people.csv".to_string(), schema };

    // create simple filter expression for "id = 2"
    let filter_expr = Rex::BinaryExpr {
        left: Box::new(Rex::TupleValue(0)),
        op: Operator::Eq,
        right: Box::new(Rex::Literal(Value::UnsignedLong(2)))
    };

    // create the selection part of the relational plan, referencing the filter expression
    let plan = Rel::Selection { expr: filter_expr, input: Box::new(csv_file) };

    let rel_str = serde_json::to_string_pretty(&plan).unwrap();

    println!("Relational plan: {}", rel_str);

    //TODO: create an execution plan

//    let execution_plan = execute(&selection).unwrap();
//
//    // get iterator over data
//    {
//        let it = execution_plan.scan();
//
//        it.for_each(|t| {
//            println!("{:?}", t);
//        });
//    }

//    for &tuple in &it.as_ref() {
//        println!("{:?}", tuple);
//    }

}

use query_planner::exec::*;
<|endoftext|>


<commit_before>use crate::Msg;
use chrono::{NaiveDate};
use seed::prelude::*;

pub fn render() -> seed::dom_types::Node<Msg> {
    div![
        h1!["News"],
        br![],
        br![],
        br![],
        El::from_html("

Date	News

28th July 2019	bigprimes.net has been rewritten from the ground up using rust!

22nd January 2019	Ethereum bounty contracts have now been added for anyone that would like to try to push the boundaries of human knowledge. The first contract is a competition for the correct solution to a³+b³+c³ = 33. Tweet me if you need assistance using these contracts!

10th March 2018	Added torrents for the first million primes and first billion prime numbers.

12th November 2017	Site is now running on AWS Lambda, but can still fallback to regular VM hosting if ever needed. Site is now ~40% covered by unit tests.

13th November 2016	Site source code has been converted to PHP7 with Silex framework. Some methods have also been moved to cpp from PHP https://github.com/craigmayhew/bigprimes.net/

28th February 2014	You can now find the websites php source code here https://github.com/craigmayhew/bigprimes.net/

19th November 2011	Thank you to Yu Kwong Yiu Wilson for the donation!

13th July 2011	We are retiring the distributed computing client. Thank you all for your help and processing cycles.
        Watch this space for an open source GPU client coming soon...

10th February 2010	We have added a page that shows the sum of the digits of prime numbers (now retired).

1st February 2010	Thanks to everyone for donating computer time, we are now upto 1.4 billion primes. We now also have a facebook group where you get news updates and show your support for the project!

28th September 2009	Thanks for all your help! We made it to one billion prime numbers! Please keep on donating processor time as we still have plenty of storage for the prime numbers. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

18th August 2009	It's been a while but we have been very busy. We've put together a distributed computing client written in javascript. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

17th July 2008	We've now added a Forum (now retired) which can be found on the navigation links on the left.

14th July 2008	Someone named Kirk just emailed me to say the download links wern't working. I've now fixed this. Thanks Kirk!

4th July 2008	Added much faster code to the cruncher so that we can handle more of your page loads! Lots of little updates and some reorganizing of the site.

23rd June 2007	Added the Downloads section.

11th February 2007	Added the Fibonacci number archive containing the first 70331 Fibonacci numbers.

16th January 2007	Added the 44th Mersenne Prime number to the archive.

12th January 2007	The Archives are now more organized.

28th September 2005	We have managed to archive the first 100 million prime numbers.

20th May 2005	We have managed to archive the first 75 million prime numbers.

16th May 2005	We have managed to archive the first 50 million prime numbers.

14th May 2005	We have managed to archive the first 10 million prime numbers.

13th May 2005	We have managed to archive the first 1 million prime numbers.

"),
    ]
}<commit_msg>Improved latest news update on rust!<commit_after>use crate::Msg;
use chrono::{NaiveDate};
use seed::prelude::*;

pub fn render() -> seed::dom_types::Node<Msg> {
    div![
        h1!["News"],
        br![],
        br![],
        br![],
        El::from_html("

Date	News

28th July 2019	bigprimes.net has been rewritten from the ground up using rust!
All archives have been retired in favour of client side processing in web assembly.

22nd January 2019	Ethereum bounty contracts have now been added for anyone that would like to try to push the boundaries of human knowledge. The first contract is a competition for the correct solution to a³+b³+c³ = 33. Tweet me if you need assistance using these contracts!

10th March 2018	Added torrents for the first million primes and first billion prime numbers.

12th November 2017	Site is now running on AWS Lambda, but can still fallback to regular VM hosting if ever needed. Site is now ~40% covered by unit tests.

13th November 2016	Site source code has been converted to PHP7 with Silex framework. Some methods have also been moved to cpp from PHP https://github.com/craigmayhew/bigprimes.net/

28th February 2014	You can now find the websites php source code here https://github.com/craigmayhew/bigprimes.net/

19th November 2011	Thank you to Yu Kwong Yiu Wilson for the donation!

13th July 2011	We are retiring the distributed computing client. Thank you all for your help and processing cycles.
        Watch this space for an open source GPU client coming soon...

10th February 2010	We have added a page that shows the sum of the digits of prime numbers (now retired).

1st February 2010	Thanks to everyone for donating computer time, we are now upto 1.4 billion primes. We now also have a facebook group where you get news updates and show your support for the project!

28th September 2009	Thanks for all your help! We made it to one billion prime numbers! Please keep on donating processor time as we still have plenty of storage for the prime numbers. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

18th August 2009	It's been a while but we have been very busy. We've put together a distributed computing client written in javascript. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

17th July 2008	We've now added a Forum (now retired) which can be found on the navigation links on the left.

14th July 2008	Someone named Kirk just emailed me to say the download links wern't working. I've now fixed this. Thanks Kirk!

4th July 2008	Added much faster code to the cruncher so that we can handle more of your page loads! Lots of little updates and some reorganizing of the site.

23rd June 2007	Added the Downloads section.

11th February 2007	Added the Fibonacci number archive containing the first 70331 Fibonacci numbers.

16th January 2007	Added the 44th Mersenne Prime number to the archive.

12th January 2007	The Archives are now more organized.

28th September 2005	We have managed to archive the first 100 million prime numbers.

20th May 2005	We have managed to archive the first 75 million prime numbers.

16th May 2005	We have managed to archive the first 50 million prime numbers.

14th May 2005	We have managed to archive the first 10 million prime numbers.

13th May 2005	We have managed to archive the first 1 million prime numbers.

"),
    ]
}<|endoftext|>