<commit_before>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: obj/map.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Loader and handler of BSP maps.
*/

use math::{ Vec3f, Vec4u8, BB3 };

#[path = "lump.rs"]
mod lump;
#[path = "../../gl/mod.rs"]
mod gl;

#[path = "../../gl/check.rs"]
mod check;

pub struct Map
{
  header: lump::Header,
  entity: lump::Entity,
  verts: ~[lump::Vertex],
  faces: ~[lump::Face],
  mesh_verts: ~[lump::Mesh_Vert],
  vao: gl::GLuint,
  vbo: ~[gl::GLuint], /* TODO: No need for the array */
  position: Vec3f, /* TODO: Trait for positional objects. */
  bb: BB3
}

impl Map
{
  pub fn new(file: &str) -> Map
  {
    let mut map = Map{  header: lump::Header::new(),
                        entity: lump::Entity::new(),
                        verts: ~[],
                        faces: ~[],
                        mesh_verts: ~[],
                        vao: 0,
                        vbo: ~[],
                        position: Vec3f::zero(),
                        bb: BB3::zero()
                        };

    let mut fio = io::file_reader(@path::PosixPath(file)).unwrap();
    unsafe {  fio.read( cast::transmute((&map.header, sys::size_of::<lump::Header>())),
              sys::size_of::<lump::Header>()); }

    assert!( map.header.magic[0] == 'I' as i8 &&
             map.header.magic[1] == 'B' as i8 &&
             map.header.magic[2] == 'S' as i8 &&
             map.header.magic[3] == 'P' as i8);

    map.read_verts(fio);
    map.read_faces(fio);
    map.read_mesh_verts(fio);

    map.triangulate();
    map.upload();

    map
  }

  /* TODO: Make this generic. */
  priv fn read_verts(&mut self, fio: @io::Reader)
  {
    fio.seek(self.header.lumps[lump::Vertex_Type as int].offset as int, io::SeekSet);
    let num_verts = (self.header.lumps[lump::Vertex_Type as int].length) /
                    (sys::size_of::<lump::Vertex>() as i32);
    assert!(num_verts > 0);

    let mut vert = lump::Vertex::new();
    for i32::range(0, num_verts) |i|
    {
      unsafe { fio.read( cast::transmute((&vert, sys::size_of::<lump::Vertex>())),
                sys::size_of::<lump::Vertex>()); }

      /* BSP likes Z to be up; I like Y to be up. */
      let temp = vert.position.y;
      vert.position.y = vert.position.z;
      vert.position.z = -temp;

      /* TODO: Color hack. */
      if vert.color.x == 0 { vert.color.x += 100; }
      if vert.color.y == 0 { vert.color.y += 100; }
      if vert.color.z == 0 { vert.color.z += 100; }

      if vert.color.x == 255 { vert.color.x -= 100; }
      if vert.color.y == 255 { vert.color.y -= 100; }
      if vert.color.z == 255 { vert.color.z -= 100; }
      vert.color.w = 1;

      /* Global size scale. */
      vert.position.x /= 32.0;
      vert.position.y /= 32.0;
      vert.position.z /= 32.0;

      /* Create bounding box based on first vert; this'll update as more come. */
      match i
      {
        0 =>
        { self.bb.top_left = vert.position; self.bb.bottom_right = vert.position; }
        _ =>
        {
          /* Keep track of bounds. */
          if vert.position.x < self.bb.top_left.x
          { self.bb.top_left.x = vert.position.x; }
          else if vert.position.x > self.bb.bottom_right.x
          { self.bb.bottom_right.x = vert.position.x }

          if vert.position.y > self.bb.top_left.y
          { self.bb.top_left.y = vert.position.y; }
          else if vert.position.y < self.bb.bottom_right.y
          { self.bb.bottom_right.y = vert.position.y }

          if vert.position.z > self.bb.top_left.z
          { self.bb.top_left.z = vert.position.z; }
          else if vert.position.z < self.bb.bottom_right.z
          { self.bb.bottom_right.z = vert.position.z }
        }
      }

      self.verts.push(vert);
    }
  }

  priv fn read_faces(&mut self, fio: @io::Reader)
  {
    fio.seek(self.header.lumps[lump::Face_Type as int].offset as int, io::SeekSet);
    let num_faces = (self.header.lumps[lump::Face_Type as int].length) /
                    (sys::size_of::<lump::Face>() as i32);
    assert!(num_faces > 0);

    let mut face = lump::Face::new();

    for i32::range(0, num_faces) |_|
    {
      unsafe { fio.read( cast::transmute((&face, sys::size_of::<lump::Face>())),
                sys::size_of::<lump::Face>()); }
      self.faces.push(face);
    }
  }

  priv fn read_mesh_verts(&mut self, fio: @io::Reader)
  {
    fio.seek(self.header.lumps[lump::Mesh_Vert_Type as int].offset as int, io::SeekSet);
    let num_obj = (self.header.lumps[lump::Mesh_Vert_Type as int].length) /
                    (sys::size_of::<lump::Mesh_Vert>() as i32);
    assert!(num_obj > 0);

    let mut obj = lump::Mesh_Vert::new();

    for i32::range(0, num_obj) |_|
    {
      unsafe { fio.read( cast::transmute((&obj, sys::size_of::<lump::Mesh_Vert>())),
                sys::size_of::<lump::Mesh_Vert>()); }
      self.mesh_verts.push(obj);
    }
  }

  priv fn triangulate(&mut self)
  {
    let mut verts: ~[lump::Vertex] = ~[];
    for self.faces.each() |face|
    {
      if face.kind != 1 { loop; }

      match face.num_vertices
      {
        n if n >= 3 =>
        {
          for i32::range(0, n - 2) |i|
          {
            verts.push(self.verts[face.start_vertex]);
            verts.push(self.verts[face.start_vertex + i + 2]);
            verts.push(self.verts[face.start_vertex + i + 1]);
          }
        }
        /* Something else. */
        n => { io::println(fmt!("BSP: Invalid face: %?", n)); }
      }
    };

    self.verts = verts;
    debug!("Trianglulated to %? faces.", self.verts.len());
  }

  priv fn upload(&mut self)
  {
    self.vao = check!(gl::gen_vertex_arrays(1))[0];
    self.vbo = check!(gl::gen_buffers(1));
    assert!(self.vbo.len() == 1);

    check!(gl::bind_vertex_array(self.vao));
    check!(gl::bind_buffer(gl::ARRAY_BUFFER, self.vbo[0]));
    check!(gl::buffer_data(gl::ARRAY_BUFFER, self.verts, gl::STATIC_DRAW));
  }

  pub fn draw(&self)
  {
    check!(gl::bind_vertex_array(self.vao));
    check!(gl::bind_buffer(gl::ARRAY_BUFFER, self.vbo[0]));
    check!(gl::enable_vertex_attrib_array(0));
    check!(gl::enable_vertex_attrib_array(1));

    check!(gl::vertex_attrib_pointer_f32(0, 3, false,
                sys::size_of::<lump::Vertex>() as i32,
                0));
    check!(gl::vertex_attrib_pointer_u8(1, 4, true,
                sys::size_of::<lump::Vertex>() as i32,
                sys::size_of::<lump::Vertex>() as u32 -
                sys::size_of::<Vec4u8>() as u32));
    check!(gl::draw_arrays(gl::TRIANGLES, 0, self.verts.len() as i32));

    check!(gl::disable_vertex_attrib_array(0));
    check!(gl::disable_vertex_attrib_array(1));
    check!(gl::bind_vertex_array(0));
    check!(gl::bind_buffer(gl::ARRAY_BUFFER, 0));
  }

  pub fn center(&self) -> Vec3f
  { self.bb.center_with_offset(self.position) }
}

<commit_msg> #7 Updated warnings in BSP map<commit_after>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: obj/map.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Loader and handler of BSP maps.
*/

use math::{ Vec3f, Vec4u8, BB3 };

#[path = "lump.rs"]
mod lump;
#[path = "../../gl/mod.rs"]
mod gl;

#[path = "../../gl/check.rs"]
mod check;

pub struct Map
{
  header: lump::Header,
  entity: lump::Entity,
  verts: ~[lump::Vertex],
  faces: ~[lump::Face],
  mesh_verts: ~[lump::Mesh_Vert],
  vao: gl::GLuint,
  vbo: ~[gl::GLuint], /* TODO: No need for the array */
  position: Vec3f, /* TODO: Trait for positional objects. */
  bb: BB3
}

impl Map
{
  pub fn new(file: &str) -> Map
  {
    let mut map = Map{  header: lump::Header::new(),
                        entity: lump::Entity::new(),
                        verts: ~[],
                        faces: ~[],
                        mesh_verts: ~[],
                        vao: 0,
                        vbo: ~[],
                        position: Vec3f::zero(),
                        bb: BB3::zero()
                        };

    let mut fio = io::file_reader(@path::PosixPath(file)).unwrap();
    unsafe {  fio.read( cast::transmute((&map.header, sys::size_of::<lump::Header>())),
              sys::size_of::<lump::Header>()); }

    assert!( map.header.magic[0] == 'I' as i8 &&
             map.header.magic[1] == 'B' as i8 &&
             map.header.magic[2] == 'S' as i8 &&
             map.header.magic[3] == 'P' as i8);

    map.read_verts(fio);
    map.read_faces(fio);
    map.read_mesh_verts(fio);

    map.triangulate();
    map.upload();

    map
  }

  /* TODO: Make this generic. */
  priv fn read_verts(&mut self, fio: @io::Reader)
  {
    fio.seek(self.header.lumps[lump::Vertex_Type as int].offset as int, io::SeekSet);
    let num_verts = (self.header.lumps[lump::Vertex_Type as int].length) /
                    (sys::size_of::<lump::Vertex>() as i32);
    assert!(num_verts > 0);

    let mut vert = lump::Vertex::new();
    for i32::range(0, num_verts) |i|
    {
      unsafe { fio.read( cast::transmute((&vert, sys::size_of::<lump::Vertex>())),
                sys::size_of::<lump::Vertex>()); }

      /* BSP likes Z to be up; I like Y to be up. */
      let temp = vert.position.y;
      vert.position.y = vert.position.z;
      vert.position.z = -temp;

      /* TODO: Color hack. */
      if vert.color.x == 0 { vert.color.x += 100; }
      if vert.color.y == 0 { vert.color.y += 100; }
      if vert.color.z == 0 { vert.color.z += 100; }

      if vert.color.x == 255 { vert.color.x -= 100; }
      if vert.color.y == 255 { vert.color.y -= 100; }
      if vert.color.z == 255 { vert.color.z -= 100; }
      vert.color.w = 1;

      /* Global size scale. */
      vert.position.x /= 32.0;
      vert.position.y /= 32.0;
      vert.position.z /= 32.0;

      /* Create bounding box based on first vert; this'll update as more come. */
      match i
      {
        0 =>
        { self.bb.top_left = vert.position; self.bb.bottom_right = vert.position; }
        _ =>
        {
          /* Keep track of bounds. */
          if vert.position.x < self.bb.top_left.x
          { self.bb.top_left.x = vert.position.x; }
          else if vert.position.x > self.bb.bottom_right.x
          { self.bb.bottom_right.x = vert.position.x }

          if vert.position.y > self.bb.top_left.y
          { self.bb.top_left.y = vert.position.y; }
          else if vert.position.y < self.bb.bottom_right.y
          { self.bb.bottom_right.y = vert.position.y }

          if vert.position.z > self.bb.top_left.z
          { self.bb.top_left.z = vert.position.z; }
          else if vert.position.z < self.bb.bottom_right.z
          { self.bb.bottom_right.z = vert.position.z }
        }
      }

      self.verts.push(vert);
    }
  }

