<commit_before>use cmd;
use channel;
use channel::{Channel};
use channel::util::{Secret, Private};
use msg::RawMessage;
use msg::util;

use server::{Server};
use client::{SharedClient, ClientProxy};
/// Handles the WHO message
/// The reply consists of two parts:
///
/// ```
/// 352    RPL_WHOREPLY
///        "<channel> <user> <host> <server> <nick>
///        ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
///        :<hopcount> <real name>"
///
/// 315    RPL_ENDOFWHO
///        "<name> :End of WHO list"
/// ```
///
/// Unfortunately the RFC 2812 does not specify what H, G, *, @ or + mean.
/// @/+ is op/voice.
/// * is maybe irc op
/// H/G means here/gone in terms of the away status
///
pub struct Who {
    raw: RawMessage,
    mask: String,
    op_only: bool
}
impl Who {
    pub fn handle_who(&self, channel: &Channel, client: ClientProxy) {
        if (channel.has_flag(Private) || channel.has_flag(Secret))
        && !channel.member_with_id(client.id()).is_some() {
            // Don't give information about this channel to the outside
            // this should also be ok for secret because RPL_ENDOFWHO is
            // always sent.
            channel.send_response(&client, cmd::RPL_ENDOFWHO, [
                self.mask.as_slice(), "End of WHO list"
            ]);
        } else {
            let sender = channel.list_sender(&client, cmd::RPL_WHOREPLY, cmd::RPL_ENDOFWHO);
            for member in channel.members() {
                sender.feed_line(&[
                    channel.name(),
                    member.username(),
                    member.hostname(),
                    channel.server_name(),
                    member.nick(),
                    format!("{}{}{}",
                        "H", // always here as long away is not implemented
                        "", // * is not supported yet
                        member.decoration()
                    ).as_slice(),
                    format!("0 {}", member.realname()).as_slice()
                ]);
            }
        }
    }
}
impl super::MessageHandler for Who {
    fn from_message(message: RawMessage) -> Result<Box<Who>, RawMessage> {
        let mask = message.params().as_slice().get(0).map_or("0".to_string(),
            |&v| String::from_utf8_lossy(v).to_string());
        let op_only = match message.params().as_slice().get(1) {
            Some(&o) => o == b"o",
            None => false
        };
        Ok(box Who {
            raw: message, mask: mask, op_only: op_only
        })
    }
    fn invoke(self, server: &mut Server, origin: SharedClient) {
        match server.channels.find(&self.mask) {
            Some(channel) => {
                let proxy = origin.borrow().proxy();
                channel.send(channel::Handle(proc(channel) {
                    self.handle_who(channel, proxy)
                }))
            },
            None => {} // handle later
        }
    }
    fn raw_message(&self) -> &RawMessage {
        &self.raw
    }
}

/// Handles NAMES message
pub struct Names {
    raw: RawMessage,
    receivers: Vec<util::Receiver>
}
impl Names {
    /// Sends the list of users to the client
    pub fn handle_names(channel: &Channel, proxy: &ClientProxy) {
        // TODO check if channel is visible to user…
        // TODO replace with generic list sending function
        for member in channel.members() {
            channel.send_response(proxy, cmd::RPL_NAMREPLY, [
                String::from_str("= ").append(channel.name()).as_slice(),
                member.decorated_nick()
            ])
        }
        channel.send_response(proxy, cmd::RPL_ENDOFNAMES,
            [channel.name(), "End of /NAMES list"])
    }
}
impl super::MessageHandler for Names {
    fn from_message(message: RawMessage) -> Result<Box<Names>, RawMessage> {
        if message.params().len() > 0 {
            Ok(box Names {
                raw: message.clone(),
                receivers: message.params()[0].as_slice().split(|c| *c == b',').map(|v|
                    util::verify_receiver(v)
                ).collect()
            })
        } else {
            Err(RawMessage::new(cmd::REPLY(cmd::ERR_NEEDMOREPARAMS), [
                "*", message.command().to_string().as_slice(),
                "not enought params given"
            ], None))
        }
    }
    fn invoke(self, server: &mut Server, origin: SharedClient) {
        for &recv in self.receivers.iter() {
            match recv {
                util::ChannelName(ref name) => {
                    match server.channels.find_mut(&name.to_string()) {
                        Some(channel) => {
                            let proxy = origin.borrow().proxy();
                            channel.send(channel::Handle(proc(channel) {
                                Names::handle_names(channel, &proxy)
                            }))
                        },
                        None => origin
                            .borrow_mut().send_response(cmd::ERR_NOSUCHCHANNEL,
                                Some(name.as_slice()), Some("No such channel"))
                    }
                },
                _ => {}
            }

        }
    }
    fn raw_message(&self) -> &RawMessage {
        &self.raw
    }
}<commit_msg>explicitly finish the list<commit_after>use cmd;
use channel;
use channel::{Channel};
use channel::util::{Secret, Private};
use msg::RawMessage;
use msg::util;

use server::{Server};
use client::{SharedClient, ClientProxy};
/// Handles the WHO message
/// The reply consists of two parts:
///
/// ```
/// 352    RPL_WHOREPLY
///        "<channel> <user> <host> <server> <nick>
///        ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
///        :<hopcount> <real name>"
///
/// 315    RPL_ENDOFWHO
///        "<name> :End of WHO list"
/// ```
///
/// Unfortunately the RFC 2812 does not specify what H, G, *, @ or + mean.
/// @/+ is op/voice.
/// * is maybe irc op
/// H/G means here/gone in terms of the away status
///
pub struct Who {
    raw: RawMessage,
    mask: String,
    op_only: bool
}
impl Who {
    pub fn handle_who(&self, channel: &Channel, client: ClientProxy) {
        if (channel.has_flag(Private) || channel.has_flag(Secret))
        && !channel.member_with_id(client.id()).is_some() {
            // Don't give information about this channel to the outside
            // this should also be ok for secret because RPL_ENDOFWHO is
            // always sent.
            channel.send_response(&client, cmd::RPL_ENDOFWHO, [
                self.mask.as_slice(), "End of WHO list"
            ]);
        } else {
            let sender = channel.list_sender(&client, cmd::RPL_WHOREPLY, cmd::RPL_ENDOFWHO);
            for member in channel.members() {
                sender.feed_line(&[
                    channel.name(),
                    member.username(),
                    member.hostname(),
                    channel.server_name(),
                    member.nick(),
                    format!("{}{}{}",
                        "H", // always here as long away is not implemented
                        "", // * is not supported yet
                        member.decoration()
                    ).as_slice(),
                    format!("0 {}", member.realname()).as_slice()
                ]);
            }
            sender.end_of_list()
        }
    }
}
impl super::MessageHandler for Who {
    fn from_message(message: RawMessage) -> Result<Box<Who>, RawMessage> {
        let mask = message.params().as_slice().get(0).map_or("0".to_string(),
            |&v| String::from_utf8_lossy(v).to_string());
        let op_only = match message.params().as_slice().get(1) {
            Some(&o) => o == b"o",
            None => false
        };
        Ok(box Who {
            raw: message, mask: mask, op_only: op_only
        })
    }
    fn invoke(self, server: &mut Server, origin: SharedClient) {
        match server.channels.find(&self.mask) {
            Some(channel) => {
                let proxy = origin.borrow().proxy();
                channel.send(channel::Handle(proc(channel) {
                    self.handle_who(channel, proxy)
                }))
            },
            None => {} // handle later
        }
    }
    fn raw_message(&self) -> &RawMessage {
        &self.raw
    }
}

/// Handles NAMES message
pub struct Names {
    raw: RawMessage,
    receivers: Vec<util::Receiver>
}
impl Names {
    /// Sends the list of users to the client
    pub fn handle_names(channel: &Channel, proxy: &ClientProxy) {
        // TODO check if channel is visible to user…
        // TODO replace with generic list sending function
        for member in channel.members() {
            channel.send_response(proxy, cmd::RPL_NAMREPLY, [
                String::from_str("= ").append(channel.name()).as_slice(),
                member.decorated_nick()
            ])
        }
        channel.send_response(proxy, cmd::RPL_ENDOFNAMES,
            [channel.name(), "End of /NAMES list"])
    }
}
impl super::MessageHandler for Names {
    fn from_message(message: RawMessage) -> Result<Box<Names>, RawMessage> {
        if message.params().len() > 0 {
            Ok(box Names {
                raw: message.clone(),
                receivers: message.params()[0].as_slice().split(|c| *c == b',').map(|v|
                    util::verify_receiver(v)
                ).collect()
            })
        } else {
            Err(RawMessage::new(cmd::REPLY(cmd::ERR_NEEDMOREPARAMS), [
                "*", message.command().to_string().as_slice(),
                "not enought params given"
            ], None))
        }
    }
    fn invoke(self, server: &mut Server, origin: SharedClient) {
        for &recv in self.receivers.iter() {
            match recv {
                util::ChannelName(ref name) => {
                    match server.channels.find_mut(&name.to_string()) {
                        Some(channel) => {
                            let proxy = origin.borrow().proxy();
                            channel.send(channel::Handle(proc(channel) {
                                Names::handle_names(channel, &proxy)
                            }))
                        },
                        None => origin
                            .borrow_mut().send_response(cmd::ERR_NOSUCHCHANNEL,
                                Some(name.as_slice()), Some("No such channel"))
                    }
                },
                _ => {}
            }

        }
    }
    fn raw_message(&self) -> &RawMessage {
        &self.raw
    }
}<|endoftext|>


<commit_before>use super::super::{Grid, Coord, FiniteSearchQueue};
use super::*;

