@@ -3,7 +3,7 @@ use p3_field::PrimeField64;
33use crate :: {
44 errors:: { memory:: MemoryError , vm:: VirtualMachineError } ,
55 memory:: { address:: MemoryAddress , manager:: MemoryManager , val:: MemoryValue } ,
6- types:: instruction:: MemOrConstant ,
6+ types:: instruction:: { MemOrConstant , MemOrFp , MemOrFpOrConstant } ,
77} ;
88
99#[ derive( Debug , Default ) ]
@@ -47,7 +47,56 @@ impl RunContext {
4747 match operand {
4848 MemOrConstant :: Constant ( val) => Ok ( MemoryValue :: Int ( * val) ) ,
4949 MemOrConstant :: MemoryAfterFp { shift } => {
50- let addr = ( self . fp + * shift) ?;
50+ let addr = self . fp . add_usize ( * shift) ?;
51+ memory
52+ . get ( addr)
53+ . ok_or_else ( || MemoryError :: UninitializedMemory ( addr) . into ( ) )
54+ }
55+ }
56+ }
57+
58+ /// Resolves a `MemOrFp` operand to its final value.
59+ ///
60+ /// - If the operand is the frame pointer `Fp`, it returns the `fp` address itself.
61+ /// - If it's a memory location, it computes the address relative to `fp` and fetches the value.
62+ pub fn get_value_from_mem_or_fp < F > (
63+ & self ,
64+ operand : & MemOrFp ,
65+ memory : & MemoryManager ,
66+ ) -> Result < MemoryValue < F > , VirtualMachineError < F > >
67+ where
68+ F : PrimeField64 ,
69+ {
70+ match operand {
71+ MemOrFp :: Fp => Ok ( MemoryValue :: Address ( self . fp ) ) ,
72+ MemOrFp :: MemoryAfterFp { shift } => {
73+ let addr = self . fp . add_usize ( * shift) ?;
74+ memory
75+ . get ( addr)
76+ . ok_or_else ( || MemoryError :: UninitializedMemory ( addr) . into ( ) )
77+ }
78+ }
79+ }
80+
81+ /// Resolves a `MemOrFpOrConstant` operand to its final value.
82+ ///
83+ /// This is a comprehensive resolver that handles all three potential operand types:
84+ /// - a constant value,
85+ /// - a memory location relative to `fp`,
86+ /// - the `fp` register itself.
87+ pub fn get_value_from_mem_or_fp_or_constant < F > (
88+ & self ,
89+ operand : & MemOrFpOrConstant < F > ,
90+ memory : & MemoryManager ,
91+ ) -> Result < MemoryValue < F > , VirtualMachineError < F > >
92+ where
93+ F : PrimeField64 ,
94+ {
95+ match operand {
96+ MemOrFpOrConstant :: Constant ( val) => Ok ( MemoryValue :: Int ( * val) ) ,
97+ MemOrFpOrConstant :: Fp => Ok ( MemoryValue :: Address ( self . fp ) ) ,
98+ MemOrFpOrConstant :: MemoryAfterFp { shift } => {
99+ let addr = self . fp . add_usize ( * shift) ?;
51100 memory
52101 . get ( addr)
53102 . ok_or_else ( || MemoryError :: UninitializedMemory ( addr) . into ( ) )
@@ -159,4 +208,46 @@ mod tests {
159208 other => panic ! ( "Unexpected error: {other:?}" ) ,
160209 }
161210 }
211+
212+ #[ test]
213+ fn test_get_value_from_mem_or_fp_or_constant_is_constant ( ) {
214+ let ctx = RunContext :: new ( MemoryAddress :: new ( 0 , 0 ) , MemoryAddress :: new ( 1 , 0 ) ) ;
215+ let operand = MemOrFpOrConstant :: Constant ( F :: from_u64 ( 123 ) ) ;
216+ let memory = MemoryManager :: default ( ) ;
217+ let result = ctx
218+ . get_value_from_mem_or_fp_or_constant ( & operand, & memory)
219+ . unwrap ( ) ;
220+ assert_eq ! ( result, MemoryValue :: Int ( F :: from_u64( 123 ) ) ) ;
221+ }
222+
223+ #[ test]
224+ fn test_get_value_from_mem_or_fp_or_constant_is_fp ( ) {
225+ let fp_addr = MemoryAddress :: new ( 1 , 10 ) ;
226+ let ctx = RunContext :: new ( MemoryAddress :: new ( 0 , 0 ) , fp_addr) ;
227+ let operand = MemOrFpOrConstant :: < F > :: Fp ;
228+ let memory = MemoryManager :: default ( ) ;
229+ let result = ctx
230+ . get_value_from_mem_or_fp_or_constant ( & operand, & memory)
231+ . unwrap ( ) ;
232+ assert_eq ! ( result, MemoryValue :: Address ( fp_addr) ) ;
233+ }
234+
235+ #[ test]
236+ fn test_get_value_from_mem_or_fp_or_constant_is_mem_success ( ) {
237+ let mut memory = MemoryManager :: default ( ) ;
238+ let fp = memory. add ( ) ;
239+ let addr_to_read = fp. add_usize :: < F > ( 7 ) . unwrap ( ) ;
240+ let expected_val = MemoryValue :: < F > :: Address ( MemoryAddress :: new ( 5 , 5 ) ) ;
241+ memory
242+ . memory
243+ . insert ( addr_to_read, expected_val. clone ( ) )
244+ . unwrap ( ) ;
245+
246+ let ctx = RunContext :: new ( MemoryAddress :: new ( 0 , 0 ) , fp) ;
247+ let operand = MemOrFpOrConstant :: MemoryAfterFp { shift : 7 } ;
248+ let result = ctx
249+ . get_value_from_mem_or_fp_or_constant ( & operand, & memory)
250+ . unwrap ( ) ;
251+ assert_eq ! ( result, expected_val) ;
252+ }
162253}
0 commit comments