use anyhow::{Context, Result};
use cairo_lang_sierra::program::Program;
use cairo_lang_sierra_to_casm::compiler::{CairoProgramDebugInfo, SierraToCasmConfig};
use cairo_lang_sierra_to_casm::metadata::{calc_metadata, Metadata, MetadataComputationConfig};
use cairo_lang_sierra_type_size::ProgramRegistryInfo;
use clap::Args;
use serde_json::{json, Map, Value};
use std::collections::HashMap;
use std::path::PathBuf;
use tracing::trace_span;
#[derive(Args)]
pub struct CompileRaw {
#[arg(short, long)]
pub sierra_path: PathBuf,
#[arg(short, long)]
pub output_path: Option<PathBuf>,
#[arg(long)]
pub cache_dir: Option<PathBuf>,
}
#[tracing::instrument(skip_all, level = "info")]
pub fn compile(sierra_program: &Program) -> Result<Value> {
let metadata_config = MetadataComputationConfig::default();
let span = trace_span!("calc_metadata");
let program_info =
ProgramRegistryInfo::new(sierra_program).with_context(|| "Failed building registry.")?;
let metadata = {
let _g = span.enter();
calc_metadata(sierra_program, &program_info, metadata_config)?
};
let span = trace_span!("compile_sierra_to_casm");
let cairo_program = {
let _g = span.enter();
cairo_lang_sierra_to_casm::compiler::compile(
sierra_program,
&program_info,
&metadata,
SierraToCasmConfig {
gas_usage_check: true,
max_bytecode_size: usize::MAX,
},
)?
};
let span = trace_span!("assemble_cairo_program");
let assembled_cairo_program = {
let _g = span.enter();
cairo_program.assemble()
};
let span = trace_span!("serialize_result");
Ok({
let _g = span.enter();
json!({
"assembled_cairo_program": {
"bytecode": serde_json::to_value(assembled_cairo_program.bytecode)?,
"hints": serde_json::to_value(assembled_cairo_program.hints)?
},
"debug_info": serde_json::to_value(serialize_cairo_program_debug_info(&cairo_program.debug_info))?,
"function_costs": serialize_function_costs(sierra_program, &metadata)
})
})
}
fn serialize_function_costs(
sierra_program: &Program,
metadata: &Metadata,
) -> HashMap<usize, Map<String, Value>> {
sierra_program
.funcs
.iter()
.map(|function| {
let costs = metadata.gas_info.function_costs[&function.id]
.iter()
.map(|(token_type, value)| (token_type.name(), Value::from(*value)))
.collect();
(function.entry_point.0, costs)
})
.collect()
}
fn serialize_cairo_program_debug_info(debug_info: &CairoProgramDebugInfo) -> Vec<(usize, usize)> {
debug_info
.sierra_statement_info
.iter()
.map(|statement_debug_info| {
(
statement_debug_info.start_offset,
statement_debug_info.instruction_idx,
)
})
.collect()
}