<commit_before>//! The Brainfuck interpreter executable.
//!
//! ```
//! USAGE:
//! bfi [FLAGS] [OPTIONS] [--] [INPUT]...
//!
//! FLAGS:
//! --ast          Interpret the unoptimized AST
//! --flat         Flatten to bytecode (implies --peep)
//! -h, --help         Prints help information
//! --jit          JIT to native x64 (implies --peep)
//! --peep         Peephole optimize (default, implies --rle)
//! --rle          Run-length encode the AST
//! -u, --unchecked    Omit memory bounds checks in JIT
//! -V, --version      Prints version information
//!
//! OPTIONS:
//! -e, --expr <CODE>...    BF code to execute
//! -s, --size <SIZE>       Memory size in bytes (default 30,000)
//!
//! ARGS:
//! <INPUT>...    The source file(s) to interpret
//! ```
//!
//! See [the library crate documentation](../bf/index.html) for more.

extern crate bf;
extern crate clap;

use std::io::{self, Read, Write};
use std::fs::File;
use std::process::exit;

use clap::{Arg, App};

use bf::ast;
use bf::rle;
use bf::flat;
use bf::peephole;

#[cfg(feature = "jit")]
use bf::jit;

use bf::traits::Interpretable;

const VERSION: &'static str = "0.2.5";

#[derive(Debug, Clone)]
struct Options {
    program_text:  Vec<u8>,
    memory_size:   Option<usize>,
    compiler_pass: Pass,
    unchecked:     bool,
}

#[derive(Debug, Clone, Copy)]
enum Pass {
    Ast,
    Rle,
    Flat,
    Peep,
    #[cfg(feature = "jit")]
    Jit,
}

fn main() {
    // Process command-line options:
    let options = get_options();

    // Parse the program to AST:
    let program = parse(&options);

    match options.compiler_pass {
        Pass::Ast => {
            interpret(&*program, &options);
        }

        Pass::Rle => {
            let program = rle::compile(&program);
            interpret(&*program, &options);
        }

        Pass::Peep => {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            interpret(&*program, &options);
        }

        Pass::Flat => {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            let program = flat::compile(&program);
            interpret(&*program, &options);
        }

        #[cfg(feature = "jit")]
        Pass::Jit => {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            let program = jit::compile(&program, !options.unchecked);
            interpret(&program, &options);
        }
    }
}

fn parse(options: &Options) -> Box<ast::Program> {
    ast::parse_program(&options.program_text)
        .unwrap_or_else(|e| error_exit(2, format!("Syntax error: {}.", e)))
}

fn interpret<P: Interpretable + ?Sized>(program: &P, options: &Options) {
    program.interpret_stdin(options.memory_size)
        .unwrap_or_else(|e| error_exit(3, format!("Runtime error: {}.", e)))
}

#[cfg(feature="jit")]
const DEFAULT_PASS: Pass = Pass::Jit;

#[cfg(not(feature="jit"))]
const DEFAULT_PASS: Pass = Pass::Peep;

fn get_options() -> Options {
    let mut result = Options {
        program_text:  Vec::new(),
        memory_size:   None,
        compiler_pass: DEFAULT_PASS,
        unchecked:     false,
    };

    let matches = build_clap_app().get_matches();

    if let Some(size) = matches.value_of("size") {
        let size = size.parse()
            .unwrap_or_else(|e| error_exit(1, format!("Could not parse memory size: {}", e)));
        result.memory_size = Some(size);
    }

    if matches.is_present("ast") {
        result.compiler_pass = Pass::Ast;
    } else if matches.is_present("jit") {
        #[cfg(feature = "jit")]
        let _ = result.compiler_pass = Pass::Jit;
    } else if matches.is_present("flat") {
        result.compiler_pass = Pass::Flat;
    } else if matches.is_present("peep") {
        result.compiler_pass = Pass::Peep;
    } else if matches.is_present("rle") {
        result.compiler_pass = Pass::Rle;
    }

    if matches.is_present("unchecked") {
        result.unchecked = true;
    }

    if let Some(exprs) = matches.values_of("expr") {
        for e in exprs {
            result.program_text.extend(e.as_bytes());
        }
    } else if let Some(files) = matches.values_of("INPUT") {
        for f in files {
            let mut file = File::open(f)
                .unwrap_or_else(|e| error_exit(1, format!("{}: {}", e, f)));
            file.read_to_end(&mut result.program_text)
                .unwrap_or_else(|e| error_exit(1, format!("{}: {}", e, f)));
        }
    } else {
        error_exit(1, "No program given.".to_owned());
    }

    result
}

fn build_clap_app() -> App<'static, 'static> {
    let app = App::new("bfi")
        .version(VERSION)
        .author("Jesse A. Tov <jesse.tov@gmail.com>")
        .about("A Brainfuck interpreter")
        .arg(Arg::with_name("expr")
            .short("e")
            .long("expr")
            .value_name("CODE")
            .help("BF code to execute")
            .multiple(true)
            .takes_value(true)
            .conflicts_with("INPUT"))
        .arg(Arg::with_name("INPUT")
            .help("The source file(s) to interpret")
            .multiple(true)
            .conflicts_with("expr")
            .index(1))
        .arg(Arg::with_name("size")
            .short("s")
            .long("size")
            .value_name("SIZE")
            .help("Memory size in bytes (default 30,000)")
            .takes_value(true))
        .arg(Arg::with_name("ast")
            .long("ast")
            .help("Interpret the unoptimized AST")
            .conflicts_with_all(&["rle", "peep", "flat", "jit"]))
        .arg(Arg::with_name("rle")
            .long("rle")
            .help("Run-length encode the AST"))
        .arg(Arg::with_name("peep")
            .long("peep")
            .help(if cfg!(feature = "jit") {"Peephole optimize (implies --rle)"}
                  else {"Peephole optimize (default, implies --rle)"}))
        .arg(Arg::with_name("flat")
            .long("flat")
            .help("Flatten to bytecode (implies --peep)")
            .conflicts_with("jit"));

    #[cfg(feature = "jit")]
    let app = app
        .arg(Arg::with_name("jit")
            .long("jit")
            .help("JIT to native x64 (default, implies --peep)")
            .conflicts_with("flat"))
        .arg(Arg::with_name("unchecked")
            .short("u")
            .long("unchecked")
            .help("Omit memory bounds checks in JIT"));

    app
}

fn error_exit(code: i32, msg: String) -> ! {
    writeln!(io::stderr(), "{}", msg).unwrap();
    exit(code)
}

<commit_msg>Updated usage information to match.<commit_after>//! The Brainfuck interpreter executable.
//!
//! ```
//! USAGE:
//! bfi [FLAGS] [OPTIONS] [--] [INPUT]...
//!
//! FLAGS:
//! --ast          Interpret the unoptimized AST
//! --flat         Flatten to bytecode (implies --peep)
//! -h, --help         Prints help information
//! --jit          JIT to native x64 (default, implies --peep)
//! --peep         Peephole optimize (implies --rle)
//! --rle          Run-length encode the AST
//! -u, --unchecked    Omit memory bounds checks in JIT
//! -V, --version      Prints version information
//!
//! OPTIONS:
//! -e, --expr <CODE>...    BF code to execute
//! -s, --size <SIZE>       Memory size in bytes (default 30,000)
//!
//! ARGS:
//! <INPUT>...    The source file(s) to interpret
//! ```
//!
//! See [the library crate documentation](../bf/index.html) for more.

extern crate bf;
extern crate clap;

use std::io::{self, Read, Write};
use std::fs::File;
use std::process::exit;

use clap::{Arg, App};

use bf::ast;
use bf::rle;
use bf::flat;
use bf::peephole;

#[cfg(feature = "jit")]
use bf::jit;

use bf::traits::Interpretable;

const VERSION: &'static str = "0.2.5";

#[derive(Debug, Clone)]
struct Options {
    program_text:  Vec<u8>,
    memory_size:   Option<usize>,
    compiler_pass: Pass,
    unchecked:     bool,
}

#[derive(Debug, Clone, Copy)]
enum Pass {
    Ast,
    Rle,
    Flat,
    Peep,
    #[cfg(feature = "jit")]
    Jit,
}

fn main() {
    // Process command-line options:
    let options = get_options();

    // Parse the program to AST:
    let program = parse(&options);

    match options.compiler_pass {
        Pass::Ast => {
            interpret(&*program, &options);
        }

        Pass::Rle => {
            let program = rle::compile(&program);
            interpret(&*program, &options);
        }

        Pass::Peep => {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            interpret(&*program, &options);
        }

        Pass::Flat => {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            let program = flat::compile(&program);
            interpret(&*program, &options);
        }

        #[cfg(feature = "jit")]
        Pass::Jit => {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            let program = jit::compile(&program, !options.unchecked);
            interpret(&program, &options);
        }
    }
}

