From 83d6b5243ee42018b8577972436f2e54602a4bf7 Mon Sep 17 00:00:00 2001 From: rvcas Date: Thu, 2 Jun 2022 21:39:09 -0400 Subject: [PATCH] feat: get program ready for debruijn --- crates/uplc/src/ast.rs | 29 +++++++++++++++++++---------- crates/uplc/src/flat.rs | 31 +++++++++++++++++++++---------- crates/uplc/src/parser.rs | 22 +++++++++++----------- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index 6e90a927..db9b0c89 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -1,31 +1,31 @@ use crate::builtins::DefaultFunction; #[derive(Debug, Clone, PartialEq)] -pub struct Program { +pub struct Program { pub version: (usize, usize, usize), - pub term: Term, + pub term: Term, } #[derive(Debug, Clone, PartialEq)] -pub enum Term { +pub enum Term { // tag: 0 - Var(Name), + Var(T), // tag: 1 - Delay(Box), + Delay(Box>), // tag: 2 Lambda { - parameter_name: Name, - body: Box, + parameter_name: T, + body: Box>, }, // tag: 3 Apply { - function: Box, - argument: Box, + function: Box>, + argument: Box>, }, // tag: 4 Constant(Constant), // tag: 5 - Force(Box), + Force(Box>), // tag: 6 Error, // tag: 7 @@ -53,3 +53,12 @@ pub struct Name { pub text: String, pub unique: isize, } + +#[derive(Debug, Clone, PartialEq)] +pub struct NamedDeBruijn { + pub text: String, + pub index: isize, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct DeBruijn(isize); diff --git a/crates/uplc/src/flat.rs b/crates/uplc/src/flat.rs index c76e818c..c3ce2780 100644 --- a/crates/uplc/src/flat.rs +++ b/crates/uplc/src/flat.rs @@ -15,9 +15,12 @@ const BUILTIN_TAG_WIDTH: u32 = 7; const CONST_TAG_WIDTH: u32 = 4; const TERM_TAG_WIDTH: u32 = 4; -impl<'b> Flat<'b> for Program {} +impl<'b, T> Flat<'b> for Program where T: Encode + Decode<'b> {} -impl Program { +impl<'b, T> Program +where + T: Encode + Decode<'b>, +{ // convenient so that people don't need to depend on the flat crate // directly to call programs flat function pub fn to_flat(&self) -> anyhow::Result> { @@ -33,7 +36,7 @@ impl Program { } } -impl Encode for Program { +impl Encode for Program { fn encode(&self, e: &mut Encoder) -> Result<(), String> { let (major, minor, patch) = self.version; @@ -47,7 +50,10 @@ impl Encode for Program { } } -impl<'b> Decode<'b> for Program { +impl<'b, T> Decode<'b> for Program +where + T: Decode<'b>, +{ fn decode(d: &mut Decoder) -> Result { let version = (usize::decode(d)?, usize::decode(d)?, usize::decode(d)?); let term = Term::decode(d)?; @@ -55,7 +61,7 @@ impl<'b> Decode<'b> for Program { } } -impl Encode for Term { +impl Encode for Term { fn encode(&self, e: &mut Encoder) -> Result<(), String> { match self { Term::Var(name) => { @@ -104,13 +110,16 @@ impl Encode for Term { } } -impl<'b> Decode<'b> for Term { +impl<'b, T> Decode<'b> for Term +where + T: Decode<'b>, +{ fn decode(d: &mut Decoder) -> Result { match decode_term_tag(d)? { - 0 => Ok(Term::Var(Name::decode(d)?)), + 0 => Ok(Term::Var(T::decode(d)?)), 1 => Ok(Term::Delay(Box::new(Term::decode(d)?))), 2 => Ok(Term::Lambda { - parameter_name: Name::decode(d)?, + parameter_name: T::decode(d)?, body: Box::new(Term::decode(d)?), }), 3 => Ok(Term::Apply { @@ -255,11 +264,13 @@ pub fn decode_constant_tag(d: &mut Decoder) -> Result { mod test { use flat::Flat; + use crate::ast::Name; + use super::{Constant, Program, Term}; #[test] fn flat_encode_integer() { - let program = Program { + let program = Program:: { version: (11, 22, 33), term: Term::Constant(Constant::Integer(11)), }; @@ -283,7 +294,7 @@ mod test { term: Term::Constant(Constant::Integer(11)), }; - let actual_program: Program = Program::unflat(&flat_encoded).unwrap(); + let actual_program: Program = Program::unflat(&flat_encoded).unwrap(); assert_eq!(actual_program, expected_program) } diff --git a/crates/uplc/src/parser.rs b/crates/uplc/src/parser.rs index 8c3b07b7..28468b57 100644 --- a/crates/uplc/src/parser.rs +++ b/crates/uplc/src/parser.rs @@ -43,7 +43,7 @@ impl ParserState { } } -pub fn program(src: &str) -> anyhow::Result { +pub fn program(src: &str) -> anyhow::Result> { let mut parser = program_(); let result = parser.parse(state::Stream { @@ -57,7 +57,7 @@ pub fn program(src: &str) -> anyhow::Result { } } -fn program_() -> impl Parser, Output = Program> +fn program_() -> impl Parser, Output = Program> where Input: Stream, Input::Error: ParseError, @@ -93,7 +93,7 @@ where ) } -fn term() -> impl Parser, Output = Term> +fn term() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError, @@ -109,7 +109,7 @@ where )))) } -fn delay() -> impl Parser, Output = Term> +fn delay() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError, @@ -124,7 +124,7 @@ where ) } -fn force() -> impl Parser, Output = Term> +fn force() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError, @@ -139,7 +139,7 @@ where ) } -fn lambda() -> impl Parser, Output = Term> +fn lambda() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError, @@ -151,7 +151,7 @@ where .with(skip_many1(space())) .with((many1(alpha_num()), skip_many1(space()), term())) .map_input( - |(parameter_name, _, term): (String, _, Term), input| Term::Lambda { + |(parameter_name, _, term): (String, _, Term), input| Term::Lambda { parameter_name: Name { unique: input.state.intern(¶meter_name), text: parameter_name, @@ -162,7 +162,7 @@ where ) } -fn apply() -> impl Parser, Output = Term> +fn apply() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError, @@ -177,7 +177,7 @@ where ) } -fn builtin() -> impl Parser, Output = Term> +fn builtin() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError, @@ -194,7 +194,7 @@ where ) } -fn error() -> impl Parser, Output = Term> +fn error() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError, @@ -208,7 +208,7 @@ where ) } -fn constant() -> impl Parser, Output = Term> +fn constant() -> impl Parser, Output = Term> where Input: Stream, Input::Error: ParseError,