1- use crate :: memory:: address:: MemoryAddress ;
1+ use p3_field:: PrimeField64 ;
2+
3+ use crate :: {
4+ errors:: { memory:: MemoryError , vm:: VirtualMachineError } ,
5+ memory:: { address:: MemoryAddress , manager:: MemoryManager , val:: MemoryValue } ,
6+ types:: instruction:: MemOrConstant ,
7+ } ;
28
39#[ derive( Debug , Default ) ]
410pub struct RunContext {
@@ -25,4 +31,132 @@ impl RunContext {
2531 pub const fn fp ( & self ) -> & MemoryAddress {
2632 & self . fp
2733 }
34+
35+ /// Resolves a `MemOrConstant` operand to its final value.
36+ ///
37+ /// - If the operand is a constant, it returns the constant.
38+ /// - If it's a memory location, it computes the address relative to `fp` and fetches the value from memory.
39+ pub fn get_value < F > (
40+ & self ,
41+ operand : & MemOrConstant < F > ,
42+ memory : & MemoryManager ,
43+ ) -> Result < MemoryValue < F > , VirtualMachineError < F > >
44+ where
45+ F : PrimeField64 ,
46+ {
47+ match operand {
48+ MemOrConstant :: Constant ( val) => Ok ( MemoryValue :: Int ( * val) ) ,
49+ MemOrConstant :: MemoryAfterFp { shift } => {
50+ let addr = ( self . fp + * shift) ?;
51+ memory
52+ . get ( addr)
53+ . ok_or_else ( || MemoryError :: UninitializedMemory ( addr) . into ( ) )
54+ }
55+ }
56+ }
57+ }
58+
59+ #[ cfg( test) ]
60+ mod tests {
61+ use p3_baby_bear:: BabyBear ;
62+ use p3_field:: PrimeCharacteristicRing ;
63+
64+ use super :: * ;
65+
66+ type F = BabyBear ;
67+
68+ #[ test]
69+ fn test_get_value_constant ( ) {
70+ // Create a dummy RunContext with pc and fp.
71+ let ctx = RunContext :: new (
72+ MemoryAddress {
73+ segment_index : 0 ,
74+ offset : 0 ,
75+ } ,
76+ MemoryAddress {
77+ segment_index : 1 ,
78+ offset : 0 ,
79+ } ,
80+ ) ;
81+
82+ // A constant operand with field element 42.
83+ let operand = MemOrConstant :: Constant ( F :: from_u64 ( 42 ) ) ;
84+
85+ // Run `get_value` with an unused memory manager (memory is not needed for constants).
86+ let memory = MemoryManager :: default ( ) ;
87+
88+ // It should return the wrapped constant as a MemoryValue::Int.
89+ let result = ctx. get_value ( & operand, & memory) . unwrap ( ) ;
90+ assert_eq ! ( result, MemoryValue :: Int ( F :: from_u64( 42 ) ) ) ;
91+ }
92+
93+ #[ test]
94+ fn test_get_value_memory_after_fp_success ( ) {
95+ let mut memory = MemoryManager :: default ( ) ;
96+
97+ // Add a segment that will be used for `fp`.
98+ let fp = memory. add ( ) ; // segment_index = 0, offset = 0
99+
100+ // Shift = 2, so address to read is fp + 2 => offset 2 in the same segment.
101+ let addr_to_read = MemoryAddress {
102+ segment_index : fp. segment_index ,
103+ offset : fp. offset + 2 ,
104+ } ;
105+
106+ // Insert a value at that address manually.
107+ let expected_val = MemoryValue :: Int ( F :: from_u64 ( 99 ) ) ;
108+ memory
109+ . memory
110+ . insert ( addr_to_read, expected_val. clone ( ) )
111+ . unwrap ( ) ;
112+
113+ // Create a RunContext with that fp.
114+ let ctx = RunContext :: new (
115+ MemoryAddress {
116+ segment_index : 0 ,
117+ offset : 0 ,
118+ } , // dummy pc
119+ fp,
120+ ) ;
121+
122+ // The operand asks to read memory at fp + 2.
123+ let operand = MemOrConstant :: MemoryAfterFp { shift : 2 } ;
124+
125+ // Call get_value, which should fetch the value we inserted.
126+ let result = ctx. get_value ( & operand, & memory) . unwrap ( ) ;
127+ assert_eq ! ( result, expected_val) ;
128+ }
129+
130+ #[ test]
131+ fn test_get_value_memory_after_fp_uninitialized_memory ( ) {
132+ let mut memory = MemoryManager :: default ( ) ;
133+
134+ // Create a segment and set fp to its base.
135+ let fp = memory. add ( ) ; // segment_index = 0, offset = 0
136+
137+ // We won't insert anything, so all memory is uninitialized.
138+
139+ // Shift = 1 → fp + 1 points to offset 1 (which is uninitialized).
140+ let operand: MemOrConstant < F > = MemOrConstant :: MemoryAfterFp { shift : 1 } ;
141+
142+ // Set up context.
143+ let ctx = RunContext :: new (
144+ MemoryAddress {
145+ segment_index : 0 ,
146+ offset : 0 ,
147+ } , // dummy pc
148+ fp,
149+ ) ;
150+
151+ // Calling get_value should return a VirtualMachineError::MemoryError::UninitializedMemory.
152+ let err = ctx. get_value ( & operand, & memory) . unwrap_err ( ) ;
153+
154+ match err {
155+ VirtualMachineError :: Memory ( MemoryError :: UninitializedMemory ( addr) ) => {
156+ assert_eq ! ( addr. segment_index, fp. segment_index) ;
157+ assert_eq ! ( addr. offset, fp. offset + 1 ) ;
158+ }
159+ other => panic ! ( "Unexpected error: {other:?}" ) ,
160+ }
161+ }
28162}
0 commit comments