fn parse(options: &Options) -> Box<ast::Program> {
    ast::parse_program(&options.program_text)
        .unwrap_or_else(|e| error_exit(2, format!("Syntax error: {}.", e)))
}

fn interpret<P: Interpretable + ?Sized>(program: &P, options: &Options) {
    program.interpret_stdin(options.memory_size)
        .unwrap_or_else(|e| error_exit(3, format!("Runtime error: {}.", e)))
}

#[cfg(feature="jit")]
const DEFAULT_PASS: Pass = Pass::Jit;

#[cfg(not(feature="jit"))]
const DEFAULT_PASS: Pass = Pass::Peep;

fn get_options() -> Options {
    let mut result = Options {
        program_text:  Vec::new(),
        memory_size:   None,
        compiler_pass: DEFAULT_PASS,
        unchecked:     false,
    };

    let matches = build_clap_app().get_matches();

    if let Some(size) = matches.value_of("size") {
        let size = size.parse()
            .unwrap_or_else(|e| error_exit(1, format!("Could not parse memory size: {}", e)));
        result.memory_size = Some(size);
    }

    if matches.is_present("ast") {
        result.compiler_pass = Pass::Ast;
    } else if matches.is_present("jit") {
        #[cfg(feature = "jit")]
        let _ = result.compiler_pass = Pass::Jit;
    } else if matches.is_present("flat") {
        result.compiler_pass = Pass::Flat;
    } else if matches.is_present("peep") {
        result.compiler_pass = Pass::Peep;
    } else if matches.is_present("rle") {
        result.compiler_pass = Pass::Rle;
    }

    if matches.is_present("unchecked") {
        result.unchecked = true;
    }

    if let Some(exprs) = matches.values_of("expr") {
        for e in exprs {
            result.program_text.extend(e.as_bytes());
        }
    } else if let Some(files) = matches.values_of("INPUT") {
        for f in files {
            let mut file = File::open(f)
                .unwrap_or_else(|e| error_exit(1, format!("{}: {}", e, f)));
            file.read_to_end(&mut result.program_text)
                .unwrap_or_else(|e| error_exit(1, format!("{}: {}", e, f)));
        }
    } else {
        error_exit(1, "No program given.".to_owned());
    }

    result
}

fn build_clap_app() -> App<'static, 'static> {
    let app = App::new("bfi")
        .version(VERSION)
        .author("Jesse A. Tov <jesse.tov@gmail.com>")
        .about("A Brainfuck interpreter")
        .arg(Arg::with_name("expr")
            .short("e")
            .long("expr")
            .value_name("CODE")
            .help("BF code to execute")
            .multiple(true)
            .takes_value(true)
            .conflicts_with("INPUT"))
        .arg(Arg::with_name("INPUT")
            .help("The source file(s) to interpret")
            .multiple(true)
            .conflicts_with("expr")
            .index(1))
        .arg(Arg::with_name("size")
            .short("s")
            .long("size")
            .value_name("SIZE")
            .help("Memory size in bytes (default 30,000)")
            .takes_value(true))
        .arg(Arg::with_name("ast")
            .long("ast")
            .help("Interpret the unoptimized AST")
            .conflicts_with_all(&["rle", "peep", "flat", "jit"]))
        .arg(Arg::with_name("rle")
            .long("rle")
            .help("Run-length encode the AST"))
        .arg(Arg::with_name("peep")
            .long("peep")
            .help(if cfg!(feature = "jit") {"Peephole optimize (implies --rle)"}
                  else {"Peephole optimize (default, implies --rle)"}))
        .arg(Arg::with_name("flat")
            .long("flat")
            .help("Flatten to bytecode (implies --peep)")
            .conflicts_with("jit"));

    #[cfg(feature = "jit")]
    let app = app
        .arg(Arg::with_name("jit")
            .long("jit")
            .help("JIT to native x64 (default, implies --peep)")
            .conflicts_with("flat"))
        .arg(Arg::with_name("unchecked")
            .short("u")
            .long("unchecked")
            .help("Omit memory bounds checks in JIT"));

    app
}

fn error_exit(code: i32, msg: String) -> ! {
    writeln!(io::stderr(), "{}", msg).unwrap();
    exit(code)
}

<|endoftext|>


<commit_before>use std::cmp::min;
use std::mem::replace;

use it;

use ::{Point, Vector};
use bounds::{Axis, Bounds3f};
use primitive::Primitive;
use ray::Ray;

pub struct BVH<T: Primitive> {
    max_prims_per_node: usize,
    primitives: Vec<T>,
    nodes: Vec<LinearBVHNode>,
}

impl<T: Primitive> BVH<T> {
    pub fn new(max_prims_per_node: usize, prims: &mut Vec<T>) -> BVH<T> {
        info!("Generating BVH:");

        // 1. Get bounds info
        info!("\tGenerating primitive info");
        let mut primitive_info: Vec<BVHPrimitiveInfo> = prims.iter()
            .enumerate()
            .map(|(i, p)| BVHPrimitiveInfo::new(i, p.world_bounds()))
            .collect();

        // 2. Build tree
        info!("\tBuilding tree for {} primitives", prims.len());
        let mut total_nodes = 0;
        let mut ordered_prims_idx = Vec::with_capacity(prims.len());
        let root: BVHBuildNode = BVH::<T>::recursive_build(&mut primitive_info,
                                                           0usize,
                                                           prims.len(),
                                                           max_prims_per_node,
                                                           &mut total_nodes,
                                                           &mut ordered_prims_idx);

        // Sort the primitives according to the indices in ordered_prims_idx. This is made tricky
        // due to the fact that a vector owns its elements, which means we can't easily move
        // elements from one vector to another. We have to use drain() instead. Also, zip() and
        // enumerate() are defined on Iterator, and sort_by_key() is defined on Vector, causing a
        // lot of iter()/collect() shennanigans...
        let mut sorted_idx: Vec<(usize, &usize)> = ordered_prims_idx.iter().enumerate().collect();
        sorted_idx.sort_by_key(|i| i.1);

        let mut prims_with_idx: Vec<(T, usize)> =
            prims.drain(..).zip(sorted_idx.iter().map(|i| i.0)).collect();
        prims_with_idx.sort_by_key(|i| i.1);
        let ordered_prims: Vec<T> = prims_with_idx.drain(..).map(|i| i.0).collect();

        info!("\tCreated {} nodes", total_nodes);
        info!("\tOrdered {} primitives", ordered_prims.len());

        // 3. Build flatten representation
        info!("\tFlattening tree");
        let mut nodes = Vec::with_capacity(total_nodes);
        BVH::<T>::flatten_bvh(&root, &mut nodes);
        assert!(nodes.len() == total_nodes);

        BVH {
            max_prims_per_node: min(max_prims_per_node, 255),
            primitives: ordered_prims,
            nodes: nodes,
        }
    }

    fn recursive_build(build_data: &mut Vec<BVHPrimitiveInfo>,
                       start: usize,
                       end: usize,
                       max_prims_per_node: usize,
                       total_nodes: &mut usize,
                       ordered_prims: &mut Vec<usize>)
                       -> BVHBuildNode {
        *total_nodes += 1;
        let n_primitives = end - start;
        assert!(start != end);
        // Compute bounds of all primitives in node
        let bbox = build_data[start..end]
            .iter()
            .fold(Bounds3f::new(), |b, pi| Bounds3f::union(&b, &pi.bounds));
        if n_primitives == 1 {
            // Create leaf
            let first_prim_offset = ordered_prims.len();
            for pi in build_data[start..end].iter() {
                ordered_prims.push(pi.prim_number);
            }
            BVHBuildNode::leaf(first_prim_offset, n_primitives, bbox)
        } else {
            // Compute bounds of primitive centroids
            let centroids_bounds = build_data[start..end]
                .iter()
                .fold(Bounds3f::new(),
                      |bb, pi| Bounds3f::union_point(&bb, &pi.centroid));
            // Choose split dimension
            let dimension = centroids_bounds.maximum_extent();
            // Partition primitives into 2 sets and build children
            if centroids_bounds[0][dimension] == centroids_bounds[1][dimension] {
                let first_prim_offset = ordered_prims.len();
                for pi in build_data[start..end].iter() {
                    ordered_prims.push(pi.prim_number);
                }
                return BVHBuildNode::leaf(first_prim_offset, n_primitives, bbox);
            }
            // Partition primitives based on split method (here split middle)
            let pmid = 0.5 * (centroids_bounds[0][dimension] + centroids_bounds[1][dimension]);
            let mut mid = it::partition(build_data[start..end].iter_mut(),
                                        |pi| pi.centroid[dimension] < pmid) +
                          start;
            if mid == start || mid == end {
                // If partition failed, used Split Equal method
                build_data[start..end].sort_by(|p1, p2| {
                    p1.centroid[dimension]
                        .partial_cmp(&p2.centroid[dimension])
                        .unwrap()
                });
                mid = (start + end) / 2;
            }

            BVHBuildNode::interior(dimension,
                                   Box::new(BVH::<T>::recursive_build(build_data,
                                                                      start,
                                                                      mid,
                                                                      max_prims_per_node,
                                                                      total_nodes,
                                                                      ordered_prims)),
                                   Box::new(BVH::<T>::recursive_build(build_data,
                                                                      mid,
                                                                      end,
                                                                      max_prims_per_node,
                                                                      total_nodes,
                                                                      ordered_prims)))

        }
    }

