<commit_before>/*!

This module provides an index (entity) based tree structure compatible
to the Entity Component System ([DCES]). OrbTK methods will use
**DCES** for entity and property storage.

[DCES]: (https://gitlab.redox-os.org/redox-os/dces-rust)

# Example

Basic usage of the tree:

```rust,no_run

use orbtk_tree::prelude::*;

let mut tree = Tree::new();
tree.register_node(0);
tree.register_node(1);
tree.append_child(0, 1);
```

 */

use std::{cell::Cell, collections::BTreeMap};

use dces::{entity::EntityStore, prelude::Entity};

/// Used as return type if a requested entity is not found on the tree.
#[derive(Debug, PartialEq, Eq)]
pub enum NotFound {
    /// Parent could not be found.
    Parent(Entity),

    /// Child could not be found
    Child(Entity),
}

/// Base data structure to manage the entities of a window in a tree based structure.
#[derive(Clone, Default, Debug)]
pub struct Tree {
    pub root: Option<Entity>,
    pub overlay: Option<Entity>,
    pub children: BTreeMap<Entity, Vec<Entity>>,
    pub parent: BTreeMap<Entity, Option<Entity>>,
    iterator_start_node: Cell<Option<Entity>>,
}

impl Tree {
    /// Creates a new tree with default values.
    pub fn new() -> Self {
        Tree::default()
    }

    /// Returns the root of the tree.
    pub fn root(&self) -> Entity {
        if let Some(root) = self.root {
            return root;
        }

        if let Some(root) = self.parent.keys().next() {
            return *root;
        }

        0.into()
    }

    // /// Configure the tree iterator with a start node.
    pub fn start_node(&self, start_node: impl Into<Entity>) -> &Self {
        self.iterator_start_node.set(Some(start_node.into()));
        self
    }

    /// Registers a new entity `entity` as node.
    pub fn register_node(&mut self, entity: impl Into<Entity>) {
        let entity = entity.into();
        self.children.insert(entity, vec![]);
        self.parent.insert(entity, None);
    }

    /// Sets the root.
    pub fn set_root(&mut self, root: impl Into<Entity>) {
        let root = root.into();
        self.root = Some(root);

        if let Some(overlay) = self.overlay {
            if let Some(p) = self.children.get_mut(&root) {
                p.push(overlay);
            }
        }
    }

    pub fn set_overlay(&mut self, overlay: impl Into<Entity>) {
        let overlay = overlay.into();
        self.overlay = Some(overlay);

        if let Some(root) = self.root {
            if let Some(p) = self.children.get_mut(&root) {
                p.push(overlay);
            }
        }
    }

    /// Appends a `child` entity to the given `parent` entity.
    /// Raised `NotFound` error if the parent is not part of the tree.
    pub fn append_child(
        &mut self,
        parent: impl Into<Entity>,
        child: impl Into<Entity>,
    ) -> Result<Entity, NotFound> {
        let parent = parent.into();
        let child = child.into();

        if self.root.is_some() && parent == self.root.unwrap() && self.overlay.is_some() {
            // insert child to root before overlay
            let len = self.children.len();
            if let Some(p) = self.children.get_mut(&parent) {
                p.insert(len - 2, child);
            } else {
                return Err(NotFound::Parent(parent));
            }
        } else {
            if let Some(p) = self.children.get_mut(&parent) {
                p.push(child);
            } else {
                return Err(NotFound::Parent(parent));
            }
            self.parent.insert(child, Some(parent));
        }

        Ok(child)
    }

    /// Returns the number of all entities in the tree.
    pub fn len(&self) -> usize {
        self.children.len()
    }

    /// Returns true if the tree has no entities.
    pub fn is_empty(&self) -> bool {
        self.children.is_empty()
    }
}

impl EntityStore for Tree {
    fn register_entity(&mut self, entity: impl Into<Entity>) {
        self.register_node(entity.into());
    }

    fn remove_entity(&mut self, entity: impl Into<Entity>) {
        let entity = entity.into();

        if let Some(parent_index) = self.parent[&entity] {
            if let Some(parent_children) = self.children.get_mut(&parent_index) {
                if let Some(index) = parent_children.iter().position(|&r| r == entity) {
                    parent_children.remove(index);
                }
            }
        }

        self.children.remove(&entity);
        self.parent.remove(&entity);
    }
}

impl<'a> IntoIterator for &'a Tree {
    type Item = Entity;
    type IntoIter = TreeIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        let start_node = {
            if let Some(start_node) = self.iterator_start_node.get() {
                start_node
            } else if let Some(root) = self.root {
                root
            } else {
                0.into()
            }
        };

        self.iterator_start_node.set(None);

        TreeIterator {
            tree: self,
            start_node,
            current_node: None,
        }
    }
}

/// Used to create an iterator for the tree.
pub struct TreeIterator<'a> {
    tree: &'a Tree,
    start_node: Entity,
    current_node: Option<Entity>,
}

impl<'a> Iterator for TreeIterator<'a> {
    type Item = Entity;

    fn next(&mut self) -> Option<Entity> {
        if let Some(node) = self.current_node {
            if !self.tree.children.contains_key(&node) {
                panic!("TreeIterator.next: Tree does not contains node {}", node.0);
            }
            if !self.tree.children[&node].is_empty() {
                self.current_node = Some(self.tree.children[&node][0]);
                return self.current_node;
            } else {
                if !self.tree.children.contains_key(&node) {
                    panic!("TreeIterator.next: Tree does not contains node {}", node.0);
                }
                let mut tree_node = node;
                while let Some(parent) = self.tree.parent[&tree_node] {
                    let siblings = &self.tree.children[&parent];

                    let sibling_index = siblings.iter().position(|&r| r == tree_node).unwrap() + 1;

                    if sibling_index < siblings.len() {
                        self.current_node = Some(siblings[sibling_index]);
                        return self.current_node;
                    } else {
                        tree_node = parent;
                    }
                }
                // root
                return None;
            }
        }

        self.current_node = Some(self.start_node);
        self.current_node
    }
}

#[cfg(test)]
mod tests {
    use dces::entity::EntityStore;
    use dces::prelude::*;

    use super::*;

    #[test]
    fn test_register_node() {
        let mut tree = Tree::new();
        tree.register_node(0);

        assert_eq!(tree.children.len(), 1);
        assert_eq!(tree.parent.len(), 1);
        assert!(tree.children.get(&Entity(0)).is_some());
    }

    #[test]
    fn test_append_child() {
        let parent = Entity(0);
        let child = Entity(1);

        let mut tree = Tree::new();
        tree.register_node(parent);
        tree.register_node(child);
        tree.append_child(parent, child).unwrap();

        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.parent.len(), 2);
        assert_eq!(tree.children.get(&parent).unwrap()[0], child);
        assert_eq!(tree.parent.get(&child).unwrap().unwrap(), parent);
    }

    #[test]
    fn test_len() {
        let mut tree = Tree::new();
        assert_eq!(tree.children.len(), 0);

        tree.register_node(0);
        assert_eq!(tree.children.len(), 1);

        tree.register_node(1);
        assert_eq!(tree.children.len(), 2);
    }

    #[test]
    fn test_is_empty() {
        let mut tree = Tree::new();
        assert!(tree.is_empty());

        tree.register_node(0);
        assert!(!tree.is_empty());
    }

    #[test]
    fn test_register_entity() {
        let mut tree = Tree::new();
        tree.register_entity(0);

        assert_eq!(tree.children.len(), 1);
        assert_eq!(tree.parent.len(), 1);
        assert!(tree.children.get(&Entity(0)).is_some());
    }

    #[test]
    fn test_remove_entity() {
        let mut tree = Tree::new();

        tree.register_entity(0);
        assert_eq!(tree.children.len(), 1);
        assert_eq!(tree.parent.len(), 1);
        assert!(tree.children.get(&Entity(0)).is_some());

        tree.remove_entity(0);
        assert_eq!(tree.children.len(), 0);
        assert_eq!(tree.parent.len(), 0);
        assert!(tree.children.get(&Entity(0)).is_none());
    }

    #[test]
    fn test_iterator_next() {
        let mut tree = Tree::new();
        tree.register_entity(0);
        tree.register_entity(1);
        tree.register_entity(2);
        tree.register_entity(3);
        tree.register_entity(4);
        tree.register_entity(5);
        tree.register_entity(6);

        tree.append_child(0, 1).unwrap();
        tree.append_child(0, 2).unwrap();

        tree.append_child(1, 3).unwrap();
        tree.append_child(1, 4).unwrap();

        tree.append_child(2, 5).unwrap();
        tree.append_child(2, 6).unwrap();

        let mut iterator = tree.into_iter();

        assert_eq!(Entity(0), iterator.next().unwrap());
        assert_eq!(Entity(1), iterator.next().unwrap());
        assert_eq!(Entity(3), iterator.next().unwrap());
        assert_eq!(Entity(4), iterator.next().unwrap());
        assert_eq!(Entity(2), iterator.next().unwrap());
        assert_eq!(Entity(5), iterator.next().unwrap());
        assert_eq!(Entity(6), iterator.next().unwrap());
    }
}
<commit_msg>orbtk_core: update tree documentation<commit_after>/*!

This module provides an index (entity) based tree structure compatible
to the Entity Component System ([DCES]). OrbTK methods will use
**DCES** for entity and property storage.

[DCES]: https://gitlab.redox-os.org/redox-os/dces-rust

# Example

Basic usage of the tree:

```rust,no_run

use orbtk_tree::prelude::*;

let mut tree = Tree::new();
tree.register_node(0);
tree.register_node(1);
tree.append_child(0, 1);
```

 */

use std::{cell::Cell, collections::BTreeMap};

use dces::{entity::EntityStore, prelude::Entity};

/// Used as return type if a requested entity is not found on the tree.
#[derive(Debug, PartialEq, Eq)]
pub enum NotFound {
    /// Parent could not be found.
    Parent(Entity),

    /// Child could not be found
    Child(Entity),
}

/// Base data structure to manage the entities of a window in a tree based structure.
#[derive(Clone, Default, Debug)]
pub struct Tree {
    pub root: Option<Entity>,
    pub overlay: Option<Entity>,
    pub children: BTreeMap<Entity, Vec<Entity>>,
    pub parent: BTreeMap<Entity, Option<Entity>>,
    iterator_start_node: Cell<Option<Entity>>,
}

impl Tree {
    /// Creates a new tree with default values.
    pub fn new() -> Self {
        Tree::default()
    }

    /// Returns the root of the tree.
    pub fn root(&self) -> Entity {
        if let Some(root) = self.root {
            return root;
        }

        if let Some(root) = self.parent.keys().next() {
            return *root;
        }

        0.into()
    }

    // /// Configure the tree iterator with a start node.
    pub fn start_node(&self, start_node: impl Into<Entity>) -> &Self {
        self.iterator_start_node.set(Some(start_node.into()));
        self
    }

    /// Registers a new entity `entity` as node.
    pub fn register_node(&mut self, entity: impl Into<Entity>) {
        let entity = entity.into();
        self.children.insert(entity, vec![]);
        self.parent.insert(entity, None);
    }

    /// Sets the root.
    pub fn set_root(&mut self, root: impl Into<Entity>) {
        let root = root.into();
        self.root = Some(root);

        if let Some(overlay) = self.overlay {
            if let Some(p) = self.children.get_mut(&root) {
                p.push(overlay);
            }
        }
    }

    pub fn set_overlay(&mut self, overlay: impl Into<Entity>) {
        let overlay = overlay.into();
        self.overlay = Some(overlay);

        if let Some(root) = self.root {
            if let Some(p) = self.children.get_mut(&root) {
                p.push(overlay);
            }
        }
    }

    /// Appends a `child` entity to the given `parent` entity.
    /// Raised `NotFound` error if the parent is not part of the tree.
    pub fn append_child(
        &mut self,
        parent: impl Into<Entity>,
        child: impl Into<Entity>,
    ) -> Result<Entity, NotFound> {
        let parent = parent.into();
        let child = child.into();

        if self.root.is_some() && parent == self.root.unwrap() && self.overlay.is_some() {
            // insert child to root before overlay
            let len = self.children.len();
            if let Some(p) = self.children.get_mut(&parent) {
                p.insert(len - 2, child);
            } else {
                return Err(NotFound::Parent(parent));
            }
        } else {
            if let Some(p) = self.children.get_mut(&parent) {
                p.push(child);
            } else {
                return Err(NotFound::Parent(parent));
            }
            self.parent.insert(child, Some(parent));
        }

        Ok(child)
    }

    /// Returns the number of all entities in the tree.
    pub fn len(&self) -> usize {
        self.children.len()
    }

    /// Returns true if the tree has no entities.
    pub fn is_empty(&self) -> bool {
        self.children.is_empty()
    }
}

impl EntityStore for Tree {
    fn register_entity(&mut self, entity: impl Into<Entity>) {
        self.register_node(entity.into());
    }

    fn remove_entity(&mut self, entity: impl Into<Entity>) {
        let entity = entity.into();

        if let Some(parent_index) = self.parent[&entity] {
            if let Some(parent_children) = self.children.get_mut(&parent_index) {
                if let Some(index) = parent_children.iter().position(|&r| r == entity) {
                    parent_children.remove(index);
                }
            }
        }

        self.children.remove(&entity);
        self.parent.remove(&entity);
    }
}

impl<'a> IntoIterator for &'a Tree {
    type Item = Entity;
    type IntoIter = TreeIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        let start_node = {
            if let Some(start_node) = self.iterator_start_node.get() {
                start_node
            } else if let Some(root) = self.root {
                root
            } else {
                0.into()
            }
        };

        self.iterator_start_node.set(None);

        TreeIterator {
            tree: self,
            start_node,
            current_node: None,
        }
    }
}

/// Used to create an iterator for the tree.
pub struct TreeIterator<'a> {
    tree: &'a Tree,
    start_node: Entity,
    current_node: Option<Entity>,
}

impl<'a> Iterator for TreeIterator<'a> {
    type Item = Entity;

    fn next(&mut self) -> Option<Entity> {
        if let Some(node) = self.current_node {
            if !self.tree.children.contains_key(&node) {
                panic!("TreeIterator.next: Tree does not contains node {}", node.0);
            }
            if !self.tree.children[&node].is_empty() {
                self.current_node = Some(self.tree.children[&node][0]);
                return self.current_node;
            } else {
                if !self.tree.children.contains_key(&node) {
                    panic!("TreeIterator.next: Tree does not contains node {}", node.0);
                }
                let mut tree_node = node;
                while let Some(parent) = self.tree.parent[&tree_node] {
                    let siblings = &self.tree.children[&parent];

                    let sibling_index = siblings.iter().position(|&r| r == tree_node).unwrap() + 1;

                    if sibling_index < siblings.len() {
                        self.current_node = Some(siblings[sibling_index]);
                        return self.current_node;
                    } else {
                        tree_node = parent;
                    }
                }
                // root
                return None;
            }
        }

        self.current_node = Some(self.start_node);
        self.current_node
    }
}

#[cfg(test)]
mod tests {
    use dces::entity::EntityStore;
    use dces::prelude::*;

    use super::*;

    #[test]
    fn test_register_node() {
        let mut tree = Tree::new();
        tree.register_node(0);

        assert_eq!(tree.children.len(), 1);
        assert_eq!(tree.parent.len(), 1);
        assert!(tree.children.get(&Entity(0)).is_some());
    }

    #[test]
    fn test_append_child() {
        let parent = Entity(0);
        let child = Entity(1);

        let mut tree = Tree::new();
        tree.register_node(parent);
        tree.register_node(child);
        tree.append_child(parent, child).unwrap();

        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.parent.len(), 2);
        assert_eq!(tree.children.get(&parent).unwrap()[0], child);
        assert_eq!(tree.parent.get(&child).unwrap().unwrap(), parent);
    }

    #[test]
    fn test_len() {
        let mut tree = Tree::new();
        assert_eq!(tree.children.len(), 0);

        tree.register_node(0);
        assert_eq!(tree.children.len(), 1);

        tree.register_node(1);
        assert_eq!(tree.children.len(), 2);
    }

    #[test]
    fn test_is_empty() {
        let mut tree = Tree::new();
        assert!(tree.is_empty());

        tree.register_node(0);
        assert!(!tree.is_empty());
    }

    #[test]
    fn test_register_entity() {
        let mut tree = Tree::new();
        tree.register_entity(0);

        assert_eq!(tree.children.len(), 1);
        assert_eq!(tree.parent.len(), 1);
        assert!(tree.children.get(&Entity(0)).is_some());
    }

    #[test]
    fn test_remove_entity() {
        let mut tree = Tree::new();

        tree.register_entity(0);
        assert_eq!(tree.children.len(), 1);
        assert_eq!(tree.parent.len(), 1);
        assert!(tree.children.get(&Entity(0)).is_some());

        tree.remove_entity(0);
        assert_eq!(tree.children.len(), 0);
        assert_eq!(tree.parent.len(), 0);
        assert!(tree.children.get(&Entity(0)).is_none());
    }

    #[test]
    fn test_iterator_next() {
        let mut tree = Tree::new();
        tree.register_entity(0);
        tree.register_entity(1);
        tree.register_entity(2);
        tree.register_entity(3);
        tree.register_entity(4);
        tree.register_entity(5);
        tree.register_entity(6);

        tree.append_child(0, 1).unwrap();
        tree.append_child(0, 2).unwrap();

        tree.append_child(1, 3).unwrap();
        tree.append_child(1, 4).unwrap();

        tree.append_child(2, 5).unwrap();
        tree.append_child(2, 6).unwrap();

        let mut iterator = tree.into_iter();

        assert_eq!(Entity(0), iterator.next().unwrap());
        assert_eq!(Entity(1), iterator.next().unwrap());
        assert_eq!(Entity(3), iterator.next().unwrap());
        assert_eq!(Entity(4), iterator.next().unwrap());
        assert_eq!(Entity(2), iterator.next().unwrap());
        assert_eq!(Entity(5), iterator.next().unwrap());
        assert_eq!(Entity(6), iterator.next().unwrap());
    }
}
<|endoftext|>


<commit_before>//! EVM Program Counter.

use bigint::M256;
use util::opcode::Opcode;
use std::cmp::min;
use std::marker::PhantomData;
use super::Patch;
use super::errors::OnChainError;

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[allow(missing_docs)]
/// Instructions for the program counter. This is the same as `Opcode`
/// except `PUSH`, which might take longer length.
pub enum Instruction {
    STOP, ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, ADDMOD, MULMOD, EXP,
    SIGNEXTEND, LT, GT, SLT, SGT, EQ, ISZERO, AND, OR, XOR, NOT, BYTE,
    SHA3, ADDRESS, BALANCE, ORIGIN, CALLER, CALLVALUE, CALLDATALOAD,
    CALLDATASIZE, CALLDATACOPY, CODESIZE, CODECOPY, GASPRICE,
    EXTCODESIZE, EXTCODECOPY, BLOCKHASH, COINBASE, TIMESTAMP, NUMBER,
    DIFFICULTY, GASLIMIT, POP, MLOAD, MSTORE, MSTORE8, SLOAD, SSTORE,
    JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, CREATE, CALL, CALLCODE,
    RETURN, DELEGATECALL, SUICIDE,

    PUSH(M256),
    DUP(usize),
    SWAP(usize),
    LOG(usize),
}

/// Represents a program counter in EVM.
pub struct PC<P: Patch> {
    position: usize,
    code: Vec<u8>,
    valids: Vec<bool>,
    _patch: PhantomData<P>,
}

impl<P: Patch> PC<P> {
    /// Create a new program counter from the given code.
    pub fn new(code: &[u8]) -> Self {
        let code: Vec<u8> = code.into();
        let mut valids: Vec<bool> = Vec::with_capacity(code.len());
        valids.resize(code.len(), false);

        let mut i = 0;
        while i < code.len() {
            let opcode: Opcode = code[i].into();
            match opcode {
                Opcode::JUMPDEST => {
                    valids[i] = true;
                    i = i + 1;
                },
                Opcode::PUSH(v) => {
                    i = i + v + 1;
                },
                _ => {
                    i = i + 1;
                }
            }
        }

        PC {
            code,
            position: 0,
            valids: valids,
            _patch: PhantomData,
        }
    }

    fn read_bytes(&self, from_position: usize, byte_count: usize) -> Result<M256, OnChainError> {
        if from_position > self.code.len() {
            return Err(OnChainError::PCOverflow);
        }
        let position = from_position;
        let max = min(position.saturating_add(byte_count), self.code.len());
        Ok(M256::from(&self.code[position..max]))
    }

    /// Get the code bytearray.
    pub fn code(&self) -> &[u8] {
        &self.code
    }

    /// Jump to a position in the code. The destination must be valid
    /// to jump.
    pub fn jump(&mut self, position: usize) -> Result<(), OnChainError> {
        if position >= self.code.len() {
            return Err(OnChainError::PCOverflow);
        }

        if !self.valids[position] {
            return Err(OnChainError::BadJumpDest);
        }

        self.position = position;
        Ok(())
    }

    /// Get the current program counter position.
    pub fn position(&self) -> usize {
        self.position
    }

    /// Returns `true` if the position is a valid jump destination. If
    /// not, returns `false`.
    pub fn is_valid(&self, position: usize) -> bool {
        if position >= self.code.len() {
            return false;
        }

        if !self.valids[position] {
            return false;
        }

        return true;
    }

    /// Check whether the PC is ended. Next `read` on this PC would
    /// result in `PCError::PCOverflow`.
    pub fn is_end(&self) -> bool {
        self.position == self.code.len()
    }