  priv fn read_faces(&mut self, fio: @io::Reader)
  {
    fio.seek(self.header.lumps[lump::Face_Type as int].offset as int, io::SeekSet);
    let num_faces = (self.header.lumps[lump::Face_Type as int].length) /
                    (sys::size_of::<lump::Face>() as i32);
    assert!(num_faces > 0);

    let mut face = lump::Face::new();

    for i32::range(0, num_faces) |_|
    {
      unsafe { fio.read( cast::transmute((&face, sys::size_of::<lump::Face>())),
                sys::size_of::<lump::Face>()); }
      self.faces.push(face);
    }
  }

  priv fn read_mesh_verts(&mut self, fio: @io::Reader)
  {
    fio.seek(self.header.lumps[lump::Mesh_Vert_Type as int].offset as int, io::SeekSet);
    let num_obj = (self.header.lumps[lump::Mesh_Vert_Type as int].length) /
                    (sys::size_of::<lump::Mesh_Vert>() as i32);
    assert!(num_obj > 0);

    let mut obj = lump::Mesh_Vert::new();

    for i32::range(0, num_obj) |_|
    {
      unsafe { fio.read( cast::transmute((&obj, sys::size_of::<lump::Mesh_Vert>())),
                sys::size_of::<lump::Mesh_Vert>()); }
      self.mesh_verts.push(obj);
    }
  }

  priv fn triangulate(&mut self)
  {
    let mut verts: ~[lump::Vertex] = ~[];
    for self.faces.each() |face|
    {
      if face.kind != 1 { loop; }

      match face.num_vertices
      {
        n if n >= 3 =>
        {
          for i32::range(0, n - 2) |i|
          {
            verts.push(self.verts[face.start_vertex]);
            verts.push(self.verts[face.start_vertex + i + 2]);
            verts.push(self.verts[face.start_vertex + i + 1]);
          }
        }
        /* Something else. */
        n => { warn!(fmt!("BSP: Invalid face: %?", n)); }
      }
    };

    self.verts = verts;
    debug!("BSP: Trianglulated to %? faces.", self.verts.len());
  }

  priv fn upload(&mut self)
  {
    self.vao = check!(gl::gen_vertex_arrays(1))[0];
    self.vbo = check!(gl::gen_buffers(1));
    assert!(self.vbo.len() == 1);

    check!(gl::bind_vertex_array(self.vao));
    check!(gl::bind_buffer(gl::ARRAY_BUFFER, self.vbo[0]));
    check!(gl::buffer_data(gl::ARRAY_BUFFER, self.verts, gl::STATIC_DRAW));
  }

  pub fn draw(&self)
  {
    check!(gl::bind_vertex_array(self.vao));
    check!(gl::bind_buffer(gl::ARRAY_BUFFER, self.vbo[0]));
    check!(gl::enable_vertex_attrib_array(0));
    check!(gl::enable_vertex_attrib_array(1));

    check!(gl::vertex_attrib_pointer_f32(0, 3, false,
                sys::size_of::<lump::Vertex>() as i32,
                0));
    check!(gl::vertex_attrib_pointer_u8(1, 4, true,
                sys::size_of::<lump::Vertex>() as i32,
                sys::size_of::<lump::Vertex>() as u32 -
                sys::size_of::<Vec4u8>() as u32));
    check!(gl::draw_arrays(gl::TRIANGLES, 0, self.verts.len() as i32));

    check!(gl::disable_vertex_attrib_array(0));
    check!(gl::disable_vertex_attrib_array(1));
    check!(gl::bind_vertex_array(0));
    check!(gl::bind_buffer(gl::ARRAY_BUFFER, 0));
  }

  pub fn center(&self) -> Vec3f
  { self.bb.center_with_offset(self.position) }
}

<|endoftext|>


<commit_before>use nom::*;
use std::str;

#[derive(Debug)]
pub struct Paragraph<'a> {
    parts: Vec<Text<'a>>,
}