    fn flatten_bvh(node: &BVHBuildNode, nodes: &mut Vec<LinearBVHNode>) -> usize {
        let offset = nodes.len();

        match *node {
            BVHBuildNode::Leaf { first_prim_offset, num_prims, .. } => {
                let linear_node = LinearBVHNode {
                    bounds: *node.bounds(),
                    data: LinearBVHNodeData::Leaf {
                        num_prims: num_prims,
                        primitives_offset: first_prim_offset,
                    },
                };
                nodes.push(linear_node);
            }
            BVHBuildNode::Interior { split_axis, ref children, .. } => {
                let linear_node = LinearBVHNode {
                    bounds: *node.bounds(),
                    data: LinearBVHNodeData::Interior {
                        axis: split_axis,
                        second_child_offset: 0,
                    },
                };
                nodes.push(linear_node);
                BVH::<T>::flatten_bvh(&*children[0], nodes);
                let second_offset = BVH::<T>::flatten_bvh(&*children[1], nodes);
                replace(&mut nodes[offset].data,
                        LinearBVHNodeData::Interior {
                            axis: split_axis,
                            second_child_offset: second_offset,
                        });
            }
        }

        offset
    }

    pub fn intersect<'a, R, F>(&'a self, ray: &mut Ray, f: F) -> Option<R>
        where F: Fn(&mut Ray, &'a T) -> Option<R>
    {
        if self.nodes.is_empty() {
            return None;
        }
        let mut result = None;

        let mut to_visit_offset = 0;
        let mut current_node_idx = 0;
        let mut nodes_to_visit = [0; 64];
        let inv_dir = Vector::new(1.0 / ray.d.x, 1.0 / ray.d.y, 1.0 / ray.d.z);
        let dir_is_neg =
            [(inv_dir.x < 0.0) as usize, (inv_dir.y < 0.0) as usize, (inv_dir.z < 0.0) as usize];
        loop {
            let linear_node = &self.nodes[current_node_idx];
            if linear_node.bounds.intersect_p_fast(ray, &inv_dir, &dir_is_neg) {
                match linear_node.data {
                    LinearBVHNodeData::Leaf { num_prims, primitives_offset } => {
                        for i in 0..num_prims {
                            result = f(ray, &self.primitives[primitives_offset + i]).or(result);
                            // if let Some(isect) = f(ray, &self.primitives[primitives_offset + i]) {
                            //     result = Some(isect);
                            // }
                        }
                        if to_visit_offset == 0 {
                            break;
                        }
                        to_visit_offset -= 1;
                        current_node_idx = nodes_to_visit[to_visit_offset];
                    }
                    LinearBVHNodeData::Interior { axis, second_child_offset, .. } => {
                        let axis_num = match axis {
                            Axis::X => 0,
                            Axis::Y => 1,
                            Axis::Z => 2,
                        };
                        if dir_is_neg[axis_num] != 0 {
                            nodes_to_visit[to_visit_offset] = current_node_idx + 1;
                            to_visit_offset += 1;
                            current_node_idx = second_child_offset;
                        } else {
                            nodes_to_visit[to_visit_offset] = second_child_offset;
                            to_visit_offset += 1;
                            current_node_idx += 1;
                        }
                    }
                }
            } else {
                if to_visit_offset == 0 {
                    break;
                }
                to_visit_offset -= 1;
                current_node_idx = nodes_to_visit[to_visit_offset];
            }

        }
        result
    }
}

struct BVHPrimitiveInfo {
    pub prim_number: usize,
    pub centroid: Point,
    pub bounds: Bounds3f,
}

impl BVHPrimitiveInfo {
    fn new(pn: usize, bb: Bounds3f) -> BVHPrimitiveInfo {
        BVHPrimitiveInfo {
            prim_number: pn,
            centroid: (0.5 * bb[0].to_vector() + 0.5 * bb[1].to_vector()).to_point(),
            bounds: bb,
        }
    }
}

enum BVHBuildNode {
    Interior {
        bounds: Bounds3f,
        children: [Box<BVHBuildNode>; 2],
        split_axis: Axis,
    },
    Leaf {
        bounds: Bounds3f,
        first_prim_offset: usize,
        num_prims: usize,
    },
}

impl BVHBuildNode {
    fn interior(axis: Axis, child1: Box<BVHBuildNode>, child2: Box<BVHBuildNode>) -> BVHBuildNode {
        let bbox = Bounds3f::union(child1.bounds(), child2.bounds());
        BVHBuildNode::Interior {
            bounds: bbox,
            children: [child1, child2],
            split_axis: axis,
        }
    }

    fn leaf(first_prim_offset: usize, num_prims: usize, bbox: Bounds3f) -> BVHBuildNode {
        BVHBuildNode::Leaf {
            bounds: bbox,
            first_prim_offset: first_prim_offset,
            num_prims: num_prims,
        }
    }

    fn bounds(&self) -> &Bounds3f {
        match *self {
            BVHBuildNode::Interior { ref bounds, .. } |
            BVHBuildNode::Leaf { ref bounds, .. } => bounds,
        }
    }
}

#[derive(Debug)]
enum LinearBVHNodeData {
    Interior {
        second_child_offset: usize,
        axis: Axis,
    },
    Leaf {
        primitives_offset: usize,
        num_prims: usize,
    },
}

#[derive(Debug)]
struct LinearBVHNode {
    bounds: Bounds3f,
    data: LinearBVHNodeData,
}
<commit_msg>Implement Primitive for BVH<commit_after>use std::cmp::min;
use std::mem::replace;
use std::sync::Arc;

use it;

use ::{Point, Vector};
use bounds::{Axis, Bounds3f};
use interaction::SurfaceInteraction;
use light::AreaLight;
use material::{Material, TransportMode};
use primitive::Primitive;
use ray::Ray;

pub struct BVH<T> {
    max_prims_per_node: usize,
    primitives: Vec<T>,
    nodes: Vec<LinearBVHNode>,
}

impl<T: Primitive> BVH<T> {
    pub fn new(max_prims_per_node: usize, prims: &mut Vec<T>) -> BVH<T> {
        info!("Generating BVH:");

        // 1. Get bounds info
        info!("\tGenerating primitive info");
        let mut primitive_info: Vec<BVHPrimitiveInfo> = prims.iter()
            .enumerate()
            .map(|(i, p)| BVHPrimitiveInfo::new(i, p.world_bounds()))
            .collect();

        // 2. Build tree
        info!("\tBuilding tree for {} primitives", prims.len());
        let mut total_nodes = 0;
        let mut ordered_prims_idx = Vec::with_capacity(prims.len());
        let root: BVHBuildNode = BVH::<T>::recursive_build(&mut primitive_info,
                                                           0usize,
                                                           prims.len(),
                                                           max_prims_per_node,
                                                           &mut total_nodes,
                                                           &mut ordered_prims_idx);

        // Sort the primitives according to the indices in ordered_prims_idx. This is made tricky
        // due to the fact that a vector owns its elements, which means we can't easily move
        // elements from one vector to another. We have to use drain() instead. Also, zip() and
        // enumerate() are defined on Iterator, and sort_by_key() is defined on Vector, causing a
        // lot of iter()/collect() shennanigans...
        let mut sorted_idx: Vec<(usize, &usize)> = ordered_prims_idx.iter().enumerate().collect();
        sorted_idx.sort_by_key(|i| i.1);

        let mut prims_with_idx: Vec<(T, usize)> =
            prims.drain(..).zip(sorted_idx.iter().map(|i| i.0)).collect();
        prims_with_idx.sort_by_key(|i| i.1);
        let ordered_prims: Vec<T> = prims_with_idx.drain(..).map(|i| i.0).collect();

        info!("\tCreated {} nodes", total_nodes);
        info!("\tOrdered {} primitives", ordered_prims.len());

        // 3. Build flatten representation
        info!("\tFlattening tree");
        let mut nodes = Vec::with_capacity(total_nodes);
        BVH::<T>::flatten_bvh(&root, &mut nodes);
        assert!(nodes.len() == total_nodes);

        BVH {
            max_prims_per_node: min(max_prims_per_node, 255),
            primitives: ordered_prims,
            nodes: nodes,
        }
    }

