2013-12-17 18:27:24 +00:00
# include <stdint.h>
# include <stdlib.h>
# include <stdio.h>
# include <stdarg.h>
# include <string.h>
# include <assert.h>
# include "nlr.h"
# include "misc.h"
2013-12-21 18:17:45 +00:00
# include "mpconfig.h"
2014-01-04 15:57:35 +00:00
# include "mpqstr.h"
2013-12-21 18:17:45 +00:00
# include "obj.h"
# include "runtime0.h"
2013-12-17 18:27:24 +00:00
# include "runtime.h"
# include "map.h"
# include "builtin.h"
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
mp_obj_t mp_builtin___build_class__ ( int n_args , const mp_obj_t * args ) {
assert ( 2 < = n_args ) ;
2013-12-17 21:35:38 +00:00
// we differ from CPython: we set the new __locals__ object here
2014-01-03 14:03:48 +00:00
mp_map_t * old_locals = rt_locals_get ( ) ;
2014-01-09 20:57:50 +00:00
mp_obj_t class_locals = mp_obj_new_dict ( 0 ) ;
rt_locals_set ( mp_obj_dict_get_map ( class_locals ) ) ;
2013-12-17 21:35:38 +00:00
// call the class code
2014-01-08 11:47:55 +00:00
mp_obj_t cell = rt_call_function_1 ( args [ 0 ] , ( mp_obj_t ) 0xdeadbeef ) ;
2013-12-17 21:35:38 +00:00
// restore old __locals__ object
2014-01-03 14:03:48 +00:00
rt_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'
meta = ( mp_obj_t ) & mp_const_type ;
} 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
// (arguments must be backwards in the array)
mp_obj_t meta_args [ 3 ] ;
meta_args [ 2 ] = args [ 1 ] ; // class name
meta_args [ 1 ] = mp_obj_new_tuple ( n_args - 2 , args + 2 ) ; // tuple of bases
2014-01-09 20:57:50 +00:00
meta_args [ 0 ] = class_locals ; // dict of members
2014-01-08 11:47:55 +00:00
mp_obj_t new_class = rt_call_function_n ( meta , 3 , meta_args ) ;
// 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__ ) ;
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin___repl_print__ ( mp_obj_t o ) {
if ( o ! = mp_const_none ) {
mp_obj_print ( o ) ;
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
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_abs ( mp_obj_t o_in ) {
if ( MP_OBJ_IS_SMALL_INT ( o_in ) ) {
mp_small_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 ) ;
2013-12-17 21:35:38 +00:00
# if MICROPY_ENABLE_FLOAT
2013-12-21 18:17:45 +00:00
} else if ( MP_OBJ_IS_TYPE ( o_in , & float_type ) ) {
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
}
2013-12-21 18:17:45 +00:00
} else if ( MP_OBJ_IS_TYPE ( o_in , & complex_type ) ) {
mp_float_t real , imag ;
mp_obj_complex_get ( o_in , & real , & imag ) ;
return mp_obj_new_float ( machine_sqrt ( real * real + imag * imag ) ) ;
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
}
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_all ( mp_obj_t o_in ) {
mp_obj_t iterable = rt_getiter ( o_in ) ;
mp_obj_t item ;
while ( ( item = rt_iternext ( iterable ) ) ! = mp_const_stop_iteration ) {
2013-12-17 21:35:38 +00:00
if ( ! rt_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
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_any ( mp_obj_t o_in ) {
mp_obj_t iterable = rt_getiter ( o_in ) ;
mp_obj_t item ;
while ( ( item = rt_iternext ( iterable ) ) ! = mp_const_stop_iteration ) {
2013-12-17 21:35:38 +00:00
if ( rt_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
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_callable ( mp_obj_t o_in ) {
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
}
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_chr ( mp_obj_t o_in ) {
int ord = mp_obj_get_int ( o_in ) ;
2013-12-17 21:35:38 +00:00
if ( 0 < = ord & & ord < = 0x10ffff ) {
char * str = m_new ( char , 2 ) ;
str [ 0 ] = ord ;
str [ 1 ] = ' \0 ' ;
2013-12-29 19:33:23 +00:00
return mp_obj_new_str ( qstr_from_str_take ( str , 2 ) ) ;
2013-12-17 21:35:38 +00:00
} else {
2014-01-04 15:57:35 +00:00
nlr_jump ( mp_obj_new_exception_msg ( MP_QSTR_ValueError , " chr() arg not in range(0x110000) " ) ) ;
2013-12-17 18:27:24 +00:00
}
2013-12-17 21:35:38 +00:00
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_divmod ( mp_obj_t o1_in , mp_obj_t o2_in ) {
if ( MP_OBJ_IS_SMALL_INT ( o1_in ) & & MP_OBJ_IS_SMALL_INT ( o2_in ) ) {
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE ( o1_in ) ;
mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE ( o2_in ) ;
mp_obj_t revs_args [ 2 ] ;
revs_args [ 1 ] = MP_OBJ_NEW_SMALL_INT ( i1 / i2 ) ;
revs_args [ 0 ] = MP_OBJ_NEW_SMALL_INT ( i1 % i2 ) ;
2013-12-17 21:35:38 +00:00
return rt_build_tuple ( 2 , revs_args ) ;
} else {
2014-01-08 18:11:23 +00:00
nlr_jump ( mp_obj_new_exception_msg_varg ( MP_QSTR_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
}
}
2013-12-21 18:17:45 +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
2013-12-21 18:17:45 +00:00
static mp_obj_t mp_builtin_iter ( mp_obj_t o_in ) {
return rt_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 ) ;
mp_obj_t mp_builtin_len ( mp_obj_t o_in ) {
2014-01-10 11:25:03 +00:00
mp_obj_t len = mp_obj_len_maybe ( o_in ) ;
if ( len = = NULL ) {
2014-01-08 18:11:23 +00:00
nlr_jump ( mp_obj_new_exception_msg_varg ( MP_QSTR_TypeError , " object of type '%s' has no len() " , mp_obj_get_type_str ( o_in ) ) ) ;
2014-01-10 11:25:03 +00:00
} else {
return len ;
2013-12-17 18:27:24 +00:00
}
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_max ( int n_args , const mp_obj_t * args ) {
2013-12-17 21:35:38 +00:00
if ( n_args = = 1 ) {
// given an iterable
2013-12-21 18:17:45 +00:00
mp_obj_t iterable = rt_getiter ( args [ 0 ] ) ;
mp_obj_t max_obj = NULL ;
mp_obj_t item ;
while ( ( item = rt_iternext ( iterable ) ) ! = mp_const_stop_iteration ) {
if ( max_obj = = NULL | | mp_obj_less ( max_obj , item ) ) {
2013-12-17 21:35:38 +00:00
max_obj = item ;
}
2013-12-17 18:27:24 +00:00
}
2013-12-17 21:35:38 +00:00
if ( max_obj = = NULL ) {
2014-01-04 15:57:35 +00:00
nlr_jump ( mp_obj_new_exception_msg ( MP_QSTR_ValueError , " max() arg is an empty sequence " ) ) ;
2013-12-17 21:35:38 +00:00
}
return max_obj ;
2013-12-17 18:27:24 +00:00
} else {
2013-12-17 21:35:38 +00:00
// given many args
2013-12-21 18:17:45 +00:00
mp_obj_t max_obj = args [ 0 ] ;
2013-12-17 21:35:38 +00:00
for ( int i = 1 ; i < n_args ; i + + ) {
2013-12-21 18:17:45 +00:00
if ( mp_obj_less ( max_obj , args [ i ] ) ) {
2013-12-17 21:35:38 +00:00
max_obj = args [ i ] ;
}
}
return max_obj ;
2013-12-17 18:27:24 +00:00
}
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_min ( int n_args , const mp_obj_t * args ) {
2013-12-17 21:35:38 +00:00
if ( n_args = = 1 ) {
// given an iterable
2013-12-21 18:17:45 +00:00
mp_obj_t iterable = rt_getiter ( args [ 0 ] ) ;
mp_obj_t min_obj = NULL ;
mp_obj_t item ;
while ( ( item = rt_iternext ( iterable ) ) ! = mp_const_stop_iteration ) {
if ( min_obj = = NULL | | mp_obj_less ( item , min_obj ) ) {
2013-12-17 21:35:38 +00:00
min_obj = item ;
}
}
if ( min_obj = = NULL ) {
2014-01-04 15:57:35 +00:00
nlr_jump ( mp_obj_new_exception_msg ( MP_QSTR_ValueError , " min() arg is an empty sequence " ) ) ;
2013-12-17 21:35:38 +00:00
}
return min_obj ;
} else {
// given many args
2013-12-21 18:17:45 +00:00
mp_obj_t min_obj = args [ 0 ] ;
2013-12-17 21:35:38 +00:00
for ( int i = 1 ; i < n_args ; i + + ) {
2013-12-21 18:17:45 +00:00
if ( mp_obj_less ( args [ i ] , min_obj ) ) {
2013-12-17 21:35:38 +00:00
min_obj = args [ i ] ;
}
}
return min_obj ;
}
}
2013-12-17 18:27:24 +00:00
2013-12-21 18:38:03 +00:00
static mp_obj_t mp_builtin_next ( mp_obj_t o ) {
mp_obj_t ret = rt_iternext ( o ) ;
if ( ret = = mp_const_stop_iteration ) {
2014-01-04 15:57:35 +00:00
nlr_jump ( mp_obj_new_exception ( MP_QSTR_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 ) ;
mp_obj_t mp_builtin_ord ( mp_obj_t o_in ) {
const char * str = qstr_str ( mp_obj_get_qstr ( o_in ) ) ;
2013-12-17 21:35:38 +00:00
if ( strlen ( str ) = = 1 ) {
2013-12-21 18:17:45 +00:00
return mp_obj_new_int ( str [ 0 ] ) ;
2013-12-17 21:35:38 +00:00
} else {
2014-01-08 18:11:23 +00:00
nlr_jump ( mp_obj_new_exception_msg_varg ( MP_QSTR_TypeError , " ord() expected a character, but string of length %d found " , strlen ( str ) ) ) ;
2013-12-17 21:35:38 +00:00
}
}
2013-12-17 18:27:24 +00:00
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_pow ( int n_args , const mp_obj_t * args ) {
2013-12-17 21:35:38 +00:00
switch ( n_args ) {
case 2 : return rt_binary_op ( RT_BINARY_OP_POWER , args [ 0 ] , args [ 1 ] ) ;
case 3 : return rt_binary_op ( RT_BINARY_OP_MODULO , rt_binary_op ( RT_BINARY_OP_POWER , args [ 0 ] , args [ 1 ] ) , args [ 2 ] ) ; // TODO optimise...
2014-01-08 18:11:23 +00:00
default : nlr_jump ( mp_obj_new_exception_msg_varg ( MP_QSTR_TypeError , " pow expected at most 3 arguments, got %d " , n_args ) ) ;
2013-12-17 21:35:38 +00:00
}
}
2013-12-17 18:27:24 +00:00
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_print ( int n_args , const mp_obj_t * args ) {
2013-12-17 21:35:38 +00:00
for ( int i = 0 ; i < n_args ; i + + ) {
if ( i > 0 ) {
printf ( " " ) ;
}
2013-12-21 18:17:45 +00:00
if ( MP_OBJ_IS_TYPE ( args [ i ] , & str_type ) ) {
2013-12-17 21:35:38 +00:00
// special case, print string raw
2013-12-21 18:17:45 +00:00
printf ( " %s " , qstr_str ( mp_obj_str_get ( args [ i ] ) ) ) ;
2013-12-17 21:35:38 +00:00
} else {
// print the object Python style
2013-12-21 18:17:45 +00:00
mp_obj_print ( args [ i ] ) ;
2013-12-17 21:35:38 +00:00
}
}
printf ( " \n " ) ;
2013-12-21 18:17:45 +00:00
return mp_const_none ;
2013-12-17 18:27:24 +00:00
}
2013-12-21 18:17:45 +00:00
mp_obj_t mp_builtin_range ( int n_args , const mp_obj_t * args ) {
2013-12-17 18:27:24 +00:00
switch ( n_args ) {
2013-12-21 18:17:45 +00:00
case 1 : return mp_obj_new_range ( 0 , mp_obj_get_int ( args [ 0 ] ) , 1 ) ;
case 2 : return mp_obj_new_range ( mp_obj_get_int ( args [ 0 ] ) , mp_obj_get_int ( args [ 1 ] ) , 1 ) ;
case 3 : return mp_obj_new_range ( mp_obj_get_int ( args [ 0 ] ) , mp_obj_get_int ( args [ 1 ] ) , mp_obj_get_int ( args [ 2 ] ) ) ;
2014-01-08 18:11:23 +00:00
default : nlr_jump ( mp_obj_new_exception_msg_varg ( MP_QSTR_TypeError , " range expected at most 3 arguments, got %d " , n_args ) ) ;
2013-12-21 18:17:45 +00:00
}
}
mp_obj_t mp_builtin_sum ( int n_args , const mp_obj_t * args ) {
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 ;
2013-12-17 21:35:38 +00:00
case 2 : value = args [ 1 ] ; break ;
2014-01-08 18:11:23 +00:00
default : nlr_jump ( mp_obj_new_exception_msg_varg ( MP_QSTR_TypeError , " sum expected at most 2 arguments, got %d " , n_args ) ) ;
2013-12-17 21:35:38 +00:00
}
2013-12-21 18:17:45 +00:00
mp_obj_t iterable = rt_getiter ( args [ 0 ] ) ;
mp_obj_t item ;
while ( ( item = rt_iternext ( iterable ) ) ! = mp_const_stop_iteration ) {
2013-12-17 21:35:38 +00:00
value = rt_binary_op ( RT_BINARY_OP_ADD , value , item ) ;
}
return value ;
}