    /// Peek the next instruction.
    pub fn peek(&self) -> Result<Instruction, OnChainError> {
        let position = self.position;
        if position >= self.code.len() {
            return Err(OnChainError::PCOverflow);
        }
        let opcode: Opcode = self.code[position].into();
        Ok(match opcode {
            Opcode::STOP => Instruction::STOP,
            Opcode::ADD => Instruction::ADD,
            Opcode::MUL => Instruction::MUL,
            Opcode::SUB => Instruction::SUB,
            Opcode::DIV => Instruction::DIV,
            Opcode::SDIV => Instruction::SDIV,
            Opcode::MOD => Instruction::MOD,
            Opcode::SMOD => Instruction::SMOD,
            Opcode::ADDMOD => Instruction::ADDMOD,
            Opcode::MULMOD => Instruction::MULMOD,
            Opcode::EXP => Instruction::EXP,
            Opcode::SIGNEXTEND => Instruction::SIGNEXTEND,

            Opcode::LT => Instruction::LT,
            Opcode::GT => Instruction::GT,
            Opcode::SLT => Instruction::SLT,
            Opcode::SGT => Instruction::SGT,
            Opcode::EQ => Instruction::EQ,
            Opcode::ISZERO => Instruction::ISZERO,
            Opcode::AND => Instruction::AND,
            Opcode::OR => Instruction::OR,
            Opcode::XOR => Instruction::XOR,
            Opcode::NOT => Instruction::NOT,
            Opcode::BYTE => Instruction::BYTE,

            Opcode::SHA3 => Instruction::SHA3,

            Opcode::ADDRESS => Instruction::ADDRESS,
            Opcode::BALANCE => Instruction::BALANCE,
            Opcode::ORIGIN => Instruction::ORIGIN,
            Opcode::CALLER => Instruction::CALLER,
            Opcode::CALLVALUE => Instruction::CALLVALUE,
            Opcode::CALLDATALOAD => Instruction::CALLDATALOAD,
            Opcode::CALLDATASIZE => Instruction::CALLDATASIZE,
            Opcode::CALLDATACOPY => Instruction::CALLDATACOPY,
            Opcode::CODESIZE => Instruction::CODESIZE,
            Opcode::CODECOPY => Instruction::CODECOPY,
            Opcode::GASPRICE => Instruction::GASPRICE,
            Opcode::EXTCODESIZE => Instruction::EXTCODESIZE,
            Opcode::EXTCODECOPY => Instruction::EXTCODECOPY,

            Opcode::BLOCKHASH => Instruction::BLOCKHASH,
            Opcode::COINBASE => Instruction::COINBASE,
            Opcode::TIMESTAMP => Instruction::TIMESTAMP,
            Opcode::NUMBER => Instruction::NUMBER,
            Opcode::DIFFICULTY => Instruction::DIFFICULTY,
            Opcode::GASLIMIT => Instruction::GASLIMIT,

            Opcode::POP => Instruction::POP,
            Opcode::MLOAD => Instruction::MLOAD,
            Opcode::MSTORE => Instruction::MSTORE,
            Opcode::MSTORE8 => Instruction::MSTORE8,
            Opcode::SLOAD => Instruction::SLOAD,
            Opcode::SSTORE => Instruction::SSTORE,
            Opcode::JUMP => Instruction::JUMP,
            Opcode::JUMPI => Instruction::JUMPI,
            Opcode::PC => Instruction::PC,
            Opcode::MSIZE => Instruction::MSIZE,
            Opcode::GAS => Instruction::GAS,
            Opcode::JUMPDEST => Instruction::JUMPDEST,

            Opcode::PUSH(v) => {
                let param = self.read_bytes(position + 1, v)?;
                Instruction::PUSH(param)
            },

            Opcode::DUP(v) => Instruction::DUP(v),
            Opcode::SWAP(v) => Instruction::SWAP(v),
            Opcode::LOG(v) => Instruction::LOG(v),

            Opcode::CREATE => Instruction::CREATE,
            Opcode::CALL => Instruction::CALL,
            Opcode::CALLCODE => Instruction::CALLCODE,
            Opcode::RETURN => Instruction::RETURN,
            Opcode::DELEGATECALL => {
                if P::has_delegate_call() {
                    Instruction::DELEGATECALL
                } else {
                    return Err(OnChainError::InvalidOpcode);
                }
            },

            Opcode::INVALID => {
                return Err(OnChainError::InvalidOpcode);
            },
            Opcode::SUICIDE => Instruction::SUICIDE,
        })
    }

    /// Read the next instruction and step the program counter.
    pub fn read(&mut self) -> Result<Instruction, OnChainError> {
        let result = self.peek()?;
        let opcode: Opcode = self.code[self.position].into();
        match opcode {
            Opcode::PUSH(v) => {
                self.position = min(self.position + v + 1, self.code.len());
            },
            _ => {
                self.position = self.position + 1;
            },
        }
        Ok(result)
    }
}
<commit_msg>PC::opcode_position for getting the current opcode position<commit_after>//! EVM Program Counter.

use bigint::M256;
use util::opcode::Opcode;
use std::cmp::min;
use std::marker::PhantomData;
use super::Patch;
use super::errors::OnChainError;

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[allow(missing_docs)]
/// Instructions for the program counter. This is the same as `Opcode`
/// except `PUSH`, which might take longer length.
pub enum Instruction {
    STOP, ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, ADDMOD, MULMOD, EXP,
    SIGNEXTEND, LT, GT, SLT, SGT, EQ, ISZERO, AND, OR, XOR, NOT, BYTE,
    SHA3, ADDRESS, BALANCE, ORIGIN, CALLER, CALLVALUE, CALLDATALOAD,
    CALLDATASIZE, CALLDATACOPY, CODESIZE, CODECOPY, GASPRICE,
    EXTCODESIZE, EXTCODECOPY, BLOCKHASH, COINBASE, TIMESTAMP, NUMBER,
    DIFFICULTY, GASLIMIT, POP, MLOAD, MSTORE, MSTORE8, SLOAD, SSTORE,
    JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, CREATE, CALL, CALLCODE,
    RETURN, DELEGATECALL, SUICIDE,

    PUSH(M256),
    DUP(usize),
    SWAP(usize),
    LOG(usize),
}

/// Represents a program counter in EVM.
pub struct PC<P: Patch> {
    position: usize,
    code: Vec<u8>,
    valids: Vec<bool>,
    _patch: PhantomData<P>,
}

impl<P: Patch> PC<P> {
    /// Create a new program counter from the given code.
    pub fn new(code: &[u8]) -> Self {
        let code: Vec<u8> = code.into();
        let mut valids: Vec<bool> = Vec::with_capacity(code.len());
        valids.resize(code.len(), false);

        let mut i = 0;
        while i < code.len() {
            let opcode: Opcode = code[i].into();
            match opcode {
                Opcode::JUMPDEST => {
                    valids[i] = true;
                    i = i + 1;
                },
                Opcode::PUSH(v) => {
                    i = i + v + 1;
                },
                _ => {
                    i = i + 1;
                }
            }
        }

        PC {
            code,
            position: 0,
            valids: valids,
            _patch: PhantomData,
        }
    }

    fn read_bytes(&self, from_position: usize, byte_count: usize) -> Result<M256, OnChainError> {
        if from_position > self.code.len() {
            return Err(OnChainError::PCOverflow);
        }
        let position = from_position;
        let max = min(position.saturating_add(byte_count), self.code.len());
        Ok(M256::from(&self.code[position..max]))
    }

    /// Get the code bytearray.
    pub fn code(&self) -> &[u8] {
        &self.code
    }

    /// Jump to a position in the code. The destination must be valid
    /// to jump.
    pub fn jump(&mut self, position: usize) -> Result<(), OnChainError> {
        if position >= self.code.len() {
            return Err(OnChainError::PCOverflow);
        }

        if !self.valids[position] {
            return Err(OnChainError::BadJumpDest);
        }

        self.position = position;
        Ok(())
    }

    /// Get the current program counter position.
    pub fn position(&self) -> usize {
        self.position
    }

    /// Get the current opcode position. Should only be used when debugging.
    pub fn opcode_position(&self) -> usize {
        let mut o = 0;
        let mut i = 0;
        while i <= self.position {
            let opcode: Opcode = self.code[i].into();
            match opcode {
                Opcode::PUSH(v) => {
                    i = i + v + 1;
                },
                _ => {
                    i = i + 1;
                }
            }
            o = o + 1;
        }
        o
    }

    /// Returns `true` if the position is a valid jump destination. If
    /// not, returns `false`.
    pub fn is_valid(&self, position: usize) -> bool {
        if position >= self.code.len() {
            return false;
        }

        if !self.valids[position] {
            return false;
        }

        return true;
    }

    /// Check whether the PC is ended. Next `read` on this PC would
    /// result in `PCError::PCOverflow`.
    pub fn is_end(&self) -> bool {
        self.position == self.code.len()
    }

    /// Peek the next instruction.
    pub fn peek(&self) -> Result<Instruction, OnChainError> {
        let position = self.position;
        if position >= self.code.len() {
            return Err(OnChainError::PCOverflow);
        }
        let opcode: Opcode = self.code[position].into();
        Ok(match opcode {
            Opcode::STOP => Instruction::STOP,
            Opcode::ADD => Instruction::ADD,
            Opcode::MUL => Instruction::MUL,
            Opcode::SUB => Instruction::SUB,
            Opcode::DIV => Instruction::DIV,
            Opcode::SDIV => Instruction::SDIV,
            Opcode::MOD => Instruction::MOD,
            Opcode::SMOD => Instruction::SMOD,
            Opcode::ADDMOD => Instruction::ADDMOD,
            Opcode::MULMOD => Instruction::MULMOD,
            Opcode::EXP => Instruction::EXP,
            Opcode::SIGNEXTEND => Instruction::SIGNEXTEND,

            Opcode::LT => Instruction::LT,
            Opcode::GT => Instruction::GT,
            Opcode::SLT => Instruction::SLT,
            Opcode::SGT => Instruction::SGT,
            Opcode::EQ => Instruction::EQ,
            Opcode::ISZERO => Instruction::ISZERO,
            Opcode::AND => Instruction::AND,
            Opcode::OR => Instruction::OR,
            Opcode::XOR => Instruction::XOR,
            Opcode::NOT => Instruction::NOT,
            Opcode::BYTE => Instruction::BYTE,

            Opcode::SHA3 => Instruction::SHA3,

            Opcode::ADDRESS => Instruction::ADDRESS,
            Opcode::BALANCE => Instruction::BALANCE,
            Opcode::ORIGIN => Instruction::ORIGIN,
            Opcode::CALLER => Instruction::CALLER,
            Opcode::CALLVALUE => Instruction::CALLVALUE,
            Opcode::CALLDATALOAD => Instruction::CALLDATALOAD,
            Opcode::CALLDATASIZE => Instruction::CALLDATASIZE,
            Opcode::CALLDATACOPY => Instruction::CALLDATACOPY,
            Opcode::CODESIZE => Instruction::CODESIZE,
            Opcode::CODECOPY => Instruction::CODECOPY,
            Opcode::GASPRICE => Instruction::GASPRICE,
            Opcode::EXTCODESIZE => Instruction::EXTCODESIZE,
            Opcode::EXTCODECOPY => Instruction::EXTCODECOPY,

            Opcode::BLOCKHASH => Instruction::BLOCKHASH,
            Opcode::COINBASE => Instruction::COINBASE,
            Opcode::TIMESTAMP => Instruction::TIMESTAMP,
            Opcode::NUMBER => Instruction::NUMBER,
            Opcode::DIFFICULTY => Instruction::DIFFICULTY,
            Opcode::GASLIMIT => Instruction::GASLIMIT,

            Opcode::POP => Instruction::POP,
            Opcode::MLOAD => Instruction::MLOAD,
            Opcode::MSTORE => Instruction::MSTORE,
            Opcode::MSTORE8 => Instruction::MSTORE8,
            Opcode::SLOAD => Instruction::SLOAD,
            Opcode::SSTORE => Instruction::SSTORE,
            Opcode::JUMP => Instruction::JUMP,
            Opcode::JUMPI => Instruction::JUMPI,
            Opcode::PC => Instruction::PC,
            Opcode::MSIZE => Instruction::MSIZE,
            Opcode::GAS => Instruction::GAS,
            Opcode::JUMPDEST => Instruction::JUMPDEST,

            Opcode::PUSH(v) => {
                let param = self.read_bytes(position + 1, v)?;
                Instruction::PUSH(param)
            },

            Opcode::DUP(v) => Instruction::DUP(v),
            Opcode::SWAP(v) => Instruction::SWAP(v),
            Opcode::LOG(v) => Instruction::LOG(v),

            Opcode::CREATE => Instruction::CREATE,
            Opcode::CALL => Instruction::CALL,
            Opcode::CALLCODE => Instruction::CALLCODE,
            Opcode::RETURN => Instruction::RETURN,
            Opcode::DELEGATECALL => {
                if P::has_delegate_call() {
                    Instruction::DELEGATECALL
                } else {
                    return Err(OnChainError::InvalidOpcode);
                }
            },

            Opcode::INVALID => {
                return Err(OnChainError::InvalidOpcode);
            },
            Opcode::SUICIDE => Instruction::SUICIDE,
        })
    }

