<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

//! An implementation of the visitor pattern for the HIR.
//!
//! This module defines the [`Visitor`] trait that allows the HIR tree graph to
//! be visited.

use super::{nodes::*, HirNode};
use crate::{
    common::{name::Name, source::Spanned, NodeId},
    Context,
};

/// A visitor of the HIR.
pub trait Visitor<'a>: Sized {
    /// The type of context that this visitor uses.
    type Context: Context<'a>;

    /// Get the context to be used to resolve queries.
    fn context(&self) -> &Self::Context;

    fn visit_node_with_id(&mut self, node_id: NodeId, lvalue: bool) {
        match self.context().hir_of(node_id) {
            Ok(x) => self.visit_node(x, lvalue),
            Err(()) => (),
        }
    }

    fn visit_node(&mut self, node: HirNode<'a>, lvalue: bool) {
        match node {
            HirNode::Module(x) => self.visit_module(x),
            HirNode::Proc(x) => self.visit_proc(x),
            HirNode::Stmt(x) => self.visit_stmt(x),
            HirNode::Expr(x) => self.visit_expr(x, lvalue),
            HirNode::EventExpr(x) => self.visit_event_expr(x),
            HirNode::Typedef(x) => self.visit_typedef(x),
            HirNode::VarDecl(x) => self.visit_var_decl(x),
            HirNode::Assign(x) => self.visit_assign(x),
            HirNode::IntPort(x) => self.visit_int_port(x),
            HirNode::ExtPort(x) => self.visit_ext_port(x),
            HirNode::Inst(x) => self.visit_inst(x),
            _ => (),
        }
    }

    fn visit_ident(&mut self, _ident: Spanned<Name>) {}
    fn visit_unary_op(&mut self, _op: UnaryOp) {}
    fn visit_binary_op(&mut self, _op: BinaryOp) {}

    fn visit_module(&mut self, module: &'a Module) {
        walk_module(self, module)
    }

    fn visit_proc(&mut self, prok: &'a Proc) {
        walk_proc(self, prok)
    }

    fn visit_stmt(&mut self, stmt: &'a Stmt) {
        walk_stmt(self, stmt)
    }

    fn visit_expr(&mut self, expr: &'a Expr, lvalue: bool) {
        walk_expr(self, expr, lvalue);
    }

    fn visit_timing_control(&mut self, ctrl: &'a TimingControl) {
        walk_timing_control(self, ctrl);
    }

    fn visit_event_expr(&mut self, expr: &'a EventExpr) {
        walk_event_expr(self, expr);
    }

    fn visit_event(&mut self, event: &'a Event) {
        walk_event(self, event);
    }

    fn visit_typedef(&mut self, typedef: &'a Typedef) {
        walk_typedef(self, typedef);
    }

    fn visit_var_decl(&mut self, decl: &'a VarDecl) {
        walk_var_decl(self, decl);
    }

    fn visit_assign(&mut self, assign: &'a Assign) {
        walk_assign(self, assign);
    }

    fn visit_int_port(&mut self, int_port: &'a IntPort) {
        walk_int_port(self, int_port);
    }

    fn visit_ext_port(&mut self, ext_port: &'a ExtPort) {
        walk_ext_port(self, ext_port);
    }

    fn visit_inst(&mut self, _hir: &'a Inst) {}
}

/// Walk the contents of a module.
pub fn walk_module<'a>(visitor: &mut impl Visitor<'a>, module: &'a Module) {
    for port in &module.ports_new.int {
        visitor.visit_node_with_id(port.id, false);
    }
    for port in &module.ports_new.ext_pos {
        visitor.visit_node_with_id(port.id, false);
    }
    for &id in module.params {
        visitor.visit_node_with_id(id, false);
    }
    walk_module_block(visitor, &module.block);
}

/// Walk the contents of a module block.
pub fn walk_module_block<'a>(visitor: &mut impl Visitor<'a>, blk: &'a ModuleBlock) {
    for &id in &blk.insts {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.decls {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.procs {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.gens {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.params {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.assigns {
        visitor.visit_node_with_id(id, false);
    }
}

/// Walk the contents of a procedure.
pub fn walk_proc<'a>(visitor: &mut impl Visitor<'a>, prok: &'a Proc) {
    visitor.visit_node_with_id(prok.stmt, false);
}

/// Walk the contents of a statement.
pub fn walk_stmt<'a>(visitor: &mut impl Visitor<'a>, stmt: &'a Stmt) {
    #[allow(unreachable_patterns)]
    match stmt.kind {
        StmtKind::Null => (),
        StmtKind::Block(ref stmts) => {
            for &id in stmts {
                visitor.visit_node_with_id(id, false);
            }
        }
        StmtKind::Assign { lhs, rhs, .. } => {
            visitor.visit_node_with_id(lhs, true);
            visitor.visit_node_with_id(rhs, false);
        }
        StmtKind::Timed { ref control, stmt } => {
            visitor.visit_timing_control(control);
            visitor.visit_node_with_id(stmt, false);
        }
        StmtKind::Expr(expr) => visitor.visit_node_with_id(expr, false),
        StmtKind::If {
            cond,
            main_stmt,
            else_stmt,
        } => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(main_stmt, false);
            if let Some(else_stmt) = else_stmt {
                visitor.visit_node_with_id(else_stmt, false);
            }
        }
        StmtKind::Loop { kind, body } => {
            match kind {
                LoopKind::Forever => (),
                LoopKind::Repeat(id) | LoopKind::While(id) | LoopKind::Do(id) => {
                    visitor.visit_node_with_id(id, false);
                }
                LoopKind::For(init, cond, step) => {
                    visitor.visit_node_with_id(init, false);
                    visitor.visit_node_with_id(cond, false);
                    visitor.visit_node_with_id(step, false);
                }
            }
            visitor.visit_node_with_id(body, false);
        }
        StmtKind::InlineGroup { ref stmts, .. } => {
            for &stmt in stmts {
                visitor.visit_node_with_id(stmt, false);
            }
        }
        StmtKind::Case {
            expr,
            ref ways,
            default,
            ..
        } => {
            visitor.visit_node_with_id(expr, false);
            for &(ref exprs, stmt) in ways {
                for &expr in exprs {
                    visitor.visit_node_with_id(expr, false);
                }
                visitor.visit_node_with_id(stmt, false);
            }
            if let Some(default) = default {
                visitor.visit_node_with_id(default, false);
            }
        }
    }
}

/// Walk the contents of an expression.
pub fn walk_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a Expr, lvalue: bool) {
    match expr.kind {
        ExprKind::Builtin(BuiltinCall::Unsupported)
        | ExprKind::IntConst { .. }
        | ExprKind::UnsizedConst(_)
        | ExprKind::TimeConst(_)
        | ExprKind::StringConst(_) => (),
        ExprKind::Ident(x) => {
            visitor.visit_ident(x);
        }
        ExprKind::Unary(op, arg) => {
            visitor.visit_unary_op(op);
            visitor.visit_node_with_id(arg, lvalue);
        }
        ExprKind::Binary(op, lhs, rhs) => {
            visitor.visit_binary_op(op);
            visitor.visit_node_with_id(lhs, lvalue);
            visitor.visit_node_with_id(rhs, lvalue);
        }
        ExprKind::Field(expr, _) => {
            visitor.visit_node_with_id(expr, lvalue);
        }
        ExprKind::Index(expr, mode) => {
            visitor.visit_node_with_id(expr, lvalue);
            match mode {
                IndexMode::One(expr) => visitor.visit_node_with_id(expr, false),
                IndexMode::Many(_, lhs, rhs) => {
                    visitor.visit_node_with_id(lhs, false);
                    visitor.visit_node_with_id(rhs, false);
                }
            }
        }
        ExprKind::Builtin(BuiltinCall::Clog2(arg))
        | ExprKind::Builtin(BuiltinCall::Bits(arg))
        | ExprKind::Builtin(BuiltinCall::Signed(arg))
        | ExprKind::Builtin(BuiltinCall::Unsigned(arg)) => {
            visitor.visit_node_with_id(arg, false);
        }
        ExprKind::Ternary(cond, true_expr, false_expr) => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(true_expr, lvalue);
            visitor.visit_node_with_id(false_expr, lvalue);
        }
        ExprKind::Scope(expr, _) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::PositionalPattern(ref exprs) => {
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::NamedPattern(ref mappings) => {
            for &(key, value) in mappings {
                match key {
                    PatternMapping::Type(ty) => visitor.visit_node_with_id(ty, false),
                    PatternMapping::Member(expr) => visitor.visit_node_with_id(expr, false),
                    PatternMapping::Default => (),
                }
                visitor.visit_node_with_id(value, lvalue);
            }
        }
        ExprKind::RepeatPattern(count, ref exprs) => {
            visitor.visit_node_with_id(count, lvalue);
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::EmptyPattern => (),
        ExprKind::Concat(repeat, ref exprs) => {
            if let Some(repeat) = repeat {
                visitor.visit_node_with_id(repeat, false);
            }
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::Cast(ty, expr) => {
            visitor.visit_node_with_id(ty, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSign(_, expr) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSize(size_expr, expr) => {
            visitor.visit_node_with_id(size_expr, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::Inside(expr, ref ranges) => {
            visitor.visit_node_with_id(expr, false);
            for r in ranges {
                match r.value {
                    InsideRange::Single(expr) => visitor.visit_node_with_id(expr, false),
                    InsideRange::Range(lo, hi) => {
                        visitor.visit_node_with_id(lo, false);
                        visitor.visit_node_with_id(hi, false);
                    }
                }
            }
        }
        ExprKind::FunctionCall(_, ref args) => {
            for &arg in args {
                if let Some(expr) = arg.expr {
                    visitor.visit_node_with_id(expr, false);
                }
            }
        }
    }
}

/// Walk the contents of a timing control block.
pub fn walk_timing_control<'a>(visitor: &mut impl Visitor<'a>, ctrl: &'a TimingControl) {
    match *ctrl {
        TimingControl::Delay(id) => visitor.visit_node_with_id(id, false),
        TimingControl::ImplicitEvent => (),
        TimingControl::ExplicitEvent(id) => visitor.visit_node_with_id(id, false),
    }
}

/// Walk the contents of an event expression.
pub fn walk_event_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a EventExpr) {
    for event in &expr.events {
        visitor.visit_event(event);
    }
}

/// Walk the contents of an event.
pub fn walk_event<'a>(visitor: &mut impl Visitor<'a>, event: &'a Event) {
    visitor.visit_node_with_id(event.expr, false);
    for &iff in &event.iff {
        visitor.visit_node_with_id(iff, false);
    }
}

/// Walk the contents of a typedef.
pub fn walk_typedef<'a>(visitor: &mut impl Visitor<'a>, typedef: &'a Typedef) {
    visitor.visit_node_with_id(typedef.ty, false);
}

/// Walk the contents of a variable declaration.
pub fn walk_var_decl<'a>(visitor: &mut impl Visitor<'a>, decl: &'a VarDecl) {
    visitor.visit_node_with_id(decl.ty, false);
    if let Some(init) = decl.init {
        visitor.visit_node_with_id(init, false);
    }
}

/// Walk the contents of an assignment.
pub fn walk_assign<'a>(visitor: &mut impl Visitor<'a>, assign: &'a Assign) {
    visitor.visit_node_with_id(assign.lhs, true);
    visitor.visit_node_with_id(assign.rhs, false);
}

