<commit_before>
use std::io;
use std::clone::Clone;
use std::slice::Iter;

use linked_hash_map::LinkedHashMap;

use parser::ast::*;
use parser::util::*;
use processing::structs::*;
use processing::scope::*;
use output::client_ops_stream_writer::*;
use output::client_misc::*;

#[derive(Debug)]
pub struct BlockDefinition {
    pub block_id: String,
    pub ops: Vec<ElementOp>
}
pub type BlockMap = LinkedHashMap<String, BlockDefinition>;

pub struct ElementOpsWriter<'input: 'scope, 'scope> {
    pub doc: &'input DocumentState<'input>,
    pub stream_writer: &'scope mut ElementOpsStreamWriter,
    base_scope: ElementOpScope,
    pub scopes: LinkedHashMap<String, ElementOpScope>,
    pub blocks: BlockMap,
    pub events_vec: EventsVec,
    component_instances: Vec<(String, String)>,
    pub cur_block_id: Option<String>
}

impl<'input: 'scope, 'scope> ElementOpsWriter<'input, 'scope> {

    fn scope(&mut self) -> ElementOpScope {
        self.scopes.back().map_or(self.base_scope.clone(), |s| s.1.clone())
    }

    fn push_scope(&mut self, scope: ElementOpScope) {
        let scope_id = scope.0.complete_element_key();
        self.scopes.insert(scope_id, scope);
    }

    fn push_scope_as(&mut self, scope: ElementOpScope, scope_id: &str) {
        self.scopes.insert(scope_id.to_owned(), scope);
    }

    fn pop_scope(&mut self) { self.scopes.pop_back(); }

    pub fn with_doc(doc: &'input DocumentState<'input>, stream_writer: &'scope mut ElementOpsStreamWriter, base_scope: ElementOpScope) -> Self {
        ElementOpsWriter {
            doc: doc,
            stream_writer: stream_writer,
            base_scope: base_scope,
            scopes: Default::default(),
            blocks: Default::default(),
            events_vec: Default::default(),
            component_instances: Default::default(),
            cur_block_id: None
        }
    }

    pub fn events_iter(&self) -> Iter<EventsItem> {
        self.events_vec.iter()
    }

    pub fn component_instances_iter(&self) -> Iter<(String, String)> {
        self.component_instances.iter()
    }

    #[inline]
    fn write_loop_item(&mut self, w: &mut io::Write, doc: &'input DocumentState, item_expr: &ExprValue, ele: Option<&str>, element_ty: Option<&VarType>, block_id: &str, output_component_contents: bool) -> Result {
        let mut scope = self.scope();
        scope.0.append_key(block_id);

        let complete_key = scope.0.complete_element_key();

        if let Some(ele_key) = ele {
            scope.add_loop_var_with_value(ele_key, item_expr);

            if output_component_contents {
                scope.0.set_index(0);
            } else {
                let sym_expr = ExprValue::SymbolReference(Symbol::loop_idx("foridx", block_id));
                scope.0.set_prefix_expr(&sym_expr);
            };
        };

        let block_ops = self.blocks.get(block_id)
            .map(|block| block.ops.clone());

        if let Some(ref block_ops) = block_ops {
            let mut scope = scope.clone();

            // Push scope
            let scope_id = scope.0.complete_element_key();
            self.scopes.insert(complete_key, scope.clone());

            // Output ops
            self.write_ops_content(w, block_ops.iter(), doc, output_component_contents)?;

            // Pop scope
            self.scopes.pop_back();
        };
        Ok(())
    }

    #[inline]
    fn invoke_component_with_props(&mut self, w: &mut io::Write, doc: &'input DocumentState, comp: &Component, props: Option<Iter<Prop>>, output_component_contents: bool) -> Result {
        let mut scope = self.scope();

        let prop_values = props.map(|p| map_props_using_scope(p, &scope));

        // TODO: Restore props from Component object

        // let scope_key = allocate_element_key();
        // let scope_id = scope.0.key_prefix(&scope_key);
        // self.scopes.insert(scope_id, scope.clone());

        if let Some(ref ops) = comp.ops {
            let mut events_vec: EventsVec = Default::default();
            self.write_ops_content(w, ops.iter(), doc, output_component_contents)?;
        };
        Ok(())
    }

    #[inline]
    #[allow(dead_code)]
    pub fn write_single_component_instance(&mut self, w: &mut io::Write, op: &ElementOp, doc: &'input DocumentState, comp: &Component, component_key: &str, props: Option<Iter<Prop>>, lens: Option<&LensExprType>, loop_iteration: Option<(&Symbol, i32)>, output_component_contents: bool) -> Result {
        let mut scope = self.scope();

        if output_component_contents {
            // Add iteration
            if let Some(ref li) = loop_iteration {
                scope.0.set_index(li.1);
            };

            // Push scope
            self.push_scope(scope.clone());

            let complete_key = scope.0.complete_element_key();

            // OpenS
            // let props_iter = props.as_ref().map(|s| s.clone());
            self.stream_writer.write_op_element_instance_component_open(w, op, doc, &scope, &comp, props.clone(), lens)?;

            // let props_iter = props.as_ref().map(|s| s.clone());
            self.invoke_component_with_props(w, doc, comp, props.clone(), true)?;

            // Close
            self.stream_writer.write_op_element_instance_component_close(w, op, doc, &scope, &comp)?;

            // DISABLE attempt to look up event bindings and write out
            // using the component_instances vector
            // // if let Some(ref events_vec) = events_vec {
            //     if let Some(ref events) = comp.events {
            //         for event in events {
            //             let mut event = event.clone();
            //             event.0 = format!("{}.{}", complete_key, &event.0);
            //             self.events_vec.push(event);
            //         }
            //     };
            // // };

            self.component_instances.push((complete_key.to_owned(), comp.name.to_owned()));

            // Pop scope
            self.pop_scope();
        } else {
            // let scope_key = {
            //     let mut scope = scope.clone();
            //     scope.0.append_key(component_key);
            //     scope.0.complete_element_key()
            // };

            let mut scope = scope.clone();
            // let props = props.as_ref().map(|p| map_prop_references(p.iter(), &scope));

            scope.0.clear_key();
            // scope.0.append_key(component_key);
            if let Some(ref li) = loop_iteration {
                let sym_expr = ExprValue::SymbolReference(li.0.clone());
                scope.0.set_prefix_expr(&sym_expr);
            };

            // let key_expr = ExprValue::LiteralString(format!("{}", component_key));
            // let prefix_expr = scope.0.make_prefix_expr(&key_expr, None);

            // self.scopes.insert(scope_key.to_owned(), scope.clone());

            // OpenS
            // let props_iter = props.as_ref().map(|s| s.clone());
            self.stream_writer.write_op_element_instance_component_open(w, op, doc, &scope, &comp, props.clone(), lens)?;

            // Close
            self.stream_writer.write_op_element_instance_component_close(w, op, doc, &scope, &comp)?;

            // self.scopes.pop_back();
        };

        Ok(())
    }

    #[inline]
    #[allow(unused_variables)]
    pub fn write_ops_content<'op>(&mut self, w: &mut io::Write, ops: Iter<'op, ElementOp>, doc: &'input DocumentState, output_component_contents: bool) -> Result {
        for op in ops {
            let mut scope = self.scope();

            if output_component_contents {
                if let &ElementOp::EndBlock(..) = op {
                    self.pop_scope();
                    self.cur_block_id = None;
                    continue;
                };

                if let Some(ref cur_block_id) = self.cur_block_id {
                    let block = self.blocks.entry(cur_block_id.to_owned())
                        .or_insert_with(|| BlockDefinition { block_id: cur_block_id.clone(), ops: Default::default() });

                    block.ops.push(op.clone());
                    continue;
                };
            };

            let is_void = if let &ElementOp::ElementVoid(..) = op { true } else { false };

            match op {
                &ElementOp::ElementOpen(ref element_tag, ref element_key, ref props, ref events, ref value_binding) |
                &ElementOp::ElementVoid(ref element_tag, ref element_key, ref props, ref events, ref value_binding) => {
                    let mut scope = scope.clone();

                    let props = if output_component_contents {
                        props.as_ref().map(|p| map_props_using_scope(p.iter(), &scope))
                    } else {
                        props.as_ref().map(|p| map_prop_references(p.iter(), &scope))
                    };

                    // let prop_list = prop_list.as_ref().map(|s| s.iter().map(|s| &s));

                    let element_key = element_key.as_ref().map_or("null", |s| s);
                    let complete_key = scope.0.make_complete_element_key_with(element_key);
                    self.push_scope_as(scope.clone(), &complete_key);

                    let events = events.as_ref().map(|events| events.iter());
                    let value_binding = value_binding.as_ref().map(|s| s.clone());

                    self.stream_writer.write_op_element(w, op, doc, &scope, &complete_key, element_tag, is_void, props.as_ref().map(|s| s.iter()), events, value_binding)?;
                    if is_void {
                        // Pop scope for self closing, this fixes issue with ElementVoid which
                        // was not being emitted previously by the parser/processor code.
                        self.pop_scope();
                    };
                }
                &ElementOp::ElementClose(ref element_tag) => {
                    // let scope = self.scopes.back().map_or(scope.clone(), |s| s.1.clone());

                    self.stream_writer.write_op_element_close(w, op, doc, &scope, element_tag)?;
                    self.pop_scope();
                }
                &ElementOp::WriteValue(ref expr, ref value_key) => {
                    // let scope = self.scopes.back().map_or(scope.clone(), |s| s.1.clone());

                    let value_key = value_key.as_ref().map_or("null", |s| s);
                    let complete_key = scope.0.make_complete_element_key_with(value_key);
                    self.stream_writer.write_op_element_value(w, op, doc, &scope, expr, &complete_key)?;
                }
                &ElementOp::InstanceComponent(ref component_ty,
                                            ref component_key,
                                            ref prop_list,
                                            ref lens) => {
                    let mut scope = scope.clone();
                    // let mut prop_list = prop_list.clone();

                    let mut props = if output_component_contents {
                        prop_list.as_ref().map(|p| map_prop_list_using_scope(p.iter(), &scope))
                    } else {
                        prop_list.as_ref().map(|p| map_prop_list_references(p.iter(), &scope))
                    };

                    let component_key = component_key.as_ref().map_or("null", |s| s);

                    let mut write_single = true;

                    if output_component_contents {
                        // Add component key to base key
                        scope.0.append_base_key(&format!("c_{}", component_key));
                        // scope.0.append_key(&s);
                        self.push_scope(scope.clone());

                    }

                    let comp = doc.comp_map.get(component_ty.as_str());
                    if let Some(ref comp) = comp {
                        match lens {
                            &Some(LensExprType::ForLens(ref ele_key, ref coll_sym)) => {
                                let coll_expr = ExprValue::SymbolReference(coll_sym.clone());
                                let coll_expr = reduce_expr(&coll_expr, doc, &scope);

                                if let &Some(ref ele_key) = ele_key {
                                    let mut scope = scope.clone();
                                    scope.1.add_param(ele_key);

                                    if output_component_contents {
                                        if let Some(ExprValue::LiteralArray(Some(ref items))) = coll_expr {
                                            write_single = false;

                                            for (item_idx, item_expr) in items.iter().enumerate() {
                                                let prefix_sym = Symbol::param("key_prefix");
                                                if let Some(ref mut props) = props {
                                                    props.push((ele_key.to_owned(), Some(item_expr.to_owned())));
                                                };
                                                self.write_single_component_instance(w, op, doc, comp, &component_key, props.as_ref().map(|p| p.iter()), lens.as_ref(), Some((&prefix_sym, item_idx as i32)), output_component_contents)?;
                                            };
                                        };
                                    } else {
                                        self.write_single_component_instance(w, op, doc, comp, &component_key, props.as_ref().map(|p| p.iter()), lens.as_ref(), None, output_component_contents)?;
                                   };
                                };
                            }

                            &Some(LensExprType::GetLens(ref sym)) => {
                            }

                            _ => {}
                        };

                        if write_single {
                            self.write_single_component_instance(w, op, doc, comp, &component_key, props.as_ref().map(|p| p.iter()), None, None, output_component_contents)?;
                        };

                        if output_component_contents {
                            self.pop_scope();
                        }
                    }
                }

                &ElementOp::StartBlock(ref block_id) => {
                    let mut scope = self.scope();

                    let complete_key = scope.0.complete_element_key();

                    if output_component_contents {
                        // Collect blocks to render
                        self.cur_block_id = Some(block_id.to_owned());
                    } else {
                        // Write function header
                        let loopidx_expr = ExprValue::SymbolReference(Symbol::loop_idx("foridx", block_id));
                        scope.0.set_prefix_expr(&loopidx_expr);
                        self.stream_writer.write_op_element_start_block(w, op, doc, &scope, block_id)?;
                    };

                    self.push_scope(scope);
                }

                &ElementOp::EndBlock(ref block_id) => {
                    if output_component_contents {
                        // Finish current block
                        self.cur_block_id = None;
                    } else {
                        self.scopes.pop_back();
                        let scope = self.scopes.back().map_or(scope.clone(), |s| s.1.clone());

                        self.stream_writer.write_op_element_end_block(w, op, doc, &scope, block_id)?;
                    };
                }

                &ElementOp::MapCollection(ref block_id, ref ele, ref coll_expr) => {
                    if output_component_contents {
                        let mut scope = self.scope();

                        let has_block = self.blocks.contains_key(block_id);
                        if has_block {
                            let ele = ele.as_ref().map(|e| e.as_str());

                            let coll_expr = reduce_expr(coll_expr, doc, &scope);

                            if let Some(ExprValue::LiteralArray(Some(ref items))) = coll_expr {
                                for item_expr in items {
                                    self.write_loop_item(w, doc, item_expr, ele, None, block_id, output_component_contents)?;
                                };
                            };
                        };
                    } else {
                        let forvar_default = &format!("__forvar_{}", block_id);
                        let scope_id = format!("{}_map", block_id);

                        // Map to block
                        self.stream_writer.write_op_element_map_collection_to_block(w, op, doc, &scope, coll_expr, block_id)?;
                    };
                }
            }
        }

        Ok(())
    }
}<commit_msg>Fix component params<commit_after>
use std::io;
use std::clone::Clone;
use std::slice::Iter;