#[derive(Debug, PartialEq)]
pub enum Text<'a> {
    Plain(&'a str),
    Italics(&'a str),
}

impl<'a> Paragraph<'a> {
    pub fn to_html(&self) -> String {
        self.parts.iter()
            .map(|text| match *text {
                Text::Plain(ref s) => s.to_string(),
                Text::Italics(ref s) => ["", &s[..], ""].concat(),
            })
            .collect::<Vec<_>>()
            .concat()
    }
}

named!(paragraph<Paragraph>,
    chain!(
        vec: many1!(alt!(plain | italics)),
        || { Paragraph { parts: vec } }
    )
);

named!(plain<Text>,
    chain!(
        bytes: is_not!("*") ~
        s:     expr_res!(str::from_utf8(bytes)),
        || { Text::Plain(s) }
    )
);

named!(italics<Text>,
    delimited!(
        char!('*'),
        chain!(
            bytes: is_not!("*") ~
            s:     expr_res!(str::from_utf8(bytes)),
            || { Text::Italics(s) }
        ),
        char!('*')
    )
);

#[test]
fn test_paragraph_parse() {
    if let IResult::Done(input, output) = paragraph(b"Hello *World*") {
        assert_eq!(input, b"");
        assert_eq!(output.parts, vec![Text::Plain("Hello "),
                                      Text::Italics("World")]);
    } else {
        panic!(r#" Paragraph parse failed with "Hello *World*" "#);
    }

    if let IResult::Done(input, output) = paragraph(b"*This* is *a test*") {
        assert_eq!(input, b"");
        assert_eq!(output.parts, vec![Text::Italics("This"),
                                      Text::Plain(" is "),
                                      Text::Italics("a test")]);
    } else {
        panic!(r#" Paragraph parse failed with "Hello *World*" "#);
    }
}

#[test]
fn test_plain_parse() {
    if let IResult::Done(input, output) = plain(b"Hello *World*") {
        assert_eq!(input, b"*World*");
        assert_eq!(output, Text::Plain("Hello "));
    } else {
        panic!(r#" Plain parse failed with "Hello *World*" "#);
    }

    match plain(b"*Hello World*") {
        IResult::Error(_) => (),
        _ => panic!(r#" Plain failed with "*Hello World*" "#),
    }
}

#[test]
fn test_html1() {
    let p = Paragraph {
        parts: vec![Text::Plain("plaintext "),
                    Text::Italics("italics text")],
    };

    assert!(p.to_html() == "plaintext italics text".to_owned());
}

#[test]
fn test_italics_parse() {
    if let IResult::Done(input, output) = italics(b"*Hello* World") {
        assert_eq!(input, b" World");
        assert_eq!(output, Text::Italics("Hello"));
    } else {
        panic!(r#" Italics failed with "*Hello* World" "#);
    }

    match italics(b"Hello World") {
        IResult::Error(_) => (),
        _ => panic!(r#" Italics failed with "Hello World" "#),
    };

    match italics(b"*Hello World") {
        IResult::Incomplete(_) => (),
        _ => panic!(r#" Italics failed with "*Hello World" "#),
    }
}

#[test]
#[should_panic]                 // TODO: Fix
fn test_italics_escaped() {
    if let IResult::Done(input, output) = italics(br"*Hell\*o* World") {
        assert_eq!(output, Text::Italics("Hell*o"));
        assert_eq!(input, b" World");
    } else {
        panic!("Italics failed with \"*Hell\\*o* World");
    }
}
<commit_msg>Oops... asterisks are for bold, not italics<commit_after>use nom::*;
use std::str;

#[derive(Debug)]
pub struct Paragraph<'a> {
    parts: Vec<Text<'a>>,
}

#[derive(Debug, PartialEq)]
pub enum Text<'a> {
    Plain(&'a str),
    Bold(&'a str),
}

impl<'a> Paragraph<'a> {
    pub fn to_html(&self) -> String {
        self.parts.iter()
            .map(|text| match *text {
                Text::Plain(ref s) => s.to_string(),
                Text::Bold(ref s) => ["", &s[..], ""].concat(),
            })
            .collect::<Vec<_>>()
            .concat()
    }
}

named!(paragraph<Paragraph>,
    chain!(
        vec: many1!(alt!(plain | bold)),
        || { Paragraph { parts: vec } }
    )
);

named!(plain<Text>,
    chain!(
        bytes: is_not!("*") ~
        s:     expr_res!(str::from_utf8(bytes)),
        || { Text::Plain(s) }
    )
);

named!(bold<Text>,
    delimited!(
        char!('*'),
        chain!(
            bytes: is_not!("*") ~
            s:     expr_res!(str::from_utf8(bytes)),
            || { Text::Bold(s) }
        ),
        char!('*')
    )
);

#[test]
fn test_paragraph_parse() {
    if let IResult::Done(input, output) = paragraph(b"Hello *World*") {
        assert_eq!(input, b"");
        assert_eq!(output.parts, vec![Text::Plain("Hello "),
                                      Text::Bold("World")]);
    } else {
        panic!(r#" Paragraph parse failed with "Hello *World*" "#);
    }

    if let IResult::Done(input, output) = paragraph(b"*This* is *a test*") {
        assert_eq!(input, b"");
        assert_eq!(output.parts, vec![Text::Bold("This"),
                                      Text::Plain(" is "),
                                      Text::Bold("a test")]);
    } else {
        panic!(r#" Paragraph parse failed with "Hello *World*" "#);
    }
}

#[test]
fn test_plain_parse() {
    if let IResult::Done(input, output) = plain(b"Hello *World*") {
        assert_eq!(input, b"*World*");
        assert_eq!(output, Text::Plain("Hello "));
    } else {
        panic!(r#" Plain parse failed with "Hello *World*" "#);
    }

    match plain(b"*Hello World*") {
        IResult::Error(_) => (),
        _ => panic!(r#" Plain failed with "*Hello World*" "#),
    }
}

#[test]
fn test_html1() {
    let p = Paragraph {
        parts: vec![Text::Plain("plaintext "),
                    Text::Bold("bold text")],
    };

    assert!(p.to_html() == "plaintext bold text".to_owned());
}

#[test]
fn test_bold_parse() {
    if let IResult::Done(input, output) = bold(b"*Hello* World") {
        assert_eq!(input, b" World");
        assert_eq!(output, Text::Bold("Hello"));
    } else {
        panic!(r#" Bold failed with "*Hello* World" "#);
    }

    match bold(b"Hello World") {
        IResult::Error(_) => (),
        _ => panic!(r#" Bold failed with "Hello World" "#),
    };

    match bold(b"*Hello World") {
        IResult::Incomplete(_) => (),
        _ => panic!(r#" Bold failed with "*Hello World" "#),
    }
}

#[test]
#[should_panic]                 // TODO: Fix
fn test_bold_escaped() {
    if let IResult::Done(input, output) = bold(br"*Hell\*o* World") {
        assert_eq!(output, Text::Bold("Hell*o"));
        assert_eq!(input, b" World");
    } else {
        panic!("Bold failed with \"*Hell\\*o* World");
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;
use super::Span;
use super::token::{Token, TokenSpan, Lit};

pub struct Lexer<'a> {
    chars: Chars<'a>,
    last: Option<char>,
    last_pos: Option<usize>,
    curr: Option<char>,
    curr_pos: Option<usize>,
    next: Option<char>,
    span_pos: Option<usize>,
}

impl<'a> Lexer<'a> {
    pub fn from_query(q: &str) -> Lexer {
        let mut lex = Lexer {
            chars: q.chars(),
            last: None,
            last_pos: None,
            curr: None,
            curr_pos: None,
            next: None,
            span_pos: None,
        };

        lex.bump();
        lex.bump();
        lex
    }

    pub fn next_real(&mut self) -> Result<Option<TokenSpan>, LexError> {
        let tokenspn = try!(self.next());

        let wspace = match tokenspn {
            Some(ref token) => {
                match token.token {
                    Token::Whitespace => true,
                    _ => false,
                }
            }
            _ => false,
        };

        if wspace {
            self.next()
        } else {
            Ok(tokenspn)
        }
    }

    fn bump(&mut self) {
        self.last = self.curr;
        self.curr = self.next;
        self.next = self.chars.next();

        self.last_pos = self.curr_pos;

        match self.next {
            Some(c) => {
                if let Some(n) = self.curr_pos {
                    self.curr_pos = Some(n + c.len_utf8());
                } else {
                    self.curr_pos = Some(c.len_utf8());
                }
            }
            _ => {}
        }
    }

    fn scan_words(&mut self) -> String {
        let mut s = String::new();

        loop {
            match self.curr.unwrap_or(' ') {
                c @ 'a'...'z' |
                c @ 'A'...'Z' |
                c @ '0'...'9' |
                c @ '_' => {
                    s.push(c);
                }
                _ => break,
            }

            self.bump();
        }

        s
    }

    fn scan_nums(&mut self) -> String {
        let mut s = String::new();

        loop {
            match self.curr.unwrap_or(' ') {
                c @ '0'...'9' |
                c @ '.' => {
                    s.push(c);
                }
                _ => break,
            }

            self.bump();
        }

        s
    }

    fn scan_lits(&mut self) -> Result<String, LexError> {
        let mut s = String::new();

        self.bump(); // skip first char of the literal

        loop {
            match self.curr {
                Some('\'') |
                Some('"') => break,

                Some(c) => s.push(c),

                None => return Err(LexError::UnclosedQuote),
            }

            self.bump();
        }
        self.bump();

        Ok(s)
    }

    fn skip_whitespaces(&mut self) {
        loop {
            if Self::is_whitespace(self.curr.unwrap_or('x')) {
                self.bump();
            } else {
                break;
            }
        }
    }

    fn is_whitespace(c: char) -> bool {
        match c {
            ' ' | '\n' | '\t' => true,
            _ => false,
        }
    }

    fn next(&mut self) -> Result<Option<TokenSpan>, LexError> {
        let nextchar = self.next.unwrap_or('\x00').to_lowercase().next().unwrap();

        self.span_pos = self.curr_pos;

        let curr = match self.curr {
            Some(c) => c,
            None => return Ok(None),
        };

        let token = match curr {
            'a'...'z' | 'A'...'B' => {
                let word = self.scan_words();
                Token::Word(word)
            }

            // TODO: check to see if '.' is not a valid Literal
            '0'...'9' => {
                let n = self.scan_nums();
                if let Ok(i) = n.parse::<i64>() {
                    Token::Literal(Lit::Int(i))
                } else {
                    if let Ok(f) = n.parse::<f64>() {
                        Token::Literal(Lit::Float(f))
                    } else {
                        Token::Unknown
                    }
                }
            }

            ';' => {
                self.bump();
                Token::Semi
            }
            '.' => {
                self.bump();
                Token::Dot
            }
            ',' => {
                self.bump();
                Token::Comma
            }

            '(' => {
                self.bump();
                Token::ParentOP
            }

            // Literals
            '\'' | '"' => {
                let lit = try!(self.scan_lits());
                Token::Literal(Lit::String(lit))
            }

            '=' => {
                self.bump();
                Token::Equ
            }

            // Not Equal
            '!' if nextchar == '=' => {
                self.bump();
                self.bump();

                Token::NEqu
            }
            '<' if nextchar == '>' => {
                self.bump();
                self.bump();

                Token::NEqu
            }

            '>' => {
                self.bump();
                if nextchar == '=' {
                    self.bump();
                    Token::GEThan
                } else {
                    Token::GThan
                }
            }
            '<' => {
                self.bump();
                if nextchar == '=' {
                    self.bump();
                    Token::LEThan
                } else {
                    Token::LThan
                }
            }

            '+' => {
                self.bump();
                Token::Add
            }
            '-' => {
                self.bump();
                Token::Sub
            }
            '/' => {
                self.bump();
                Token::Div
            }
            '%' => {
                self.bump();
                Token::Mod
            }

            '*' => {
                self.bump();
                Token::Star
            }

            c if Self::is_whitespace(c) => {
                self.skip_whitespaces();
                Token::Whitespace
            }

            _ => {
                self.bump();
                Token::Unknown
            }

        };

        Ok(Some(TokenSpan {
            token: token,
            span: Span {
                // TODO: clean up the unwraps
                start: self.span_pos.unwrap(),
                end: self.curr_pos.unwrap(),
            },
        }))
    }
}

#[derive(Debug, PartialEq)]
pub enum LexError {
    UnclosedQuote,
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::super::token::*;

    fn compare_lex(q: &str, cmds: &[Token]) {
        let mut lex = Lexer::from_query(q);
        let mut index = 0;

        loop {
            let val = match lex.next_real().unwrap() {
                Some(val) => val,
                None => break,
            };

            // println!("{:?}, {:?}", val.token, cmds[index]);
            assert_eq!(val.token, cmds[index]);
            index += 1;
        }
    }

    #[test]
    fn lexer_simple() {
        let mut lex = Lexer::from_query("select");
        let val = lex.next_real().unwrap().unwrap().token;

        assert_eq!(val, Token::Word("select".to_owned()));
    }

    #[test]
    fn lexer_medium() {
        let mut lex = Lexer::from_query("select from");

        let val = lex.next_real().unwrap().unwrap();
        assert_eq!(format!("{:?}", val.token), "Word(\"select\")");

        let val = lex.next_real().unwrap().unwrap();
        assert_eq!(format!("{:?}", val.token), "Word(\"from\")");
    }

    #[test]
    fn lexer_hard() {
        let cmds = &[Token::Word("select".to_owned()),
                     Token::Star,
                     Token::Word("from".to_owned()),
                     Token::Semi];
        compare_lex("select * from;", cmds);

    }
}
<commit_msg>update lexer tests<commit_after>use std::str::Chars;
use super::Span;
use super::token::{Token, TokenSpan, Lit};

pub struct Lexer<'a> {
    chars: Chars<'a>,
    last: Option<char>,
    last_pos: Option<usize>,
    curr: Option<char>,
    curr_pos: Option<usize>,
    next: Option<char>,
    span_pos: Option<usize>,
}

impl<'a> Lexer<'a> {
    pub fn from_query(q: &str) -> Lexer {
        let mut lex = Lexer {
            chars: q.chars(),
            last: None,
            last_pos: None,
            curr: None,
            curr_pos: None,
            next: None,
            span_pos: None,
        };

        lex.bump();
        lex.bump();
        lex
    }

    pub fn next_real(&mut self) -> Result<Option<TokenSpan>, LexError> {
        let tokenspn = try!(self.next());

        let wspace = match tokenspn {
            Some(ref token) => {
                match token.token {
                    Token::Whitespace => true,
                    _ => false,
                }
            }
            _ => false,
        };

        if wspace {
            self.next()
        } else {
            Ok(tokenspn)
        }
    }

    fn bump(&mut self) {
        self.last = self.curr;
        self.curr = self.next;
        self.next = self.chars.next();

        self.last_pos = self.curr_pos;

        match self.next {
            Some(c) => {
                if let Some(n) = self.curr_pos {
                    self.curr_pos = Some(n + c.len_utf8());
                } else {
                    self.curr_pos = Some(c.len_utf8());
                }
            }
            _ => {}
        }
    }

    fn scan_words(&mut self) -> String {
        let mut s = String::new();

        loop {
            match self.curr.unwrap_or(' ') {
                c @ 'a'...'z' |
                c @ 'A'...'Z' |
                c @ '0'...'9' |
                c @ '_' => {
                    s.push(c);
                }
                _ => break,
            }

            self.bump();
        }

        s
    }

    fn scan_nums(&mut self) -> String {
        let mut s = String::new();

        loop {
            match self.curr.unwrap_or(' ') {
                c @ '0'...'9' |
                c @ '.' => {
                    s.push(c);
                }
                _ => break,
            }

            self.bump();
        }

        s
    }

    fn scan_lits(&mut self) -> Result<String, LexError> {
        let mut s = String::new();

        self.bump(); // skip first char of the literal

        loop {
            match self.curr {
                Some('\'') |
                Some('"') => break,

                Some(c) => s.push(c),

                None => return Err(LexError::UnclosedQuote),
            }

            self.bump();
        }
        self.bump();

        Ok(s)
    }

    fn skip_whitespaces(&mut self) {
        loop {
            if Self::is_whitespace(self.curr.unwrap_or('x')) {
                self.bump();
            } else {
                break;
            }
        }
    }

    fn is_whitespace(c: char) -> bool {
        match c {
            ' ' | '\n' | '\t' => true,
            _ => false,
        }
    }

    fn next(&mut self) -> Result<Option<TokenSpan>, LexError> {
        let nextchar = self.next.unwrap_or('\x00').to_lowercase().next().unwrap();

        self.span_pos = self.curr_pos;

        let curr = match self.curr {
            Some(c) => c,
            None => return Ok(None),
        };

        let token = match curr {
            'a'...'z' | 'A'...'B' => {
                let word = self.scan_words();
                Token::Word(word)
            }

            // TODO: check to see if '.' is not a valid Literal
            '0'...'9' => {
                let n = self.scan_nums();
                if let Ok(i) = n.parse::<i64>() {
                    Token::Literal(Lit::Int(i))
                } else {
                    if let Ok(f) = n.parse::<f64>() {
                        Token::Literal(Lit::Float(f))
                    } else {
                        Token::Unknown
                    }
                }
            }

            ';' => {
                self.bump();
                Token::Semi
            }
            '.' => {
                self.bump();
                Token::Dot
            }
            ',' => {
                self.bump();
                Token::Comma
            }

            '(' => {
                self.bump();
                Token::ParentOP
            }

            // Literals
            '\'' | '"' => {
                let lit = try!(self.scan_lits());
                Token::Literal(Lit::String(lit))
            }

            '=' => {
                self.bump();
                Token::Equ
            }

            // Not Equal
            '!' if nextchar == '=' => {
                self.bump();
                self.bump();

                Token::NEqu
            }
            '<' if nextchar == '>' => {
                self.bump();
                self.bump();

                Token::NEqu
            }

            '>' => {
                self.bump();
                if nextchar == '=' {
                    self.bump();
                    Token::GEThan
                } else {
                    Token::GThan
                }
            }
            '<' => {
                self.bump();
                if nextchar == '=' {
                    self.bump();
                    Token::LEThan
                } else {
                    Token::LThan
                }
            }

            '+' => {
                self.bump();
                Token::Add
            }
            '-' => {
                self.bump();
                Token::Sub
            }
            '/' => {
                self.bump();
                Token::Div
            }
            '%' => {
                self.bump();
                Token::Mod
            }

            '*' => {
                self.bump();
                Token::Star
            }

            c if Self::is_whitespace(c) => {
                self.skip_whitespaces();
                Token::Whitespace
            }

            _ => {
                self.bump();
                Token::Unknown
            }

        };

        Ok(Some(TokenSpan {
            token: token,
            span: Span {
                // TODO: clean up the unwraps
                start: self.span_pos.unwrap(),
                end: self.curr_pos.unwrap(),
            },
        }))
    }
}

#[derive(Debug, PartialEq)]
pub enum LexError {
    UnclosedQuote,
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::super::token::*;

    #[test]
    fn lexer_simple() {
        compare_lex("select", &[Token::Word("select".to_owned())]);
    }

    #[test]
    fn lexer_medium() {
        let cmds = &[Token::Word("select".to_owned()), Token::Word("from".to_owned())];

        compare_lex("select from", cmds);
    }

    #[test]
    fn lexer_hard() {
        let cmds = &[Token::Word("select".to_owned()),
                     Token::Star,
                     Token::Word("from".to_owned()),
                     Token::Semi];
        compare_lex("select * from;", cmds);

    }

    fn compare_lex(q: &str, cmds: &[Token]) {
        let mut lex = Lexer::from_query(q);
        let mut index = 0;

        loop {
            let val = match lex.next_real().unwrap() {
                Some(val) => val,
                None => break,
            };

            // println!("{:?}, {:?}", val.token, cmds[index]);
            assert_eq!(val.token, cmds[index]);
            index += 1;
        }
    }
}
<|endoftext|>


<commit_before>use std::io::buffered::BufferedStream;
use std::io::net::ip::SocketAddr;
use std::io::net::tcp::TcpStream;
use std::io::Stream;
use std::vec::bytes::push_bytes;
use std::vec;

pub enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

fn read_char<T: Stream>(io: &mut BufferedStream<T>) -> char {
  match io.read_byte() {
    Some(ch) => ch as char,
    None     => fail!()
  }
}

fn parse_data<T: Stream>(len: uint, io: &mut BufferedStream<T>) -> Result {
  let res =
    if (len > 0) {
      let bytes = io.read_bytes(len);
      assert!(bytes.len() == len);
      Data(bytes)
    } else {
      Data(~[])
    };
  assert!(read_char(io) == '\r');
  assert!(read_char(io) == '\n');
  return res;
}

fn parse_list<T: Stream>(len: uint, io: &mut BufferedStream<T>) -> Result {
  List(vec::from_fn(len, |_| { parse_response(io) }))
}

fn parse_int_line<T: Stream>(io: &mut BufferedStream<T>) -> int {
  let mut i: int = 0;
  let mut digits: uint = 0;
  let mut negative: bool = false;

  loop {
    let ch = read_char(io);
    match ch {
      '0' .. '9' => {
        digits += 1;
        i = (i * 10) + (ch as int - '0' as int);
        },
      '-' => {
        if negative { fail!() }
        negative = true
        },
      '\r' => {
        assert!(read_char(io) == '\n');
        break
        },
      '\n' => break,
      _ => fail!()
    }
  }

  if digits == 0 { fail!() }

  if negative { -i }
  else { i }
}

fn parse_n<T: Stream>(io: &mut BufferedStream<T>, f: |uint, &mut BufferedStream<T>| -> Result) -> Result {
  match parse_int_line(io) {
    -1 => Nil,
    len if len >= 0 => f(len as uint, io),
    _ => fail!()
  }
}

fn parse_status<T: Stream>(io: &mut BufferedStream<T>) -> Result {
  match io.read_line() {
    Some(line) => Status(line),
    None       => fail!()
  }
}

fn parse_error<T: Stream>(io: &mut BufferedStream<T>) -> Result {
  match io.read_line() {
    Some(line) => Error(line),
    None       => fail!()
  }
}

fn parse_response<T: Stream>(io: &mut BufferedStream<T>) -> Result {
  match read_char(io) {
    '$' => parse_n(io, parse_data),
    '*' => parse_n(io, parse_list),
    '+' => parse_status(io),
    '-' => parse_error(io),
    ':' => Int(parse_int_line(io)),
    _   => fail!()
  }
}

struct CommandWriter {
  buf: ~[u8]
}

impl CommandWriter {
  fn new() -> CommandWriter {
    CommandWriter { buf: ~[] }
  }

  fn args(&mut self, n: uint) {
    self.write_char('*');
    self.write_uint(n);
    self.write_crnl();
  }

  fn arg(&mut self, arg: &str) {
    self.write_char('$');
    self.write_uint(arg.len());
    self.write_crnl();
    self.write_str(arg);
    self.write_crnl();
  }

  fn write_crnl(&mut self) {
    self.write_char('\r');
    self.write_char('\n');
  }

  fn write_uint(&mut self, n: uint) {
    if n < 10 {
      self.write_byte('0' as u8 + (n as u8));
    }
    else {
      push_bytes(&mut self.buf, n.to_str().into_bytes());
    }
  }

  fn write_str(&mut self, s: &str) {
    push_bytes(&mut self.buf, s.as_bytes());
  }

  fn write_char(&mut self, s: char) {
    self.buf.push(s as u8);
  }

  fn write_byte(&mut self, b: u8) {
    self.buf.push(b);
  }

  fn with_buf<T>(&self, f: |&[u8]| -> T) -> T {
    f(self.buf.as_slice())
  }
}

fn execute<T: Stream>(cmd: &[u8], io: &mut BufferedStream<T>) -> Result {
  io.write(cmd);
  io.flush();
  parse_response(io)
}

pub struct Client<T> {
  priv io: BufferedStream<T>
}

impl Client<TcpStream> {
  pub fn new(sock_addr: &str) -> Client<TcpStream> {
    let addr = from_str::<SocketAddr>(sock_addr).unwrap();
    let tcp_stream = TcpStream::connect(addr).unwrap();
    Client::new_from_stream(tcp_stream)
  }
}

impl<T: Stream> Client<T> {
  pub fn new_from_stream(io: T) -> Client<T> {
    Client { io: BufferedStream::new(io) }
  }

  pub fn get(&mut self, key: &str) -> Result {
    let mut cwr = CommandWriter::new();
    cwr.args(2);
    cwr.arg("GET");
    cwr.arg(key);
    cwr.with_buf(|cmd| execute(cmd, &mut self.io))
  }

  pub fn set(&mut self, key: &str, val: &str) -> Result {
    let mut cwr = CommandWriter::new();
    cwr.args(3);
    cwr.arg("SET");
    cwr.arg(key);
    cwr.arg(val);
    cwr.with_buf(|cmd| execute(cmd, &mut self.io))
  }
}
<commit_msg>Do not fail! or assert!. Return ProtocolError<commit_after>use std::io::buffered::BufferedStream;
use std::io::net::ip::SocketAddr;
use std::io::net::tcp::TcpStream;
use std::io::Stream;
use std::vec::bytes::push_bytes;
use std::vec;

pub enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str),
  ProtocolError(&'static str)
}

fn read_char<T: Stream>(io: &mut BufferedStream<T>) -> Option<char> {
  match io.read_byte() {
    Some(ch) => Some(ch as char),
    None     => None
  }
}

fn parse_data<T: Stream>(len: uint, io: &mut BufferedStream<T>) -> Result {
  let res =
    if (len > 0) {
      let bytes = io.read_bytes(len);
      if bytes.len() != len {
        return ProtocolError("Invalid number of bytes")
      } else {
        Data(bytes)
      }
    } else {
      Data(~[])
    };

  if (read_char(io) != Some('\r')) {
    return ProtocolError("Carriage return expected"); // TODO: ignore
  }

  if (read_char(io) != Some('\n')) {
    return ProtocolError("Newline expected");
  }

  return res;
}

fn parse_list<T: Stream>(len: uint, io: &mut BufferedStream<T>) -> Result {
  let mut list: ~[Result] = vec::with_capacity(len);

  for _ in range(0, len) {
    match parse_response(io) {
      ProtocolError(err) => {
        return ProtocolError(err);
      }
      other => {
        list.push(other);
      }
    }
  }

  List(list)
}

fn parse_int_line<T: Stream>(io: &mut BufferedStream<T>) -> Option<int> {
  let mut i: int = 0;
  let mut digits: uint = 0;
  let mut negative: bool = false;

  loop {
    match read_char(io) {
      None => { return None }
      Some(ch) => {
        match ch {
          '0' .. '9' => {
            digits += 1;
            i = (i * 10) + (ch as int - '0' as int);
          }
          '-' => {
            if negative { return None }
            negative = true
          }
          '\r' => {
            if read_char(io) != Some('\n') { return None }
            break
          }
          '\n' => { break }
          _ => { return None }
        }
      }
    }
  }

  if digits == 0 { return None }

  if negative { Some(-i) }
  else { Some(i) }
}

fn parse_n<T: Stream>(io: &mut BufferedStream<T>, f: |uint, &mut BufferedStream<T>| -> Result) -> Result {
  match parse_int_line(io) {
    Some(-1) => Nil,
    Some(len) if len >= 0 => f(len as uint, io),
    _ => ProtocolError("Invalid number")
  }
}

fn parse_status<T: Stream>(io: &mut BufferedStream<T>) -> Result {
  match io.read_line() {
    Some(line) => Status(line),
    None       => ProtocolError("Invalid status line")
  }
}

fn parse_error<T: Stream>(io: &mut BufferedStream<T>) -> Result {
  match io.read_line() {
    Some(line) => Error(line),
    None       => ProtocolError("Invalid error line")
  }
}

fn parse_response<T: Stream>(io: &mut BufferedStream<T>) -> Result {
  match read_char(io) {
    Some('$') => parse_n(io, parse_data),
    Some('*') => parse_n(io, parse_list),
    Some('+') => parse_status(io),
    Some('-') => parse_error(io),
    Some(':') => {
      match parse_int_line(io) {
        Some(i) => Int(i),
        None => ProtocolError("Invalid number")
      }
    },
    Some(_)   => ProtocolError("Invalid character"),
    None      => ProtocolError("Invalid EOF")
  }
}

struct CommandWriter {
  buf: ~[u8]
}

impl CommandWriter {
  fn new() -> CommandWriter {
    CommandWriter { buf: ~[] }
  }

  fn args(&mut self, n: uint) {
    self.write_char('*');
    self.write_uint(n);
    self.write_crnl();
  }

  fn arg(&mut self, arg: &str) {
    self.write_char('$');
    self.write_uint(arg.len());
    self.write_crnl();
    self.write_str(arg);
    self.write_crnl();
  }

  fn write_crnl(&mut self) {
    self.write_char('\r');
    self.write_char('\n');
  }

  fn write_uint(&mut self, n: uint) {
    if n < 10 {
      self.write_byte('0' as u8 + (n as u8));
    }
    else {
      push_bytes(&mut self.buf, n.to_str().into_bytes());
    }
  }

  fn write_str(&mut self, s: &str) {
    push_bytes(&mut self.buf, s.as_bytes());
  }

  fn write_char(&mut self, s: char) {
    self.buf.push(s as u8);
  }

  fn write_byte(&mut self, b: u8) {
    self.buf.push(b);
  }

  fn with_buf<T>(&self, f: |&[u8]| -> T) -> T {
    f(self.buf.as_slice())
  }
}

fn execute<T: Stream>(cmd: &[u8], io: &mut BufferedStream<T>) -> Result {
  io.write(cmd);
  io.flush();
  parse_response(io)
}

pub struct Client<T> {
  priv io: BufferedStream<T>
}

impl Client<TcpStream> {
  pub fn new(sock_addr: &str) -> Client<TcpStream> {
    let addr = from_str::<SocketAddr>(sock_addr).unwrap();
    let tcp_stream = TcpStream::connect(addr).unwrap();
    Client::new_from_stream(tcp_stream)
  }
}

impl<T: Stream> Client<T> {
  pub fn new_from_stream(io: T) -> Client<T> {
    Client { io: BufferedStream::new(io) }
  }

  pub fn get(&mut self, key: &str) -> Result {
    let mut cwr = CommandWriter::new();
    cwr.args(2);
    cwr.arg("GET");
    cwr.arg(key);
    cwr.with_buf(|cmd| execute(cmd, &mut self.io))
  }

  pub fn set(&mut self, key: &str, val: &str) -> Result {
    let mut cwr = CommandWriter::new();
    cwr.args(3);
    cwr.arg("SET");
    cwr.arg(key);
    cwr.arg(val);
    cwr.with_buf(|cmd| execute(cmd, &mut self.io))
  }
}
<|endoftext|>


<commit_before>use satyrs::cnf::{CNF, Assignment, PartialAssignment};

/**
 * DPLL Algorithm implementation
 * Start by cloning the cnf so we can modify the HashMap
 * Clone might be slow, consider a faster option
 * TODO: Consider using HashSet instead of Vec for the clauses
 */
#[allow(non_snake_case)]
pub fn DPLL(cnf: &CNF) -> Option<Assignment> {
    //let _cnf = cnf.clone();
    //println!("DPLL {:?}", _cnf);
    let mut p_assn = PartialAssignment::new(cnf.nvar as usize);
    match _dpll(cnf, &mut p_assn) {
        Some(assn) => Some(assn.assignment.iter().map(|a| {
            println!("WE HERE ");
            match *a {
                Some(a) => a,
                None => true,
            }
        }).collect()),
        None => None,
    }
}

#[allow(unused_variables)]
fn _dpll(cnf: &CNF, p_assn: &mut PartialAssignment) -> Option<PartialAssignment> {
    // If consistent set of literals, return True
    println!("{}\n{}",cnf,p_assn);
    if cnf.clauses.is_empty() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);  // Display optional value
    }

    // If contains an empty clause return None
    // TODO: Consider optimizing
    for clause in cnf.clauses.values() {
        if clause.len() == 0 {
            return None;
        }
    }

    // For every unit-clause, unit-propogate
    let mut _cnf = cnf.clone();
    for unit in cnf.units.iter() {
        let clause = cnf.clauses.get(&unit).expect("Clause not found");
        let lit : i32 = zeroth!(clause);
        p_assn.assign_literal(lit);
        _cnf.unit_propagate(*unit); // Only propogate in the clone
    } // FIXME: Unit propogate might be the end of things
    println!("After Prop! {}",_cnf);
    // Clone for the right
    let mut r_cnf = _cnf.clone();
    // TODO: For every pure literal, pure literal assign
    // Choose literal L for split
    //let literal: i32 = zeroth!(_cnf.clauses.values().next().unwrap());
    let literal = match _cnf.clauses.values().next() {
        Some(thing) => Some(zeroth!(thing)),
        None => None,
    };

    if literal.is_none() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);
    }
    let lit = literal.unwrap();
    println!("Split on {} ({})",lit,lit/2);
    // Propagate literal
    _cnf.propagate(lit);

    // Return DPLL with L and -L
    p_assn.assign_literal(lit);
    let left = _dpll(&_cnf, p_assn);
    if left.is_some() { return left; }
    p_assn.unassign_literal(lit);
    p_assn.assign_literal(lit ^ 1);
    r_cnf.propagate(lit^1);
    _dpll(&_cnf, p_assn)
}
<commit_msg>Step through<commit_after>use satyrs::cnf::{CNF, Assignment, PartialAssignment};
use std::io;

/**
 * DPLL Algorithm implementation
 * Start by cloning the cnf so we can modify the HashMap
 * Clone might be slow, consider a faster option
 * TODO: Consider using HashSet instead of Vec for the clauses
 */
#[allow(non_snake_case)]
pub fn DPLL(cnf: &CNF) -> Option<Assignment> {
    //let _cnf = cnf.clone();
    //println!("DPLL {:?}", _cnf);
    let mut p_assn = PartialAssignment::new(cnf.nvar as usize);
    match _dpll(cnf, &mut p_assn) {
        Some(assn) => Some(assn.assignment.iter().map(|a| {
            println!("WE HERE ");
            match *a {
                Some(a) => a,
                None => true,
            }
        }).collect()),
        None => None,
    }
}

#[allow(unused_variables)]
fn _dpll(cnf: &CNF, p_assn: &mut PartialAssignment) -> Option<PartialAssignment> {
    // If consistent set of literals, return True
    println!("{}\n{}",cnf,p_assn);
    if cnf.clauses.is_empty() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);  // Display optional value
    }

    // If contains an empty clause return None
    // TODO: Consider optimizing
    for clause in cnf.clauses.values() {
        if clause.len() == 0 {
            return None;
        }
    }

    // For every unit-clause, unit-propogate
    let mut _cnf = cnf.clone();
    for unit in cnf.units.iter() {
        let clause = cnf.clauses.get(&unit).expect("Clause not found");
        let lit : i32 = zeroth!(clause);
        p_assn.assign_literal(lit);
        _cnf.unit_propagate(*unit); // Only propogate in the clone
    } // FIXME: Unit propogate might be the end of things
    println!("After Prop! {}",_cnf);
    // Clone for the right
    let mut r_cnf = _cnf.clone();

    // TODO: For every pure literal, pure literal assign
    // Choose literal L for split
    //let literal: i32 = zeroth!(_cnf.clauses.values().next().unwrap());
    let literal = match _cnf.clauses.values().next() {
        Some(thing) => Some(zeroth!(thing)),
        None => None,
    };

    if literal.is_none() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);
    }
    let lit = literal.unwrap();
    println!("Split on {} ({})",lit,lit/2);
    // Propagate literal
    _cnf.propagate(lit);

    // Return DPLL with L and -L
    p_assn.assign_literal(lit);

    let mut buffer = String::new();
    let _ = io::stdin().read_line(&mut buffer);

    let left = _dpll(&_cnf, p_assn);
    if left.is_some() { return left; }
    p_assn.unassign_literal(lit);
    p_assn.assign_literal(lit ^ 1);
    r_cnf.propagate(lit^1);
    _dpll(&_cnf, p_assn)
}
<|endoftext|>


<commit_before>// Queries.
use crate::bounding_volume::{BoundingSphere, AABB};
use crate::math::{Isometry, Vector};
use na::{self, RealField, Unit};
use crate::query::{PointQuery, RayCast};
use crate::shape::{CompositeShape, ConvexPolyhedron, DeformableShape, FeatureId, SupportMap};
use std::ops::Deref;
use std::sync::Arc;
use downcast_rs::Downcast;

pub trait ShapeClone<N: RealField> {
    fn clone_box(&self) -> Box<Shape<N>> {
        unimplemented!()
    }
}

impl<N: RealField, T: 'static + Shape<N> + Clone> ShapeClone<N> for T {
    fn clone_box(&self) -> Box<Shape<N>> {
        Box::new(self.clone())
    }
}

/// Trait implemented by all shapes supported by ncollide.
///
/// This allows dynamic inspection of the shape capabilities.
pub trait Shape<N: RealField>: Send + Sync + Downcast + ShapeClone<N> {
    /// The AABB of `self` transformed by `m`.
    #[inline]
    fn aabb(&self, m: &Isometry<N>) -> AABB<N>;

    /// The AABB of `self`.
    #[inline]
    fn local_aabb(&self) -> AABB<N> {
        self.aabb(&Isometry::identity())
    }

    /// The bounding sphere of `self` transformed by `m`.
    #[inline]
    fn bounding_sphere(&self, m: &Isometry<N>) -> BoundingSphere<N> {
        let aabb = self.aabb(m);
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// The bounding sphere of `self`.
    #[inline]
    fn local_bounding_sphere(&self) -> BoundingSphere<N> {
        let aabb = self.local_aabb();
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// Check if if the feature `_feature` of the `i-th` subshape of `self` transformed by `m` has a tangent
    /// cone that contains `dir` at the point `pt`.
    // NOTE: for the moment, we assume the tangent cone is the same for the whole feature.
    #[inline]
    fn tangent_cone_contains_dir(
        &self,
        _feature: FeatureId,
        _m: &Isometry<N>,
        _deformations: Option<&[N]>,
        _dir: &Unit<Vector<N>>,
    ) -> bool;

    /// Returns the id of the subshape containing the specified feature.
    ///
    /// If several subshape contains the same feature, any one is returned.
    fn subshape_containing_feature(&self, _i: FeatureId) -> usize {
        0
    }

    /// The `RayCast` implementation of `self`.
    #[inline]
    fn as_ray_cast(&self) -> Option<&RayCast<N>> {
        None
    }

    /// The `PointQuery` implementation of `self`.
    #[inline]
    fn as_point_query(&self) -> Option<&PointQuery<N>> {
        None
    }

    /// The convex polyhedron representation of `self` if applicable.
    #[inline]
    fn as_convex_polyhedron(&self) -> Option<&ConvexPolyhedron<N>> {
        None
    }

    /// The support mapping of `self` if applicable.
    #[inline]
    fn as_support_map(&self) -> Option<&SupportMap<N>> {
        None
    }

    /// The composite shape representation of `self` if applicable.
    #[inline]
    fn as_composite_shape(&self) -> Option<&CompositeShape<N>> {
        None
    }

    /// The deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape(&self) -> Option<&DeformableShape<N>> {
        None
    }

    /// The mutable deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape_mut(&mut self) -> Option<&mut DeformableShape<N>> {
        None
    }

    /// Whether `self` uses a convex polyhedron representation.
    #[inline]
    fn is_convex_polyhedron(&self) -> bool {
        self.as_convex_polyhedron().is_some()
    }

    /// Whether `self` uses a support-mapping based representation.
    #[inline]
    fn is_support_map(&self) -> bool {
        self.as_support_map().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_composite_shape(&self) -> bool {
        self.as_composite_shape().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_deformable_shape(&self) -> bool {
        self.as_deformable_shape().is_some()
    }
}

impl_downcast!(Shape<N> where N: RealField);

/// Trait for casting shapes to its exact represetation.
impl<N: RealField> Shape<N> {
    /// Tests if this shape has a specific type `T`.
    #[inline]
    pub fn is_shape<T: Shape<N>>(&self) -> bool {
        self.is::<T>()
    }

    /// Performs the cast.
    #[inline]
    pub fn as_shape<T: Shape<N>>(&self) -> Option<&T> {
        self.downcast_ref()
    }
}

impl<N: RealField> Clone for Box<Shape<N>> {
    fn clone(&self) -> Box<Shape<N>> {
        self.clone_box()
    }
}

/// A shared handle to an abstract shape.
///
/// This can be mutated using COW.
#[derive(Clone)]
pub struct ShapeHandle<N: RealField>(Arc<Box<Shape<N>>>);

impl<N: RealField> ShapeHandle<N> {
    /// Creates a sharable shape handle from a shape.
    #[inline]
    pub fn new<S: Shape<N>>(shape: S) -> ShapeHandle<N> {
        ShapeHandle(Arc::new(Box::new(shape)))
    }

    /// Creates a sharable shape handle from a shape trait object.
    pub fn new_from_box(shape: Box<Shape<N>>) -> ShapeHandle<N> {
        ShapeHandle(Arc::new(shape))
    }

    pub(crate) fn make_mut(&mut self) -> &mut Shape<N> {
        &mut **Arc::make_mut(&mut self.0)
    }
}

impl<N: RealField> AsRef<Shape<N>> for ShapeHandle<N> {
    #[inline]
    fn as_ref(&self) -> &Shape<N> {
        &*self.deref()
    }
}

impl<N: RealField> Deref for ShapeHandle<N> {
    type Target = Shape<N>;

    #[inline]
    fn deref(&self) -> &Shape<N> {
        &**self.0.deref()
    }
}<commit_msg>Rename ShapeHandle method new_from_box to from_box<commit_after>// Queries.
use crate::bounding_volume::{BoundingSphere, AABB};
use crate::math::{Isometry, Vector};
use na::{self, RealField, Unit};
use crate::query::{PointQuery, RayCast};
use crate::shape::{CompositeShape, ConvexPolyhedron, DeformableShape, FeatureId, SupportMap};
use std::ops::Deref;
use std::sync::Arc;
use downcast_rs::Downcast;

pub trait ShapeClone<N: RealField> {
    fn clone_box(&self) -> Box<Shape<N>> {
        unimplemented!()
    }
}

impl<N: RealField, T: 'static + Shape<N> + Clone> ShapeClone<N> for T {
    fn clone_box(&self) -> Box<Shape<N>> {
        Box::new(self.clone())
    }
}

/// Trait implemented by all shapes supported by ncollide.
///
/// This allows dynamic inspection of the shape capabilities.
pub trait Shape<N: RealField>: Send + Sync + Downcast + ShapeClone<N> {
    /// The AABB of `self` transformed by `m`.
    #[inline]
    fn aabb(&self, m: &Isometry<N>) -> AABB<N>;

    /// The AABB of `self`.
    #[inline]
    fn local_aabb(&self) -> AABB<N> {
        self.aabb(&Isometry::identity())
    }

    /// The bounding sphere of `self` transformed by `m`.
    #[inline]
    fn bounding_sphere(&self, m: &Isometry<N>) -> BoundingSphere<N> {
        let aabb = self.aabb(m);
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// The bounding sphere of `self`.
    #[inline]
    fn local_bounding_sphere(&self) -> BoundingSphere<N> {
        let aabb = self.local_aabb();
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// Check if if the feature `_feature` of the `i-th` subshape of `self` transformed by `m` has a tangent
    /// cone that contains `dir` at the point `pt`.
    // NOTE: for the moment, we assume the tangent cone is the same for the whole feature.
    #[inline]
    fn tangent_cone_contains_dir(
        &self,
        _feature: FeatureId,
        _m: &Isometry<N>,
        _deformations: Option<&[N]>,
        _dir: &Unit<Vector<N>>,
    ) -> bool;

    /// Returns the id of the subshape containing the specified feature.
    ///
    /// If several subshape contains the same feature, any one is returned.
    fn subshape_containing_feature(&self, _i: FeatureId) -> usize {
        0
    }

    /// The `RayCast` implementation of `self`.
    #[inline]
    fn as_ray_cast(&self) -> Option<&RayCast<N>> {
        None
    }

    /// The `PointQuery` implementation of `self`.
    #[inline]
    fn as_point_query(&self) -> Option<&PointQuery<N>> {
        None
    }

    /// The convex polyhedron representation of `self` if applicable.
    #[inline]
    fn as_convex_polyhedron(&self) -> Option<&ConvexPolyhedron<N>> {
        None
    }

    /// The support mapping of `self` if applicable.
    #[inline]
    fn as_support_map(&self) -> Option<&SupportMap<N>> {
        None
    }

    /// The composite shape representation of `self` if applicable.
    #[inline]
    fn as_composite_shape(&self) -> Option<&CompositeShape<N>> {
        None
    }

    /// The deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape(&self) -> Option<&DeformableShape<N>> {
        None
    }

    /// The mutable deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape_mut(&mut self) -> Option<&mut DeformableShape<N>> {
        None
    }

    /// Whether `self` uses a convex polyhedron representation.
    #[inline]
    fn is_convex_polyhedron(&self) -> bool {
        self.as_convex_polyhedron().is_some()
    }

    /// Whether `self` uses a support-mapping based representation.
    #[inline]
    fn is_support_map(&self) -> bool {
        self.as_support_map().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_composite_shape(&self) -> bool {
        self.as_composite_shape().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_deformable_shape(&self) -> bool {
        self.as_deformable_shape().is_some()
    }
}

impl_downcast!(Shape<N> where N: RealField);

/// Trait for casting shapes to its exact represetation.
impl<N: RealField> Shape<N> {
    /// Tests if this shape has a specific type `T`.
    #[inline]
    pub fn is_shape<T: Shape<N>>(&self) -> bool {
        self.is::<T>()
    }

    /// Performs the cast.
    #[inline]
    pub fn as_shape<T: Shape<N>>(&self) -> Option<&T> {
        self.downcast_ref()
    }
}

impl<N: RealField> Clone for Box<Shape<N>> {
    fn clone(&self) -> Box<Shape<N>> {
        self.clone_box()
    }
}

/// A shared handle to an abstract shape.
///
/// This can be mutated using COW.
#[derive(Clone)]
pub struct ShapeHandle<N: RealField>(Arc<Box<Shape<N>>>);

impl<N: RealField> ShapeHandle<N> {
    /// Creates a sharable shape handle from a shape.
    #[inline]
    pub fn new<S: Shape<N>>(shape: S) -> ShapeHandle<N> {
        ShapeHandle(Arc::new(Box::new(shape)))
    }

    /// Creates a sharable shape handle from a shape trait object.
    pub fn from_box(shape: Box<Shape<N>>) -> ShapeHandle<N> {
        ShapeHandle(Arc::new(shape))
    }

    pub(crate) fn make_mut(&mut self) -> &mut Shape<N> {
        &mut **Arc::make_mut(&mut self.0)
    }
}

impl<N: RealField> AsRef<Shape<N>> for ShapeHandle<N> {
    #[inline]
    fn as_ref(&self) -> &Shape<N> {
        &*self.deref()
    }
}

impl<N: RealField> Deref for ShapeHandle<N> {
    type Target = Shape<N>;

    #[inline]
    fn deref(&self) -> &Shape<N> {
        &**self.0.deref()
    }
}<|endoftext|>


<commit_before>
///
/// Systems are a set of event handlers and optionally some associated state.
///
/// The event handlers are invoked with a list of event data and have access to component
/// lists. This access can be immutable or mutable which is made explicit so that
/// the event handler scheduler might parallelize handler invocations.
///
/// To properly enforce this I guess the scheduler would acquire the locks on the component
/// lists.
///
/// So the context of the handler function would consist of:
///
///   The handler state
///   The event data list
///   Immutable components lists
///   Mutable components lists
///
/// For example the following invocation:
///
/// system! my_system {
///   state! { i: i64 }
///   on!(event_name, { positions: Position}, { descriptions: Description }) {
///     state.i += 1;
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
/// }
///
/// Expands to:
///
/// pub mod my_system {
///   struct State { i: i64 }
///
///   pub fn event_name(state: &mut State, data: &Vec<event_name::Data>, positions: &Vec<Position>, descriptions: &mut Vec<Description> ) {
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
///
///   pub fn register() {
///      events::register_handler(event_name); // etc..
///   }
/// }
///
/// How are we going to register this handler at the event loop?
///
/// Ideally we would have just one 'register' call per system. But to have that the register call should enable
/// all nested handlers. We could also just have one handler per system. That would make things easier..
/// Maybe there's some scheme using recursive macros that we could use to generate a register_system that collects
/// all on! calls. Ok this is definitely a possibility. We could simply match the on! macro in the system! macro
/// and use that to populate the register function.
///
/// How are we going to store/invoke these handlers.
///
/// To invoke the handler it will require the state, the components and the data list passed in the right order.
/// we could have a separate invoker function that invokes event_name with the arguments passed in. Its arguments
/// would be the component lists in two vecs, as well as the event data list.
///
/// This could work!
///

#[macro_export]
macro_rules! system {
	( $system_name:ident { $($contents:tt)* } ) => {
		pub mod $system_name {
			use std::collections::HashMap;
			use std::any::Any;
			use shared_mutex::{ SharedMutex, MappedSharedMutexReadGuard };

			system_contents!{ ( $($contents)* ) [ ] }
		}
	}
}

#[macro_export]
macro_rules! system_contents {
	// Consume on! invocations
	(
		(
			on! (
				$event_name:ident, $($event_declaration:tt)*
			) $_self:ident => $event_body:block $($rest:tt)*
		) [
			$($event_decls:tt)*
		]
	) => (
		on! { ($event_name, $( $event_declaration)* ) $_self => $event_body }

		system_contents!{( $($rest)* ) [ ( $event_name, $($event_declaration)* ) , $($event_decls)* ] }
	);

	(
		(
			state! { $($state_declaration:tt)* } $($rest:tt)*
		) [ $($event_decls:tt)* ]
	) => (
		state! { $($state_declaration)* }

		system_contents!{( $($rest)* ) [ $($event_decls)* ] }
	);

	// When all content has been consumed emit register macro
	(
		() [ $($event_decls:tt)* ]
	) => (
		system_register!{ $($event_decls)* }
	)
}

#[macro_export]
macro_rules! on {
	( ($event_name:ident, { $( $mut_name:ident : $mut_typ:ty )* } , { $($name:ident : $typ:ty)* } ) $_self:ident => $event_body:block ) => (

		use super::$event_name;

		impl State {
			pub fn $event_name(&mut $_self,
				data: Vec<$event_name::Data>,
				$( $name : &Vec<$typ>),*
				$( $mut_name : &mut Vec<$mut_typ> ),* ) $event_body

		}

		pub fn $event_name(data: Vec<$event_name::Data>, components: Vec<&Any>, mut_components: Vec<&mut Any>) {
			let components_iter = components.iter();
			let components_iter = mut_components.iter_mut();

			$(
				let $name : &Vec<$typ> = components_iter
					.next().expect("Event components list too short.")
					.downcast_ref().expect("Event component not of expected type.");
			)*

			$(
				let $mut_name: &mut Vec<$mut_name> = components_iter
					.next().expect("Event components list too short.")
					.downcast_ref().expect("Event component not of expected type.");
			)*

			state.write().expect("Event state corrupted").$event_name(
				data,
				$($name),*
				$($mut_name),*
			);
		}
	)
}

#[macro_export]
macro_rules! state {
	( $( $name:ident : $field:ty )* ) => (
		#[derive(Default)]
		pub struct State {
			pub $($name : $field),*
		}

		lazy_static! {
			pub static ref state: SharedMutex<State> = SharedMutex::new(State::default());
		}
	)
}

#[macro_export]
macro_rules! system_register {
	( $($event_decls:tt)* )=> (
		pub fn register() {

		}
	)
}

pub mod example_event {
	pub struct Data {
		x: i64
	}
}

system!( example_system {
	state! { x: i64 }

	on!( example_event, { positions: State }, {}) self => {
		self.x += 1;
	}

});

<commit_msg>small fixes to make it compile for non-mut components<commit_after>
///
/// Systems are a set of event handlers and optionally some associated state.
///
/// The event handlers are invoked with a list of event data and have access to component
/// lists. This access can be immutable or mutable which is made explicit so that
/// the event handler scheduler might parallelize handler invocations.
///
/// To properly enforce this I guess the scheduler would acquire the locks on the component
/// lists.
///
/// So the context of the handler function would consist of:
///
///   The handler state
///   The event data list
///   Immutable components lists
///   Mutable components lists
///
/// For example the following invocation:
///
/// system! my_system {
///   state! { i: i64 }
///   on!(event_name, { positions: Position}, { descriptions: Description }) {
///     state.i += 1;
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
/// }
///
/// Expands to:
///
/// pub mod my_system {
///   struct State { i: i64 }
///
///   pub fn event_name(state: &mut State, data: &Vec<event_name::Data>, positions: &Vec<Position>, descriptions: &mut Vec<Description> ) {
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
///
///   pub fn register() {
///      events::register_handler(event_name); // etc..
///   }
/// }
///
/// How are we going to register this handler at the event loop?
///
/// Ideally we would have just one 'register' call per system. But to have that the register call should enable
/// all nested handlers. We could also just have one handler per system. That would make things easier..
/// Maybe there's some scheme using recursive macros that we could use to generate a register_system that collects
/// all on! calls. Ok this is definitely a possibility. We could simply match the on! macro in the system! macro
/// and use that to populate the register function.
///
/// How are we going to store/invoke these handlers.
///
/// To invoke the handler it will require the state, the components and the data list passed in the right order.
/// we could have a separate invoker function that invokes event_name with the arguments passed in. Its arguments
/// would be the component lists in two vecs, as well as the event data list.
///
/// This could work!
///

#[macro_export]
macro_rules! system {
	( $system_name:ident { $($contents:tt)* } ) => {
		pub mod $system_name {
			use std::collections::HashMap;
			use std::any::Any;
			use shared_mutex::{ SharedMutex, MappedSharedMutexReadGuard };

			system_contents!{ ( $($contents)* ) [ ] }
		}
	}
}

#[macro_export]
macro_rules! system_contents {
	// Consume on! invocations
	(
		(
			on! (
				$event_name:ident, $($event_declaration:tt)*
			) $_self:ident => $event_body:block $($rest:tt)*
		) [
			$($event_decls:tt)*
		]
	) => (
		on! { ($event_name, $( $event_declaration)* ) $_self => $event_body }

		system_contents!{( $($rest)* ) [ ( $event_name, $($event_declaration)* ) , $($event_decls)* ] }
	);

	(
		(
			state! { $($state_declaration:tt)* } $($rest:tt)*
		) [ $($event_decls:tt)* ]
	) => (
		state! { $($state_declaration)* }

		system_contents!{( $($rest)* ) [ $($event_decls)* ] }
	);

	// When all content has been consumed emit register macro
	(
		() [ $($event_decls:tt)* ]
	) => (
		system_register!{ $($event_decls)* }
	)
}

#[macro_export]
macro_rules! on {
	( ($event_name:ident, { $( $mut_name:ident : $mut_typ:ty )* } , { $($name:ident : $typ:ty)* } ) $_self:ident => $event_body:block ) => (

		use super::$event_name;

		impl State {
			pub fn $event_name(&mut $_self,
				data: Vec<$event_name::Data>,
				$( $name : &Vec<$typ>),*
				$( $mut_name : &Vec<$mut_typ> ),* ) $event_body

		}

		pub fn $event_name(data: Vec<$event_name::Data>, components: Vec<&Any>, mut_components: Vec<&Any>) {
			let mut components_iter = components.iter();
			let mut mut_components_iter = mut_components.iter();

			$(
				let $name : &Vec<$typ> = components_iter
					.next().expect("Event components list too short.")
					.downcast_ref().expect("Event component not of expected type.");
			)*

			$(
				let $mut_name: &Vec<$mut_typ> = mut_components_iter
					.next().expect("Event components list too short.")
					.downcast_ref().expect("Event component not of expected type.");
			)*

			state.write().expect("Event state corrupted").$event_name(
				data,
				$($name),*
				$($mut_name),*
			);
		}
	)
}

#[macro_export]
macro_rules! state {
	( $( $name:ident : $field:ty )* ) => (
		#[derive(Default)]
		pub struct State {
			pub $($name : $field),*
		}

		lazy_static! {
			pub static ref state: SharedMutex<State> = SharedMutex::new(State::default());
		}
	)
}

#[macro_export]
macro_rules! system_register {
	( $($event_decls:tt)* )=> (
		pub fn register() {

		}
	)
}

pub mod example_event {
	pub struct Data {
		x: i64
	}
}

system!( example_system {
	state! { x: i64 }

	on!( example_event, { positions: State }, {}) self => {
		self.x += 1;
	}

});

<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A tree stream is the result of annotating an annotated stream. This forms a tree structure with the original input
//! stream at the leaves.
//!

use super::countable::*;
use super::symbol_reader::*;
use super::annotated_stream::*;
use super::symbol_range_dfa::*;

///
/// Represents a stream that has been decomposed into a tree
///
#[derive(Clone)]
pub struct TreeStream<InputSymbol, TokenType> {
    /// How the original input stream maps onto tokens
    tokens: AnnotatedStream<InputSymbol, TokenType>,

    /// The hierarchy of annotations. As a tree, the 'root' is considered to be the last entry in this list (it's built from the bottom up)
    annotations: Vec<AnnotatedStream<TokenType, TokenType>>
}

impl<InputSymbol: Clone+Ord+Countable, TokenType: Clone+Ord+Countable+'static> TreeStream<InputSymbol, TokenType> {
    ///
    /// Creates a new tree stream from a tokenized stream
    ///
    pub fn new_with_tokens(tokens: AnnotatedStream<InputSymbol, TokenType>) -> Self {
        TreeStream { tokens: tokens, annotations: vec![] }
    }

    ///
    /// Reads the input that made up this tree stream
    ///
    pub fn read_input<'a>(&'a self) -> Box<SymbolReader<InputSymbol>+'a> {
        self.tokens.read_input()
    }

    ///
    /// Works out the depth of this tree
    ///
    pub fn depth(&self) -> usize {
        self.annotations.len()+1
    }

    ///
    /// Reads a the tokens on a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level_tokens<'a>(&'a self, depth: usize) -> Box<SymbolReader<Token<TokenType>>+'a> {
        if depth == self.annotations.len() {
            // Just the tokens, mapping onto the original input stream
            self.tokens.read_tokens()
        } else {
            // Build up a symbol reader from the output and input of this stream
            let level  = (self.annotations.len()-1) - depth;
            let stream = &self.annotations[level];

            let mut tokens   = vec![];
            let mut last_pos = 0..0;
            let mut reader   = stream.read_tokens();

            loop {
                if let Some(level_token) = reader.next_symbol() {
                    // Append input symbols if there is a gap
                    if last_pos.end != level_token.location.start {
                        let gap_range         = last_pos.end..level_token.location.start;
                        let from_higher_level = stream.input_for_range(gap_range.clone());

                        for pos in gap_range.clone() {
                            tokens.push(Token::new(pos..pos+1, from_higher_level[pos-gap_range.start].clone()));
                        }
                    }

                    // Update the last pos so we can detect gaps after it
                    last_pos = level_token.location.clone();

                    // Add this token
                    tokens.push(level_token);
                } else {
                    // End of stream
                    break;
                }
            }

            // Append input tokens from the end of the stream
            let end_pos  = stream.input_len();
            let end_gap  = last_pos.end..end_pos;
            let from_end = stream.input_for_range(end_gap.clone());

            for pos in end_gap.clone() {
                tokens.push(Token::new(pos..pos+1, from_end[pos-end_gap.start].clone()));
            }

            // Result is a new vector stream
            Box::new(VecReader::from_vec(tokens))
        }
    }

    ///
    /// Reads a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level<'a>(&'a self, depth: usize) -> Box<SymbolReader<TokenType>+'a> {
        Box::new(self.read_level_tokens(depth).map_symbols(|token| token.output))
    }

    ///
    /// Performs pattern matching on the 'top level', adding another level to the tree. Returns the number of symbols in the new stream
    ///
    /// By matching a series of tokens against a regular pattern, we can further reduce a tokenized string, and build up a tree
    /// representation of the string's contents. 'Holes' that do not match the pattern allow the tree to have variable depth:
    ///
    pub fn tokenize_top_level(&mut self, dfa: &SymbolRangeDfa<TokenType, TokenType>) -> usize {
        // Read the tokens at the top level
        let next_level  = AnnotatedStream::from_tokenizer(dfa, self.read_level(0));
        let num_matched = next_level.output_len();

        self.annotations.push(next_level);

        num_matched
    }
}

#[cfg(test)]
mod test {
    use super::super::*;

    #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
    enum TestToken {
        Digit,
        Identifier,
        Operator,
        Whitespace,

        Expression
    }

    impl Countable for TestToken {
        fn next(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Identifier,
                TestToken::Identifier   => TestToken::Operator,
                TestToken::Operator     => TestToken::Whitespace,
                TestToken::Whitespace   => TestToken::Expression,
                TestToken::Expression   => TestToken::Digit
            }
        }

        fn prev(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Expression,
                TestToken::Identifier   => TestToken::Digit,
                TestToken::Operator     => TestToken::Identifier,
                TestToken::Whitespace   => TestToken::Operator,
                TestToken::Expression   => TestToken::Whitespace
            }
        }
    }

    fn create_simple_tokenizer() -> SymbolRangeDfa<char, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(MatchRange('0', '9').repeat_forever(1), TestToken::Digit);
        token_matcher.add_pattern(MatchRange('a', 'z').repeat_forever(1), TestToken::Identifier);
        token_matcher.add_pattern("+".into_pattern(), TestToken::Operator);
        token_matcher.add_pattern(" ".repeat_forever(1), TestToken::Whitespace);

        token_matcher.prepare_to_match()
    }

    fn create_expression_parser() -> SymbolRangeDfa<TestToken, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(Match(vec![TestToken::Digit]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Identifier]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]), TestToken::Expression);

        token_matcher.prepare_to_match()
    }

    #[test]
    pub fn can_iterate_over_base_stream() {
        let tokenizer        = create_simple_tokenizer();
        let tokenized_stream = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let tokenized_tree   = TreeStream::new_with_tokens(tokenized_stream);

        assert!(tokenized_tree.depth() == 1);
        assert!(tokenized_tree.read_input().to_vec() == vec!['a', '+', '1']);
    }

    #[test]
    pub fn can_reduce_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 2);            // 'Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression'
    }

    #[test]
    pub fn can_reduce_longer_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1+b".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_3  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(3).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit, TestToken::Operator, TestToken::Identifier]);
        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 3);            // 'Expression Operator Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression Operator Expression'
        assert!(num_expressions_3 == 1);            // 'Expression'
    }
}
<commit_msg>Start work on a tree node type for navigating the tree stream<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A tree stream is the result of annotating an annotated stream. This forms a tree structure with the original input
//! stream at the leaves. This can be used to represent the result of parsing an input.
//!

