1
1
mod helper;
2
2
3
- use rustpython_parser:: error:: { LexicalErrorType , ParseErrorType } ;
3
+ use rustpython_parser:: {
4
+ error:: { LexicalErrorType , ParseErrorType } ,
5
+ token:: Tok ,
6
+ } ;
4
7
use rustpython_vm:: {
5
8
builtins:: PyBaseExceptionRef ,
6
9
compiler:: { self , CompileError , CompileErrorBody , CompileErrorType } ,
@@ -19,15 +22,13 @@ fn shell_exec(
19
22
vm : & VirtualMachine ,
20
23
source : & str ,
21
24
scope : Scope ,
22
- last_row : & mut usize ,
23
25
empty_line_given : bool ,
24
26
continuing : bool ,
25
27
) -> ShellExecResult {
26
28
match vm. compile ( source, compiler:: Mode :: Single , "<stdin>" . to_owned ( ) ) {
27
29
Ok ( code) => {
28
30
if empty_line_given || !continuing {
29
31
// We want to execute the full code
30
- * last_row = 0 ;
31
32
match vm. run_code_obj ( code, scope) {
32
33
Ok ( _val) => ShellExecResult :: Ok ,
33
34
Err ( err) => ShellExecResult :: PyErr ( err) ,
@@ -54,28 +55,30 @@ fn shell_exec(
54
55
..
55
56
} ) => ShellExecResult :: Continue ,
56
57
Err ( err) => {
57
- // Indent error or something else?
58
- let indent_error = match err. body . error {
59
- CompileErrorType :: Parse ( ref p) => p. is_indentation_error ( ) ,
60
- _ => false ,
58
+ // bad_error == true if we are handling an error that should be thrown even if we are continuing
59
+ // if its an indentation error, set to true if we are continuing and the error is on column 0,
60
+ // since indentations errors on columns other than 0 should be ignored.
61
+ // if its an unrecognized token for dedent, set to false
62
+
63
+ let bad_error = match err. body . error {
64
+ CompileErrorType :: Parse ( ref p) => {
65
+ if matches ! (
66
+ p,
67
+ ParseErrorType :: Lexical ( LexicalErrorType :: IndentationError )
68
+ ) {
69
+ continuing && err. body . location . column ( ) != 0
70
+ } else {
71
+ !matches ! ( p, ParseErrorType :: UnrecognizedToken ( Tok :: Dedent , _) )
72
+ }
73
+ }
74
+ _ => true , // It is a bad error for everything else
61
75
} ;
62
76
63
- if indent_error && !empty_line_given {
64
- // The input line is not empty and it threw an indentation error
65
- let l = err. body . location ;
66
-
67
- // This is how we can mask unnecesary errors
68
- if l. row ( ) > * last_row {
69
- * last_row = l. row ( ) ;
70
- ShellExecResult :: Continue
71
- } else {
72
- * last_row = 0 ;
73
- ShellExecResult :: PyErr ( vm. new_syntax_error ( & err) )
74
- }
75
- } else {
76
- // Throw the error for all other cases
77
- * last_row = 0 ;
77
+ // If we are handling an error on an empty line or an error worthy of throwing
78
+ if empty_line_given || bad_error {
78
79
ShellExecResult :: PyErr ( vm. new_syntax_error ( & err) )
80
+ } else {
81
+ ShellExecResult :: Continue
79
82
}
80
83
}
81
84
}
@@ -100,7 +103,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
100
103
}
101
104
102
105
let mut continuing = false ;
103
- let mut last_row: usize = 0 ;
104
106
105
107
loop {
106
108
let prompt_name = if continuing { "ps2" } else { "ps1" } ;
@@ -128,14 +130,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
128
130
}
129
131
full_input. push ( '\n' ) ;
130
132
131
- match shell_exec (
132
- vm,
133
- & full_input,
134
- scope. clone ( ) ,
135
- & mut last_row,
136
- empty_line_given,
137
- continuing,
138
- ) {
133
+ match shell_exec ( vm, & full_input, scope. clone ( ) , empty_line_given, continuing) {
139
134
ShellExecResult :: Ok => {
140
135
if continuing {
141
136
if empty_line_given {
@@ -150,7 +145,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
150
145
}
151
146
} else {
152
147
// We aren't in continue mode so proceed normally
153
- last_row = 0 ;
154
148
continuing = false ;
155
149
full_input. clear ( ) ;
156
150
Ok ( ( ) )
@@ -168,7 +162,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
168
162
}
169
163
}
170
164
ReadlineResult :: Interrupt => {
171
- last_row = 0 ;
172
165
continuing = false ;
173
166
full_input. clear ( ) ;
174
167
let keyboard_interrupt =
0 commit comments