use linked_hash_map::LinkedHashMap;

use parser::ast::*;
use parser::util::*;
use processing::structs::*;
use processing::scope::*;
use output::client_ops_stream_writer::*;
use output::client_misc::*;

#[derive(Debug)]
pub struct BlockDefinition {
    pub block_id: String,
    pub ops: Vec<ElementOp>
}
pub type BlockMap = LinkedHashMap<String, BlockDefinition>;

pub struct ElementOpsWriter<'input: 'scope, 'scope> {
    pub doc: &'input DocumentState<'input>,
    pub stream_writer: &'scope mut ElementOpsStreamWriter,
    base_scope: ElementOpScope,
    pub scopes: LinkedHashMap<String, ElementOpScope>,
    pub blocks: BlockMap,
    pub events_vec: EventsVec,
    component_instances: Vec<(String, String)>,
    pub cur_block_id: Option<String>
}

impl<'input: 'scope, 'scope> ElementOpsWriter<'input, 'scope> {

    fn scope(&mut self) -> ElementOpScope {
        self.scopes.back().map_or(self.base_scope.clone(), |s| s.1.clone())
    }

    fn push_scope(&mut self, scope: ElementOpScope) {
        let scope_id = scope.0.complete_element_key();
        self.scopes.insert(scope_id, scope);
    }

    fn push_scope_as(&mut self, scope: ElementOpScope, scope_id: &str) {
        self.scopes.insert(scope_id.to_owned(), scope);
    }

    fn pop_scope(&mut self) { self.scopes.pop_back(); }

    pub fn with_doc(doc: &'input DocumentState<'input>, stream_writer: &'scope mut ElementOpsStreamWriter, base_scope: ElementOpScope) -> Self {
        ElementOpsWriter {
            doc: doc,
            stream_writer: stream_writer,
            base_scope: base_scope,
            scopes: Default::default(),
            blocks: Default::default(),
            events_vec: Default::default(),
            component_instances: Default::default(),
            cur_block_id: None
        }
    }

    pub fn events_iter(&self) -> Iter<EventsItem> {
        self.events_vec.iter()
    }

    pub fn component_instances_iter(&self) -> Iter<(String, String)> {
        self.component_instances.iter()
    }

    #[inline]
    fn write_loop_item(&mut self, w: &mut io::Write, doc: &'input DocumentState, item_expr: &ExprValue, ele: Option<&str>, element_ty: Option<&VarType>, block_id: &str, output_component_contents: bool) -> Result {
        let mut scope = self.scope();
        scope.0.append_key(block_id);

        let complete_key = scope.0.complete_element_key();

        if let Some(ele_key) = ele {
            scope.add_loop_var_with_value(ele_key, item_expr);

            if output_component_contents {
                scope.0.set_index(0);
            } else {
                let sym_expr = ExprValue::SymbolReference(Symbol::loop_idx("foridx", block_id));
                scope.0.set_prefix_expr(&sym_expr);
            };
        };

        let block_ops = self.blocks.get(block_id)
            .map(|block| block.ops.clone());

        if let Some(ref block_ops) = block_ops {
            // Push scope
            self.push_scope_as(scope, &complete_key);

            // Output ops
            self.write_ops_content(w, block_ops.iter(), doc, output_component_contents)?;

            // Pop scope
            self.pop_scope();
        };
        Ok(())
    }

    #[inline]
    fn invoke_component_with_props(&mut self, w: &mut io::Write, doc: &'input DocumentState, comp: &Component, props: Option<Iter<Prop>>, output_component_contents: bool) -> Result {
        let mut scope = self.scope();

        if let Some(props) = props {
            for prop in props {
                if let Some(ref expr) = prop.1 {
                    scope.2.add_prop_with_value(&prop.0, expr);
                };
            }
        };
        // TODO: Merge default props from Component object
        self.push_scope(scope);

        if let Some(ref ops) = comp.ops {
            self.write_ops_content(w, ops.iter(), doc, output_component_contents)?;
        };
        Ok(())
    }

    #[inline]
    #[allow(dead_code)]
    pub fn write_single_component_instance(&mut self, w: &mut io::Write, op: &ElementOp, doc: &'input DocumentState, comp: &Component, component_key: &str, props: Option<Iter<Prop>>, lens: Option<&LensExprType>, loop_iteration: Option<(&Symbol, i32)>, output_component_contents: bool) -> Result {
        let mut scope = self.scope();

        if output_component_contents {
            // Add iteration
            if let Some(ref li) = loop_iteration {
                scope.0.set_index(li.1);
            };

            // Push scope
            self.push_scope(scope.clone());

            let complete_key = scope.0.complete_element_key();

            // OpenS
            // let props_iter = props.as_ref().map(|s| s.clone());
            self.stream_writer.write_op_element_instance_component_open(w, op, doc, &scope, &comp, props.clone(), lens)?;

            // let props_iter = props.as_ref().map(|s| s.clone());
            self.invoke_component_with_props(w, doc, comp, props.clone(), true)?;

            // Close
            self.stream_writer.write_op_element_instance_component_close(w, op, doc, &scope, &comp)?;

            // DISABLE attempt to look up event bindings and write out
            // using the component_instances vector
            // // if let Some(ref events_vec) = events_vec {
            //     if let Some(ref events) = comp.events {
            //         for event in events {
            //             let mut event = event.clone();
            //             event.0 = format!("{}.{}", complete_key, &event.0);
            //             self.events_vec.push(event);
            //         }
            //     };
            // // };

            self.component_instances.push((complete_key.to_owned(), comp.name.to_owned()));

            // Pop scope
            self.pop_scope();
        } else {
            // let scope_key = {
            //     let mut scope = scope.clone();
            //     scope.0.append_key(component_key);
            //     scope.0.complete_element_key()
            // };

            let mut scope = scope.clone();
            // let props = props.as_ref().map(|p| map_prop_references(p.iter(), &scope));

            scope.0.clear_key();
            // scope.0.append_key(component_key);
            if let Some(ref li) = loop_iteration {
                let sym_expr = ExprValue::SymbolReference(li.0.clone());
                scope.0.set_prefix_expr(&sym_expr);
            };

            // let key_expr = ExprValue::LiteralString(format!("{}", component_key));
            // let prefix_expr = scope.0.make_prefix_expr(&key_expr, None);

            // self.scopes.insert(scope_key.to_owned(), scope.clone());

            // OpenS
            // let props_iter = props.as_ref().map(|s| s.clone());
            self.stream_writer.write_op_element_instance_component_open(w, op, doc, &scope, &comp, props.clone(), lens)?;

            // Close
            self.stream_writer.write_op_element_instance_component_close(w, op, doc, &scope, &comp)?;

            // self.scopes.pop_back();
        };

        Ok(())
    }

    #[inline]
    #[allow(unused_variables)]
    pub fn write_ops_content<'op>(&mut self, w: &mut io::Write, ops: Iter<'op, ElementOp>, doc: &'input DocumentState, output_component_contents: bool) -> Result {
        for op in ops {
            let mut scope = self.scope();

            if output_component_contents {
                if let &ElementOp::EndBlock(..) = op {
                    self.pop_scope();
                    self.cur_block_id = None;
                    continue;
                };

                if let Some(ref cur_block_id) = self.cur_block_id {
                    let block = self.blocks.entry(cur_block_id.to_owned())
                        .or_insert_with(|| BlockDefinition { block_id: cur_block_id.clone(), ops: Default::default() });

                    block.ops.push(op.clone());
                    continue;
                };
            };

            let is_void = if let &ElementOp::ElementVoid(..) = op { true } else { false };

            match op {
                &ElementOp::ElementOpen(ref element_tag, ref element_key, ref props, ref events, ref value_binding) |
                &ElementOp::ElementVoid(ref element_tag, ref element_key, ref props, ref events, ref value_binding) => {
                    let mut scope = scope.clone();

                    let props = if output_component_contents {
                        props.as_ref().map(|p| map_props_using_scope(p.iter(), &scope))
                    } else {
                        props.as_ref().map(|p| map_prop_references(p.iter(), &scope))
                    };

                    // let prop_list = prop_list.as_ref().map(|s| s.iter().map(|s| &s));

                    let element_key = element_key.as_ref().map_or("null", |s| s);
                    let complete_key = scope.0.make_complete_element_key_with(element_key);
                    self.push_scope_as(scope.clone(), &complete_key);

                    let events = events.as_ref().map(|events| events.iter());
                    let value_binding = value_binding.as_ref().map(|s| s.clone());

                    self.stream_writer.write_op_element(w, op, doc, &scope, &complete_key, element_tag, is_void, props.as_ref().map(|s| s.iter()), events, value_binding)?;
                    if is_void {
                        // Pop scope for self closing, this fixes issue with ElementVoid which
                        // was not being emitted previously by the parser/processor code.
                        self.pop_scope();
                    };
                }
                &ElementOp::ElementClose(ref element_tag) => {
                    // let scope = self.scopes.back().map_or(scope.clone(), |s| s.1.clone());

                    self.stream_writer.write_op_element_close(w, op, doc, &scope, element_tag)?;
                    self.pop_scope();
                }
                &ElementOp::WriteValue(ref expr, ref value_key) => {
                    // let scope = self.scopes.back().map_or(scope.clone(), |s| s.1.clone());

                    let value_key = value_key.as_ref().map_or("null", |s| s);
                    let complete_key = scope.0.make_complete_element_key_with(value_key);
                    self.stream_writer.write_op_element_value(w, op, doc, &scope, expr, &complete_key)?;
                }
                &ElementOp::InstanceComponent(ref component_ty,
                                            ref component_key,
                                            ref prop_list,
                                            ref lens) => {
                    let mut scope = scope.clone();
                    // let mut prop_list = prop_list.clone();

                    let mut props = if output_component_contents {
                        prop_list.as_ref().map(|p| map_prop_list_using_scope(p.iter(), &scope))
                    } else {
                        prop_list.as_ref().map(|p| map_prop_list_references(p.iter(), &scope))
                    };

                    let component_key = component_key.as_ref().map_or("null", |s| s);

                    let mut write_single = true;

                    if output_component_contents {
                        // Add component key to base key
                        scope.0.append_base_key(&format!("c_{}", component_key));
                        // scope.0.append_key(&s);
                        self.push_scope(scope.clone());

                    }

                    let comp = doc.comp_map.get(component_ty.as_str());
                    if let Some(ref comp) = comp {
                        match lens {
                            &Some(LensExprType::ForLens(ref ele_key, ref coll_sym)) => {
                                let coll_expr = ExprValue::SymbolReference(coll_sym.clone());
                                let coll_expr = reduce_expr(&coll_expr, doc, &scope);

                                if let &Some(ref ele_key) = ele_key {
                                    let mut scope = scope.clone();
                                    scope.1.add_param(ele_key);

                                    if output_component_contents {
                                        if let Some(ExprValue::LiteralArray(Some(ref items))) = coll_expr {
                                            write_single = false;

                                            for (item_idx, item_expr) in items.iter().enumerate() {
                                                let prefix_sym = Symbol::param("key_prefix");
                                                if let Some(ref mut props) = props {
                                                    props.push((ele_key.to_owned(), Some(item_expr.to_owned())));
                                                };
                                                self.write_single_component_instance(w, op, doc, comp, &component_key, props.as_ref().map(|p| p.iter()), lens.as_ref(), Some((&prefix_sym, item_idx as i32)), output_component_contents)?;
                                            };
                                        };
                                    } else {
                                        self.write_single_component_instance(w, op, doc, comp, &component_key, props.as_ref().map(|p| p.iter()), lens.as_ref(), None, output_component_contents)?;
                                   };
                                };
                            }

                            &Some(LensExprType::GetLens(ref sym)) => {
                            }

                            _ => {}
                        };

                        if write_single {
                            self.write_single_component_instance(w, op, doc, comp, &component_key, props.as_ref().map(|p| p.iter()), None, None, output_component_contents)?;
                        };

                        if output_component_contents {
                            self.pop_scope();
                        }
                    }
                }

                &ElementOp::StartBlock(ref block_id) => {
                    let mut scope = self.scope();

                    let complete_key = scope.0.complete_element_key();

                    if output_component_contents {
                        // Collect blocks to render
                        self.cur_block_id = Some(block_id.to_owned());
                    } else {
                        // Write function header
                        let loopidx_expr = ExprValue::SymbolReference(Symbol::loop_idx("foridx", block_id));
                        scope.0.set_prefix_expr(&loopidx_expr);
                        self.stream_writer.write_op_element_start_block(w, op, doc, &scope, block_id)?;
                    };

                    self.push_scope(scope);
                }

                &ElementOp::EndBlock(ref block_id) => {
                    if output_component_contents {
                        // Finish current block
                        self.cur_block_id = None;
                    } else {
                        self.scopes.pop_back();
                        let scope = self.scopes.back().map_or(scope.clone(), |s| s.1.clone());

                        self.stream_writer.write_op_element_end_block(w, op, doc, &scope, block_id)?;
                    };
                }

                &ElementOp::MapCollection(ref block_id, ref ele, ref coll_expr) => {
                    if output_component_contents {
                        let mut scope = self.scope();

                        let has_block = self.blocks.contains_key(block_id);
                        if has_block {
                            let ele = ele.as_ref().map(|e| e.as_str());

                            let coll_expr = reduce_expr(coll_expr, doc, &scope);

                            if let Some(ExprValue::LiteralArray(Some(ref items))) = coll_expr {
                                for item_expr in items {
                                    self.write_loop_item(w, doc, item_expr, ele, None, block_id, output_component_contents)?;
                                };
                            };
                        };
                    } else {
                        let forvar_default = &format!("__forvar_{}", block_id);
                        let scope_id = format!("{}_map", block_id);

                        // Map to block
                        self.stream_writer.write_op_element_map_collection_to_block(w, op, doc, &scope, coll_expr, block_id)?;
                    };
                }
            }
        }

        Ok(())
    }
}<|endoftext|>


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

