feat: start on encoding constants with Flat Encoder

This commit is contained in:
Kasey White 2022-05-22 20:29:59 -04:00
parent fdfaf91bcf
commit 52f9f5ab41
2 changed files with 112 additions and 23 deletions

View File

@ -43,10 +43,12 @@ impl Encoder {
/// Encode a `bool` value. /// Encode a `bool` value.
pub fn bool(&mut self, x: bool) -> &mut Self { pub fn bool(&mut self, x: bool) -> &mut Self {
if x { if x {
self.one() self.one();
} else { } else {
self.zero() self.zero();
} }
self
} }
pub fn bytes(&mut self, arr: &[u8]) -> Result<&mut Self, String> { pub fn bytes(&mut self, arr: &[u8]) -> Result<&mut Self, String> {
@ -73,17 +75,15 @@ impl Encoder {
Ok(self) Ok(self)
} }
fn zero(&mut self) -> &mut Self { fn zero(&mut self) {
if self.used_bits == 7 { if self.used_bits == 7 {
self.next_word(); self.next_word();
} else { } else {
self.used_bits += 1; self.used_bits += 1;
} }
self
} }
fn one(&mut self) -> &mut Self { fn one(&mut self) {
if self.used_bits == 7 { if self.used_bits == 7 {
self.current_byte |= 1; self.current_byte |= 1;
self.next_word(); self.next_word();
@ -91,8 +91,6 @@ impl Encoder {
self.current_byte |= 128 >> self.used_bits; self.current_byte |= 128 >> self.used_bits;
self.used_bits += 1; self.used_bits += 1;
} }
self
} }
fn byte_unaligned(&mut self, x: u8) { fn byte_unaligned(&mut self, x: u8) {
@ -139,7 +137,36 @@ impl Encoder {
} }
} }
fn bits(&mut self, num_bits: i64, val: u8) { pub fn encode_list_with<T: Encode>(&mut self, list: Vec<T>) -> Result<(), String> {
for item in list {
self.one();
self.encode(item)?;
}
self.zero();
Ok(())
}
pub fn bits(&mut self, num_bits: i64, val: u8) {
match (num_bits, val) {
(1, 0) => self.zero(),
(1, 1) => self.one(),
(2, 0) => {
self.zero();
self.zero();
}
(2, 1) => {
self.zero();
self.one();
}
(2, 2) => {
self.one();
self.zero();
}
(2, 3) => {
self.one();
self.one();
}
(_, _) => {
self.used_bits += num_bits; self.used_bits += num_bits;
let unused_bits = 8 - self.used_bits; let unused_bits = 8 - self.used_bits;
match unused_bits { match unused_bits {
@ -159,6 +186,8 @@ impl Encoder {
} }
} }
} }
}
}
pub(crate) fn filler(&mut self) { pub(crate) fn filler(&mut self) {
self.current_byte |= 1; self.current_byte |= 1;

View File

@ -1,5 +1,9 @@
use flat::en::{Encode, Encoder};
use crate::builtins::DefaultFunction; use crate::builtins::DefaultFunction;
const TERM_TAG_WIDTH: u32 = 4;
#[derive(Debug)] #[derive(Debug)]
pub struct Program { pub struct Program {
pub version: String, pub version: String,
@ -32,6 +36,22 @@ pub enum Term {
Builtin(DefaultFunction), Builtin(DefaultFunction),
} }
pub fn encode_term_tag(tag: u8, e: &mut Encoder) -> Result<(), String> {
safe_encode_bits(TERM_TAG_WIDTH, tag, e)
}
pub fn safe_encode_bits(num_bits: u32, byte: u8, e: &mut Encoder) -> Result<(), String> {
if 2_u8.pow(num_bits) < byte {
Err(format!(
"Overflow detected, cannot fit {} in {} bits.",
byte, num_bits
))
} else {
e.bits(num_bits as i64, byte);
Ok(())
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Constant { pub enum Constant {
// TODO: figure out the right size for this // TODO: figure out the right size for this
@ -48,3 +68,43 @@ pub enum Constant {
// tag: 5 // tag: 5
Bool(bool), Bool(bool),
} }
impl Encode for Program {
fn encode(&self, e: &mut Encoder) -> Result<(), String> {
self.version.encode(e)?;
self.term.encode(e)?;
Ok(())
}
}
impl Encode for Term {
fn encode(&self, e: &mut Encoder) -> Result<(), String> {
match self {
Term::Constant(constant) => {
encode_term_tag(4, e)?;
constant.encode(e)?;
}
rest => {
todo!("Implement: {:?}", rest)
}
}
Ok(())
}
}
impl Encode for &Constant {
fn encode(&self, e: &mut Encoder) -> Result<(), String> {
match self {
Constant::Integer(_) => todo!(),
Constant::ByteString(bytes) => bytes.encode(e)?,
Constant::String(s) => s.encode(e)?,
Constant::Char(c) => c.encode(e)?,
Constant::Unit => todo!(),
Constant::Bool(b) => b.encode(e)?,
}
Ok(())
}
}