use super::countable::*;
use super::symbol_reader::*;
use super::annotated_stream::*;
use super::symbol_range_dfa::*;

///
/// Represents a stream that has been decomposed into a tree
///
#[derive(Clone)]
pub struct TreeStream<InputSymbol, TokenType> {
    /// How the original input stream maps onto tokens
    tokens: AnnotatedStream<InputSymbol, TokenType>,

    /// The hierarchy of annotations. As a tree, the 'root' is considered to be the last entry in this list (it's built from the bottom up)
    annotations: Vec<AnnotatedStream<TokenType, TokenType>>
}

impl<InputSymbol: Clone+Ord+Countable, TokenType: Clone+Ord+Countable+'static> TreeStream<InputSymbol, TokenType> {
    ///
    /// Creates a new tree stream from a tokenized stream
    ///
    pub fn new_with_tokens(tokens: AnnotatedStream<InputSymbol, TokenType>) -> Self {
        TreeStream { tokens: tokens, annotations: vec![] }
    }

    ///
    /// Reads the input that made up this tree stream
    ///
    pub fn read_input<'a>(&'a self) -> Box<SymbolReader<InputSymbol>+'a> {
        self.tokens.read_input()
    }

    ///
    /// Works out the depth of this tree
    ///
    pub fn depth(&self) -> usize {
        self.annotations.len()+1
    }

    ///
    /// Reads a the tokens on a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level_tokens<'a>(&'a self, depth: usize) -> Box<SymbolReader<Token<TokenType>>+'a> {
        if depth == self.annotations.len() {
            // Just the tokens, mapping onto the original input stream
            self.tokens.read_tokens()
        } else {
            // Build up a symbol reader from the output and input of this stream
            let level  = (self.annotations.len()-1) - depth;
            let stream = &self.annotations[level];

            let mut tokens   = vec![];
            let mut last_pos = 0..0;
            let mut reader   = stream.read_tokens();

            loop {
                if let Some(level_token) = reader.next_symbol() {
                    // Append input symbols if there is a gap
                    if last_pos.end != level_token.location.start {
                        let gap_range         = last_pos.end..level_token.location.start;
                        let from_higher_level = stream.input_for_range(gap_range.clone());

                        for pos in gap_range.clone() {
                            tokens.push(Token::new(pos..pos+1, from_higher_level[pos-gap_range.start].clone()));
                        }
                    }

                    // Update the last pos so we can detect gaps after it
                    last_pos = level_token.location.clone();

                    // Add this token
                    tokens.push(level_token);
                } else {
                    // End of stream
                    break;
                }
            }

            // Append input tokens from the end of the stream
            let end_pos  = stream.input_len();
            let end_gap  = last_pos.end..end_pos;
            let from_end = stream.input_for_range(end_gap.clone());

            for pos in end_gap.clone() {
                tokens.push(Token::new(pos..pos+1, from_end[pos-end_gap.start].clone()));
            }

            // Result is a new vector stream
            Box::new(VecReader::from_vec(tokens))
        }
    }

    ///
    /// Reads a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level<'a>(&'a self, depth: usize) -> Box<SymbolReader<TokenType>+'a> {
        Box::new(self.read_level_tokens(depth).map_symbols(|token| token.output))
    }

    ///
    /// Performs pattern matching on the 'top level', adding another level to the tree. Returns the number of symbols in the new stream
    ///
    /// By matching a series of tokens against a regular pattern, we can further reduce a tokenized string, and build up a tree
    /// representation of the string's contents. 'Holes' that do not match the pattern allow the tree to have variable depth:
    ///
    pub fn tokenize_top_level(&mut self, dfa: &SymbolRangeDfa<TokenType, TokenType>) -> usize {
        // Read the tokens at the top level
        let next_level  = AnnotatedStream::from_tokenizer(dfa, self.read_level(0));
        let num_matched = next_level.output_len();

        self.annotations.push(next_level);

        num_matched
    }
}

