@@ -8,7 +8,9 @@ use clap::{App, AppSettings, Arg, ArgMatches};
8
8
use rustpython_compiler:: { compile, error:: CompileError , error:: CompileErrorType } ;
9
9
use rustpython_parser:: error:: ParseErrorType ;
10
10
use rustpython_vm:: {
11
- import, print_exception,
11
+ import, match_class,
12
+ obj:: { objint:: PyInt , objtuple:: PyTuple , objtype} ,
13
+ print_exception,
12
14
pyobject:: { ItemProtocol , PyObjectRef , PyResult } ,
13
15
scope:: Scope ,
14
16
util, PySettings , VirtualMachine ,
@@ -30,14 +32,57 @@ fn main() {
30
32
let vm = VirtualMachine :: new ( settings) ;
31
33
32
34
let res = run_rustpython ( & vm, & matches) ;
33
- // See if any exception leaked out:
34
- handle_exception ( & vm, res) ;
35
35
36
36
#[ cfg( feature = "flame-it" ) ]
37
37
{
38
38
main_guard. end ( ) ;
39
39
if let Err ( e) = write_profile ( & matches) {
40
40
error ! ( "Error writing profile information: {}" , e) ;
41
+ }
42
+ }
43
+
44
+ // See if any exception leaked out:
45
+ if let Err ( err) = res {
46
+ if objtype:: isinstance ( & err, & vm. ctx . exceptions . system_exit ) {
47
+ let args = vm. get_attribute ( err. clone ( ) , "args" ) . unwrap ( ) ;
48
+ let args = args. payload :: < PyTuple > ( ) . expect ( "'args' must be a tuple" ) ;
49
+ match args. elements . len ( ) {
50
+ 0 => return ,
51
+ 1 => match_class ! ( match args. elements[ 0 ] . clone( ) {
52
+ i @ PyInt => {
53
+ use num_traits:: cast:: ToPrimitive ;
54
+ std:: process:: exit( i. as_bigint( ) . to_i32( ) . unwrap( ) ) ;
55
+ }
56
+ _ => {
57
+ if vm. is_none( & args. elements[ 0 ] ) {
58
+ return
59
+ }
60
+ let s = vm. to_str( & args. elements[ 0 ] ) ;
61
+ let s = s
62
+ . as_ref( )
63
+ . ok( )
64
+ . map_or( "<element str() failed>" , |s| s. as_str( ) ) ;
65
+ println!( "{}" , s) ;
66
+ }
67
+ } ) ,
68
+ _ => {
69
+ print ! ( "(" ) ;
70
+ for ( i, elem) in args. elements . iter ( ) . enumerate ( ) {
71
+ if i != 0 {
72
+ print ! ( ", " )
73
+ }
74
+ let s = vm. to_str ( elem) ;
75
+ let s = s
76
+ . as_ref ( )
77
+ . ok ( )
78
+ . map_or ( "<element str() failed>" , |s| s. as_str ( ) ) ;
79
+ print ! ( "{}" , s)
80
+ }
81
+ print ! ( ")" ) ;
82
+ }
83
+ }
84
+ } else {
85
+ print_exception ( & vm, & err) ;
41
86
process:: exit ( 1 ) ;
42
87
}
43
88
}
@@ -349,13 +394,6 @@ fn _run_string(vm: &VirtualMachine, scope: Scope, source: &str, source_path: Str
349
394
vm. run_code_obj ( code_obj, scope)
350
395
}
351
396
352
- fn handle_exception < T > ( vm : & VirtualMachine , result : PyResult < T > ) {
353
- if let Err ( err) = result {
354
- print_exception ( vm, & err) ;
355
- process:: exit ( 1 ) ;
356
- }
357
- }
358
-
359
397
fn run_command ( vm : & VirtualMachine , scope : Scope , source : String ) -> PyResult < ( ) > {
360
398
debug ! ( "Running command {}" , source) ;
361
399
_run_string ( vm, scope, & source, "<stdin>" . to_string ( ) ) ?;
@@ -560,6 +598,10 @@ fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
560
598
} ;
561
599
562
600
if let Err ( exc) = result {
601
+ if objtype:: isinstance ( & exc, & vm. ctx . exceptions . system_exit ) {
602
+ repl. save_history ( & repl_history_path) . unwrap ( ) ;
603
+ return Err ( exc) ;
604
+ }
563
605
print_exception ( vm, & exc) ;
564
606
}
565
607
}
0 commit comments