diff options
Diffstat (limited to 'matrix-lang/src/binary/deserialize.rs')
-rw-r--r-- | matrix-lang/src/binary/deserialize.rs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/matrix-lang/src/binary/deserialize.rs b/matrix-lang/src/binary/deserialize.rs new file mode 100644 index 0000000..679f6e5 --- /dev/null +++ b/matrix-lang/src/binary/deserialize.rs @@ -0,0 +1,160 @@ +use crate::prelude::*; + +use super::{prim::VarInt, Deserialize, Deserializer}; + +macro_rules! error { + ($($arg:tt)*) => { + exception!(BINARY_EXCEPTION, $($arg)*) + }; +} + +impl Deserialize for Program { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + for _ in 0..5 { s.read::<u8>()?; } // skip header + let version: u8 = s.read()?; + if version != 0 { + return Err(error!("invalid program version {version}")) + } + let fun = <Rc<Function>>::deserialize(s)?; + Ok(Self { version, fun }) + } +} + +impl Deserialize for Instruction { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + use Instruction as I; + let ins: u8 = s.read()?; + let ins = match ins { + 0 => I::NoOp, + 1 => I::CreateLocal, + 2 => I::LoadLocal(s.read()?), + 3 => I::StoreLocal(s.read()?), + 4 => I::DiscardLocals(s.read()?), + 5 => I::LoadGlobal(s.read()?), + 6 => I::StoreGlobal(s.read()?), + 7 => I::Const(s.read()?), + 8 => I::Int(s.read()?), + 9 => I::True, + 10 => I::False, + 11 => I::Nil, + 12 => I::Dup, + 13 => I::Discard(s.read()?), + 14 => I::UnaryOp(UnaryOp::try_from(s.read::<u8>()?)?), + 15 => I::BinaryOp(BinaryOp::try_from(s.read::<u8>()?)?), + 16 => I::NewList(s.read()?), + 17 => I::NewTable(s.read()?), + 18 => I::NewMatrix(s.read()?, s.read()?), + 19 => I::Field(s.read()?), + 20 => I::StoreField(s.read()?), + 21 => I::Index(s.read()?), + 22 => I::StoreIndex(s.read()?), + 23 => I::Jump(s.read()?), + 24 => I::JumpTrue(s.read()?), + 25 => I::JumpFalse(s.read()?), + 26 => I::JumpNil(s.read()?), + 27 => I::IterCreate, + 28 => I::IterNext, + 29 => I::Try(s.read()?), + 30 => I::TryEnd, + 31 => I::Call(s.read()?), + 32 => I::Return, + n => return Err(error!("invalid instruction op code {n}")) + }; + Ok(ins) + } +} + +impl<T: Deserialize> Deserialize for Vec<T> { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + let len = s.read::<VarInt>()?.0; + let mut vec = Vec::with_capacity(len); + for _ in 0..len { + let v = T::deserialize(s)?; + vec.push(v); + } + Ok(vec) + } +} + +impl<T: Deserialize> Deserialize for Gc<T> { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + Ok(Gc::new(T::deserialize(s)?)) + } +} + +impl<T: Deserialize> Deserialize for Rc<T> { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + Ok(Rc::new(T::deserialize(s)?)) + } +} + +impl Deserialize for Position { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + let row = s.read::<VarInt>()?.0; + let col = s.read::<VarInt>()?.0; + Ok(Self { row, col }) + } +} + +impl Deserialize for Chunk { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + let constants = <Vec<Value>>::deserialize(s)?; + let code = <Vec<Instruction>>::deserialize(s)?; + let pos = <Vec<Position>>::deserialize(s)?; + Ok(Self { constants, code, pos }) + } +} + +impl Deserialize for Value { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + use Value as V; + let ty = s.read::<u8>()?; + let value = match ty { + 0 => V::Nil, + 1 => V::Bool(s.read()?), + 2 => V::Int(s.read()?), + 3 => V::Float(s.read()?), + 4 => V::Ratio(Rational64::new(s.read()?, s.read()?)), + 5 => V::Complex(Complex64::new(s.read()?, s.read()?)), + 6 => V::to_regex(s.read::<String>()?.as_str())?, + 7 => V::String(s.read::<String>()?.into()), + 8 => V::List(<Vec<Value>>::deserialize(s)?.into()), + 9 => { + let domain = s.read()?; + let codomain = s.read()?; + let values = <Vec<Value>>::deserialize(s)?; + V::Matrix(Matrix::new(domain, codomain, values).into()) + }, + 10 => { + let len = s.read::<VarInt>()?.0; + let mut table = ValueMap::new(); + for _ in 0..len { + let key = <Value>::deserialize(s)?; + let value = <Value>::deserialize(s)?; + table.insert(key, value)?; + } + V::Table(table.into()) + }, + 11 => V::Function(<Rc<Function>>::deserialize(s)?), + 12 => V::Range((s.read()?, s.read()?, s.read()?).into()), + 13 => V::Iter(<Rc<Function>>::deserialize(s)?), + n => return Err(error!("invalid value code {n}")) + }; + Ok(value) + } +} + +impl Deserialize for Function { + fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self> { + let name = s.read::<String>()?; + let arity = s.read()?; + let variadic = s.read()?; + let chunk = <Chunk>::deserialize(s)?; + Ok(Function { + name: Rc::from(name.as_str()), + arity, + variadic, + fun: InnerFunction::Compiled(chunk.into()) + }) + } +} |