#[derive(Clone, Copy)]
struct FieldGrp {
    unmet_num: i32,
    unmet_sum: i32,
    unused: Cand,
}
pub struct Field<'a> {
    dic: &'a Dictionary,
    shape: FieldShape,
    grps: Vec<FieldGrp>,
    val: Vec<i32>,
    cand: Vec<Cand>,
    inconsistent: bool,
    queue: FiniteSearchQueue
}
impl<'a> Field<'a> {
    pub fn new(problem: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let n_cells = (problem.height() * problem.width()) as usize;
        let mut has_clue = Grid::new(problem.height(), problem.width(), false);
        for i in 0..n_cells {
            if let Clue::Clue { vertical: _, horizontal: _ } = problem[i] {
                has_clue[i] = true;
            }
        }
        let shape = FieldShape::new(&has_clue);

        let mut grps = vec![FieldGrp {
            unmet_num: 0,
            unmet_sum: 0,
            unused: 0,
        }; shape.group_to_cells.len()];
        let n_groups = grps.len();

        for i in 0..shape.group_to_cells.len() {
            let loc = shape.clue_locations[i];
            let clue_val = match loc {
                ClueLocation::Vertical(v) => match problem[v as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: v, horizontal: _ } => v,
                },
                ClueLocation::Horizontal(h) => match problem[h as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: _, horizontal: h } => h,
                },
            };
            let mut n_cells = 0;
            for _ in shape.group_to_cells[i] {
                n_cells += 1;
            }
            grps[i] = FieldGrp {
                unmet_num: n_cells,
                unmet_sum: clue_val,
                unused: CAND_ALL,
            };
        }

        Field {
            dic: dic,
            shape: shape,
            grps: grps,
            val: vec![UNDECIDED; n_cells],
            cand: vec![CAND_ALL; n_cells],
            inconsistent: false,
            queue: FiniteSearchQueue::new(n_groups as i32),
        }
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn height(&self) -> i32 {
        self.shape.has_clue.height()
    }
    pub fn width(&self) -> i32 {
        self.shape.has_clue.width()
    }
    pub fn val(&self, loc: Coord) -> i32 {
        self.val[self.location(loc)]
    }
    pub fn decide(&mut self, loc: Coord, val: i32) {
        let loc = self.location(loc);

        self.queue.start();
        self.decide_int(loc, val);
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();

    }
    pub fn check_all(&mut self) {
        self.queue.start();
        for i in 0..(self.grps.len() as i32) {
            self.queue.push(i);
        }
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();
    }
    fn location(&self, loc: Coord) -> usize {
        self.shape.has_clue.index(loc)
    }
    fn decide_int(&mut self, loc: usize, val: i32) {
        if self.val[loc] != UNDECIDED {
            if self.val[loc] != val {
                self.inconsistent = true;
            }
            return;
        }

        self.val[loc] = val;
        if (self.cand[loc] & (1 << (val - 1))) == 0 {
            self.inconsistent = true;
            return;
        }
        self.cand[loc] = 1 << (val - 1);

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.grps[g1 as usize].unmet_num -= 1;
        self.grps[g1 as usize].unmet_sum -= val;
        if (self.grps[g1 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g1 as usize].unused &= !(1 << (val - 1) as Cand);
        self.grps[g2 as usize].unmet_num -= 1;
        self.grps[g2 as usize].unmet_sum -= val;
        if (self.grps[g2 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g2 as usize].unused &= !(1 << (val - 1) as Cand);

        self.eliminate_cand_from_group(g1, val, loc as i32);
        self.eliminate_cand_from_group(g2, val, loc as i32);

        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn eliminate_cand_from_group(&mut self, grp: i32, rem_cand: i32, cur: i32) {
        let cand = !(1 << (rem_cand - 1) as Cand);
        for c in self.shape.group_to_cells[grp as usize] {
            if c != cur {
                self.limit_cand(c as usize, cand);
            }
        }
    }
    fn limit_cand(&mut self, loc: usize, lim: Cand) {
        if self.cand[loc] & lim == self.cand[loc] {
            return;
        }
        self.cand[loc] &= lim;

        let current_cand = self.cand[loc];
        if current_cand == 0 {
            self.inconsistent = true;
            return;
        }
        if current_cand.count_ones() == 1 {
            self.decide_int(loc, (current_cand.trailing_zeros() + 1) as i32);
        }

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn check_group(&mut self, gid: i32) {
        let grp = self.grps[gid as usize];
        let (imperative, allowed) = self.dic.at(grp.unmet_num, grp.unmet_sum, grp.unused);
        if (imperative, allowed) == dictionary::IMPOSSIBLE {
            self.inconsistent = true;
            return;
        }

        // unique position technique
        if imperative != 0 {
            let mut uniq = 0;
            let mut mult = 0;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    mult |= uniq & self.cand[c as usize];
                    uniq |= self.cand[c as usize];
                }
            }
            uniq &= imperative & !mult;
            if uniq != 0 {
                for c in self.shape.group_to_cells[gid as usize] {
                    if self.val[c as usize] == UNDECIDED && (self.cand[c as usize] & uniq) != 0 {
                        let val = ((self.cand[c as usize] & uniq).trailing_zeros() + 1) as i32;
                        self.decide_int(c as usize, val);
                    }
                }
            }
        }

        // candidate limitation
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] == UNDECIDED {
                self.limit_cand(c as usize, allowed);
            }
        }

        // two-cells propagation (TODO: improve complexity)
        let grp = self.grps[gid as usize];
        if grp.unmet_num == 2 {
            let mut c1 = -1;
            let mut c2 = -1;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    if c1 == -1 {
                        c1 = c;
                    } else {
                        c2 = c;
                    }
                }
            }
            for i in 1..(MAX_VAL + 1) {
                if (self.cand[c1 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c2 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
                if (self.cand[c2 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c1 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
            }
        }

        // naked pair (TODO: improve complexity)
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            for d in self.shape.group_to_cells[gid as usize] {
                if self.val[d as usize] != -1 { continue; }
                if c != d && self.cand[c as usize] == self.cand[d as usize] && self.cand[c as usize].count_ones() == 2 {
                    for e in self.shape.group_to_cells[gid as usize] {
                        if c != e && d != e {
                            let lim = !self.cand[c as usize];
                            self.limit_cand(e as usize, lim);
                        }
                    }
                }
            }
        }

        // min-max method
        let grp = self.grps[gid as usize];
        let mut min_sum = 0;
        let mut max_sum = 0;
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];
            min_sum += cand.trailing_zeros() + 1;
            max_sum += 32 - cand.leading_zeros();
        }
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];

            let current_max = grp.unmet_sum - (min_sum - (cand.trailing_zeros() + 1)) as i32;
            let current_min = grp.unmet_sum - (max_sum - (32 - cand.leading_zeros())) as i32;

            let mut lim = CAND_ALL;
            if current_max <= 8 {
                lim &= (1 << current_max as Cand) - 1;
            }
            if current_min >= 2 {
                lim &= !((1 << (current_min as Cand - 1)) - 1);
            }
            if lim != CAND_ALL {
                self.limit_cand(c as usize, lim);
            }
        }
    }
}

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

    #[test]
    fn test_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 8 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 7, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.val(Coord { y: 1, x: 1 }), 1);
        assert_eq!(field.val(Coord { y: 1, x: 2 }), 3);
        assert_eq!(field.val(Coord { y: 2, x: 1 }), 2);
        assert_eq!(field.val(Coord { y: 2, x: 2 }), 5);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_inconsistent_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 6 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 5, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.inconsistent(), true);
    }
}
<commit_msg>Kakuro: improve check_group in Field<commit_after>use super::super::{Grid, Coord, FiniteSearchQueue};
use super::*;

#[derive(Clone, Copy)]
struct FieldGrp {
    unmet_num: i32,
    unmet_sum: i32,
    unused: Cand,
}
pub struct Field<'a> {
    dic: &'a Dictionary,
    shape: FieldShape,
    grps: Vec<FieldGrp>,
    val: Vec<i32>,
    cand: Vec<Cand>,
    inconsistent: bool,
    queue: FiniteSearchQueue
}
impl<'a> Field<'a> {
    pub fn new(problem: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let n_cells = (problem.height() * problem.width()) as usize;
        let mut has_clue = Grid::new(problem.height(), problem.width(), false);
        for i in 0..n_cells {
            if let Clue::Clue { vertical: _, horizontal: _ } = problem[i] {
                has_clue[i] = true;
            }
        }
        let shape = FieldShape::new(&has_clue);

        let mut grps = vec![FieldGrp {
            unmet_num: 0,
            unmet_sum: 0,
            unused: 0,
        }; shape.group_to_cells.len()];
        let n_groups = grps.len();

        for i in 0..shape.group_to_cells.len() {
            let loc = shape.clue_locations[i];
            let clue_val = match loc {
                ClueLocation::Vertical(v) => match problem[v as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: v, horizontal: _ } => v,
                },
                ClueLocation::Horizontal(h) => match problem[h as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: _, horizontal: h } => h,
                },
            };
            let mut n_cells = 0;
            for _ in shape.group_to_cells[i] {
                n_cells += 1;
            }
            grps[i] = FieldGrp {
                unmet_num: n_cells,
                unmet_sum: clue_val,
                unused: CAND_ALL,
            };
        }

        Field {
            dic: dic,
            shape: shape,
            grps: grps,
            val: vec![UNDECIDED; n_cells],
            cand: vec![CAND_ALL; n_cells],
            inconsistent: false,
            queue: FiniteSearchQueue::new(n_groups as i32),
        }
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn height(&self) -> i32 {
        self.shape.has_clue.height()
    }
    pub fn width(&self) -> i32 {
        self.shape.has_clue.width()
    }
    pub fn val(&self, loc: Coord) -> i32 {
        self.val[self.location(loc)]
    }
    pub fn decide(&mut self, loc: Coord, val: i32) {
        let loc = self.location(loc);

        self.queue.start();
        self.decide_int(loc, val);
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();

    }
    pub fn check_all(&mut self) {
        self.queue.start();
        for i in 0..(self.grps.len() as i32) {
            self.queue.push(i);
        }
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();
    }
    fn location(&self, loc: Coord) -> usize {
        self.shape.has_clue.index(loc)
    }
    fn decide_int(&mut self, loc: usize, val: i32) {
        if self.val[loc] != UNDECIDED {
            if self.val[loc] != val {
                self.inconsistent = true;
            }
            return;
        }

        self.val[loc] = val;
        if (self.cand[loc] & (1 << (val - 1))) == 0 {
            self.inconsistent = true;
            return;
        }
        self.cand[loc] = 1 << (val - 1);

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.grps[g1 as usize].unmet_num -= 1;
        self.grps[g1 as usize].unmet_sum -= val;
        if (self.grps[g1 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g1 as usize].unused &= !(1 << (val - 1) as Cand);
        self.grps[g2 as usize].unmet_num -= 1;
        self.grps[g2 as usize].unmet_sum -= val;
        if (self.grps[g2 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g2 as usize].unused &= !(1 << (val - 1) as Cand);

        self.eliminate_cand_from_group(g1, val, loc as i32);
        self.eliminate_cand_from_group(g2, val, loc as i32);

        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn eliminate_cand_from_group(&mut self, grp: i32, rem_cand: i32, cur: i32) {
        let cand = !(1 << (rem_cand - 1) as Cand);
        for c in self.shape.group_to_cells[grp as usize] {
            if c != cur {
                self.limit_cand(c as usize, cand);
            }
        }
    }
    fn limit_cand(&mut self, loc: usize, lim: Cand) {
        if self.cand[loc] & lim == self.cand[loc] {
            return;
        }
        self.cand[loc] &= lim;

        let current_cand = self.cand[loc];
        if current_cand == 0 {
            self.inconsistent = true;
            return;
        }
        if current_cand.count_ones() == 1 {
            self.decide_int(loc, (current_cand.trailing_zeros() + 1) as i32);
        }

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn check_group(&mut self, gid: i32) {
        let grp = self.grps[gid as usize];
        let (imperative, allowed) = self.dic.at(grp.unmet_num, grp.unmet_sum, grp.unused);
        if (imperative, allowed) == dictionary::IMPOSSIBLE {
            self.inconsistent = true;
            return;
        }

        // unique position technique
        if imperative != 0 {
            let mut uniq = 0;
            let mut mult = 0;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    mult |= uniq & self.cand[c as usize];
                    uniq |= self.cand[c as usize];
                }
            }
            uniq &= imperative & !mult;
            if uniq != 0 {
                for c in self.shape.group_to_cells[gid as usize] {
                    if self.val[c as usize] == UNDECIDED && (self.cand[c as usize] & uniq) != 0 {
                        let val = ((self.cand[c as usize] & uniq).trailing_zeros() + 1) as i32;
                        self.decide_int(c as usize, val);
                    }
                }
            }
        }

        // candidate limitation
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] == UNDECIDED {
                self.limit_cand(c as usize, allowed);
            }
        }
        // two-cells propagation (TODO: improve complexity)
        let grp = self.grps[gid as usize];
        if grp.unmet_num == 2 {
            let mut c1 = -1;
            let mut c2 = -1;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    if c1 == -1 {
                        c1 = c;
                    } else {
                        c2 = c;
                    }
                }
            }
            let mut c1_lim = CAND_ALL;
            let mut c2_lim = CAND_ALL;
            for i in 1..(MAX_VAL + 1) {
                if (self.cand[c1 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    c2_lim &= !(1 << (grp.unmet_sum - i - 1) as Cand);
                }
                if (self.cand[c2 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    c1_lim &= !(1 << (grp.unmet_sum - i - 1) as Cand);
                }
            }
            self.limit_cand(c1 as usize, c1_lim);
            self.limit_cand(c2 as usize, c2_lim);
        }

        // naked pair (TODO: improve complexity)
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 || self.cand[c as usize].count_ones() != 2 { continue; }
            for d in self.shape.group_to_cells[gid as usize] {
                if self.val[d as usize] != -1 { continue; }
                if c != d && self.cand[c as usize] == self.cand[d as usize] {
                    for e in self.shape.group_to_cells[gid as usize] {
                        if c != e && d != e {
                            let lim = !self.cand[c as usize];
                            self.limit_cand(e as usize, lim);
                        }
                    }
                }
            }
        }

        // min-max method
        let grp = self.grps[gid as usize];
        let mut min_sum = 0;
        let mut max_sum = 0;
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];
            min_sum += cand.trailing_zeros() + 1;
            max_sum += 32 - cand.leading_zeros();
        }
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];

            let current_max = grp.unmet_sum - (min_sum - (cand.trailing_zeros() + 1)) as i32;
            let current_min = grp.unmet_sum - (max_sum - (32 - cand.leading_zeros())) as i32;

            let mut lim = CAND_ALL;
            if current_max <= 8 {
                lim &= (1 << current_max as Cand) - 1;
            }
            if current_min >= 2 {
                lim &= !((1 << (current_min as Cand - 1)) - 1);
            }
            if lim != CAND_ALL {
                self.limit_cand(c as usize, lim);
            }
        }
    }
}

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

    #[test]
    fn test_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 8 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 7, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.val(Coord { y: 1, x: 1 }), 1);
        assert_eq!(field.val(Coord { y: 1, x: 2 }), 3);
        assert_eq!(field.val(Coord { y: 2, x: 1 }), 2);
        assert_eq!(field.val(Coord { y: 2, x: 2 }), 5);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_inconsistent_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 6 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 5, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.inconsistent(), true);
    }
}
<|endoftext|>


<commit_before>use crate::base::ExtCtxt;
use crate::expand::{AstFragment, AstFragmentKind};

use rustc_ast as ast;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::Ident;

use smallvec::{smallvec, SmallVec};

use rustc_data_structures::fx::FxHashMap;

pub fn placeholder(
    kind: AstFragmentKind,
    id: ast::NodeId,
    vis: Option<ast::Visibility>,
) -> AstFragment {
    fn mac_placeholder() -> ast::MacCall {
        ast::MacCall {
            path: ast::Path { span: DUMMY_SP, segments: Vec::new(), tokens: None },
            args: P(ast::MacArgs::Empty),
            prior_type_ascription: None,
        }
    }

    let ident = Ident::invalid();
    let attrs = Vec::new();
    let vis = vis.unwrap_or(ast::Visibility {
        span: DUMMY_SP,
        kind: ast::VisibilityKind::Inherited,
        tokens: None,
    });
    let span = DUMMY_SP;
    let expr_placeholder = || {
        P(ast::Expr {
            id,
            span,
            attrs: ast::AttrVec::new(),
            kind: ast::ExprKind::MacCall(mac_placeholder()),
            tokens: None,
        })
    };
    let ty =
        || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span, tokens: None });
    let pat =
        || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });

    match kind {
        AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
        AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
        AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
            id,
            span,
            ident,
            vis,
            attrs,
            kind: ast::ItemKind::MacCall(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
            id,
            span,
            ident,
            vis,
            attrs,
            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
            id,
            span,
            ident,
            vis,
            attrs,
            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::ForeignItems => {
            AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
                id,
                span,
                ident,
                vis,
                attrs,
                kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
                tokens: None,
            })])
        }
        AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
            id,
            span,
            kind: ast::PatKind::MacCall(mac_placeholder()),
            tokens: None,
        })),
        AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
            id,
            span,
            kind: ast::TyKind::MacCall(mac_placeholder()),
            tokens: None,
        })),
        AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
            let mac = P(ast::MacCallStmt {
                mac: mac_placeholder(),
                style: ast::MacStmtStyle::Braces,
                attrs: ast::AttrVec::new(),
            });
            ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac), tokens: None }
        }]),
        AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
            attrs: Default::default(),
            body: expr_placeholder(),
            guard: None,
            id,
            pat: pat(),
            span,
            is_placeholder: true,
        }]),
        AstFragmentKind::Fields => AstFragment::Fields(smallvec![ast::Field {
            attrs: Default::default(),
            expr: expr_placeholder(),
            id,
            ident,
            is_shorthand: false,
            span,
            is_placeholder: true,
        }]),
        AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![ast::FieldPat {
            attrs: Default::default(),
            id,
            ident,
            is_shorthand: false,
            pat: pat(),
            span,
            is_placeholder: true,
        }]),
        AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
            ast::GenericParam {
                attrs: Default::default(),
                bounds: Default::default(),
                id,
                ident,
                is_placeholder: true,
                kind: ast::GenericParamKind::Lifetime,
            }
        }]),
        AstFragmentKind::Params => AstFragment::Params(smallvec![ast::Param {
            attrs: Default::default(),
            id,
            pat: pat(),
            span,
            ty: ty(),
            is_placeholder: true,
        }]),
        AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![ast::StructField {
            attrs: Default::default(),
            id,
            ident: None,
            span,
            ty: ty(),
            vis,
            is_placeholder: true,
        }]),
        AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant {
            attrs: Default::default(),
            data: ast::VariantData::Struct(Default::default(), false),
            disr_expr: None,
            id,
            ident,
            span,
            vis,
            is_placeholder: true,
        }]),
    }
}

pub struct PlaceholderExpander<'a, 'b> {
    expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
    cx: &'a mut ExtCtxt<'b>,
    monotonic: bool,
}

impl<'a, 'b> PlaceholderExpander<'a, 'b> {
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
        PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic }
    }

    pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
        fragment.mut_visit_with(self);
        self.expanded_fragments.insert(id, fragment);
    }

    fn remove(&mut self, id: ast::NodeId) -> AstFragment {
        self.expanded_fragments.remove(&id).unwrap()
    }
}

impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
        if arm.is_placeholder {
            self.remove(arm.id).make_arms()
        } else {
            noop_flat_map_arm(arm, self)
        }
    }

    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
        if field.is_placeholder {
            self.remove(field.id).make_fields()
        } else {
            noop_flat_map_field(field, self)
        }
    }

    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
        if fp.is_placeholder {
            self.remove(fp.id).make_field_patterns()
        } else {
            noop_flat_map_field_pattern(fp, self)
        }
    }

    fn flat_map_generic_param(
        &mut self,
        param: ast::GenericParam,
    ) -> SmallVec<[ast::GenericParam; 1]> {
        if param.is_placeholder {
            self.remove(param.id).make_generic_params()
        } else {
            noop_flat_map_generic_param(param, self)
        }
    }

    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
        if p.is_placeholder {
            self.remove(p.id).make_params()
        } else {
            noop_flat_map_param(p, self)
        }
    }

    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
        if sf.is_placeholder {
            self.remove(sf.id).make_struct_fields()
        } else {
            noop_flat_map_struct_field(sf, self)
        }
    }

    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
        if variant.is_placeholder {
            self.remove(variant.id).make_variants()
        } else {
            noop_flat_map_variant(variant, self)
        }
    }

    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        match item.kind {
            ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(),
            ast::ItemKind::MacroDef(_) => return smallvec![item],
            _ => {}
        }

        noop_flat_map_item(item, self)
    }

    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        match item.kind {
            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(),
            _ => noop_flat_map_assoc_item(item, self),
        }
    }

    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        match item.kind {
            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(),
            _ => noop_flat_map_assoc_item(item, self),
        }
    }

    fn flat_map_foreign_item(
        &mut self,
        item: P<ast::ForeignItem>,
    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
        match item.kind {
            ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
            _ => noop_flat_map_foreign_item(item, self),
        }
    }

    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        match expr.kind {
            ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
            _ => noop_visit_expr(expr, self),
        }
    }

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        match expr.kind {
            ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
            _ => noop_filter_map_expr(expr, self),
        }
    }

    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        let (style, mut stmts) = match stmt.kind {
            ast::StmtKind::MacCall(mac) => (mac.style, self.remove(stmt.id).make_stmts()),
            _ => return noop_flat_map_stmt(stmt, self),
        };

        if style == ast::MacStmtStyle::Semicolon {
            // Implement the proposal described in
            // https://github.com/rust-lang/rust/issues/61733#issuecomment-509626449
            //
            // The macro invocation expands to the list of statements.
            // If the list of statements is empty, then 'parse'
            // the trailing semicolon on the original invocation
            // as an empty statement. That is:
            //
            // `empty();` is parsed as a single `StmtKind::Empty`
            //
            // If the list of statements is non-empty, see if the
            // final statement alreayd has a trailing semicolon.
            //
            // If it doesn't have a semicolon, then 'parse' the trailing semicolon
            // from the invocation as part of the final statement,
            // using `stmt.add_trailing_semicolon()`
            //
            // If it does have a semicolon, then 'parse' the trailing semicolon
            // from the invocation as a new StmtKind::Empty

            // FIXME: We will need to preserve the original
            // semicolon token and span as part of #15701
            let empty_stmt = ast::Stmt {
                id: ast::DUMMY_NODE_ID,
                kind: ast::StmtKind::Empty,
                span: DUMMY_SP,
                tokens: None,
            };

            if let Some(stmt) = stmts.pop() {
                if stmt.has_trailing_semicolon() {
                    stmts.push(stmt);
                    stmts.push(empty_stmt);
                } else {
                    stmts.push(stmt.add_trailing_semicolon());
                }
            } else {
                stmts.push(empty_stmt);
            }
        }

        stmts
    }

    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
        match pat.kind {
            ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
            _ => noop_visit_pat(pat, self),
        }
    }

    fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
        match ty.kind {
            ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
            _ => noop_visit_ty(ty, self),
        }
    }

    fn visit_block(&mut self, block: &mut P<ast::Block>) {
        noop_visit_block(block, self);

        for stmt in block.stmts.iter_mut() {
            if self.monotonic {
                assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
                stmt.id = self.cx.resolver.next_node_id();
            }
        }
    }

    fn visit_mod(&mut self, module: &mut ast::Mod) {
        noop_visit_mod(module, self);
        // remove macro definitions
        module.items.retain(
            |item| !matches!(item.kind, ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs),
        );
    }

    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
        // Do nothing.
    }
}
<commit_msg>typo and formatting<commit_after>use crate::base::ExtCtxt;
use crate::expand::{AstFragment, AstFragmentKind};

use rustc_ast as ast;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::Ident;

use smallvec::{smallvec, SmallVec};

use rustc_data_structures::fx::FxHashMap;

pub fn placeholder(
    kind: AstFragmentKind,
    id: ast::NodeId,
    vis: Option<ast::Visibility>,
) -> AstFragment {
    fn mac_placeholder() -> ast::MacCall {
        ast::MacCall {
            path: ast::Path { span: DUMMY_SP, segments: Vec::new(), tokens: None },
            args: P(ast::MacArgs::Empty),
            prior_type_ascription: None,
        }
    }

    let ident = Ident::invalid();
    let attrs = Vec::new();
    let vis = vis.unwrap_or(ast::Visibility {
        span: DUMMY_SP,
        kind: ast::VisibilityKind::Inherited,
        tokens: None,
    });
    let span = DUMMY_SP;
    let expr_placeholder = || {
        P(ast::Expr {
            id,
            span,
            attrs: ast::AttrVec::new(),
            kind: ast::ExprKind::MacCall(mac_placeholder()),
            tokens: None,
        })
    };
    let ty =
        || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span, tokens: None });
    let pat =
        || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });

    match kind {
        AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
        AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
        AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
            id,
            span,
            ident,
            vis,
            attrs,
            kind: ast::ItemKind::MacCall(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
            id,
            span,
            ident,
            vis,
            attrs,
            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
            id,
            span,
            ident,
            vis,
            attrs,
            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::ForeignItems => {
            AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
                id,
                span,
                ident,
                vis,
                attrs,
                kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
                tokens: None,
            })])
        }
        AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
            id,
            span,
            kind: ast::PatKind::MacCall(mac_placeholder()),
            tokens: None,
        })),
        AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
            id,
            span,
            kind: ast::TyKind::MacCall(mac_placeholder()),
            tokens: None,
        })),
        AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
            let mac = P(ast::MacCallStmt {
                mac: mac_placeholder(),
                style: ast::MacStmtStyle::Braces,
                attrs: ast::AttrVec::new(),
            });
            ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac), tokens: None }
        }]),
        AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
            attrs: Default::default(),
            body: expr_placeholder(),
            guard: None,
            id,
            pat: pat(),
            span,
            is_placeholder: true,
        }]),
        AstFragmentKind::Fields => AstFragment::Fields(smallvec![ast::Field {
            attrs: Default::default(),
            expr: expr_placeholder(),
            id,
            ident,
            is_shorthand: false,
            span,
            is_placeholder: true,
        }]),
        AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![ast::FieldPat {
            attrs: Default::default(),
            id,
            ident,
            is_shorthand: false,
            pat: pat(),
            span,
            is_placeholder: true,
        }]),
        AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
            ast::GenericParam {
                attrs: Default::default(),
                bounds: Default::default(),
                id,
                ident,
                is_placeholder: true,
                kind: ast::GenericParamKind::Lifetime,
            }
        }]),
        AstFragmentKind::Params => AstFragment::Params(smallvec![ast::Param {
            attrs: Default::default(),
            id,
            pat: pat(),
            span,
            ty: ty(),
            is_placeholder: true,
        }]),
        AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![ast::StructField {
            attrs: Default::default(),
            id,
            ident: None,
            span,
            ty: ty(),
            vis,
            is_placeholder: true,
        }]),
        AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant {
            attrs: Default::default(),
            data: ast::VariantData::Struct(Default::default(), false),
            disr_expr: None,
            id,
            ident,
            span,
            vis,
            is_placeholder: true,
        }]),
    }
}

pub struct PlaceholderExpander<'a, 'b> {
    expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
    cx: &'a mut ExtCtxt<'b>,
    monotonic: bool,
}

impl<'a, 'b> PlaceholderExpander<'a, 'b> {
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
        PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic }
    }

    pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
        fragment.mut_visit_with(self);
        self.expanded_fragments.insert(id, fragment);
    }

    fn remove(&mut self, id: ast::NodeId) -> AstFragment {
        self.expanded_fragments.remove(&id).unwrap()
    }
}

impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
        if arm.is_placeholder {
            self.remove(arm.id).make_arms()
        } else {
            noop_flat_map_arm(arm, self)
        }
    }

    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
        if field.is_placeholder {
            self.remove(field.id).make_fields()
        } else {
            noop_flat_map_field(field, self)
        }
    }

    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
        if fp.is_placeholder {
            self.remove(fp.id).make_field_patterns()
        } else {
            noop_flat_map_field_pattern(fp, self)
        }
    }

    fn flat_map_generic_param(
        &mut self,
        param: ast::GenericParam,
    ) -> SmallVec<[ast::GenericParam; 1]> {
        if param.is_placeholder {
            self.remove(param.id).make_generic_params()
        } else {
            noop_flat_map_generic_param(param, self)
        }
    }

    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
        if p.is_placeholder {
            self.remove(p.id).make_params()
        } else {
            noop_flat_map_param(p, self)
        }
    }

    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
        if sf.is_placeholder {
            self.remove(sf.id).make_struct_fields()
        } else {
            noop_flat_map_struct_field(sf, self)
        }
    }

    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
        if variant.is_placeholder {
            self.remove(variant.id).make_variants()
        } else {
            noop_flat_map_variant(variant, self)
        }
    }

    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        match item.kind {
            ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(),
            ast::ItemKind::MacroDef(_) => return smallvec![item],
            _ => {}
        }

        noop_flat_map_item(item, self)
    }

    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        match item.kind {
            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(),
            _ => noop_flat_map_assoc_item(item, self),
        }
    }

    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        match item.kind {
            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(),
            _ => noop_flat_map_assoc_item(item, self),
        }
    }

    fn flat_map_foreign_item(
        &mut self,
        item: P<ast::ForeignItem>,
    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
        match item.kind {
            ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
            _ => noop_flat_map_foreign_item(item, self),
        }
    }

    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        match expr.kind {
            ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
            _ => noop_visit_expr(expr, self),
        }
    }

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        match expr.kind {
            ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
            _ => noop_filter_map_expr(expr, self),
        }
    }

    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        let (style, mut stmts) = match stmt.kind {
            ast::StmtKind::MacCall(mac) => (mac.style, self.remove(stmt.id).make_stmts()),
            _ => return noop_flat_map_stmt(stmt, self),
        };

        if style == ast::MacStmtStyle::Semicolon {
            // Implement the proposal described in
            // https://github.com/rust-lang/rust/issues/61733#issuecomment-509626449
            //
            // The macro invocation expands to the list of statements. If the
            // list of statements is empty, then 'parse' the trailing semicolon
            // on the original invocation as an empty statement. That is:
            //
            // `empty();` is parsed as a single `StmtKind::Empty`
            //
            // If the list of statements is non-empty, see if the final
            // statement already has a trailing semicolon.
            //
            // If it doesn't have a semicolon, then 'parse' the trailing
            // semicolon from the invocation as part of the final statement,
            // using `stmt.add_trailing_semicolon()`
            //
            // If it does have a semicolon, then 'parse' the trailing semicolon
            // from the invocation as a new StmtKind::Empty

            // FIXME: We will need to preserve the original semicolon token and
            // span as part of #15701
            let empty_stmt = ast::Stmt {
                id: ast::DUMMY_NODE_ID,
                kind: ast::StmtKind::Empty,
                span: DUMMY_SP,
                tokens: None,
            };

            if let Some(stmt) = stmts.pop() {
                if stmt.has_trailing_semicolon() {
                    stmts.push(stmt);
                    stmts.push(empty_stmt);
                } else {
                    stmts.push(stmt.add_trailing_semicolon());
                }
            } else {
                stmts.push(empty_stmt);
            }
        }

        stmts
    }

    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
        match pat.kind {
            ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
            _ => noop_visit_pat(pat, self),
        }
    }

    fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
        match ty.kind {
            ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
            _ => noop_visit_ty(ty, self),
        }
    }

    fn visit_block(&mut self, block: &mut P<ast::Block>) {
        noop_visit_block(block, self);

        for stmt in block.stmts.iter_mut() {
            if self.monotonic {
                assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
                stmt.id = self.cx.resolver.next_node_id();
            }
        }
    }

    fn visit_mod(&mut self, module: &mut ast::Mod) {
        noop_visit_mod(module, self);
        // remove macro definitions
        module.items.retain(
            |item| !matches!(item.kind, ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs),
        );
    }

    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
        // Do nothing.
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Servo Project Developers.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.

