feat(uplc): add Case and Const terms
- parsering - interning - flat encoding and decoding - pretty printing - debruijn conversion Co-authored-by: Lucas Rosa <x@rvcas.dev>
This commit is contained in:
parent
dfe433ea46
commit
e566c4e1de
|
@ -171,7 +171,7 @@ impl<'b> Decoder<'b> {
|
|||
/// Otherwise we decode an item in the list with the decoder function passed in.
|
||||
/// Then decode the next bit in the buffer and repeat above.
|
||||
/// Returns a list of items decoded with the decoder function.
|
||||
pub fn decode_list_with<T: Decode<'b>, F>(&mut self, decoder_func: F) -> Result<Vec<T>, Error>
|
||||
pub fn decode_list_with<T, F>(&mut self, decoder_func: F) -> Result<Vec<T>, Error>
|
||||
where
|
||||
F: Copy + FnOnce(&mut Decoder) -> Result<T, Error>,
|
||||
{
|
||||
|
|
|
@ -196,10 +196,7 @@ impl Encoder {
|
|||
&mut self,
|
||||
list: &[T],
|
||||
encoder_func: for<'r> fn(&T, &'r mut Encoder) -> Result<(), Error>,
|
||||
) -> Result<&mut Self, Error>
|
||||
where
|
||||
T: Encode,
|
||||
{
|
||||
) -> Result<&mut Self, Error> {
|
||||
for item in list {
|
||||
self.one();
|
||||
encoder_func(item, self)?;
|
||||
|
|
|
@ -196,6 +196,14 @@ pub enum Term<T> {
|
|||
Error,
|
||||
// tag: 7
|
||||
Builtin(DefaultFunction),
|
||||
Constr {
|
||||
tag: usize,
|
||||
fields: Vec<Term<T>>,
|
||||
},
|
||||
Case {
|
||||
constr: Rc<Term<T>>,
|
||||
branches: Vec<Term<T>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<T> Term<T> {
|
||||
|
|
|
@ -79,6 +79,20 @@ impl Converter {
|
|||
Term::Force(term) => Term::Force(Rc::new(self.name_to_named_debruijn(term)?)),
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.name_to_named_debruijn(field))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.name_to_named_debruijn(constr)?),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.name_to_named_debruijn(branch))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
};
|
||||
|
||||
Ok(converted_term)
|
||||
|
@ -117,6 +131,20 @@ impl Converter {
|
|||
Term::Force(term) => Term::Force(Rc::new(self.name_to_debruijn(term)?)),
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.name_to_debruijn(field))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.name_to_debruijn(constr)?),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.name_to_debruijn(branch))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
};
|
||||
|
||||
Ok(converted_term)
|
||||
|
@ -167,6 +195,20 @@ impl Converter {
|
|||
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_name(term)?)),
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.named_debruijn_to_name(field))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.named_debruijn_to_name(constr)?),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.named_debruijn_to_name(branch))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
};
|
||||
|
||||
Ok(converted_term)
|
||||
|
@ -218,6 +260,20 @@ impl Converter {
|
|||
Term::Force(term) => Term::Force(Rc::new(self.debruijn_to_name(term)?)),
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.debruijn_to_name(field))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.debruijn_to_name(constr)?),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.debruijn_to_name(branch))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
};
|
||||
|
||||
Ok(converted_term)
|
||||
|
@ -243,6 +299,20 @@ impl Converter {
|
|||
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_debruijn(term))),
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.named_debruijn_to_debruijn(field))
|
||||
.collect(),
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.named_debruijn_to_debruijn(constr)),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.named_debruijn_to_debruijn(branch))
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,6 +342,20 @@ impl Converter {
|
|||
Term::Force(term) => Term::Force(Rc::new(self.debruijn_to_named_debruijn(term))),
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.debruijn_to_named_debruijn(field))
|
||||
.collect(),
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.debruijn_to_named_debruijn(constr)),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.debruijn_to_named_debruijn(branch))
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,6 +386,20 @@ impl Converter {
|
|||
}
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.fake_named_debruijn_to_named_debruijn(field))
|
||||
.collect(),
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.fake_named_debruijn_to_named_debruijn(constr)),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.fake_named_debruijn_to_named_debruijn(branch))
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,6 +430,20 @@ impl Converter {
|
|||
}
|
||||
Term::Error => Term::Error,
|
||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
||||
Term::Constr { tag, fields } => Term::Constr {
|
||||
tag: *tag,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.named_debruijn_to_fake_named_debruijn(field))
|
||||
.collect(),
|
||||
},
|
||||
Term::Case { constr, branches } => Term::Case {
|
||||
constr: Rc::new(self.named_debruijn_to_fake_named_debruijn(constr)),
|
||||
branches: branches
|
||||
.iter()
|
||||
.map(|branch| self.named_debruijn_to_fake_named_debruijn(branch))
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -165,6 +165,20 @@ where
|
|||
|
||||
builtin.encode(e)?;
|
||||
}
|
||||
Term::Constr { tag, fields } => {
|
||||
encode_term_tag(8, e)?;
|
||||
|
||||
tag.encode(e)?;
|
||||
|
||||
e.encode_list_with(fields, |term, e| (*term).encode(e))?;
|
||||
}
|
||||
Term::Case { constr, branches } => {
|
||||
encode_term_tag(9, e)?;
|
||||
|
||||
constr.encode(e)?;
|
||||
|
||||
e.encode_list_with(branches, |term, e| (*term).encode(e))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -192,6 +206,24 @@ where
|
|||
5 => Ok(Term::Force(Rc::new(Term::decode(d)?))),
|
||||
6 => Ok(Term::Error),
|
||||
7 => Ok(Term::Builtin(DefaultFunction::decode(d)?)),
|
||||
8 => {
|
||||
let fields = d.decode_list_with(|d| Term::<T>::decode(d))?;
|
||||
|
||||
Ok(Term::Constr {
|
||||
tag: usize::decode(d)?,
|
||||
fields,
|
||||
})
|
||||
}
|
||||
9 => {
|
||||
let constr = Term::<T>::decode(d)?;
|
||||
|
||||
let branches = d.decode_list_with(|d| Term::<T>::decode(d))?;
|
||||
|
||||
Ok(Term::Case {
|
||||
constr: Rc::new(constr),
|
||||
branches,
|
||||
})
|
||||
}
|
||||
x => {
|
||||
let buffer_slice: Vec<u8> = d
|
||||
.buffer
|
||||
|
|
|
@ -147,6 +147,8 @@ impl Machine {
|
|||
Value::Builtin { fun, runtime },
|
||||
))
|
||||
}
|
||||
Term::Constr { .. } => todo!(),
|
||||
Term::Case { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,8 +81,8 @@ peg::parser! {
|
|||
rule comma() = _* "," _*
|
||||
|
||||
rule version() -> (usize, usize, usize)
|
||||
= major:number() "." minor:number() "." patch:number() {
|
||||
(major as usize, minor as usize, patch as usize)
|
||||
= major:decimal() "." minor:decimal() "." patch:decimal() {
|
||||
(major, minor, patch)
|
||||
}
|
||||
|
||||
pub rule term() -> Term<Name>
|
||||
|
@ -94,6 +94,8 @@ peg::parser! {
|
|||
/ delay()
|
||||
/ force()
|
||||
/ error()
|
||||
/ constr()
|
||||
/ case()
|
||||
|
||||
rule constant() -> Term<Name>
|
||||
= "(" _* "con" _+ con:(
|
||||
|
@ -142,6 +144,17 @@ peg::parser! {
|
|||
rule error() -> Term<Name>
|
||||
= "(" _* "error" _* ")" { Term::Error }
|
||||
|
||||
rule constr() -> Term<Name>
|
||||
= "(" _* "constr" _+ tag:decimal() _+ fields:(t:term() _* { t })+ ")" {
|
||||
Term::Constr { tag, fields }
|
||||
}
|
||||
|
||||
#[cache_left_rec]
|
||||
rule case() -> Term<Name>
|
||||
= "(" _* "case" _+ constr:term() _* branches:(t:term() _* { t })+ ")" {
|
||||
Term::Case { constr: constr.into(), branches }
|
||||
}
|
||||
|
||||
rule constant_integer() -> Constant
|
||||
= "integer" _+ i:big_number() { Constant::Integer(i) }
|
||||
|
||||
|
@ -173,6 +186,9 @@ peg::parser! {
|
|||
rule pair(type_info: Option<(&Type, &Type)>) -> (Constant, Constant)
|
||||
= "(" _* x:typed_constant(type_info.map(|t| t.0)) comma() y:typed_constant(type_info.map(|t| t.1)) _* ")" { (x, y) }
|
||||
|
||||
rule decimal() -> usize
|
||||
= n:$(['0'..='9']+) {? n.parse().or(Err("usize")) }
|
||||
|
||||
rule number() -> isize
|
||||
= n:$("-"* ['0'..='9']+) {? n.parse().or(Err("isize")) }
|
||||
|
||||
|
@ -199,7 +215,7 @@ peg::parser! {
|
|||
/ expected!("or any valid ascii character")
|
||||
|
||||
rule data() -> PlutusData
|
||||
= _* "Constr" _+ t:number() _+ fs:plutus_list() {?
|
||||
= _* "Constr" _+ t:decimal() _+ fs:plutus_list() {?
|
||||
Ok(PlutusData::Constr(pallas_primitives::babbage::Constr {
|
||||
tag: u64::try_from(t).or(Err("tag"))?,
|
||||
any_constructor: None,
|
||||
|
|
|
@ -48,6 +48,18 @@ impl Interner {
|
|||
Term::Force(term) => self.term(Rc::make_mut(term)),
|
||||
Term::Error => (),
|
||||
Term::Builtin(_) => (),
|
||||
Term::Constr { fields, .. } => {
|
||||
for field in fields {
|
||||
self.term(field);
|
||||
}
|
||||
}
|
||||
Term::Case { constr, branches } => {
|
||||
self.term(Rc::make_mut(constr));
|
||||
|
||||
for branch in branches {
|
||||
self.term(branch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,32 @@ where
|
|||
)
|
||||
.append(RcDoc::line_())
|
||||
.append(RcDoc::text(")")),
|
||||
Term::Constr { tag, fields } => RcDoc::text("(")
|
||||
.append(
|
||||
RcDoc::text("constr")
|
||||
.append(RcDoc::line())
|
||||
.append(RcDoc::as_string(tag))
|
||||
.nest(2),
|
||||
)
|
||||
.append(RcDoc::line_())
|
||||
.append(RcDoc::intersperse(
|
||||
fields.iter().map(|f| f.to_doc()),
|
||||
RcDoc::line_(),
|
||||
))
|
||||
.append(RcDoc::text(")")),
|
||||
Term::Case { constr, branches } => RcDoc::text("(")
|
||||
.append(
|
||||
RcDoc::text("case")
|
||||
.append(RcDoc::line())
|
||||
.append(constr.to_doc())
|
||||
.nest(2),
|
||||
)
|
||||
.append(RcDoc::line_())
|
||||
.append(RcDoc::intersperse(
|
||||
branches.iter().map(|f| f.to_doc()),
|
||||
RcDoc::line_(),
|
||||
))
|
||||
.append(RcDoc::text(")")),
|
||||
}
|
||||
.group()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue