openvm_transpiler/
transpiler.rs1use std::rc::Rc;
2
3use openvm_instructions::instruction::Instruction;
4use openvm_stark_backend::p3_field::PrimeField32;
5use thiserror::Error;
6
7use crate::TranspilerExtension;
8
9#[derive(Clone)]
12pub struct Transpiler<F> {
13 processors: Vec<Rc<dyn TranspilerExtension<F>>>,
14}
15
16impl<F: PrimeField32> Default for Transpiler<F> {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22#[derive(Error, Debug)]
23pub enum TranspilerError {
24 #[error("ambiguous next instruction")]
25 AmbiguousNextInstruction,
26 #[error("couldn't parse the next instruction: {0:032b}")]
27 ParseError(u32),
28}
29
30impl<F: PrimeField32> Transpiler<F> {
31 pub fn new() -> Self {
32 Self { processors: vec![] }
33 }
34
35 pub fn with_processor(self, proc: Rc<dyn TranspilerExtension<F>>) -> Self {
36 let mut procs = self.processors;
37 procs.push(proc);
38 Self { processors: procs }
39 }
40
41 pub fn with_extension<T: TranspilerExtension<F> + 'static>(self, ext: T) -> Self {
42 self.with_processor(Rc::new(ext))
43 }
44
45 pub fn transpile(
52 &self,
53 instructions_u32: &[u32],
54 ) -> Result<Vec<Option<Instruction<F>>>, TranspilerError> {
55 let mut instructions = Vec::new();
56 let mut ptr = 0;
57 while ptr < instructions_u32.len() {
58 let mut options = self
59 .processors
60 .iter()
61 .map(|proc| proc.process_custom(&instructions_u32[ptr..]))
62 .filter(|opt| opt.is_some())
63 .collect::<Vec<_>>();
64 if options.is_empty() {
65 return Err(TranspilerError::ParseError(instructions_u32[ptr]));
66 }
67 if options.len() > 1 {
68 return Err(TranspilerError::AmbiguousNextInstruction);
69 }
70 let transpiler_output = options.pop().unwrap().unwrap();
71 instructions.extend(transpiler_output.instructions);
72 ptr += transpiler_output.used_u32s;
73 }
74 Ok(instructions)
75 }
76}