159 lines
4.7 KiB
Rust
159 lines
4.7 KiB
Rust
use std::{fmt::Write as _, fs};
|
|
|
|
use uplc::{
|
|
ast::{DeBruijn, FakeNamedDeBruijn, Name, NamedDeBruijn, Program, Term},
|
|
machine::cost_model::ExBudget,
|
|
parser,
|
|
};
|
|
|
|
mod args;
|
|
|
|
use args::{Args, UplcCommand};
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
let args = Args::default();
|
|
|
|
match args {
|
|
Args::Build => {
|
|
// 1. load and parse modules
|
|
// * lib - contains modules, types, and functions
|
|
// * contracts - contains validators
|
|
// * scripts - contains native scripts dsl
|
|
// 2. type check everything
|
|
// 3. generate uplc and policy/address if relevant
|
|
todo!()
|
|
}
|
|
|
|
Args::Dev => {
|
|
// launch a development server
|
|
// this should allow people to test
|
|
// their contracts over http
|
|
todo!()
|
|
}
|
|
|
|
Args::New { name } => {
|
|
if !name.exists() {
|
|
fs::create_dir_all(name.join("lib"))?;
|
|
fs::create_dir_all(name.join("policies"))?;
|
|
fs::create_dir_all(name.join("scripts"))?;
|
|
}
|
|
}
|
|
|
|
Args::Uplc(uplc) => match uplc {
|
|
UplcCommand::Flat { input, print, out } => {
|
|
let code = std::fs::read_to_string(&input)?;
|
|
|
|
let program = parser::program(&code)?;
|
|
|
|
let program = Program::<DeBruijn>::try_from(program)?;
|
|
|
|
let bytes = program.to_flat()?;
|
|
|
|
if print {
|
|
let mut output = String::new();
|
|
|
|
for (i, byte) in bytes.iter().enumerate() {
|
|
let _ = write!(output, "{:08b}", byte);
|
|
|
|
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)?;
|
|
}
|
|
}
|
|
|
|
UplcCommand::Fmt { input, print } => {
|
|
let code = std::fs::read_to_string(&input)?;
|
|
|
|
let program = parser::program(&code)?;
|
|
|
|
let pretty = program.to_pretty();
|
|
|
|
if print {
|
|
println!("{}", pretty);
|
|
} else {
|
|
fs::write(&input, pretty)?;
|
|
}
|
|
}
|
|
|
|
UplcCommand::Unflat { input, print, out } => {
|
|
let bytes = std::fs::read(&input)?;
|
|
|
|
let program = Program::<DeBruijn>::from_flat(&bytes)?;
|
|
|
|
let program: Program<Name> = program.try_into()?;
|
|
|
|
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)?;
|
|
}
|
|
}
|
|
|
|
UplcCommand::Eval { input, flat } => {
|
|
let program = if flat {
|
|
let bytes = std::fs::read(&input)?;
|
|
|
|
let prog = Program::<FakeNamedDeBruijn>::from_flat(&bytes)?;
|
|
|
|
prog.into()
|
|
} else {
|
|
let code = std::fs::read_to_string(&input)?;
|
|
|
|
let prog = parser::program(&code)?;
|
|
|
|
Program::<NamedDeBruijn>::try_from(prog)?
|
|
};
|
|
|
|
let (term, cost, logs) = program.eval();
|
|
|
|
match term {
|
|
Ok(term) => {
|
|
let term: Term<Name> = term.try_into()?;
|
|
|
|
println!("\nResult\n------\n\n{}\n", term.to_pretty());
|
|
}
|
|
Err(err) => {
|
|
eprintln!("\nError\n-----\n\n{}\n", err);
|
|
}
|
|
}
|
|
|
|
let budget = ExBudget::default();
|
|
|
|
println!(
|
|
"\nCosts\n-----\ncpu: {}\nmemory: {}",
|
|
budget.cpu - cost.cpu,
|
|
budget.mem - cost.mem
|
|
);
|
|
println!(
|
|
"\nBudget\n------\ncpu: {}\nmemory: {}\n",
|
|
cost.cpu, cost.mem
|
|
);
|
|
println!("\nLogs\n----\n{}", logs.join("\n"))
|
|
}
|
|
},
|
|
}
|
|
|
|
Ok(())
|
|
}
|