    /// Read the next instruction and step the program counter.
    pub fn read(&mut self) -> Result<Instruction, OnChainError> {
        let result = self.peek()?;
        let opcode: Opcode = self.code[self.position].into();
        match opcode {
            Opcode::PUSH(v) => {
                self.position = min(self.position + v + 1, self.code.len());
            },
            _ => {
                self.position = self.position + 1;
            },
        }
        Ok(result)
    }
}
<|endoftext|>


<commit_before>type Cell = u8;

pub struct VM {
    cells: [Cell; 30_000],
    data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) -> Cell {
        self.cells[self.data_pointer]
    }

    pub fn increment(&mut self) {
        let value = self.cells[self.data_pointer];
        self.cells[self.data_pointer] = value + 1;
    }

    pub fn right_shift(&mut self) {
        self.data_pointer = self.data_pointer + 1;
    }
}
<commit_msg>Add vm.left_shift function<commit_after>type Cell = u8;

pub struct VM {
    cells: [Cell; 30_000],
    data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) -> Cell {
        self.cells[self.data_pointer]
    }

    pub fn increment(&mut self) {
        let value = self.cells[self.data_pointer];
        self.cells[self.data_pointer] = value + 1;
    }

    pub fn right_shift(&mut self) {
        self.data_pointer = self.data_pointer + 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer = self.data_pointer - 1;
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::{AsValue, Value};

/// Holds the arguments being used to format a [`Message`].
///
/// [`Message`]: struct.Message.html
pub struct Args<'a> {
    name: &'a str,
    value: Value<'a>,
    prev: Option<&'a Args<'a>>,
}

/// Create an argument holder.
///
/// ```
/// use message_format::arg;
///
/// let args = arg("name", "John");
/// assert!(args.get("name").is_some());
/// ```
pub fn arg<'a, T: 'a + AsValue<'a>>(name: &'a str, value: T) -> Args<'a> {
    Args {
        name: name,
        value: value.as_formattable(),
        prev: None,
    }
}

impl<'a> Args<'a> {
    /// Add an additional argument. This returns a new value which maintains a link
    /// to the old value. You must maintain a reference to the return value for it to
    /// remain valid.
    ///
    /// ```
    /// use message_format::arg;
    ///
    /// let args = arg("name", "John");
    /// let args = args.arg("city", "Rome");
    /// assert!(args.get("name").is_some());
    /// assert!(args.get("city").is_some());
    /// ```
    pub fn arg<T: 'a + AsValue<'a>>(&'a self, name: &'a str, value: T) -> Args<'a>
        where Self: Sized
    {
        Args {
            name: name,
            value: value.as_formattable(),
            prev: Some(self),
        }
    }

    /// Retrieve the argument with the given `name`.
    ///
    /// ```
    /// use message_format::arg;
    ///
    /// let args = arg("count", 3);
    /// let arg = args.get("count").unwrap();
    /// ```
    pub fn get(&'a self, name: &str) -> Option<&'a Args<'a>> {
        if self.name == name {
            Some(self)
        } else if let Some(prev) = self.prev {
            prev.get(name)
        } else {
            None
        }
    }

    /// Retrieve the `Value` wrapper around the argument value.
    ///
    /// ```
    /// use message_format::{arg, Value};
    ///
    /// let args = arg("count", 3);
    /// let arg = args.get("count").unwrap();
    /// if let &Value::Number(count) = arg.value() {
    ///     assert_eq!(count, 3);
    /// } else {
    ///     panic!("The count was not a number!");
    /// }
    /// ```
    pub fn value(&'a self) -> &'a Value<'a> {
        &self.value
    }
}

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

    #[test]
    fn get_works() {
        let name = "John";
        let args = arg("name", name);
        assert_eq!(format!("{}", args.get("name").unwrap().value()), "John");
    }

    #[test]
    fn numbers_work() {
        let count = 3;
        let args = arg("count", count);
        assert_eq!(args.get("count").unwrap().value(), &Value::Number(3));
        assert_eq!(format!("{}", args.get("count").unwrap().value()), "3");
    }
}
<commit_msg>Args::value docs: Link to `Value`.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::{AsValue, Value};

/// Holds the arguments being used to format a [`Message`].
///
/// [`Message`]: struct.Message.html
pub struct Args<'a> {
    name: &'a str,
    value: Value<'a>,
    prev: Option<&'a Args<'a>>,
}

/// Create an argument holder.
///
/// ```
/// use message_format::arg;
///
/// let args = arg("name", "John");
/// assert!(args.get("name").is_some());
/// ```
pub fn arg<'a, T: 'a + AsValue<'a>>(name: &'a str, value: T) -> Args<'a> {
    Args {
        name: name,
        value: value.as_formattable(),
        prev: None,
    }
}

impl<'a> Args<'a> {
    /// Add an additional argument. This returns a new value which maintains a link
    /// to the old value. You must maintain a reference to the return value for it to
    /// remain valid.
    ///
    /// ```
    /// use message_format::arg;
    ///
    /// let args = arg("name", "John");
    /// let args = args.arg("city", "Rome");
    /// assert!(args.get("name").is_some());
    /// assert!(args.get("city").is_some());
    /// ```
    pub fn arg<T: 'a + AsValue<'a>>(&'a self, name: &'a str, value: T) -> Args<'a>
        where Self: Sized
    {
        Args {
            name: name,
            value: value.as_formattable(),
            prev: Some(self),
        }
    }

    /// Retrieve the argument with the given `name`.
    ///
    /// ```
    /// use message_format::arg;
    ///
    /// let args = arg("count", 3);
    /// let arg = args.get("count").unwrap();
    /// ```
    pub fn get(&'a self, name: &str) -> Option<&'a Args<'a>> {
        if self.name == name {
            Some(self)
        } else if let Some(prev) = self.prev {
            prev.get(name)
        } else {
            None
        }
    }

    /// Retrieve the [`Value`] wrapper around the argument value.
    ///
    /// ```
    /// use message_format::{arg, Value};
    ///
    /// let args = arg("count", 3);
    /// let arg = args.get("count").unwrap();
    /// if let &Value::Number(count) = arg.value() {
    ///     assert_eq!(count, 3);
    /// } else {
    ///     panic!("The count was not a number!");
    /// }
    /// ```
    ///
    /// [`Value`]: enum.Value.html
    pub fn value(&'a self) -> &'a Value<'a> {
        &self.value
    }
}

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

    #[test]
    fn get_works() {
        let name = "John";
        let args = arg("name", name);
        assert_eq!(format!("{}", args.get("name").unwrap().value()), "John");
    }

    #[test]
    fn numbers_work() {
        let count = 3;
        let args = arg("count", count);
        assert_eq!(args.get("count").unwrap().value(), &Value::Number(3));
        assert_eq!(format!("{}", args.get("count").unwrap().value()), "3");
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;

/// A TIS-100 port.
#[derive(Debug, PartialEq)]
pub enum Port {
    Up,
    Down,
    Left,
    Right,
    Any,
    Last,
}

/// An error which can be returned when parsing a port.
#[derive(Debug, PartialEq)]
pub struct ParsePortError;

impl FromStr for Port {
    type Err = ParsePortError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_uppercase().as_str() {
            "UP" => Ok(Port::Up),
            "DOWN" => Ok(Port::Down),
            "LEFT" => Ok(Port::Left),
            "RIGHT" => Ok(Port::Right),
            "ANY" => Ok(Port::Any),
            "LAST" => Ok(Port::Last),
            _ => Err(ParsePortError)
        }
    }
}

/// A TIS-100 register.
#[derive(Debug, PartialEq)]
pub enum Register {
    Acc,
    Bak,
    Nil,
    Io(Port),
}

/// An error which can be returned when parsing a register.
#[derive(Debug, PartialEq)]
pub struct ParseRegisterError;

impl FromStr for Register {
    type Err = ParseRegisterError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_uppercase().as_str() {
            "ACC" => Ok(Register::Acc),
            "BAK" => Ok(Register::Bak),
            "NIL" => Ok(Register::Nil),
            _ => {
                if let Ok(port) = str::parse::<Port>(s) {
                    Ok(Register::Io(port))
                } else {
                    Err(ParseRegisterError)
                }
            }
        }
    }
}

/// The operand component of a TIS-100 instruction.
#[derive(Debug, PartialEq)]
pub enum Operand {
    Val(isize),
    Reg(Register),
}

/// An error which can be returned when parsing an operand.
#[derive(Debug, PartialEq)]
pub struct ParseOperandError;

impl FromStr for Operand {
    type Err = ParseOperandError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Ok(val) = str::parse::<isize>(s) {
            Ok(Operand::Val(val))
        } else if let Ok(register) = str::parse::<Register>(s) {
            Ok(Operand::Reg(register))
        } else {
            Err(ParseOperandError)
        }
    }
}

/// The opcode component of a TIS-100 instruction.
#[derive(Debug, PartialEq)]
pub enum Opcode {
    Nop,
    Mov,
    Swp,
    Sav,
    Add,
    Sub,
    Neg,
    Jmp,
    Jez,
    Jnz,
    Jgz,
    Jlz,
    Jro,
}

/// An error which can be returned when parsing an opcode.
#[derive(Debug, PartialEq)]
pub struct ParseOpcodeError;

impl FromStr for Opcode {
    type Err = ParseOpcodeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_uppercase().as_str() {
            "NOP" => Ok(Opcode::Nop),
            "MOV" => Ok(Opcode::Mov),
            "SWP" => Ok(Opcode::Swp),
            "SAV" => Ok(Opcode::Sav),
            "ADD" => Ok(Opcode::Add),
            "SUB" => Ok(Opcode::Sub),
            "NEG" => Ok(Opcode::Neg),
            "JMP" => Ok(Opcode::Jmp),
            "JEZ" => Ok(Opcode::Jez),
            "JNZ" => Ok(Opcode::Jnz),
            "JGZ" => Ok(Opcode::Jgz),
            "JLZ" => Ok(Opcode::Jlz),
            "JRO" => Ok(Opcode::Jro),
            _ => Err(ParseOpcodeError),
        }
    }
}