extern crate serde;
extern crate serde_json;

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string ()}
    }
}
<commit_msg>Config manager can query for config files<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

extern crate glob;
extern crate serde;
extern crate serde_json;

use self::glob::glob;

use std::vec::Vec;

/*===============================================================================================*/
/*------CONFIG STRUCT----------------------------------------------------------------------------*/
/*===============================================================================================*/

#[derive (Clone)]
pub struct Config {

    // Public
    /// The name of the config file.
    pub name: String,
    /// The path to the config file.
    pub path: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String,

    // Private
    _config_list: Vec<Config>
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Queries the config directory, and stores a list of configs.
    pub fn query_config_dir (&mut self) {

        // Clear the old config list
        self._config_list.clear ();

        info! ("Searching for config files...");

        // Recurse through all items in the config directory
        for path in glob (&format! ("{}/*{}", &self.config_dir, ".json")).unwrap ().filter_map (Result::ok) {

            self._config_list.push (Config {name: path.file_stem ().unwrap ().to_str ().unwrap ().to_string (),
                                            path: path.to_str ().unwrap ().to_string ()});

            info! ("Found: {:?}", &path.file_name ().unwrap ());
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._config_list.is_empty () {
            info! ("No config files found.");
        }

        else {
            info! ("Config searching complete.");
        }
    }

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string (),
                       _config_list: Vec::new ()}
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use const_fn_assert::cfn_debug_assert;

// Integer binary logarithm of a 64-bit value.
// v: A 64-bit value.
// Returns floor(log2(v)) + 1, or 0 if v == 0.
// This is the number of bits that would be required to represent v in two's
//  complement notation with all of the leading zeros stripped.
const fn ilog64(v: i64) -> i32 {
  64 - v.leading_zeros() as i32
}

/// Convert an integer into a Q57 fixed-point fraction.
pub const fn q57(v: i32) -> i64 {
  cfn_debug_assert!(v >= -64 && v <= 63);
  (v as i64) << 57
}

#[rustfmt::skip]
const ATANH_LOG2: &[i64; 32] = &[
  0x32B803473F7AD0F4, 0x2F2A71BD4E25E916, 0x2E68B244BB93BA06,
  0x2E39FB9198CE62E4, 0x2E2E683F68565C8F, 0x2E2B850BE2077FC1,
  0x2E2ACC58FE7B78DB, 0x2E2A9E2DE52FD5F2, 0x2E2A92A338D53EEC,
  0x2E2A8FC08F5E19B6, 0x2E2A8F07E51A485E, 0x2E2A8ED9BA8AF388,
  0x2E2A8ECE2FE7384A, 0x2E2A8ECB4D3E4B1A, 0x2E2A8ECA94940FE8,
  0x2E2A8ECA6669811D, 0x2E2A8ECA5ADEDD6A, 0x2E2A8ECA57FC347E,
  0x2E2A8ECA57438A43, 0x2E2A8ECA57155FB4, 0x2E2A8ECA5709D510,
  0x2E2A8ECA5706F267, 0x2E2A8ECA570639BD, 0x2E2A8ECA57060B92,
  0x2E2A8ECA57060008, 0x2E2A8ECA5705FD25, 0x2E2A8ECA5705FC6C,
  0x2E2A8ECA5705FC3E, 0x2E2A8ECA5705FC33, 0x2E2A8ECA5705FC30,
  0x2E2A8ECA5705FC2F, 0x2E2A8ECA5705FC2F
];

/// Computes the binary exponential of logq57.
/// input: a log base 2 in Q57 format.
/// output: a 64 bit integer in Q0 (no fraction).
pub const fn bexp64(logq57: i64) -> i64 {
  let ipart = (logq57 >> 57) as i32;
  if ipart < 0 {
    return 0;
  }
  if ipart >= 63 {
    return 0x7FFFFFFFFFFFFFFF;
  }
  // z is the fractional part of the log in Q62 format.
  // We need 1 bit of headroom since the magnitude can get larger than 1
  //  during the iteration, and a sign bit.
  let mut z = logq57 - q57(ipart);
  let mut w: i64;
  if z != 0 {
    // Rust has 128 bit multiplies, so it should be possible to do this
    //  faster without losing accuracy.
    z <<= 5;
    // w is the exponential in Q61 format (since it also needs headroom and can
    //  get as large as 2.0); we could get another bit if we dropped the sign,
    //  but we'll recover that bit later anyway.
    // Ideally this should start out as
    //   \lim_{n->\infty} 2^{61}/\product_{i=1}^n \sqrt{1-2^{-2i}}
    //  but in order to guarantee convergence we have to repeat iterations 4,
    //  13 (=3*4+1), and 40 (=3*13+1, etc.), so it winds up somewhat larger.
    w = 0x26A3D0E401DD846D;
    let mut i: i64 = 0;
    loop {
      let mask = -((z < 0) as i64);
      w += ((w >> (i + 1)) + mask) ^ mask;
      z -= (ATANH_LOG2[i as usize] + mask) ^ mask;
      // Repeat iteration 4.
      if i >= 3 {
        break;
      }
      z *= 2;
      i += 1;
    }
    loop {
      let mask = -((z < 0) as i64);
      w += ((w >> (i + 1)) + mask) ^ mask;
      z -= (ATANH_LOG2[i as usize] + mask) ^ mask;
      // Repeat iteration 13.
      if i >= 12 {
        break;
      }
      z *= 2;
      i += 1;
    }
    while i < 32 {
      let mask = -((z < 0) as i64);
      w += ((w >> (i + 1)) + mask) ^ mask;
      z = (z - ((ATANH_LOG2[i as usize] + mask) ^ mask)) * 2;
      i += 1;
    }
    // Skip the remaining iterations unless we really require that much
    //  precision.
    // We could have bailed out earlier for smaller iparts, but that would
    //  require initializing w from a table, as the limit doesn't converge to
    //  61-bit precision until n=30.
    let mut wlo: i32 = 0;
    if ipart > 30 {
      // For these iterations, we just update the low bits, as the high bits
      //  can't possibly be affected.
      // OD_ATANH_LOG2 has also converged (it actually did so one iteration
      //  earlier, but that's no reason for an extra special case).
      loop {
        let mask = -((z < 0) as i64);
        wlo += (((w >> i) + mask) ^ mask) as i32;
        z -= (ATANH_LOG2[31] + mask) ^ mask;
        // Repeat iteration 40.
        if i >= 39 {
          break;
        }
        z *= 2;
        i += 1;
      }
      while i < 61 {
        let mask = -((z < 0) as i64);
        wlo += (((w >> i) + mask) ^ mask) as i32;
        z = (z - ((ATANH_LOG2[31] + mask) ^ mask)) * 2;
        i += 1;
      }
    }
    w = (w << 1) + (wlo as i64);
  } else {
    w = 1i64 << 62;
  }
  if ipart < 62 {
    w = ((w >> (61 - ipart)) + 1) >> 1;
  }
  w
}

/// Computes the binary log of w.
/// input: a 64-bit integer in Q0 (no fraction).
/// output: a 64-bit log in Q57.
/// TODO: Mark const once we can use local variables in a const function.
pub fn blog64(w: i64) -> i64 {
  let mut w = w;
  if w <= 0 {
    return -1;
  }
  let ipart = ilog64(w) - 1;
  if ipart > 61 {
    w >>= ipart - 61;
  } else {
    w <<= 61 - ipart;
  }
  // z is the fractional part of the log in Q61 format.
  let mut z: i64 = 0;
  if (w & (w - 1)) != 0 {
    // Rust has 128 bit multiplies, so it should be possible to do this
    //  faster without losing accuracy.
    // x and y are the cosh() and sinh(), respectively, in Q61 format.
    // We are computing z = 2*atanh(y/x) = 2*atanh((w - 1)/(w + 1)).
    let mut x = w + (1i64 << 61);
    let mut y = w - (1i64 << 61);
    for i in 0..4 {
      let mask = -((y < 0) as i64);
      z += ((ATANH_LOG2[i as usize] >> i) + mask) ^ mask;
      let u = x >> (i + 1);
      x -= ((y >> (i + 1)) + mask) ^ mask;
      y -= (u + mask) ^ mask;
    }
    // Repeat iteration 4.
    for i in 3..13 {
      let mask = -((y < 0) as i64);
      z += ((ATANH_LOG2[i as usize] >> i) + mask) ^ mask;
      let u = x >> (i + 1);
      x -= ((y >> (i + 1)) + mask) ^ mask;
      y -= (u + mask) ^ mask;
    }
    // Repeat iteration 13.
    for i in 12..32 {
      let mask = -((y < 0) as i64);
      z += ((ATANH_LOG2[i as usize] >> i) + mask) ^ mask;
      let u = x >> (i + 1);
      x -= ((y >> (i + 1)) + mask) ^ mask;
      y -= (u + mask) ^ mask;
    }
    // OD_ATANH_LOG2 has converged.
    for i in 32..40 {
      let mask = -((y < 0) as i64);
      z += ((ATANH_LOG2[31] >> i) + mask) ^ mask;
      let u = x >> (i + 1);
      x -= ((y >> (i + 1)) + mask) ^ mask;
      y -= (u + mask) ^ mask;
    }
    // Repeat iteration 40.
    for i in 39..62 {
      let mask = -((y < 0) as i64);
      z += ((ATANH_LOG2[31] >> i) + mask) ^ mask;
      let u = x >> (i + 1);
      x -= ((y >> (i + 1)) + mask) ^ mask;
      y -= (u + mask) ^ mask;
    }
    z = (z + 8) >> 4;
  }
  q57(ipart) + z
}

/// Converts a Q57 fixed-point fraction to Q24 by rounding.
pub const fn q57_to_q24(v: i64) -> i32 {
  (((v >> 32) + 1) >> 1) as i32
}

/// Converts a Q24 fixed-point fraction to Q57.
pub const fn q24_to_q57(v: i32) -> i64 {
  (v as i64) << 33
}

/// Binary exponentiation of a log_scale with 24-bit fractional precision and
///  saturation.
/// `log_scale`: A binary logarithm in Q24 format.
/// Returns the binary exponential in Q24 format, saturated to 2**47 - 1 if
///  `log_scale` was too large.
pub const fn bexp_q24(log_scale: i32) -> i64 {
  if log_scale < 23 << 24 {
    let ret = bexp64(((log_scale as i64) << 33) + q57(24));
    if ret < (1i64 << 47) - 1 {
      return ret;
    }
  }
  (1i64 << 47) - 1
}

#[cfg(test)]
mod test {
  use super::{bexp64, blog64};

