dcpu 0.5.0

An assembler, debugger and emulator for the DCPU-16
Documentation
use assembler::types::*;

pub fn print_unused(ast: &[ParsedItem]) {
    let used_labels: Vec<String> = ast.iter().flat_map(|i| i.used_labels().into_iter()).collect();
    for item in ast {
        match *item {
            ParsedItem::LabelDecl(ref l) |
                ParsedItem::Directive(Directive::Lcomm(ref l, _))=> {
                    if !used_labels.contains(&l) {
                        println!("Unused label: {}", l);
                    }
            }
            _ => (),
        }
    }
}

pub fn clean(ast: Vec<ParsedItem>) -> Vec<ParsedItem> {
    let used_labels: Vec<String> = ast.clone().into_iter().flat_map(|i| i.used_labels().into_iter()).collect();
    let mut res = vec![];
    let mut keep = true;
    for item in ast {
        match &item {
            &ParsedItem::LabelDecl(ref l) |
                &ParsedItem::Directive(Directive::Lcomm(ref l, _))=> {
                keep = used_labels.contains(&l);
            }
            _ => (),
        }
        if keep {
            res.push(item);
        }
    }
    res
}

impl ParsedItem {
    fn used_labels(&self) -> Vec<String> {
        match *self {
            ParsedItem::Directive(ref d) => d.used_labels(),
            ParsedItem::Comment(_) |
                ParsedItem::LabelDecl(_) |
                ParsedItem::LocalLabelDecl(_) => vec![],
            ParsedItem::Instruction(ref i) => i.used_labels(),
        }
    }
}

impl Directive {
    fn used_labels(&self) -> Vec<String> {
        use assembler::types::Directive::*;

        match *self {
            Dat(ref ds) => ds.clone().into_iter().flat_map(|d| d.used_labels()).collect(),
            Lcomm(..) | Org(..) | Skip(..) | Global | Text | BSS => vec![],
        }
    }
}

impl DatItem {
    fn used_labels(&self) -> Vec<String> {
        match *self {
            DatItem::E(ref e) => e.used_labels(),
            DatItem::S(..) => vec![],
        }
    }
}

impl Instruction<Expression> {
    fn used_labels(&self) -> Vec<String> {
        match *self {
            Instruction::BasicOp(_, ref b, ref a) => {
                let mut x = a.used_labels();
                x.extend(b.used_labels());
                x
            }
            Instruction::SpecialOp(_, ref a) => a.used_labels(),
        }
    }
}

impl Value<Expression> {
    fn used_labels(&self) -> Vec<String> {
        use types::Value::*;

        match *self {
            AtRegPlus(_, ref e) | Pick(ref e) | AtAddr(ref e) | Litteral(ref e) => {
                e.used_labels()
            }
            _ => vec![],
        }
    }
}

impl Expression {
    fn used_labels(&self) -> Vec<String> {
        use assembler::types::Expression::*;

        match *self {
            Label(ref l) => vec![l.clone()],
            Not(ref e) => e.used_labels(),
            Add(ref a, ref b) |
                Sub(ref a, ref b) |
                Mul(ref a, ref b) |
                Div(ref a, ref b) |
                Shr(ref a, ref b) |
                Shl(ref a, ref b) |
                Mod(ref a, ref b) |
                Less(ref a, ref b) |
                Equal(ref a, ref b) |
                Greater(ref a, ref b) => {
                    let mut x = a.used_labels();
                    x.extend(b.used_labels());
                    x
                }
            LocalLabel(_) | Num(_) => vec![],
        }
    }
}