extern crate fontsan;

use std::io::{Read, self};
use std::{env, process};

fn main() {
    let mut input = vec![];
    io::stdin().read_to_end(&mut input).unwrap();

    match fontsan::process(&input) {
        Ok(output) => println!("ok, result is {} bytes", output.len()),
        Err(_) => {
            println!("there's something fishy about this font!");
            process::exit(1);
        }
    }
}
<commit_msg>Unused import<commit_after>// Copyright 2015 The Servo Project Developers.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.

extern crate fontsan;

use std::io::{Read, self};
use std::process;

fn main() {
    let mut input = vec![];
    io::stdin().read_to_end(&mut input).unwrap();

    match fontsan::process(&input) {
        Ok(output) => println!("ok, result is {} bytes", output.len()),
        Err(_) => {
            println!("there's something fishy about this font!");
            process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::env;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! forward_features {
	($cmd:expr, $($feature:literal,)+ ) => {
		let mut features = vec![];

		$(
			if cfg!(feature = $feature) {
				features.push($feature);
			}
		)+

		if !features.is_empty() {
			$cmd.arg("--features");
			$cmd.arg(features.join(" "));
		}
	};
}

fn build_hermit(src_dir: &Path, target_dir_opt: Option<&Path>) {
	let manifest_path = src_dir.join("Cargo.toml");
	assert!(
		manifest_path.exists(),
		"kernel manifest path `{}` does not exist",
		manifest_path.display()
	);
	let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
	let profile = env::var("PROFILE").expect("PROFILE was not set");
	let mut cmd = Command::new("cargo");

	let kernel_triple = match target_arch.as_str() {
		"x86_64" => "x86_64-unknown-none-hermitkernel",
		"aarch64" => "aarch64-unknown-hermit",
		_ => panic!("Unsupported target arch: {}", target_arch),
	};

	cmd.arg("build")
		.arg("-Z")
		.arg("build-std=core,alloc")
		.arg("--target")
		.arg(kernel_triple)
		.arg("--manifest-path")
		.arg("Cargo.toml");

	cmd.current_dir(src_dir);

	cmd.env_remove("RUSTUP_TOOLCHAIN");
	if option_env!("RUSTC_WORKSPACE_WRAPPER")
		.unwrap_or_default()
		.ends_with("clippy-driver")
	{
		cmd.env("RUSTC_WORKSPACE_WRAPPER", "clippy-driver");
	}

	cmd.env("CARGO_TERM_COLOR", "always");

	if let Some(target_dir) = target_dir_opt {
		cmd.arg("--target-dir").arg(target_dir);
	}
	let target_dir = match target_dir_opt {
		Some(target_dir) => target_dir.to_path_buf(),
		None => src_dir.join("target"),
	};

	if profile == "release" {
		cmd.arg("--release");
	}

	// Control enabled features via this crate's features
	cmd.arg("--no-default-features");
	forward_features!(cmd, "acpi", "fsgsbase", "pci", "smp", "vga",);

	let mut rustflags = vec!["-Zmutable-noalias=no".to_string()];
	let outer_rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();

	#[cfg(feature = "instrument")]
	{
		rustflags.push("-Zinstrument-mcount".to_string());
		// Add outer rustflags to command
		rustflags.push(outer_rustflags);
	}

	#[cfg(not(feature = "instrument"))]
	{
		// If the `instrument` feature feature is not enabled,
		// filter it from outer rustflags before adding them to the command.
		if !outer_rustflags.is_empty() {
			let flags = outer_rustflags
				.split('\x1f')
				.filter(|&flag| !flag.contains("instrument-mcount"))
				.map(String::from);
			rustflags.extend(flags);
		}
	}

	cmd.env("CARGO_ENCODED_RUSTFLAGS", rustflags.join("\x1f"));

	let status = cmd.status().expect("failed to start kernel build");
	assert!(status.success());

	let lib_location = target_dir
		.join(kernel_triple)
		.join(&profile)
		.canonicalize()
		.unwrap();

	println!("Lib location: {}", lib_location.display());

	let lib = lib_location.join("libhermit.a");

	let mut symbols = vec!["rust_begin_unwind", "rust_oom"];

	if target_arch == "aarch64" {
		symbols.extend(include_str!("aarch64-duplicate-symbols").lines());
	}

	rename_symbols(symbols, &lib);

	println!("cargo:rustc-link-search=native={}", lib_location.display());
	println!("cargo:rustc-link-lib=static=hermit");

	println!("cargo:rerun-if-changed={}", src_dir.display());
	// HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
	println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
}

/// Kernel and user space has its own versions of panic handler, oom handler, memcpy, memset, etc,
/// Consequently, we rename the functions in the libos to avoid collisions.
fn rename_symbols(symbols: impl IntoIterator<Item = impl AsRef<OsStr>>, lib: impl AsRef<Path>) {
	let args = symbols.into_iter().flat_map(|symbol| {
		let option = OsStr::new("--redefine-sym");
		let arg = [symbol.as_ref(), "=kernel-".as_ref(), symbol.as_ref()]
			.into_iter()
			.collect::<OsString>();
		[Cow::Borrowed(option), Cow::Owned(arg)]
	});

	let status = Command::new("rust-objcopy")
		.args(args)
		.arg(lib.as_ref())
		.status()
		.expect("Failed to execute rust-objcopy. Is cargo-binutils installed?");
	assert!(status.success(), "rust-objcopy was not successful");
}

#[cfg(all(not(feature = "rustc-dep-of-std"), not(feature = "with_submodule")))]
fn build() {
	#[cfg(windows)]
	let out_dir = env::temp_dir();
	#[cfg(not(windows))]
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let src_dir = out_dir.join("rusty-hermit");

	if !src_dir.as_path().exists() {
		let status = Command::new(env!("CARGO"))
			.current_dir(out_dir)
			.arg("download")
			.arg("--output")
			.arg(src_dir.clone().into_os_string())
			.arg("--extract")
			.arg("rusty-hermit")
			.status()
			.expect("failed to start kernel download");
		assert!(
			status.success(),
			"Unable to download rusty-hermit. Is cargo-download installed?"
		);
	}

	build_hermit(src_dir.as_ref(), None);
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn build() {
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let target_dir = out_dir.join("target");
	let src_dir = env::current_dir()
		.unwrap()
		.parent()
		.unwrap()
		.join("libhermit-rs");

	build_hermit(src_dir.as_ref(), Some(target_dir.as_ref()));
}

#[cfg(not(feature = "rustc-dep-of-std"))]
fn create_constants() {
	let out_dir = env::var("OUT_DIR").expect("No out dir");
	let dest_path = Path::new(&out_dir).join("constants.rs");
	let mut f = File::create(&dest_path).expect("Could not create file");

	let ip = option_env!("HERMIT_IP");
	let ip = ip.map_or("10.0.5.3", |v| v);

	let gateway = option_env!("HERMIT_GATEWAY");
	let gateway = gateway.map_or("10.0.5.1", |v| v);

	let mask = option_env!("HERMIT_MASK");
	let mask = mask.map_or("255.255.255.0", |v| v);

	writeln!(f, "const HERMIT_IP: &str = \"{}\";", ip).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_IP");

	writeln!(f, "const HERMIT_GATEWAY: &str = \"{}\";", gateway).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_GATEWAY");

	writeln!(f, "const HERMIT_MASK: &str = \"{}\";", mask).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_MASK");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	create_constants();
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<commit_msg>Sys: Build kernel always out of tree<commit_after>use std::borrow::Cow;
use std::env;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! forward_features {
	($cmd:expr, $($feature:literal,)+ ) => {
		let mut features = vec![];

		$(
			if cfg!(feature = $feature) {
				features.push($feature);
			}
		)+

		if !features.is_empty() {
			$cmd.arg("--features");
			$cmd.arg(features.join(" "));
		}
	};
}

fn build_hermit(src_dir: &Path) {
	let target_dir = {
		let mut target_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
		target_dir.push("target");
		target_dir
	};
	let manifest_path = src_dir.join("Cargo.toml");
	assert!(
		manifest_path.exists(),
		"kernel manifest path `{}` does not exist",
		manifest_path.display()
	);
	let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
	let profile = env::var("PROFILE").expect("PROFILE was not set");
	let mut cmd = Command::new("cargo");

	let kernel_triple = match target_arch.as_str() {
		"x86_64" => "x86_64-unknown-none-hermitkernel",
		"aarch64" => "aarch64-unknown-hermit",
		_ => panic!("Unsupported target arch: {}", target_arch),
	};

	cmd.arg("build")
		.arg("-Z")
		.arg("build-std=core,alloc")
		.arg("--target")
		.arg(kernel_triple)
		.arg("--manifest-path")
		.arg("Cargo.toml");

	cmd.current_dir(src_dir);

	cmd.env_remove("RUSTUP_TOOLCHAIN");
	if option_env!("RUSTC_WORKSPACE_WRAPPER")
		.unwrap_or_default()
		.ends_with("clippy-driver")
	{
		cmd.env("RUSTC_WORKSPACE_WRAPPER", "clippy-driver");
	}

	cmd.env("CARGO_TERM_COLOR", "always");

	cmd.arg("--target-dir").arg(&target_dir);

	if profile == "release" {
		cmd.arg("--release");
	}

	// Control enabled features via this crate's features
	cmd.arg("--no-default-features");
	forward_features!(cmd, "acpi", "fsgsbase", "pci", "smp", "vga",);

	let mut rustflags = vec!["-Zmutable-noalias=no".to_string()];
	let outer_rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();

	#[cfg(feature = "instrument")]
	{
		rustflags.push("-Zinstrument-mcount".to_string());
		// Add outer rustflags to command
		rustflags.push(outer_rustflags);
	}

	#[cfg(not(feature = "instrument"))]
	{
		// If the `instrument` feature feature is not enabled,
		// filter it from outer rustflags before adding them to the command.
		if !outer_rustflags.is_empty() {
			let flags = outer_rustflags
				.split('\x1f')
				.filter(|&flag| !flag.contains("instrument-mcount"))
				.map(String::from);
			rustflags.extend(flags);
		}
	}

	cmd.env("CARGO_ENCODED_RUSTFLAGS", rustflags.join("\x1f"));

	let status = cmd.status().expect("failed to start kernel build");
	assert!(status.success());

	let lib_location = target_dir
		.join(kernel_triple)
		.join(&profile)
		.canonicalize()
		.unwrap();

	println!("Lib location: {}", lib_location.display());

	let lib = lib_location.join("libhermit.a");

	let mut symbols = vec!["rust_begin_unwind", "rust_oom"];

	if target_arch == "aarch64" {
		symbols.extend(include_str!("aarch64-duplicate-symbols").lines());
	}

	rename_symbols(symbols, &lib);

	println!("cargo:rustc-link-search=native={}", lib_location.display());
	println!("cargo:rustc-link-lib=static=hermit");

	println!("cargo:rerun-if-changed={}", src_dir.display());
	// HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
	println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
}

/// Kernel and user space has its own versions of panic handler, oom handler, memcpy, memset, etc,
/// Consequently, we rename the functions in the libos to avoid collisions.
fn rename_symbols(symbols: impl IntoIterator<Item = impl AsRef<OsStr>>, lib: impl AsRef<Path>) {
	let args = symbols.into_iter().flat_map(|symbol| {
		let option = OsStr::new("--redefine-sym");
		let arg = [symbol.as_ref(), "=kernel-".as_ref(), symbol.as_ref()]
			.into_iter()
			.collect::<OsString>();
		[Cow::Borrowed(option), Cow::Owned(arg)]
	});

	let status = Command::new("rust-objcopy")
		.args(args)
		.arg(lib.as_ref())
		.status()
		.expect("Failed to execute rust-objcopy. Is cargo-binutils installed?");
	assert!(status.success(), "rust-objcopy was not successful");
}

#[cfg(all(not(feature = "rustc-dep-of-std"), not(feature = "with_submodule")))]
fn build() {
	#[cfg(windows)]
	let out_dir = env::temp_dir();
	#[cfg(not(windows))]
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let src_dir = out_dir.join("rusty-hermit");

	if !src_dir.as_path().exists() {
		let status = Command::new(env!("CARGO"))
			.current_dir(out_dir)
			.arg("download")
			.arg("--output")
			.arg(src_dir.clone().into_os_string())
			.arg("--extract")
			.arg("rusty-hermit")
			.status()
			.expect("failed to start kernel download");
		assert!(
			status.success(),
			"Unable to download rusty-hermit. Is cargo-download installed?"
		);
	}

	build_hermit(src_dir.as_ref());
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn build() {
	let src_dir = env::current_dir()
		.unwrap()
		.parent()
		.unwrap()
		.join("libhermit-rs");

	build_hermit(src_dir.as_ref());
}

#[cfg(not(feature = "rustc-dep-of-std"))]
fn create_constants() {
	let out_dir = env::var("OUT_DIR").expect("No out dir");
	let dest_path = Path::new(&out_dir).join("constants.rs");
	let mut f = File::create(&dest_path).expect("Could not create file");

	let ip = option_env!("HERMIT_IP");
	let ip = ip.map_or("10.0.5.3", |v| v);

	let gateway = option_env!("HERMIT_GATEWAY");
	let gateway = gateway.map_or("10.0.5.1", |v| v);

	let mask = option_env!("HERMIT_MASK");
	let mask = mask.map_or("255.255.255.0", |v| v);

	writeln!(f, "const HERMIT_IP: &str = \"{}\";", ip).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_IP");

	writeln!(f, "const HERMIT_GATEWAY: &str = \"{}\";", gateway).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_GATEWAY");

	writeln!(f, "const HERMIT_MASK: &str = \"{}\";", mask).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_MASK");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	create_constants();
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<|endoftext|>


<commit_before>// multi tasking k-nucleotide

import io::reader_util;

use std;
import std::map;
import std::map::hashmap;
import std::sort;

// given a map, print a sorted version of it
fn sort_and_fmt(mm: hashmap<[u8], uint>, total: uint) -> str {
   fn pct(xx: uint, yy: uint) -> float {
      ret (xx as float) * 100f / (yy as float);
   }

   fn le_by_val<TT: copy, UU: copy>(kv0: (TT,UU), kv1: (TT,UU)) -> bool {
      let (_, v0) = kv0;
      let (_, v1) = kv1;
      ret v0 >= v1;
   }

   fn le_by_key<TT: copy, UU: copy>(kv0: (TT,UU), kv1: (TT,UU)) -> bool {
      let (k0, _) = kv0;
      let (k1, _) = kv1;
      ret k0 <= k1;
   }

   // sort by key, then by value
   fn sortKV<TT: copy, UU: copy>(orig: [(TT,UU)]) -> [(TT,UU)] {
      ret sort::merge_sort(le_by_val, sort::merge_sort(le_by_key, orig));
   }

   let mut pairs = [];

   // map -> [(k,%)]
   mm.each(fn&(key: [u8], val: uint) -> bool {
      pairs += [(key, pct(val, total))];
      ret true;
   });

   let pairs_sorted = sortKV(pairs);

   let mut buffer = "";

   pairs_sorted.each(fn&(kv: ([u8], float)) -> bool unsafe {
      let (k,v) = kv;
      buffer += (#fmt["%s %0.3f\n", str::to_upper(str::unsafe::from_bytes(k)), v]);
      ret true;
   });

   ret buffer;
}

// given a map, search for the frequency of a pattern
fn find(mm: hashmap<[u8], uint>, key: str) -> uint {
   alt mm.find(str::bytes(str::to_lower(key))) {
      option::none      { ret 0u; }
      option::some(num) { ret num; }
   }
}

// given a map, increment the counter for a key
fn update_freq(mm: hashmap<[u8], uint>, key: [u8]) {
   alt mm.find(key) {
      option::none      { mm.insert(key, 1u      ); }
      option::some(val) { mm.insert(key, 1u + val); }
   }
}

// given a [u8], for each window call a function
// i.e., for "hello" and windows of size four,
// run it("hell") and it("ello"), then return "llo"
fn windows_with_carry(bb: [const u8], nn: uint, it: fn(window: [u8])) -> [u8] {
   let mut ii = 0u;

   let len = vec::len(bb);
   while ii < len - (nn - 1u) {
      it(vec::slice(bb, ii, ii+nn));
      ii += 1u;
   }

   ret vec::slice(bb, len - (nn - 1u), len);
}

fn make_sequence_processor(sz: uint, from_parent: comm::port<[u8]>, to_parent: comm::chan<str>) {

   let freqs: hashmap<[u8], uint> = map::bytes_hash();
   let mut carry: [u8] = [];
   let mut total: uint = 0u;

   let mut line: [u8];

   loop {

      line = comm::recv(from_parent);
      if line == [] { break; }

      carry = windows_with_carry(carry + line, sz, { |window|
         update_freq(freqs, window);
         total += 1u;
      });
   }

   let buffer = alt sz {
       1u { sort_and_fmt(freqs, total) }
       2u { sort_and_fmt(freqs, total) }
       3u { #fmt["%u\t%s", find(freqs, "GGT"), "GGT"] }
       4u { #fmt["%u\t%s", find(freqs, "GGTA"), "GGTA"] }
       6u { #fmt["%u\t%s", find(freqs, "GGTATT"), "GGTATT"] }
      12u { #fmt["%u\t%s", find(freqs, "GGTATTTTAATT"), "GGTATTTTAATT"] }
      18u { #fmt["%u\t%s", find(freqs, "GGTATTTTAATTTATAGT"), "GGTATTTTAATTTATAGT"] }
        _ { "" }
   };

   //comm::send(to_parent, #fmt["yay{%u}", sz]);
   comm::send(to_parent, buffer);
}

// given a FASTA file on stdin, process sequence THREE
fn main(args: [str]) {
   let rdr = if os::getenv("RUST_BENCH").is_some() {
       // FIXME: Using this compile-time env variable is a crummy way to
       // get to this massive data set, but #include_bin chokes on it
       let path = path::connect(
           #env("CFG_SRC_DIR"),
           "src/test/bench/shootout-k-nucleotide.data"
           );
       result::get(io::file_reader(path))
   } else {
      io::stdin()
   };

   // initialize each sequence sorter
   let sizes = [1u,2u,3u,4u,6u,12u,18u];
   let from_child = vec::map (sizes, { |_sz|     comm::port() });
   let to_parent  = vec::mapi(sizes, { |ii, _sz| comm::chan(from_child[ii]) });
   let to_child   = vec::mapi(sizes, fn@(ii: uint, sz: uint) -> comm::chan<[u8]> {
      ret task::spawn_listener { |from_parent|
         make_sequence_processor(sz, from_parent, to_parent[ii]);
      };
   });

   // latch stores true after we've started
   // reading the sequence of interest
   let mut proc_mode = false;

   while !rdr.eof() {
      let line: str = rdr.read_line();

      if str::len(line) == 0u { cont; }

      alt (line[0], proc_mode) {

         // start processing if this is the one
         ('>' as u8, false) {
            alt str::find_str_from(line, "THREE", 1u) {
               option::some(_) { proc_mode = true; }
               option::none    { }
            }
         }

         // break our processing
         ('>' as u8, true) { break; }

         // process the sequence for k-mers
         (_, true) {
            let line_bytes = str::bytes(line);

            for sizes.eachi { |ii, _sz|
               let mut lb = line_bytes;
               comm::send(to_child[ii], lb);
            }
         }

         // whatever
         _ { }
      }
   }

   // finish...
   for sizes.eachi { |ii, _sz|
      comm::send(to_child[ii], []);
   }

   // now fetch and print result messages
   for sizes.eachi { |ii, _sz|
      io::println(comm::recv(from_child[ii]));
   }
}

<commit_msg>bench: xfail-pretty shootout-k-nucleotide<commit_after>// xfail-pretty

// multi tasking k-nucleotide

import io::reader_util;

use std;
import std::map;
import std::map::hashmap;
import std::sort;

// given a map, print a sorted version of it
fn sort_and_fmt(mm: hashmap<[u8], uint>, total: uint) -> str {
   fn pct(xx: uint, yy: uint) -> float {
      ret (xx as float) * 100f / (yy as float);
   }

   fn le_by_val<TT: copy, UU: copy>(kv0: (TT,UU), kv1: (TT,UU)) -> bool {
      let (_, v0) = kv0;
      let (_, v1) = kv1;
      ret v0 >= v1;
   }

   fn le_by_key<TT: copy, UU: copy>(kv0: (TT,UU), kv1: (TT,UU)) -> bool {
      let (k0, _) = kv0;
      let (k1, _) = kv1;
      ret k0 <= k1;
   }

   // sort by key, then by value
   fn sortKV<TT: copy, UU: copy>(orig: [(TT,UU)]) -> [(TT,UU)] {
      ret sort::merge_sort(le_by_val, sort::merge_sort(le_by_key, orig));
   }

   let mut pairs = [];

   // map -> [(k,%)]
   mm.each(fn&(key: [u8], val: uint) -> bool {
      pairs += [(key, pct(val, total))];
      ret true;
   });

   let pairs_sorted = sortKV(pairs);

   let mut buffer = "";

   pairs_sorted.each(fn&(kv: ([u8], float)) -> bool unsafe {
      let (k,v) = kv;
      buffer += (#fmt["%s %0.3f\n", str::to_upper(str::unsafe::from_bytes(k)), v]);
      ret true;
   });

   ret buffer;
}

// given a map, search for the frequency of a pattern
fn find(mm: hashmap<[u8], uint>, key: str) -> uint {
   alt mm.find(str::bytes(str::to_lower(key))) {
      option::none      { ret 0u; }
      option::some(num) { ret num; }
   }
}

// given a map, increment the counter for a key
fn update_freq(mm: hashmap<[u8], uint>, key: [u8]) {
   alt mm.find(key) {
      option::none      { mm.insert(key, 1u      ); }
      option::some(val) { mm.insert(key, 1u + val); }
   }
}

// given a [u8], for each window call a function
// i.e., for "hello" and windows of size four,
// run it("hell") and it("ello"), then return "llo"
fn windows_with_carry(bb: [const u8], nn: uint, it: fn(window: [u8])) -> [u8] {
   let mut ii = 0u;

   let len = vec::len(bb);
   while ii < len - (nn - 1u) {
      it(vec::slice(bb, ii, ii+nn));
      ii += 1u;
   }

   ret vec::slice(bb, len - (nn - 1u), len);
}

fn make_sequence_processor(sz: uint, from_parent: comm::port<[u8]>, to_parent: comm::chan<str>) {

   let freqs: hashmap<[u8], uint> = map::bytes_hash();
   let mut carry: [u8] = [];
   let mut total: uint = 0u;

   let mut line: [u8];

   loop {

      line = comm::recv(from_parent);
      if line == [] { break; }

      carry = windows_with_carry(carry + line, sz, { |window|
         update_freq(freqs, window);
         total += 1u;
      });
   }

   let buffer = alt sz {
       1u { sort_and_fmt(freqs, total) }
       2u { sort_and_fmt(freqs, total) }
       3u { #fmt["%u\t%s", find(freqs, "GGT"), "GGT"] }
       4u { #fmt["%u\t%s", find(freqs, "GGTA"), "GGTA"] }
       6u { #fmt["%u\t%s", find(freqs, "GGTATT"), "GGTATT"] }
      12u { #fmt["%u\t%s", find(freqs, "GGTATTTTAATT"), "GGTATTTTAATT"] }
      18u { #fmt["%u\t%s", find(freqs, "GGTATTTTAATTTATAGT"), "GGTATTTTAATTTATAGT"] }
        _ { "" }
   };

   //comm::send(to_parent, #fmt["yay{%u}", sz]);
   comm::send(to_parent, buffer);
}

// given a FASTA file on stdin, process sequence THREE
fn main(args: [str]) {
   let rdr = if os::getenv("RUST_BENCH").is_some() {
       // FIXME: Using this compile-time env variable is a crummy way to
       // get to this massive data set, but #include_bin chokes on it
       let path = path::connect(
           #env("CFG_SRC_DIR"),
           "src/test/bench/shootout-k-nucleotide.data"
           );
       result::get(io::file_reader(path))
   } else {
      io::stdin()
   };

   // initialize each sequence sorter
   let sizes = [1u,2u,3u,4u,6u,12u,18u];
   let from_child = vec::map (sizes, { |_sz|     comm::port() });
   let to_parent  = vec::mapi(sizes, { |ii, _sz| comm::chan(from_child[ii]) });
   let to_child   = vec::mapi(sizes, fn@(ii: uint, sz: uint) -> comm::chan<[u8]> {
      ret task::spawn_listener { |from_parent|
         make_sequence_processor(sz, from_parent, to_parent[ii]);
      };
   });

   // latch stores true after we've started
   // reading the sequence of interest
   let mut proc_mode = false;

   while !rdr.eof() {
      let line: str = rdr.read_line();

      if str::len(line) == 0u { cont; }

      alt (line[0], proc_mode) {

         // start processing if this is the one
         ('>' as u8, false) {
            alt str::find_str_from(line, "THREE", 1u) {
               option::some(_) { proc_mode = true; }
               option::none    { }
            }
         }

         // break our processing
         ('>' as u8, true) { break; }

         // process the sequence for k-mers
         (_, true) {
            let line_bytes = str::bytes(line);

            for sizes.eachi { |ii, _sz|
               let mut lb = line_bytes;
               comm::send(to_child[ii], lb);
            }
         }

         // whatever
         _ { }
      }
   }

   // finish...
   for sizes.eachi { |ii, _sz|
      comm::send(to_child[ii], []);
   }

   // now fetch and print result messages
   for sizes.eachi { |ii, _sz|
      io::println(comm::recv(from_child[ii]));
   }
}

<|endoftext|>


<commit_before>use rustc::mir::visit::Visitor;
use rustc::mir::{self, Local, Location};
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::bit_set::BitSet;
use syntax_pos::DUMMY_SP;

use crate::dataflow::{self, GenKillSet};

/// Whether a borrow to a `Local` has been created that could allow that `Local` to be mutated
/// indirectly. This could either be a mutable reference (`&mut`) or a shared borrow if the type of
/// that `Local` allows interior mutability.
///
/// If this returns `false` for a `Local` at a given `Location`, the user can assume that `Local`
/// has not been mutated as a result of an indirect assignment (`*p = x`) or as a side-effect of a
/// function call or drop terminator.
#[derive(Copy, Clone)]
pub struct IndirectlyMutableLocals<'mir, 'tcx> {
    body: &'mir mir::Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'mir, 'tcx> IndirectlyMutableLocals<'mir, 'tcx> {
    pub fn new(
        tcx: TyCtxt<'tcx>,
        body: &'mir mir::Body<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> Self {
        IndirectlyMutableLocals { body, tcx, param_env }
    }

    fn transfer_function<'a>(
        &self,
        trans: &'a mut GenKillSet<Local>,
    ) -> TransferFunction<'a, 'mir, 'tcx> {
        TransferFunction {
            body: self.body,
            tcx: self.tcx,
            param_env: self.param_env,
            trans
        }
    }
}

impl<'mir, 'tcx> dataflow::BitDenotation<'tcx> for IndirectlyMutableLocals<'mir, 'tcx> {
    type Idx = Local;

    fn name() -> &'static str { "mut_borrowed_locals" }

    fn bits_per_block(&self) -> usize {
        self.body.local_decls.len()
    }

    fn start_block_effect(&self, _entry_set: &mut BitSet<Local>) {
        // Nothing is borrowed on function entry
    }

    fn statement_effect(
        &self,
        trans: &mut GenKillSet<Local>,
        loc: Location,
    ) {
        let stmt = &self.body[loc.block].statements[loc.statement_index];
        self.transfer_function(trans).visit_statement(stmt, loc);
    }

    fn terminator_effect(
        &self,
        trans: &mut GenKillSet<Local>,
        loc: Location,
    ) {
        let terminator = self.body[loc.block].terminator();
        self.transfer_function(trans).visit_terminator(terminator, loc);
    }

    fn propagate_call_return(
        &self,
        _in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        _dest_place: &mir::Place<'tcx>,
    ) {
        // Nothing to do when a call returns successfully
    }
}

impl<'mir, 'tcx> dataflow::BottomValue for IndirectlyMutableLocals<'mir, 'tcx> {
    // bottom = unborrowed
    const BOTTOM_VALUE: bool = false;
}

/// A `Visitor` that defines the transfer function for `IndirectlyMutableLocals`.
struct TransferFunction<'a, 'mir, 'tcx> {
    trans: &'a mut GenKillSet<Local>,
    body: &'mir mir::Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> {
    fn visit_rvalue(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        location: Location,
    ) {
        if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue {
            let is_mut = match kind {
                mir::BorrowKind::Mut { .. } => true,

                | mir::BorrowKind::Shared
                | mir::BorrowKind::Shallow
                | mir::BorrowKind::Unique
                => {
                    !borrowed_place
                        .ty(self.body, self.tcx)
                        .ty
                        .is_freeze(self.tcx, self.param_env, DUMMY_SP)
                }
            };

            if is_mut {
                match borrowed_place.base {
                    mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect()
                        => self.trans.gen(borrowed_local),

                    _ => (),
                }
            }
        }

        self.super_rvalue(rvalue, location);
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
        // This method purposely does nothing except call `super_terminator`. It exists solely to
        // document the subtleties around drop terminators.

        self.super_terminator(terminator, location);

        if let mir::TerminatorKind::Drop { location: _, .. }
             | mir::TerminatorKind::DropAndReplace { location: _, .. } = &terminator.kind
        {
            // Although drop terminators mutably borrow the location being dropped, that borrow
            // cannot live beyond the drop terminator because the dropped location is invalidated.
        }
    }
}
<commit_msg>Give usage instructions `IndirectlyMutableLocals` docs<commit_after>use rustc::mir::visit::Visitor;
use rustc::mir::{self, Local, Location};
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::bit_set::BitSet;
use syntax_pos::DUMMY_SP;

use crate::dataflow::{self, GenKillSet};

/// Whether a borrow to a `Local` has been created that could allow that `Local` to be mutated
/// indirectly. This could either be a mutable reference (`&mut`) or a shared borrow if the type of
/// that `Local` allows interior mutability.
///
/// If this returns false for a `Local` at the location of an indirect assignment, that `Local`
/// cannot be mutated by that assignment. For example, if the dataflow state at a statement like
/// `*p = 42` contained locals `x` and `z` but not `y`, we know that while `x` or `z` may be the
/// target of that assignment, `y` cannot be.
///
/// Assignments through a pointer are not the only place where a `Local` can be mutated indirectly:
/// Function calls, drop terminators and inline assembly can all mutate `Local`s as a side-effect.
#[derive(Copy, Clone)]
pub struct IndirectlyMutableLocals<'mir, 'tcx> {
    body: &'mir mir::Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'mir, 'tcx> IndirectlyMutableLocals<'mir, 'tcx> {
    pub fn new(
        tcx: TyCtxt<'tcx>,
        body: &'mir mir::Body<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> Self {
        IndirectlyMutableLocals { body, tcx, param_env }
    }

    fn transfer_function<'a>(
        &self,
        trans: &'a mut GenKillSet<Local>,
    ) -> TransferFunction<'a, 'mir, 'tcx> {
        TransferFunction {
            body: self.body,
            tcx: self.tcx,
            param_env: self.param_env,
            trans
        }
    }
}

impl<'mir, 'tcx> dataflow::BitDenotation<'tcx> for IndirectlyMutableLocals<'mir, 'tcx> {
    type Idx = Local;

    fn name() -> &'static str { "mut_borrowed_locals" }

    fn bits_per_block(&self) -> usize {
        self.body.local_decls.len()
    }

    fn start_block_effect(&self, _entry_set: &mut BitSet<Local>) {
        // Nothing is borrowed on function entry
    }

    fn statement_effect(
        &self,
        trans: &mut GenKillSet<Local>,
        loc: Location,
    ) {
        let stmt = &self.body[loc.block].statements[loc.statement_index];
        self.transfer_function(trans).visit_statement(stmt, loc);
    }

    fn terminator_effect(
        &self,
        trans: &mut GenKillSet<Local>,
        loc: Location,
    ) {
        let terminator = self.body[loc.block].terminator();
        self.transfer_function(trans).visit_terminator(terminator, loc);
    }

    fn propagate_call_return(
        &self,
        _in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        _dest_place: &mir::Place<'tcx>,
    ) {
        // Nothing to do when a call returns successfully
    }
}

impl<'mir, 'tcx> dataflow::BottomValue for IndirectlyMutableLocals<'mir, 'tcx> {
    // bottom = unborrowed
    const BOTTOM_VALUE: bool = false;
}

/// A `Visitor` that defines the transfer function for `IndirectlyMutableLocals`.
struct TransferFunction<'a, 'mir, 'tcx> {
    trans: &'a mut GenKillSet<Local>,
    body: &'mir mir::Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> {
    fn visit_rvalue(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        location: Location,
    ) {
        if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue {
            let is_mut = match kind {
                mir::BorrowKind::Mut { .. } => true,

                | mir::BorrowKind::Shared
                | mir::BorrowKind::Shallow
                | mir::BorrowKind::Unique
                => {
                    !borrowed_place
                        .ty(self.body, self.tcx)
                        .ty
                        .is_freeze(self.tcx, self.param_env, DUMMY_SP)
                }
            };

            if is_mut {
                match borrowed_place.base {
                    mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect()
                        => self.trans.gen(borrowed_local),

                    _ => (),
                }
            }
        }

        self.super_rvalue(rvalue, location);
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
        // This method purposely does nothing except call `super_terminator`. It exists solely to
        // document the subtleties around drop terminators.

        self.super_terminator(terminator, location);

        if let mir::TerminatorKind::Drop { location: _, .. }
             | mir::TerminatorKind::DropAndReplace { location: _, .. } = &terminator.kind
        {
            // Although drop terminators mutably borrow the location being dropped, that borrow
            // cannot live beyond the drop terminator because the dropped location is invalidated.
        }
    }
}
<|endoftext|>


<commit_before>use Result;
use super::{Component, Layout, Spec};

const CORE_LABEL: &'static str = "Core";
const L3_LABEL: &'static str = "L3";

const CORE_WIDTH_HEIGHT_RATIO: f64 = 0.5;
const CORES_PER_L3: usize = 4;

pub struct Tiles;

impl Layout for Tiles {
    fn construct(&self, &Spec { core_count, core_area, l3_area }: &Spec)
                 -> Result<Vec<Component>> {

        if core_count % CORES_PER_L3 != 0 {
            raise!("the number of cores should be a multiple of {}", CORES_PER_L3);
        }

        let core_width = (core_area * CORE_WIDTH_HEIGHT_RATIO).sqrt();
        let core_height = core_area / core_width;

        let l3_width = (CORES_PER_L3 as f64) * core_width;
        let l3_height = l3_area / l3_width;

        let mut components = Vec::new();
        for k in 0..core_count {
            let l = k / (2 * CORES_PER_L3);
            let i = (k % (2 * CORES_PER_L3)) % CORES_PER_L3 + l * CORES_PER_L3;
            let j = (k % (2 * CORES_PER_L3)) / CORES_PER_L3;
            if i % CORES_PER_L3 == 0 && j == 1 {
                components.push(Component {
                    name: format!("{}{}", L3_LABEL, 2 * l + 1),
                    position: ((l as f64) * l3_width, core_height + l3_height),
                    dimension: (l3_width, l3_height),
                });
            }
            components.push(Component {
                name: format!("{}{}", CORE_LABEL, k),
                position: ((i as f64) * core_width, (j as f64) * (core_height + 2.0 * l3_height)),
                dimension: (core_width, core_height),
            });
            if i % CORES_PER_L3 == CORES_PER_L3 - 1 && j == 0 {
                components.push(Component {
                    name: format!("{}{}", L3_LABEL, 2 * l),
                    position: ((l as f64) * l3_width, core_height),
                    dimension: (l3_width, l3_height),
                });
            }
        }
        Ok(components)
    }
}
<commit_msg>Introduce size resolution<commit_after>use Result;
use super::{Component, Layout, Spec};

const CORE_LABEL: &'static str = "Core";
const L3_LABEL: &'static str = "L3";

const CORES_PER_L3: usize = 4;
const CORE_WIDTH_HEIGHT_RATIO: f64 = 0.5;
const SIZE_RESOLUTION: f64 = 1e6;

pub struct Tiles;

impl Layout for Tiles {
    fn construct(&self, &Spec { core_count, core_area, l3_area }: &Spec)
                 -> Result<Vec<Component>> {

        macro_rules! round(
            ($size:expr) => ({
                let mut size = (SIZE_RESOLUTION * $size).round() as usize;
                size += size % 2;
                (size as f64) / SIZE_RESOLUTION
            });
        );

        if core_count % CORES_PER_L3 != 0 {
            raise!("the number of cores should be a multiple of {}", CORES_PER_L3);
        }

        let core_width = round!((core_area * CORE_WIDTH_HEIGHT_RATIO).sqrt());
        let core_height = round!(core_area / core_width);

        let l3_width = round!((CORES_PER_L3 as f64) * core_width);
        let l3_height = round!(l3_area / l3_width);

        let mut components = Vec::new();
        for k in 0..core_count {
            let l = k / (2 * CORES_PER_L3);
            let i = (k % (2 * CORES_PER_L3)) % CORES_PER_L3 + l * CORES_PER_L3;
            let j = (k % (2 * CORES_PER_L3)) / CORES_PER_L3;
            if i % CORES_PER_L3 == 0 && j == 1 {
                components.push(Component {
                    name: format!("{}{}", L3_LABEL, 2 * l + 1),
                    position: ((l as f64) * l3_width, core_height + l3_height),
                    dimension: (l3_width, l3_height),
                });
            }
            components.push(Component {
                name: format!("{}{}", CORE_LABEL, k),
                position: ((i as f64) * core_width, (j as f64) * (core_height + 2.0 * l3_height)),
                dimension: (core_width, core_height),
            });
            if i % CORES_PER_L3 == CORES_PER_L3 - 1 && j == 0 {
                components.push(Component {
                    name: format!("{}{}", L3_LABEL, 2 * l),
                    position: ((l as f64) * l3_width, core_height),
                    dimension: (l3_width, l3_height),
                });
            }
        }
        Ok(components)
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test the uninit() construct returning various empty types.

use std::vec;
use std::unstable::intrinsics;

#[deriving(Clone)]
struct Foo;

fn main() {
    unsafe {
        let _x: Foo = intrinsics::uninit();
        let _x: [Foo, ..2] = intrinsics::uninit();
    }
}
<commit_msg>Make main() public in uninit-empty-types<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test the uninit() construct returning various empty types.

use std::vec;
use std::unstable::intrinsics;

#[deriving(Clone)]
struct Foo;

pub fn main() {
    unsafe {
        let _x: Foo = intrinsics::uninit();
        let _x: [Foo, ..2] = intrinsics::uninit();
    }
}
<|endoftext|>