///
/// Represents a node in a tree stream
///
pub struct TreeNode<'a, InputSymbol: 'a, OutputSymbol: 'a> {
    /// The tree that this node is a part of
    tree: &'a TreeStream<InputSymbol, OutputSymbol>,

    /// The distance from the bottom of the tree that this node represents (0 = tokens, 1+ = a leven in the annotations)
    level: usize,

    /// The token representing the 'root' of this tree
    token: Token<OutputSymbol>
}

impl<'a, InputSymbol: 'a, OutputSymbol: Clone+'a> TreeNode<'a, InputSymbol, OutputSymbol> {
    ///
    /// Retrieves the output symbol represented by this tree node
    ///
    pub fn get_symbol(&self) -> OutputSymbol {
        self.token.output.clone()
    }

    ///
    /// Retrieves the child nodes of this node (the empty set if this is a leaf node)
    ///
    pub fn get_children(&self) -> Vec<TreeNode<'a, InputSymbol, OutputSymbol>> {
        if self.level == 0 {
            // Level 0 is at the bottom
            vec![]
        } else {
            unimplemented!()
        }
    }
}

#[cfg(test)]
mod test {
    use super::super::*;

    #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
    enum TestToken {
        Digit,
        Identifier,
        Operator,
        Whitespace,

        Expression
    }

