1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
//! code generation for trashcan bits/atoms

use std::io;
use std::io::Write;

use ast::*;
use super::*;
use analysis::SymbolTable;

// used to handle some of our wacky gensyms; they're the only
//   non-ASCII characters we emit, and they're all valid Latin-1
fn to_latin1(s: &str) -> Vec<u8> {
    s.chars().map(|c| c as u8).collect()
}

impl Emit<()> for Ident {
    fn emit<W: Write>(&self, out: &mut W, _symtab: &SymbolTable,
      _ctxt: (), indent: u32) -> io::Result<()> {
        write!(out, "{:in$}", "", in = (indent * INDENT) as usize)?;
        out.write_all(&to_latin1(&self.0))
    }
}

impl Emit<()> for Path {
    fn emit<W: Write>(&self, out: &mut W, _symtab: &SymbolTable,
      _ctxt: (), indent: u32) -> io::Result<()> {
        write!(out, "{:in$}", "", in = (indent * INDENT) as usize)?;
        if let Some(ref module) = self.0 {
            out.write_all(&to_latin1(&module.0))?;
            out.write_all(b".")?;
        }
        out.write_all(&to_latin1(&(self.1).0))
    }
}

impl Emit<()> for Access {
    fn emit<W: Write>(&self, out: &mut W, _symtab: &SymbolTable,
      _ctxt: (), indent: u32) -> io::Result<()> {
        write!(out, "{:in$}{}", "", match *self {
            Access::Private => "Private",
            Access::Public => "Public",
        }, in = (indent * INDENT) as usize)
    }
}

impl Emit<()> for ParamMode {
    fn emit<W: Write>(&self, out: &mut W, _symtab: &SymbolTable,
      _ctxt: (), indent: u32) -> io::Result<()> {
        write!(out, "{:in$}{}", "", match *self {
            ParamMode::ByVal => "ByVal",
            ParamMode::ByRef => "ByRef",
        }, in = (indent * INDENT) as usize)
    }
}

// just the "combination" operator
impl Emit<()> for AssignOp {
    fn emit<W: Write>(&self, out: &mut W, _symtab: &SymbolTable,
      _ctxt: (), _indent: u32) -> io::Result<()> {
        let op: &[u8] = match *self {
            AssignOp::AddAssign => b" + ",
            AssignOp::SubAssign => b" - ",
            AssignOp::MulAssign => b" * ",
            AssignOp::DivAssign => b" / ",
            AssignOp::ModAssign => b" Mod ",
            AssignOp::PowAssign => b" ^ ",
            AssignOp::StrCatAssign => b" & ",
            AssignOp::BitAndAssign => b" And ",
            AssignOp::BitOrAssign => b" Or ",
            AssignOp::LogAndAssign => b" And ",
            AssignOp::LogOrAssign => b" Or ",
            AssignOp::Assign => panic!("dumpster fire basic assign should \
              never result in AssignOp::emit()"),
        };
        out.write_all(op)
    }
}

// just the operator
impl Emit<()> for BinOp {
    fn emit<W: Write>(&self, out: &mut W, _symtab: &SymbolTable,
      _ctxt: (), _indent: u32) -> io::Result<()> {
        let op: &[u8] = match *self {
            BinOp::Add => b" + ",
            BinOp::Sub => b" - ",
            BinOp::Mul => b" * ",
            BinOp::Div => b" / ",
            BinOp::Mod => b" Mod ",
            BinOp::Pow => b"^",
            BinOp::StrCat => b" & ",
            BinOp::Eq => b" = ",
            BinOp::NotEq => b" <> ",
            BinOp::IdentEq => b" Is ",
            BinOp::Lt => b" < ",
            BinOp::Gt => b" > ",
            BinOp::LtEq => b" <= ",
            BinOp::GtEq => b" >= ",
            BinOp::BitAnd => b" And ",
            BinOp::BitOr => b" Or ",
            BinOp::LogAnd => b" And ",
            BinOp::LogOr => b" Or ",
            BinOp::NotIdentEq => panic!("dumpster fire: BinOp::NotIdentEq \
              should never be emitted directly"),
        };
        out.write_all(op)
    }
}