  #[test]
  fn blog64_vectors() {
    assert!(blog64(1793) == 0x159dc71e24d32daf);
    assert!(blog64(0x678dde6e5fd29f05) == 0x7d6373ad151ca685);
  }

  #[test]
  fn bexp64_vectors() {
    assert!(bexp64(0x159dc71e24d32daf) == 1793);
    assert!((bexp64(0x7d6373ad151ca685) - 0x678dde6e5fd29f05).abs() < 29);
  }

  #[test]
  fn blog64_bexp64_round_trip() {
    for a in 1..=std::u16::MAX as i64 {
      let b = std::i64::MAX / a;
      let (log_a, log_b, log_ab) = (blog64(a), blog64(b), blog64(a * b));
      assert!((log_a + log_b - log_ab).abs() < 4);
      assert!(bexp64(log_a) == a);
      assert!((bexp64(log_b) - b).abs() < 128);
      assert!((bexp64(log_ab) - a * b).abs() < 128);
    }
  }
}
<commit_msg>logexp: Rewrite blog64 so that it is const<commit_after>// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use const_fn_assert::cfn_debug_assert;

/// Convert an integer into a Q57 fixed-point fraction.
pub const fn q57(v: i32) -> i64 {
  cfn_debug_assert!(v >= -64 && v <= 63);
  (v as i64) << 57
}

#[rustfmt::skip]
const ATANH_LOG2: &[i64; 32] = &[
  0x32B803473F7AD0F4, 0x2F2A71BD4E25E916, 0x2E68B244BB93BA06,
  0x2E39FB9198CE62E4, 0x2E2E683F68565C8F, 0x2E2B850BE2077FC1,
  0x2E2ACC58FE7B78DB, 0x2E2A9E2DE52FD5F2, 0x2E2A92A338D53EEC,
  0x2E2A8FC08F5E19B6, 0x2E2A8F07E51A485E, 0x2E2A8ED9BA8AF388,
  0x2E2A8ECE2FE7384A, 0x2E2A8ECB4D3E4B1A, 0x2E2A8ECA94940FE8,
  0x2E2A8ECA6669811D, 0x2E2A8ECA5ADEDD6A, 0x2E2A8ECA57FC347E,
  0x2E2A8ECA57438A43, 0x2E2A8ECA57155FB4, 0x2E2A8ECA5709D510,
  0x2E2A8ECA5706F267, 0x2E2A8ECA570639BD, 0x2E2A8ECA57060B92,
  0x2E2A8ECA57060008, 0x2E2A8ECA5705FD25, 0x2E2A8ECA5705FC6C,
  0x2E2A8ECA5705FC3E, 0x2E2A8ECA5705FC33, 0x2E2A8ECA5705FC30,
  0x2E2A8ECA5705FC2F, 0x2E2A8ECA5705FC2F
];

/// Computes the binary exponential of `logq57`.
/// `logq57`: a log base 2 in Q57 format.
/// Returns a 64 bit integer in Q0 (no fraction).
pub const fn bexp64(logq57: i64) -> i64 {
  let ipart = (logq57 >> 57) as i32;
  if ipart < 0 {
    return 0;
  }
  if ipart >= 63 {
    return 0x7FFFFFFFFFFFFFFF;
  }
  // z is the fractional part of the log in Q62 format.
  // We need 1 bit of headroom since the magnitude can get larger than 1
  //  during the iteration, and a sign bit.
  let mut z = logq57 - q57(ipart);
  let mut w: i64;
  if z != 0 {
    // Rust has 128 bit multiplies, so it should be possible to do this
    //  faster without losing accuracy.
    z <<= 5;
    // w is the exponential in Q61 format (since it also needs headroom and can
    //  get as large as 2.0); we could get another bit if we dropped the sign,
    //  but we'll recover that bit later anyway.
    // Ideally this should start out as
    //   \lim_{n->\infty} 2^{61}/\product_{i=1}^n \sqrt{1-2^{-2i}}
    //  but in order to guarantee convergence we have to repeat iterations 4,
    //  13 (=3*4+1), and 40 (=3*13+1, etc.), so it winds up somewhat larger.
    w = 0x26A3D0E401DD846D;
    let mut i: i64 = 0;
    loop {
      let mask = -((z < 0) as i64);
      w += ((w >> (i + 1)) + mask) ^ mask;
      z -= (ATANH_LOG2[i as usize] + mask) ^ mask;
      // Repeat iteration 4.
      if i >= 3 {
        break;
      }
      z *= 2;
      i += 1;
    }
    loop {
      let mask = -((z < 0) as i64);
      w += ((w >> (i + 1)) + mask) ^ mask;
      z -= (ATANH_LOG2[i as usize] + mask) ^ mask;
      // Repeat iteration 13.
      if i >= 12 {
        break;
      }
      z *= 2;
      i += 1;
    }
    while i < 32 {
      let mask = -((z < 0) as i64);
      w += ((w >> (i + 1)) + mask) ^ mask;
      z = (z - ((ATANH_LOG2[i as usize] + mask) ^ mask)) * 2;
      i += 1;
    }
    // Skip the remaining iterations unless we really require that much
    //  precision.
    // We could have bailed out earlier for smaller iparts, but that would
    //  require initializing w from a table, as the limit doesn't converge to
    //  61-bit precision until n=30.
    let mut wlo: i32 = 0;
    if ipart > 30 {
      // For these iterations, we just update the low bits, as the high bits
      //  can't possibly be affected.
      // OD_ATANH_LOG2 has also converged (it actually did so one iteration
      //  earlier, but that's no reason for an extra special case).
      loop {
        let mask = -((z < 0) as i64);
        wlo += (((w >> i) + mask) ^ mask) as i32;
        z -= (ATANH_LOG2[31] + mask) ^ mask;
        // Repeat iteration 40.
        if i >= 39 {
          break;
        }
        z *= 2;
        i += 1;
      }
      while i < 61 {
        let mask = -((z < 0) as i64);
        wlo += (((w >> i) + mask) ^ mask) as i32;
        z = (z - ((ATANH_LOG2[31] + mask) ^ mask)) * 2;
        i += 1;
      }
    }
    w = (w << 1) + (wlo as i64);
  } else {
    w = 1i64 << 62;
  }
  if ipart < 62 {
    w = ((w >> (61 - ipart)) + 1) >> 1;
  }
  w
}

/// Computes the binary log of `n`.
/// `n`: a 64-bit integer in Q0 (no fraction).
/// Returns a 64-bit log in Q57.
pub const fn blog64(n: i64) -> i64 {
  if n <= 0 {
    return -1;
  }
  let ipart = 63 - n.leading_zeros() as i32;
  let w = if ipart > 61 { n >> (ipart - 61) } else { n << (61 - ipart) };
  if (w & (w - 1)) == 0 {
    return q57(ipart);
  }
  // z is the fractional part of the log in Q61 format.
  let mut z: i64 = 0;
  // Rust has 128 bit multiplies, so it should be possible to do this
  //  faster without losing accuracy.
  // x and y are the cosh() and sinh(), respectively, in Q61 format.
  // We are computing z = 2*atanh(y/x) = 2*atanh((w - 1)/(w + 1)).
  let mut x = w + (1i64 << 61);
  let mut y = w - (1i64 << 61);
  // Repeat iteration 4.
  // Repeat iteration 13.
  // Repeat iteration 40.
  let bounds = [3, 12, 39, 61];
  let mut i = 0;
  let mut j = 0;
  loop {
    let end = bounds[j];
    loop {
      let mask = -((y < 0) as i64);
      // ATANH_LOG2 has converged at iteration 32.
      z += ((ATANH_LOG2[if i < 31 { i } else { 31 }] >> i) + mask) ^ mask;
      let u = x >> (i + 1);
      x -= ((y >> (i + 1)) + mask) ^ mask;
      y -= (u + mask) ^ mask;
      if i == end {
        break;
      }
      i += 1;
    }
    j += 1;
    if j == bounds.len() {
      break;
    }
  }
  z = (z + 8) >> 4;
  q57(ipart) + z
}

/// Converts a Q57 fixed-point fraction to Q24 by rounding.
pub const fn q57_to_q24(v: i64) -> i32 {
  (((v >> 32) + 1) >> 1) as i32
}

/// Converts a Q24 fixed-point fraction to Q57.
pub const fn q24_to_q57(v: i32) -> i64 {
  (v as i64) << 33
}

/// Binary exponentiation of a `log_scale` with 24-bit fractional precision and
///  saturation.
/// `log_scale`: A binary logarithm in Q24 format.
/// Returns the binary exponential in Q24 format, saturated to 2**47 - 1 if
///  `log_scale` was too large.
pub const fn bexp_q24(log_scale: i32) -> i64 {
  if log_scale < 23 << 24 {
    let ret = bexp64(((log_scale as i64) << 33) + q57(24));
    if ret < (1i64 << 47) - 1 {
      return ret;
    }
  }
  (1i64 << 47) - 1
}

#[cfg(test)]
mod test {
  use super::{bexp64, blog64};