    fn recursive_build(build_data: &mut Vec<BVHPrimitiveInfo>,
                       start: usize,
                       end: usize,
                       max_prims_per_node: usize,
                       total_nodes: &mut usize,
                       ordered_prims: &mut Vec<usize>)
                       -> BVHBuildNode {
        *total_nodes += 1;
        let n_primitives = end - start;
        assert!(start != end);
        // Compute bounds of all primitives in node
        let bbox = build_data[start..end]
            .iter()
            .fold(Bounds3f::new(), |b, pi| Bounds3f::union(&b, &pi.bounds));
        if n_primitives == 1 {
            // Create leaf
            let first_prim_offset = ordered_prims.len();
            for pi in build_data[start..end].iter() {
                ordered_prims.push(pi.prim_number);
            }
            BVHBuildNode::leaf(first_prim_offset, n_primitives, bbox)
        } else {
            // Compute bounds of primitive centroids
            let centroids_bounds = build_data[start..end]
                .iter()
                .fold(Bounds3f::new(),
                      |bb, pi| Bounds3f::union_point(&bb, &pi.centroid));
            // Choose split dimension
            let dimension = centroids_bounds.maximum_extent();
            // Partition primitives into 2 sets and build children
            if centroids_bounds[0][dimension] == centroids_bounds[1][dimension] {
                let first_prim_offset = ordered_prims.len();
                for pi in build_data[start..end].iter() {
                    ordered_prims.push(pi.prim_number);
                }
                return BVHBuildNode::leaf(first_prim_offset, n_primitives, bbox);
            }
            // Partition primitives based on split method (here split middle)
            let pmid = 0.5 * (centroids_bounds[0][dimension] + centroids_bounds[1][dimension]);
            let mut mid = it::partition(build_data[start..end].iter_mut(),
                                        |pi| pi.centroid[dimension] < pmid) +
                          start;
            if mid == start || mid == end {
                // If partition failed, used Split Equal method
                build_data[start..end].sort_by(|p1, p2| {
                    p1.centroid[dimension]
                        .partial_cmp(&p2.centroid[dimension])
                        .unwrap()
                });
                mid = (start + end) / 2;
            }

            BVHBuildNode::interior(dimension,
                                   Box::new(BVH::<T>::recursive_build(build_data,
                                                                      start,
                                                                      mid,
                                                                      max_prims_per_node,
                                                                      total_nodes,
                                                                      ordered_prims)),
                                   Box::new(BVH::<T>::recursive_build(build_data,
                                                                      mid,
                                                                      end,
                                                                      max_prims_per_node,
                                                                      total_nodes,
                                                                      ordered_prims)))

        }
    }

    fn flatten_bvh(node: &BVHBuildNode, nodes: &mut Vec<LinearBVHNode>) -> usize {
        let offset = nodes.len();

        match *node {
            BVHBuildNode::Leaf { first_prim_offset, num_prims, .. } => {
                let linear_node = LinearBVHNode {
                    bounds: *node.bounds(),
                    data: LinearBVHNodeData::Leaf {
                        num_prims: num_prims,
                        primitives_offset: first_prim_offset,
                    },
                };
                nodes.push(linear_node);
            }
            BVHBuildNode::Interior { split_axis, ref children, .. } => {
                let linear_node = LinearBVHNode {
                    bounds: *node.bounds(),
                    data: LinearBVHNodeData::Interior {
                        axis: split_axis,
                        second_child_offset: 0,
                    },
                };
                nodes.push(linear_node);
                BVH::<T>::flatten_bvh(&*children[0], nodes);
                let second_offset = BVH::<T>::flatten_bvh(&*children[1], nodes);
                replace(&mut nodes[offset].data,
                        LinearBVHNodeData::Interior {
                            axis: split_axis,
                            second_child_offset: second_offset,
                        });
            }
        }

        offset
    }

    pub fn intersect(&self, ray: &mut Ray) -> Option<SurfaceInteraction> {
        if self.nodes.is_empty() {
            return None;
        }
        let mut result = None;

        let mut to_visit_offset = 0;
        let mut current_node_idx = 0;
        let mut nodes_to_visit = [0; 64];
        let inv_dir = Vector::new(1.0 / ray.d.x, 1.0 / ray.d.y, 1.0 / ray.d.z);
        let dir_is_neg =
            [(inv_dir.x < 0.0) as usize, (inv_dir.y < 0.0) as usize, (inv_dir.z < 0.0) as usize];
        loop {
            let linear_node = &self.nodes[current_node_idx];
            if linear_node.bounds.intersect_p_fast(ray, &inv_dir, &dir_is_neg) {
                match linear_node.data {
                    LinearBVHNodeData::Leaf { num_prims, primitives_offset } => {
                        for i in 0..num_prims {
                            result =
                                self.primitives[primitives_offset + i].intersect(ray).or(result);
                            // if let Some(isect) = f(ray, &self.primitives[primitives_offset + i]) {
                            //     result = Some(isect);
                            // }
                        }
                        if to_visit_offset == 0 {
                            break;
                        }
                        to_visit_offset -= 1;
                        current_node_idx = nodes_to_visit[to_visit_offset];
                    }
                    LinearBVHNodeData::Interior { axis, second_child_offset, .. } => {
                        let axis_num = match axis {
                            Axis::X => 0,
                            Axis::Y => 1,
                            Axis::Z => 2,
                        };
                        if dir_is_neg[axis_num] != 0 {
                            nodes_to_visit[to_visit_offset] = current_node_idx + 1;
                            to_visit_offset += 1;
                            current_node_idx = second_child_offset;
                        } else {
                            nodes_to_visit[to_visit_offset] = second_child_offset;
                            to_visit_offset += 1;
                            current_node_idx += 1;
                        }
                    }
                }
            } else {
                if to_visit_offset == 0 {
                    break;
                }
                to_visit_offset -= 1;
                current_node_idx = nodes_to_visit[to_visit_offset];
            }

        }
        result
    }
}

impl<T: Primitive> Primitive for BVH<T> {
    fn world_bounds(&self) -> Bounds3f {
        self.primitives[0].world_bounds()
    }

    fn intersect(&self, ray: &mut Ray) -> Option<SurfaceInteraction> {
        self.intersect(ray)
    }

    fn intersect_p(&self, ray: &Ray) -> bool {
        self.intersect_p(ray)
    }

    fn area_light(&self) -> Option<Arc<AreaLight + Send + Sync>> {
        panic!("area_light() should not be called on an Aggregate Primitive!");
    }

    fn material(&self) -> Option<Arc<Material + Send + Sync>> {
        panic!("material() should not be called on an Aggregate Primitive!");
    }

    fn compute_scattering_functions(&self,
                                    isect: &mut SurfaceInteraction,
                                    mode: TransportMode,
                                    allow_multiple_lobes: bool) {
        panic!("compute_scattering_functions() should not be called on an Aggregate Primitive!");
    }
}

struct BVHPrimitiveInfo {
    pub prim_number: usize,
    pub centroid: Point,
    pub bounds: Bounds3f,
}

impl BVHPrimitiveInfo {
    fn new(pn: usize, bb: Bounds3f) -> BVHPrimitiveInfo {
        BVHPrimitiveInfo {
            prim_number: pn,
            centroid: (0.5 * bb[0].to_vector() + 0.5 * bb[1].to_vector()).to_point(),
            bounds: bb,
        }
    }
}

enum BVHBuildNode {
    Interior {
        bounds: Bounds3f,
        children: [Box<BVHBuildNode>; 2],
        split_axis: Axis,
    },
    Leaf {
        bounds: Bounds3f,
        first_prim_offset: usize,
        num_prims: usize,
    },
}

impl BVHBuildNode {
    fn interior(axis: Axis, child1: Box<BVHBuildNode>, child2: Box<BVHBuildNode>) -> BVHBuildNode {
        let bbox = Bounds3f::union(child1.bounds(), child2.bounds());
        BVHBuildNode::Interior {
            bounds: bbox,
            children: [child1, child2],
            split_axis: axis,
        }
    }

