@@ -28,6 +28,28 @@ enum NameUsage {
28
28
Delete ,
29
29
}
30
30
31
+ enum CallType {
32
+ Positional { nargs : u32 } ,
33
+ Keyword { nargs : u32 } ,
34
+ Ex { has_kwargs : bool } ,
35
+ }
36
+ impl CallType {
37
+ fn normal_call ( self ) -> Instruction {
38
+ match self {
39
+ CallType :: Positional { nargs } => Instruction :: CallFunctionPositional { nargs } ,
40
+ CallType :: Keyword { nargs } => Instruction :: CallFunctionKeyword { nargs } ,
41
+ CallType :: Ex { has_kwargs } => Instruction :: CallFunctionEx { has_kwargs } ,
42
+ }
43
+ }
44
+ fn method_call ( self ) -> Instruction {
45
+ match self {
46
+ CallType :: Positional { nargs } => Instruction :: CallMethodPositional { nargs } ,
47
+ CallType :: Keyword { nargs } => Instruction :: CallMethodKeyword { nargs } ,
48
+ CallType :: Ex { has_kwargs } => Instruction :: CallMethodEx { has_kwargs } ,
49
+ }
50
+ }
51
+ }
52
+
31
53
/// Main structure holding the state of compilation.
32
54
struct Compiler {
33
55
code_stack : Vec < CodeInfo > ,
@@ -667,14 +689,13 @@ impl Compiler {
667
689
self . switch_to_block ( after_block) ;
668
690
}
669
691
}
670
- Break => match self . ctx . loop_data {
671
- Some ( ( _, end) ) => {
672
- self . emit ( Instruction :: Break { target : end } ) ;
673
- }
674
- None => {
675
- return Err ( self . error_loc ( CompileErrorType :: InvalidBreak , statement. location ) )
692
+ Break => {
693
+ if self . ctx . loop_data . is_some ( ) {
694
+ self . emit ( Instruction :: Break ) ;
695
+ } else {
696
+ return Err ( self . error_loc ( CompileErrorType :: InvalidBreak , statement. location ) ) ;
676
697
}
677
- } ,
698
+ }
678
699
Continue => match self . ctx . loop_data {
679
700
Some ( ( start, _) ) => {
680
701
self . emit ( Instruction :: Continue { target : start } ) ;
@@ -1242,7 +1263,8 @@ impl Compiler {
1242
1263
value : qualified_name,
1243
1264
} ) ;
1244
1265
1245
- self . compile_call ( 2 , bases, keywords) ?;
1266
+ let call = self . compile_call_inner ( 2 , bases, keywords) ?;
1267
+ self . emit ( call. normal_call ( ) ) ;
1246
1268
1247
1269
self . apply_decorators ( decorator_list) ;
1248
1270
@@ -1271,7 +1293,9 @@ impl Compiler {
1271
1293
let else_block = self . new_block ( ) ;
1272
1294
let after_block = self . new_block ( ) ;
1273
1295
1274
- self . emit ( Instruction :: SetupLoop ) ;
1296
+ self . emit ( Instruction :: SetupLoop {
1297
+ break_target : after_block,
1298
+ } ) ;
1275
1299
self . switch_to_block ( while_block) ;
1276
1300
1277
1301
self . compile_jump_if ( test, false , else_block) ?;
@@ -1360,7 +1384,9 @@ impl Compiler {
1360
1384
let else_block = self . new_block ( ) ;
1361
1385
let after_block = self . new_block ( ) ;
1362
1386
1363
- self . emit ( Instruction :: SetupLoop ) ;
1387
+ self . emit ( Instruction :: SetupLoop {
1388
+ break_target : after_block,
1389
+ } ) ;
1364
1390
1365
1391
// The thing iterated:
1366
1392
self . compile_expression ( iter) ?;
@@ -1794,10 +1820,7 @@ impl Compiler {
1794
1820
func,
1795
1821
args,
1796
1822
keywords,
1797
- } => {
1798
- self . compile_expression ( func) ?;
1799
- self . compile_call ( 0 , args, keywords) ?;
1800
- }
1823
+ } => self . compile_call ( func, args, keywords) ?,
1801
1824
BoolOp { op, values } => self . compile_bool_op ( op, values) ?,
1802
1825
BinOp { left, op, right } => {
1803
1826
self . compile_expression ( left) ?;
@@ -2103,17 +2126,41 @@ impl Compiler {
2103
2126
2104
2127
fn compile_call (
2105
2128
& mut self ,
2106
- additional_positional : u32 ,
2129
+ func : & ast :: Expr ,
2107
2130
args : & [ ast:: Expr ] ,
2108
2131
keywords : & [ ast:: Keyword ] ,
2109
2132
) -> CompileResult < ( ) > {
2133
+ let method = if let ast:: ExprKind :: Attribute { value, attr, .. } = & func. node {
2134
+ self . compile_expression ( value) ?;
2135
+ let idx = self . name ( attr) ;
2136
+ self . emit ( Instruction :: LoadMethod { idx } ) ;
2137
+ true
2138
+ } else {
2139
+ self . compile_expression ( func) ?;
2140
+ false
2141
+ } ;
2142
+ let call = self . compile_call_inner ( 0 , args, keywords) ?;
2143
+ self . emit ( if method {
2144
+ call. method_call ( )
2145
+ } else {
2146
+ call. normal_call ( )
2147
+ } ) ;
2148
+ Ok ( ( ) )
2149
+ }
2150
+
2151
+ fn compile_call_inner (
2152
+ & mut self ,
2153
+ additional_positional : u32 ,
2154
+ args : & [ ast:: Expr ] ,
2155
+ keywords : & [ ast:: Keyword ] ,
2156
+ ) -> CompileResult < CallType > {
2110
2157
let count = ( args. len ( ) + keywords. len ( ) ) as u32 + additional_positional;
2111
2158
2112
2159
// Normal arguments:
2113
2160
let ( size, unpack) = self . gather_elements ( additional_positional, args) ?;
2114
2161
let has_double_star = keywords. iter ( ) . any ( |k| k. node . arg . is_none ( ) ) ;
2115
2162
2116
- if unpack || has_double_star {
2163
+ let call = if unpack || has_double_star {
2117
2164
// Create a tuple with positional args:
2118
2165
self . emit ( Instruction :: BuildTuple { size, unpack } ) ;
2119
2166
@@ -2122,7 +2169,7 @@ impl Compiler {
2122
2169
if has_kwargs {
2123
2170
self . compile_keywords ( keywords) ?;
2124
2171
}
2125
- self . emit ( Instruction :: CallFunctionEx { has_kwargs } ) ;
2172
+ CallType :: Ex { has_kwargs }
2126
2173
} else if !keywords. is_empty ( ) {
2127
2174
let mut kwarg_names = vec ! [ ] ;
2128
2175
for keyword in keywords {
@@ -2140,12 +2187,12 @@ impl Compiler {
2140
2187
self . emit_constant ( ConstantData :: Tuple {
2141
2188
elements : kwarg_names,
2142
2189
} ) ;
2143
- self . emit ( Instruction :: CallFunctionKeyword { nargs : count } ) ;
2190
+ CallType :: Keyword { nargs : count }
2144
2191
} else {
2145
- self . emit ( Instruction :: CallFunctionPositional { nargs : count } ) ;
2146
- }
2192
+ CallType :: Positional { nargs : count }
2193
+ } ;
2147
2194
2148
- Ok ( ( ) )
2195
+ Ok ( call )
2149
2196
}
2150
2197
2151
2198
// Given a vector of expr / star expr generate code which gives either
@@ -2262,8 +2309,13 @@ impl Compiler {
2262
2309
unimplemented ! ( "async for comprehensions" ) ;
2263
2310
}
2264
2311
2312
+ let loop_block = self . new_block ( ) ;
2313
+ let after_block = self . new_block ( ) ;
2314
+
2265
2315
// Setup for loop:
2266
- self . emit ( Instruction :: SetupLoop ) ;
2316
+ self . emit ( Instruction :: SetupLoop {
2317
+ break_target : after_block,
2318
+ } ) ;
2267
2319
2268
2320
if loop_labels. is_empty ( ) {
2269
2321
// Load iterator onto stack (passed as first argument):
@@ -2276,8 +2328,6 @@ impl Compiler {
2276
2328
self . emit ( Instruction :: GetIter ) ;
2277
2329
}
2278
2330
2279
- let loop_block = self . new_block ( ) ;
2280
- let after_block = self . new_block ( ) ;
2281
2331
loop_labels. push ( ( loop_block, after_block) ) ;
2282
2332
2283
2333
self . switch_to_block ( loop_block) ;
0 commit comments