/// A valid TIS-100 instruction.
#[derive(Debug, PartialEq)]
pub enum Instruction {
    Nop,
    Mov(Operand, Register),
    Swp,
    Sav,
    Add(Operand),
    Sub(Operand),
    Neg,
    Jmp(usize),
    Jez(usize),
    Jnz(usize),
    Jgz(usize),
    Jlz(usize),
    Jro(isize),
}

/// The list of instructions created by parsing the program source code. The
/// instructions can then be evaluated by a basic execution node.
pub type Program = Vec<Instruction>;

#[test]
fn test_parse_port() {
    assert_eq!(str::parse::<Port>("UP"), Ok(Port::Up));
    assert_eq!(str::parse::<Port>("up"), Ok(Port::Up));
    assert_eq!(str::parse::<Port>("DOWN"), Ok(Port::Down));
    assert_eq!(str::parse::<Port>("LEFT"), Ok(Port::Left));
    assert_eq!(str::parse::<Port>("RIGHT"), Ok(Port::Right));
    assert_eq!(str::parse::<Port>("ANY"), Ok(Port::Any));
    assert_eq!(str::parse::<Port>("LAST"), Ok(Port::Last));
    assert_eq!(str::parse::<Port>("bad"), Err(ParsePortError));
}

#[test]
fn test_parse_register() {
    assert_eq!(str::parse::<Register>("ACC"), Ok(Register::Acc));
    assert_eq!(str::parse::<Register>("acc"), Ok(Register::Acc));
    assert_eq!(str::parse::<Register>("BAK"), Ok(Register::Bak));
    assert_eq!(str::parse::<Register>("NIl"), Ok(Register::Nil));
    assert_eq!(str::parse::<Register>("UP"), Ok(Register::Io(Port::Up)));
    assert_eq!(str::parse::<Register>("bad"), Err(ParseRegisterError));
}

#[test]
fn test_parse_operand() {
    assert_eq!(str::parse::<Operand>("ACC"), Ok(Operand::Reg(Register::Acc)));
    assert_eq!(str::parse::<Operand>("1"), Ok(Operand::Val(1)));
    assert_eq!(str::parse::<Operand>("bad"), Err(ParseOperandError));
}

#[test]
fn test_parse_opcode() {
    assert_eq!(str::parse::<Opcode>("NOP"), Ok(Opcode::Nop));
    assert_eq!(str::parse::<Opcode>("nop"), Ok(Opcode::Nop));
    assert_eq!(str::parse::<Opcode>("MOV"), Ok(Opcode::Mov));
    assert_eq!(str::parse::<Opcode>("SWP"), Ok(Opcode::Swp));
    assert_eq!(str::parse::<Opcode>("SAV"), Ok(Opcode::Sav));
    assert_eq!(str::parse::<Opcode>("ADD"), Ok(Opcode::Add));
    assert_eq!(str::parse::<Opcode>("SUB"), Ok(Opcode::Sub));
    assert_eq!(str::parse::<Opcode>("NEG"), Ok(Opcode::Neg));
    assert_eq!(str::parse::<Opcode>("JMP"), Ok(Opcode::Jmp));
    assert_eq!(str::parse::<Opcode>("JEZ"), Ok(Opcode::Jez));
    assert_eq!(str::parse::<Opcode>("JNZ"), Ok(Opcode::Jnz));
    assert_eq!(str::parse::<Opcode>("JGZ"), Ok(Opcode::Jgz));
    assert_eq!(str::parse::<Opcode>("JLZ"), Ok(Opcode::Jlz));
    assert_eq!(str::parse::<Opcode>("JRO"), Ok(Opcode::Jro));
    assert_eq!(str::parse::<Opcode>("bad"), Err(ParseOpcodeError));
}
<commit_msg>Core types are copyable and cloneable<commit_after>use std::str::FromStr;

/// A TIS-100 port.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Port {
    Up,
    Down,
    Left,
    Right,
    Any,
    Last,
}

/// An error which can be returned when parsing a port.
#[derive(Debug, PartialEq)]
pub struct ParsePortError;

impl FromStr for Port {
    type Err = ParsePortError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_uppercase().as_str() {
            "UP" => Ok(Port::Up),
            "DOWN" => Ok(Port::Down),
            "LEFT" => Ok(Port::Left),
            "RIGHT" => Ok(Port::Right),
            "ANY" => Ok(Port::Any),
            "LAST" => Ok(Port::Last),
            _ => Err(ParsePortError)
        }
    }
}

/// A TIS-100 register.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Register {
    Acc,
    Bak,
    Nil,
    Io(Port),
}

/// An error which can be returned when parsing a register.
#[derive(Debug, PartialEq)]
pub struct ParseRegisterError;

impl FromStr for Register {
    type Err = ParseRegisterError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_uppercase().as_str() {
            "ACC" => Ok(Register::Acc),
            "BAK" => Ok(Register::Bak),
            "NIL" => Ok(Register::Nil),
            _ => {
                if let Ok(port) = str::parse::<Port>(s) {
                    Ok(Register::Io(port))
                } else {
                    Err(ParseRegisterError)
                }
            }
        }
    }
}

/// The operand component of a TIS-100 instruction.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Operand {
    Val(isize),
    Reg(Register),
}

/// An error which can be returned when parsing an operand.
#[derive(Debug, PartialEq)]
pub struct ParseOperandError;

impl FromStr for Operand {
    type Err = ParseOperandError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Ok(val) = str::parse::<isize>(s) {
            Ok(Operand::Val(val))
        } else if let Ok(register) = str::parse::<Register>(s) {
            Ok(Operand::Reg(register))
        } else {
            Err(ParseOperandError)
        }
    }
}

/// The opcode component of a TIS-100 instruction.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Opcode {
    Nop,
    Mov,
    Swp,
    Sav,
    Add,
    Sub,
    Neg,
    Jmp,
    Jez,
    Jnz,
    Jgz,
    Jlz,
    Jro,
}

/// An error which can be returned when parsing an opcode.
#[derive(Debug, PartialEq)]
pub struct ParseOpcodeError;

impl FromStr for Opcode {
    type Err = ParseOpcodeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_uppercase().as_str() {
            "NOP" => Ok(Opcode::Nop),
            "MOV" => Ok(Opcode::Mov),
            "SWP" => Ok(Opcode::Swp),
            "SAV" => Ok(Opcode::Sav),
            "ADD" => Ok(Opcode::Add),
            "SUB" => Ok(Opcode::Sub),
            "NEG" => Ok(Opcode::Neg),
            "JMP" => Ok(Opcode::Jmp),
            "JEZ" => Ok(Opcode::Jez),
            "JNZ" => Ok(Opcode::Jnz),
            "JGZ" => Ok(Opcode::Jgz),
            "JLZ" => Ok(Opcode::Jlz),
            "JRO" => Ok(Opcode::Jro),
            _ => Err(ParseOpcodeError),
        }
    }
}

/// A valid TIS-100 instruction.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Instruction {
    Nop,
    Mov(Operand, Register),
    Swp,
    Sav,
    Add(Operand),
    Sub(Operand),
    Neg,
    Jmp(usize),
    Jez(usize),
    Jnz(usize),
    Jgz(usize),
    Jlz(usize),
    Jro(isize),
}

/// The list of instructions created by parsing the program source code. The
/// instructions can then be evaluated by a basic execution node.
pub type Program = Vec<Instruction>;

#[test]
fn test_parse_port() {
    assert_eq!(str::parse::<Port>("UP"), Ok(Port::Up));
    assert_eq!(str::parse::<Port>("up"), Ok(Port::Up));
    assert_eq!(str::parse::<Port>("DOWN"), Ok(Port::Down));
    assert_eq!(str::parse::<Port>("LEFT"), Ok(Port::Left));
    assert_eq!(str::parse::<Port>("RIGHT"), Ok(Port::Right));
    assert_eq!(str::parse::<Port>("ANY"), Ok(Port::Any));
    assert_eq!(str::parse::<Port>("LAST"), Ok(Port::Last));
    assert_eq!(str::parse::<Port>("bad"), Err(ParsePortError));
}

#[test]
fn test_parse_register() {
    assert_eq!(str::parse::<Register>("ACC"), Ok(Register::Acc));
    assert_eq!(str::parse::<Register>("acc"), Ok(Register::Acc));
    assert_eq!(str::parse::<Register>("BAK"), Ok(Register::Bak));
    assert_eq!(str::parse::<Register>("NIl"), Ok(Register::Nil));
    assert_eq!(str::parse::<Register>("UP"), Ok(Register::Io(Port::Up)));
    assert_eq!(str::parse::<Register>("bad"), Err(ParseRegisterError));
}

#[test]
fn test_parse_operand() {
    assert_eq!(str::parse::<Operand>("ACC"), Ok(Operand::Reg(Register::Acc)));
    assert_eq!(str::parse::<Operand>("1"), Ok(Operand::Val(1)));
    assert_eq!(str::parse::<Operand>("bad"), Err(ParseOperandError));
}

#[test]
fn test_parse_opcode() {
    assert_eq!(str::parse::<Opcode>("NOP"), Ok(Opcode::Nop));
    assert_eq!(str::parse::<Opcode>("nop"), Ok(Opcode::Nop));
    assert_eq!(str::parse::<Opcode>("MOV"), Ok(Opcode::Mov));
    assert_eq!(str::parse::<Opcode>("SWP"), Ok(Opcode::Swp));
    assert_eq!(str::parse::<Opcode>("SAV"), Ok(Opcode::Sav));
    assert_eq!(str::parse::<Opcode>("ADD"), Ok(Opcode::Add));
    assert_eq!(str::parse::<Opcode>("SUB"), Ok(Opcode::Sub));
    assert_eq!(str::parse::<Opcode>("NEG"), Ok(Opcode::Neg));
    assert_eq!(str::parse::<Opcode>("JMP"), Ok(Opcode::Jmp));
    assert_eq!(str::parse::<Opcode>("JEZ"), Ok(Opcode::Jez));
    assert_eq!(str::parse::<Opcode>("JNZ"), Ok(Opcode::Jnz));
    assert_eq!(str::parse::<Opcode>("JGZ"), Ok(Opcode::Jgz));
    assert_eq!(str::parse::<Opcode>("JLZ"), Ok(Opcode::Jlz));
    assert_eq!(str::parse::<Opcode>("JRO"), Ok(Opcode::Jro));
    assert_eq!(str::parse::<Opcode>("bad"), Err(ParseOpcodeError));
}
<|endoftext|>


<commit_before>use Cost;

/// Pass an instance of this Type to a training algorithm to optimize for C=Error^2
///
/// Optimizing a `model::Constant` for LeastSquares should yield the mean value
pub struct LeastSquares;

impl Cost for LeastSquares{

    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent : f64) -> f64
    {
        let error = prediction - truth;
        2.0 * error * gradient_error_by_coefficent
    }
}

/// Pass an instance of this Type to a training algorithm to optimize for C=|Error|
///
/// Optimizing a `model::Constant` for LeastSquares should yield the median
/// Gradient for error == 0 is set to 0
pub struct LeastAbsoluteDeviation;

