feat(cli): rework uplc subcommands
closes #553 * rename flat to encode * rename unflat to decode * alias both to their old names * both only print to stdout use can pipe to file * split cbor and hex flags * hex flag works for either cbor or flat * encode takes --to flag [name, named-debruijn, debruijn] * decode takes --from flag [name, named-debruijn, debruijn]
This commit is contained in:
parent
e5d9398625
commit
335cc0c8bc
|
@ -0,0 +1,78 @@
|
||||||
|
use miette::IntoDiagnostic;
|
||||||
|
use std::{path::PathBuf, println};
|
||||||
|
use uplc::ast::{DeBruijn, Name, NamedDeBruijn, Program};
|
||||||
|
|
||||||
|
use super::Format;
|
||||||
|
|
||||||
|
#[derive(clap::Args)]
|
||||||
|
/// Decode flat bytes to textual Untyped Plutus Core
|
||||||
|
pub struct Args {
|
||||||
|
/// Flat encoded Untyped Plutus Core file
|
||||||
|
input: PathBuf,
|
||||||
|
|
||||||
|
// Format to convert from
|
||||||
|
#[clap(long, default_value = "debruijn")]
|
||||||
|
from: Format,
|
||||||
|
|
||||||
|
/// Input file contains cbor encoded flat bytes
|
||||||
|
#[clap(short, long)]
|
||||||
|
cbor: bool,
|
||||||
|
|
||||||
|
/// Input file contents will be hex decoded
|
||||||
|
#[clap(long)]
|
||||||
|
hex: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exec(
|
||||||
|
Args {
|
||||||
|
input,
|
||||||
|
from,
|
||||||
|
cbor,
|
||||||
|
hex,
|
||||||
|
}: Args,
|
||||||
|
) -> miette::Result<()> {
|
||||||
|
let bytes = if hex {
|
||||||
|
let hex_bytes = std::fs::read_to_string(&input).into_diagnostic()?;
|
||||||
|
|
||||||
|
hex::decode(hex_bytes).into_diagnostic()?
|
||||||
|
} else {
|
||||||
|
std::fs::read(&input).into_diagnostic()?
|
||||||
|
};
|
||||||
|
|
||||||
|
let pretty_uplc = match from {
|
||||||
|
Format::Name => {
|
||||||
|
let program: Program<Name> = if cbor {
|
||||||
|
let mut flat_buffer = Vec::new();
|
||||||
|
Program::from_cbor(&bytes, &mut flat_buffer).into_diagnostic()?
|
||||||
|
} else {
|
||||||
|
Program::from_flat(&bytes).into_diagnostic()?
|
||||||
|
};
|
||||||
|
|
||||||
|
program.to_pretty()
|
||||||
|
}
|
||||||
|
Format::NamedDebruijn => {
|
||||||
|
let program: Program<NamedDeBruijn> = if cbor {
|
||||||
|
let mut flat_buffer = Vec::new();
|
||||||
|
Program::from_cbor(&bytes, &mut flat_buffer).into_diagnostic()?
|
||||||
|
} else {
|
||||||
|
Program::from_flat(&bytes).into_diagnostic()?
|
||||||
|
};
|
||||||
|
|
||||||
|
program.to_pretty()
|
||||||
|
}
|
||||||
|
Format::Debruijn => {
|
||||||
|
let program: Program<DeBruijn> = if cbor {
|
||||||
|
let mut flat_buffer = Vec::new();
|
||||||
|
Program::from_cbor(&bytes, &mut flat_buffer).into_diagnostic()?
|
||||||
|
} else {
|
||||||
|
Program::from_flat(&bytes).into_diagnostic()?
|
||||||
|
};
|
||||||
|
|
||||||
|
program.to_pretty()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{pretty_uplc}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
use miette::IntoDiagnostic;
|
||||||
|
use std::{
|
||||||
|
io::{self, Write},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
use uplc::{
|
||||||
|
ast::{DeBruijn, NamedDeBruijn, Program},
|
||||||
|
flat::Binder,
|
||||||
|
parser,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Format;
|
||||||
|
|
||||||
|
/// Encode textual Untyped Plutus Core to flat bytes
|
||||||
|
#[derive(clap::Args)]
|
||||||
|
pub struct Args {
|
||||||
|
/// Textual Untyped Plutus Core file
|
||||||
|
input: PathBuf,
|
||||||
|
|
||||||
|
// Format to convert to
|
||||||
|
#[clap(long, default_value = "debruijn")]
|
||||||
|
to: Format,
|
||||||
|
|
||||||
|
/// Further encode the flat bytes as cbor bytes
|
||||||
|
#[clap(short, long)]
|
||||||
|
cbor: bool,
|
||||||
|
|
||||||
|
/// Hex encode the bytes
|
||||||
|
#[clap(long)]
|
||||||
|
hex: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exec(
|
||||||
|
Args {
|
||||||
|
input,
|
||||||
|
to,
|
||||||
|
cbor,
|
||||||
|
hex,
|
||||||
|
}: Args,
|
||||||
|
) -> miette::Result<()> {
|
||||||
|
let code = std::fs::read_to_string(input).into_diagnostic()?;
|
||||||
|
|
||||||
|
let program = parser::program(&code).into_diagnostic()?;
|
||||||
|
|
||||||
|
match to {
|
||||||
|
Format::Name => encode(program, cbor, hex),
|
||||||
|
Format::NamedDebruijn => {
|
||||||
|
let program: Program<NamedDeBruijn> = program.try_into().into_diagnostic()?;
|
||||||
|
|
||||||
|
encode(program, cbor, hex)
|
||||||
|
}
|
||||||
|
Format::Debruijn => {
|
||||||
|
let program: Program<DeBruijn> = program.try_into().into_diagnostic()?;
|
||||||
|
|
||||||
|
encode(program, cbor, hex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode<'a, T>(program: Program<T>, cbor: bool, hex: bool) -> miette::Result<()>
|
||||||
|
where
|
||||||
|
T: Binder<'a> + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
let mut stdout = io::stdout();
|
||||||
|
|
||||||
|
let bytes = if cbor {
|
||||||
|
program.to_cbor().into_diagnostic()?
|
||||||
|
} else {
|
||||||
|
program.to_flat().into_diagnostic()?
|
||||||
|
};
|
||||||
|
|
||||||
|
if hex {
|
||||||
|
let bytes_hex = hex::encode(bytes);
|
||||||
|
|
||||||
|
print!("{bytes_hex}");
|
||||||
|
} else {
|
||||||
|
stdout.write_all(&bytes).into_diagnostic()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout.flush().into_diagnostic()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,83 +0,0 @@
|
||||||
use miette::IntoDiagnostic;
|
|
||||||
use std::{fmt::Write, fs, path::PathBuf};
|
|
||||||
use uplc::{
|
|
||||||
ast::{DeBruijn, Program},
|
|
||||||
parser,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
|
||||||
/// Encode textual Untyped Plutus Core to flat bytes
|
|
||||||
pub struct Args {
|
|
||||||
/// Textual Untyped Plutus Core file
|
|
||||||
input: PathBuf,
|
|
||||||
|
|
||||||
/// Output file name
|
|
||||||
#[clap(short, long)]
|
|
||||||
out: Option<String>,
|
|
||||||
|
|
||||||
/// Print output instead of saving to file
|
|
||||||
#[clap(short, long)]
|
|
||||||
print: bool,
|
|
||||||
|
|
||||||
#[clap(short, long)]
|
|
||||||
cbor_hex: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exec(
|
|
||||||
Args {
|
|
||||||
input,
|
|
||||||
out,
|
|
||||||
print,
|
|
||||||
cbor_hex,
|
|
||||||
}: Args,
|
|
||||||
) -> miette::Result<()> {
|
|
||||||
let code = std::fs::read_to_string(&input).into_diagnostic()?;
|
|
||||||
|
|
||||||
let program = parser::program(&code).into_diagnostic()?;
|
|
||||||
|
|
||||||
let program = Program::<DeBruijn>::try_from(program).into_diagnostic()?;
|
|
||||||
|
|
||||||
if !cbor_hex {
|
|
||||||
let bytes = program.to_flat().into_diagnostic()?;
|
|
||||||
|
|
||||||
if print {
|
|
||||||
let mut output = String::new();
|
|
||||||
|
|
||||||
for (i, byte) in bytes.iter().enumerate() {
|
|
||||||
let _ = write!(output, "{byte:08b}");
|
|
||||||
|
|
||||||
if (i + 1) % 4 == 0 {
|
|
||||||
output.push('\n');
|
|
||||||
} else {
|
|
||||||
output.push(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{output}");
|
|
||||||
} else {
|
|
||||||
let out_name = if let Some(out) = out {
|
|
||||||
out
|
|
||||||
} else {
|
|
||||||
format!("{}.flat", input.file_stem().unwrap().to_str().unwrap())
|
|
||||||
};
|
|
||||||
|
|
||||||
fs::write(out_name, &bytes).into_diagnostic()?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let cbor = program.to_hex().into_diagnostic()?;
|
|
||||||
|
|
||||||
if print {
|
|
||||||
println!("{}", &cbor);
|
|
||||||
} else {
|
|
||||||
let out_name = if let Some(out) = out {
|
|
||||||
out
|
|
||||||
} else {
|
|
||||||
format!("{}.cbor", input.file_stem().unwrap().to_str().unwrap())
|
|
||||||
};
|
|
||||||
|
|
||||||
fs::write(out_name, &cbor).into_diagnostic()?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1,24 +1,33 @@
|
||||||
|
mod decode;
|
||||||
|
mod encode;
|
||||||
mod eval;
|
mod eval;
|
||||||
mod flat;
|
|
||||||
mod fmt;
|
mod fmt;
|
||||||
mod unflat;
|
|
||||||
|
|
||||||
use clap::Subcommand;
|
use clap::{Subcommand, ValueEnum};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, ValueEnum)]
|
||||||
|
pub(super) enum Format {
|
||||||
|
Name,
|
||||||
|
NamedDebruijn,
|
||||||
|
Debruijn,
|
||||||
|
}
|
||||||
|
|
||||||
/// Commands for working with untyped Plutus-core
|
/// Commands for working with untyped Plutus-core
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum Cmd {
|
pub enum Cmd {
|
||||||
Fmt(fmt::Args),
|
Fmt(fmt::Args),
|
||||||
Eval(eval::Args),
|
Eval(eval::Args),
|
||||||
Flat(flat::Args),
|
#[clap(alias = "flat")]
|
||||||
Unflat(unflat::Args),
|
Encode(encode::Args),
|
||||||
|
#[clap(alias = "unflat")]
|
||||||
|
Decode(decode::Args),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec(cmd: Cmd) -> miette::Result<()> {
|
pub fn exec(cmd: Cmd) -> miette::Result<()> {
|
||||||
match cmd {
|
match cmd {
|
||||||
Cmd::Fmt(args) => fmt::exec(args),
|
Cmd::Fmt(args) => fmt::exec(args),
|
||||||
Cmd::Eval(args) => eval::exec(args),
|
Cmd::Eval(args) => eval::exec(args),
|
||||||
Cmd::Flat(args) => flat::exec(args),
|
Cmd::Encode(args) => encode::exec(args),
|
||||||
Cmd::Unflat(args) => unflat::exec(args),
|
Cmd::Decode(args) => decode::exec(args),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
use miette::IntoDiagnostic;
|
|
||||||
use std::{fs, path::PathBuf};
|
|
||||||
use uplc::ast::{DeBruijn, Name, Program};
|
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
|
||||||
/// Decode flat bytes to textual Untyped Plutus Core
|
|
||||||
pub struct Args {
|
|
||||||
/// Flat encoded Untyped Plutus Core file
|
|
||||||
input: PathBuf,
|
|
||||||
|
|
||||||
/// Output file name
|
|
||||||
#[clap(short, long)]
|
|
||||||
out: Option<String>,
|
|
||||||
|
|
||||||
/// Print output instead of saving to file
|
|
||||||
#[clap(short, long)]
|
|
||||||
print: bool,
|
|
||||||
|
|
||||||
#[clap(short, long)]
|
|
||||||
cbor_hex: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exec(
|
|
||||||
Args {
|
|
||||||
input,
|
|
||||||
out,
|
|
||||||
print,
|
|
||||||
cbor_hex,
|
|
||||||
}: Args,
|
|
||||||
) -> miette::Result<()> {
|
|
||||||
let program = if cbor_hex {
|
|
||||||
let cbor = std::fs::read_to_string(&input).into_diagnostic()?;
|
|
||||||
|
|
||||||
let mut cbor_buffer = Vec::new();
|
|
||||||
let mut flat_buffer = Vec::new();
|
|
||||||
|
|
||||||
Program::<DeBruijn>::from_hex(cbor.trim(), &mut cbor_buffer, &mut flat_buffer)
|
|
||||||
.into_diagnostic()?
|
|
||||||
} else {
|
|
||||||
let bytes = std::fs::read(&input).into_diagnostic()?;
|
|
||||||
|
|
||||||
Program::<DeBruijn>::from_flat(&bytes).into_diagnostic()?
|
|
||||||
};
|
|
||||||
|
|
||||||
let program: Program<Name> = program.try_into().into_diagnostic()?;
|
|
||||||
|
|
||||||
let pretty = program.to_pretty();
|
|
||||||
|
|
||||||
if print {
|
|
||||||
println!("{pretty}");
|
|
||||||
} else {
|
|
||||||
let out_name = if let Some(out) = out {
|
|
||||||
out
|
|
||||||
} else {
|
|
||||||
format!("{}.uplc", input.file_stem().unwrap().to_str().unwrap())
|
|
||||||
};
|
|
||||||
|
|
||||||
fs::write(out_name, pretty).into_diagnostic()?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@ pub mod ast;
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod builtins;
|
pub mod builtins;
|
||||||
mod debruijn;
|
mod debruijn;
|
||||||
mod flat;
|
pub mod flat;
|
||||||
pub mod machine;
|
pub mod machine;
|
||||||
pub mod optimize;
|
pub mod optimize;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
artifacts/
|
||||||
build/
|
build/
|
||||||
*.sk
|
*.sk
|
||||||
*.addr
|
*.addr
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
"$ref": "#/definitions/hello_world~1Redeemer"
|
"$ref": "#/definitions/hello_world~1Redeemer"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"compiledCode": "58dd0100003232323232323232222533300632323232533300a002100114a06464660026eb0cc010c014cc010c014019200048040dd7198021802804240006002002444a66601e00429404c8c94ccc038cdc78010018a5113330050050010033012003375c602000466e3cdd71980098010022400091010d48656c6c6f2c20576f726c64210022323330010014800000c888cccc030cdc3802001008119980200219b8000348008c0480040048c024dd50008a4c2c6002002444a66600e004293099802980098040011998018019804801000ab9a5736aae7955cfaba15745",
|
"compiledCode": "5901ec01000032323232323232323232322223232533300a3232533300c002100114a066646002002444a66602400429404c8c94ccc040cdc78010018a5113330050050010033015003375c60260046eb0cc01cc024cc01cc024011200048040dd71980398048012400066e3cdd7198031804001240009110d48656c6c6f2c20576f726c642100149858c8014c94ccc028cdc3a400000226464a66602060240042930a99806a49334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375c6020002601000a2a660169212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e7400163008004320033253330093370e900000089919299980798088010a4c2a66018921334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375c601e002600e0062a660149212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300700233001001480008888cccc01ccdc38008018061199980280299b8000448008c0380040080088c018dd5000918021baa0015734ae7155ceaab9e5573eae855d11",
|
||||||
"hash": "46872294cadbacb2c3214086c0129ede75cf9f767e95a449f996685f"
|
"hash": "f3f821d122b041244de074b9554c7dbcc62f34f62426344c0d0b4c86"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
|
Loading…
Reference in New Issue