  #[test]
  fn blog64_vectors() {
    assert!(blog64(1793) == 0x159dc71e24d32daf);
    assert!(blog64(0x678dde6e5fd29f05) == 0x7d6373ad151ca685);
  }

  #[test]
  fn bexp64_vectors() {
    assert!(bexp64(0x159dc71e24d32daf) == 1793);
    assert!((bexp64(0x7d6373ad151ca685) - 0x678dde6e5fd29f05).abs() < 29);
  }

  #[test]
  fn blog64_bexp64_round_trip() {
    for a in 1..=std::u16::MAX as i64 {
      let b = std::i64::MAX / a;
      let (log_a, log_b, log_ab) = (blog64(a), blog64(b), blog64(a * b));
      assert!((log_a + log_b - log_ab).abs() < 4);
      assert!(bexp64(log_a) == a);
      assert!((bexp64(log_b) - b).abs() < 128);
      assert!((bexp64(log_ab) - a * b).abs() < 128);
    }
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref NUMBER: u32 = times_two(3);
    static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)];
    static ref STRING: String = "hello".to_string();
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "abc");
        m.insert(1, "def");
        m.insert(2, "ghi");
        m
    };
    // This *should* triggger warn(dead_code) by design.
    static ref UNUSED: () = ();
}

fn times_two(n: u32) -> u32 {
    n * 2
}

#[test]
fn test_basic() {
    assert_eq!(&STRING[..], "hello");
    assert_eq!(*NUMBER, 6);
    assert!(HASHMAP.get(&1).is_some());
    assert!(HASHMAP.get(&3).is_none());
    assert_eq!(&ARRAY_BOXES[..], &[Box::new(1), Box::new(2), Box::new(3)][..]);
}

#[test]
fn test_repeat() {
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
}

mod visibility {
    lazy_static! {
        pub static ref FOO: Box<u32> = Box::new(0);
    }
}

#[test]
fn test_visibility() {
    assert_eq!(*visibility::FOO, Box::new(0));
}

// This should not cause a warning about a missing Copy implementation
lazy_static! {
    pub static ref VAR: i32 = { 0 };
}
<commit_msg>Updated tests to work with nightly 1.0.0-beta (9854143cb 2015-04-02)<commit_after>#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref NUMBER: u32 = times_two(3);
    static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)];
    static ref STRING: String = "hello".to_string();
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "abc");
        m.insert(1, "def");
        m.insert(2, "ghi");
        m
    };
    // This *should* triggger warn(dead_code) by design.
    static ref UNUSED: () = ();
}

fn times_two(n: u32) -> u32 {
    n * 2
}

#[test]
fn test_basic() {
    assert_eq!(&**STRING, "hello");
    assert_eq!(*NUMBER, 6);
    assert!(HASHMAP.get(&1).is_some());
    assert!(HASHMAP.get(&3).is_none());
    assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]);
}

#[test]
fn test_repeat() {
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
}

mod visibility {
    lazy_static! {
        pub static ref FOO: Box<u32> = Box::new(0);
    }
}

#[test]
fn test_visibility() {
    assert_eq!(*visibility::FOO, Box::new(0));
}

// This should not cause a warning about a missing Copy implementation
lazy_static! {
    pub static ref VAR: i32 = { 0 };
}
<|endoftext|>


<commit_before>//! VM implementation, traits and structs
//!
//! ### Lifecycle
//!
//! A VM can be started given a `Context` and a `BlockHeader`. The
//! user can then `fire` or `step` to run it. Those functions would
//! only fail if it needs some information (accounts in the current
//! block, or block hashes of previous blocks). If this happens, one
//! can use the function `commit_account` and `commit_blockhash` to
//! commit those information to the VM, and `fire` or `step` again
//! until it succeeds. The current VM status can always be obtained
//! using the `status` function.

mod memory;
mod stack;
mod pc;
mod storage;
mod params;
mod eval;
mod commit;
mod patch;
mod transaction;
pub mod errors;

pub use self::memory::{Memory, SeqMemory};
pub use self::stack::Stack;
pub use self::pc::{PC, Instruction};
pub use self::storage::Storage;
pub use self::params::*;
pub use self::patch::*;
pub use self::eval::{State, Machine, MachineStatus};
pub use self::commit::{AccountCommitment, Account, AccountState, BlockhashState};
pub use self::transaction::{Transaction, TransactionVM};

