use std::collections::{HashMap, HashSet};
use std::{u16, u32};
use byteorder::{ByteOrder, LE};
use gc::Trace;
use oftlisp::{CompilerContext, Symbol, Value};
use oftlisp::ast::Args;
use oftlisp::modules::ExportedModule;
use smallvec::SmallVec;
use errors::CompileError;
use types::{Context, Expr, Prim};
const ANFIR_VERSION: u32 = 0x001_00_000;
impl CompilerContext for Context {
type CompileError = CompileError;
fn compile(main_module: Symbol, mut exported_modules: HashMap<Symbol, ExportedModule<Self>>) -> Result<Vec<u8>, Self::CompileError> {
let mut modules = vec![];
let mut moved = HashSet::new();
move_modules(main_module, &mut exported_modules, &mut modules, &mut moved)?;
for (name, _) in exported_modules {
warn!("Unused module: {}", name);
}
if modules.len() > u32::MAX as usize {
return Err(CompileError::TooManyModules);
}
let num_modules = modules.len() as u32;
let mut buf = vec![0; 8];
LE::write_u32(&mut buf[0..4], ANFIR_VERSION);
LE::write_u32(&mut buf[4..8], num_modules);
for (name, m) in modules {
serialize_module(name, &m, &mut buf)?;
}
Ok(buf)
}
}
fn move_modules(name: Symbol, exported: &mut HashMap<Symbol, ExportedModule<Context>>, modules: &mut Vec<(Symbol, ExportedModule<Context>)>, moved: &mut HashSet<Symbol>) -> Result<(), CompileError> {
if moved.contains(&name) {
return Ok(());
}
if let Some(m) = exported.remove(&name) {
let imports = m.imports.iter()
.map(|(&n, _)| n)
.collect::<SmallVec<[Symbol; 64]>>();
modules.push((name, m));
moved.insert(name);
for name in imports {
move_modules(name, exported, modules, moved)?;
}
Ok(())
} else {
Err(CompileError::MissingModule(name))
}
}
fn serialize_module(name: Symbol, m: &ExportedModule<Context>, buf: &mut Vec<u8>) -> Result<(), CompileError> {
let mut out = vec![];
name.serialize(&mut out)?;
if m.exports.len() > u32::MAX as usize {
return Err(CompileError::TooManyExports(name));
} else {
let mut len = [0, 0, 0, 0];
LE::write_u32(&mut len, m.exports.len() as u32);
out.extend(&len);
}
for &ex in &m.exports {
ex.serialize(&mut out)?;
}
if m.imports.len() > u32::MAX as usize {
return Err(CompileError::TooManyImports(name));
} else {
let mut len = [0, 0, 0, 0];
LE::write_u32(&mut len, m.imports.len() as u32);
out.extend(&len);
}
for (&im, syms) in &m.imports {
im.serialize(&mut out)?;
if syms.len() > u32::MAX as usize {
return Err(CompileError::TooManyImportedSymbols(name, im));
} else {
let mut len = [0, 0, 0, 0];
LE::write_u32(&mut len, syms.len() as u32);
out.extend(&len);
}
for &sym in syms {
sym.serialize(&mut out)?;
}
}
if m.body.len() > u32::MAX as usize {
return Err(CompileError::TooManyDecls(name));
} else {
let mut len = [0, 0, 0, 0];
LE::write_u32(&mut len, m.body.len() as u32);
out.extend(&len);
}
for &(name, ref expr) in &m.body {
name.serialize(&mut out)?;
expr.serialize(&mut out)?;
}
buf.extend(out);
Ok(())
}
trait Serializable: Trace {
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CompileError>;
}
impl Serializable for Symbol {
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CompileError> {
if self.len() > u16::MAX as usize {
Err(CompileError::SymbolTooLong(*self))
} else {
let s = self.as_str();
let mut len = [0, 0];
LE::write_u16(&mut len, s.len() as u16);
buf.extend(&len);
buf.extend(s.bytes());
Ok(())
}
}
}
impl Serializable for Option<Symbol> {
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CompileError> {
match *self {
Some(sym) => sym.serialize(buf),
None => {
buf.push(0);
buf.push(0);
Ok(())
},
}
}
}
impl Serializable for Args<Context> {
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CompileError> {
if self.required.len() > u16::MAX as usize {
return Err(CompileError::TooManyArgsInDefn);
} else {
let mut len = [0, 0];
LE::write_u16(&mut len, self.required.len() as u16);
buf.extend(&len);
for sym in &self.required {
sym.serialize(buf)?;
}
}
if self.optional.len() > u16::MAX as usize {
return Err(CompileError::TooManyArgsInDefn);
} else {
let mut len = [0, 0];
LE::write_u16(&mut len, self.optional.len() as u16);
buf.extend(&len);
for &(sym, ref val) in &self.optional {
sym.serialize(buf)?;
val.serialize(buf)?;
}
}
self.rest.serialize(buf)
}
}
impl Serializable for Expr {
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CompileError> {
match *self {
Expr::Call(ref f, ref a) => {
buf.push(0x80);
f.serialize(buf)?;
if a.len() > u16::MAX as usize {
Err(CompileError::TooManyArgsInCall)
} else {
let mut len = [0, 0];
LE::write_u16(&mut len, a.len() as u16);
buf.extend(&len);
for a in a {
a.serialize(buf)?;
}
Ok(())
}
},
Expr::If(ref c, ref t, ref e) => {
buf.push(0xc0);
c.serialize(buf)?;
t.serialize(buf)?;
e.serialize(buf)
},
Expr::Let(n, ref x, ref y) => {
buf.push(0xf0);
n.serialize(buf)?;
x.serialize(buf)?;
y.serialize(buf)
},
Expr::Prim(ref prim) => prim.serialize(buf),
}
}
}
impl Serializable for Prim {
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CompileError> {
match *self {
Prim::Fn(ref n, ref a, ref b) => {
buf.push(0x10);
n.serialize(buf)?;
a.serialize(buf)?;
b.serialize(buf)
},
Prim::Lit(ref v) => v.serialize(buf),
Prim::Var(ref n) => {
buf.push(0x20);
n.serialize(buf)
},
Prim::Vec(ref ps) => {
buf.push(0x30);
if ps.len() > u16::MAX as usize {
Err(CompileError::TooManyArgsInCall)
} else {
let mut len = [0, 0];
LE::write_u16(&mut len, ps.len() as u16);
buf.extend(&len);
for p in ps {
p.serialize(buf)?;
}
Ok(())
}
},
}
}
}
impl Serializable for Value<Context> {
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CompileError> {
match *self {
Value::AtomicWord(..) => Err(CompileError::CannotSerialize(self.clone())),
Value::BuiltinFunction(..) => Err(CompileError::CannotSerialize(self.clone())),
Value::Byte(n, _) => {
buf.push(0x01);
buf.push(n);
Ok(())
},
Value::Bytes(ref bs, _) => {
buf.push(0x02);
if bs.len() > u32::MAX as usize {
Err(CompileError::BytesTooLong(bs.clone()))
} else {
let mut len = [0, 0, 0, 0];
LE::write_u32(&mut len, bs.len() as u32);
buf.extend(&len);
buf.extend(bs.as_ref() as &[u8]);
Ok(())
}
},
Value::Cons(ref h, ref t, _) => {
buf.push(0x03);
h.serialize(buf)?;
t.serialize(buf)
},
Value::Fixnum(n, _) => {
buf.push(0x04);
let mut n_buf = [0, 0, 0, 0, 0, 0, 0, 0];
LE::write_i64(&mut n_buf, n as i64);
buf.extend(&n_buf);
Ok(())
},
Value::Func(..) => Err(CompileError::CannotSerialize(self.clone())),
Value::Object(..) => Err(CompileError::CannotSerialize(self.clone())),
Value::Nil(_) => {
buf.push(0x00);
Ok(())
},
Value::String(ref s, _) => {
buf.push(0x05);
if s.len() > u32::MAX as usize {
Err(CompileError::StringTooLong(s.clone()))
} else {
let mut len = [0, 0, 0, 0];
LE::write_u32(&mut len, s.len() as u32);
buf.extend(&len);
buf.extend(s.bytes());
Ok(())
}
},
Value::Symbol(s, _) => {
buf.push(0x06);
s.serialize(buf)
},
Value::Vector(ref vs, _) => {
buf.push(0x07);
if vs.len() > u32::MAX as usize {
Err(CompileError::VectorTooLong(vs.clone()))
} else {
let mut len = [0, 0, 0, 0];
LE::write_u32(&mut len, vs.len() as u32);
buf.extend(&len);
for v in vs {
v.serialize(buf)?;
}
Ok(())
}
},
}
}
}