/// Walk the contents of an internal port.
pub fn walk_int_port<'a>(visitor: &mut impl Visitor<'a>, int_port: &'a IntPort) {
    if let Some(data) = &int_port.data {
        visitor.visit_node_with_id(data.ty, false);
        if let Some(default) = data.default {
            visitor.visit_node_with_id(default, false);
        }
    }
}

/// Walk the contents of an external port.
pub fn walk_ext_port<'a>(_visitor: &mut impl Visitor<'a>, _ext_port: &'a ExtPort) {}
<commit_msg>svlog: hir: Add inst params/ports to visitor<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

//! An implementation of the visitor pattern for the HIR.
//!
//! This module defines the [`Visitor`] trait that allows the HIR tree graph to
//! be visited.

use super::{nodes::*, HirNode};
use crate::{
    common::{name::Name, source::Spanned, NodeId},
    Context,
};

/// A visitor of the HIR.
pub trait Visitor<'a>: Sized {
    /// The type of context that this visitor uses.
    type Context: Context<'a>;

    /// Get the context to be used to resolve queries.
    fn context(&self) -> &Self::Context;

    fn visit_node_with_id(&mut self, node_id: NodeId, lvalue: bool) {
        match self.context().hir_of(node_id) {
            Ok(x) => self.visit_node(x, lvalue),
            Err(()) => (),
        }
    }

    fn visit_node(&mut self, node: HirNode<'a>, lvalue: bool) {
        match node {
            HirNode::Module(x) => self.visit_module(x),
            HirNode::Proc(x) => self.visit_proc(x),
            HirNode::Stmt(x) => self.visit_stmt(x),
            HirNode::Expr(x) => self.visit_expr(x, lvalue),
            HirNode::EventExpr(x) => self.visit_event_expr(x),
            HirNode::Typedef(x) => self.visit_typedef(x),
            HirNode::VarDecl(x) => self.visit_var_decl(x),
            HirNode::Assign(x) => self.visit_assign(x),
            HirNode::IntPort(x) => self.visit_int_port(x),
            HirNode::ExtPort(x) => self.visit_ext_port(x),
            HirNode::Inst(x) => self.visit_inst(x),
            HirNode::InstTarget(x) => self.visit_inst_target(x),
            _ => (),
        }
    }

    fn visit_ident(&mut self, _ident: Spanned<Name>) {}
    fn visit_unary_op(&mut self, _op: UnaryOp) {}
    fn visit_binary_op(&mut self, _op: BinaryOp) {}

    fn visit_module(&mut self, module: &'a Module) {
        walk_module(self, module)
    }

    fn visit_proc(&mut self, prok: &'a Proc) {
        walk_proc(self, prok)
    }

    fn visit_stmt(&mut self, stmt: &'a Stmt) {
        walk_stmt(self, stmt)
    }

    fn visit_expr(&mut self, expr: &'a Expr, lvalue: bool) {
        walk_expr(self, expr, lvalue);
    }

    fn visit_timing_control(&mut self, ctrl: &'a TimingControl) {
        walk_timing_control(self, ctrl);
    }

    fn visit_event_expr(&mut self, expr: &'a EventExpr) {
        walk_event_expr(self, expr);
    }

    fn visit_event(&mut self, event: &'a Event) {
        walk_event(self, event);
    }

    fn visit_typedef(&mut self, typedef: &'a Typedef) {
        walk_typedef(self, typedef);
    }

    fn visit_var_decl(&mut self, decl: &'a VarDecl) {
        walk_var_decl(self, decl);
    }

    fn visit_assign(&mut self, assign: &'a Assign) {
        walk_assign(self, assign);
    }

    fn visit_int_port(&mut self, int_port: &'a IntPort) {
        walk_int_port(self, int_port);
    }

    fn visit_ext_port(&mut self, ext_port: &'a ExtPort) {
        walk_ext_port(self, ext_port);
    }

    fn visit_inst(&mut self, hir: &'a Inst) {
        walk_inst(self, hir);
    }

    fn visit_inst_target(&mut self, hir: &'a InstTarget) {
        walk_inst_target(self, hir);
    }
}

/// Walk the contents of a module.
pub fn walk_module<'a>(visitor: &mut impl Visitor<'a>, module: &'a Module) {
    for port in &module.ports_new.int {
        visitor.visit_node_with_id(port.id, false);
    }
    for port in &module.ports_new.ext_pos {
        visitor.visit_node_with_id(port.id, false);
    }
    for &id in module.params {
        visitor.visit_node_with_id(id, false);
    }
    walk_module_block(visitor, &module.block);
}

