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.
|
/// 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.
|
/// Then decode the next bit in the buffer and repeat above.
|
||||||
/// Returns a list of items decoded with the decoder function.
|
/// 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
|
where
|
||||||
F: Copy + FnOnce(&mut Decoder) -> Result<T, Error>,
|
F: Copy + FnOnce(&mut Decoder) -> Result<T, Error>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -196,10 +196,7 @@ impl Encoder {
|
||||||
&mut self,
|
&mut self,
|
||||||
list: &[T],
|
list: &[T],
|
||||||
encoder_func: for<'r> fn(&T, &'r mut Encoder) -> Result<(), Error>,
|
encoder_func: for<'r> fn(&T, &'r mut Encoder) -> Result<(), Error>,
|
||||||
) -> Result<&mut Self, Error>
|
) -> Result<&mut Self, Error> {
|
||||||
where
|
|
||||||
T: Encode,
|
|
||||||
{
|
|
||||||
for item in list {
|
for item in list {
|
||||||
self.one();
|
self.one();
|
||||||
encoder_func(item, self)?;
|
encoder_func(item, self)?;
|
||||||
|
|
|
@ -196,6 +196,14 @@ pub enum Term<T> {
|
||||||
Error,
|
Error,
|
||||||
// tag: 7
|
// tag: 7
|
||||||
Builtin(DefaultFunction),
|
Builtin(DefaultFunction),
|
||||||
|
Constr {
|
||||||
|
tag: usize,
|
||||||
|
fields: Vec<Term<T>>,
|
||||||
|
},
|
||||||
|
Case {
|
||||||
|
constr: Rc<Term<T>>,
|
||||||
|
branches: Vec<Term<T>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> 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::Force(term) => Term::Force(Rc::new(self.name_to_named_debruijn(term)?)),
|
||||||
Term::Error => Term::Error,
|
Term::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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)
|
Ok(converted_term)
|
||||||
|
@ -117,6 +131,20 @@ impl Converter {
|
||||||
Term::Force(term) => Term::Force(Rc::new(self.name_to_debruijn(term)?)),
|
Term::Force(term) => Term::Force(Rc::new(self.name_to_debruijn(term)?)),
|
||||||
Term::Error => Term::Error,
|
Term::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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)
|
Ok(converted_term)
|
||||||
|
@ -167,6 +195,20 @@ impl Converter {
|
||||||
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_name(term)?)),
|
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_name(term)?)),
|
||||||
Term::Error => Term::Error,
|
Term::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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)
|
Ok(converted_term)
|
||||||
|
@ -218,6 +260,20 @@ impl Converter {
|
||||||
Term::Force(term) => Term::Force(Rc::new(self.debruijn_to_name(term)?)),
|
Term::Force(term) => Term::Force(Rc::new(self.debruijn_to_name(term)?)),
|
||||||
Term::Error => Term::Error,
|
Term::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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)
|
Ok(converted_term)
|
||||||
|
@ -243,6 +299,20 @@ impl Converter {
|
||||||
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_debruijn(term))),
|
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_debruijn(term))),
|
||||||
Term::Error => Term::Error,
|
Term::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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::Force(term) => Term::Force(Rc::new(self.debruijn_to_named_debruijn(term))),
|
||||||
Term::Error => Term::Error,
|
Term::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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::Error => Term::Error,
|
||||||
Term::Builtin(builtin) => Term::Builtin(*builtin),
|
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)?;
|
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(())
|
Ok(())
|
||||||
|
@ -192,6 +206,24 @@ where
|
||||||
5 => Ok(Term::Force(Rc::new(Term::decode(d)?))),
|
5 => Ok(Term::Force(Rc::new(Term::decode(d)?))),
|
||||||
6 => Ok(Term::Error),
|
6 => Ok(Term::Error),
|
||||||
7 => Ok(Term::Builtin(DefaultFunction::decode(d)?)),
|
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 => {
|
x => {
|
||||||
let buffer_slice: Vec<u8> = d
|
let buffer_slice: Vec<u8> = d
|
||||||
.buffer
|
.buffer
|
||||||
|
|
|
@ -147,6 +147,8 @@ impl Machine {
|
||||||
Value::Builtin { fun, runtime },
|
Value::Builtin { fun, runtime },
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
Term::Constr { .. } => todo!(),
|
||||||
|
Term::Case { .. } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,8 @@ peg::parser! {
|
||||||
rule comma() = _* "," _*
|
rule comma() = _* "," _*
|
||||||
|
|
||||||
rule version() -> (usize, usize, usize)
|
rule version() -> (usize, usize, usize)
|
||||||
= major:number() "." minor:number() "." patch:number() {
|
= major:decimal() "." minor:decimal() "." patch:decimal() {
|
||||||
(major as usize, minor as usize, patch as usize)
|
(major, minor, patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub rule term() -> Term<Name>
|
pub rule term() -> Term<Name>
|
||||||
|
@ -94,6 +94,8 @@ peg::parser! {
|
||||||
/ delay()
|
/ delay()
|
||||||
/ force()
|
/ force()
|
||||||
/ error()
|
/ error()
|
||||||
|
/ constr()
|
||||||
|
/ case()
|
||||||
|
|
||||||
rule constant() -> Term<Name>
|
rule constant() -> Term<Name>
|
||||||
= "(" _* "con" _+ con:(
|
= "(" _* "con" _+ con:(
|
||||||
|
@ -142,6 +144,17 @@ peg::parser! {
|
||||||
rule error() -> Term<Name>
|
rule error() -> Term<Name>
|
||||||
= "(" _* "error" _* ")" { Term::Error }
|
= "(" _* "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
|
rule constant_integer() -> Constant
|
||||||
= "integer" _+ i:big_number() { Constant::Integer(i) }
|
= "integer" _+ i:big_number() { Constant::Integer(i) }
|
||||||
|
|
||||||
|
@ -173,6 +186,9 @@ peg::parser! {
|
||||||
rule pair(type_info: Option<(&Type, &Type)>) -> (Constant, Constant)
|
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) }
|
= "(" _* 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
|
rule number() -> isize
|
||||||
= n:$("-"* ['0'..='9']+) {? n.parse().or(Err("isize")) }
|
= n:$("-"* ['0'..='9']+) {? n.parse().or(Err("isize")) }
|
||||||
|
|
||||||
|
@ -199,7 +215,7 @@ peg::parser! {
|
||||||
/ expected!("or any valid ascii character")
|
/ expected!("or any valid ascii character")
|
||||||
|
|
||||||
rule data() -> PlutusData
|
rule data() -> PlutusData
|
||||||
= _* "Constr" _+ t:number() _+ fs:plutus_list() {?
|
= _* "Constr" _+ t:decimal() _+ fs:plutus_list() {?
|
||||||
Ok(PlutusData::Constr(pallas_primitives::babbage::Constr {
|
Ok(PlutusData::Constr(pallas_primitives::babbage::Constr {
|
||||||
tag: u64::try_from(t).or(Err("tag"))?,
|
tag: u64::try_from(t).or(Err("tag"))?,
|
||||||
any_constructor: None,
|
any_constructor: None,
|
||||||
|
|
|
@ -48,6 +48,18 @@ impl Interner {
|
||||||
Term::Force(term) => self.term(Rc::make_mut(term)),
|
Term::Force(term) => self.term(Rc::make_mut(term)),
|
||||||
Term::Error => (),
|
Term::Error => (),
|
||||||
Term::Builtin(_) => (),
|
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::line_())
|
||||||
.append(RcDoc::text(")")),
|
.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()
|
.group()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue