use crate::{prelude::*, binary::PROGRAM_HEADER}; use std::ops::Deref; use super::{prim::VarInt, Program, Serializer, Serialize}; macro_rules! error { ($($arg:tt)*) => { exception!(BINARY_EXCEPTION, $($arg)*) }; } impl Serialize for Program { fn serialize(&self, s: &mut S) -> Result<()> { for b in PROGRAM_HEADER { s.write(b)?; } s.write(self.version)?; s.serialize(self.fun.as_ref())?; Ok(()) } } impl Serialize for Instruction { fn serialize(&self, s: &mut S) -> Result<()> { use Instruction as I; match self { I::NoOp => { s.write(0u8)?; }, I::CreateLocal => { s.write(1u8)?; }, I::LoadLocal(idx) => { s.write(2u8)?; s.write(*idx)?; }, I::StoreLocal(idx) => { s.write(3u8)?; s.write(*idx)?; }, I::DiscardLocals(idx) => { s.write(4u8)?; s.write(*idx)?; }, I::LoadGlobal(idx) => { s.write(5u8)?; s.write(*idx)?; } I::StoreGlobal(idx) => { s.write(6u8)?; s.write(*idx)?; }, I::Const(idx) => { s.write(7u8)?; s.write(*idx)?; }, I::Int(i) => { s.write(8u8)?; s.write(*i)?; }, I::True => { s.write(9u8)?; }, I::False => { s.write(10u8)?; }, I::Nil => { s.write(11u8)?; }, I::Dup => { s.write(12u8)?; }, I::Discard(idx) => { s.write(13u8)?; s.write(*idx)?; }, I::UnaryOp(op) => { s.write(14u8)?; s.write(*op as u8)?; }, I::BinaryOp(op) => { s.write(15u8)?; s.write(*op as u8)?; }, I::NewList(len) => { s.write(16u8)?; s.write(*len)?; }, I::NewTable(len) => { s.write(17u8)?; s.write(*len)?; }, I::NewMatrix(d, c) => { s.write(18u8)?; s.write(*d)?; s.write(*c)?; }, I::Field(idx) => { s.write(19u8)?; s.write(*idx)?; }, I::StoreField(idx) => { s.write(20u8)?; s.write(*idx)?; }, I::Index(idx) => { s.write(21u8)?; s.write(*idx)?; }, I::StoreIndex(idx) => { s.write(22u8)?; s.write(*idx)?; }, I::Jump(ip) => { s.write(23u8)?; s.write(*ip)?; }, I::JumpTrue(ip) => { s.write(24u8)?; s.write(*ip)?; }, I::JumpFalse(ip) => { s.write(25u8)?; s.write(*ip)?; }, I::JumpNil(ip) => { s.write(26u8)?; s.write(*ip)?; }, I::IterCreate => { s.write(27u8)?; }, I::IterNext => { s.write(28u8)?; }, I::Try(ip) => { s.write(29u8)?; s.write(*ip)?; }, I::TryEnd => { s.write(30u8)?; }, I::Call(arity) => { s.write(31u8)?; s.write(*arity)?; }, I::Return => { s.write(32u8)?; }, }; Ok(()) } } impl Serialize for Vec { fn serialize(&self, s: &mut S) -> Result<()> { s.write(VarInt(self.len()))?; for val in self { val.serialize(s)?; } Ok(()) } } impl Serialize for Gc { fn serialize(&self, s: &mut S) -> Result<()> { self.deref().serialize(s) } } impl Serialize for Rc { fn serialize(&self, s: &mut S) -> Result<()> { self.deref().serialize(s) } } impl Serialize for Position { fn serialize(&self, s: &mut S) -> Result<()> { s.write(VarInt(self.row))?; s.write(VarInt(self.col))?; Ok(()) } } impl Serialize for Chunk { fn serialize(&self, s: &mut S) -> Result<()> { self.constants.serialize(s)?; self.code.serialize(s)?; self.pos.serialize(s)?; Ok(()) } } impl Serialize for Value { fn serialize(&self, s: &mut S) -> Result<()> { use Value as V; match self { V::Nil => { s.write(0u8)?; }, V::Bool(b) => { s.write(1u8)?; s.write(*b)?; }, V::Int(i) => { s.write(2u8)?; s.write(*i)?; }, V::Float(f) => { s.write(3u8)?; s.write(*f)?; }, V::Ratio(r) => { s.write(4u8)?; s.write(*r.numer())?; s.write(*r.denom())?; }, V::Complex(c) => { s.write(5u8)?; s.write(c.re)?; s.write(c.im)?; }, V::Regex(r) => { s.write(6u8)?; s.write(r.to_string())?; }, V::String(str) => { s.write(7u8)?; s.write(str.to_string())?; }, V::List(l) => { s.write(8u8)?; l.serialize(s)?; }, V::Matrix(m) => { s.write(9u8)?; s.write(m.domain)?; s.write(m.codomain)?; m.values.serialize(s)?; }, V::Table(t) => { s.write(10u8)?; s.write(VarInt(t.len()))?; for (key, value) in t.entries() { key.serialize(s)?; value.serialize(s)?; } }, V::Function(f) => { s.write(11u8)?; f.serialize(s)?; }, V::Range(r) => { s.write(12u8)?; s.write(r.0)?; s.write(r.1)?; s.write(r.2)?; }, V::Iter(f) => { s.write(13u8)?; f.serialize(s)?; }, V::File(_) => return Err(error!("cannot compile file")), V::Exception(_) => return Err(error!("cannot compile exception")), }; Ok(()) } } impl Serialize for Function { fn serialize(&self, s: &mut S) -> Result<()> { s.write(self.name.to_string())?; s.write(self.arity)?; s.write(self.variadic)?; use InnerFunction as F; match &self.fun { F::Compiled(c) => { c.serialize(s)?; }, F::Native(_) => return Err(error!("cannot compile native function")), }; Ok(()) } }