impl Cost for LeastAbsoluteDeviation{

    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64
    {
        let error = prediction - truth;
        if error > 0.0 {
            gradient_error_by_coefficent
        } else if error < 0.0{
            - gradient_error_by_coefficent
        } else {
            0.0
        }
    }
}

/// Maximies the likelihood function `L` by defining `C=-ln(L)`
///
/// This cost function is best used to optimize propabilities
pub struct MaxLikelihood;

impl Cost for MaxLikelihood{

    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64{
        gradient_error_by_coefficent * ((1.0 - truth) / (1.0 - prediction) - truth / prediction)
    }
}<commit_msg>improved documentation of cost function<commit_after>use Cost;

/// Pass an instance of this Type to a training algorithm to optimize for C=Error^2
///
/// Optimizing a `model::Constant` for LeastSquares should yield the mean value
pub struct LeastSquares;

impl Cost for LeastSquares{

    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent : f64) -> f64
    {
        let error = prediction - truth;
        2.0 * error * gradient_error_by_coefficent
    }
}

/// Pass an instance of this Type to a training algorithm to optimize for C=|Error|
///
/// Optimizing a `model::Constant` for LeastSquares should yield the median
/// Gradient for error == 0 is set to 0
pub struct LeastAbsoluteDeviation;

impl Cost for LeastAbsoluteDeviation{

    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64
    {
        let error = prediction - truth;
        if error > 0.0 {
            gradient_error_by_coefficent
        } else if error < 0.0{
            - gradient_error_by_coefficent
        } else {
            0.0
        }
    }
}

/// Maximies the likelihood function `L` by defining `C=-ln(L)`
///
/// You can use this function if your truth is a propability
/// (i.e. a value betwenn 0 and 1). Maximizing the Likelihood
/// function is equivalent to minimizing the least square error
/// yet this cost function has shown itself to converge quicker
/// for some problems.
pub struct MaxLikelihood;

impl Cost for MaxLikelihood{

    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64{
        gradient_error_by_coefficent * ((1.0 - truth) / (1.0 - prediction) - truth / prediction)
    }
}<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::rc::Rc;

use ast::*;
use env::*;
use parser::*;
use test::Bencher;

pub struct Evaler {
    parser: Parser,
    env:    Rc<RefCell<Env>>
}

#[allow(dead_code)]
impl Evaler {
    pub fn new() -> Evaler {
        let env = Env::new();
        Evaler {
            parser: Parser::new(),
            env:    Rc::new(RefCell::new(env))
        }
    }

    pub fn eval(&mut self, code: String) -> Option<Expr> {
        self.parser.load(code);
        let mut res = None;
        loop {
            let exp = self.parser.read_exp();
            match exp {
                Some(_exp) => {
                    let r = self.eval_exp(_exp);
                    //r.print();
                    //println!("");
                    res = Some(r);
                },
                None => break
            }
        }
        res
    }

    fn eval_exp(&mut self, exp: Expr) -> Expr {
        if exp.is_self()   { return exp; }
        if exp.is_symbol() { return self.env.clone().borrow().lookup(exp.as_str()).unwrap(); }
        if exp.is_quote()  { return exp.cdr().car(); }
        if exp.is_assign() { return self.eval_assign(exp); }
        if exp.is_def()    { return self.eval_def(exp); }
        if exp.is_begin()  { return self.eval_begin(exp); }
        if exp.is_if()     { return self.eval_if(exp); }
        if exp.is_lambda() { return self.eval_lambda(exp); }
        if exp.is_and()    { return self.eval_and(exp); }
        if exp.is_or()     { return self.eval_or(exp); }
        if exp.is_cond()   { return self.eval_cond(exp); }
        if exp.is_let()    { return self.eval_let(exp); }
        if exp.is_pair()   { return self.eval_app(exp); }
        Expr::Symbol(SymbolNode::new("OK"))
    }

    fn eval_assign(&mut self, exp: Expr) -> Expr {
        let var = exp.c("da");
        let val = self.eval_exp(exp.c("dda"));
        self.env.clone().borrow_mut().def_var(var.as_str(), val);
        Expr::Symbol(SymbolNode::new("OK"))
    }

    fn eval_def(&mut self, exp: Expr) -> Expr {
        let var = exp.def_var();
        let val = exp.def_val();
        let val = self.eval_exp(val);
        self.env.clone().borrow_mut().def_var(var.as_str(), val);
        Expr::Symbol(SymbolNode::new("OK"))
    }

    fn eval_if(&mut self, exp: Expr) -> Expr {
        let pred = exp.c("da");
        let blk_t = exp.c("dda");
        let blk_f = exp.c("ddd");
        let res = self.eval_exp(pred);
        if res.is_true() {
            self.eval_exp(blk_t)
        } else {
            if res.is_empty() {
                Expr::Bool(BoolNode::new(false))
            } else {
                self.eval_exp(blk_f.car())
            }
        }
    }

    fn eval_and(&mut self, exp: Expr) -> Expr {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return Expr::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_false() {
                return Expr::Bool(BoolNode::new(false));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_or(&mut self, exp: Expr) -> Expr {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return Expr::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_true() {
                return Expr::Bool(BoolNode::new(true));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_cond(&mut self, exp: Expr) -> Expr {
        let mut elems = exp.cdr().car();
        loop {
            if elems.is_empty() { break; }
            let cur = elems.car();
            let val = self.eval_exp(cur.clone());
            if val.is_true() || val == Expr::Symbol(SymbolNode::new("else")) {
                return self.eval_exp(cur.clone().cdr().car());
            }
            elems = elems.cdr();
        }
        Expr::Bool(BoolNode::new(true))
    }

    fn eval_let(&mut self, exp: Expr) -> Expr {
        fn bind_params(exp: Expr) -> Expr {
            if exp.is_empty() {
                Expr::Nil
            } else {
                Expr::Pair(PairNode::new(exp.c("aa"), bind_params(exp.cdr())))
            }
        }

        fn bind_args(exp: Expr) -> Expr {
            if exp.is_empty() {
                Expr::Nil
            } else {
                Expr::Pair(PairNode::new(exp.c("ada"), bind_args(exp.cdr())))
            }
        }

        let bindings = exp.c("da");
        let obj = Expr::Pair(PairNode::new(
            bind_params(bindings.clone()).make_lambda(exp.c("dd")),
            bind_args(bindings)));
        self.eval_exp(obj)
    }

    fn eval_begin(&mut self, exp: Expr) -> Expr {
        let mut _exp = exp.cdr();
        loop {
            if _exp.is_last() { break; }
            self.eval_exp(_exp.car());
            _exp = _exp.cdr();
        }
        self.eval_exp(_exp.car())
    }

    fn eval_values(&mut self, exprs: Expr) -> Expr {
        if exprs.is_empty() {
            Expr::Nil
        } else {
            let first = self.eval_exp(exprs.car());
            Expr::Pair(PairNode::new(first, self.eval_values(exprs.cdr())))
        }
    }

    fn eval_app(&mut self, expr: Expr) -> Expr {
        let _proc = self.eval_exp(expr.car());
        let _args = self.eval_values(expr.cdr());
        if _proc.is_proc() {
            let func = _proc.as_proc().func();
            return func(_args);
        } else {
            assert!(_proc.is_cproc());
            let _vars = _proc.params();
            self.env = self.env.clone().borrow_mut().extend(_vars, _args);
            let begin = Expr::Symbol(SymbolNode::new("begin"));
            let res = self.eval_exp(Expr::Pair(PairNode::new(begin, _proc.body())));
            self.env = self.env.clone().borrow_mut().parent().unwrap();
            res
        }
    }

    fn eval_lambda(&mut self, expr: Expr) -> Expr {
        // vars + body + env
        Expr::CompProc(CompProcNode::new(expr.c("da"), expr.c("dd"), self.env.clone()))
    }
}

macro_rules! test_case {
    ($test_str:expr, $expect_type:ident, $expect_val:expr) => { {
        let mut evaler = Evaler::new();
        let res = evaler.eval($test_str.to_string()).unwrap();
        if res.$expect_type() != $expect_val {
            assert!(false);
        }
    }}
}

#[test]
fn test_evaler() {
    test_case!("11", as_int, 11);
    test_case!("'a", as_str, "a");
    test_case!(r#""hello""#, as_str, "hello");
    test_case!("#t", as_bool, true);
    test_case!("(and #t #t)", as_bool, true);
    test_case!("(and #t #f)", as_bool, false);
    test_case!("(or #t #t)", as_bool, true);
    test_case!("(or #f #f)", as_bool, false);
    test_case!("(or #t #f)", as_bool, true);
    test_case!("(set! a 1)", as_str, "OK");
    test_case!("(integer? 1)", as_bool, true);
    test_case!("(boolean? #t)", as_bool, true);
    test_case!("(boolean? #f)", as_bool, true);
    test_case!("(integer? #t)", as_bool, false);
    test_case!("(+ 1 1)", as_int, 2);
    test_case!("(- 1 1)", as_int, 0);
    test_case!("(+ 1 1  1)", as_int, 3);
    test_case!("(+ 1 1 -1 -1)", as_int, 0);
    test_case!("(/ 2 1)", as_int, 2);
    test_case!("(* 2 2)", as_int, 4);
    test_case!("(> 2 1)", as_bool, true);
    test_case!("(> 1 2)", as_bool, false);
    test_case!("(> 1 1)", as_bool, false);
    test_case!("(- (+ 3 (* 8 5)) 1)", as_int, 42);
    test_case!("(eq? 1 1)", as_bool, true);
    test_case!("(eq? 1 2)", as_bool, false);
    test_case!("(eq? 1 #f)", as_bool, false);
    test_case!("(pair? '())", as_bool, true);
    test_case!("(> (+ 1 1) 0)", as_bool, true);
    test_case!("(if (> 1 0) 1 else 2)", as_int, 1);
    test_case!("(begin (set! a 1) a)", as_int, 1);
    test_case!("(let ((a 1)) (+ a 1))", as_int, 2);
    test_case!("(let ((a 1)) (> (+ a 1) 0))", as_bool, true);
    test_case!("(let ((a 1) (b 2)) (> a b))", as_bool, false);
    test_case!("(define (add a b) (+ a b))", as_str, "OK");
    test_case!("(cond ((eq? 1 1) 1) ((> 1 2) 2) ))", as_int, 1);
    test_case!("(begin (set! x 5) (set! x 4) (+ x 1))", as_int, 5);
    test_case!("(car '(1 2))", as_int, 1);
    test_case!("(car (cdr '(1 2)))", as_int, 2);
    test_case!("(car (cons 1 2))", as_int, 1);
    test_case!("(car (cons (pair? '(1)) pair? '()))", as_bool, true);
    test_case!("(car (cdr (cons 1 2)))", as_int, 2);
    test_case!("(car (car (cons (cons 2 3) (cons 1 2))))", as_int, 2);
    test_case!("((lambda (x) x) 1)", as_int, 1);
    test_case!("((lambda (x y) (+ x y )) 1 2)", as_int, 3);
    test_case!("(define add4 (let ((x 4)) (lambda (y) (+ x y))))", as_str, "OK");
    test_case!("(begin 1 2)", as_int, 2);
    test_case!("((lambda (x) x) 5)", as_int, 5);
    test_case!("(let ((fu (lambda (x) (+ x 1)))) (fu 1))", as_int, 2);
    test_case!("((lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1)))))
               (lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1))))) 5)", as_int, 5is*4*3*2);
}

#[bench]
fn eval_bench(b: &mut Bencher) {
    b.iter(|| test_evaler());
}

#[bench]
fn lambda_bench(b: &mut Bencher) {
    b.iter(||
           test_case!("((lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1)))))
                      (lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1))))) 5)", as_int, 5is*4*3*2));
}
<commit_msg>remove clone<commit_after>use std::cell::RefCell;
use std::rc::Rc;