/// Walk the contents of a module block.
pub fn walk_module_block<'a>(visitor: &mut impl Visitor<'a>, blk: &'a ModuleBlock) {
    for &id in &blk.insts {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.decls {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.procs {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.gens {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.params {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.assigns {
        visitor.visit_node_with_id(id, false);
    }
}

/// Walk the contents of a procedure.
pub fn walk_proc<'a>(visitor: &mut impl Visitor<'a>, prok: &'a Proc) {
    visitor.visit_node_with_id(prok.stmt, false);
}

/// Walk the contents of a statement.
pub fn walk_stmt<'a>(visitor: &mut impl Visitor<'a>, stmt: &'a Stmt) {
    #[allow(unreachable_patterns)]
    match stmt.kind {
        StmtKind::Null => (),
        StmtKind::Block(ref stmts) => {
            for &id in stmts {
                visitor.visit_node_with_id(id, false);
            }
        }
        StmtKind::Assign { lhs, rhs, .. } => {
            visitor.visit_node_with_id(lhs, true);
            visitor.visit_node_with_id(rhs, false);
        }
        StmtKind::Timed { ref control, stmt } => {
            visitor.visit_timing_control(control);
            visitor.visit_node_with_id(stmt, false);
        }
        StmtKind::Expr(expr) => visitor.visit_node_with_id(expr, false),
        StmtKind::If {
            cond,
            main_stmt,
            else_stmt,
        } => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(main_stmt, false);
            if let Some(else_stmt) = else_stmt {
                visitor.visit_node_with_id(else_stmt, false);
            }
        }
        StmtKind::Loop { kind, body } => {
            match kind {
                LoopKind::Forever => (),
                LoopKind::Repeat(id) | LoopKind::While(id) | LoopKind::Do(id) => {
                    visitor.visit_node_with_id(id, false);
                }
                LoopKind::For(init, cond, step) => {
                    visitor.visit_node_with_id(init, false);
                    visitor.visit_node_with_id(cond, false);
                    visitor.visit_node_with_id(step, false);
                }
            }
            visitor.visit_node_with_id(body, false);
        }
        StmtKind::InlineGroup { ref stmts, .. } => {
            for &stmt in stmts {
                visitor.visit_node_with_id(stmt, false);
            }
        }
        StmtKind::Case {
            expr,
            ref ways,
            default,
            ..
        } => {
            visitor.visit_node_with_id(expr, false);
            for &(ref exprs, stmt) in ways {
                for &expr in exprs {
                    visitor.visit_node_with_id(expr, false);
                }
                visitor.visit_node_with_id(stmt, false);
            }
            if let Some(default) = default {
                visitor.visit_node_with_id(default, false);
            }
        }
    }
}

/// Walk the contents of an expression.
pub fn walk_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a Expr, lvalue: bool) {
    match expr.kind {
        ExprKind::Builtin(BuiltinCall::Unsupported)
        | ExprKind::IntConst { .. }
        | ExprKind::UnsizedConst(_)
        | ExprKind::TimeConst(_)
        | ExprKind::StringConst(_) => (),
        ExprKind::Ident(x) => {
            visitor.visit_ident(x);
        }
        ExprKind::Unary(op, arg) => {
            visitor.visit_unary_op(op);
            visitor.visit_node_with_id(arg, lvalue);
        }
        ExprKind::Binary(op, lhs, rhs) => {
            visitor.visit_binary_op(op);
            visitor.visit_node_with_id(lhs, lvalue);
            visitor.visit_node_with_id(rhs, lvalue);
        }
        ExprKind::Field(expr, _) => {
            visitor.visit_node_with_id(expr, lvalue);
        }
        ExprKind::Index(expr, mode) => {
            visitor.visit_node_with_id(expr, lvalue);
            match mode {
                IndexMode::One(expr) => visitor.visit_node_with_id(expr, false),
                IndexMode::Many(_, lhs, rhs) => {
                    visitor.visit_node_with_id(lhs, false);
                    visitor.visit_node_with_id(rhs, false);
                }
            }
        }
        ExprKind::Builtin(BuiltinCall::Clog2(arg))
        | ExprKind::Builtin(BuiltinCall::Bits(arg))
        | ExprKind::Builtin(BuiltinCall::Signed(arg))
        | ExprKind::Builtin(BuiltinCall::Unsigned(arg)) => {
            visitor.visit_node_with_id(arg, false);
        }
        ExprKind::Ternary(cond, true_expr, false_expr) => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(true_expr, lvalue);
            visitor.visit_node_with_id(false_expr, lvalue);
        }
        ExprKind::Scope(expr, _) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::PositionalPattern(ref exprs) => {
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::NamedPattern(ref mappings) => {
            for &(key, value) in mappings {
                match key {
                    PatternMapping::Type(ty) => visitor.visit_node_with_id(ty, false),
                    PatternMapping::Member(expr) => visitor.visit_node_with_id(expr, false),
                    PatternMapping::Default => (),
                }
                visitor.visit_node_with_id(value, lvalue);
            }
        }
        ExprKind::RepeatPattern(count, ref exprs) => {
            visitor.visit_node_with_id(count, lvalue);
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::EmptyPattern => (),
        ExprKind::Concat(repeat, ref exprs) => {
            if let Some(repeat) = repeat {
                visitor.visit_node_with_id(repeat, false);
            }
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::Cast(ty, expr) => {
            visitor.visit_node_with_id(ty, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSign(_, expr) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSize(size_expr, expr) => {
            visitor.visit_node_with_id(size_expr, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::Inside(expr, ref ranges) => {
            visitor.visit_node_with_id(expr, false);
            for r in ranges {
                match r.value {
                    InsideRange::Single(expr) => visitor.visit_node_with_id(expr, false),
                    InsideRange::Range(lo, hi) => {
                        visitor.visit_node_with_id(lo, false);
                        visitor.visit_node_with_id(hi, false);
                    }
                }
            }
        }
        ExprKind::FunctionCall(_, ref args) => {
            for &arg in args {
                if let Some(expr) = arg.expr {
                    visitor.visit_node_with_id(expr, false);
                }
            }
        }
    }
}

/// Walk the contents of a timing control block.
pub fn walk_timing_control<'a>(visitor: &mut impl Visitor<'a>, ctrl: &'a TimingControl) {
    match *ctrl {
        TimingControl::Delay(id) => visitor.visit_node_with_id(id, false),
        TimingControl::ImplicitEvent => (),
        TimingControl::ExplicitEvent(id) => visitor.visit_node_with_id(id, false),
    }
}

/// Walk the contents of an event expression.
pub fn walk_event_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a EventExpr) {
    for event in &expr.events {
        visitor.visit_event(event);
    }
}

/// Walk the contents of an event.
pub fn walk_event<'a>(visitor: &mut impl Visitor<'a>, event: &'a Event) {
    visitor.visit_node_with_id(event.expr, false);
    for &iff in &event.iff {
        visitor.visit_node_with_id(iff, false);
    }
}

/// Walk the contents of a typedef.
pub fn walk_typedef<'a>(visitor: &mut impl Visitor<'a>, typedef: &'a Typedef) {
    visitor.visit_node_with_id(typedef.ty, false);
}

/// Walk the contents of a variable declaration.
pub fn walk_var_decl<'a>(visitor: &mut impl Visitor<'a>, decl: &'a VarDecl) {
    visitor.visit_node_with_id(decl.ty, false);
    if let Some(init) = decl.init {
        visitor.visit_node_with_id(init, false);
    }
}

/// Walk the contents of an assignment.
pub fn walk_assign<'a>(visitor: &mut impl Visitor<'a>, assign: &'a Assign) {
    visitor.visit_node_with_id(assign.lhs, true);
    visitor.visit_node_with_id(assign.rhs, false);
}

/// Walk the contents of an internal port.
pub fn walk_int_port<'a>(visitor: &mut impl Visitor<'a>, int_port: &'a IntPort) {
    if let Some(data) = &int_port.data {
        visitor.visit_node_with_id(data.ty, false);
        if let Some(default) = data.default {
            visitor.visit_node_with_id(default, false);
        }
    }
}

/// Walk the contents of an external port.
pub fn walk_ext_port<'a>(_visitor: &mut impl Visitor<'a>, _ext_port: &'a ExtPort) {}

/// Walk the contents of an instantiation.
pub fn walk_inst<'a>(visitor: &mut impl Visitor<'a>, hir: &'a Inst) {
    visitor.visit_node_with_id(hir.target, false);
    let pos_ports = hir.pos_ports.iter().flat_map(|&(_, p)| p);
    let named_ports = hir.named_ports.iter().flat_map(|&(_, _, p)| p);
    for p in pos_ports.chain(named_ports) {
        visitor.visit_node_with_id(p, false);
    }
}

/// Walk the contents of an instantiation target.
pub fn walk_inst_target<'a>(visitor: &mut impl Visitor<'a>, hir: &'a InstTarget) {
    let pos_params = hir.pos_params.iter().flat_map(|&(_, p)| p);
    let named_params = hir.named_params.iter().flat_map(|&(_, _, p)| p);
    for p in pos_params.chain(named_params) {
        visitor.visit_node_with_id(p, false);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::io::{Error, ErrorKind, Read, Result};
use std::fs::File;
use std::fs;

use filter::{FilterFunction, DEFAULT_FILTERS, CHRONO_FILTERS};
use template::Template;
use context::Context;

pub type FilterStorage = HashMap<String, FilterFunction>;

fn read_file(path: &Path) -> Result<String> {
    let mut text = String::new();
    let mut file = try!(File::open(path));
    try!(file.read_to_string(&mut text));
    Ok(text)
}

pub struct TemplateCompiler {
	pub filters: FilterStorage,
	pub root: PathBuf,
}

impl TemplateCompiler {
	fn add_filters(storage: &mut FilterStorage, filters: &[(&str, FilterFunction)]) {
		for i in (0..filters.len()) {
			let (name, func) = filters[i];
			storage.insert(name.to_string(), func);
		}
	}

	fn get_default_filters() -> FilterStorage {
		let mut storage: FilterStorage = HashMap::new();
		Self::add_filters(&mut storage, &DEFAULT_FILTERS);
		if cfg!(feature = "chrono") {
			Self::add_filters(&mut storage, &CHRONO_FILTERS);
		}
		storage
	}

	pub fn new(root: PathBuf) -> Result<TemplateCompiler> {
	    let metadata = try!(fs::metadata(root.clone()));
	    match metadata.is_dir() {
	    	true => Ok(
	    		TemplateCompiler {
					root: root,
					filters: Self::get_default_filters(),
				}
    		),
	    	false => Err(
	    		Error::new(
	    			ErrorKind::InvalidInput,
	    			format!("{} is not directory", root.as_path().display())
    			)
    		),
	    }
	}

	pub fn compile_file(&self, path: &Path) -> Result<Template> {
	    let mut filepath = self.root.clone();
	    filepath.push(path);
		let text = try!(read_file(filepath.as_path()));
		Template::compile(text, self)
	}

	pub fn render_file(root: PathBuf, path: &Path, context: &Context) -> Result<String> {
		let compiler = try!(Self::new(root));
		Ok(try!(compiler.compile_file(path)).render(context))
	}

	pub fn add_filter(&mut self, name: String, function: FilterFunction) {
		self.filters.insert(name, function);
	}
}<commit_msg>Added TemplateCompiler::render<commit_after>use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::io::{Error, ErrorKind, Read, Result};
use std::fs::File;
use std::fs;

use filter::{FilterFunction, DEFAULT_FILTERS, CHRONO_FILTERS};
use template::Template;
use context::Context;

pub type FilterStorage = HashMap<String, FilterFunction>;

fn read_file(path: &Path) -> Result<String> {
    let mut text = String::new();
    let mut file = try!(File::open(path));
    try!(file.read_to_string(&mut text));
    Ok(text)
}

pub struct TemplateCompiler {
	pub filters: FilterStorage,
	pub root: PathBuf,
}

impl TemplateCompiler {
	fn add_filters(storage: &mut FilterStorage, filters: &[(&str, FilterFunction)]) {
		for i in (0..filters.len()) {
			let (name, func) = filters[i];
			storage.insert(name.to_string(), func);
		}
	}

	fn get_default_filters() -> FilterStorage {
		let mut storage: FilterStorage = HashMap::new();
		Self::add_filters(&mut storage, &DEFAULT_FILTERS);
		if cfg!(feature = "chrono") {
			Self::add_filters(&mut storage, &CHRONO_FILTERS);
		}
		storage
	}

	pub fn new(root: PathBuf) -> Result<TemplateCompiler> {
	    let metadata = try!(fs::metadata(root.clone()));
	    match metadata.is_dir() {
	    	true => Ok(
	    		TemplateCompiler {
					root: root,
					filters: Self::get_default_filters(),
				}
    		),
	    	false => Err(
	    		Error::new(
	    			ErrorKind::InvalidInput,
	    			format!("{} is not directory", root.as_path().display())
    			)
    		),
	    }
	}

	pub fn compile_file(&self, path: &Path) -> Result<Template> {
	    let mut filepath = self.root.clone();
	    filepath.push(path);
		let text = try!(read_file(filepath.as_path()));
		Template::compile(text, self)
	}

	pub fn render_file(root: PathBuf, path: &Path, context: &Context) -> Result<String> {
		let compiler = try!(Self::new(root));
		Ok(try!(compiler.compile_file(path)).render(context))
	}

	pub fn render(&self, path: &Path, context: &Context) -> Result<String> {
		Ok(try!(self.compile_file(path)).render(context))
	}

	pub fn add_filter(&mut self, name: String, function: FilterFunction) {
		self.filters.insert(name, function);
	}
}<|endoftext|>


<commit_before>use std::iter;
use std::fmt;
use std::cmp::Ordering;
use super::{ST, OrderedST};
// FIXME: out implementation can't be used. :(
// use super::super::stacks_and_queues::Queue;
// use super::super::stacks_and_queues::resizing_array_queue::ResizingArrayQueue;

pub struct Node<K, V> {
    key: K,
    val: V,
    left:  Option<Box<Node<K, V>>>,
    right: Option<Box<Node<K, V>>>
}

impl<K, V> Node<K, V> {
    pub fn new(key: K, val: V) -> Node<K, V> {
        Node {
            key: key,
            val: val,
            left: None,
            right: None
        }
    }

    fn size(&self) -> usize {
        let mut ret = 1;
        if self.left.is_some() {
            ret += self.left.as_ref().unwrap().size()
        }
        if self.right.is_some() {
            ret += self.right.as_ref().unwrap().size()
        }
        ret
    }
}

impl<K: fmt::Debug, V: fmt::Debug> Node<K, V> {
    fn dump(&self, depth: usize, f: &mut fmt::Formatter, symbol: char) {
        if depth == 0 {
            writeln!(f, "{:?}[{:?}]", self.key, self.val).unwrap();
        } else {
            writeln!(f, "{}{}--{:?}[{:?}]", iter::repeat("|  ").take(depth-1).collect::<Vec<&str>>().concat(),
                     symbol, self.key, self.val).unwrap();
        }
        if self.left.is_some() {
            self.left.as_ref().unwrap().dump(depth + 1, f, '+');
        }
        if self.right.is_some() {
            self.right.as_ref().unwrap().dump(depth + 1, f, '`');
        }
    }
}

fn put<K: Ord, V>(x: Option<Box<Node<K,V>>>, key: K, val: V) -> Option<Box<Node<K,V>>> {
    let mut x = x;
    if x.is_none() {
        return Some(Box::new(Node::new(key, val)));
    }
    let cmp = key.cmp(&x.as_ref().unwrap().key);
    match cmp {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = put(left, key, val)
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = put(right, key, val)
        },
        Ordering::Equal => {
            x.as_mut().unwrap().val = val
        }
    }
    x
}

fn min<K: Ord, V>(x: &mut Option<Box<Node<K,V>>>) -> &mut Option<Box<Node<K,V>>> {
    if x.is_none() {
        return x;
    }
    if x.as_ref().unwrap().left.is_none() {
        x
    } else {
        min(&mut x.as_mut().unwrap().left)
    }
}

fn delete<K: Ord, V>(x: Option<Box<Node<K,V>>>, key: &K) -> Option<Box<Node<K,V>>> {
    if x.is_none() {
        return None;
    }

    let mut x = x;
    match key.cmp(&x.as_ref().unwrap().key) {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = delete(left, key);
            return x;
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = delete(right, key);
            return x;
        },
        Ordering::Equal => {
            if x.as_ref().unwrap().right.is_none() {
                return x.as_mut().unwrap().left.take();
            }
            if x.as_ref().unwrap().left.is_none() {
                return x.as_mut().unwrap().right.take();
            }

            // Save top
            let mut t = x;

            // split right into right without min, and the min
            let (mut right, mut right_min) = delete_min(t.as_mut().unwrap().right.take());
            x = right_min;
            x.as_mut().unwrap().right = right;
            x.as_mut().unwrap().left = t.as_mut().unwrap().left.take();
            x
        }
    }
}

pub struct BST<K, V> {
    root: Option<Box<Node<K, V>>>
}

impl<K: Ord, V> ST<K, V> for BST<K, V> {
    fn new() -> BST<K, V> {
        BST { root: None }
    }

    fn get(&self, key: &K) -> Option<&V> {
        let mut x = self.root.as_ref();
        while x.is_some() {
            match key.cmp(&x.unwrap().key) {
                Ordering::Less => {
                    x = x.unwrap().left.as_ref();
                },
                Ordering::Greater => {
                    x = x.unwrap().right.as_ref();
                },
                Ordering::Equal  => {
                    return Some(&x.unwrap().val)
                }
            }
        }
        None
    }

    fn put(&mut self, key: K, val: V) {
        self.root = put(self.root.take(), key, val);
    }

    fn delete(&mut self, key: &K) {
        self.root = delete(self.root.take(), key);
    }

    fn is_empty(&self) -> bool {
        self.root.is_none()
    }

    /// number of key-value pairs in the table
    fn size(&self) -> usize {
        if self.is_empty() {
            0
        } else {
            self.root.as_ref().unwrap().size()
        }
    }
}

fn floor<'a, K: Ord, V>(x: Option<&'a Box<Node<K,V>>>, key: &K) -> Option<&'a Node<K,V>> {
    if x.is_none() {
        return None;
    }

    match key.cmp(&x.unwrap().key) {
        Ordering::Equal => {
            return Some(&(**x.unwrap()));
        },
        Ordering::Less => {
            return floor(x.unwrap().left.as_ref(), key);
        },
        _ => (),
    }

    let t = floor(x.unwrap().right.as_ref(), key);
    if t.is_some() {
        return t
    } else {
        return Some(x.unwrap())
    }
}

// delete_min helper
// returns: top, deleted
fn delete_min<K: Ord, V>(x: Option<Box<Node<K,V>>>) -> (Option<Box<Node<K,V>>>, Option<Box<Node<K,V>>>) {
    let mut x = x;
    if x.is_none() {
        return (None, None);
    }
    match x.as_mut().unwrap().left.take() {
        None           => (x.as_mut().unwrap().right.take(), x),
        left @ Some(_) => {
            let (t, deleted) = delete_min(left);
            x.as_mut().unwrap().left = t;
            (x, deleted)
        }
    }
}

impl<K: Ord, V> OrderedST<K, V> for BST<K, V> {
    /// smallest key
    fn min(&self) -> Option<&K> {
        unimplemented!()
    }

    /// largest key
    fn max(&self) -> Option<&K> {
        unimplemented!()
    }

    /// largest key less than or equal to key
    fn floor(&self, key: &K) -> Option<&K> {
        let x = floor(self.root.as_ref(), key);
        if x.is_none() {
            None
        } else {
            Some(&x.unwrap().key)
        }
    }

    /// smallest key greater than or equal to key
    fn ceiling(&self, key: &K) -> Option<&K> {
        unimplemented!()
    }

    /// number of keys less than key
    fn rank(&self, key: &K) -> usize {
        fn rank_helper<'a, K: Ord, V>(x: Option<&'a Box<Node<K,V>>>, key: &K) -> usize {
            if x.is_none() {
                return 0;
            }

            match key.cmp(&x.unwrap().key) {
                Ordering::Less => {
                    rank_helper(x.unwrap().left.as_ref(), key)
                },
                Ordering::Greater => {
                    1 + x.as_ref().unwrap().left.as_ref().map(|ref n| n.size()).unwrap_or(0) +
                        rank_helper(x.unwrap().right.as_ref(), key)
                }
                Ordering::Equal => {
                    x.as_ref().unwrap().left.as_ref().map(|ref n| n.size()).unwrap_or(0)
                }
            }
        }

        rank_helper(self.root.as_ref(), key)
    }

    /// key of rank k
    fn select(&self, k: usize) -> Option<&K> {
        unimplemented!()
    }

    /// delete smallest key
    fn delete_min(&mut self) {
        self.root = delete_min(self.root.take()).0;
    }

    /// delete largest key
    fn delete_max(&mut self) {
        unimplemented!()
    }
}

impl<K: Ord, V> BST<K, V> {
    pub fn keys<'a>(&'a self) -> ::std::vec::IntoIter<&'a K> {
        let mut queue: Vec<&'a K> = Vec::new();
        fn inorder<'a, K, V>(x: Option<&'a Box<Node<K,V>>>, queue: &mut Vec<&'a K>) {
            if x.is_none() {
                return;
            }
            inorder(x.unwrap().left.as_ref(), queue);
            queue.push(&x.unwrap().key);
            inorder(x.unwrap().right.as_ref(), queue);
        };
        inorder(self.root.as_ref(), &mut queue);
        queue.into_iter()
    }
}

impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for BST<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.root.is_none() {
            write!(f, "<empty tree>")
        } else {
            self.root.as_ref().unwrap().dump(0, f, ' ');
            Ok(())
        }
    }
}

#[test]
fn test_binary_search_tree_delete_min() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAMP".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    assert!(t.get(&'A').is_some());
    t.delete_min();             // assume delete 'A'
    assert_eq!(t.get(&'A'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree_delete_case0() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAM".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    t.delete(&'C');
    assert_eq!(t.get(&'C'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree_delete_case1() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAM".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    t.delete(&'R');
    assert_eq!(t.get(&'R'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree_delete_case2() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAM".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    t.delete(&'E');
    assert_eq!(t.get(&'E'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree() {
    use std::iter::FromIterator;

    let mut t = BST::<char, usize>::new();
    for (i, c) in "SEARCHEXAMP".chars().enumerate() {
        t.put(c, i);
    }

    // println!("{:?}", t);
    assert_eq!(t.get(&'E'),  Some(&6));
    assert_eq!(t.floor(&'O'), Some(&'M'));
    assert_eq!(t.size(), 9);
    assert_eq!(t.rank(&'E'), 2);
    assert_eq!(t.rank(&'M'), 4);
    // inorder visite
    assert_eq!(String::from_iter(t.keys().map(|&c| c)), "ACEHMPRSX");
}
<commit_msg>symbol_tables/binary_search_tree: fix compile warnings<commit_after>use std::iter;
use std::fmt;
use std::cmp::Ordering;
use super::{ST, OrderedST};
// FIXME: out implementation can't be used. :(
// use super::super::stacks_and_queues::Queue;
// use super::super::stacks_and_queues::resizing_array_queue::ResizingArrayQueue;

pub struct Node<K, V> {
    key: K,
    val: V,
    left:  Option<Box<Node<K, V>>>,
    right: Option<Box<Node<K, V>>>
}

impl<K, V> Node<K, V> {
    pub fn new(key: K, val: V) -> Node<K, V> {
        Node {
            key: key,
            val: val,
            left: None,
            right: None
        }
    }

    fn size(&self) -> usize {
        let mut ret = 1;
        if self.left.is_some() {
            ret += self.left.as_ref().unwrap().size()
        }
        if self.right.is_some() {
            ret += self.right.as_ref().unwrap().size()
        }
        ret
    }
}

impl<K: fmt::Debug, V: fmt::Debug> Node<K, V> {
    fn dump(&self, depth: usize, f: &mut fmt::Formatter, symbol: char) {
        if depth == 0 {
            writeln!(f, "{:?}[{:?}]", self.key, self.val).unwrap();
        } else {
            writeln!(f, "{}{}--{:?}[{:?}]", iter::repeat("|  ").take(depth-1).collect::<Vec<&str>>().concat(),
                     symbol, self.key, self.val).unwrap();
        }
        if self.left.is_some() {
            self.left.as_ref().unwrap().dump(depth + 1, f, '+');
        }
        if self.right.is_some() {
            self.right.as_ref().unwrap().dump(depth + 1, f, '`');
        }
    }
}

fn put<K: Ord, V>(x: Option<Box<Node<K,V>>>, key: K, val: V) -> Option<Box<Node<K,V>>> {
    let mut x = x;
    if x.is_none() {
        return Some(Box::new(Node::new(key, val)));
    }
    let cmp = key.cmp(&x.as_ref().unwrap().key);
    match cmp {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = put(left, key, val)
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = put(right, key, val)
        },
        Ordering::Equal => {
            x.as_mut().unwrap().val = val
        }
    }
    x
}

fn delete<K: Ord, V>(x: Option<Box<Node<K,V>>>, key: &K) -> Option<Box<Node<K,V>>> {
    if x.is_none() {
        return None;
    }

    let mut x = x;
    match key.cmp(&x.as_ref().unwrap().key) {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = delete(left, key);
            return x;
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = delete(right, key);
            return x;
        },
        Ordering::Equal => {
            if x.as_ref().unwrap().right.is_none() {
                return x.as_mut().unwrap().left.take();
            }
            if x.as_ref().unwrap().left.is_none() {
                return x.as_mut().unwrap().right.take();
            }

            // Save top
            let mut t = x;

            // split right into right without min, and the min
            let (right, right_min) = delete_min(t.as_mut().unwrap().right.take());
            x = right_min;
            x.as_mut().unwrap().right = right;
            x.as_mut().unwrap().left = t.as_mut().unwrap().left.take();
            x
        }
    }
}

pub struct BST<K, V> {
    root: Option<Box<Node<K, V>>>
}

impl<K: Ord, V> ST<K, V> for BST<K, V> {
    fn new() -> BST<K, V> {
        BST { root: None }
    }

    fn get(&self, key: &K) -> Option<&V> {
        let mut x = self.root.as_ref();
        while x.is_some() {
            match key.cmp(&x.unwrap().key) {
                Ordering::Less => {
                    x = x.unwrap().left.as_ref();
                },
                Ordering::Greater => {
                    x = x.unwrap().right.as_ref();
                },
                Ordering::Equal  => {
                    return Some(&x.unwrap().val)
                }
            }
        }
        None
    }

    fn put(&mut self, key: K, val: V) {
        self.root = put(self.root.take(), key, val);
    }

    fn delete(&mut self, key: &K) {
        self.root = delete(self.root.take(), key);
    }

    fn is_empty(&self) -> bool {
        self.root.is_none()
    }

    /// number of key-value pairs in the table
    fn size(&self) -> usize {
        if self.is_empty() {
            0
        } else {
            self.root.as_ref().unwrap().size()
        }
    }
}

fn floor<'a, K: Ord, V>(x: Option<&'a Box<Node<K,V>>>, key: &K) -> Option<&'a Node<K,V>> {
    if x.is_none() {
        return None;
    }

    match key.cmp(&x.unwrap().key) {
        Ordering::Equal => {
            return Some(&(**x.unwrap()));
        },
        Ordering::Less => {
            return floor(x.unwrap().left.as_ref(), key);
        },
        _ => (),
    }

    let t = floor(x.unwrap().right.as_ref(), key);
    if t.is_some() {
        return t
    } else {
        return Some(x.unwrap())
    }
}

// delete_min helper
// returns: top, deleted
fn delete_min<K: Ord, V>(x: Option<Box<Node<K,V>>>) -> (Option<Box<Node<K,V>>>, Option<Box<Node<K,V>>>) {
    let mut x = x;
    if x.is_none() {
        return (None, None);
    }
    match x.as_mut().unwrap().left.take() {
        None           => (x.as_mut().unwrap().right.take(), x),
        left @ Some(_) => {
            let (t, deleted) = delete_min(left);
            x.as_mut().unwrap().left = t;
            (x, deleted)
        }
    }
}

impl<K: Ord, V> OrderedST<K, V> for BST<K, V> {
    /// smallest key
    fn min(&self) -> Option<&K> {
        unimplemented!()
    }

    /// largest key
    fn max(&self) -> Option<&K> {
        unimplemented!()
    }

    /// largest key less than or equal to key
    fn floor(&self, key: &K) -> Option<&K> {
        let x = floor(self.root.as_ref(), key);
        if x.is_none() {
            None
        } else {
            Some(&x.unwrap().key)
        }
    }

    /// smallest key greater than or equal to key
    fn ceiling(&self, key: &K) -> Option<&K> {
        unimplemented!()
    }

    /// number of keys less than key
    fn rank(&self, key: &K) -> usize {
        fn rank_helper<'a, K: Ord, V>(x: Option<&'a Box<Node<K,V>>>, key: &K) -> usize {
            if x.is_none() {
                return 0;
            }

            match key.cmp(&x.unwrap().key) {
                Ordering::Less => {
                    rank_helper(x.unwrap().left.as_ref(), key)
                },
                Ordering::Greater => {
                    1 + x.as_ref().unwrap().left.as_ref().map(|ref n| n.size()).unwrap_or(0) +
                        rank_helper(x.unwrap().right.as_ref(), key)
                }
                Ordering::Equal => {
                    x.as_ref().unwrap().left.as_ref().map(|ref n| n.size()).unwrap_or(0)
                }
            }
        }

        rank_helper(self.root.as_ref(), key)
    }

    /// key of rank k
    fn select(&self, k: usize) -> Option<&K> {
        unimplemented!()
    }

    /// delete smallest key
    fn delete_min(&mut self) {
        self.root = delete_min(self.root.take()).0;
    }

    /// delete largest key
    fn delete_max(&mut self) {
        unimplemented!()
    }
}

impl<K: Ord, V> BST<K, V> {
    pub fn keys<'a>(&'a self) -> ::std::vec::IntoIter<&'a K> {
        let mut queue: Vec<&'a K> = Vec::new();
        fn inorder<'a, K, V>(x: Option<&'a Box<Node<K,V>>>, queue: &mut Vec<&'a K>) {
            if x.is_none() {
                return;
            }
            inorder(x.unwrap().left.as_ref(), queue);
            queue.push(&x.unwrap().key);
            inorder(x.unwrap().right.as_ref(), queue);
        };
        inorder(self.root.as_ref(), &mut queue);
        queue.into_iter()
    }
}

impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for BST<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.root.is_none() {
            write!(f, "<empty tree>")
        } else {
            self.root.as_ref().unwrap().dump(0, f, ' ');
            Ok(())
        }
    }
}

