<commit_before>#[cfg(not(syn_can_match_ident_after_attrs))]
macro_rules! ast_struct {
    (
        $(#[$attr:meta])*
        pub struct $name:ident #full $($rest:tt)*
    ) => {
        #[cfg(feature = "full")]
        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        pub struct $name $($rest)*

        #[cfg(not(feature = "full"))]
        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        pub struct $name {
            _noconstruct: (),
        }
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident #manual_extra_traits $($rest:tt)*
    ) => {
        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        pub struct $name $($rest)*
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident $($rest:tt)*
    ) => {
        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        pub struct $name $($rest)*
    };
}

#[cfg(syn_can_match_ident_after_attrs)]
macro_rules! ast_struct {
    (
        $(#[$attr:meta])*
        $pub:ident $struct:ident $name:ident #full $($rest:tt)*
    ) => {
        check_keyword_matches!(pub $pub);
        check_keyword_matches!(struct $struct);

        #[cfg(feature = "full")]
        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $pub $struct $name $($rest)*

        #[cfg(not(feature = "full"))]
        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $pub $struct $name {
            _noconstruct: (),
        }
    };

    (
        $(#[$attr:meta])*
        $pub:ident $struct:ident $name:ident #manual_extra_traits $($rest:tt)*
    ) => {
        check_keyword_matches!(pub $pub);
        check_keyword_matches!(struct $struct);

        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $pub $struct $name $($rest)*
    };

    (
        $(#[$attr:meta])*
        $pub:ident $struct:ident $name:ident $($rest:tt)*
    ) => {
        check_keyword_matches!(pub $pub);
        check_keyword_matches!(struct $struct);

        $(#[$attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $pub $struct $name $($rest)*
    };
}

#[cfg(not(syn_can_match_ident_after_attrs))]
macro_rules! ast_enum {
    // Drop the `#no_visit` attribute, if present.
    (
        $(#[$enum_attr:meta])*
        pub enum $name:ident #no_visit $($rest:tt)*
    ) => (
        ast_enum! { $(#[$enum_attr])* pub enum $name $($rest)* }
    );

    (
        $(#[$enum_attr:meta])*
        pub enum $name:ident $($rest:tt)*
    ) => (
        $(#[$enum_attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        pub enum $name $($rest)*
    );
}

#[cfg(syn_can_match_ident_after_attrs)]
macro_rules! ast_enum {
    // Drop the `#no_visit` attribute, if present.
    (
        $(#[$enum_attr:meta])*
        $pub:ident $enum:ident $name:ident #no_visit $($rest:tt)*
    ) => (
        ast_enum! { $(#[$enum_attr])* $pub $enum $name $($rest)* }
    );

    (
        $(#[$enum_attr:meta])*
        $pub:ident $enum:ident $name:ident $($rest:tt)*
    ) => (
        check_keyword_matches!(pub $pub);
        check_keyword_matches!(enum $enum);

        $(#[$enum_attr])*
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $pub $enum $name $($rest)*
    );
}

#[cfg(not(syn_can_match_ident_after_attrs))]
macro_rules! ast_enum_of_structs {
    (
        $(#[$enum_attr:meta])*
        pub enum $name:ident {
            $(
                $(#[$variant_attr:meta])*
                pub $variant:ident $( ($member:ident $($rest:tt)*) )*,
            )*
        }

        $($remaining:tt)*
    ) => (
        ast_enum! {
            $(#[$enum_attr])*
            pub enum $name {
                $(
                    $(#[$variant_attr])*
                    $variant $( ($member) )*,
                )*
            }
        }

        $(
            maybe_ast_struct! {
                $(#[$variant_attr])*
                $(
                    pub struct $member $($rest)*
                )*
            }

            $(
                impl From<$member> for $name {
                    fn from(e: $member) -> $name {
                        $name::$variant(e)
                    }
                }
            )*
        )*

        #[cfg(feature = "printing")]
        generate_to_tokens! {
            $($remaining)*
            ()
            tokens
            $name { $($variant $( [$($rest)*] )*,)* }
        }
    )
}

// Unfortunately, at this time, we can't make the generated enum here have the
// correct span. The way that the span for the overall enum decl is calculated
// is using `lo.to(prev_span)` [1].
//
// If the beginning and ending spans of the enum item don't have the same macro
// context, fallback code is run [2]. This code chooses the span within the
// macro context to avoid firing spurious diagnostics [3].
//
// This means `[src]` links in rustdoc will point to the macro, instead of the
// actual declaration, if either the first or last token of our declaration has
// a span from the macro. With `macro_rules!` there is no way to preserve the
// span of a `{}` block while changing its contents, so we're forced to have the
// span of our final token point to our macro.
//
// [1]: https://github.com/rust-lang/rust/blob/9a90d03ad171856dc016c2dcc19292ec49a8a26f/src/libsyntax/parse/parser.rs#L7377
// [2]: https://github.com/rust-lang/rust/blob/9a90d03ad171856dc016c2dcc19292ec49a8a26f/src/libsyntax_pos/lib.rs#L467-L478
// [3]: https://github.com/rust-lang/rust/pull/47942
#[cfg(syn_can_match_ident_after_attrs)]
macro_rules! ast_enum_of_structs {
    (
        $(#[$enum_attr:meta])*
        $pub:ident $enum:ident $name:ident {
            $(
                $(#[$variant_attr:meta])*
                $vpub:ident $variant:ident $( ($member:ident $($rest:tt)*) )*,
            )*
        }

        $($remaining:tt)*
    ) => (
        check_keyword_matches!(pub $pub);
        check_keyword_matches!(enum $enum);

        ast_enum! {
            $(#[$enum_attr])*
            $pub $enum $name {
                $(
                    $(#[$variant_attr])*
                    $variant $( ($member) )*,
                )*
            }
        }

        $(
            check_keyword_matches!(pub $vpub);
            maybe_ast_struct! {
                $(#[$variant_attr])*
                $(
                    $vpub struct $member $($rest)*
                )*
            }

            $(
                impl From<$member> for $name {
                    fn from(e: $member) -> $name {
                        $name::$variant(e)
                    }
                }
            )*
        )*

        #[cfg(feature = "printing")]
        generate_to_tokens! {
            $($remaining)*
            ()
            tokens
            $name { $($variant $( [$($rest)*] )*,)* }
        }
    )
}

#[cfg(feature = "printing")]
macro_rules! generate_to_tokens {
    (do_not_generate_to_tokens $($foo:tt)*) => ();

    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident, $($next:tt)*}) => {
        generate_to_tokens!(
            ($($arms)* $name::$variant => {})
            $tokens $name { $($next)* }
        );
    };

    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident [$($rest:tt)*], $($next:tt)*}) => {
        generate_to_tokens!(
            ($($arms)* $name::$variant(ref _e) => to_tokens_call!(_e, $tokens, $($rest)*),)
            $tokens $name { $($next)* }
        );
    };

    (($($arms:tt)*) $tokens:ident $name:ident {}) => {
        impl ::quote::ToTokens for $name {
            fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
                match *self {
                    $($arms)*
                }
            }
        }
    };
}

#[cfg(all(feature = "printing", feature = "full"))]
macro_rules! to_tokens_call {
    ($e:ident, $tokens:ident, $($rest:tt)*) => {
        $e.to_tokens($tokens)
    };
}

#[cfg(all(feature = "printing", feature = "derive", not(feature = "full")))]
macro_rules! to_tokens_call {
    // If the variant is marked as #full, don't auto-generate to-tokens for it.
    ($e:ident, $tokens:ident, #full $($rest:tt)*) => {
        unreachable!()
    };
    ($e:ident, $tokens:ident, $($rest:tt)*) => {
        $e.to_tokens($tokens)
    };
}

macro_rules! maybe_ast_struct {
    (
        $(#[$attr:meta])*
        $(
            pub struct $name:ident
        )*
    ) => ();

    ($($rest:tt)*) => (ast_struct! { $($rest)* });
}

#[cfg(syn_can_match_ident_after_attrs)]
macro_rules! check_keyword_matches {
    (struct struct) => {};
    (enum enum) => {};
    (pub pub) => {};
}
<commit_msg>Factor out fallback logic for ast_struct and ast_enum<commit_after>macro_rules! ast_struct {
    (
        @@ [$($attrs_pub:tt)*]
        struct $name:ident #full $($rest:tt)*
    ) => {
        #[cfg(feature = "full")]
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $($attrs_pub)* struct $name $($rest)*

        #[cfg(not(feature = "full"))]
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $($attrs_pub)* struct $name {
            _noconstruct: (),
        }
    };

    (
        @@ [$($attrs_pub:tt)*]
        struct $name:ident #manual_extra_traits $($rest:tt)*
    ) => {
        #[cfg_attr(feature = "extra-traits", derive(Debug))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $($attrs_pub)* struct $name $($rest)*
    };

    (
        @@ [$($attrs_pub:tt)*]
        struct $name:ident $($rest:tt)*
    ) => {
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $($attrs_pub)* struct $name $($rest)*
    };

    ($($t:tt)*) => {
        strip_attrs_pub!(ast_struct!($($t)*));
    };
}

macro_rules! ast_enum {
    // Drop the `#no_visit` attribute, if present.
    (
        @@ [$($attrs_pub:tt)*]
        enum $name:ident #no_visit $($rest:tt)*
    ) => (
        ast_enum!(@@ [$($attrs_pub)*] enum $name $($rest)*);
    );

    (
        @@ [$($attrs_pub:tt)*]
        enum $name:ident $($rest:tt)*
    ) => (
        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
        #[cfg_attr(feature = "clone-impls", derive(Clone))]
        $($attrs_pub)* enum $name $($rest)*
    );

    ($($t:tt)*) => {
        strip_attrs_pub!(ast_enum!($($t)*));
    };
}

#[cfg(not(syn_can_match_ident_after_attrs))]
macro_rules! ast_enum_of_structs {
    (
        $(#[$enum_attr:meta])*
        pub enum $name:ident {
            $(
                $(#[$variant_attr:meta])*
                pub $variant:ident $( ($member:ident $($rest:tt)*) )*,
            )*
        }

        $($remaining:tt)*
    ) => (
        ast_enum! {
            $(#[$enum_attr])*
            pub enum $name {
                $(
                    $(#[$variant_attr])*
                    $variant $( ($member) )*,
                )*
            }
        }

        $(
            maybe_ast_struct! {
                $(#[$variant_attr])*
                $(
                    pub struct $member $($rest)*
                )*
            }

            $(
                impl From<$member> for $name {
                    fn from(e: $member) -> $name {
                        $name::$variant(e)
                    }
                }
            )*
        )*

        #[cfg(feature = "printing")]
        generate_to_tokens! {
            $($remaining)*
            ()
            tokens
            $name { $($variant $( [$($rest)*] )*,)* }
        }
    )
}

// Unfortunately, at this time, we can't make the generated enum here have the
// correct span. The way that the span for the overall enum decl is calculated
// is using `lo.to(prev_span)` [1].
//
// If the beginning and ending spans of the enum item don't have the same macro
// context, fallback code is run [2]. This code chooses the span within the
// macro context to avoid firing spurious diagnostics [3].
//
// This means `[src]` links in rustdoc will point to the macro, instead of the
// actual declaration, if either the first or last token of our declaration has
// a span from the macro. With `macro_rules!` there is no way to preserve the
// span of a `{}` block while changing its contents, so we're forced to have the
// span of our final token point to our macro.
//
// [1]: https://github.com/rust-lang/rust/blob/9a90d03ad171856dc016c2dcc19292ec49a8a26f/src/libsyntax/parse/parser.rs#L7377
// [2]: https://github.com/rust-lang/rust/blob/9a90d03ad171856dc016c2dcc19292ec49a8a26f/src/libsyntax_pos/lib.rs#L467-L478
// [3]: https://github.com/rust-lang/rust/pull/47942
#[cfg(syn_can_match_ident_after_attrs)]
macro_rules! ast_enum_of_structs {
    (
        $(#[$enum_attr:meta])*
        $pub:ident $enum:ident $name:ident {
            $(
                $(#[$variant_attr:meta])*
                $vpub:ident $variant:ident $( ($member:ident $($rest:tt)*) )*,
            )*
        }

        $($remaining:tt)*
    ) => (
        check_keyword_matches!(pub $pub);
        check_keyword_matches!(enum $enum);

        ast_enum! {
            $(#[$enum_attr])*
            $pub $enum $name {
                $(
                    $(#[$variant_attr])*
                    $variant $( ($member) )*,
                )*
            }
        }

        $(
            check_keyword_matches!(pub $vpub);
            maybe_ast_struct! {
                $(#[$variant_attr])*
                $(
                    $vpub struct $member $($rest)*
                )*
            }

            $(
                impl From<$member> for $name {
                    fn from(e: $member) -> $name {
                        $name::$variant(e)
                    }
                }
            )*
        )*

        #[cfg(feature = "printing")]
        generate_to_tokens! {
            $($remaining)*
            ()
            tokens
            $name { $($variant $( [$($rest)*] )*,)* }
        }
    )
}

#[cfg(feature = "printing")]
macro_rules! generate_to_tokens {
    (do_not_generate_to_tokens $($foo:tt)*) => ();

    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident, $($next:tt)*}) => {
        generate_to_tokens!(
            ($($arms)* $name::$variant => {})
            $tokens $name { $($next)* }
        );
    };

    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident [$($rest:tt)*], $($next:tt)*}) => {
        generate_to_tokens!(
            ($($arms)* $name::$variant(ref _e) => to_tokens_call!(_e, $tokens, $($rest)*),)
            $tokens $name { $($next)* }
        );
    };

    (($($arms:tt)*) $tokens:ident $name:ident {}) => {
        impl ::quote::ToTokens for $name {
            fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
                match *self {
                    $($arms)*
                }
            }
        }
    };
}

#[cfg(all(feature = "printing", feature = "full"))]
macro_rules! to_tokens_call {
    ($e:ident, $tokens:ident, $($rest:tt)*) => {
        $e.to_tokens($tokens)
    };
}

#[cfg(all(feature = "printing", feature = "derive", not(feature = "full")))]
macro_rules! to_tokens_call {
    // If the variant is marked as #full, don't auto-generate to-tokens for it.
    ($e:ident, $tokens:ident, #full $($rest:tt)*) => {
        unreachable!()
    };
    ($e:ident, $tokens:ident, $($rest:tt)*) => {
        $e.to_tokens($tokens)
    };
}

macro_rules! maybe_ast_struct {
    (
        $(#[$attr:meta])*
        $(
            pub struct $name:ident
        )*
    ) => ();

    ($($rest:tt)*) => (ast_struct! { $($rest)* });
}

#[cfg(not(syn_can_match_ident_after_attrs))]
macro_rules! strip_attrs_pub {
    ($mac:ident!($(#[$m:meta])* pub $($t:tt)*)) => {
        $mac!(@@ [$(#[$m])* pub] $($t)*);
    };
}

#[cfg(syn_can_match_ident_after_attrs)]
macro_rules! strip_attrs_pub {
    ($mac:ident!($(#[$m:meta])* $pub:ident $($t:tt)*)) => {
        check_keyword_matches!(pub $pub);

        $mac!(@@ [$(#[$m])* $pub] $($t)*);
    };
}

#[cfg(syn_can_match_ident_after_attrs)]
macro_rules! check_keyword_matches {
    (struct struct) => {};
    (enum enum) => {};
    (pub pub) => {};
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! bson {
    ([$($val:tt),*]) => {{
        let mut array = Vec::new();

        $(
            array.push(bson!($val));
        )*

        $crate::Bson::Array(array)
    }};

    ([$val:expr]) => {{
        $crate::Bson::Array(vec!(::std::convert::From::from($val)))
    }};

    ({ $($k:expr => $v:tt),* }) => {{
        $crate::Bson::Document(doc! {
            $(
                $k => $v
            ),*
        })
    }};

    ($val:expr) => {{
        ::std::convert::From::from($val)
    }};
}

#[macro_export]
macro_rules! doc {
    ( $($key:expr => $val:tt),* ) => {{
        let mut document = $crate::Document::new();

        $(
            document.insert($key.to_owned(), bson!($val));
        )*

        document
    }};
}
<commit_msg>Remove mut warning for empty macro<commit_after>#[macro_export]
macro_rules! bson {
    ([$($val:tt),*]) => {{
        let mut array = Vec::new();

        $(
            array.push(bson!($val));
        )*

        $crate::Bson::Array(array)
    }};

    ([$val:expr]) => {{
        $crate::Bson::Array(vec!(::std::convert::From::from($val)))
    }};

    ({ $($k:expr => $v:tt),* }) => {{
        $crate::Bson::Document(doc! {
            $(
                $k => $v
            ),*
        })
    }};

    ($val:expr) => {{
        ::std::convert::From::from($val)
    }};
}

#[macro_export]
macro_rules! doc {
    () => {{ $crate::Document::new() }};

    ( $($key:expr => $val:tt),* ) => {{
        let mut document = $crate::Document::new();

        $(
            document.insert($key.to_owned(), bson!($val));
        )*

        document
    }};
}
<|endoftext|>


<commit_before>pub struct Matrix {
  rows: uint,
  cols: uint,
  data: Vec<f64>
}

impl Index<uint, [f64]> for Matrix {
  fn index<'a>(&'a self, index: &uint) -> &'a [f64] {
    self.data.as_slice().slice(self.rows * *index, self.rows * *index + self.cols)
  }
}

impl Matrix {
  #[inline(always)]
  pub fn num_rows(&self) -> uint{
    self.rows
  }

  #[inline(always)]
  pub fn num_cols(&self) -> uint {
    self.cols
  }

  #[inline(always)]
  pub fn get(&self, i: uint, j: uint) -> f64 {
    if i < self.num_rows() && j < self.num_cols() {
      self.data[i * self.num_cols() + j]
    } else {
      panic!(format!("Matrix index {} out of bounds.", (i, j)))
    }
  }

  #[inline(always)]
  pub fn set(&mut self, i: uint, j: uint, num: f64) {
    if i < self.num_rows() && j < self.num_cols() {
      self.data.as_mut_slice()[i * self.num_cols() + j] = num
    } else {
      panic!(format!("Matrix index {} out of bounds.", (i, j)))
    }
  }

  pub fn add(&self, m: Matrix) -> Matrix {
    if self.num_rows() == m.num_rows() && self.num_cols() == self.num_cols() {
      let mut new_mat = Matrix::new(self.num_rows(), self.num_cols(), 0.0);
      for i in range(0, self.num_rows()) {
        for j in range(0, self.num_cols()) {
          new_mat.set(i, j, self.get(i, j) + m.get(i, j));
        }
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for addition.")
    }
  }

  pub fn multiply(&self, m: Matrix) -> Matrix {
    if self.num_cols() == m.num_rows() {
      let mut new_mat = Matrix::new(self.num_rows(), m.num_cols(), 0.0);
      for i in range(0, self.num_rows()) {
        for j in range(0, m.num_cols()) {
          let mut sum: f64 = 0.0;
          for k in range(0, self.num_cols()) {
            sum += self.get(i, k) * m.get(k, j);
          }
          new_mat.set(i, j, sum);
        }
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for multiplication.")
    }
  }

  pub fn scalar_multiply(&mut self, m: f64) {
    for i in range(0, self.num_rows()) {
      for j in range(0, self.num_cols()) {
        let tmp: f64 = m * self.get(i, j);
        self.set(i, j, tmp);
      }
    }
  }

  pub fn new(rows: uint, cols: uint, default: f64) -> Matrix {
    Matrix {
      rows: rows,
      cols: cols,
      data: Vec::from_elem(rows * cols, default)
    }
  }

  pub fn from_elems(rows: uint, cols: uint, elems: &[f64]) -> Matrix {
    let mut m = Matrix {
      rows: rows,
      cols: cols,
      data: Vec::new()
    };
    m.data.push_all(elems);
    m
  }

  pub fn identity(n: uint) -> Matrix {
    let mut m = Matrix {
      rows: n,
      cols: n,
      data: Vec::from_elem(n * n, 0.0)
    };
    for i in range(0, n) {
      m.set(i, i, 1.0);
    }
    m
  }
}
<commit_msg>change compiler directive<commit_after>pub struct Matrix {
  rows: uint,
  cols: uint,
  data: Vec<f64>
}

impl Index<uint, [f64]> for Matrix {
  #[inline]
  fn index<'a>(&'a self, index: &uint) -> &'a [f64] {
    self.data.as_slice().slice(self.rows * *index, self.rows * *index + self.cols)
  }
}

impl Matrix {
  #[inline]
  pub fn num_rows(&self) -> uint{
    self.rows
  }

  #[inline]
  pub fn num_cols(&self) -> uint {
    self.cols
  }

  #[inline]
  pub fn get(&self, i: uint, j: uint) -> f64 {
    if i < self.num_rows() && j < self.num_cols() {
      self.data[i * self.num_cols() + j]
    } else {
      panic!(format!("Matrix index {} out of bounds.", (i, j)))
    }
  }

  #[inline]
  pub fn set(&mut self, i: uint, j: uint, num: f64) {
    if i < self.num_rows() && j < self.num_cols() {
      self.data.as_mut_slice()[i * self.num_cols() + j] = num
    } else {
      panic!(format!("Matrix index {} out of bounds.", (i, j)))
    }
  }

  pub fn add(&self, m: Matrix) -> Matrix {
    if self.num_rows() == m.num_rows() && self.num_cols() == self.num_cols() {
      let mut new_mat = Matrix::new(self.num_rows(), self.num_cols(), 0.0);
      for i in range(0, self.num_rows()) {
        for j in range(0, self.num_cols()) {
          new_mat.set(i, j, self.get(i, j) + m.get(i, j));
        }
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for addition.")
    }
  }

  pub fn multiply(&self, m: Matrix) -> Matrix {
    if self.num_cols() == m.num_rows() {
      let mut new_mat = Matrix::new(self.num_rows(), m.num_cols(), 0.0);
      for i in range(0, self.num_rows()) {
        for j in range(0, m.num_cols()) {
          let mut sum: f64 = 0.0;
          for k in range(0, self.num_cols()) {
            sum += self.get(i, k) * m.get(k, j);
          }
          new_mat.set(i, j, sum);
        }
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for multiplication.")
    }
  }

  pub fn scalar_multiply(&mut self, m: f64) {
    for i in range(0, self.num_rows()) {
      for j in range(0, self.num_cols()) {
        let tmp: f64 = m * self.get(i, j);
        self.set(i, j, tmp);
      }
    }
  }

  pub fn new(rows: uint, cols: uint, default: f64) -> Matrix {
    Matrix {
      rows: rows,
      cols: cols,
      data: Vec::from_elem(rows * cols, default)
    }
  }

  pub fn from_elems(rows: uint, cols: uint, elems: &[f64]) -> Matrix {
    let mut m = Matrix {
      rows: rows,
      cols: cols,
      data: Vec::new()
    };
    m.data.push_all(elems);
    m
  }

  pub fn identity(n: uint) -> Matrix {
    let mut m = Matrix {
      rows: n,
      cols: n,
      data: Vec::from_elem(n * n, 0.0)
    };
    for i in range(0, n) {
      m.set(i, i, 1.0);
    }
    m
  }
}
<|endoftext|>


<commit_before>use Itertools;

/// `MinMaxResult` is an enum returned by `minmax`. See `Itertools::minmax()` for
/// more detail.
#[derive(PartialEq, Debug)]
pub enum MinMaxResult<T> {
    /// Empty iterator
    NoElements,

    /// Iterator with one element, so the minimum and maximum are the same
    OneElement(T),

    /// More than one element in the iterator, the first element is not larger
    /// than the second
    MinMax(T, T)
}

impl<T: Clone> MinMaxResult<T> {
    /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option`
    /// has variant `None` if and only if the `MinMaxResult` has variant
    /// `NoElements`. Otherwise variant `Some(x, y)` is returned where `x <= y`.
    /// If `MinMaxResult` has variant `OneElement(x)`, performing this operation
    /// will make one clone of `x`.
    ///
    /// # Examples
    ///
    /// ```
    /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax};
    ///
    /// let r: MinMaxResult<i32> = NoElements;
    /// assert_eq!(r.into_option(), None);
    ///
    /// let r = OneElement(1);
    /// assert_eq!(r.into_option(), Some((1, 1)));
    ///
    /// let r = MinMax(1, 2);
    /// assert_eq!(r.into_option(), Some((1, 2)));
    /// ```
    pub fn into_option(self) -> Option<(T,T)> {
        match self {
            MinMaxResult::NoElements => None,
            MinMaxResult::OneElement(x) => Some((x.clone(), x)),
            MinMaxResult::MinMax(x, y) => Some((x, y))
        }
    }
}

/// Implementation guts for `minmax` and `minmax_by_key`.
pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F,
                               mut lt: L) -> MinMaxResult<I::Item>
    where I: Iterator,
          F: FnMut(&I::Item) -> K,
          L: FnMut(&I::Item, &I::Item, &K, &K) -> bool,
{
    let (mut min, mut max, mut min_key, mut max_key) = match it.next() {
        None => return MinMaxResult::NoElements,
        Some(x) => {
            match it.next() {
                None => return MinMaxResult::OneElement(x),
                Some(y) => {
                    let xk = key_for(&x);
                    let yk = key_for(&y);
                    if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)}
                }
            }
        }
    };

    loop {
        // `first` and `second` are the two next elements we want to look
        // at.  We first compare `first` and `second` (#1). The smaller one
        // is then compared to current minimum (#2). The larger one is
        // compared to current maximum (#3). This way we do 3 comparisons
        // for 2 elements.
        let first = match it.next() {
            None => break,
            Some(x) => x
        };
        let second = match it.next() {
            None => {
                let first_key = key_for(&first);
                if lt(&first, &min, &first_key, &min_key) {
                    min = first;
                } else if !lt(&first, &max, &first_key, &max_key) {
                    max = first;
                }
                break;
            }
            Some(x) => x
        };
        let first_key = key_for(&first);
        let second_key = key_for(&second);
        if !lt(&second, &first, &second_key, &first_key) {
            if lt(&first, &min, &first_key, &min_key) {
                min = first;
                min_key = first_key;
            }
            if !lt(&second, &max, &second_key, &max_key) {
                max = second;
                max_key = second_key;
            }
        } else {
            if lt(&second, &min, &second_key, &min_key) {
                min = second;
                min_key = second_key;
            }
            if !lt(&first, &max, &first_key, &max_key) {
                max = first;
                max_key = first_key;
            }
        }
    }

    MinMaxResult::MinMax(min, max)
}
<commit_msg>minmax: Fix warning<commit_after>
/// `MinMaxResult` is an enum returned by `minmax`. See `Itertools::minmax()` for
/// more detail.
#[derive(PartialEq, Debug)]
pub enum MinMaxResult<T> {
    /// Empty iterator
    NoElements,

    /// Iterator with one element, so the minimum and maximum are the same
    OneElement(T),

    /// More than one element in the iterator, the first element is not larger
    /// than the second
    MinMax(T, T)
}

impl<T: Clone> MinMaxResult<T> {
    /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option`
    /// has variant `None` if and only if the `MinMaxResult` has variant
    /// `NoElements`. Otherwise variant `Some(x, y)` is returned where `x <= y`.
    /// If `MinMaxResult` has variant `OneElement(x)`, performing this operation
    /// will make one clone of `x`.
    ///
    /// # Examples
    ///
    /// ```
    /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax};
    ///
    /// let r: MinMaxResult<i32> = NoElements;
    /// assert_eq!(r.into_option(), None);
    ///
    /// let r = OneElement(1);
    /// assert_eq!(r.into_option(), Some((1, 1)));
    ///
    /// let r = MinMax(1, 2);
    /// assert_eq!(r.into_option(), Some((1, 2)));
    /// ```
    pub fn into_option(self) -> Option<(T,T)> {
        match self {
            MinMaxResult::NoElements => None,
            MinMaxResult::OneElement(x) => Some((x.clone(), x)),
            MinMaxResult::MinMax(x, y) => Some((x, y))
        }
    }
}

/// Implementation guts for `minmax` and `minmax_by_key`.
pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F,
                               mut lt: L) -> MinMaxResult<I::Item>
    where I: Iterator,
          F: FnMut(&I::Item) -> K,
          L: FnMut(&I::Item, &I::Item, &K, &K) -> bool,
{
    let (mut min, mut max, mut min_key, mut max_key) = match it.next() {
        None => return MinMaxResult::NoElements,
        Some(x) => {
            match it.next() {
                None => return MinMaxResult::OneElement(x),
                Some(y) => {
                    let xk = key_for(&x);
                    let yk = key_for(&y);
                    if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)}
                }
            }
        }
    };

    loop {
        // `first` and `second` are the two next elements we want to look
        // at.  We first compare `first` and `second` (#1). The smaller one
        // is then compared to current minimum (#2). The larger one is
        // compared to current maximum (#3). This way we do 3 comparisons
        // for 2 elements.
        let first = match it.next() {
            None => break,
            Some(x) => x
        };
        let second = match it.next() {
            None => {
                let first_key = key_for(&first);
                if lt(&first, &min, &first_key, &min_key) {
                    min = first;
                } else if !lt(&first, &max, &first_key, &max_key) {
                    max = first;
                }
                break;
            }
            Some(x) => x
        };
        let first_key = key_for(&first);
        let second_key = key_for(&second);
        if !lt(&second, &first, &second_key, &first_key) {
            if lt(&first, &min, &first_key, &min_key) {
                min = first;
                min_key = first_key;
            }
            if !lt(&second, &max, &second_key, &max_key) {
                max = second;
                max_key = second_key;
            }
        } else {
            if lt(&second, &min, &second_key, &min_key) {
                min = second;
                min_key = second_key;
            }
            if !lt(&first, &max, &first_key, &max_key) {
                max = first;
                max_key = first_key;
            }
        }
    }

    MinMaxResult::MinMax(min, max)
}
<|endoftext|>


<commit_before>use std::io;
use std::result;

use byteorder::{BigEndian, WriteBytesExt};

use constants::*;
use job::*;

pub struct PacketType {
    pub name: &'static str,
    pub ptype: u32,
    pub nargs: i8,
}

#[derive(PartialEq)]
pub enum PacketMagic {
    UNKNOWN,
    REQ,
    RES,
}

pub struct Packet {
    pub magic: PacketMagic,
    pub ptype: u32,
    pub psize: u32,
    pub data: Box<Vec<u8>>,
    _field_byte_count: usize,
    _field_count: i8,
}

const READ_BUFFER_INIT_CAPACITY: usize = 2048;

impl Iterator for Packet {
    type Item = (usize, usize);
    fn next(&mut self) -> Option<(usize, usize)> {
        let nargs = PTYPES[self.ptype as usize].nargs;
        if self._field_count >= nargs {
            return None
        }
        self._field_count += 1;
        if self._field_count == nargs {
            return Some((self._field_byte_count, self.data.len()))
        };
        let start = self._field_byte_count;
        for byte in &self.data[start..] {
            self._field_byte_count += 1;
            if *byte == '\0' as u8 {
                break
            }
        };
        Some((start, self._field_byte_count))
    }
}

pub struct ParseError {}

pub type Result<T> = result::Result<T, ParseError>;

impl Packet {
    pub fn new() -> Packet {
        Packet {
            magic: PacketMagic::UNKNOWN,
            ptype: 0,
            psize: 0,
            data: Box::new(Vec::with_capacity(READ_BUFFER_INIT_CAPACITY)),
            _field_byte_count: 0,
            _field_count: 0,
        }
    }

    pub fn process(&mut self) -> Result<Option<Packet>> {
        match self.ptype {
            SUBMIT_JOB => {
                match self.handleSubmitJob()? {
                    None => Ok(None),
                    Some(p) => {
                        println!("Should send a packet here {}",
                                 PTYPES[p.ptype as usize].name);
                        Ok(None)
                    }
                }
            },
            _ => {
                println!("Unimplemented: processing packet");
                Ok(None)
            },
        }
    }

    fn nextField(&mut self) -> Result<Vec<u8>> {
        let (start, finish) = match self.next() {
            None => return Err(ParseError{}),
            Some((start, finish)) => (start, finish),
        };
        let mut r = Vec::with_capacity(finish - start);
        r.clone_from_slice(&self.data[start..finish]);
        Ok(r)
    }

    fn handleSubmitJob(&mut self) -> Result<Option<Packet>> {
        let fname = self.nextField()?;
        let unique = self.nextField()?;
        let data = self.nextField()?;
        let j = Job {
            fname: fname,
            unique: unique,
            data: data,
        };
        Ok(None)
    }

    pub fn to_byteslice(&self) -> Box<[u8]> {
        let len = 12 + self.psize;
        let mut buf = Vec::with_capacity(len as usize) as Vec<u8>;
        let magic = match self.magic {
            PacketMagic::UNKNOWN => panic!("Unknown packet magic cannot be sent"),
            PacketMagic::REQ => REQ,
            PacketMagic::RES => RES,
        };
        buf.extend(magic.iter());
        buf.write_u32::<BigEndian>(self.ptype);
        buf.write_u32::<BigEndian>(self.psize);
        buf.extend(self.data.iter());
        buf.into_boxed_slice()
    }
}

pub static PTYPES: [PacketType; 43] = [
    PacketType { name: "__UNUSED__", ptype: 0, nargs: -1 },
    PacketType { name: "CAN_DO", ptype: 1, nargs: 0 },
    PacketType { name: "CANT_DO", ptype: 2, nargs: 0 },
    PacketType { name: "RESET_ABILITIES", ptype: 3, nargs: -1 },
    PacketType { name: "PRE_SLEEP", ptype: 4, nargs: -1 },
    PacketType { name: "__UNUSED__", ptype: 5, nargs: -1 },
    PacketType { name: "NOOP", ptype: 6, nargs: -1 },
    PacketType { name: "SUBMIT_JOB", ptype: 7, nargs: 2 },
    PacketType { name: "JOB_CREATED", ptype: 8, nargs: 0 },
    PacketType { name: "GRAB_JOB", ptype: 9, nargs: -1 },
    PacketType { name: "NO_JOB", ptype: 10, nargs: -1 },
    PacketType { name: "JOB_ASSIGN", ptype: 11, nargs: 2 },
    PacketType { name: "WORK_STATUS", ptype: 12, nargs: 2 },
    PacketType { name: "WORK_COMPLETE", ptype: 13, nargs: 1 },
    PacketType { name: "WORK_FAIL", ptype: 14, nargs: 0 },
    PacketType { name: "GET_STATUS", ptype: 15, nargs: 0 },
    PacketType { name: "ECHO_REQ", ptype: 16, nargs: 0 },
    PacketType { name: "ECHO_RES", ptype: 17, nargs: 1 },
    PacketType { name: "SUBMIT_JOB_BG", ptype: 18, nargs: 2 },
    PacketType { name: "ERROR", ptype: 19, nargs: 1 },
    PacketType { name: "STATUS_RES", ptype: 20, nargs: 4 },
    PacketType { name: "SUBMIT_JOB_HIGH", ptype: 21, nargs: 2 },
    PacketType { name: "SET_CLIENT_ID", ptype: 22, nargs: 0 },
    PacketType { name: "CAN_DO_TIMEOUT", ptype: 23, nargs: 1 },
    PacketType { name: "ALL_YOURS", ptype: 24, nargs: -1 },
    PacketType { name: "WORK_EXCEPTION", ptype: 25, nargs: 1 },
    PacketType { name: "OPTION_REQ", ptype: 26, nargs: 0 },
    PacketType { name: "OPTION_RES", ptype: 27, nargs: 0 },
    PacketType { name: "WORK_DATA", ptype: 28, nargs: 1 },
    PacketType { name: "WORK_WARNING", ptype: 29, nargs: 1 },
    PacketType { name: "GRAB_JOB_UNIQ", ptype: 30, nargs: -1 },
    PacketType { name: "JOB_ASSIGN_UNIQ", ptype: 31, nargs: 3 },
    PacketType { name: "SUBMIT_JOB_HIGH_BG", ptype: 32, nargs: 2 },
    PacketType { name: "SUBMIT_JOB_LOW", ptype: 33, nargs: 2 },
    PacketType { name: "SUBMIT_JOB_LOW_BG", ptype: 34, nargs: 2 },
    PacketType { name: "SUBMIT_JOB_SCHED", ptype: 35, nargs: 7 },
    PacketType { name: "SUBMIT_JOB_EPOCH", ptype: 36, nargs: 3 },
    PacketType { name: "SUBMIT_REDUCE_JOB", ptype: 37, nargs: 3 },
    PacketType { name: "SUBMIT_REDUCE_JOB_BACKGROUND", ptype: 38, nargs: 3 },
    PacketType { name: "GRAB_JOB_ALL", ptype: 39, nargs: -1 },
    PacketType { name: "JOB_ASSIGN_ALL", ptype: 40, nargs: 4 },
    PacketType { name: "GET_STATUS_UNIQUE", ptype: 41, nargs: 0 },
    PacketType { name: "STATUS_RES_UNIQUE", ptype: 42, nargs: 5 },
];
<commit_msg>Fixing nargs off by one<commit_after>use std::io;
use std::result;

use byteorder::{BigEndian, WriteBytesExt};

use constants::*;
use job::*;

pub struct PacketType {
    pub name: &'static str,
    pub ptype: u32,
    pub nargs: i8,
}

#[derive(PartialEq)]
pub enum PacketMagic {
    UNKNOWN,
    REQ,
    RES,
}

pub struct Packet {
    pub magic: PacketMagic,
    pub ptype: u32,
    pub psize: u32,
    pub data: Box<Vec<u8>>,
    _field_byte_count: usize,
    _field_count: i8,
}

const READ_BUFFER_INIT_CAPACITY: usize = 2048;

impl Iterator for Packet {
    type Item = (usize, usize);
    fn next(&mut self) -> Option<(usize, usize)> {
        let nargs = PTYPES[self.ptype as usize].nargs;
        if self._field_count > nargs {
            return None
        }
        self._field_count += 1;
        println!("DEBUG: returning field #{}", self._field_count);
        if self._field_count == nargs {
            return Some((self._field_byte_count, self.data.len()))
        };
        let start = self._field_byte_count;
        for byte in &self.data[start..] {
            self._field_byte_count += 1;
            if *byte == '\0' as u8 {
                break
            }
        };
        Some((start, self._field_byte_count))
    }
}

pub struct ParseError {}

pub type Result<T> = result::Result<T, ParseError>;

impl Packet {
    pub fn new() -> Packet {
        Packet {
            magic: PacketMagic::UNKNOWN,
            ptype: 0,
            psize: 0,
            data: Box::new(Vec::with_capacity(READ_BUFFER_INIT_CAPACITY)),
            _field_byte_count: 0,
            _field_count: 0,
        }
    }

    pub fn process(&mut self) -> Result<Option<Packet>> {
        match self.ptype {
            SUBMIT_JOB => {
                match self.handleSubmitJob()? {
                    None => Ok(None),
                    Some(p) => {
                        println!("Should send a packet here {}",
                                 PTYPES[p.ptype as usize].name);
                        Ok(None)
                    }
                }
            },
            _ => {
                println!("Unimplemented: processing packet");
                Ok(None)
            },
        }
    }

    fn nextField(&mut self) -> Result<Vec<u8>> {
        let (start, finish) = match self.next() {
            None => return Err(ParseError{}),
            Some((start, finish)) => (start, finish),
        };
        let mut r = Vec::with_capacity(finish - start);
        let new_size = r.capacity();
        r.resize(new_size, 0);
        r.clone_from_slice(&self.data[start..finish]);
        Ok(r)
    }

    fn handleSubmitJob(&mut self) -> Result<Option<Packet>> {
        let fname = self.nextField()?;
        let unique = self.nextField()?;
        let data = self.nextField()?;
        let j = Job {
            fname: fname,
            unique: unique,
            data: data,
        };
        Ok(None)
    }

    pub fn to_byteslice(&self) -> Box<[u8]> {
        let len = 12 + self.psize;
        let mut buf = Vec::with_capacity(len as usize) as Vec<u8>;
        let magic = match self.magic {
            PacketMagic::UNKNOWN => panic!("Unknown packet magic cannot be sent"),
            PacketMagic::REQ => REQ,
            PacketMagic::RES => RES,
        };
        buf.extend(magic.iter());
        buf.write_u32::<BigEndian>(self.ptype);
        buf.write_u32::<BigEndian>(self.psize);
        buf.extend(self.data.iter());
        buf.into_boxed_slice()
    }
}

pub static PTYPES: [PacketType; 43] = [
    PacketType { name: "__UNUSED__", ptype: 0, nargs: -1 },
    PacketType { name: "CAN_DO", ptype: 1, nargs: 0 },
    PacketType { name: "CANT_DO", ptype: 2, nargs: 0 },
    PacketType { name: "RESET_ABILITIES", ptype: 3, nargs: -1 },
    PacketType { name: "PRE_SLEEP", ptype: 4, nargs: -1 },
    PacketType { name: "__UNUSED__", ptype: 5, nargs: -1 },
    PacketType { name: "NOOP", ptype: 6, nargs: -1 },
    PacketType { name: "SUBMIT_JOB", ptype: 7, nargs: 2 },
    PacketType { name: "JOB_CREATED", ptype: 8, nargs: 0 },
    PacketType { name: "GRAB_JOB", ptype: 9, nargs: -1 },
    PacketType { name: "NO_JOB", ptype: 10, nargs: -1 },
    PacketType { name: "JOB_ASSIGN", ptype: 11, nargs: 2 },
    PacketType { name: "WORK_STATUS", ptype: 12, nargs: 2 },
    PacketType { name: "WORK_COMPLETE", ptype: 13, nargs: 1 },
    PacketType { name: "WORK_FAIL", ptype: 14, nargs: 0 },
    PacketType { name: "GET_STATUS", ptype: 15, nargs: 0 },
    PacketType { name: "ECHO_REQ", ptype: 16, nargs: 0 },
    PacketType { name: "ECHO_RES", ptype: 17, nargs: 1 },
    PacketType { name: "SUBMIT_JOB_BG", ptype: 18, nargs: 2 },
    PacketType { name: "ERROR", ptype: 19, nargs: 1 },
    PacketType { name: "STATUS_RES", ptype: 20, nargs: 4 },
    PacketType { name: "SUBMIT_JOB_HIGH", ptype: 21, nargs: 2 },
    PacketType { name: "SET_CLIENT_ID", ptype: 22, nargs: 0 },
    PacketType { name: "CAN_DO_TIMEOUT", ptype: 23, nargs: 1 },
    PacketType { name: "ALL_YOURS", ptype: 24, nargs: -1 },
    PacketType { name: "WORK_EXCEPTION", ptype: 25, nargs: 1 },
    PacketType { name: "OPTION_REQ", ptype: 26, nargs: 0 },
    PacketType { name: "OPTION_RES", ptype: 27, nargs: 0 },
    PacketType { name: "WORK_DATA", ptype: 28, nargs: 1 },
    PacketType { name: "WORK_WARNING", ptype: 29, nargs: 1 },
    PacketType { name: "GRAB_JOB_UNIQ", ptype: 30, nargs: -1 },
    PacketType { name: "JOB_ASSIGN_UNIQ", ptype: 31, nargs: 3 },
    PacketType { name: "SUBMIT_JOB_HIGH_BG", ptype: 32, nargs: 2 },
    PacketType { name: "SUBMIT_JOB_LOW", ptype: 33, nargs: 2 },
    PacketType { name: "SUBMIT_JOB_LOW_BG", ptype: 34, nargs: 2 },
    PacketType { name: "SUBMIT_JOB_SCHED", ptype: 35, nargs: 7 },
    PacketType { name: "SUBMIT_JOB_EPOCH", ptype: 36, nargs: 3 },
    PacketType { name: "SUBMIT_REDUCE_JOB", ptype: 37, nargs: 3 },
    PacketType { name: "SUBMIT_REDUCE_JOB_BACKGROUND", ptype: 38, nargs: 3 },
    PacketType { name: "GRAB_JOB_ALL", ptype: 39, nargs: -1 },
    PacketType { name: "JOB_ASSIGN_ALL", ptype: 40, nargs: 4 },
    PacketType { name: "GET_STATUS_UNIQUE", ptype: 41, nargs: 0 },
    PacketType { name: "STATUS_RES_UNIQUE", ptype: 42, nargs: 5 },
];
<|endoftext|>


<commit_before>
use ast::ExprAst;
use ast::BoolNode;
use ast::CharNode;
use ast::IntNode;
use ast::StrNode;
use ast::Ast;

#[deriving(Clone, Show)]
pub struct Parser {
    code: String,
    cur: uint,
    col: uint,
    line: uint
}

#[allow(dead_code)]
pub struct ParserError {
    line: uint,
    col: uint,
    desc: String
}

#[allow(dead_code)]
impl ParserError {
    pub fn new(line: uint, col: uint, desc: String) -> ParserError {
        ParserError {
            line: line,
            col: col,
            desc: desc
        }
    }
}

#[allow(dead_code)]
pub type ParseResult<T> = Result<T, ParserError>;

#[allow(dead_code)]
impl Parser {
    pub fn new() -> Parser {
        Parser{
            code: "".to_string(),
            line: 0,
            cur: 0,
            col: 0
        }
    }

    pub fn load(&mut self, code: String) -> ExprAst {
        self.code = code;
        self.line = 1;
        self.cur = 0;
        self.col = 0;
        self.skip_space();

        let mut cur = self.readc();
        if cur == '#' {
            let next = self.readc();
            match next {
                't' => return ExprAst::Bool(BoolNode::new(true)),
                'f' => return ExprAst::Bool(BoolNode::new(false)),
                '\\' => return self.read_char(),
                _ => panic!("error")
            }
        } else if UnicodeChar::is_numeric(cur) ||
            (cur == '-' && (UnicodeChar::is_numeric(self.peekc()))) {
                let mut sign = 1i;
                let mut num = 0i;
                if cur == '-' {
                    sign = -1;
                } else {
                    self.unread();
                }
                loop {
                    cur = self.readc();
                    if !UnicodeChar::is_numeric(cur) {
                        break;
                    }
                    num = (num * 10i) + (cur as int - '0' as int);
                }
                num *= sign;
                if self.is_delimiter(cur) {
                    self.unread();
                    return ExprAst::Int(IntNode::new(num));
                } else {
                    panic!("number not followed by delimiter");
                }
            } else if cur == '\"' {
                let mut buf = String::new();
                loop {
                    cur = self.readc();
                    if cur == '\"' {
                        break;
                    }
                    buf.push(cur);
                }
                return ExprAst::Str(StrNode::new(buf));
            }
        ExprAst::Char(CharNode::new('a'))
    }

    //============= private methods =================
    fn is_delimiter(&self, ch: char) -> bool {
        ch.is_whitespace() ||
            ch == '\"' || ch == '(' || ch == ')' ||  ch == ';' ||
            (ch as u32 == 0)
    }

    fn is_initial(&self, ch: char) -> bool {
        ch.is_alphabetic() ||
            ch == '*' || ch == '/' || ch == '+' || ch == '-' ||
            ch == '>' || ch == '<' || ch == '=' || ch == '?' ||
            ch == '!'
    }

    fn skip_space(&mut self) {
        while self.peekc().is_whitespace() {
            self.readc();
        }
    }

    fn peekc(&self) -> char {
        if self.cur >= self.code.len() {
            panic!("invalid position");
        }
        self.code.char_at(self.cur)
    }

    fn prevc(&self) -> char {
        if self.cur <= 0 {
            panic!("invalid position");
        }
        self.code.char_at(self.cur - 1)
    }

    fn readc(&mut self) -> char {
        if self.cur < self.code.len() {
            let res = self.peekc();
            if res == '\n' {
                self.line += 1;
            }
            self.cur += 1;
            res
        } else {
            0 as char
        }
    }

    fn unread(&mut self) {
        if self.cur == 0 {
            panic!("error current position");
        }
        if self.prevc() == '\n' {
            assert!(self.line > 1);
            self.line -= 1;
        }
        self.cur -= 1;
    }

    fn read_char(&mut self) -> ExprAst {
        ExprAst::Char(CharNode::new('a'))
    }

}

#[test]
fn test_parser() {
    let mut parser = Parser::new();
    let res = parser.load("11".to_string());
    assert!(res.as_int() == 11);
    res.print();
}
<commit_msg>more test<commit_after>
use ast::ExprAst;
use ast::BoolNode;
use ast::CharNode;
use ast::IntNode;
use ast::StrNode;
use ast::Ast;

#[deriving(Clone, Show)]
pub struct Parser {
    code: String,
    cur: uint,
    col: uint,
    line: uint
}

#[allow(dead_code)]
pub struct ParserError {
    line: uint,
    col: uint,
    desc: String
}

#[allow(dead_code)]
impl ParserError {
    pub fn new(line: uint, col: uint, desc: String) -> ParserError {
        ParserError {
            line: line,
            col: col,
            desc: desc
        }
    }
}

#[allow(dead_code)]
pub type ParseResult<T> = Result<T, ParserError>;

#[allow(dead_code)]
impl Parser {
    pub fn new() -> Parser {
        Parser{
            code: "".to_string(),
            line: 0,
            cur: 0,
            col: 0
        }
    }

    pub fn load(&mut self, code: String) -> ExprAst {
        self.code = code;
        self.line = 1;
        self.cur = 0;
        self.col = 0;
        self.skip_space();

        let mut cur = self.readc();
        if cur == '#' {
            let next = self.readc();
            match next {
                't' => return ExprAst::Bool(BoolNode::new(true)),
                'f' => return ExprAst::Bool(BoolNode::new(false)),
                '\\' => return self.read_char(),
                _ => panic!("error")
            }
        } else if UnicodeChar::is_numeric(cur) ||
            (cur == '-' && (UnicodeChar::is_numeric(self.peekc()))) {
                let mut sign = 1i;
                let mut num = 0i;
                if cur == '-' {
                    sign = -1;
                } else {
                    self.unread();
                }
                loop {
                    cur = self.readc();
                    if !UnicodeChar::is_numeric(cur) {
                        break;
                    }
                    num = (num * 10i) + (cur as int - '0' as int);
                }
                num *= sign;
                if self.is_delimiter(cur) {
                    self.unread();
                    return ExprAst::Int(IntNode::new(num));
                } else {
                    panic!("number not followed by delimiter");
                }
            } else if cur == '\"' {
                let mut buf = String::new();
                loop {
                    cur = self.readc();
                    if cur == '\"' {
                        break;
                    }
                    buf.push(cur);
                }
                return ExprAst::Str(StrNode::new(buf));
            }
        ExprAst::Char(CharNode::new('a'))
    }

    //============= private methods =================
    fn is_delimiter(&self, ch: char) -> bool {
        ch.is_whitespace() ||
            ch == '\"' || ch == '(' || ch == ')' ||  ch == ';' ||
            (ch as u32 == 0)
    }

    fn is_initial(&self, ch: char) -> bool {
        ch.is_alphabetic() ||
            ch == '*' || ch == '/' || ch == '+' || ch == '-' ||
            ch == '>' || ch == '<' || ch == '=' || ch == '?' ||
            ch == '!'
    }

    fn skip_space(&mut self) {
        while self.peekc().is_whitespace() {
            self.readc();
        }
    }

    fn peekc(&self) -> char {
        if self.cur >= self.code.len() {
            panic!("invalid position");
        }
        self.code.char_at(self.cur)
    }

    fn prevc(&self) -> char {
        if self.cur <= 0 {
            panic!("invalid position");
        }
        self.code.char_at(self.cur - 1)
    }

    fn readc(&mut self) -> char {
        if self.cur < self.code.len() {
            let res = self.peekc();
            if res == '\n' {
                self.line += 1;
            }
            self.cur += 1;
            res
        } else {
            0 as char
        }
    }

    fn unread(&mut self) {
        if self.cur == 0 {
            panic!("error current position");
        }
        if self.prevc() == '\n' {
            assert!(self.line > 1);
            self.line -= 1;
        }
        self.cur -= 1;
    }

    fn read_char(&mut self) -> ExprAst {
        ExprAst::Char(CharNode::new('a'))
    }
}

#[test]
fn test_parser() {
    let mut parser = Parser::new();
    let res = parser.load("11".to_string());
    assert!(res.as_int() == 11);
    res.print();

    let res = parser.load("-11".to_string());
    assert!(res.as_int() == -11);
    res.print();
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use dictionary::Dictionary;
use word::Word;
use branch::Branch;
use state::InterpState;

/// Takes a chars iterator and returns all characters up to the next whitespace,
/// excluding the whitespace character. Returns `None` the `chars` iterator is
/// exhausted.
pub fn next_word<T: Iterator<Item = char>>(chars: &mut T) -> Option<String> {
    let mut word = String::new();

    while let Some(c) = chars.next() {
        if c == ' ' || c == '\n' {
            if word.is_empty() {
                continue;
            }
            break;
        }
        word.push(c);
    }

    if word.is_empty() {
        // No input left
        None
    } else {
        Some(word)
    }
}

pub fn parse_word<T: Iterator<Item = char>>(word_str: &str,
                                            chars: &mut T,
                                            dict: &mut Dictionary,
                                            state: &mut InterpState)
                                            -> Option<Branch> {
    if let Some(word) = dict.get(word_str) {
        match word {
            Word::Custom(x) => Some(Branch::Custom(x)),
            Word::Builtin(x) => Some(Branch::Builtin(x)),
            Word::Int(x) => Some(Branch::Int(x)),
            Word::Float(x) => Some(Branch::Float(x)),
            Word::Dotquote => {
                let text = chars.take_while(|x| *x != '"').collect();
                Some(Branch::Dotquote(text))
            }
            Word::Paren => {
                // Consumes all characters up to next )
                chars.take_while(|x| *x != ')').count();
                None
            }
            Word::Colon => {
                let name = next_word(chars).unwrap();
                let mut inner_branches: Vec<Branch> = Vec::new();
                while let Some(inner_word_str) = next_word(chars) {
                    if dict.get(&inner_word_str) == Some(Word::Semicolon) {
                        break;
                    }
                    if let Some(branch) = parse_word(&inner_word_str, chars, dict, state) {
                        inner_branches.push(branch);
                    }
                }
                dict.set(&name, Word::Custom(Rc::new(inner_branches)));
                None
            }
            Word::If => {
                let mut ifbranches = Vec::new();
                let mut elsebranches = Vec::new();
                let mut inelse = false;
                while let Some(inner_word_str) = next_word(chars) {
                    match dict.get(&inner_word_str) {
                        Some(Word::Else) => inelse = true,
                        Some(Word::Then) => break,
                        _ => {}
                    }
                    if let Some(branch) = parse_word(&inner_word_str, chars, dict, state) {
                        if inelse {
                            elsebranches.push(branch);
                        } else {
                            ifbranches.push(branch);
                        }
                    }
                }
                Some(Branch::IfElse(ifbranches, elsebranches))
            }
            Word::Variable => {
                let name = next_word(chars).unwrap();
                let addr = state.memory.new(0);
                dict.set(&name, Word::Int(addr));
                None
            }
            Word::Create => {
                let name = next_word(chars).unwrap();
                let addr = state.memory.here() + 1;
                dict.set(&name, Word::Int(addr));
                None
            }
            Word::Semicolon | Word::Else | Word::Then => {
                panic!("Invalid here");
            }
        }
    } else {
        panic!("Word '{}' not in dictionary.", word_str);
    }
}

pub fn parse<T: Iterator<Item = char>>(code: &mut T,
                                       dict: &mut Dictionary,
                                       state: &mut InterpState)
                                       -> Vec<Branch> {
    let mut branches: Vec<Branch> = Vec::new();
    while let Some(word_str) = next_word(code) {
        if let Some(branch) = parse_word(&word_str, code, dict, state) {
            branches.push(branch);
        }
    }

    branches
}
<commit_msg>Use iterator methods to implement next_word<commit_after>use std::rc::Rc;
use dictionary::Dictionary;
use word::Word;
use branch::Branch;
use state::InterpState;

/// Takes a chars iterator and returns all characters up to the next whitespace,
/// excluding the whitespace character. Returns `None` the `chars` iterator is
/// exhausted.
pub fn next_word<T: Iterator<Item = char>>(chars: &mut T) -> Option<String> {
    let word = chars.skip_while(|x| x.is_whitespace())
        .take_while(|x| !x.is_whitespace())
        .collect::<String>();

    if word.is_empty() {
        // No input left
        None
    } else {
        Some(word)
    }
}

pub fn parse_word<T: Iterator<Item = char>>(word_str: &str,
                                            chars: &mut T,
                                            dict: &mut Dictionary,
                                            state: &mut InterpState)
                                            -> Option<Branch> {
    if let Some(word) = dict.get(word_str) {
        match word {
            Word::Custom(x) => Some(Branch::Custom(x)),
            Word::Builtin(x) => Some(Branch::Builtin(x)),
            Word::Int(x) => Some(Branch::Int(x)),
            Word::Float(x) => Some(Branch::Float(x)),
            Word::Dotquote => {
                let text = chars.take_while(|x| *x != '"').collect();
                Some(Branch::Dotquote(text))
            }
            Word::Paren => {
                // Consumes all characters up to next )
                chars.take_while(|x| *x != ')').count();
                None
            }
            Word::Colon => {
                let name = next_word(chars).unwrap();
                let mut inner_branches: Vec<Branch> = Vec::new();
                while let Some(inner_word_str) = next_word(chars) {
                    if dict.get(&inner_word_str) == Some(Word::Semicolon) {
                        break;
                    }
                    if let Some(branch) = parse_word(&inner_word_str, chars, dict, state) {
                        inner_branches.push(branch);
                    }
                }
                dict.set(&name, Word::Custom(Rc::new(inner_branches)));
                None
            }
            Word::If => {
                let mut ifbranches = Vec::new();
                let mut elsebranches = Vec::new();
                let mut inelse = false;
                while let Some(inner_word_str) = next_word(chars) {
                    match dict.get(&inner_word_str) {
                        Some(Word::Else) => inelse = true,
                        Some(Word::Then) => break,
                        _ => {}
                    }
                    if let Some(branch) = parse_word(&inner_word_str, chars, dict, state) {
                        if inelse {
                            elsebranches.push(branch);
                        } else {
                            ifbranches.push(branch);
                        }
                    }
                }
                Some(Branch::IfElse(ifbranches, elsebranches))
            }
            Word::Variable => {
                let name = next_word(chars).unwrap();
                let addr = state.memory.new(0);
                dict.set(&name, Word::Int(addr));
                None
            }
            Word::Create => {
                let name = next_word(chars).unwrap();
                let addr = state.memory.here() + 1;
                dict.set(&name, Word::Int(addr));
                None
            }
            Word::Semicolon | Word::Else | Word::Then => {
                panic!("Invalid here");
            }
        }
    } else {
        panic!("Word '{}' not in dictionary.", word_str);
    }
}

pub fn parse<T: Iterator<Item = char>>(code: &mut T,
                                       dict: &mut Dictionary,
                                       state: &mut InterpState)
                                       -> Vec<Branch> {
    let mut branches: Vec<Branch> = Vec::new();
    while let Some(word_str) = next_word(code) {
        if let Some(branch) = parse_word(&word_str, code, dict, state) {
            branches.push(branch);
        }
    }

    branches
}
<|endoftext|>


<commit_before>use syntax::parse::parser::Parser;
use syntax::parse::token;

use block::{Block, Describe, It, Bench};

pub fn parse(parser: &mut Parser) -> Describe {
    parse_describe("sup", parser)
}

pub fn parse_describe(name: &str, parser: &mut Parser) -> Describe {
    let brace = token::CloseDelim(token::Brace);

    let mut before = None;
    let mut after = None;
    let mut blocks = vec![];

    loop {
        if parser.token == brace || parser.token == token::Eof {
            break
        }

        let span = parser.span;
        let ident = parser.parse_ident();

        match ident.as_str() {
            "describe" | "context" => {
                let (name, _) = parser.parse_str();
                parser.expect(&token::OpenDelim(token::Brace));
                let block = Block::Describe(parse_describe(name.get(), parser));
                parser.expect(&token::CloseDelim(token::Brace));
                blocks.push(block);
            },

            "it" => {
                let (name, _) = parser.parse_str();
                let block = parser.parse_block();

                blocks.push(Block::It(It {
                    name: name.get().to_string(),
                    block: block
                }))
            },

            "bench" => {
                let (name, _) = parser.parse_str();
                parser.expect(&token::BinOp(token::Or));
                let ident = parser.parse_ident();
                parser.expect(&token::BinOp(token::Or));
                let block = parser.parse_block();

                blocks.push(Block::Bench(Bench {
                    name: name.get().to_string(),
                    ident: ident,
                    block: block
                }))
            },

            "before" => {
                before = Some(parser.parse_block());
            },

            "after" => {
                after = Some(parser.parse_block());
            },

            otherwise => {
                let message = format!("Expected \
`describe`, `context`, `before`, `after`, or `it`, found `{}`", otherwise);
                parser.span_fatal(span, message[])
            }
        }
    }

    Describe {
        name: name.to_string(),
        before: before,
        after: after,
        blocks: blocks
    }
}
<commit_msg>Ensure that the `it` etc. blocks end with a statement.<commit_after>use syntax::ast;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::ptr::P;

use block::{Block, Describe, It, Bench};

pub fn parse(parser: &mut Parser) -> Describe {
    parse_describe("sup", parser)
}

pub fn parse_describe(name: &str, parser: &mut Parser) -> Describe {
    let brace = token::CloseDelim(token::Brace);

    let mut before = None;
    let mut after = None;
    let mut blocks = vec![];

    loop {
        if parser.token == brace || parser.token == token::Eof {
            break
        }

        let span = parser.span;
        let ident = parser.parse_ident();

        match ident.as_str() {
            "describe" | "context" => {
                let (name, _) = parser.parse_str();
                parser.expect(&token::OpenDelim(token::Brace));
                let block = Block::Describe(parse_describe(name.get(), parser));
                parser.expect(&token::CloseDelim(token::Brace));
                blocks.push(block);
            },

            "it" => {
                let (name, _) = parser.parse_str();
                let block = parse_block(parser);

                blocks.push(Block::It(It {
                    name: name.get().to_string(),
                    block: block
                }))
            },

            "bench" => {
                let (name, _) = parser.parse_str();
                parser.expect(&token::BinOp(token::Or));
                let ident = parser.parse_ident();
                parser.expect(&token::BinOp(token::Or));
                let block = parse_block(parser);

                blocks.push(Block::Bench(Bench {
                    name: name.get().to_string(),
                    ident: ident,
                    block: block
                }))
            },

            "before" => {
                before = Some(parse_block(parser));
            },

            "after" => {
                after = Some(parse_block(parser));
            },

            otherwise => {
                let message = format!("Expected \
`describe`, `context`, `before`, `after`, or `it`, found `{}`", otherwise);
                parser.span_fatal(span, message[])
            }
        }
    }

    Describe {
        name: name.to_string(),
        before: before,
        after: after,
        blocks: blocks
    }
}

fn parse_block(parser: &mut Parser) -> P<ast::Block> {
    let span = parser.span;
    let block = parser.parse_block();
    if block.expr.is_some() {
        parser.span_fatal(
            span,
            "last expression in this block must be terminated by `;`")
    }
    block
}
<|endoftext|>


<commit_before>//! Responsavel pelo parsing e de gerar a AST do programa BIRL

#![allow(dead_code)]

/// Representa as keywords da linguagem
pub mod kw {
    // Definições
    /// Usada para declaração de globais
    pub const KW_GLOBAL: &'static str = "SAI DE CASA";
    /// Usada para definição de seções
    pub const KW_SECTION: &'static str = "JAULA";
    /// Usada para finalizar a definição de seções
    pub const KW_SECTEND: &'static str = "SAINDO DA JAULA";

    // Comandos
    /// Copia o valor de uma variavel a outra
    pub const KW_MOVE: &'static str = "BORA";
    /// Limpa o valor de uma variavel
    pub const KW_CLEAR: &'static str = "NUM VAI DA NAO";
    /// Xor (operador binário)
    pub const KW_XOR: &'static str = "TRAPEZIO DESCENDENTE";
    /// And (operador binário)
    pub const KW_AND: &'static str = "FIBRA";
    /// Or (operador binário)
    pub const KW_OR: &'static str = "TRAPEZIO";
    /// Adição
    pub const KW_ADD: &'static str = "CONSTROI";
    /// Diminuição
    pub const KW_REM: &'static str = "NEGATIVA";
    /// Divisão
    pub const KW_DIV: &'static str = "AGUA COM MUSCULO";
    /// Multiplicação
    pub const KW_MUL: &'static str = "CONSTROI FIBRA";
    /// Declara uma variável
    pub const KW_DECL: &'static str = "VEM";
    /// Declara uma variável com um valor
    pub const KW_DECLWV: &'static str = "VEM PORRA";
    /// Realiza um "pulo" de uma seção para outra
    pub const KW_JUMP: &'static str = "HORA DO";
    /// Comparação
    pub const KW_CMP: &'static str = "E ELE QUE A GENTE QUER";
}

/// Representa um valor que pode ser atribuido a uma variavel
pub enum Value {
    /// Numero inteiro de 64 bits
    Integer(i64),
    /// Numero de ponto flutuante de 64 bits
    FloatP(f64),
    /// Caractere UTF-8
    Char(char),
    /// Texto em UTF-8, guarda apenas a referencia ao valor no heap
    Str(Box<String>),
    /// Simbolo, que representa uma variavel no contexto do programa
    Symbol(String),
}

/// Sub-modulo responsavel por fazer parsing de expressões
mod value {

    use super::*;

    /// Tenta fazer parsing de uma expressão e retornar seu valor
    pub fn parse_expr(expr: &str) -> Option<Value> {
        let e = String::from(expr.trim());
        if e == "" {
            None
        } else {
            let fchar = e.chars().collect::<Vec<char>>()[0];
            match fchar {
                '0'...'9' => {}
                '\"' => {
                    // last_escape é se o ultimo caractere foi uma barra de escape, ignore ela
                    let (mut value, mut last_escape) = (String::new(), false);
                    let chars = e.chars().collect::<Vec<char>>();
                    for c in 1..chars.len() {
                        let actual = chars[c];
                        if actual == '\\' {
                            if last_escape {
                                value.push('\\');
                                last_escape = false;
                            } else {
                                last_escape = true;
                            }
                            continue;
                        }
                        if last_escape {
                            match actual {
                                'n' => value.push('\n'),
                                '\"' => value.push('\"'),
                                't' => value.push('\t'),
                                'r' => value.push('\r'),
                                '\'' => value.push('\''),
                                _ => {
                                    println!("Aviso: Sequencia de escape não reconhecida: \"{}\".",
                                             actual)
                                }
                            }
                            last_escape = false;
                            continue;
                        }
                        if actual == '\"' {
                            // Fim da string
                            return Some(Value::Str(Box::new(value)));
                        }
                        value.push(actual);
                    }
                }
                _ => println!("Erro, caractere \"{}\" encontrado durante parsing.", fchar),
            }
            None
        }
    }
}

/// Representa um comando, que é executado dentro do contexto atual
/// Os valores passados aos comandos têm nomes fantasia alfabéticos para exemplificação
pub enum Command {
    /// Move (copia) o conteudo da variavel no endereco a pro b
    Move(u64, u64),
    /// Limpa o valor da variavel no endereco a
    Clear(u64),
    /// Aplica xor na variavel no endereco a com o valor b
    Xor(u64, i64),
    /// Aplica and na variavel no endereco a com o valor b
    And(u64, i64),
    /// Aplica or  na variavel no endereco a com o valor b
    Or(u64, i64),
    /// Adiciona b ao valor da variavel no endereco a
    Add(u64, i64),
    /// Remove b do valor da variavel no endereco a
    Rem(u64, i64),
    /// Divide o valor da variavel no endereco a com o valor b
    Div(u64, i64),
    /// Multiplica o valor da variavel no endereco a com o valor b
    Mul(u64, i64),
    /// Declara a variavel com nome a
    Decl(String),
    /// Declara a variavel com nome a e valor b
    DeclWV(String, Value),
    /// Passa a execução para outra seção com nome a, retornando uma instrução à frente
    Jump(String),
    /// Compara os valores de a e b, usado em condicionais
    Cmp(u64, u64),
}

/// Procura pelo caractere c em src e retorna quantas vezes ele foi encontrado
fn n_of_char(c: char, src: &str) -> i32 {
    if src.len() <= 0 {
        0
    } else {
        let mut num = 0i32;
        for curr in src.chars() {
            if curr == c {
                num += 1;
            }
        }
        num
    }
}

/// Faz parsing de um comando
fn parse_cmd(cmd: &str) -> Option<Command> {
    // Estrutura de um comando:
    // COMANDO: var1, var2, ...
    let cmd = cmd.trim();
    let cmd_parts = cmd.split(':').collect::<Vec<&str>>();
    // Tipo/nome do comando
    let cmd_type = cmd_parts[0];
    let mut arguments: Vec<&str> = vec![];
    if n_of_char(',', cmd_parts[1]) == 0 {
        // Apenas um argumento
        arguments.push(cmd_parts[1].trim());
    } else {
        arguments = cmd_parts[1].split(',').collect::<Vec<&str>>();
    }
    match cmd_type {
        kw::KW_MOVE => {}
        kw::KW_CLEAR => {}
        kw::KW_XOR => {}
        kw::KW_AND => {}
        kw::KW_OR => {}
        kw::KW_ADD => {}
        kw::KW_REM => {}
        kw::KW_DIV => {}
        kw::KW_MUL => {}
        kw::KW_DECL => {}
        kw::KW_DECLWV => {}
        kw::KW_JUMP => {}
        kw::KW_CMP => {}
        _ => panic!("Erro: Tipo de comando \"{}\" não existe.", cmd_type),
    }
    None
}

/// Representa uma unidade (arquivo compilado) contendo o conteudo a ser executado
pub struct Unit {
    /// Conjunto de seções para execução
    sects: Vec<Section>,
    /// Conjunto de globais
    consts: Vec<Global>,
}

/// Realiza a interpretação de um arquivo e retorna sua unidade compilada
pub fn parse(file: &str) -> Unit {
    unimplemented!();
}

/// Representa uma área chamável que pode ser executada
pub struct Section {
    /// Nome da seção
    name: String,
    /// Conjunto de linhas/comandos para execução
    lines: Vec<Command>,
}

/// Faz parsing de uma seção
fn parse_section(sect_str: &str) -> Section {
    // Separa a seção em linhas
    let lines = sect_str.split('\n').collect::<Vec<&str>>();
    if lines.len() <= 1 {
        panic!("Erro fazendo parsing da seção. Número incorreto de linhas.")
    } else {
        // Checagens de declaração e finalização são feitas em parse
        // Declaração de uma seção:
        // PALAVRA_CHAVE nome
        if !lines[0].contains(' ') {
            panic!("Erro na declaração da seção! Falta nome depois da palavra chave");
        }
        let mut sect = Section {
            name: String::from(lines[0].split(' ').collect::<Vec<&str>>()[0]),
            lines: vec![],
        };
        for l in 1..lines.len() - 1 {
            let line = lines[l];
            sect.lines.push(parse_cmd(line).unwrap());
        }
        sect
    }
}

/// Representa um valor global, constante
pub struct Global {
    /// Identificador do valor global
    identifier: String,
    /// Valor do global
    value: Value,
}

/// Faz parsing de um global
fn parse_global(glb: &str) -> Global {
    // Estrutura da declaração de um global: PALAVRA_CHAVE: nome: valor
    let global = String::from(glb.trim());
    let words = global.split(':').collect::<Vec<&str>>();
    // Separa o nome e valor do global
    let (glb_name, glb_value) = (words[1].trim(), words[2].trim());
    let glb_value = match value::parse_expr(glb_value) {
        Some(val) => val,
        None => panic!(),
    };
    Global {
        identifier: String::from(glb_name),
        value: glb_value,
    }
}
<commit_msg>Palavras chave melhoradas e adicionado comando NEGATIVA<commit_after>//! Responsavel pelo parsing e de gerar a AST do programa BIRL

#![allow(dead_code)]

/// Representa as keywords da linguagem
pub mod kw {
    // Definições
    /// Usada para declaração de globais
    pub const KW_GLOBAL: &'static str = "SAI DE CASA";
    /// Usada para definição de seções
    pub const KW_SECTION: &'static str = "JAULA";
    /// Usada para finalizar a definição de seções
    pub const KW_SECTEND: &'static str = "SAINDO DA JAULA";

    // Comandos
    /// Copia o valor de uma variavel a outra
    pub const KW_MOVE: &'static str = "BORA";
    /// Limpa o valor de uma variavel
    pub const KW_CLEAR: &'static str = "NUM VAI DA NAO";
    /// Xor (operador binário)
    pub const KW_XOR: &'static str = "TRAPEZIO DESCENDENTE";
    /// And (operador binário)
    pub const KW_AND: &'static str = "FIBRA";
    /// Or (operador binário)
    pub const KW_OR: &'static str = "TRAPEZIO";
    /// Adição
    pub const KW_ADD: &'static str = "CONSTROI";
    /// Diminuição
    pub const KW_REM: &'static str = "MENOS CUMPADE";
    /// Divisão
    pub const KW_DIV: &'static str = "DIVIDE CUMPADE";
    /// Multiplicação
    pub const KW_MUL: &'static str = "CONSTROI FIBRA";
    /// Multiplica por -1
    pub const KW_NEG: &'static str = "NEGATIVA BAMBAM";
    /// Declara uma variável
    pub const KW_DECL: &'static str = "VEM";
    /// Declara uma variável com um valor
    pub const KW_DECLWV: &'static str = "VEM PORRA";
    /// Realiza um "pulo" de uma seção para outra
    pub const KW_JUMP: &'static str = "E HORA DO";
    /// Comparação
    pub const KW_CMP: &'static str = "E ELE QUE A GENTE QUER";
}

/// Representa um valor que pode ser atribuido a uma variavel
pub enum Value {
    /// Numero inteiro de 64 bits
    Integer(i64),
    /// Numero de ponto flutuante de 64 bits
    FloatP(f64),
    /// Caractere UTF-8
    Char(char),
    /// Texto em UTF-8, guarda apenas a referencia ao valor no heap
    Str(Box<String>),
    /// Simbolo, que representa uma variavel no contexto do programa
    Symbol(String),
}

/// Sub-modulo responsavel por fazer parsing de expressões
mod value {

    use super::*;

    /// Tenta fazer parsing de uma expressão e retornar seu valor
    pub fn parse_expr(expr: &str) -> Option<Value> {
        let e = String::from(expr.trim());
        if e == "" {
            None
        } else {
            let fchar = e.chars().collect::<Vec<char>>()[0];
            match fchar {
                '0'...'9' => {}
                '\"' => {
                    // last_escape é se o ultimo caractere foi uma barra de escape, ignore ela
                    let (mut value, mut last_escape) = (String::new(), false);
                    let chars = e.chars().collect::<Vec<char>>();
                    for c in 1..chars.len() {
                        let actual = chars[c];
                        if actual == '\\' {
                            if last_escape {
                                value.push('\\');
                                last_escape = false;
                            } else {
                                last_escape = true;
                            }
                            continue;
                        }
                        if last_escape {
                            match actual {
                                'n' => value.push('\n'),
                                '\"' => value.push('\"'),
                                't' => value.push('\t'),
                                'r' => value.push('\r'),
                                '\'' => value.push('\''),
                                _ => {
                                    println!("Aviso: Sequencia de escape não reconhecida: \"{}\".",
                                             actual)
                                }
                            }
                            last_escape = false;
                            continue;
                        }
                        if actual == '\"' {
                            // Fim da string
                            return Some(Value::Str(Box::new(value)));
                        }
                        value.push(actual);
                    }
                }
                'a' ... 'z' | 'A' ... 'Z' | '_' => {
                    return Some(Value::Symbol(e));
                }
                _ => println!("Erro, caractere \"{}\" encontrado durante parsing.", fchar),
            }
            None
        }
    }
}

/// Representa um comando, que é executado dentro do contexto atual
/// Os valores passados aos comandos têm nomes fantasia alfabéticos para exemplificação
pub enum Command {
    /// Move (copia) o conteudo da variavel no endereco a pro b
    Move(u64, u64),
    /// Limpa o valor da variavel no endereco a
    Clear(u64),
    /// Aplica xor na variavel no endereco a com o valor b
    Xor(u64, i64),
    /// Aplica and na variavel no endereco a com o valor b
    And(u64, i64),
    /// Aplica or  na variavel no endereco a com o valor b
    Or(u64, i64),
    /// Adiciona b ao valor da variavel no endereco a
    Add(u64, i64),
    /// Remove b do valor da variavel no endereco a
    Rem(u64, i64),
    /// Divide o valor da variavel no endereco a com o valor b
    Div(u64, i64),
    /// Multiplica o valor da variavel no endereco a com o valor b
    Mul(u64, i64),
    /// Multiplica um valor por -1
    Neg(u64),
    /// Declara a variavel com nome a
    Decl(String),
    /// Declara a variavel com nome a e valor b
    DeclWV(String, Value),
    /// Passa a execução para outra seção com nome a, retornando uma instrução à frente
    Jump(String),
    /// Compara os valores de a e b, usado em condicionais
    Cmp(u64, u64),
}

/// Procura pelo caractere c em src e retorna quantas vezes ele foi encontrado
fn n_of_char(c: char, src: &str) -> i32 {
    if src.len() <= 0 {
        0
    } else {
        let mut num = 0i32;
        for curr in src.chars() {
            if curr == c {
                num += 1;
            }
        }
        num
    }
}

/// Faz parsing de um comando
fn parse_cmd(cmd: &str) -> Option<Command> {
    // Estrutura de um comando:
    // COMANDO: var1, var2, ...
    let cmd = cmd.trim();
    let cmd_parts = cmd.split(':').collect::<Vec<&str>>();
    // Tipo/nome do comando
    let cmd_type = cmd_parts[0];
    let mut arguments: Vec<&str> = vec![];
    if n_of_char(',', cmd_parts[1]) == 0 {
        // Apenas um argumento
        arguments.push(cmd_parts[1].trim());
    } else {
        arguments = cmd_parts[1].split(',').collect::<Vec<&str>>();
    }
    match cmd_type {
        kw::KW_MOVE => {}
        kw::KW_CLEAR => {}
        kw::KW_XOR => {}
        kw::KW_AND => {}
        kw::KW_OR => {}
        kw::KW_ADD => {}
        kw::KW_REM => {}
        kw::KW_DIV => {}
        kw::KW_MUL => {}
        kw::KW_DECL => {}
        kw::KW_DECLWV => {}
        kw::KW_JUMP => {}
        kw::KW_CMP => {}
        _ => panic!("Erro: Tipo de comando \"{}\" não existe.", cmd_type),
    }
    None
}

/// Representa uma unidade (arquivo compilado) contendo o conteudo a ser executado
pub struct Unit {
    /// Conjunto de seções para execução
    sects: Vec<Section>,
    /// Conjunto de globais
    consts: Vec<Global>,
}

/// Realiza a interpretação de um arquivo e retorna sua unidade compilada
pub fn parse(file: &str) -> Unit {
    unimplemented!();
}

/// Representa uma área chamável que pode ser executada
pub struct Section {
    /// Nome da seção
    name: String,
    /// Conjunto de linhas/comandos para execução
    lines: Vec<Command>,
}

/// Faz parsing de uma seção
fn parse_section(sect_str: &str) -> Section {
    // Separa a seção em linhas
    let lines = sect_str.split('\n').collect::<Vec<&str>>();
    if lines.len() <= 1 {
        panic!("Erro fazendo parsing da seção. Número incorreto de linhas.")
    } else {
        // Checagens de declaração e finalização são feitas em parse
        // Declaração de uma seção:
        // PALAVRA_CHAVE nome
        if !lines[0].contains(' ') {
            panic!("Erro na declaração da seção! Falta nome depois da palavra chave");
        }
        let mut sect = Section {
            name: String::from(lines[0].split(' ').collect::<Vec<&str>>()[0]),
            lines: vec![],
        };
        for l in 1..lines.len() - 1 {
            let line = lines[l];
            sect.lines.push(parse_cmd(line).unwrap());
        }
        sect
    }
}

/// Representa um valor global, constante
pub struct Global {
    /// Identificador do valor global
    identifier: String,
    /// Valor do global
    value: Value,
}

/// Faz parsing de um global
fn parse_global(glb: &str) -> Global {
    // Estrutura da declaração de um global: PALAVRA_CHAVE: nome: valor
    let global = String::from(glb.trim());
    let words = global.split(':').collect::<Vec<&str>>();
    // Separa o nome e valor do global
    let (glb_name, glb_value) = (words[1].trim(), words[2].trim());
    let glb_value = match value::parse_expr(glb_value) {
        Some(val) => val,
        None => panic!(),
    };
    Global {
        identifier: String::from(glb_name),
        value: glb_value,
    }
}
<|endoftext|>