@@ -132,6 +132,8 @@ fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
132
132
]
133
133
) ;
134
134
let source = objstr:: get_value ( source) ;
135
+ // TODO: fix this newline bug:
136
+ let source = format ! ( "{}\n " , source) ;
135
137
136
138
let mode = {
137
139
let mode = objstr:: get_value ( mode) ;
@@ -206,19 +208,36 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
206
208
arg_check ! (
207
209
vm,
208
210
args,
209
- required = [
210
- ( source , None ) , // TODO: Use more specific type
211
+ required = [ ( source , None ) ] ,
212
+ optional = [
211
213
( _globals, Some ( vm. ctx. dict_type( ) ) ) ,
212
214
( locals, Some ( vm. ctx. dict_type( ) ) )
213
215
]
214
216
) ;
215
- // TODO: handle optional global and locals
216
217
217
- let code_obj = source; // if source.borrow().kind
218
+ // Determine code object:
219
+ let code_obj = if objtype:: isinstance ( source, & vm. ctx . code_type ( ) ) {
220
+ source. clone ( )
221
+ } else if objtype:: isinstance ( source, & vm. ctx . str_type ( ) ) {
222
+ let mode = compile:: Mode :: Eval ;
223
+ let source = objstr:: get_value ( source) ;
224
+ // TODO: fix this newline bug:
225
+ let source = format ! ( "{}\n " , source) ;
226
+ compile:: compile ( vm, & source, mode, None ) ?
227
+ } else {
228
+ return Err ( vm. new_type_error ( "code argument must be str or code object" . to_string ( ) ) ) ;
229
+ } ;
230
+
231
+ let locals = if let Some ( locals) = locals {
232
+ locals. clone ( )
233
+ } else {
234
+ vm. new_dict ( )
235
+ } ;
218
236
237
+ // TODO: handle optional globals
219
238
// Construct new scope:
220
239
let scope_inner = Scope {
221
- locals : locals. clone ( ) ,
240
+ locals : locals,
222
241
parent : None ,
223
242
} ;
224
243
let scope = PyObject {
@@ -235,26 +254,38 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
235
254
arg_check ! (
236
255
vm,
237
256
args,
238
- required = [
239
- ( source , None ) ,
257
+ required = [ ( source , None ) ] ,
258
+ optional = [
240
259
( _globals, Some ( vm. ctx. dict_type( ) ) ) ,
241
260
( locals, Some ( vm. ctx. dict_type( ) ) )
242
261
]
243
262
) ;
244
- // TODO: handle optional global and locals
245
263
246
264
// Determine code object:
247
265
let code_obj = if objtype:: isinstance ( source, & vm. ctx . str_type ( ) ) {
248
266
let mode = compile:: Mode :: Exec ;
249
267
let source = objstr:: get_value ( source) ;
268
+ // TODO: fix this newline bug:
269
+ let source = format ! ( "{}\n " , source) ;
250
270
compile:: compile ( vm, & source, mode, None ) ?
251
- } else {
271
+ } else if objtype :: isinstance ( source , & vm . ctx . code_type ( ) ) {
252
272
source. clone ( )
273
+ } else {
274
+ return Err ( vm. new_type_error ( "source argument must be str or code object" . to_string ( ) ) ) ;
253
275
} ;
254
276
277
+ // handle optional global and locals
278
+ let locals = if let Some ( locals) = locals {
279
+ locals. clone ( )
280
+ } else {
281
+ vm. new_dict ( )
282
+ } ;
283
+
284
+ // TODO: use globals
285
+
255
286
// Construct new scope:
256
287
let scope_inner = Scope {
257
- locals : locals. clone ( ) ,
288
+ locals : locals,
258
289
parent : None ,
259
290
} ;
260
291
let scope = PyObject {
@@ -416,15 +447,56 @@ fn builtin_map(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
416
447
}
417
448
418
449
fn builtin_max ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
419
- arg_check ! ( vm, args, required = [ ( x, None ) , ( y, None ) ] ) ;
450
+ // arg_check!(vm, args, required = [(x, None), (y, None)]);
420
451
421
- let order = vm. call_method ( x, "__gt__" , vec ! [ y. clone( ) ] ) ?;
452
+ let candidates = if args. args . len ( ) > 1 {
453
+ args. args . clone ( )
454
+ } else if args. args . len ( ) == 1 {
455
+ vm. extract_elements ( & args. args [ 0 ] ) ?
456
+ } else {
457
+ // zero arguments means type error:
458
+ return Err ( vm. new_type_error ( "Expected 1 or more arguments" . to_string ( ) ) ) ;
459
+ } ;
422
460
423
- if objbool:: get_value ( & order) {
424
- Ok ( x. clone ( ) )
461
+ if candidates. len ( ) == 0 {
462
+ let default = args. get_optional_kwarg ( "default" ) ;
463
+ if default. is_none ( ) {
464
+ return Err ( vm. new_value_error ( "max() arg is an empty sequence" . to_string ( ) ) ) ;
465
+ } else {
466
+ return Ok ( default. unwrap ( ) ) ;
467
+ }
468
+ }
469
+
470
+ let key_func = args. get_optional_kwarg ( "key" ) ;
471
+
472
+ // Start with first assumption:
473
+ let mut candidates_iter = candidates. into_iter ( ) ;
474
+ let mut x = candidates_iter. next ( ) . unwrap ( ) ;
475
+ // TODO: this key function looks pretty duplicate. Maybe we can create
476
+ // a local function?
477
+ let mut x_key = if let Some ( f) = & key_func {
478
+ let args = PyFuncArgs :: new ( vec ! [ x. clone( ) ] , vec ! [ ] ) ;
479
+ vm. invoke ( f. clone ( ) , args) ?
425
480
} else {
426
- Ok ( y. clone ( ) )
481
+ x. clone ( )
482
+ } ;
483
+
484
+ for y in candidates_iter {
485
+ let y_key = if let Some ( f) = & key_func {
486
+ let args = PyFuncArgs :: new ( vec ! [ y. clone( ) ] , vec ! [ ] ) ;
487
+ vm. invoke ( f. clone ( ) , args) ?
488
+ } else {
489
+ y. clone ( )
490
+ } ;
491
+ let order = vm. call_method ( & x_key, "__gt__" , vec ! [ y_key. clone( ) ] ) ?;
492
+
493
+ if !objbool:: get_value ( & order) {
494
+ x = y. clone ( ) ;
495
+ x_key = y_key;
496
+ }
427
497
}
498
+
499
+ Ok ( x)
428
500
}
429
501
430
502
// builtin_memoryview
0 commit comments