2014-05-03 23:27:38 +01:00
/*
* This file is part of the Micro Python project , http : //micropython.org/
*
* The MIT License ( MIT )
*
* Copyright ( c ) 2013 , 2014 Damien P . George
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
2013-12-17 18:27:24 +00:00
# include <stdio.h>
# include <assert.h>
2014-05-02 15:47:01 +01:00
# include "mpconfig.h"
2013-12-17 18:27:24 +00:00
# include "nlr.h"
# include "misc.h"
2014-01-21 21:40:13 +00:00
# include "qstr.h"
2013-12-21 18:17:45 +00:00
# include "obj.h"
2014-04-15 22:03:55 +01:00
# include "objstr.h"
2013-12-21 18:17:45 +00:00
# include "runtime0.h"
2013-12-17 18:27:24 +00:00
# include "runtime.h"
# include "builtin.h"
2014-07-13 21:07:42 +01:00
# include "stream.h"
# include "pfenv.h"
2013-12-17 18:27:24 +00:00
2014-06-01 13:32:54 +01:00
# if MICROPY_PY_BUILTINS_FLOAT
2014-03-08 15:24:39 +00:00
# include <math.h>
# endif
2014-01-08 11:47:55 +00:00
// args[0] is function from class body
// args[1] is class name
// args[2:] are base objects
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin___build_class__ ( mp_uint_t n_args , const mp_obj_t * args ) {
2014-01-08 11:47:55 +00:00
assert ( 2 < = n_args ) ;
2014-04-05 22:36:42 +01:00
// set the new classes __locals__ object
mp_obj_dict_t * old_locals = mp_locals_get ( ) ;
2014-01-09 20:57:50 +00:00
mp_obj_t class_locals = mp_obj_new_dict ( 0 ) ;
2014-04-05 22:36:42 +01:00
mp_locals_set ( class_locals ) ;
2013-12-17 21:35:38 +00:00
// call the class code
2014-04-02 15:56:31 +01:00
mp_obj_t cell = mp_call_function_0 ( args [ 0 ] ) ;
2013-12-17 21:35:38 +00:00
// restore old __locals__ object
2014-03-30 13:35:08 +01:00
mp_locals_set ( old_locals ) ;
2013-12-17 21:35:38 +00:00
2014-01-08 11:47:55 +00:00
// get the class type (meta object) from the base objects
mp_obj_t meta ;
if ( n_args = = 2 ) {
// no explicit bases, so use 'type'
2014-02-15 16:10:44 +00:00
meta = ( mp_obj_t ) & mp_type_type ;
2014-01-08 11:47:55 +00:00
} else {
// use type of first base object
meta = mp_obj_get_type ( args [ 2 ] ) ;
}
// TODO do proper metaclass resolution for multiple base objects
// create the new class using a call to the meta object
mp_obj_t meta_args [ 3 ] ;
2014-01-18 14:10:48 +00:00
meta_args [ 0 ] = args [ 1 ] ; // class name
2014-01-08 11:47:55 +00:00
meta_args [ 1 ] = mp_obj_new_tuple ( n_args - 2 , args + 2 ) ; // tuple of bases
2014-01-18 14:10:48 +00:00
meta_args [ 2 ] = class_locals ; // dict of members
2014-03-30 13:35:08 +01:00
mp_obj_t new_class = mp_call_function_n_kw ( meta , 3 , 0 , meta_args ) ;
2014-01-08 11:47:55 +00:00
// store into cell if neede
if ( cell ! = mp_const_none ) {
mp_obj_cell_set ( cell , new_class ) ;
}
return new_class ;
2013-12-17 21:35:38 +00:00
}
2014-01-08 11:47:55 +00:00
MP_DEFINE_CONST_FUN_OBJ_VAR ( mp_builtin___build_class___obj , 2 , mp_builtin___build_class__ ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin___repl_print__ ( mp_obj_t o ) {
2013-12-21 18:17:45 +00:00
if ( o ! = mp_const_none ) {
2014-01-13 17:19:16 +00:00
mp_obj_print ( o , PRINT_REPR ) ;
2013-12-17 18:27:24 +00:00
printf ( " \n " ) ;
}
2013-12-21 18:17:45 +00:00
return mp_const_none ;
2013-12-17 18:27:24 +00:00
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin___repl_print___obj , mp_builtin___repl_print__ ) ;
2014-08-12 18:13:44 +01:00
STATIC mp_obj_t mp_builtin_abs ( mp_obj_t o_in ) {
2013-12-21 18:17:45 +00:00
if ( MP_OBJ_IS_SMALL_INT ( o_in ) ) {
2014-07-03 13:25:24 +01:00
mp_int_t val = MP_OBJ_SMALL_INT_VALUE ( o_in ) ;
2013-12-17 21:35:38 +00:00
if ( val < 0 ) {
val = - val ;
2013-12-17 18:27:24 +00:00
}
2013-12-21 18:17:45 +00:00
return MP_OBJ_NEW_SMALL_INT ( val ) ;
2014-06-01 13:32:54 +01:00
# if MICROPY_PY_BUILTINS_FLOAT
2014-03-08 15:24:39 +00:00
} else if ( MP_OBJ_IS_TYPE ( o_in , & mp_type_float ) ) {
2013-12-21 18:17:45 +00:00
mp_float_t value = mp_obj_float_get ( o_in ) ;
2013-12-17 21:35:38 +00:00
// TODO check for NaN etc
2013-12-21 18:17:45 +00:00
if ( value < 0 ) {
return mp_obj_new_float ( - value ) ;
2013-12-17 18:27:24 +00:00
} else {
2013-12-17 21:35:38 +00:00
return o_in ;
2013-12-17 18:27:24 +00:00
}
2014-06-19 23:48:35 +01:00
# if MICROPY_PY_BUILTINS_COMPLEX
2014-03-08 15:24:39 +00:00
} else if ( MP_OBJ_IS_TYPE ( o_in , & mp_type_complex ) ) {
2013-12-21 18:17:45 +00:00
mp_float_t real , imag ;
mp_obj_complex_get ( o_in , & real , & imag ) ;
2014-03-08 15:24:39 +00:00
return mp_obj_new_float ( MICROPY_FLOAT_C_FUN ( sqrt ) ( real * real + imag * imag ) ) ;
2014-06-19 23:48:35 +01:00
# endif
2013-12-17 21:35:38 +00:00
# endif
} else {
assert ( 0 ) ;
2013-12-21 18:17:45 +00:00
return mp_const_none ;
2013-12-17 21:35:38 +00:00
}
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_abs_obj , mp_builtin_abs ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_all ( mp_obj_t o_in ) {
2014-03-30 13:35:08 +01:00
mp_obj_t iterable = mp_getiter ( o_in ) ;
2013-12-21 18:17:45 +00:00
mp_obj_t item ;
2014-04-17 23:19:36 +01:00
while ( ( item = mp_iternext ( iterable ) ) ! = MP_OBJ_STOP_ITERATION ) {
2014-03-30 13:35:08 +01:00
if ( ! mp_obj_is_true ( item ) ) {
2013-12-21 18:17:45 +00:00
return mp_const_false ;
2013-12-17 21:35:38 +00:00
}
}
2013-12-21 18:17:45 +00:00
return mp_const_true ;
2013-12-17 21:35:38 +00:00
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_all_obj , mp_builtin_all ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_any ( mp_obj_t o_in ) {
2014-03-30 13:35:08 +01:00
mp_obj_t iterable = mp_getiter ( o_in ) ;
2013-12-21 18:17:45 +00:00
mp_obj_t item ;
2014-04-17 23:19:36 +01:00
while ( ( item = mp_iternext ( iterable ) ) ! = MP_OBJ_STOP_ITERATION ) {
2014-03-30 13:35:08 +01:00
if ( mp_obj_is_true ( item ) ) {
2013-12-21 18:17:45 +00:00
return mp_const_true ;
2013-12-17 21:35:38 +00:00
}
}
2013-12-21 18:17:45 +00:00
return mp_const_false ;
2013-12-17 21:35:38 +00:00
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_any_obj , mp_builtin_any ) ;
2014-04-15 22:03:55 +01:00
STATIC mp_obj_t mp_builtin_bin ( mp_obj_t o_in ) {
mp_obj_t args [ ] = { MP_OBJ_NEW_QSTR ( MP_QSTR__brace_open__colon__hash_b_brace_close_ ) , o_in } ;
2014-06-19 17:54:34 +01:00
return mp_obj_str_format ( MP_ARRAY_SIZE ( args ) , args ) ;
2014-04-15 22:03:55 +01:00
}
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_bin_obj , mp_builtin_bin ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_callable ( mp_obj_t o_in ) {
2013-12-21 18:17:45 +00:00
if ( mp_obj_is_callable ( o_in ) ) {
return mp_const_true ;
2013-12-17 21:35:38 +00:00
} else {
2013-12-21 18:17:45 +00:00
return mp_const_false ;
2013-12-17 21:35:38 +00:00
}
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_callable_obj , mp_builtin_callable ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_chr ( mp_obj_t o_in ) {
2014-06-13 00:39:37 +01:00
# if MICROPY_PY_BUILTINS_STR_UNICODE
2014-07-31 14:41:43 +01:00
mp_uint_t c = mp_obj_get_int ( o_in ) ;
2014-06-03 20:28:12 +01:00
char str [ 4 ] ;
int len = 0 ;
if ( c < 0x80 ) {
* str = c ; len = 1 ;
} else if ( c < 0x800 ) {
str [ 0 ] = ( c > > 6 ) | 0xC0 ;
str [ 1 ] = ( c & 0x3F ) | 0x80 ;
len = 2 ;
} else if ( c < 0x10000 ) {
str [ 0 ] = ( c > > 12 ) | 0xE0 ;
str [ 1 ] = ( ( c > > 6 ) & 0x3F ) | 0x80 ;
str [ 2 ] = ( c & 0x3F ) | 0x80 ;
len = 3 ;
} else if ( c < 0x110000 ) {
str [ 0 ] = ( c > > 18 ) | 0xF0 ;
str [ 1 ] = ( ( c > > 12 ) & 0x3F ) | 0x80 ;
str [ 2 ] = ( ( c > > 6 ) & 0x3F ) | 0x80 ;
str [ 3 ] = ( c & 0x3F ) | 0x80 ;
len = 4 ;
2013-12-17 21:35:38 +00:00
} else {
2014-04-05 18:32:08 +01:00
nlr_raise ( mp_obj_new_exception_msg ( & mp_type_ValueError , " chr() arg not in range(0x110000) " ) ) ;
2013-12-17 18:27:24 +00:00
}
2014-06-03 20:28:12 +01:00
return mp_obj_new_str ( str , len , true ) ;
2014-06-13 00:39:37 +01:00
# else
2014-07-03 13:25:24 +01:00
mp_int_t ord = mp_obj_get_int ( o_in ) ;
2014-06-13 00:39:37 +01:00
if ( 0 < = ord & & ord < = 0x10ffff ) {
char str [ 1 ] = { ord } ;
return mp_obj_new_str ( str , 1 , true ) ;
} else {
nlr_raise ( mp_obj_new_exception_msg ( & mp_type_ValueError , " chr() arg not in range(0x110000) " ) ) ;
}
# endif
2013-12-17 21:35:38 +00:00
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_chr_obj , mp_builtin_chr ) ;
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_dir ( mp_uint_t n_args , const mp_obj_t * args ) {
2014-02-02 22:07:44 +00:00
// TODO make this function more general and less of a hack
2014-04-05 22:36:42 +01:00
mp_obj_dict_t * dict = NULL ;
2014-02-02 22:07:44 +00:00
if ( n_args = = 0 ) {
// make a list of names in the local name space
2014-04-05 22:36:42 +01:00
dict = mp_locals_get ( ) ;
2014-02-02 22:07:44 +00:00
} else { // n_args == 1
// make a list of names in the given object
2014-03-26 22:35:00 +00:00
if ( MP_OBJ_IS_TYPE ( args [ 0 ] , & mp_type_module ) ) {
2014-04-05 22:36:42 +01:00
dict = mp_obj_module_get_globals ( args [ 0 ] ) ;
2014-03-26 22:35:00 +00:00
} else {
mp_obj_type_t * type ;
if ( MP_OBJ_IS_TYPE ( args [ 0 ] , & mp_type_type ) ) {
type = args [ 0 ] ;
} else {
type = mp_obj_get_type ( args [ 0 ] ) ;
}
2014-03-29 13:43:38 +00:00
if ( type - > locals_dict ! = MP_OBJ_NULL & & MP_OBJ_IS_TYPE ( type - > locals_dict , & mp_type_dict ) ) {
2014-04-05 22:36:42 +01:00
dict = type - > locals_dict ;
2014-03-26 22:35:00 +00:00
}
2014-03-23 00:03:11 +00:00
}
2014-02-02 22:07:44 +00:00
}
mp_obj_t dir = mp_obj_new_list ( 0 , NULL ) ;
2014-04-05 22:36:42 +01:00
if ( dict ! = NULL ) {
2014-08-30 14:19:41 +01:00
for ( mp_uint_t i = 0 ; i < dict - > map . alloc ; i + + ) {
2014-04-05 22:36:42 +01:00
if ( MP_MAP_SLOT_IS_FILLED ( & dict - > map , i ) ) {
mp_obj_list_append ( dir , dict - > map . table [ i ] . key ) ;
2014-03-23 00:03:11 +00:00
}
}
}
2014-03-26 21:47:19 +00:00
2014-02-02 22:07:44 +00:00
return dir ;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN ( mp_builtin_dir_obj , 0 , 1 , mp_builtin_dir ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_divmod ( mp_obj_t o1_in , mp_obj_t o2_in ) {
2013-12-21 18:17:45 +00:00
if ( MP_OBJ_IS_SMALL_INT ( o1_in ) & & MP_OBJ_IS_SMALL_INT ( o2_in ) ) {
2014-07-03 13:25:24 +01:00
mp_int_t i1 = MP_OBJ_SMALL_INT_VALUE ( o1_in ) ;
mp_int_t i2 = MP_OBJ_SMALL_INT_VALUE ( o2_in ) ;
2014-01-18 14:10:48 +00:00
mp_obj_t args [ 2 ] ;
args [ 0 ] = MP_OBJ_NEW_SMALL_INT ( i1 / i2 ) ;
args [ 1 ] = MP_OBJ_NEW_SMALL_INT ( i1 % i2 ) ;
2014-03-31 16:28:13 +01:00
return mp_obj_new_tuple ( 2 , args ) ;
2013-12-17 21:35:38 +00:00
} else {
2014-04-05 18:32:08 +01:00
nlr_raise ( mp_obj_new_exception_msg_varg ( & mp_type_TypeError , " unsupported operand type(s) for divmod(): '%s' and '%s' " , mp_obj_get_type_str ( o1_in ) , mp_obj_get_type_str ( o2_in ) ) ) ;
2013-12-17 21:35:38 +00:00
}
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_2 ( mp_builtin_divmod_obj , mp_builtin_divmod ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_hash ( mp_obj_t o_in ) {
2013-12-17 21:35:38 +00:00
// TODO hash will generally overflow small integer; can we safely truncate it?
2013-12-21 18:17:45 +00:00
return mp_obj_new_int ( mp_obj_hash ( o_in ) ) ;
2013-12-17 21:35:38 +00:00
}
2013-12-21 18:17:45 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_hash_obj , mp_builtin_hash ) ;
2013-12-17 21:35:38 +00:00
2014-04-15 12:42:52 +01:00
STATIC mp_obj_t mp_builtin_hex ( mp_obj_t o_in ) {
2014-04-15 12:50:21 +01:00
return mp_binary_op ( MP_BINARY_OP_MODULO , MP_OBJ_NEW_QSTR ( MP_QSTR__percent__hash_x ) , o_in ) ;
2014-04-15 12:42:52 +01:00
}
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_hex_obj , mp_builtin_hex ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_iter ( mp_obj_t o_in ) {
2014-03-30 13:35:08 +01:00
return mp_getiter ( o_in ) ;
2013-12-17 18:27:24 +00:00
}
2013-12-21 18:17:45 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_iter_obj , mp_builtin_iter ) ;
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_min_max ( mp_uint_t n_args , const mp_obj_t * args , mp_map_t * kwargs , mp_uint_t op ) {
2014-08-24 19:14:09 +01:00
mp_map_elem_t * key_elem = mp_map_lookup ( kwargs , MP_OBJ_NEW_QSTR ( MP_QSTR_key ) , MP_MAP_LOOKUP ) ;
mp_obj_t key_fn = key_elem = = NULL ? MP_OBJ_NULL : key_elem - > value ;
2013-12-17 21:35:38 +00:00
if ( n_args = = 1 ) {
// given an iterable
2014-03-30 13:35:08 +01:00
mp_obj_t iterable = mp_getiter ( args [ 0 ] ) ;
2014-08-24 19:14:09 +01:00
mp_obj_t best_key = MP_OBJ_NULL ;
mp_obj_t best_obj = MP_OBJ_NULL ;
2013-12-21 18:17:45 +00:00
mp_obj_t item ;
2014-04-17 23:19:36 +01:00
while ( ( item = mp_iternext ( iterable ) ) ! = MP_OBJ_STOP_ITERATION ) {
2014-08-24 19:14:09 +01:00
mp_obj_t key = key_fn = = MP_OBJ_NULL ? item : mp_call_function_1 ( key_fn , item ) ;
if ( best_obj = = MP_OBJ_NULL | | ( mp_binary_op ( op , key , best_key ) = = mp_const_true ) ) {
best_key = key ;
best_obj = item ;
2013-12-17 21:35:38 +00:00
}
2013-12-17 18:27:24 +00:00
}
2014-08-24 19:14:09 +01:00
if ( best_obj = = MP_OBJ_NULL ) {
nlr_raise ( mp_obj_new_exception_msg ( & mp_type_ValueError , " arg is an empty sequence " ) ) ;
2013-12-17 21:35:38 +00:00
}
2014-08-24 19:14:09 +01:00
return best_obj ;
2013-12-17 18:27:24 +00:00
} else {
2013-12-17 21:35:38 +00:00
// given many args
2014-08-24 19:14:09 +01:00
mp_obj_t best_key = MP_OBJ_NULL ;
mp_obj_t best_obj = MP_OBJ_NULL ;
for ( mp_uint_t i = 0 ; i < n_args ; i + + ) {
mp_obj_t key = key_fn = = MP_OBJ_NULL ? args [ i ] : mp_call_function_1 ( key_fn , args [ i ] ) ;
if ( best_obj = = MP_OBJ_NULL | | ( mp_binary_op ( op , key , best_key ) = = mp_const_true ) ) {
best_key = key ;
best_obj = args [ i ] ;
2013-12-17 21:35:38 +00:00
}
}
2014-08-24 19:14:09 +01:00
return best_obj ;
2013-12-17 18:27:24 +00:00
}
}
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_max ( mp_uint_t n_args , const mp_obj_t * args , mp_map_t * kwargs ) {
2014-08-24 19:14:09 +01:00
return mp_builtin_min_max ( n_args , args , kwargs , MP_BINARY_OP_MORE ) ;
2013-12-17 21:35:38 +00:00
}
2014-08-24 19:14:09 +01:00
MP_DEFINE_CONST_FUN_OBJ_KW ( mp_builtin_max_obj , 1 , mp_builtin_max ) ;
2013-12-17 18:27:24 +00:00
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_min ( mp_uint_t n_args , const mp_obj_t * args , mp_map_t * kwargs ) {
2014-08-24 19:14:09 +01:00
return mp_builtin_min_max ( n_args , args , kwargs , MP_BINARY_OP_LESS ) ;
}
MP_DEFINE_CONST_FUN_OBJ_KW ( mp_builtin_min_obj , 1 , mp_builtin_min ) ;
2014-01-13 19:39:01 +00:00
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_next ( mp_obj_t o ) {
2014-03-30 13:35:08 +01:00
mp_obj_t ret = mp_iternext_allow_raise ( o ) ;
2014-04-17 23:19:36 +01:00
if ( ret = = MP_OBJ_STOP_ITERATION ) {
2014-04-05 18:32:08 +01:00
nlr_raise ( mp_obj_new_exception ( & mp_type_StopIteration ) ) ;
2013-12-21 18:38:03 +00:00
} else {
return ret ;
}
2013-12-21 18:17:45 +00:00
}
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_next_obj , mp_builtin_next ) ;
2014-04-15 22:03:55 +01:00
STATIC mp_obj_t mp_builtin_oct ( mp_obj_t o_in ) {
return mp_binary_op ( MP_BINARY_OP_MODULO , MP_OBJ_NEW_QSTR ( MP_QSTR__percent__hash_o ) , o_in ) ;
}
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_oct_obj , mp_builtin_oct ) ;
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_ord ( mp_obj_t o_in ) {
2014-08-30 14:19:41 +01:00
mp_uint_t len ;
2014-02-08 18:17:23 +00:00
const char * str = mp_obj_str_get_data ( o_in , & len ) ;
2014-06-13 00:39:37 +01:00
# if MICROPY_PY_BUILTINS_STR_UNICODE
2014-07-03 13:25:24 +01:00
mp_uint_t charlen = unichar_charlen ( str , len ) ;
2014-06-03 20:28:12 +01:00
if ( charlen = = 1 ) {
if ( MP_OBJ_IS_STR ( o_in ) & & UTF8_IS_NONASCII ( * str ) ) {
2014-07-03 13:25:24 +01:00
mp_int_t ord = * str + + & 0x7F ;
for ( mp_int_t mask = 0x40 ; ord & mask ; mask > > = 1 ) {
2014-06-03 20:28:12 +01:00
ord & = ~ mask ;
}
while ( UTF8_IS_CONT ( * str ) ) {
ord = ( ord < < 6 ) | ( * str + + & 0x3F ) ;
}
return mp_obj_new_int ( ord ) ;
} else {
return mp_obj_new_int ( ( ( const byte * ) str ) [ 0 ] ) ;
}
2013-12-17 21:35:38 +00:00
} else {
2014-06-03 20:28:12 +01:00
nlr_raise ( mp_obj_new_exception_msg_varg ( & mp_type_TypeError , " ord() expected a character, but string of length %d found " , charlen ) ) ;
2013-12-17 21:35:38 +00:00
}
2014-06-13 00:39:37 +01:00
# else
if ( len = = 1 ) {
// don't sign extend when converting to ord
return mp_obj_new_int ( ( ( const byte * ) str ) [ 0 ] ) ;
} else {
nlr_raise ( mp_obj_new_exception_msg_varg ( & mp_type_TypeError , " ord() expected a character, but string of length %d found " , len ) ) ;
}
# endif
2013-12-17 21:35:38 +00:00
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_ord_obj , mp_builtin_ord ) ;
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_pow ( mp_uint_t n_args , const mp_obj_t * args ) {
2014-01-13 19:39:01 +00:00
assert ( 2 < = n_args & & n_args < = 3 ) ;
2013-12-17 21:35:38 +00:00
switch ( n_args ) {
2014-03-30 13:35:08 +01:00
case 2 : return mp_binary_op ( MP_BINARY_OP_POWER , args [ 0 ] , args [ 1 ] ) ;
default : return mp_binary_op ( MP_BINARY_OP_MODULO , mp_binary_op ( MP_BINARY_OP_POWER , args [ 0 ] , args [ 1 ] ) , args [ 2 ] ) ; // TODO optimise...
2013-12-17 21:35:38 +00:00
}
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN ( mp_builtin_pow_obj , 2 , 3 , mp_builtin_pow ) ;
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_print ( mp_uint_t n_args , const mp_obj_t * args , mp_map_t * kwargs ) {
2014-04-02 10:34:44 +01:00
mp_map_elem_t * sep_elem = mp_map_lookup ( kwargs , MP_OBJ_NEW_QSTR ( MP_QSTR_sep ) , MP_MAP_LOOKUP ) ;
mp_map_elem_t * end_elem = mp_map_lookup ( kwargs , MP_OBJ_NEW_QSTR ( MP_QSTR_end ) , MP_MAP_LOOKUP ) ;
const char * sep_data = " " ;
2014-08-30 14:19:41 +01:00
mp_uint_t sep_len = 1 ;
2014-04-02 10:34:44 +01:00
const char * end_data = " \n " ;
2014-08-30 14:19:41 +01:00
mp_uint_t end_len = 1 ;
2014-04-02 10:34:44 +01:00
if ( sep_elem ! = NULL & & sep_elem - > value ! = mp_const_none ) {
sep_data = mp_obj_str_get_data ( sep_elem - > value , & sep_len ) ;
}
if ( end_elem ! = NULL & & end_elem - > value ! = mp_const_none ) {
end_data = mp_obj_str_get_data ( end_elem - > value , & end_len ) ;
}
2014-07-13 21:07:42 +01:00
# if MICROPY_PY_IO
mp_obj_t stream_obj = & mp_sys_stdout_obj ;
mp_map_elem_t * file_elem = mp_map_lookup ( kwargs , MP_OBJ_NEW_QSTR ( MP_QSTR_file ) , MP_MAP_LOOKUP ) ;
if ( file_elem ! = NULL & & file_elem - > value ! = mp_const_none ) {
stream_obj = file_elem - > value ;
}
pfenv_t pfenv ;
pfenv . data = stream_obj ;
pfenv . print_strn = ( void ( * ) ( void * , const char * , unsigned int ) ) mp_stream_write ;
# endif
2013-12-17 21:35:38 +00:00
for ( int i = 0 ; i < n_args ; i + + ) {
if ( i > 0 ) {
2014-07-13 21:07:42 +01:00
# if MICROPY_PY_IO
mp_stream_write ( stream_obj , sep_data , sep_len ) ;
# else
2014-08-30 14:59:21 +01:00
printf ( " %.*s " , ( int ) sep_len , sep_data ) ;
2014-07-13 21:07:42 +01:00
# endif
2013-12-17 21:35:38 +00:00
}
2014-07-13 21:07:42 +01:00
# if MICROPY_PY_IO
mp_obj_print_helper ( ( void ( * ) ( void * env , const char * fmt , . . . ) ) pfenv_printf , & pfenv , args [ i ] , PRINT_STR ) ;
# else
2014-01-13 17:19:16 +00:00
mp_obj_print ( args [ i ] , PRINT_STR ) ;
2014-07-13 21:07:42 +01:00
# endif
2013-12-17 21:35:38 +00:00
}
2014-07-13 21:07:42 +01:00
# if MICROPY_PY_IO
mp_stream_write ( stream_obj , end_data , end_len ) ;
# else
2014-08-30 14:59:21 +01:00
printf ( " %.*s " , ( int ) end_len , end_data ) ;
2014-07-13 21:07:42 +01:00
# endif
2013-12-21 18:17:45 +00:00
return mp_const_none ;
2013-12-17 18:27:24 +00:00
}
2014-04-02 10:34:44 +01:00
MP_DEFINE_CONST_FUN_OBJ_KW ( mp_builtin_print_obj , 0 , mp_builtin_print ) ;
2014-01-13 19:39:01 +00:00
2014-02-12 16:31:30 +00:00
STATIC mp_obj_t mp_builtin_repr ( mp_obj_t o_in ) {
2014-01-15 21:40:48 +00:00
vstr_t * vstr = vstr_new ( ) ;
2014-01-15 22:39:03 +00:00
mp_obj_print_helper ( ( void ( * ) ( void * env , const char * fmt , . . . ) ) vstr_printf , vstr , o_in , PRINT_REPR ) ;
2014-05-25 22:27:57 +01:00
mp_obj_t s = mp_obj_new_str ( vstr - > buf , vstr - > len , false ) ;
2014-01-22 14:35:10 +00:00
vstr_free ( vstr ) ;
return s ;
2014-01-15 21:40:48 +00:00
}
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_repr_obj , mp_builtin_repr ) ;
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_sum ( mp_uint_t n_args , const mp_obj_t * args ) {
2014-01-13 19:39:01 +00:00
assert ( 1 < = n_args & & n_args < = 2 ) ;
2013-12-21 18:17:45 +00:00
mp_obj_t value ;
2013-12-17 21:35:38 +00:00
switch ( n_args ) {
2013-12-21 18:17:45 +00:00
case 1 : value = mp_obj_new_int ( 0 ) ; break ;
2014-01-13 19:39:01 +00:00
default : value = args [ 1 ] ; break ;
2013-12-17 21:35:38 +00:00
}
2014-03-30 13:35:08 +01:00
mp_obj_t iterable = mp_getiter ( args [ 0 ] ) ;
2013-12-21 18:17:45 +00:00
mp_obj_t item ;
2014-04-17 23:19:36 +01:00
while ( ( item = mp_iternext ( iterable ) ) ! = MP_OBJ_STOP_ITERATION ) {
2014-03-30 13:35:08 +01:00
value = mp_binary_op ( MP_BINARY_OP_ADD , value , item ) ;
2013-12-17 21:35:38 +00:00
}
return value ;
}
2014-01-13 19:39:01 +00:00
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN ( mp_builtin_sum_obj , 1 , 2 , mp_builtin_sum ) ;
2014-01-13 05:12:50 +00:00
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_sorted ( mp_uint_t n_args , const mp_obj_t * args , mp_map_t * kwargs ) {
2014-01-18 14:10:48 +00:00
assert ( n_args > = 1 ) ;
if ( n_args > 1 ) {
2014-04-05 18:32:08 +01:00
nlr_raise ( mp_obj_new_exception_msg ( & mp_type_TypeError ,
2014-01-13 05:12:50 +00:00
" must use keyword argument for key function " ) ) ;
}
2014-03-29 13:43:38 +00:00
mp_obj_t self = mp_type_list . make_new ( ( mp_obj_t ) & mp_type_list , 1 , 0 , args ) ;
2014-01-18 14:10:48 +00:00
mp_obj_list_sort ( 1 , & self , kwargs ) ;
2014-01-13 05:12:50 +00:00
return self ;
}
2014-01-13 19:55:18 +00:00
MP_DEFINE_CONST_FUN_OBJ_KW ( mp_builtin_sorted_obj , 1 , mp_builtin_sorted ) ;
2014-01-13 17:20:46 +00:00
2014-04-06 00:12:03 +01:00
// See mp_load_attr() if making any changes
STATIC inline mp_obj_t mp_load_attr_default ( mp_obj_t base , qstr attr , mp_obj_t defval ) {
mp_obj_t dest [ 2 ] ;
// use load_method, raising or not raising exception
( ( defval = = MP_OBJ_NULL ) ? mp_load_method : mp_load_method_maybe ) ( base , attr , dest ) ;
if ( dest [ 0 ] = = MP_OBJ_NULL ) {
return defval ;
} else if ( dest [ 1 ] = = MP_OBJ_NULL ) {
// load_method returned just a normal attribute
return dest [ 0 ] ;
} else {
// load_method returned a method, so build a bound method object
return mp_obj_new_bound_meth ( dest [ 0 ] , dest [ 1 ] ) ;
}
}
2014-08-30 14:19:41 +01:00
STATIC mp_obj_t mp_builtin_getattr ( mp_uint_t n_args , const mp_obj_t * args ) {
2014-06-07 23:13:35 +01:00
mp_obj_t attr = args [ 1 ] ;
if ( MP_OBJ_IS_TYPE ( attr , & mp_type_str ) ) {
attr = mp_obj_str_intern ( attr ) ;
} else if ( ! MP_OBJ_IS_QSTR ( attr ) ) {
nlr_raise ( mp_obj_new_exception_msg ( & mp_type_TypeError , " string required " ) ) ;
}
2014-04-05 11:33:04 +01:00
mp_obj_t defval = MP_OBJ_NULL ;
if ( n_args > 2 ) {
defval = args [ 2 ] ;
}
2014-06-07 23:13:35 +01:00
return mp_load_attr_default ( args [ 0 ] , MP_OBJ_QSTR_VALUE ( attr ) , defval ) ;
2014-03-26 21:35:13 +00:00
}
2014-04-05 11:33:04 +01:00
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN ( mp_builtin_getattr_obj , 2 , 3 , mp_builtin_getattr ) ;
2014-04-05 23:00:46 +01:00
2014-05-11 17:05:42 +01:00
STATIC mp_obj_t mp_builtin_hasattr ( mp_obj_t object_in , mp_obj_t attr_in ) {
assert ( MP_OBJ_IS_QSTR ( attr_in ) ) ;
mp_obj_t dest [ 2 ] ;
2014-06-05 18:51:03 +01:00
// TODO: https://docs.python.org/3/library/functions.html?highlight=hasattr#hasattr
2014-05-11 17:05:42 +01:00
// explicitly says "This is implemented by calling getattr(object, name) and seeing
// whether it raises an AttributeError or not.", so we should explicitly wrap this
// in nlr_push and handle exception.
mp_load_method_maybe ( object_in , MP_OBJ_QSTR_VALUE ( attr_in ) , dest ) ;
return MP_BOOL ( dest [ 0 ] ! = MP_OBJ_NULL ) ;
}
MP_DEFINE_CONST_FUN_OBJ_2 ( mp_builtin_hasattr_obj , mp_builtin_hasattr ) ;
2014-08-12 18:33:40 +01:00
// These are defined in terms of MicroPython API functions right away
2014-08-22 21:48:30 +01:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_id_obj , mp_obj_id ) ;
2014-08-12 18:33:40 +01:00
MP_DEFINE_CONST_FUN_OBJ_1 ( mp_builtin_len_obj , mp_obj_len ) ;
2014-04-05 23:18:19 +01:00
MP_DEFINE_CONST_FUN_OBJ_0 ( mp_builtin_globals_obj , mp_globals_get ) ;
MP_DEFINE_CONST_FUN_OBJ_0 ( mp_builtin_locals_obj , mp_locals_get ) ;