#[test]
fn test_binary_search_tree_delete_min() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAMP".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    assert!(t.get(&'A').is_some());
    t.delete_min();             // assume delete 'A'
    assert_eq!(t.get(&'A'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree_delete_case0() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAM".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    t.delete(&'C');
    assert_eq!(t.get(&'C'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree_delete_case1() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAM".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    t.delete(&'R');
    assert_eq!(t.get(&'R'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree_delete_case2() {
    let mut t = BST::<char, ()>::new();
    for c in "SEARCHEXAM".chars() {
        t.put(c, ());
    }

    let sz0 = t.size();
    t.delete(&'E');
    assert_eq!(t.get(&'E'), None);
    assert_eq!(t.size(), sz0 - 1);
}

#[test]
fn test_binary_search_tree() {
    use std::iter::FromIterator;

    let mut t = BST::<char, usize>::new();
    for (i, c) in "SEARCHEXAMP".chars().enumerate() {
        t.put(c, i);
    }

    // println!("{:?}", t);
    assert_eq!(t.get(&'E'),  Some(&6));
    assert_eq!(t.floor(&'O'), Some(&'M'));
    assert_eq!(t.size(), 9);
    assert_eq!(t.rank(&'E'), 2);
    assert_eq!(t.rank(&'M'), 4);
    // inorder visite
    assert_eq!(String::from_iter(t.keys().map(|&c| c)), "ACEHMPRSX");
}
<|endoftext|>


<commit_before>
// A port of task-killjoin to use a class with a dtor to manage
// the join.

use std;
import task;

fn joinable(f: fn()) -> (task::task, comm::port<bool>) {
    class notify {
        let ch: comm::chan<bool>; let v: @mut bool;
        new(ch: comm::chan<bool>, v: @mut bool) { self.ch = ch; self.v = v; }
        drop {
            #error["notify: task=%d v=%x unwinding=%b b=%b",
               task::get_task(),
               ptr::addr_of(*(self.v)) as uint,
               task::failing(),
               *(self.v)];
            comm::send(self.ch, *(self.v));
        }
    }
    fn wrapper(pair: (comm::chan<bool>, fn())) {
        let (c, f) = pair;
        let b = @mut false;
        #error["wrapper: task=%d allocated v=%x",
               task::get_task(),
               ptr::addr_of(*b) as uint];
        let _r = notify(c, b);
        f();
        *b = true;
    }
    let p = comm::port();
    let c = comm::chan(p);
    let t = task::spawn {|| wrapper((c, f)) };
    ret (t, p);
}

fn join(pair: (task::task, comm::port<bool>)) -> bool {
    let (_, port) = pair;
    comm::recv(port)
}

fn supervised() {
    // Yield to make sure the supervisor joins before we
    // fail. This is currently not needed because the supervisor
    // runs first, but I can imagine that changing.
    #error["supervised task=%d", task::get_task()];
    task::yield();
    fail;
}

fn supervisor() {
    // Unsupervise this task so the process doesn't return a failure status as
    // a result of the main task being killed.
    task::unsupervise();
    #error["supervisor task=%d", task::get_task()];
    let t = joinable(supervised);
    join(t);
}

fn main() {
    join(joinable(supervisor));
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Update task-killjoin-rsrc to use classes<commit_after>// xfail-test

// A port of task-killjoin to use a class with a dtor to manage
// the join.

use std;
import task;

class notify {
    let ch: comm::chan<bool>; let v: @mut bool;
    new(ch: comm::chan<bool>, v: @mut bool) { self.ch = ch; self.v = v; }
    drop {
        #error["notify: task=%? v=%x unwinding=%b b=%b",
               task::get_task(),
               ptr::addr_of(*(self.v)) as uint,
               task::failing(),
               *(self.v)];
        let b = *(self.v);
        comm::send(self.ch, b);
    }
}

fn joinable(f: fn~()) -> comm::port<bool> {
    fn wrapper(+pair: (comm::chan<bool>, fn())) {
        let (c, f) = pair;
        let b = @mut false;
        #error["wrapper: task=%? allocated v=%x",
               task::get_task(),
               ptr::addr_of(*b) as uint];
        let _r = notify(c, b);
        f();
        *b = true;
    }
    let p = comm::port();
    let c = comm::chan(p);
    let _ = task::spawn {|| wrapper((c, f)) };
    p
}

fn join(port: comm::port<bool>) -> bool {
    comm::recv(port)
}

fn supervised() {
    // Yield to make sure the supervisor joins before we
    // fail. This is currently not needed because the supervisor
    // runs first, but I can imagine that changing.
    #error["supervised task=%?", task::get_task];
    task::yield();
    fail;
}

fn supervisor(b: task::builder) {
    // Unsupervise this task so the process doesn't return a failure status as
    // a result of the main task being killed.
    task::unsupervise(b);
    #error["supervisor task=%?", task::get_task()];
    let t = joinable(supervised);
    join(t);
}

fn main() {
    join(joinable({|| supervisor(task::builder())}));
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>use cranelift_module::*;
use crate::prelude::*;
use rustc::mir::interpret::{read_target_uint, AllocId, ConstValue, GlobalId};
use rustc::ty::Const;
use rustc_mir::interpret::{CompileTimeEvaluator, Memory};

#[derive(Default)]
pub struct ConstantCx {
    todo_allocs: HashSet<AllocId>,
    done: HashSet<DataId>,
}

impl ConstantCx {
    pub fn finalize<'a, 'tcx: 'a, B: Backend>(mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, module: &mut Module<B>) {
        println!("todo allocs: {:?}", self.todo_allocs);
        define_all_allocs(tcx, module, &mut self);
        println!("done {:?}", self.done);
        for data_id in self.done.drain() {
            module.finalize_data(data_id);
        }
    }
}

pub fn codegen_static<'a, 'tcx: 'a, B: Backend>(cx: &mut CodegenCx<'a, 'tcx, B>, def_id: DefId) {
    unimpl!("static mono item {:?}", def_id);
}

pub fn codegen_static_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    static_: &Static<'tcx>,
) -> CPlace<'tcx> {
    unimpl!("static place {:?} ty {:?}", static_.def_id, static_.ty);
}

pub fn trans_promoted<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    promoted: Promoted,
) -> CPlace<'tcx> {
    let const_ = fx
        .tcx
        .const_eval(ParamEnv::reveal_all().and(GlobalId {
            instance: fx.instance,
            promoted: Some(promoted),
        })).unwrap();

    let const_ = force_eval_const(fx, const_);
    trans_const_place(fx, const_)
}

pub fn trans_constant<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    constant: &Constant<'tcx>,
) -> CValue<'tcx> {
    let const_ = fx.monomorphize(&constant.literal);
    let const_ = force_eval_const(fx, const_);
    trans_const_value(fx, const_)
}

fn force_eval_const<'a, 'tcx: 'a>(
    fx: &FunctionCx<'a, 'tcx>,
    const_: &'tcx Const<'tcx>,
) -> &'tcx Const<'tcx> {
    match const_.val {
        ConstValue::Unevaluated(def_id, ref substs) => {
            let param_env = ParamEnv::reveal_all();
            let instance = Instance::resolve(fx.tcx, param_env, def_id, substs).unwrap();
            let cid = GlobalId {
                instance,
                promoted: None,
            };
            fx.tcx.const_eval(param_env.and(cid)).unwrap()
        }
        _ => const_,
    }
}

fn trans_const_value<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    const_: &'tcx Const<'tcx>,
) -> CValue<'tcx> {
    let ty = fx.monomorphize(&const_.ty);
    let layout = fx.layout_of(ty);
    match ty.sty {
        TypeVariants::TyBool => {
            let bits = const_.val.to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        TypeVariants::TyUint(_) => {
            let bits = const_.val.to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        TypeVariants::TyInt(_) => {
            let bits = const_.val.to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as i128 as i64)
        }
        TypeVariants::TyFnDef(def_id, substs) => {
            let func_ref = fx.get_function_ref(Instance::new(def_id, substs));
            CValue::Func(func_ref, layout)
        }
        _ => trans_const_place(fx, const_).to_cvalue(fx),
    }
}

fn trans_const_place<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    const_: &'tcx Const<'tcx>,
) -> CPlace<'tcx> {
    let ty = fx.monomorphize(&const_.ty);
    let layout = fx.layout_of(ty);

    let alloc = fx.tcx.const_value_to_allocation(const_);
    //println!("const value: {:?} allocation: {:?}", value, alloc);
    let alloc_id = fx.tcx.alloc_map.lock().allocate(alloc);
    let data_id = get_global_for_alloc_id(
        fx.module,
        fx.constants,
        alloc_id,
    );
    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    // TODO: does global_value return a ptr of a val?
    let global_ptr = fx.bcx.ins().global_value(types::I64, local_data_id);
    CPlace::Addr(global_ptr, layout)
}

// If ret.1 is true, then the global didn't exist before
fn define_global_for_alloc_id<'a, 'tcx: 'a, B: Backend>(
    module: &mut Module<B>,
    cx: &mut ConstantCx,
    alloc_id: AllocId,
) -> DataId {
    module
        .declare_data(&alloc_id.0.to_string(), Linkage::Local, false)
        .unwrap()
}

fn get_global_for_alloc_id<'a, 'tcx: 'a, B: Backend + 'a>(
    module: &mut Module<B>,
    cx: &mut ConstantCx,
    alloc_id: AllocId,
) -> DataId {
    cx.todo_allocs.insert(alloc_id);
    let data_id = define_global_for_alloc_id(module, cx, alloc_id);
    data_id
}

fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a> (
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    module: &mut Module<B>,
    cx: &mut ConstantCx,
) {
    let memory = Memory::<CompileTimeEvaluator>::new(tcx.at(DUMMY_SP), ());

    loop {
        let alloc_id = {
            if let Some(alloc_id) = cx.todo_allocs.iter().next().map(|alloc_id| *alloc_id) {
                cx.todo_allocs.remove(&alloc_id);
                alloc_id
            } else {
                break;
            }
        };

        let data_id = define_global_for_alloc_id(module, cx, alloc_id);
        println!("alloc_id {} data_id {}", alloc_id, data_id);
        if cx.done.contains(&data_id) {
            continue;
        }

        let alloc = memory.get(alloc_id).unwrap();
        //let alloc = tcx.alloc_map.lock().get(alloc_id).unwrap();
        let mut data_ctx = DataContext::new();

        data_ctx.define(
            alloc.bytes.to_vec().into_boxed_slice(),
            Writability::Readonly,
        );

        for &(offset, reloc) in alloc.relocations.iter() {
            cx.todo_allocs.insert(reloc);
            let data_id = define_global_for_alloc_id(module, cx, reloc);

            let reloc_offset = {
                let endianness = memory.endianness();
                let offset = offset.bytes() as usize;
                let ptr_size = tcx.data_layout.pointer_size;
                let bytes = &alloc.bytes[offset..offset + ptr_size.bytes() as usize];
                read_target_uint(endianness, bytes).unwrap()
            };

            let global_value = module.declare_data_in_data(data_id, &mut data_ctx);
            data_ctx.write_data_addr(reloc_offset as u32, global_value, 0);
        }

        module.define_data(data_id, &data_ctx).unwrap();
        cx.done.insert(data_id);
    }

    assert!(cx.todo_allocs.is_empty(), "{:?}", cx.todo_allocs);
}
<commit_msg>Add helper function to pop an element from a HashSet<commit_after>use cranelift_module::*;
use crate::prelude::*;
use rustc::mir::interpret::{read_target_uint, AllocId, ConstValue, GlobalId};
use rustc::ty::Const;
use rustc_mir::interpret::{CompileTimeEvaluator, Memory};