    fn leaf(first_prim_offset: usize, num_prims: usize, bbox: Bounds3f) -> BVHBuildNode {
        BVHBuildNode::Leaf {
            bounds: bbox,
            first_prim_offset: first_prim_offset,
            num_prims: num_prims,
        }
    }

    fn bounds(&self) -> &Bounds3f {
        match *self {
            BVHBuildNode::Interior { ref bounds, .. } |
            BVHBuildNode::Leaf { ref bounds, .. } => bounds,
        }
    }
}

#[derive(Debug)]
enum LinearBVHNodeData {
    Interior {
        second_child_offset: usize,
        axis: Axis,
    },
    Leaf {
        primitives_offset: usize,
        num_prims: usize,
    },
}

#[derive(Debug)]
struct LinearBVHNode {
    bounds: Bounds3f,
    data: LinearBVHNodeData,
}
<|endoftext|>


<commit_before>//! In-memory evented channels.
//!
//! This module contains a `Sender` and `Receiver` pair types which can be used
//! to send messages between different future tasks.

use std::io;
use std::sync::mpsc::TryRecvError;

use futures::{Poll, Async};
use futures::stream::Stream;
use mio::channel;

use reactor::{Handle, PollEvented};

/// The transmission half of a channel used for sending messages to a receiver.
///
/// A `Sender` can be `clone`d to have multiple threads or instances sending
/// messages to one receiver.
///
/// This type is created by the `channel` function.
pub struct Sender<T> {
    tx: channel::Sender<T>,
}

/// The receiving half of a channel used for processing messages sent by a
/// `Sender`.
///
/// A `Receiver` cannot be cloned, so only one thread can receive messages at a
/// time.
///
/// This type is created by the `channel` function and implements the `Stream`
/// trait to represent received messages.
pub struct Receiver<T> {
    rx: PollEvented<channel::Receiver<T>>,
}

/// Creates a new in-memory channel used for sending data across `Send +
/// 'static` boundaries, frequently threads.
///
/// This type can be used to conveniently send messages between futures.
/// Unlike the futures crate `channel` method and types, the returned tx/rx
/// pair is a multi-producer single-consumer (mpsc) channel *with no
/// backpressure*. Currently it's left up to the application to implement a
/// mechanism, if necessary, to avoid messages piling up.
///
/// The returned `Sender` can be used to send messages that are processed by
/// the returned `Receiver`. The `Sender` can be cloned to send messages
/// from multiple sources simultaneously.
pub fn channel<T>(handle: &Handle) -> io::Result<(Sender<T>, Receiver<T>)>
    where T: Send + 'static,
{
    let (tx, rx) = channel::channel();
    let rx = try!(PollEvented::new(rx, handle));
    Ok((Sender { tx: tx }, Receiver { rx: rx }))
}

impl<T> Sender<T> {
    /// Sends a message to the corresponding receiver of this sender.
    ///
    /// The message provided will be enqueued on the channel immediately, and
    /// this function will return immediately. Keep in mind that the
    /// underlying channel has infinite capacity, and this may not always be
    /// desired.
    ///
    /// If an I/O error happens while sending the message, or if the receiver
    /// has gone away, then an error will be returned. Note that I/O errors here
    /// are generally quite abnormal.
    pub fn send(&self, t: T) -> io::Result<()> {
        self.tx.send(t).map_err(|e| {
            match e {
                channel::SendError::Io(e) => e,
                channel::SendError::Disconnected(_) => {
                    io::Error::new(io::ErrorKind::Other,
                                   "channel has been disconnected")
                }
            }
        })
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender { tx: self.tx.clone() }
    }
}

impl<T> Stream for Receiver<T> {
    type Item = T;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<T>, io::Error> {
        if let Async::NotReady = self.rx.poll_read() {
            return Ok(Async::NotReady)
        }
        match self.rx.get_ref().try_recv() {
            Ok(t) => Ok(Async::Ready(Some(t))),
            Err(TryRecvError::Empty) => {
                self.rx.need_read();
                Ok(Async::NotReady)
            }
            Err(TryRecvError::Disconnected) => Ok(Async::Ready(None)),
        }
    }
}
<commit_msg>Add links in docs to `channel` function.<commit_after>//! In-memory evented channels.
//!
//! This module contains a `Sender` and `Receiver` pair types which can be used
//! to send messages between different future tasks.

use std::io;
use std::sync::mpsc::TryRecvError;

use futures::{Poll, Async};
use futures::stream::Stream;
use mio::channel;

use reactor::{Handle, PollEvented};

/// The transmission half of a channel used for sending messages to a receiver.
///
/// A `Sender` can be `clone`d to have multiple threads or instances sending
/// messages to one receiver.
///
/// This type is created by the [`channel`] function.
///
/// [`channel`]: fn.channel.html
pub struct Sender<T> {
    tx: channel::Sender<T>,
}

/// The receiving half of a channel used for processing messages sent by a
/// `Sender`.
///
/// A `Receiver` cannot be cloned, so only one thread can receive messages at a
/// time.
///
/// This type is created by the [`channel`] function and implements the
/// `Stream` trait to represent received messages.
///
/// [`channel`]: fn.channel.html
pub struct Receiver<T> {
    rx: PollEvented<channel::Receiver<T>>,
}

/// Creates a new in-memory channel used for sending data across `Send +
/// 'static` boundaries, frequently threads.
///
/// This type can be used to conveniently send messages between futures.
/// Unlike the futures crate `channel` method and types, the returned tx/rx
/// pair is a multi-producer single-consumer (mpsc) channel *with no
/// backpressure*. Currently it's left up to the application to implement a
/// mechanism, if necessary, to avoid messages piling up.
///
/// The returned `Sender` can be used to send messages that are processed by
/// the returned `Receiver`. The `Sender` can be cloned to send messages
/// from multiple sources simultaneously.
pub fn channel<T>(handle: &Handle) -> io::Result<(Sender<T>, Receiver<T>)>
    where T: Send + 'static,
{
    let (tx, rx) = channel::channel();
    let rx = try!(PollEvented::new(rx, handle));
    Ok((Sender { tx: tx }, Receiver { rx: rx }))
}

impl<T> Sender<T> {
    /// Sends a message to the corresponding receiver of this sender.
    ///
    /// The message provided will be enqueued on the channel immediately, and
    /// this function will return immediately. Keep in mind that the
    /// underlying channel has infinite capacity, and this may not always be
    /// desired.
    ///
    /// If an I/O error happens while sending the message, or if the receiver
    /// has gone away, then an error will be returned. Note that I/O errors here
    /// are generally quite abnormal.
    pub fn send(&self, t: T) -> io::Result<()> {
        self.tx.send(t).map_err(|e| {
            match e {
                channel::SendError::Io(e) => e,
                channel::SendError::Disconnected(_) => {
                    io::Error::new(io::ErrorKind::Other,
                                   "channel has been disconnected")
                }
            }
        })
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender { tx: self.tx.clone() }
    }
}

impl<T> Stream for Receiver<T> {
    type Item = T;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<T>, io::Error> {
        if let Async::NotReady = self.rx.poll_read() {
            return Ok(Async::NotReady)
        }
        match self.rx.get_ref().try_recv() {
            Ok(t) => Ok(Async::Ready(Some(t))),
            Err(TryRecvError::Empty) => {
                self.rx.need_read();
                Ok(Async::NotReady)
            }
            Err(TryRecvError::Disconnected) => Ok(Async::Ready(None)),
        }
    }
}
<|endoftext|>


<commit_before>use std::net::SocketAddr;
use std::io::{Read, Write, BufRead, BufReader, stdout, stdin};

use delta_l::DeltaL;

#[derive(Debug, Copy, Clone)]
#[repr(u8)]
pub enum Colour {
    Black = 30,
    Red = 31,
    Green = 32,
    // Looks orange on Windows
    YellowSlashBrown = 33,
    Blue = 34,
    Magenta = 35,
    Cyan = 36,
    White = 37
}

use self::Colour::*;

pub struct Flags{
    pub use_colour: bool,
    pub use_compress: bool,
    pub use_checksum: bool
}

pub struct Chatter{
    pub flags: Flags
}

impl Chatter{
    pub fn reset_colour(&self) {
        if self.flags.use_colour{
            stdout().write_all(b"\x1b[0m").unwrap()
        }
    }

    pub fn set_colour(&self, c: Colour) {
        if self.flags.use_colour{
            stdout().write_all(format!("\x1b[{}m", c as u8).as_bytes()).unwrap()
        }
    }

