eval with inputs (#56)

This commit is contained in:
Lucas 2022-09-08 18:20:52 -04:00 committed by GitHub
parent 739f38beac
commit 6d6f671f4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 10 deletions

View File

@ -1,5 +1,4 @@
(program (program
1.0.0 1.0.0
[(force (force (builtin fstPair))) (con (pair integer bytestring) (22, #1122aabb))] (lam y (lam x [ [ (builtin addInteger) x ] y ]))
) )

View File

@ -39,9 +39,11 @@ pub enum UplcCommand {
}, },
/// Evaluate an Untyped Plutus Core program /// Evaluate an Untyped Plutus Core program
Eval { Eval {
input: PathBuf, script: PathBuf,
#[clap(short, long)] #[clap(short, long)]
flat: bool, flat: bool,
/// Arguments to pass to the uplc program
args: Vec<String>,
}, },
} }

View File

@ -82,21 +82,28 @@ fn main() -> anyhow::Result<()> {
fs::write(&out_name, pretty)?; fs::write(&out_name, pretty)?;
} }
} }
UplcCommand::Eval { input, flat } => {
let program = if flat { UplcCommand::Eval { script, flat, args } => {
let bytes = std::fs::read(&input)?; let mut program = if flat {
let bytes = std::fs::read(&script)?;
let prog = Program::<FakeNamedDeBruijn>::from_flat(&bytes)?; let prog = Program::<FakeNamedDeBruijn>::from_flat(&bytes)?;
prog.into() prog.into()
} else { } else {
let code = std::fs::read_to_string(&input)?; let code = std::fs::read_to_string(&script)?;
let prog = parser::program(&code)?; let prog = parser::program(&code)?;
Program::<NamedDeBruijn>::try_from(prog)? Program::<NamedDeBruijn>::try_from(prog)?
}; };
for arg in args {
let term: Term<NamedDeBruijn> = parser::term(&arg)?.try_into()?;
program = program.apply_term(&term);
}
let (term, cost, logs) = program.eval(); let (term, cost, logs) = program.eval();
match term { match term {
@ -121,7 +128,10 @@ fn main() -> anyhow::Result<()> {
"\nBudget\n------\ncpu: {}\nmemory: {}\n", "\nBudget\n------\ncpu: {}\nmemory: {}\n",
cost.cpu, cost.mem cost.cpu, cost.mem
); );
println!("\nLogs\n----\n{}", logs.join("\n"))
if !logs.is_empty() {
println!("\nLogs\n----\n{}", logs.join("\n"))
}
} }
}, },
} }

View File

@ -39,6 +39,21 @@ where
term: applied_term, term: applied_term,
} }
} }
/// We use this to apply the validator to Datum,
/// then redeemer, then ScriptContext. If datum is
/// even necessary (i.e. minting policy).
pub fn apply_term(&self, term: &Term<T>) -> Self {
let applied_term = Term::Apply {
function: Rc::new(self.term.clone()),
argument: Rc::new(term.clone()),
};
Program {
version: self.version,
term: applied_term,
}
}
} }
impl<'a, T> Display for Program<T> impl<'a, T> Display for Program<T>

View File

@ -25,6 +25,19 @@ pub fn program(src: &str) -> Result<Program<Name>, ParseError<LineCol>> {
Ok(program) Ok(program)
} }
pub fn term(src: &str) -> Result<Term<Name>, ParseError<LineCol>> {
// initialize the string interner to get unique name
let mut interner = Interner::new();
// run the generated parser
let mut term = uplc::term(src)?;
// assign proper unique ids in place
interner.term(&mut term);
Ok(term)
}
peg::parser! { peg::parser! {
grammar uplc() for str { grammar uplc() for str {
pub rule program() -> Program<Name> pub rule program() -> Program<Name>
@ -37,7 +50,7 @@ peg::parser! {
(major as usize, minor as usize, patch as usize) (major as usize, minor as usize, patch as usize)
} }
rule term() -> Term<Name> pub rule term() -> Term<Name>
= constant() = constant()
/ builtin() / builtin()
/ var() / var()