use std::collections::hash_map;
use util::bigint::M256;
use util::gas::Gas;
use util::address::Address;
use self::errors::{RequireError, CommitError, MachineError};

#[derive(Debug, Clone)]
/// VM Status
pub enum VMStatus {
    /// A running VM.
    Running,
    /// VM is stopped with out errors.
    ExitedOk,
    /// VM is stopped due to an error. The state of the VM is before
    /// the last failing instruction.
    ExitedErr(MachineError),
}

/// Represents an EVM. This is usually the main interface for clients
/// to interact with.
pub trait VM {
    /// Commit an account information to this VM. This should only
    /// be used when receiving `RequireError`.
    fn commit_account(&mut self, commitment: AccountCommitment) -> Result<(), CommitError>;
    /// Commit a block hash to this VM. This should only be used when
    /// receiving `RequireError`.
    fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError>;
    /// Returns the current status of the VM.
    fn status(&self) -> VMStatus;
    /// Run one instruction and return. If it succeeds, VM status can
    /// still be `Running`. If the call stack has more than one items,
    /// this will only executes the last items' one single
    /// instruction.
    fn step(&mut self) -> Result<(), RequireError>;
    /// Run instructions until it reaches a `RequireError` or
    /// exits. If this function succeeds, the VM status can only be
    /// either `ExitedOk` or `ExitedErr`.
    fn fire(&mut self) -> Result<(), RequireError> {
        loop {
            match self.status() {
                VMStatus::Running => self.step()?,
                VMStatus::ExitedOk | VMStatus::ExitedErr(_) => return Ok(()),
            }
        }
    }
    /// Returns the changed or committed accounts information up to
    /// current execution status.
    fn accounts(&self) -> hash_map::Values<Address, Account>;
    /// Returns the out value, if any.
    fn out(&self) -> &[u8];
    /// Returns the available gas of this VM.
    fn available_gas(&self) -> Gas;
    /// Returns the refunded gas of this VM.
    fn refunded_gas(&self) -> Gas;
    /// Returns logs to be appended to the current block if the user
    /// decided to accept the running status of this VM.
    fn logs(&self) -> &[Log];
    /// Returns all removed account addresses as for current VM execution.
    fn removed(&self) -> &[Address];
}

/// A sequencial VM. It uses sequencial memory representation and hash
/// map storage for accounts.
pub type SeqContextVM = ContextVM<SeqMemory>;
/// A sequencial transaction VM. This is same as `SeqContextVM` except
/// it runs at transaction level.
pub type SeqTransactionVM = TransactionVM<SeqMemory>;

/// A VM that executes using a context and block information.
pub struct ContextVM<M> {
    machines: Vec<Machine<M>>,
    history: Vec<Context>
}

impl<M: Memory + Default> ContextVM<M> {
    /// Create a new VM using the given context, block header and patch.
    pub fn new(context: Context, block: BlockHeader, patch: &'static Patch) -> Self {
        let mut machines = Vec::new();
        machines.push(Machine::new(context, block, patch, 1));
        ContextVM {
            machines,
            history: Vec::new()
        }
    }

    /// Create a new VM with the given account state and blockhash state.
    pub fn with_states(context: Context, block: BlockHeader, patch: &'static Patch,
                       account_state: AccountState, blockhash_state: BlockhashState) -> Self {
        let mut machines = Vec::new();
        machines.push(Machine::with_states(context, block, patch, 1, account_state, blockhash_state));
        ContextVM {
            machines,
            history: Vec::new()
        }
    }

    /// Create a new VM with the result of the previous VM. This is
    /// usually used by transaction for chainning them.
    pub fn with_previous(context: Context, block: BlockHeader, patch: &'static Patch,
                         vm: &ContextVM<M>) -> Self {
        Self::with_states(context, block, patch,
                          vm.machines[0].state().account_state.clone(),
                          vm.machines[0].state().blockhash_state.clone())
    }

    /// Returns the call create history. Only used in testing.
    pub fn history(&self) -> &[Context] {
        self.history.as_slice()
    }
}

impl<M: Memory + Default> VM for ContextVM<M> {
    fn commit_account(&mut self, commitment: AccountCommitment) -> Result<(), CommitError> {
        for machine in &mut self.machines {
            machine.commit_account(commitment.clone())?;
        }
        Ok(())
    }

    fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError> {
        for machine in &mut self.machines {
            machine.commit_blockhash(number, hash)?;
        }
        Ok(())
    }

    fn status(&self) -> VMStatus {
        match self.machines[0].status() {
            MachineStatus::Running | MachineStatus::InvokeCreate(_) | MachineStatus::InvokeCall(_, _) => VMStatus::Running,
            MachineStatus::ExitedOk => VMStatus::ExitedOk,
            MachineStatus::ExitedErr(err) => VMStatus::ExitedErr(err.into()),
        }
    }

    fn step(&mut self) -> Result<(), RequireError> {
        match self.machines.last().unwrap().status().clone() {
            MachineStatus::Running => {
                self.machines.last_mut().unwrap().step()
            },
            MachineStatus::ExitedOk | MachineStatus::ExitedErr(_) => {
                if self.machines.len() <= 1 {
                    Ok(())
                } else {
                    let finished = self.machines.pop().unwrap();
                    self.machines.last_mut().unwrap().apply_sub(finished);
                    Ok(())
                }
            },
            MachineStatus::InvokeCall(context, _) => {
                self.history.push(context.clone());
                let mut sub = self.machines.last().unwrap().derive(context);
                sub.invoke_call();
                self.machines.push(sub);
                Ok(())
            },
            MachineStatus::InvokeCreate(context) => {
                let mut sub = self.machines.last().unwrap().derive(context.clone());
                sub.invoke_create()?;
                self.history.push(context);
                self.machines.push(sub);
                Ok(())
            },
        }
    }

    fn fire(&mut self) -> Result<(), RequireError> {
        loop {
            match self.status() {
                VMStatus::Running => self.step()?,
                VMStatus::ExitedOk | VMStatus::ExitedErr(_) => return Ok(()),
            }
        }
    }

    fn accounts(&self) -> hash_map::Values<Address, Account> {
        self.machines[0].state().account_state.accounts()
    }

    fn out(&self) -> &[u8] {
        self.machines[0].state().out.as_slice()
    }

    fn available_gas(&self) -> Gas {
        self.machines[0].state().available_gas()
    }

    fn refunded_gas(&self) -> Gas {
        self.machines[0].state().refunded_gas
    }

    fn logs(&self) -> &[Log] {
        self.machines[0].state().logs.as_slice()
    }

    fn removed(&self) -> &[Address] {
        self.machines[0].state().removed.as_slice()
    }
}
<commit_msg>Doc typo<commit_after>//! VM implementation, traits and structs
//!
//! ### Lifecycle
//!
//! A VM can be started given a `Context` and a `BlockHeader`. The
//! user can then `fire` or `step` to run it. Those functions would
//! only fail if it needs some information (accounts in the current
//! block, or block hashes of previous blocks). If this happens, one
//! can use the function `commit_account` and `commit_blockhash` to
//! commit those information to the VM, and `fire` or `step` again
//! until it succeeds. The current VM status can always be obtained
//! using the `status` function.

mod memory;
mod stack;
mod pc;
mod storage;
mod params;
mod eval;
mod commit;
mod patch;
mod transaction;
pub mod errors;

pub use self::memory::{Memory, SeqMemory};
pub use self::stack::Stack;
pub use self::pc::{PC, Instruction};
pub use self::storage::Storage;
pub use self::params::*;
pub use self::patch::*;
pub use self::eval::{State, Machine, MachineStatus};
pub use self::commit::{AccountCommitment, Account, AccountState, BlockhashState};
pub use self::transaction::{Transaction, TransactionVM};

use std::collections::hash_map;
use util::bigint::M256;
use util::gas::Gas;
use util::address::Address;
use self::errors::{RequireError, CommitError, MachineError};

#[derive(Debug, Clone)]
/// VM Status
pub enum VMStatus {
    /// A running VM.
    Running,
    /// VM is stopped without errors.
    ExitedOk,
    /// VM is stopped due to an error. The state of the VM is before
    /// the last failing instruction.
    ExitedErr(MachineError),
}

/// Represents an EVM. This is usually the main interface for clients
/// to interact with.
pub trait VM {
    /// Commit an account information to this VM. This should only
    /// be used when receiving `RequireError`.
    fn commit_account(&mut self, commitment: AccountCommitment) -> Result<(), CommitError>;
    /// Commit a block hash to this VM. This should only be used when
    /// receiving `RequireError`.
    fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError>;
    /// Returns the current status of the VM.
    fn status(&self) -> VMStatus;
    /// Run one instruction and return. If it succeeds, VM status can
    /// still be `Running`. If the call stack has more than one items,
    /// this will only executes the last items' one single
    /// instruction.
    fn step(&mut self) -> Result<(), RequireError>;
    /// Run instructions until it reaches a `RequireError` or
    /// exits. If this function succeeds, the VM status can only be
    /// either `ExitedOk` or `ExitedErr`.
    fn fire(&mut self) -> Result<(), RequireError> {
        loop {
            match self.status() {
                VMStatus::Running => self.step()?,
                VMStatus::ExitedOk | VMStatus::ExitedErr(_) => return Ok(()),
            }
        }
    }
    /// Returns the changed or committed accounts information up to
    /// current execution status.
    fn accounts(&self) -> hash_map::Values<Address, Account>;
    /// Returns the out value, if any.
    fn out(&self) -> &[u8];
    /// Returns the available gas of this VM.
    fn available_gas(&self) -> Gas;
    /// Returns the refunded gas of this VM.
    fn refunded_gas(&self) -> Gas;
    /// Returns logs to be appended to the current block if the user
    /// decided to accept the running status of this VM.
    fn logs(&self) -> &[Log];
    /// Returns all removed account addresses as for current VM execution.
    fn removed(&self) -> &[Address];
}

/// A sequencial VM. It uses sequencial memory representation and hash
/// map storage for accounts.
pub type SeqContextVM = ContextVM<SeqMemory>;
/// A sequencial transaction VM. This is same as `SeqContextVM` except
/// it runs at transaction level.
pub type SeqTransactionVM = TransactionVM<SeqMemory>;

/// A VM that executes using a context and block information.
pub struct ContextVM<M> {
    machines: Vec<Machine<M>>,
    history: Vec<Context>
}