    pub fn chat_mode(&self, _ip: SocketAddr, pass: &str){
        let mut buf = BufReader::new(stdin());

        'chat: loop{
            self.set_colour(Green);
            print!(" Δ ");
            stdout().flush().unwrap();

            let mut msg = String::new();
            buf.read_line(&mut msg).unwrap();
            let msg = msg.trim();

            self.reset_colour();

            if msg.len() == 0{
                continue 'chat
            }

            if msg.chars().nth(0).unwrap() == '§'{
                match msg{
                    "§bye"|"§quit" => {
                        self.set_colour(YellowSlashBrown);
                        println!("BYE!");

                        break 'chat
                    },
                    _ => continue 'chat
                }
            }

            self.send(msg, pass)
        }
    }

    pub fn send(&self, msg: &str, pass: &str){
        let mut dl = DeltaL::new();
        if pass != ""{
            dl.set_passphrase(pass);
        }
        self.set_colour(Cyan);

        let mut buf = Vec::new();

        println!("--- begins encrypted data ---");
        dl.encode(&mut msg.as_bytes(), &mut buf, true).unwrap();

        for i in 0.. {
            let t = i * 12;

            if t >= buf.len(){
                break
            }

            let size = ::std::cmp::min(12, buf.len() - t);

            println!("[{:02X}] ({:02}) [{}]", i, size, ::utils::hex_string(&buf[t..t+size]));

        }
        println!("--- end of encrypted data ---");
        self.reset_colour();
    }
}
<commit_msg>Actually use checksum flag<commit_after>use std::net::SocketAddr;
use std::io::{Read, Write, BufRead, BufReader, stdout, stdin};

use delta_l::DeltaL;

#[derive(Debug, Copy, Clone)]
#[repr(u8)]
pub enum Colour {
    Black = 30,
    Red = 31,
    Green = 32,
    // Looks orange on Windows
    YellowSlashBrown = 33,
    Blue = 34,
    Magenta = 35,
    Cyan = 36,
    White = 37
}

use self::Colour::*;

pub struct Flags{
    pub use_colour: bool,
    pub use_compress: bool,
    pub use_checksum: bool
}

pub struct Chatter{
    pub flags: Flags
}

impl Chatter{
    pub fn reset_colour(&self) {
        if self.flags.use_colour{
            stdout().write_all(b"\x1b[0m").unwrap()
        }
    }

    pub fn set_colour(&self, c: Colour) {
        if self.flags.use_colour{
            stdout().write_all(format!("\x1b[{}m", c as u8).as_bytes()).unwrap()
        }
    }

    pub fn chat_mode(&self, _ip: SocketAddr, pass: &str){
        let mut buf = BufReader::new(stdin());

        'chat: loop{
            self.set_colour(Green);
            print!(" Δ ");
            stdout().flush().unwrap();

            let mut msg = String::new();
            buf.read_line(&mut msg).unwrap();
            let msg = msg.trim();

            self.reset_colour();

            if msg.len() == 0{
                continue 'chat
            }

            if msg.chars().nth(0).unwrap() == '§'{
                match msg{
                    "§bye"|"§quit" => {
                        self.set_colour(YellowSlashBrown);
                        println!("BYE!");

                        break 'chat
                    },
                    _ => continue 'chat
                }
            }

            self.send(msg, pass)
        }
    }

    pub fn send(&self, msg: &str, pass: &str){
        let mut dl = DeltaL::new();
        if pass != ""{
            dl.set_passphrase(pass);
        }
        self.set_colour(Cyan);

        let mut buf = Vec::new();

        println!("--- begins encrypted data ---");
        dl.encode(&mut msg.as_bytes(), &mut buf, self.flags.use_checksum).unwrap();

        for i in 0.. {
            let t = i * 12;

            if t >= buf.len(){
                break
            }

            let size = ::std::cmp::min(12, buf.len() - t);

            println!("[{:02X}] ({:02}) [{}]", i, size, ::utils::hex_string(&buf[t..t+size]));

        }
        println!("--- end of encrypted data ---");
        self.reset_colour();
    }
}
<|endoftext|>


<commit_before>use bytecode::{Chunk, Inst};
use std::collections::HashMap;
use syntax::{Expr, ExprF, Literal};

pub struct Codegen<'str> {
  next_str_id: usize,
  strs: HashMap<usize, &'str str>,

  pub chunks: Vec<Chunk>,
}

impl<'str> Codegen<'str> {
  pub fn new() -> Self {
    Codegen{
      next_str_id: 0,
      strs: HashMap::new(),

      chunks: vec![],
    }
  }

  pub fn strs(&self) -> &HashMap<usize, &'str str> {
    &self.strs
  }

  fn codegen_func_bytecode(
    &mut self,
    locals: usize,
    captures: usize,
    insts: Vec<Inst>,
  ) -> usize {
    self.chunks.push(Chunk{
      insts: insts,
      locals: locals,
      captures: captures,
    });
    self.chunks.len() - 1
  }

  pub fn codegen_func<'expr, T>(
    &mut self,
    env: &HashMap<&str, usize>,
    captures: usize,
    body: &Expr<'str, 'expr, T>,
  ) -> usize {
    let mut insts = vec![];
    self.codegen_expr(env, body, &mut insts);
    insts.push(Inst::Return);
    self.chunks.push(Chunk{
      insts: insts,
      locals: 1 + captures,
      captures: captures,
    });
    self.chunks.len() - 1
  }

  pub fn codegen_expr<'expr, T>(
    &mut self,
    env: &HashMap<&str, usize>,
    expr: &Expr<'str, 'expr, T>,
    insts: &mut Vec<Inst>,
  ) {
    match expr.1 {
      ExprF::Lit(ref lit) =>
        self.codegen_literal(lit, insts),
      ExprF::Var("stdout#") =>
        insts.push(Inst::NewI32(1)),
      ExprF::Var("to_utf8#") => {
        let chunk_id = self.codegen_func_bytecode(1, 0, vec![
          Inst::GetLocal(0),
          Inst::Return,
        ]);
        insts.push(Inst::NewFunc(chunk_id));
      },
      ExprF::Var("write#") => {
        let action_chunk_id = self.codegen_func_bytecode(3, 2, vec![
          Inst::GetLocal(1), // handle
          Inst::GetLocal(2), // bytes
          Inst::Write,
          Inst::Return,
        ]);
        let curry2_chunk_id = self.codegen_func_bytecode(2, 1, vec![
          Inst::GetLocal(0), // bytes
          Inst::GetLocal(1), // handle
          Inst::NewFunc(action_chunk_id),
          Inst::Return,
        ]);
        let curry1_chunk_id = self.codegen_func_bytecode(1, 0, vec![
          Inst::GetLocal(0), // handle
          Inst::NewFunc(curry2_chunk_id),
          Inst::Return,
        ]);
        insts.push(Inst::NewFunc(curry1_chunk_id));
      },
      ExprF::Var(name) => {
        let offset = env[name];
        insts.push(Inst::GetLocal(offset));
      },
      ExprF::Abs(param, body) => {
        let mut body_env = HashMap::new();
        body_env.insert(param, 0);
        for (i, (k, &v)) in env.iter().enumerate() {
          body_env.insert(k, i + 1);
          insts.push(Inst::GetLocal(v));
        }
        let chunk_id = self.codegen_func(&body_env, env.len(), body);
        insts.push(Inst::NewFunc(chunk_id));
      },
      ExprF::App(callee, argument) => {
        self.codegen_expr(env, callee, insts);
        self.codegen_expr(env, argument, insts);
        insts.push(Inst::Call);
      },
    }
  }

  pub fn codegen_literal(
    &mut self,
    lit: &Literal<'str>,
    insts: &mut Vec<Inst>,
  ) {
    match *lit {
      Literal::Bool(value) =>
        insts.push(Inst::NewI32(value as i32)),
      Literal::Str(value) => {
        let id = self.next_str_id;
        self.next_str_id += 1;
        self.strs.insert(id, value);
        insts.push(Inst::NewStr(id));
      },
      _ => panic!("codegen_literal: NYI"),
    }
  }
}
<commit_msg>Add comments about moving builtin codegen to builtin<commit_after>use bytecode::{Chunk, Inst};
use std::collections::HashMap;
use syntax::{Expr, ExprF, Literal};

pub struct Codegen<'str> {
  next_str_id: usize,
  strs: HashMap<usize, &'str str>,

  pub chunks: Vec<Chunk>,
}

impl<'str> Codegen<'str> {
  pub fn new() -> Self {
    Codegen{
      next_str_id: 0,
      strs: HashMap::new(),

      chunks: vec![],
    }
  }