use ast::*;
use env::*;
use parser::*;
use test::Bencher;

pub struct Evaler {
    parser: Parser,
    env:    Rc<RefCell<Env>>
}

#[allow(dead_code)]
impl Evaler {
    pub fn new() -> Evaler {
        let env = Env::new();
        Evaler {
            parser: Parser::new(),
            env:    Rc::new(RefCell::new(env))
        }
    }

    pub fn eval(&mut self, code: String) -> Option<Expr> {
        self.parser.load(code);
        let mut res = None;
        loop {
            let exp = self.parser.read_exp();
            match exp {
                Some(_exp) => {
                    let r = self.eval_exp(_exp);
                    //r.print();
                    //println!("");
                    res = Some(r);
                },
                None => break
            }
        }
        res
    }

    fn eval_exp(&mut self, exp: Expr) -> Expr {
        if exp.is_self()   { return exp; }
        if exp.is_symbol() { return self.env.borrow().lookup(exp.as_str()).unwrap(); }
        if exp.is_quote()  { return exp.cdr().car(); }
        if exp.is_assign() { return self.eval_assign(exp); }
        if exp.is_def()    { return self.eval_def(exp); }
        if exp.is_begin()  { return self.eval_begin(exp); }
        if exp.is_if()     { return self.eval_if(exp); }
        if exp.is_lambda() { return self.eval_lambda(exp); }
        if exp.is_and()    { return self.eval_and(exp); }
        if exp.is_or()     { return self.eval_or(exp); }
        if exp.is_cond()   { return self.eval_cond(exp); }
        if exp.is_let()    { return self.eval_let(exp); }
        if exp.is_pair()   { return self.eval_app(exp); }
        Expr::Symbol(SymbolNode::new("OK"))
    }

    fn eval_assign(&mut self, exp: Expr) -> Expr {
        let var = exp.c("da");
        let val = self.eval_exp(exp.c("dda"));
        self.env.clone().borrow_mut().def_var(var.as_str(), val);
        Expr::Symbol(SymbolNode::new("OK"))
    }

    fn eval_def(&mut self, exp: Expr) -> Expr {
        let var = exp.def_var();
        let val = exp.def_val();
        let val = self.eval_exp(val);
        self.env.clone().borrow_mut().def_var(var.as_str(), val);
        Expr::Symbol(SymbolNode::new("OK"))
    }

    fn eval_if(&mut self, exp: Expr) -> Expr {
        let pred = exp.c("da");
        let blk_t = exp.c("dda");
        let blk_f = exp.c("ddd");
        let res = self.eval_exp(pred);
        if res.is_true() {
            self.eval_exp(blk_t)
        } else {
            if res.is_empty() {
                Expr::Bool(BoolNode::new(false))
            } else {
                self.eval_exp(blk_f.car())
            }
        }
    }

    fn eval_and(&mut self, exp: Expr) -> Expr {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return Expr::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_false() {
                return Expr::Bool(BoolNode::new(false));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_or(&mut self, exp: Expr) -> Expr {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return Expr::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_true() {
                return Expr::Bool(BoolNode::new(true));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_cond(&mut self, exp: Expr) -> Expr {
        let mut elems = exp.cdr().car();
        loop {
            if elems.is_empty() { break; }
            let cur = elems.car();
            let val = self.eval_exp(cur.clone());
            if val.is_true() || val == Expr::Symbol(SymbolNode::new("else")) {
                return self.eval_exp(cur.clone().cdr().car());
            }
            elems = elems.cdr();
        }
        Expr::Bool(BoolNode::new(true))
    }

    fn eval_let(&mut self, exp: Expr) -> Expr {
        fn bind_params(exp: Expr) -> Expr {
            if exp.is_empty() {
                Expr::Nil
            } else {
                Expr::Pair(PairNode::new(exp.c("aa"), bind_params(exp.cdr())))
            }
        }

        fn bind_args(exp: Expr) -> Expr {
            if exp.is_empty() {
                Expr::Nil
            } else {
                Expr::Pair(PairNode::new(exp.c("ada"), bind_args(exp.cdr())))
            }
        }

        let bindings = exp.c("da");
        let obj = Expr::Pair(PairNode::new(
            bind_params(bindings.clone()).make_lambda(exp.c("dd")),
            bind_args(bindings)));
        self.eval_exp(obj)
    }

    fn eval_begin(&mut self, exp: Expr) -> Expr {
        let mut _exp = exp.cdr();
        loop {
            if _exp.is_last() { break; }
            self.eval_exp(_exp.car());
            _exp = _exp.cdr();
        }
        self.eval_exp(_exp.car())
    }

    fn eval_values(&mut self, exprs: Expr) -> Expr {
        if exprs.is_empty() {
            Expr::Nil
        } else {
            let first = self.eval_exp(exprs.car());
            Expr::Pair(PairNode::new(first, self.eval_values(exprs.cdr())))
        }
    }

    fn eval_app(&mut self, expr: Expr) -> Expr {
        let _proc = self.eval_exp(expr.car());
        let _args = self.eval_values(expr.cdr());
        if _proc.is_proc() {
            let func = _proc.as_proc().func();
            return func(_args);
        } else {
            assert!(_proc.is_cproc());
            let _vars = _proc.params();
            self.env = self.env.clone().borrow_mut().extend(_vars, _args);
            let begin = Expr::Symbol(SymbolNode::new("begin"));
            let res = self.eval_exp(Expr::Pair(PairNode::new(begin, _proc.body())));
            self.env = self.env.clone().borrow_mut().parent().unwrap();
            res
        }
    }

    fn eval_lambda(&mut self, expr: Expr) -> Expr {
        // vars + body + env
        Expr::CompProc(CompProcNode::new(expr.c("da"), expr.c("dd"), self.env.clone()))
    }
}

macro_rules! test_case {
    ($test_str:expr, $expect_type:ident, $expect_val:expr) => { {
        let mut evaler = Evaler::new();
        let res = evaler.eval($test_str.to_string()).unwrap();
        if res.$expect_type() != $expect_val {
            assert!(false);
        }
    }}
}

#[test]
fn test_evaler() {
    test_case!("11", as_int, 11);
    test_case!("'a", as_str, "a");
    test_case!(r#""hello""#, as_str, "hello");
    test_case!("#t", as_bool, true);
    test_case!("(and #t #t)", as_bool, true);
    test_case!("(and #t #f)", as_bool, false);
    test_case!("(or #t #t)", as_bool, true);
    test_case!("(or #f #f)", as_bool, false);
    test_case!("(or #t #f)", as_bool, true);
    test_case!("(set! a 1)", as_str, "OK");
    test_case!("(integer? 1)", as_bool, true);
    test_case!("(boolean? #t)", as_bool, true);
    test_case!("(boolean? #f)", as_bool, true);
    test_case!("(integer? #t)", as_bool, false);
    test_case!("(+ 1 1)", as_int, 2);
    test_case!("(- 1 1)", as_int, 0);
    test_case!("(+ 1 1  1)", as_int, 3);
    test_case!("(+ 1 1 -1 -1)", as_int, 0);
    test_case!("(/ 2 1)", as_int, 2);
    test_case!("(* 2 2)", as_int, 4);
    test_case!("(> 2 1)", as_bool, true);
    test_case!("(> 1 2)", as_bool, false);
    test_case!("(> 1 1)", as_bool, false);
    test_case!("(- (+ 3 (* 8 5)) 1)", as_int, 42);
    test_case!("(eq? 1 1)", as_bool, true);
    test_case!("(eq? 1 2)", as_bool, false);
    test_case!("(eq? 1 #f)", as_bool, false);
    test_case!("(pair? '())", as_bool, true);
    test_case!("(> (+ 1 1) 0)", as_bool, true);
    test_case!("(if (> 1 0) 1 else 2)", as_int, 1);
    test_case!("(begin (set! a 1) a)", as_int, 1);
    test_case!("(let ((a 1)) (+ a 1))", as_int, 2);
    test_case!("(let ((a 1)) (> (+ a 1) 0))", as_bool, true);
    test_case!("(let ((a 1) (b 2)) (> a b))", as_bool, false);
    test_case!("(define (add a b) (+ a b))", as_str, "OK");
    test_case!("(cond ((eq? 1 1) 1) ((> 1 2) 2) ))", as_int, 1);
    test_case!("(begin (set! x 5) (set! x 4) (+ x 1))", as_int, 5);
    test_case!("(car '(1 2))", as_int, 1);
    test_case!("(car (cdr '(1 2)))", as_int, 2);
    test_case!("(car (cons 1 2))", as_int, 1);
    test_case!("(car (cons (pair? '(1)) pair? '()))", as_bool, true);
    test_case!("(car (cdr (cons 1 2)))", as_int, 2);
    test_case!("(car (car (cons (cons 2 3) (cons 1 2))))", as_int, 2);
    test_case!("((lambda (x) x) 1)", as_int, 1);
    test_case!("((lambda (x y) (+ x y )) 1 2)", as_int, 3);
    test_case!("(define add4 (let ((x 4)) (lambda (y) (+ x y))))", as_str, "OK");
    test_case!("(begin 1 2)", as_int, 2);
    test_case!("((lambda (x) x) 5)", as_int, 5);
    test_case!("(let ((fu (lambda (x) (+ x 1)))) (fu 1))", as_int, 2);
    test_case!("((lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1)))))
               (lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1))))) 5)", as_int, 5is*4*3*2);
}

#[bench]
fn eval_bench(b: &mut Bencher) {
    b.iter(|| test_evaler());
}

#[bench]
fn lambda_bench(b: &mut Bencher) {
    b.iter(||
           test_case!("((lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1)))))
                      (lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1))))) 5)", as_int, 5is*4*3*2));
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

/// A game state
pub trait GameState {
    /// constructs the initial game state
    fn new() -> Self;
}

/// An game action
pub trait Action{
    /// The states these actions modify
    type GameState : GameState;

    /// Tests if the action is aplicable to the given state
    fn test(self : &Self, state : &Self::GameState) -> bool;

    /// Executes the action on the given state
    fn execute(self : &Self, state : &mut Self::GameState);
}

/// An history item for use in the game tree
#[derive(Debug)]
struct HistoryItem<SomeAction>
    where SomeAction : Action
{
    /// The path to the parent item
    parent : Path,

    /// An action to be executed after the parent iten
    action : SomeAction,
}

/// The game tree
///
/// A game is a tree of history items representing actions.
/// This allows for easy undo/redo. Represents the tree
/// as a flat array of items interlinked by parent-ids.
#[derive(Debug)]
pub struct Game<SomeAction>
    where SomeAction : Action
{
    data : Vec<HistoryItem<SomeAction>>
}

/// The path to one game tree item
///
/// Stores the path as an id to the parent item.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Path {
    /// There is no parent (we mean the trees root)
    Empty,
    /// The parents id
    HistoryItemId(usize)
}