impl<M: Memory + Default> ContextVM<M> {
    /// Create a new VM using the given context, block header and patch.
    pub fn new(context: Context, block: BlockHeader, patch: &'static Patch) -> Self {
        let mut machines = Vec::new();
        machines.push(Machine::new(context, block, patch, 1));
        ContextVM {
            machines,
            history: Vec::new()
        }
    }

    /// Create a new VM with the given account state and blockhash state.
    pub fn with_states(context: Context, block: BlockHeader, patch: &'static Patch,
                       account_state: AccountState, blockhash_state: BlockhashState) -> Self {
        let mut machines = Vec::new();
        machines.push(Machine::with_states(context, block, patch, 1, account_state, blockhash_state));
        ContextVM {
            machines,
            history: Vec::new()
        }
    }

    /// Create a new VM with the result of the previous VM. This is
    /// usually used by transaction for chainning them.
    pub fn with_previous(context: Context, block: BlockHeader, patch: &'static Patch,
                         vm: &ContextVM<M>) -> Self {
        Self::with_states(context, block, patch,
                          vm.machines[0].state().account_state.clone(),
                          vm.machines[0].state().blockhash_state.clone())
    }

    /// Returns the call create history. Only used in testing.
    pub fn history(&self) -> &[Context] {
        self.history.as_slice()
    }
}

impl<M: Memory + Default> VM for ContextVM<M> {
    fn commit_account(&mut self, commitment: AccountCommitment) -> Result<(), CommitError> {
        for machine in &mut self.machines {
            machine.commit_account(commitment.clone())?;
        }
        Ok(())
    }

    fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError> {
        for machine in &mut self.machines {
            machine.commit_blockhash(number, hash)?;
        }
        Ok(())
    }

    fn status(&self) -> VMStatus {
        match self.machines[0].status() {
            MachineStatus::Running | MachineStatus::InvokeCreate(_) | MachineStatus::InvokeCall(_, _) => VMStatus::Running,
            MachineStatus::ExitedOk => VMStatus::ExitedOk,
            MachineStatus::ExitedErr(err) => VMStatus::ExitedErr(err.into()),
        }
    }

    fn step(&mut self) -> Result<(), RequireError> {
        match self.machines.last().unwrap().status().clone() {
            MachineStatus::Running => {
                self.machines.last_mut().unwrap().step()
            },
            MachineStatus::ExitedOk | MachineStatus::ExitedErr(_) => {
                if self.machines.len() <= 1 {
                    Ok(())
                } else {
                    let finished = self.machines.pop().unwrap();
                    self.machines.last_mut().unwrap().apply_sub(finished);
                    Ok(())
                }
            },
            MachineStatus::InvokeCall(context, _) => {
                self.history.push(context.clone());
                let mut sub = self.machines.last().unwrap().derive(context);
                sub.invoke_call();
                self.machines.push(sub);
                Ok(())
            },
            MachineStatus::InvokeCreate(context) => {
                let mut sub = self.machines.last().unwrap().derive(context.clone());
                sub.invoke_create()?;
                self.history.push(context);
                self.machines.push(sub);
                Ok(())
            },
        }
    }

    fn fire(&mut self) -> Result<(), RequireError> {
        loop {
            match self.status() {
                VMStatus::Running => self.step()?,
                VMStatus::ExitedOk | VMStatus::ExitedErr(_) => return Ok(()),
            }
        }
    }

    fn accounts(&self) -> hash_map::Values<Address, Account> {
        self.machines[0].state().account_state.accounts()
    }

    fn out(&self) -> &[u8] {
        self.machines[0].state().out.as_slice()
    }

    fn available_gas(&self) -> Gas {
        self.machines[0].state().available_gas()
    }

    fn refunded_gas(&self) -> Gas {
        self.machines[0].state().refunded_gas
    }

    fn logs(&self) -> &[Log] {
        self.machines[0].state().logs.as_slice()
    }

    fn removed(&self) -> &[Address] {
        self.machines[0].state().removed.as_slice()
    }
}
<|endoftext|>


<commit_before>extern crate iup;

use iup::CallbackReturn;
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    iup::open().unwrap();

    let text = Rc::new(RefCell::new(iup::text()));
    {
        let mut text = text.borrow_mut();
        iup::set_handle("text", &mut text);
        iup::set_str_attribute(&mut text, "READONLY", "YES");
        iup::set_str_attribute(&mut text, "VALUE", "0");
    }

    let mut button = iup::button("Count");
    {
        let text = text.clone();
        iup::callback::set_action(&mut button, Some(move |_ih| {
            let mut text = text.borrow_mut();
            let count = iup::get_attribute(&mut text, "VALUE").unwrap().parse::<i32>().unwrap();
            iup::set_str_attribute(&mut text, "VALUE", &(count + 1).to_string());
            CallbackReturn::Default
        }));
        iup::callback::set_destroy_cb(&mut button, Some(|_ih|{
            println!("One of the buttons is getting destroyed!!");
        }));
    }

    let mut hbox = iup::hboxv(vec!(text.borrow().clone(), button));
    iup::set_str_attribute(&mut hbox, "ALIGNMENT", "ACENTER");
    iup::set_str_attribute(&mut hbox, "MARGIN", "10x10");
    iup::set_str_attribute(&mut hbox, "GAP", "10");

    iup::show(&mut iup::dialog(hbox)).unwrap();

    iup::main_loop();
    iup::close();
}
<commit_msg>Update the counter destroy callback string<commit_after>extern crate iup;

use iup::CallbackReturn;
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    iup::open().unwrap();

    let text = Rc::new(RefCell::new(iup::text()));
    {
        let mut text = text.borrow_mut();
        iup::set_handle("text", &mut text);
        iup::set_str_attribute(&mut text, "READONLY", "YES");
        iup::set_str_attribute(&mut text, "VALUE", "0");
    }

    let mut button = iup::button("Count");
    {
        let text = text.clone();
        iup::callback::set_action(&mut button, Some(move |_ih| {
            let mut text = text.borrow_mut();
            let count = iup::get_attribute(&mut text, "VALUE").unwrap().parse::<i32>().unwrap();
            iup::set_str_attribute(&mut text, "VALUE", &(count + 1).to_string());
            CallbackReturn::Default
        }));
        iup::callback::set_destroy_cb(&mut button, Some(|_ih|{
            println!("The button is getting destroyed!!");
        }));
    }

    let mut hbox = iup::hboxv(vec!(text.borrow().clone(), button));
    iup::set_str_attribute(&mut hbox, "ALIGNMENT", "ACENTER");
    iup::set_str_attribute(&mut hbox, "MARGIN", "10x10");
    iup::set_str_attribute(&mut hbox, "GAP", "10");

    iup::show(&mut iup::dialog(hbox)).unwrap();

    iup::main_loop();
    iup::close();
}
<|endoftext|>


<commit_before>use colour::Rgb24;

pub type Message = Vec<MessagePart>;

#[derive(Clone, Debug)]
pub enum MessagePart {
    Plain(String),
    Colour(Rgb24, String),
}
<commit_msg>Text wrapping for message parts<commit_after>use std::mem;

use colour::Rgb24;

pub type Message = Vec<MessagePart>;

#[derive(Clone, Debug)]
pub enum MessagePart {
    Plain(String),
    Colour(Rgb24, String),
}

impl MessagePart {
    pub fn len(&self) -> usize {
        match *self {
            MessagePart::Plain(ref s) => s.len(),
            MessagePart::Colour(_, ref s) => s.len(),
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            MessagePart::Plain(ref s) => s.is_empty(),
            MessagePart::Colour(_, ref s) => s.is_empty(),
        }
    }

    fn split_at_exclude_middle(&self, mid: usize) -> (MessagePart, MessagePart) {
        match *self {
            MessagePart::Plain(ref s) => {
                let (l, r) = s.split_at(mid);
                (MessagePart::Plain(l.to_string()), MessagePart::Plain(r[1..].to_string()))
            }
            MessagePart::Colour(c, ref s) => {
                let (l, r) = s.split_at(mid);
                (MessagePart::Colour(c, l.to_string()), MessagePart::Colour(c, r[1..].to_string()))
            }
        }
    }

    fn split_at(&self, mid: usize) -> (MessagePart, MessagePart) {
        match *self {
            MessagePart::Plain(ref s) => {
                let (l, r) = s.split_at(mid);
                (MessagePart::Plain(l.to_string()), MessagePart::Plain(r.to_string()))
            }
            MessagePart::Colour(c, ref s) => {
                let (l, r) = s.split_at(mid);
                (MessagePart::Colour(c, l.to_string()), MessagePart::Colour(c, r.to_string()))
            }
        }
    }

    pub fn string_ref(&self) -> &str {
        match *self {
            MessagePart::Plain(ref s) => s.as_ref(),
            MessagePart::Colour(_, ref s) => s.as_ref(),
        }
    }
}

pub fn wrap_message(message: &Message, width: usize, wrapped: &mut Vec<Message>) {

    let mut x = 0;
    let mut current_message = Message::new();

    for part in message.iter() {

        let mut next_x = x + part.len();
        current_message.push(part.clone());

        if next_x < width {
            x = next_x;
        } else if next_x == width {
            wrapped.push(mem::replace(&mut current_message, Message::new()));
            x = 0;
        } else {
            while next_x > width {
                let last = current_message.pop().unwrap();
                let mut split_idx = 0;
                let mut idx = 0;
                let mut first = true;
                for ch in last.string_ref().chars() {
                    if idx + x > width {
                        break;
                    }

                    if ch.is_whitespace() {
                        first = false;
                        split_idx = idx;
                    }

                    idx += 1;
                }

                let next_start = if first {
                    if x == 0 {
                        // split the part at its end - there's no whitespace
                        let (this_end, next_start) = last.split_at(width);
                        if !this_end.is_empty() {
                            current_message.push(this_end);
                        }
                        next_start
                    } else {
                        // move the entire part to the next line
                        last
                    }
                } else {
                    // split the part at white space
                    let (this_end, next_start) = last.split_at_exclude_middle(split_idx);
                    if !this_end.is_empty() {
                        current_message.push(this_end);
                    }
                    next_start
                };

                next_x = next_start.len();
                let mut next = Message::new();
                next.push(next_start);
                wrapped.push(mem::replace(&mut current_message, next));
                x = 0;
            }

            x = next_x;
        }
    }

    if x < width {
        wrapped.push(current_message);
    }
}
<|endoftext|>


<commit_before>extern crate game_state;

use game_state::state::State;
use game_state::Renderer;