#[derive(Default)]
pub struct ConstantCx {
    todo_allocs: HashSet<AllocId>,
    done: HashSet<DataId>,
}

impl ConstantCx {
    pub fn finalize<'a, 'tcx: 'a, B: Backend>(mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, module: &mut Module<B>) {
        println!("todo allocs: {:?}", self.todo_allocs);
        define_all_allocs(tcx, module, &mut self);
        println!("done {:?}", self.done);
        for data_id in self.done.drain() {
            module.finalize_data(data_id);
        }
    }
}

pub fn codegen_static<'a, 'tcx: 'a, B: Backend>(cx: &mut CodegenCx<'a, 'tcx, B>, def_id: DefId) {
    unimpl!("static mono item {:?}", def_id);
}

pub fn codegen_static_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    static_: &Static<'tcx>,
) -> CPlace<'tcx> {
    unimpl!("static place {:?} ty {:?}", static_.def_id, static_.ty);
}

pub fn trans_promoted<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    promoted: Promoted,
) -> CPlace<'tcx> {
    let const_ = fx
        .tcx
        .const_eval(ParamEnv::reveal_all().and(GlobalId {
            instance: fx.instance,
            promoted: Some(promoted),
        })).unwrap();

    let const_ = force_eval_const(fx, const_);
    trans_const_place(fx, const_)
}

pub fn trans_constant<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    constant: &Constant<'tcx>,
) -> CValue<'tcx> {
    let const_ = fx.monomorphize(&constant.literal);
    let const_ = force_eval_const(fx, const_);
    trans_const_value(fx, const_)
}

fn force_eval_const<'a, 'tcx: 'a>(
    fx: &FunctionCx<'a, 'tcx>,
    const_: &'tcx Const<'tcx>,
) -> &'tcx Const<'tcx> {
    match const_.val {
        ConstValue::Unevaluated(def_id, ref substs) => {
            let param_env = ParamEnv::reveal_all();
            let instance = Instance::resolve(fx.tcx, param_env, def_id, substs).unwrap();
            let cid = GlobalId {
                instance,
                promoted: None,
            };
            fx.tcx.const_eval(param_env.and(cid)).unwrap()
        }
        _ => const_,
    }
}

fn trans_const_value<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    const_: &'tcx Const<'tcx>,
) -> CValue<'tcx> {
    let ty = fx.monomorphize(&const_.ty);
    let layout = fx.layout_of(ty);
    match ty.sty {
        TypeVariants::TyBool => {
            let bits = const_.val.to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        TypeVariants::TyUint(_) => {
            let bits = const_.val.to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        TypeVariants::TyInt(_) => {
            let bits = const_.val.to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as i128 as i64)
        }
        TypeVariants::TyFnDef(def_id, substs) => {
            let func_ref = fx.get_function_ref(Instance::new(def_id, substs));
            CValue::Func(func_ref, layout)
        }
        _ => trans_const_place(fx, const_).to_cvalue(fx),
    }
}

fn trans_const_place<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx>,
    const_: &'tcx Const<'tcx>,
) -> CPlace<'tcx> {
    let ty = fx.monomorphize(&const_.ty);
    let layout = fx.layout_of(ty);

    let alloc = fx.tcx.const_value_to_allocation(const_);
    //println!("const value: {:?} allocation: {:?}", value, alloc);
    let alloc_id = fx.tcx.alloc_map.lock().allocate(alloc);
    let data_id = get_global_for_alloc_id(
        fx.module,
        fx.constants,
        alloc_id,
    );
    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    // TODO: does global_value return a ptr of a val?
    let global_ptr = fx.bcx.ins().global_value(types::I64, local_data_id);
    CPlace::Addr(global_ptr, layout)
}

// If ret.1 is true, then the global didn't exist before
fn define_global_for_alloc_id<'a, 'tcx: 'a, B: Backend>(
    module: &mut Module<B>,
    cx: &mut ConstantCx,
    alloc_id: AllocId,
) -> DataId {
    module
        .declare_data(&alloc_id.0.to_string(), Linkage::Local, false)
        .unwrap()
}

fn get_global_for_alloc_id<'a, 'tcx: 'a, B: Backend + 'a>(
    module: &mut Module<B>,
    cx: &mut ConstantCx,
    alloc_id: AllocId,
) -> DataId {
    cx.todo_allocs.insert(alloc_id);
    let data_id = define_global_for_alloc_id(module, cx, alloc_id);
    data_id
}

fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a> (
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    module: &mut Module<B>,
    cx: &mut ConstantCx,
) {
    let memory = Memory::<CompileTimeEvaluator>::new(tcx.at(DUMMY_SP), ());

    while let Some(alloc_id) = pop_set(&mut cx.todo_allocs) {
        let data_id = define_global_for_alloc_id(module, cx, alloc_id);
        println!("alloc_id {} data_id {}", alloc_id, data_id);
        if cx.done.contains(&data_id) {
            continue;
        }

        let alloc = memory.get(alloc_id).unwrap();
        //let alloc = tcx.alloc_map.lock().get(alloc_id).unwrap();
        let mut data_ctx = DataContext::new();

        data_ctx.define(
            alloc.bytes.to_vec().into_boxed_slice(),
            Writability::Readonly,
        );

        for &(offset, reloc) in alloc.relocations.iter() {
            cx.todo_allocs.insert(reloc);
            let data_id = define_global_for_alloc_id(module, cx, reloc);

            let reloc_offset = {
                let endianness = memory.endianness();
                let offset = offset.bytes() as usize;
                let ptr_size = tcx.data_layout.pointer_size;
                let bytes = &alloc.bytes[offset..offset + ptr_size.bytes() as usize];
                read_target_uint(endianness, bytes).unwrap()
            };

            let global_value = module.declare_data_in_data(data_id, &mut data_ctx);
            data_ctx.write_data_addr(reloc_offset as u32, global_value, 0);
        }

        module.define_data(data_id, &data_ctx).unwrap();
        cx.done.insert(data_id);
    }

    assert!(cx.todo_allocs.is_empty(), "{:?}", cx.todo_allocs);
}

fn pop_set<T: Copy + Eq + ::std::hash::Hash>(set: &mut HashSet<T>) -> Option<T> {
    if let Some(elem) = set.iter().next().map(|elem| *elem) {
        set.remove(&elem);
        Some(elem)
    } else {
        None
    }
}<|endoftext|>


<commit_before>use std::mem;

#[allow(dead_code)]
#[derive(Copy)]
struct Point {
    x: f64,
    y: f64,
}

#[allow(dead_code)]
struct Rectangle {
    p1: Point,
    p2: Point,
}

fn origin() -> Point {
    Point { x: 0.0, y: 0.0 }
}

fn boxed_origin() -> Box<Point> {
    box Point { x: 0.0, y: 0.0 }
}<commit_msg>add blank line<commit_after>use std::mem;

#[allow(dead_code)]
#[derive(Copy)]
struct Point {
    x: f64,
    y: f64,
}

#[allow(dead_code)]
struct Rectangle {
    p1: Point,
    p2: Point,
}

fn origin() -> Point {
    Point { x: 0.0, y: 0.0 }
}

fn boxed_origin() -> Box<Point> {
    box Point { x: 0.0, y: 0.0 }
}
<|endoftext|>


<commit_before>use fixedbitset::FixedBitSet;

#[derive(Debug)]
pub struct Coverage {
    n: usize,
    rows: FixedBitSet,
    cols: FixedBitSet,
}

impl Coverage {
    pub fn n(&self) -> usize {
        self.n
    }

    pub fn new(n: usize) -> Coverage {
        Coverage {
            n: n,
            rows: FixedBitSet::with_capacity(n),
            cols: FixedBitSet::with_capacity(n),
        }
    }

    #[inline]
    /// find a single uncovered (row, col) pair. Iterates in col, row order.
    pub fn find_uncovered_col_row<F>(&self, mut f: F) -> Option<(usize, usize)>
        where F: FnMut((usize, usize)) -> bool
    {

        let n = self.n();

        for col in 0..n {
            if self.is_col_covered(col) {
                continue;
            }
            for row in 0..n {
                if self.is_row_covered(row) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    return Some(pos);
                }
            }
        }

        return None;
    }

    #[inline]
    /// iterates over all uncovered (row, col) pairs in row, col order
    pub fn iter_uncovered_row_col<F>(&self, mut f: F)
        where F: FnMut((usize, usize))
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                f((row, col));
            }
        }
    }

    #[inline]
    /// iterates over all uncovered (row, col) pairs in row, col order, and set covered if f returns true.
    pub fn iter_uncovered_row_col_and_cover<F>(&mut self, mut f: F)
        where F: FnMut((usize, usize)) -> bool
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            'col: for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    self.cover(pos);
                    // the complete row is covered! break the loop!
                    break 'col;
                }
            }
        }
    }

    #[inline]
    pub fn is_row_covered(&self, row: usize) -> bool {
        self.rows.contains(row)
    }

    #[inline]
    pub fn is_col_covered(&self, col: usize) -> bool {
        self.cols.contains(col)
    }

    #[inline]
    pub fn cover(&mut self, pos: (usize, usize)) {
        match pos {
            (row, col) => {
                self.cover_row(row);
                self.cover_col(col);
            }
        }
    }

    #[inline]
    pub fn cover_col(&mut self, col: usize) {
        self.cols.set(col, true);
    }

    #[inline]
    pub fn uncover_col(&mut self, col: usize) {
        self.cols.set(col, false);
    }

    #[inline]
    pub fn cover_row(&mut self, row: usize) {
        self.rows.set(row, true);
    }

    pub fn clear(&mut self) {
        self.rows.clear();
        self.cols.clear();
    }
}
<commit_msg>Add some more debug assertions<commit_after>use fixedbitset::FixedBitSet;

