add tests for case and constr

Fix a minor issue with decoding order
This commit is contained in:
microproofs 2023-09-02 21:25:34 -04:00 committed by Kasey
parent c9b01ab365
commit 819a0a20e6
8 changed files with 67 additions and 22 deletions

View File

@ -182,6 +182,21 @@ impl<'b> Decoder<'b> {
Ok(vec_array) Ok(vec_array)
} }
pub fn decode_list_with_debug<T, F>(
&mut self,
decoder_func: F,
state_log: &mut Vec<String>,
) -> Result<Vec<T>, Error>
where
F: Copy + FnOnce(&mut Decoder, &mut Vec<String>) -> Result<T, Error>,
{
let mut vec_array: Vec<T> = Vec::new();
while self.bit()? {
vec_array.push(decoder_func(self, state_log)?)
}
Ok(vec_array)
}
/// Decode the next bit in the buffer. /// Decode the next bit in the buffer.
/// If the bit was 0 then return true. /// If the bit was 0 then return true.
/// Otherwise return false. /// Otherwise return false.

View File

@ -207,22 +207,17 @@ where
6 => Ok(Term::Error), 6 => Ok(Term::Error),
7 => Ok(Term::Builtin(DefaultFunction::decode(d)?)), 7 => Ok(Term::Builtin(DefaultFunction::decode(d)?)),
8 => { 8 => {
let tag = usize::decode(d)?;
let fields = d.decode_list_with(|d| Term::<T>::decode(d))?; let fields = d.decode_list_with(|d| Term::<T>::decode(d))?;
Ok(Term::Constr { Ok(Term::Constr { tag, fields })
tag: usize::decode(d)?,
fields,
})
} }
9 => { 9 => {
let constr = Term::<T>::decode(d)?; let constr = (Term::<T>::decode(d)?).into();
let branches = d.decode_list_with(|d| Term::<T>::decode(d))?; let branches = d.decode_list_with(|d| Term::<T>::decode(d))?;
Ok(Term::Case { Ok(Term::Case { constr, branches })
constr: Rc::new(constr),
branches,
})
} }
x => { x => {
let buffer_slice: Vec<u8> = d let buffer_slice: Vec<u8> = d
@ -386,6 +381,29 @@ where
} }
} }
} }
8 => {
state_log.push("(constr ".to_string());
let tag = usize::decode(d)?;
let fields = d.decode_list_with_debug(
|d, state_log| Term::<T>::decode_debug(d, state_log),
state_log,
)?;
Ok(Term::Constr { tag, fields })
}
9 => {
state_log.push("(case ".to_string());
let constr = Term::<T>::decode_debug(d, state_log)?.into();
let branches = d.decode_list_with_debug(
|d, state_log| Term::<T>::decode_debug(d, state_log),
state_log,
)?;
Ok(Term::Case { constr, branches })
}
x => { x => {
state_log.push("parse error".to_string()); state_log.push("parse error".to_string());

View File

@ -505,7 +505,7 @@ mod tests {
]; ];
for (fun, tag, n, m, result) in test_data { for (fun, tag, n, m, result) in test_data {
let eval_result = make_program(fun, tag, n, m).eval(ExBudget::default()); let eval_result = make_program(fun, tag, n, m).eval(ExBudget::max());
assert_eq!( assert_eq!(
eval_result.result().unwrap(), eval_result.result().unwrap(),
@ -535,7 +535,7 @@ mod tests {
let test_data = vec![(0, 5), (1, 10), (2, 15)]; let test_data = vec![(0, 5), (1, 10), (2, 15)];
for (tag, result) in test_data { for (tag, result) in test_data {
let eval_result = make_program(tag).eval(ExBudget::default()); let eval_result = make_program(tag).eval(ExBudget::max());
assert_eq!( assert_eq!(
eval_result.result().unwrap(), eval_result.result().unwrap(),

View File

@ -39,7 +39,7 @@ impl ExBudget {
pub fn max() -> Self { pub fn max() -> Self {
ExBudget { ExBudget {
mem: 14000000000, mem: 14000000000000,
cpu: 10000000000000, cpu: 10000000000000,
} }
} }
@ -147,12 +147,12 @@ impl MachineCosts {
}, },
// Placeholder values // Placeholder values
constr: ExBudget { constr: ExBudget {
mem: 100, mem: 30000000000,
cpu: 23000, cpu: 30000000000,
}, },
case: ExBudget { case: ExBudget {
mem: 100, mem: 30000000000,
cpu: 23000, cpu: 30000000000,
}, },
} }
} }
@ -193,12 +193,12 @@ impl Default for MachineCosts {
}, },
// Placeholder values // Placeholder values
constr: ExBudget { constr: ExBudget {
mem: 100, mem: 30000000000,
cpu: 23000, cpu: 30000000000,
}, },
case: ExBudget { case: ExBudget {
mem: 100, mem: 30000000000,
cpu: 23000, cpu: 30000000000,
}, },
} }
} }

View File

@ -145,13 +145,13 @@ peg::parser! {
= "(" _* "error" _* ")" { Term::Error } = "(" _* "error" _* ")" { Term::Error }
rule constr() -> Term<Name> rule constr() -> Term<Name>
= "(" _* "constr" _+ tag:decimal() _+ fields:(t:term() _* { t })+ ")" { = "(" _* "constr" _+ tag:decimal() _* fields:(t:term() _* { t })* _* ")" {
Term::Constr { tag, fields } Term::Constr { tag, fields }
} }
#[cache_left_rec] #[cache_left_rec]
rule case() -> Term<Name> rule case() -> Term<Name>
= "(" _* "case" _+ constr:term() _* branches:(t:term() _* { t })+ ")" { = "(" _* "case" _+ constr:term() _* branches:(t:term() _* { t })+ _* ")" {
Term::Case { constr: constr.into(), branches } Term::Case { constr: constr.into(), branches }
} }

Binary file not shown.

View File

@ -0,0 +1,4 @@
(program
1.0.0
(case (constr 0)(constr 0(con integer 0))(constr 1(con integer 1)))
)

View File

@ -74,6 +74,14 @@ fn fibonacci() {
round_trip_test(bytes, code); round_trip_test(bytes, code);
} }
#[test]
fn case_constr() {
let bytes = include_bytes!("../test_data/case_constr/case_constr.flat");
let code = include_str!("../test_data/case_constr/case_constr.uplc");
round_trip_test(bytes, code);
}
#[test] #[test]
fn one_way_fibonacci() { fn one_way_fibonacci() {
let bytes = include_bytes!("../test_data/fibonacci/fibonacci.flat"); let bytes = include_bytes!("../test_data/fibonacci/fibonacci.flat");