summaryrefslogtreecommitdiff
path: root/matrix-lang/src/binary/deserialize.rs
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-02-29 17:04:28 -0500
committerFreya Murphy <freya@freyacat.org>2024-02-29 17:04:28 -0500
commit5d2747e26f51cc2344a6bd95f93457248fdfebd8 (patch)
tree8755b4068166c3854d26817683ce438a771ab319 /matrix-lang/src/binary/deserialize.rs
parentmore mat, sys, and os stdlib functions, better matrix printing, other fixes (diff)
downloadmatrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.tar.gz
matrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.tar.bz2
matrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.zip
fin prob
Diffstat (limited to 'matrix-lang/src/binary/deserialize.rs')
-rw-r--r--matrix-lang/src/binary/deserialize.rs160
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())
+ })
+ }
+}