impl<SomeAction> Game<SomeAction>
    where SomeAction : Action {
    /// Creates a new game
    pub fn new() -> Self {
        Game {
            data: Vec::new()
        }
    }

    /// Inserts the action after parent
    ///
    /// Does reconstruct the game state at path and applies action
    pub fn insert(self : &mut Self, parent : &Path, action : SomeAction) -> Path {
        let state = self.get_state(parent);

        if action.test(&state) {
            self.data.push(HistoryItem{
                parent: parent.clone(),
                action: action
            });

            Path::HistoryItemId(self.data.len() -1)
        } else {
            Path::Empty
        }
    }

    /// Returns the state at the given path
    ///
    /// Does reapply all previous actions
    pub fn get_state(self : &Self, at : &Path) -> SomeAction::GameState {
        let mut state = SomeAction::GameState::new();

        if let &Path::HistoryItemId(up_to) = at  {
            let mut path = Vec::<usize>::new();
            let mut curr = up_to;

            while let Path::HistoryItemId(next) = self.data[curr].parent {
                path.push(curr);
                curr = next;
            }

            path.push(curr);

            for idx in path.iter().rev() {
                self.data[*idx].action.execute(&mut state);
            }
        }

        state
    }
}

#[cfg(test)]
mod test{
    use super::{Game, GameState, Action, Path};

    struct SimpleGameState{
        acc : i32
    }

    impl GameState for SimpleGameState {
        fn new() -> SimpleGameState {
            SimpleGameState{
                acc: 0
            }
        }
    }

    enum SimpleAction{
        Inc,
        Dec
    }

    impl Action for SimpleAction{
        type GameState = SimpleGameState;

        fn test(self : &Self, state : &SimpleGameState) -> bool {
            match self {
                &SimpleAction::Inc => true,
                &SimpleAction::Dec => {
                    state.acc > 0
                }
            }
        }

        fn execute(self : &Self, state : &mut SimpleGameState) {
            match self {
                &SimpleAction::Inc => state.acc += 1,
                &SimpleAction::Dec => state.acc -= 1
            }
        }
    }

    #[test]
    fn tree() {
        let mut g = Game::<SimpleAction>::new();
        let root_cursor = Path::Empty;

        let parent_cursor = g.insert(&root_cursor, SimpleAction::Inc);
        assert!(g.get_state(&parent_cursor).acc == 1);

        let invalid_cursor = g.insert(&root_cursor, SimpleAction::Dec);
        assert!(invalid_cursor == Path::Empty);

        let child_0 = g.insert(&parent_cursor, SimpleAction::Dec);
        assert!(child_0 != Path::Empty);
        assert!(g.get_state(&child_0).acc == 0);

        let child_1 = g.insert(&parent_cursor, SimpleAction::Inc);
        assert!(child_1 != Path::Empty);
        assert!(g.get_state(&child_1).acc == 2);
    }
}
<commit_msg>Typo in doc<commit_after>#![allow(dead_code)]

/// A game state
pub trait GameState {
    /// constructs the initial game state
    fn new() -> Self;
}

/// An game action
pub trait Action{
    /// The states these actions modify
    type GameState : GameState;

    /// Tests if the action is applicable to the given state
    fn test(self : &Self, state : &Self::GameState) -> bool;

    /// Executes the action on the given state
    fn execute(self : &Self, state : &mut Self::GameState);
}

/// An history item for use in the game tree
#[derive(Debug)]
struct HistoryItem<SomeAction>
    where SomeAction : Action
{
    /// The path to the parent item
    parent : Path,

    /// An action to be executed after the parent iten
    action : SomeAction,
}

/// The game tree
///
/// A game is a tree of history items representing actions.
/// This allows for easy undo/redo. Represents the tree
/// as a flat array of items interlinked by parent-ids.
#[derive(Debug)]
pub struct Game<SomeAction>
    where SomeAction : Action
{
    data : Vec<HistoryItem<SomeAction>>
}

/// The path to one game tree item
///
/// Stores the path as an id to the parent item.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Path {
    /// There is no parent (we mean the trees root)
    Empty,
    /// The parents id
    HistoryItemId(usize)
}

impl<SomeAction> Game<SomeAction>
    where SomeAction : Action {
    /// Creates a new game
    pub fn new() -> Self {
        Game {
            data: Vec::new()
        }
    }

    /// Inserts the action after parent
    ///
    /// Does reconstruct the game state at path and applies action
    pub fn insert(self : &mut Self, parent : &Path, action : SomeAction) -> Path {
        let state = self.get_state(parent);

        if action.test(&state) {
            self.data.push(HistoryItem{
                parent: parent.clone(),
                action: action
            });

            Path::HistoryItemId(self.data.len() -1)
        } else {
            Path::Empty
        }
    }

    /// Returns the state at the given path
    ///
    /// Does reapply all previous actions
    pub fn get_state(self : &Self, at : &Path) -> SomeAction::GameState {
        let mut state = SomeAction::GameState::new();

        if let &Path::HistoryItemId(up_to) = at  {
            let mut path = Vec::<usize>::new();
            let mut curr = up_to;

            while let Path::HistoryItemId(next) = self.data[curr].parent {
                path.push(curr);
                curr = next;
            }

            path.push(curr);

            for idx in path.iter().rev() {
                self.data[*idx].action.execute(&mut state);
            }
        }

        state
    }
}

#[cfg(test)]
mod test{
    use super::{Game, GameState, Action, Path};

    struct SimpleGameState{
        acc : i32
    }

    impl GameState for SimpleGameState {
        fn new() -> SimpleGameState {
            SimpleGameState{
                acc: 0
            }
        }
    }

    enum SimpleAction{
        Inc,
        Dec
    }

    impl Action for SimpleAction{
        type GameState = SimpleGameState;

        fn test(self : &Self, state : &SimpleGameState) -> bool {
            match self {
                &SimpleAction::Inc => true,
                &SimpleAction::Dec => {
                    state.acc > 0
                }
            }
        }

        fn execute(self : &Self, state : &mut SimpleGameState) {
            match self {
                &SimpleAction::Inc => state.acc += 1,
                &SimpleAction::Dec => state.acc -= 1
            }
        }
    }

    #[test]
    fn tree() {
        let mut g = Game::<SimpleAction>::new();
        let root_cursor = Path::Empty;

        let parent_cursor = g.insert(&root_cursor, SimpleAction::Inc);
        assert!(g.get_state(&parent_cursor).acc == 1);

        let invalid_cursor = g.insert(&root_cursor, SimpleAction::Dec);
        assert!(invalid_cursor == Path::Empty);

        let child_0 = g.insert(&parent_cursor, SimpleAction::Dec);
        assert!(child_0 != Path::Empty);
        assert!(g.get_state(&child_0).acc == 0);

        let child_1 = g.insert(&parent_cursor, SimpleAction::Inc);
        assert!(child_1 != Path::Empty);
        assert!(g.get_state(&child_1).acc == 2);
    }
}
<|endoftext|>


<commit_before>use range::Range;

use {
    Whitespace,
    Token,
    UntilAnyOrWhitespace,
    Text,
    Number,
    Parameter,
    MetaReader,
    ParseError,
    Select,
    Optional,
};

/// A rule describes how some section of a document should be parsed.
pub enum Rule {
    /// Read whitespace.
    Whitespace(Whitespace),
    /// Match against a token.
    Token(Token),
    /// Read until any or whitespace.
    UntilAnyOrWhitespace(UntilAnyOrWhitespace),
    /// Read text.
    Text(Text),
    /// Read number.
    Number(Number),
    /// Select one of the sub rules.
    /// If the first one does not succeed, try another and so on.
    /// If all sub rules fail, then the rule fails.
    Select(Select),
    /// Read parameter.
    Parameter(Parameter),
    /// Read optional.
    Optional(Optional),
}

impl Rule {
    /// Parses rule.
    pub fn parse<M>(
        &self,
        meta_reader: &mut M,
        state: &M::State,
        chars: &[char],
        offset: usize
    ) -> Result<(Range, M::State), (Range, ParseError)>
        where M: MetaReader
    {
        match self {
            &Rule::Whitespace(ref w) => {
                w.parse(chars, offset).map(|r| (r, state.clone()))
            }
            &Rule::Token(ref t) => {
                t.parse(meta_reader, state, chars, offset)
            }
            &Rule::UntilAnyOrWhitespace(ref u) => {
                u.parse(meta_reader, state, chars, offset)
            }
            &Rule::Text(ref t) => {
                t.parse(meta_reader, state, chars, offset)
            }
            &Rule::Number(ref n) => {
                n.parse(meta_reader, state, chars, offset)
            }
            &Rule::Select(ref s) => {
                s.parse(meta_reader, state, chars, offset)
            }
            &Rule::Parameter(ref p) => {
                p.parse(meta_reader, state, chars, offset)
            }
            &Rule::Optional(ref o) => {
                Ok(o.parse(meta_reader, state, chars, offset))
            }
        }
    }
}
<commit_msg>Added `Rule::Sequence`<commit_after>use range::Range;

use {
    Whitespace,
    Token,
    UntilAnyOrWhitespace,
    Text,
    Number,
    Parameter,
    MetaReader,
    ParseError,
    Select,
    Sequence,
    Optional,
};

/// A rule describes how some section of a document should be parsed.
pub enum Rule {
    /// Read whitespace.
    Whitespace(Whitespace),
    /// Match against a token.
    Token(Token),
    /// Read until any or whitespace.
    UntilAnyOrWhitespace(UntilAnyOrWhitespace),
    /// Read text.
    Text(Text),
    /// Read number.
    Number(Number),
    /// Select one of the sub rules.
    /// If the first one does not succeed, try another and so on.
    /// If all sub rules fail, then the rule fails.
    Select(Select),
    /// Run each sub rule in sequence.
    /// If any sub rule fails, the rule fails.
    Sequence(Sequence),
    /// Read parameter.
    Parameter(Parameter),
    /// Read optional.
    Optional(Optional),
}

impl Rule {
    /// Parses rule.
    pub fn parse<M>(
        &self,
        meta_reader: &mut M,
        state: &M::State,
        chars: &[char],
        offset: usize
    ) -> Result<(Range, M::State), (Range, ParseError)>
        where M: MetaReader
    {
        match self {
            &Rule::Whitespace(ref w) => {
                w.parse(chars, offset).map(|r| (r, state.clone()))
            }
            &Rule::Token(ref t) => {
                t.parse(meta_reader, state, chars, offset)
            }
            &Rule::UntilAnyOrWhitespace(ref u) => {
                u.parse(meta_reader, state, chars, offset)
            }
            &Rule::Text(ref t) => {
                t.parse(meta_reader, state, chars, offset)
            }
            &Rule::Number(ref n) => {
                n.parse(meta_reader, state, chars, offset)
            }
            &Rule::Select(ref s) => {
                s.parse(meta_reader, state, chars, offset)
            }
            &Rule::Sequence(ref s) => {
                s.parse(meta_reader, state, chars, offset)
            }
            &Rule::Parameter(ref p) => {
                p.parse(meta_reader, state, chars, offset)
            }
            &Rule::Optional(ref o) => {
                Ok(o.parse(meta_reader, state, chars, offset))
            }
        }
    }
}
<|endoftext|>