@@ -248,12 +248,13 @@ impl VmIrExecutable for VM {
248
248
}
249
249
250
250
pub trait Interpretable {
251
- fn interpret ( self , trace : bool ) -> Result < ( ) , InterpreterError > ;
251
+ fn interpret ( self , trace : bool , args : Vec < String > ) -> Result < ( ) , InterpreterError > ;
252
252
}
253
253
254
254
impl Interpretable for Program {
255
- fn interpret ( self , trace : bool ) -> Result < ( ) , InterpreterError > {
255
+ fn interpret ( self , trace : bool , args : Vec < String > ) -> Result < ( ) , InterpreterError > {
256
256
let mut vm = VM :: from ( self ) ;
257
+ vm. set_args ( args) ;
257
258
vm. set_trace ( trace) ;
258
259
vm. run ( )
259
260
}
@@ -341,6 +342,47 @@ impl VM {
341
342
print ! ( "{}" , str ) ;
342
343
}
343
344
}
345
+
346
+ fn set_args ( & mut self , args : Vec < String > ) {
347
+ let mut argv_pointers = Vec :: new ( ) ;
348
+
349
+ let mut total_length = 0 ;
350
+ for arg in & args {
351
+ total_length += arg. len ( ) + 1 ; // each argument string + null terminator
352
+ }
353
+
354
+ let initial_sp = self . regs . get ( Register :: SP ) ;
355
+ self . regs
356
+ . set ( Register :: SP , initial_sp. wrapping_sub ( total_length as u16 ) ) ;
357
+
358
+ let mut current_sp = initial_sp. wrapping_sub ( total_length as u16 ) ;
359
+ for arg in & args {
360
+ argv_pointers. push ( current_sp) ; // Record the pointer to this argument
361
+
362
+ // Copy the argument string and null terminator into memory
363
+ for byte in arg. bytes ( ) {
364
+ self . data . write_bytes ( current_sp, & [ byte] ) ;
365
+ current_sp = current_sp. wrapping_add ( 1 ) ;
366
+ }
367
+ self . data . write_bytes ( current_sp, & [ 0 ] ) ; // Null terminator
368
+ current_sp = current_sp. wrapping_add ( 1 ) ;
369
+ }
370
+
371
+ self . regs
372
+ . set ( Register :: SP , self . regs . get ( Register :: SP ) . wrapping_sub ( 2 ) ) ;
373
+ self . data . write_word ( self . regs . get ( Register :: SP ) , 0 ) ;
374
+
375
+ for & pointer in argv_pointers. iter ( ) {
376
+ self . regs
377
+ . set ( Register :: SP , self . regs . get ( Register :: SP ) . wrapping_sub ( 2 ) ) ;
378
+ self . data . write_word ( self . regs . get ( Register :: SP ) , pointer) ;
379
+ }
380
+
381
+ let argc = argv_pointers. len ( ) as u16 ;
382
+ self . regs
383
+ . set ( Register :: SP , self . regs . get ( Register :: SP ) . wrapping_sub ( 2 ) ) ;
384
+ self . data . write_word ( self . regs . get ( Register :: SP ) , argc) ;
385
+ }
344
386
}
345
387
346
388
impl std:: fmt:: Display for VM {
@@ -360,17 +402,19 @@ impl std::fmt::Display for VM {
360
402
pub fn vm_interpret ( args : Vec < String > ) {
361
403
// Args validation
362
404
if args. len ( ) < 2 {
363
- println ! ( "Usage: {} <binary file> [-m]" , args[ 0 ] ) ;
405
+ println ! ( "Usage: {} <binary file> [-m] additional_args " , args[ 0 ] ) ;
364
406
return ;
365
407
}
366
408
367
409
// Logger
368
410
let trace = args. len ( ) > 2 && args[ 2 ] == "-m" ;
411
+ // remove the first arg
412
+ let parsed_args = args[ 1 ..] . to_vec ( ) ;
369
413
370
414
// Open file
371
415
let file = std:: fs:: File :: open ( & args[ 1 ] ) . unwrap ( ) ;
372
416
let program = Program :: from_file ( file) . unwrap ( ) ;
373
417
374
418
// Interpreter
375
- program. interpret ( trace) . unwrap ( ) ;
419
+ program. interpret ( trace, parsed_args ) . unwrap ( ) ;
376
420
}
0 commit comments