  pub fn strs(&self) -> &HashMap<usize, &'str str> {
    &self.strs
  }

  fn codegen_func_bytecode(
    &mut self,
    locals: usize,
    captures: usize,
    insts: Vec<Inst>,
  ) -> usize {
    self.chunks.push(Chunk{
      insts: insts,
      locals: locals,
      captures: captures,
    });
    self.chunks.len() - 1
  }

  pub fn codegen_func<'expr, T>(
    &mut self,
    env: &HashMap<&str, usize>,
    captures: usize,
    body: &Expr<'str, 'expr, T>,
  ) -> usize {
    let mut insts = vec![];
    self.codegen_expr(env, body, &mut insts);
    insts.push(Inst::Return);
    self.chunks.push(Chunk{
      insts: insts,
      locals: 1 + captures,
      captures: captures,
    });
    self.chunks.len() - 1
  }

  pub fn codegen_expr<'expr, T>(
    &mut self,
    env: &HashMap<&str, usize>,
    expr: &Expr<'str, 'expr, T>,
    insts: &mut Vec<Inst>,
  ) {
    match expr.1 {
      ExprF::Lit(ref lit) =>
        self.codegen_literal(lit, insts),
      ExprF::Var("stdout#") => // TODO: Move to feldspar::builtin
        insts.push(Inst::NewI32(1)),
      ExprF::Var("to_utf8#") => { // TODO: Move to feldspar::builtin
        let chunk_id = self.codegen_func_bytecode(1, 0, vec![
          Inst::GetLocal(0),
          Inst::Return,
        ]);
        insts.push(Inst::NewFunc(chunk_id));
      },
      ExprF::Var("write#") => { // TODO: Move to feldspar::builtin
        let action_chunk_id = self.codegen_func_bytecode(3, 2, vec![
          Inst::GetLocal(1), // handle
          Inst::GetLocal(2), // bytes
          Inst::Write,
          Inst::Return,
        ]);
        let curry2_chunk_id = self.codegen_func_bytecode(2, 1, vec![
          Inst::GetLocal(0), // bytes
          Inst::GetLocal(1), // handle
          Inst::NewFunc(action_chunk_id),
          Inst::Return,
        ]);
        let curry1_chunk_id = self.codegen_func_bytecode(1, 0, vec![
          Inst::GetLocal(0), // handle
          Inst::NewFunc(curry2_chunk_id),
          Inst::Return,
        ]);
        insts.push(Inst::NewFunc(curry1_chunk_id));
      },
      ExprF::Var(name) => {
        let offset = env[name];
        insts.push(Inst::GetLocal(offset));
      },
      ExprF::Abs(param, body) => {
        let mut body_env = HashMap::new();
        body_env.insert(param, 0);
        for (i, (k, &v)) in env.iter().enumerate() {
          body_env.insert(k, i + 1);
          insts.push(Inst::GetLocal(v));
        }
        let chunk_id = self.codegen_func(&body_env, env.len(), body);
        insts.push(Inst::NewFunc(chunk_id));
      },
      ExprF::App(callee, argument) => {
        self.codegen_expr(env, callee, insts);
        self.codegen_expr(env, argument, insts);
        insts.push(Inst::Call);
      },
    }
  }

  pub fn codegen_literal(
    &mut self,
    lit: &Literal<'str>,
    insts: &mut Vec<Inst>,
  ) {
    match *lit {
      Literal::Bool(value) =>
        insts.push(Inst::NewI32(value as i32)),
      Literal::Str(value) => {
        let id = self.next_str_id;
        self.next_str_id += 1;
        self.strs.insert(id, value);
        insts.push(Inst::NewStr(id));
      },
      _ => panic!("codegen_literal: NYI"),
    }
  }
}
<|endoftext|>


<commit_before>extern crate semver;

use std::collections::HashMap;
use std::io::net::ip::IpAddr;

#[deriving(PartialEq, Show, Clone)]
pub enum Scheme {
    Http,
    Https
}

#[deriving(PartialEq, Show, Clone)]
pub enum Host<'a> {
    HostName(&'a str),
    HostIp(IpAddr)
}

#[deriving(PartialEq, Show, Clone)]
pub enum Method<'a> {
    Get,
    Post,
    Put,
    Patch,
    Delete,
    Other(&'a str)
}

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method<'a>(&'a self) -> Method<'a>;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_ip(&self) -> IpAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<uint>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut Reader;
}

pub type HeaderEntries<'a> = Box<Iterator<(&'a str, Vec<&'a str>)>>;

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find<'a>(&'a self, key: &str) -> Option<Vec<&'a str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn iter<'a>(&'a self) -> HeaderEntries<'a>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (uint, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, String>,

    /// A Writer for body of the response
    pub body: Box<Reader + Send>
}

pub type Handler = fn(&mut Request) -> Response;
<commit_msg>Handlers return a Result<commit_after>extern crate semver;

use std::collections::HashMap;
use std::io::net::ip::IpAddr;

#[deriving(PartialEq, Show, Clone)]
pub enum Scheme {
    Http,
    Https
}

#[deriving(PartialEq, Show, Clone)]
pub enum Host<'a> {
    HostName(&'a str),
    HostIp(IpAddr)
}

#[deriving(PartialEq, Show, Clone)]
pub enum Method<'a> {
    Get,
    Post,
    Put,
    Patch,
    Delete,
    Other(&'a str)
}

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method<'a>(&'a self) -> Method<'a>;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_ip(&self) -> IpAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<uint>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut Reader;
}

pub type HeaderEntries<'a> = Box<Iterator<(&'a str, Vec<&'a str>)>>;

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find<'a>(&'a self, key: &str) -> Option<Vec<&'a str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn iter<'a>(&'a self) -> HeaderEntries<'a>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (uint, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, String>,

    /// A Writer for body of the response
    pub body: Box<Reader + Send>
}

pub type Handler<E> = fn(&mut Request) -> Result<Response, E>;
<|endoftext|>


<commit_before>use std::num::Float;
use serialize::json::{Json, ToJson};
use regex::Regex;
use std::iter::IteratorExt;
use std::collections::RingBuf;

pub struct Context {
    data: Json,
    default: Json
}

//pub static NULL_VALUE: &'static Json = &Json::Null;
static ARRAY_INDEX_MATCHER: Regex = regex!(r"\[\d+\]$");

#[inline]
fn parse_json_visitor<'a>(path_stack: &mut RingBuf<&'a str>, path: &'a String) {
    for p in (*path).split('/') {
        match p {
            "this" | "." | "" => {
                continue;
            }
            ".." => {
                path_stack.pop_back();
            }
            _ => {
                for dot_p in p.split('.') {
                    if dot_p != "this" {
                        path_stack.push_back(dot_p);
                    }
                }
            }
        }
    }
}

impl Context {
    pub fn null() -> Context {
        Context {
            data: Json::Null,
            default: Json::Null
        }
    }

    pub fn wraps<T: ToJson>(e: &T) -> Context {
        Context {
            data: e.to_json(),
            default: Json::Null
        }
    }

    pub fn navigate(&self, path: &String, relative_path: &String) -> &Json {
        let mut path_stack :RingBuf<&str> = RingBuf::new();
        parse_json_visitor(&mut path_stack, path);
        parse_json_visitor(&mut path_stack, relative_path);

        let paths :Vec<&str> = path_stack.iter().map(|x| *x).collect();
        let mut data: &Json = &self.data;
        for p in paths.iter() {
            match ARRAY_INDEX_MATCHER.find(*p) {
                Some((s, _)) => {
                    let arr = &p[..s];
                    let idx = &p[s+1 .. p.len()-1];

                    let root = if arr == "this" {
                        Some(data)
                    } else {
                        data.find(arr)
                    };

                    data = match root {
                        Some(d) => {
                            match *d {
                                Json::Array(ref l) => {
                                    match idx.parse::<usize>() {
                                        Ok(idx_u) => l.get(idx_u).unwrap(),
                                        Err(_) => &self.default
                                    }
                                },
                                _ => &self.default
                            }
                        },
                        None => &self.default
                    };
                },
                None => {
                    data = match data.find(*p) {
                        Some(d) => d,
                        None => &self.default
                    };
                }
            }
        }
        data
    }
}

pub trait JsonRender {
    fn render(&self) -> String;
}

pub trait JsonTruthy {
    fn is_truthy(&self) -> bool;
}

impl JsonRender for Json {
    fn render(&self) -> String {
        match *self {
            Json::String(_) => {
                let s = format!("{}", *self);
                s.slice_chars(1, s.chars().count()-1).to_string()
            },
            _ => {
                format!("{}", *self)
            }
        }
    }
}

impl JsonTruthy for Json {
    fn is_truthy(&self) -> bool {
        match *self {
            Json::I64(i) => i != 0,
            Json::U64(i) => i != 0,
            Json::F64(i) => i != Float::zero() || ! i.is_nan(),
            Json::Boolean (ref i) => *i,
            Json::Null => false,
            Json::String (ref i) => i.len() > 0,
            Json::Array (ref i) => i.len() > 0,
            Json::Object (ref i) => i.len() > 0
        }
    }
}

#[cfg(test)]
mod test {
    use context::{JsonRender, Context};
    use std::collections::BTreeMap;
    use serialize::json::{Json, ToJson};

    struct Address {
        city: String,
        country: String
    }

    impl ToJson for Address {
        fn to_json(&self) -> Json {
            let mut m = BTreeMap::new();
            m.insert("city".to_string(), self.city.to_json());
            m.insert("country".to_string(), self.country.to_json());
            Json::Object(m)
        }
    }

    struct Person {
        name: String,
        age: i16,
        addr: Address,
        titles: Vec<String>
    }

    impl ToJson for Person {
        fn to_json(&self) -> Json {
            let mut m = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("age".to_string(), self.age.to_json());
            m.insert("addr".to_string(), self.addr.to_json());
            m.insert("titles".to_string(), self.titles.to_json());
            Json::Object(m)
        }
    }

    #[test]
    fn test_render() {
        let v = "hello";
        let ctx = Context::wraps(&v.to_string());
        let this = "this".to_string();
        assert_eq!(ctx.navigate(&this, &this).render(), v.to_string());
    }

    #[test]
    fn test_navigation() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string()
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(),
                         "cartographier".to_string()]
        };

        let ctx = Context::wraps(&person);
        let this = "this".to_string();
        let that = "./name/../addr/country".to_string();

        assert_eq!(ctx.navigate(&this, &that).render(), "China".to_string());

        let v = true;
        let ctx2 = Context::wraps(&v);
        assert_eq!(ctx2.navigate(&"this".to_string(), &"this".to_string()).render(), "true".to_string());

        let this2 = "this".to_string();
        let that2 = "titles[0]".to_string();
        assert_eq!(ctx.navigate(&this2, &that2).render(), "programmer".to_string());
    }
}
<commit_msg>(fix) fixed json string rendering [#4]<commit_after>use std::num::Float;
use serialize::json::{Json, ToJson};
use regex::Regex;
use std::iter::IteratorExt;
use std::collections::RingBuf;

pub struct Context {
    data: Json,
    default: Json
}

//pub static NULL_VALUE: &'static Json = &Json::Null;
static ARRAY_INDEX_MATCHER: Regex = regex!(r"\[\d+\]$");

#[inline]
fn parse_json_visitor<'a>(path_stack: &mut RingBuf<&'a str>, path: &'a String) {
    for p in (*path).split('/') {
        match p {
            "this" | "." | "" => {
                continue;
            }
            ".." => {
                path_stack.pop_back();
            }
            _ => {
                for dot_p in p.split('.') {
                    if dot_p != "this" {
                        path_stack.push_back(dot_p);
                    }
                }
            }
        }
    }
}

impl Context {
    pub fn null() -> Context {
        Context {
            data: Json::Null,
            default: Json::Null
        }
    }

    pub fn wraps<T: ToJson>(e: &T) -> Context {
        Context {
            data: e.to_json(),
            default: Json::Null
        }
    }

    pub fn navigate(&self, path: &String, relative_path: &String) -> &Json {
        let mut path_stack :RingBuf<&str> = RingBuf::new();
        parse_json_visitor(&mut path_stack, path);
        parse_json_visitor(&mut path_stack, relative_path);

        let paths :Vec<&str> = path_stack.iter().map(|x| *x).collect();
        let mut data: &Json = &self.data;
        for p in paths.iter() {
            match ARRAY_INDEX_MATCHER.find(*p) {
                Some((s, _)) => {
                    let arr = &p[..s];
                    let idx = &p[s+1 .. p.len()-1];

                    let root = if arr == "this" {
                        Some(data)
                    } else {
                        data.find(arr)
                    };

                    data = match root {
                        Some(d) => {
                            match *d {
                                Json::Array(ref l) => {
                                    match idx.parse::<usize>() {
                                        Ok(idx_u) => l.get(idx_u).unwrap(),
                                        Err(_) => &self.default
                                    }
                                },
                                _ => &self.default
                            }
                        },
                        None => &self.default
                    };
                },
                None => {
                    data = match data.find(*p) {
                        Some(d) => d,
                        None => &self.default
                    };
                }
            }
        }
        data
    }
}

pub trait JsonRender {
    fn render(&self) -> String;
}

pub trait JsonTruthy {
    fn is_truthy(&self) -> bool;
}

impl JsonRender for Json {
    fn render(&self) -> String {
        match *self {
            Json::String(_) => {
                match self.as_string() {
                    Some(s) => String::from_str(s),
                    None => String::from_str("")
                }
            },
            _ => {
                format!("{}", *self)
            }
        }
    }
}

impl JsonTruthy for Json {
    fn is_truthy(&self) -> bool {
        match *self {
            Json::I64(i) => i != 0,
            Json::U64(i) => i != 0,
            Json::F64(i) => i != Float::zero() || ! i.is_nan(),
            Json::Boolean (ref i) => *i,
            Json::Null => false,
            Json::String (ref i) => i.len() > 0,
            Json::Array (ref i) => i.len() > 0,
            Json::Object (ref i) => i.len() > 0
        }
    }
}

#[cfg(test)]
mod test {
    use context::{JsonRender, Context};
    use std::collections::BTreeMap;
    use serialize::json::{Json, ToJson};

    #[test]
    fn test_json_render() {
        let raw = "
Hello world
\n Json {
            let mut m = BTreeMap::new();
            m.insert("city".to_string(), self.city.to_json());
            m.insert("country".to_string(), self.country.to_json());
            Json::Object(m)
        }
    }

    struct Person {
        name: String,
        age: i16,
        addr: Address,
        titles: Vec<String>
    }

    impl ToJson for Person {
        fn to_json(&self) -> Json {
            let mut m = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("age".to_string(), self.age.to_json());
            m.insert("addr".to_string(), self.addr.to_json());
            m.insert("titles".to_string(), self.titles.to_json());
            Json::Object(m)
        }
    }

    #[test]
    fn test_render() {
        let v = "hello";
        let ctx = Context::wraps(&v.to_string());
        let this = "this".to_string();
        assert_eq!(ctx.navigate(&this, &this).render(), v.to_string());
    }

    #[test]
    fn test_navigation() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string()
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(),
                         "cartographier".to_string()]
        };

        let ctx = Context::wraps(&person);
        let this = "this".to_string();
        let that = "./name/../addr/country".to_string();

        assert_eq!(ctx.navigate(&this, &that).render(), "China".to_string());

        let v = true;
        let ctx2 = Context::wraps(&v);
        assert_eq!(ctx2.navigate(&"this".to_string(), &"this".to_string()).render(), "true".to_string());

        let this2 = "this".to_string();
        let that2 = "titles[0]".to_string();
        assert_eq!(ctx.navigate(&this2, &that2).render(), "programmer".to_string());
    }
}
<|endoftext|>


<commit_before>use std;

use raw::*;

pub struct Context {
    pthx: PerlContext,
    stack: OuroborosStack,
}

impl Context {
    pub fn new(pthx: PerlContext) -> Context {
        unsafe {
            let mut ctx = Context {
                pthx: pthx,
                stack: std::mem::uninitialized(),
            };
            ouroboros_stack_init(ctx.pthx, &mut ctx.stack);
            ctx
        }
    }
}
<commit_msg>Add new_xs wrapper.<commit_after>use std;
use std::os::raw::c_char;

use raw::*;

pub struct Context {
    pthx: PerlContext,
    stack: OuroborosStack,
}

impl Context {
    pub fn new(pthx: PerlContext) -> Context {
        unsafe {
            let mut ctx = Context {
                pthx: pthx,
                stack: std::mem::uninitialized(),
            };
            ouroboros_stack_init(ctx.pthx, &mut ctx.stack);
            ctx
        }
    }

    pub fn new_xs(&mut self, name: &str, func: XSUBADDR_t) {
        let cname = std::ffi::CString::new(name).unwrap();
        unsafe {
            Perl_newXS(self.pthx, cname.as_ptr(), func, b"\0" as *const _ as *const c_char);
        }
    }
}
<|endoftext|>