#[derive(Debug)]
pub struct Coverage {
    n: usize,
    rows: FixedBitSet,
    cols: FixedBitSet,
}

fn is_bitset_clear(bitset: &FixedBitSet) -> bool {
    for elm in bitset.as_slice().iter() {
        if *elm != 0 {
            return false;
        }
    }
    return true;
}

impl Coverage {
    #[inline]
    pub fn n(&self) -> usize {
        self.n
    }

    pub fn new(n: usize) -> Coverage {
        assert!(n > 0);
        Coverage {
            n: n,
            rows: FixedBitSet::with_capacity(n),
            cols: FixedBitSet::with_capacity(n),
        }
    }

    /// find a single uncovered (row, col) pair. Iterates in col, row order.
    #[inline]
    pub fn find_uncovered_col_row<F>(&self, mut f: F) -> Option<(usize, usize)>
        where F: FnMut((usize, usize)) -> bool
    {

        let n = self.n();

        for col in 0..n {
            if self.is_col_covered(col) {
                continue;
            }
            for row in 0..n {
                if self.is_row_covered(row) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    return Some(pos);
                }
            }
        }

        return None;
    }

    /// iterates over all uncovered (row, col) pairs in row, col order
    #[inline]
    pub fn iter_uncovered_row_col<F>(&self, mut f: F)
        where F: FnMut((usize, usize))
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                f((row, col));
            }
        }
    }

    /// iterates over all uncovered (row, col) pairs in row, col order, and set covered if f returns true.
    #[inline]
    pub fn iter_uncovered_row_col_and_cover<F>(&mut self, mut f: F)
        where F: FnMut((usize, usize)) -> bool
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            'col: for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    self.cover(pos);
                    // the complete row is covered! break the loop!
                    break 'col;
                }
            }
        }
    }

    #[inline]
    pub fn is_row_covered(&self, row: usize) -> bool {
        debug_assert!(row < self.n());
        self.rows.contains(row)
    }

    #[inline]
    pub fn is_col_covered(&self, col: usize) -> bool {
        debug_assert!(col < self.n());
        self.cols.contains(col)
    }

    #[inline]
    pub fn cover(&mut self, pos: (usize, usize)) {
        let (row, col) = pos;
        self.cover_row(row);
        self.cover_col(col);
    }

    #[inline]
    pub fn cover_col(&mut self, col: usize) {
        debug_assert!(col < self.n());
        self.cols.set(col, true);
    }

    #[inline]
    pub fn uncover_col(&mut self, col: usize) {
        debug_assert!(col < self.n());
        self.cols.set(col, false);
    }

    #[inline]
    pub fn cover_row(&mut self, row: usize) {
        debug_assert!(row < self.n());
        self.rows.set(row, true);
    }

    pub fn clear(&mut self) {
        self.rows.clear();
        self.cols.clear();
    }

    pub fn is_clear(&self) -> bool {
        is_bitset_clear(&self.rows) && is_bitset_clear(&self.cols)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

// #[no_mangle]
// pub extern "C" fn some_new_fn() -> c_int {
//     println!("some_new_fn");
//     65 as c_int
// }

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - start()");

    // println!("start");
    // 88 as c_int

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    println!("Rust - address: {}", host_address);

    // Create and register a way to kill this client
    // let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    // let kill_tx = k_tx.clone();
    // let mut k_tx_ptr = Box::new(k_tx);
    // unsafe {
    //     register_stop_tx(&mut *k_tx_ptr);
    // }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);

    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

// /// Connects to the provided address, (eg "123.123.123.123:3000") and registers
// /// the on data received handler
// #[no_mangle]
// pub extern "C" fn connect(address: *const c_char,
//     handler: extern fn(*const c_char, c_int),
//     on_connect_handler: extern fn(),
//     on_disconnect_handler: extern fn()) -> c_int {
//
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//
//
//     78 as c_int
//
//
//     let mut r_address;
//     unsafe {
//         r_address = CStr::from_ptr(address);
//     }
//     let s_address = r_address.to_bytes();
//     let host_address = match str::from_utf8(s_address) {
//         Ok(safe_str) => safe_str,
//         Err(_) => {
//             println!("Invalid host address");
//             return -1 as c_int;
//         }
//     };
//
//     // Create and register a way to kill this client
//     let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
//     let kill_tx = k_tx.clone();
//     let mut k_tx_ptr = Box::new(k_tx);
//     unsafe {
//         register_stop_tx(&mut *k_tx_ptr);
//     }
//
//     // Writer thread's channel
//     let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
//     let mut w_tx_ptr = Box::new(w_tx);
//     unsafe {
//         register_writer_tx(&mut *w_tx_ptr);
//     }
//
//     println!("Attempting connect to: {}", host_address);
//
//     let result = TcpStream::connect(host_address);
//     if result.is_err() {
//         println!("Error connecting to {} - {}", host_address, result.unwrap_err());
//         return -1 as c_int;
//     }
//     println!("Connected");
//     on_connect_handler();
//
//     let stream = result.unwrap();
//     let client = Bstream::new(stream);
//
//     let r_client = client.clone();
//     let r_kill_tx = kill_tx.clone();
//
//     let w_client = client.clone();
//     let w_kill_tx = kill_tx.clone();
//
//     // Start the reader thread
//     thread::Builder::new()
//         .name("ReaderThread".to_string())
//         .spawn(move||{
//             reader_thread(r_client, handler, r_kill_tx)
//         }).unwrap();
//
//     // Start the writer thread
//     thread::Builder::new()
//         .name("WriterThread".to_string())
//         .spawn(move||{
//             writer_thread(w_rx, w_client, w_kill_tx)
//         }).unwrap();
//
//     // Wait for the kill signal
//     match kill_rx.recv() {
//         Ok(_) => { }
//         Err(e) => {
//             println!("Error on kill channel: {}", e);
//             return -1 as c_int;
//         }
//     };
//     on_disconnect_handler();
//
//     // Exit out in standard C fashion
//     0 as c_int
// }

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

// #[no_mangle]
// pub extern "C" fn some_new_fn() -> c_int {
//     println!("some_new_fn");
//     65 as c_int
// }

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - start()");

    // println!("start");
    // 88 as c_int

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    println!("Rust - address: {}", host_address);

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    let kill_tx = k_tx.clone();
    let mut k_tx_ptr = Box::new(k_tx);
    unsafe {
        register_stop_tx(&mut *k_tx_ptr);
    }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);

    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

// /// Connects to the provided address, (eg "123.123.123.123:3000") and registers
// /// the on data received handler
// #[no_mangle]
// pub extern "C" fn connect(address: *const c_char,
//     handler: extern fn(*const c_char, c_int),
//     on_connect_handler: extern fn(),
//     on_disconnect_handler: extern fn()) -> c_int {
//
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//
//
//     78 as c_int
//
//
//     let mut r_address;
//     unsafe {
//         r_address = CStr::from_ptr(address);
//     }
//     let s_address = r_address.to_bytes();
//     let host_address = match str::from_utf8(s_address) {
//         Ok(safe_str) => safe_str,
//         Err(_) => {
//             println!("Invalid host address");
//             return -1 as c_int;
//         }
//     };
//
//     // Create and register a way to kill this client
//     let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
//     let kill_tx = k_tx.clone();
//     let mut k_tx_ptr = Box::new(k_tx);
//     unsafe {
//         register_stop_tx(&mut *k_tx_ptr);
//     }
//
//     // Writer thread's channel
//     let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
//     let mut w_tx_ptr = Box::new(w_tx);
//     unsafe {
//         register_writer_tx(&mut *w_tx_ptr);
//     }
//
//     println!("Attempting connect to: {}", host_address);
//
//     let result = TcpStream::connect(host_address);
//     if result.is_err() {
//         println!("Error connecting to {} - {}", host_address, result.unwrap_err());
//         return -1 as c_int;
//     }
//     println!("Connected");
//     on_connect_handler();
//
//     let stream = result.unwrap();
//     let client = Bstream::new(stream);
//
//     let r_client = client.clone();
//     let r_kill_tx = kill_tx.clone();
//
//     let w_client = client.clone();
//     let w_kill_tx = kill_tx.clone();
//
//     // Start the reader thread
//     thread::Builder::new()
//         .name("ReaderThread".to_string())
//         .spawn(move||{
//             reader_thread(r_client, handler, r_kill_tx)
//         }).unwrap();
//
//     // Start the writer thread
//     thread::Builder::new()
//         .name("WriterThread".to_string())
//         .spawn(move||{
//             writer_thread(w_rx, w_client, w_kill_tx)
//         }).unwrap();
//
//     // Wait for the kill signal
//     match kill_rx.recv() {
//         Ok(_) => { }
//         Err(e) => {
//             println!("Error on kill channel: {}", e);
//             return -1 as c_int;
//         }
//     };
//     on_disconnect_handler();
//
//     // Exit out in standard C fashion
//     0 as c_int
// }

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<|endoftext|>