Skip to content

Commit

Permalink
feat: Builder pattern for VirtualMachine
Browse files Browse the repository at this point in the history
  • Loading branch information
zarboq committed Feb 21, 2023
1 parent abaf215 commit 8f8b003
Showing 1 changed file with 208 additions and 0 deletions.
208 changes: 208 additions & 0 deletions src/vm/vm_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,125 @@ impl VirtualMachine {
}
}

pub struct VirtualMachineBuilder {
pub(crate) run_context: RunContext,
pub(crate) builtin_runners: Vec<(&'static str, BuiltinRunner)>,
pub(crate) segments: MemorySegmentManager,
pub(crate) _program_base: Option<MaybeRelocatable>,
pub(crate) accessed_addresses: Option<Vec<Relocatable>>,
pub(crate) trace: Option<Vec<TraceEntry>>,
pub(crate) current_step: usize,
skip_instruction_execution: bool,
run_finished: bool,
#[cfg(feature = "hooks")]
pub(crate) hooks: crate::vm::hooks::Hooks,
}

impl Default for VirtualMachineBuilder {
fn default() -> Self {
let run_context = RunContext {
pc: Relocatable::from((0, 0)),
ap: 0,
fp: 0,
};

VirtualMachineBuilder {
run_context,
builtin_runners: Vec::new(),
_program_base: None,
accessed_addresses: Some(Vec::new()),
trace: None,
current_step: 0,
skip_instruction_execution: false,
segments: MemorySegmentManager::new(),
run_finished: false,
#[cfg(feature = "hooks")]
hooks: Default::default(),
}
}
}

impl VirtualMachineBuilder {
pub fn run_context(mut self, run_context: RunContext) -> VirtualMachineBuilder {
self.run_context = run_context;
self
}

pub fn builtin_runners(
mut self,
builtin_runners: Vec<(&'static str, BuiltinRunner)>,
) -> VirtualMachineBuilder {
self.builtin_runners = builtin_runners;
self
}

pub fn segments(mut self, segments: MemorySegmentManager) -> VirtualMachineBuilder {
self.segments = segments;
self
}

pub fn _program_base(
mut self,
_program_base: Option<MaybeRelocatable>,
) -> VirtualMachineBuilder {
self._program_base = _program_base;
self
}

pub fn accessed_addresses(
mut self,
accessed_addresses: Option<Vec<Relocatable>>,
) -> VirtualMachineBuilder {
self.accessed_addresses = accessed_addresses;
self
}

pub fn trace(mut self, trace: Option<Vec<TraceEntry>>) -> VirtualMachineBuilder {
self.trace = trace;
self
}

pub fn current_step(mut self, current_step: usize) -> VirtualMachineBuilder {
self.current_step = current_step;
self
}

pub fn skip_instruction_execution(
mut self,
skip_instruction_execution: bool,
) -> VirtualMachineBuilder {
self.skip_instruction_execution = skip_instruction_execution;
self
}

pub fn run_finished(mut self, run_finished: bool) -> VirtualMachineBuilder {
self.run_finished = run_finished;
self
}

#[cfg(feature = "hooks")]
pub fn hooks(mut self, hooks: crate::vm::hooks::Hooks) -> VirtualMachineBuilder {
self.hooks = hooks;
self
}

pub fn build(self) -> VirtualMachine {
VirtualMachine {
run_context: self.run_context,
builtin_runners: self.builtin_runners,
_program_base: self._program_base,
accessed_addresses: self.accessed_addresses,
trace: self.trace,
current_step: self.current_step,
skip_instruction_execution: self.skip_instruction_execution,
segments: self.segments,
run_finished: self.run_finished,
#[cfg(feature = "hooks")]
hooks: Default::default(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -4015,4 +4134,93 @@ mod tests {
let expected_traceback = vec![(Relocatable::from((1, 2)), Relocatable::from((0, 34)))];
assert_eq!(vm.get_traceback_entries(), expected_traceback);
}

#[test]
fn builder_test() {
let virtual_machine_from_builder: VirtualMachine = VirtualMachineBuilder::default()
.run_finished(true)
.current_step(12)
._program_base(Some(MaybeRelocatable::from((1, 0))))
.accessed_addresses(Some(vec![Relocatable::from((1, 0))]))
.builtin_runners(vec![(
"string",
BuiltinRunner::from(HashBuiltinRunner::new(12, true)),
)])
.run_context(RunContext {
pc: Relocatable::from((0, 0)),
ap: 18,
fp: 0,
})
.segments(MemorySegmentManager {
segment_sizes: HashMap::new(),
segment_used_sizes: Some(vec![1]),
public_memory_offsets: HashMap::new(),
memory: Memory::new(),
})
.skip_instruction_execution(true)
.trace(Some(vec![TraceEntry {
pc: Relocatable::from((0, 1)),
ap: Relocatable::from((0, 1)),
fp: Relocatable::from((0, 1)),
}]))
.build();
assert_eq!(virtual_machine_from_builder.run_finished, true);
assert_eq!(virtual_machine_from_builder.current_step, 12);
assert_eq!(
virtual_machine_from_builder._program_base,
Some(MaybeRelocatable::from((1, 0)))
);
assert_eq!(
virtual_machine_from_builder.accessed_addresses,
Some(vec![Relocatable::from((1, 0))])
);
assert_eq!(
virtual_machine_from_builder
.builtin_runners
.get(0)
.unwrap()
.0,
"string"
);
assert_eq!(virtual_machine_from_builder.run_context.ap, 18,);
assert_eq!(
virtual_machine_from_builder.segments.segment_used_sizes,
Some(vec![1])
);
assert_eq!(
virtual_machine_from_builder.skip_instruction_execution,
true
);
assert_eq!(
virtual_machine_from_builder.trace,
Some(vec![TraceEntry {
pc: Relocatable::from((0, 1)),
ap: Relocatable::from((0, 1)),
fp: Relocatable::from((0, 1)),
}])
);

#[cfg(feature = "hooks")]
use std::sync::Arc;

#[cfg(feature = "hooks")]
fn pre_step_hook(
_vm: &mut VirtualMachine,
_hint_processor: &mut dyn HintProcessor,
_exec_scope: &mut ExecutionScopes,
_hint_data: &HashMap<usize, Vec<Box<dyn Any>>>,
_constants: &HashMap<String, Felt>,
) -> Result<(), VirtualMachineError> {
Ok(())
}

#[cfg(feature = "hooks")]
let _virtual_machine_from_builder: VirtualMachine = VirtualMachineBuilder::default()
.hooks(crate::vm::hooks::Hooks::new(
None,
Some(Arc::new(pre_step_hook)),
None,
))
.build();
}
}

0 comments on commit 8f8b003

Please sign in to comment.