pub mod util;
#[cfg(test)]
mod unit_tests;
use failure::prelude::*;
use solana_libra_bytecode_verifier::VerifiedModule;
use solana_libra_ir_to_bytecode::{
compiler::{compile_module, compile_program},
parser::parse_program,
};
use solana_libra_stdlib::stdlib_modules;
use solana_libra_types::{
account_address::AccountAddress,
transaction::{Script, TransactionArgument},
};
use solana_libra_vm::file_format::{CompiledModule, CompiledProgram, CompiledScript};
use std::mem;
#[derive(Clone, Debug, Default)]
pub struct Compiler {
pub address: AccountAddress,
pub skip_stdlib_deps: bool,
pub stdlib_address: AccountAddress,
pub extra_deps: Vec<VerifiedModule>,
#[allow(missing_docs)]
#[doc(hidden)]
pub _non_exhaustive: (),
}
impl Compiler {
pub fn into_compiled_program(mut self, code: &str) -> Result<CompiledProgram> {
Ok(self.compile_impl(code)?.0)
}
pub fn into_compiled_program_and_deps(
mut self,
code: &str,
) -> Result<(CompiledProgram, Vec<VerifiedModule>)> {
self.compile_impl(code)
}
pub fn into_script(mut self, code: &str) -> Result<CompiledScript> {
let compiled_program = self.compile_impl(code)?.0;
Ok(compiled_program.script)
}
pub fn into_script_blob(mut self, code: &str) -> Result<Vec<u8>> {
let compiled_program = self.compile_impl(code)?.0;
let mut serialized_script = Vec::<u8>::new();
compiled_program.script.serialize(&mut serialized_script)?;
Ok(serialized_script)
}
pub fn into_compiled_module(mut self, code: &str) -> Result<CompiledModule> {
Ok(self.compile_mod(code)?.0)
}
pub fn into_module_blob(mut self, code: &str) -> Result<Vec<u8>> {
let compiled_module = self.compile_mod(code)?.0;
let mut serialized_module = Vec::<u8>::new();
compiled_module.serialize(&mut serialized_module)?;
Ok(serialized_module)
}
pub fn into_program(self, code: &str, args: Vec<TransactionArgument>) -> Result<Script> {
Ok(Script::new(self.into_script_blob(code)?, args))
}
fn compile_impl(&mut self, code: &str) -> Result<(CompiledProgram, Vec<VerifiedModule>)> {
let parsed_program = parse_program(code)?;
let deps = self.deps();
let compiled_program = compile_program(self.address, parsed_program, &deps)?;
Ok((compiled_program, deps))
}
fn compile_mod(&mut self, code: &str) -> Result<(CompiledModule, Vec<VerifiedModule>)> {
let parsed_program = parse_program(code)?;
let deps = self.deps();
let mut modules = parsed_program.modules;
assert_eq!(modules.len(), 1, "Must have single module");
let module = modules.pop().expect("Module must exist");
let compiled_module = compile_module(self.address, module, &deps)?;
Ok((compiled_module, deps))
}
fn deps(&mut self) -> Vec<VerifiedModule> {
let extra_deps = mem::replace(&mut self.extra_deps, vec![]);
if self.skip_stdlib_deps {
extra_deps
} else {
let mut deps = stdlib_modules().to_vec();
deps.extend(extra_deps);
deps
}
}
}