    impl Countable for TestToken {
        fn next(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Identifier,
                TestToken::Identifier   => TestToken::Operator,
                TestToken::Operator     => TestToken::Whitespace,
                TestToken::Whitespace   => TestToken::Expression,
                TestToken::Expression   => TestToken::Digit
            }
        }

        fn prev(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Expression,
                TestToken::Identifier   => TestToken::Digit,
                TestToken::Operator     => TestToken::Identifier,
                TestToken::Whitespace   => TestToken::Operator,
                TestToken::Expression   => TestToken::Whitespace
            }
        }
    }

    fn create_simple_tokenizer() -> SymbolRangeDfa<char, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(MatchRange('0', '9').repeat_forever(1), TestToken::Digit);
        token_matcher.add_pattern(MatchRange('a', 'z').repeat_forever(1), TestToken::Identifier);
        token_matcher.add_pattern("+".into_pattern(), TestToken::Operator);
        token_matcher.add_pattern(" ".repeat_forever(1), TestToken::Whitespace);

        token_matcher.prepare_to_match()
    }

    fn create_expression_parser() -> SymbolRangeDfa<TestToken, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(Match(vec![TestToken::Digit]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Identifier]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]), TestToken::Expression);

        token_matcher.prepare_to_match()
    }

    #[test]
    pub fn can_iterate_over_base_stream() {
        let tokenizer        = create_simple_tokenizer();
        let tokenized_stream = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let tokenized_tree   = TreeStream::new_with_tokens(tokenized_stream);

        assert!(tokenized_tree.depth() == 1);
        assert!(tokenized_tree.read_input().to_vec() == vec!['a', '+', '1']);
    }

    #[test]
    pub fn can_reduce_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 2);            // 'Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression'
    }

    #[test]
    pub fn can_reduce_longer_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1+b".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_3  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(3).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit, TestToken::Operator, TestToken::Identifier]);
        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 3);            // 'Expression Operator Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression Operator Expression'
        assert!(num_expressions_3 == 1);            // 'Expression'
    }
}
<|endoftext|>