use std::sync::Arc;

#[no_mangle]
pub extern "C" fn mod_input_load( state: &mut State ) {
    state.input_state.clear();
}

#[no_mangle]
pub extern "C" fn mod_input_tick( state: &mut State ) {
    // Renderers own the input event loop associated with their
    // internals: i.e. the window manager window
    // - get input events and convert them to our internal format
    // and push them into the input events queue

    // we want to clear that queue each tick, regardless of if we dealt with the events
    state.input_state.pending_input_events.clear();

    // Now we want to
    for i in 0 .. state.renderers.len() {
        let mut events = state.renderers[i].get_input_events();
        println!("{}", events);
        state.input_state.pending_input_events.append(&mut events);
    }
}

#[no_mangle]
pub extern "C" fn mod_input_unload( state: &mut State ) {
    state.input_state.clear();
}
<commit_msg>only log when there are actually events<commit_after>extern crate game_state;

use game_state::state::State;
use game_state::Renderer;

use std::sync::Arc;

#[no_mangle]
pub extern "C" fn mod_input_load( state: &mut State ) {
    state.input_state.clear();
}

#[no_mangle]
pub extern "C" fn mod_input_tick( state: &mut State ) {
    // Renderers own the input event loop associated with their
    // internals: i.e. the window manager window
    // - get input events and convert them to our internal format
    // and push them into the input events queue

    // we want to clear that queue each tick, regardless of if we dealt with the events
    state.input_state.pending_input_events.clear();

    // Now we want to
    for i in 0 .. state.renderers.len() {
        let mut events = state.renderers[i].get_input_events();
        if events.len() > 0 {
            println!("Renderer {} -> {:?}", state.renderers[i].identify(), events);
        }
        state.input_state.pending_input_events.append(&mut events);
    }
}

#[no_mangle]
pub extern "C" fn mod_input_unload( state: &mut State ) {
    state.input_state.clear();
}
<|endoftext|>


<commit_before>extern crate autograd as ag;
extern crate ndarray;

use ag::tensor::Variable;
use ag::Graph;

type Tensor<'graph> = ag::Tensor<'graph, f32>;

struct LSTM<'g> {
    vector_dim: usize,
    hs: Vec<Tensor<'g>>,
    cells: Vec<Tensor<'g>>,
    wx: Tensor<'g>,
    wh: Tensor<'g>,
    b: Tensor<'g>,
}

impl<'g> LSTM<'g> {
    fn new(vector_dim: usize, s: &'g Graph<f32>) -> LSTM<'g> {
        let rng = ag::ndarray_ext::ArrayRng::<f32>::default();
        LSTM {
            vector_dim,
            hs: vec![],
            cells: vec![],
            wx: s.variable(rng.random_normal(&[vector_dim, 4 * vector_dim], 0., 0.01)),
            wh: s.variable(rng.random_normal(&[vector_dim, 4 * vector_dim], 0., 0.01)),
            b: s.variable(ag::ndarray_ext::zeros(&[1, 4 * vector_dim])),
        }
    }

    /// Applies standard LSTM unit without peephole to `x`.
    /// `x` must be a tensor with shape `(batch_size, embedding_dim)`
    ///
    /// # Returns
    /// Output tensor of this unit with shape `(batch_size, state_size)`.
    fn step(&mut self, x: Tensor<'g>, s: &'g Graph<f32>) -> &Tensor<'g> {
        let (cell, h) = {
            let ref last_output = self.hs.pop().unwrap_or_else(|| s.zeros(&s.shape(x)));
            let last_cell = self.cells.pop().unwrap_or_else(|| s.zeros(&s.shape(x)));

            let xh = s.matmul(x, self.wx) + s.matmul(last_output, self.wh) + self.b;

            let size = self.vector_dim as isize;
            let i = s.slice(xh, &[0, 0 * size], &[-1, 1 * size]);
            let f = s.slice(xh, &[0, 1 * size], &[-1, 2 * size]);
            let c = s.slice(xh, &[0, 2 * size], &[-1, 3 * size]);
            let o = s.slice(xh, &[0, 3 * size], &[-1, 4 * size]);

            let cell = s.sigmoid(f) * last_cell + s.sigmoid(i) * s.tanh(c);
            let h = s.sigmoid(o) * s.tanh(&cell);
            (cell, h)
        };
        self.cells.push(cell);
        self.hs.push(h);
        self.hs.last().unwrap()
    }
}

// TODO: Use real-world data
// TODO: Write in define-by-run style
pub fn main() {
    let vec_dim = 4;
    let max_sent = 3;
    let vocab_size = 5;

    ag::with(|s| {
        let sentences = s.placeholder(&[-1, max_sent]);
        let ref mut rnn = LSTM::new(vec_dim, s);

        let rng = ag::ndarray_ext::ArrayRng::<f32>::default();
        let lookup_table = s.variable(rng.random_normal(&[vocab_size, vec_dim], 0., 0.01));
        let w_pred = s.variable(rng.random_uniform(&[vec_dim, vocab_size], 0., 0.01));

        // Compute cross entropy losses for each LSTM step
        let losses: Vec<ag::Tensor<_>> = (0..max_sent - 1)
            .map(|i| {
                let cur_id = s.slice(sentences, &[0, i], &[-1, i + 1]);
                let next_id = s.slice(sentences, &[0, i + 1], &[-1, i + 2]);
                let x = s.squeeze(s.gather(lookup_table, &cur_id, 0), &[1]);
                let h = rnn.step(x, s);
                let prediction = s.matmul(h, w_pred);
                s.sparse_softmax_cross_entropy(prediction, next_id)
            })
            .collect();

        // Aggregate losses of generated words
        let loss = s.add_n(&losses);

        // Compute gradients
        let vars = &[rnn.wh, rnn.wx, rnn.b, lookup_table, w_pred];
        let grads = s.grad(&[loss], vars);

        // test with toy data
        ag::test_helper::check_theoretical_grads(
            loss,
            grads.as_slice(),
            vars,
            &[sentences.given(
                ndarray::arr2(&[[2., 3., 1.], [3., 0., 1.]])
                    .into_dyn()
                    .view(),
            )],
            1e-3,
            1e-3,
        );
    });
}
<commit_msg>Amended array definition as required by autograd<commit_after>extern crate autograd as ag;
extern crate ndarray;

use ag::tensor::Variable;
use ag::Graph;

type Tensor<'graph> = ag::Tensor<'graph, f32>;

struct LSTM<'g> {
    vector_dim: usize,
    hs: Vec<Tensor<'g>>,
    cells: Vec<Tensor<'g>>,
    wx: Tensor<'g>,
    wh: Tensor<'g>,
    b: Tensor<'g>,
}

impl<'g> LSTM<'g> {
    fn new(vector_dim: usize, s: &'g Graph<f32>) -> LSTM<'g> {
        let rng = ag::ndarray_ext::ArrayRng::<f32>::default();
        LSTM {
            vector_dim,
            hs: vec![],
            cells: vec![],
            wx: s.variable(rng.random_normal(&[vector_dim, 4 * vector_dim], 0., 0.01)),
            wh: s.variable(rng.random_normal(&[vector_dim, 4 * vector_dim], 0., 0.01)),
            b: s.variable(ag::ndarray_ext::zeros(&[1, 4 * vector_dim])),
        }
    }

    /// Applies standard LSTM unit without peephole to `x`.
    /// `x` must be a tensor with shape `(batch_size, embedding_dim)`
    ///
    /// # Returns
    /// Output tensor of this unit with shape `(batch_size, state_size)`.
    fn step(&mut self, x: Tensor<'g>, s: &'g Graph<f32>) -> &Tensor<'g> {
        let (cell, h) = {
            let ref last_output = self.hs.pop().unwrap_or_else(|| s.zeros(&s.shape(x)));
            let last_cell = self.cells.pop().unwrap_or_else(|| s.zeros(&s.shape(x)));

            let xh = s.matmul(x, self.wx) + s.matmul(last_output, self.wh) + self.b;

            let size = self.vector_dim as isize;
            let i = s.slice(xh, &[0, 0 * size], &[-1, 1 * size]);
            let f = s.slice(xh, &[0, 1 * size], &[-1, 2 * size]);
            let c = s.slice(xh, &[0, 2 * size], &[-1, 3 * size]);
            let o = s.slice(xh, &[0, 3 * size], &[-1, 4 * size]);

            let cell = s.sigmoid(f) * last_cell + s.sigmoid(i) * s.tanh(c);
            let h = s.sigmoid(o) * s.tanh(&cell);
            (cell, h)
        };
        self.cells.push(cell);
        self.hs.push(h);
        self.hs.last().unwrap()
    }
}

// TODO: Use real-world data
// TODO: Write in define-by-run style
pub fn main() {
    let vec_dim = 4;
    let max_sent = 3;
    let vocab_size = 5;

    ag::with(|s| {
        let sentences = s.placeholder(&[-1, max_sent]);
        let ref mut rnn = LSTM::new(vec_dim, s);

        let rng = ag::ndarray_ext::ArrayRng::<f32>::default();
        let lookup_table = s.variable(rng.random_normal(&[vocab_size, vec_dim], 0., 0.01));
        let w_pred = s.variable(rng.random_uniform(&[vec_dim, vocab_size], 0., 0.01));

        // Compute cross entropy losses for each LSTM step
        let losses: Vec<ag::Tensor<_>> = (0..max_sent - 1)
            .map(|i| {
                let cur_id = s.slice(sentences, &[0, i], &[-1, i + 1]);
                let next_id = s.slice(sentences, &[0, i + 1], &[-1, i + 2]);
                let x = s.squeeze(s.gather(lookup_table, &cur_id, 0), &[1]);
                let h = rnn.step(x, s);
                let prediction = s.matmul(h, w_pred);
                s.sparse_softmax_cross_entropy(prediction, next_id)
            })
            .collect();

        // Aggregate losses of generated words
        let loss = s.add_n(&losses);

        // Compute gradients
        let vars = &[rnn.wh, rnn.wx, rnn.b, lookup_table, w_pred];
        let grads = s.grad(&[loss], vars);

        // test with toy data
        ag::test_helper::check_theoretical_grads(
            loss,
            grads.as_slice(),
            vars,
            &[sentences.given(
                ag::ndarray::arr2(&[[2., 3., 1.], [3., 0., 1.]])
                    .into_dyn()
                    .view(),
            )],
            1e-3,
            1e-3,
        );
    });
}
<|endoftext|>