blob: 7d0122c8fef142393eb0837bcf4a8c27bf9d5413 [file] [log] [blame]
Damien660365e2013-12-17 18:27:24 +00001#include <stdint.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <stdarg.h>
5#include <assert.h>
6
7#include "nlr.h"
8#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
Damien Georgeeb7bfcb2014-01-04 15:57:35 +000010#include "mpqstr.h"
Damien660365e2013-12-17 18:27:24 +000011#include "obj.h"
Damiend99b0522013-12-21 18:17:45 +000012#include "runtime0.h"
13#include "runtime.h"
14#include "map.h"
Damien660365e2013-12-17 18:27:24 +000015
Damien Georgeb97669a2014-01-08 11:47:55 +000016mp_obj_t mp_obj_get_type(mp_obj_t o_in) {
17 if (MP_OBJ_IS_SMALL_INT(o_in)) {
18 return (mp_obj_t)&int_type;
19 } else {
20 mp_obj_base_t *o = o_in;
21 return (mp_obj_t)o->type;
22 }
23}
24
Damiend99b0522013-12-21 18:17:45 +000025const char *mp_obj_get_type_str(mp_obj_t o_in) {
26 if (MP_OBJ_IS_SMALL_INT(o_in)) {
Damien660365e2013-12-17 18:27:24 +000027 return "int";
28 } else {
Damiend99b0522013-12-21 18:17:45 +000029 mp_obj_base_t *o = o_in;
30 return o->type->name;
Damien660365e2013-12-17 18:27:24 +000031 }
32}
33
34void printf_wrapper(void *env, const char *fmt, ...) {
35 va_list args;
36 va_start(args, fmt);
37 vprintf(fmt, args);
38 va_end(args);
39}
40
Damiend99b0522013-12-21 18:17:45 +000041void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
42 if (MP_OBJ_IS_SMALL_INT(o_in)) {
43 print(env, "%d", (int)MP_OBJ_SMALL_INT_VALUE(o_in));
Damien660365e2013-12-17 18:27:24 +000044 } else {
Damiend99b0522013-12-21 18:17:45 +000045 mp_obj_base_t *o = o_in;
46 if (o->type->print != NULL) {
47 o->type->print(print, env, o_in);
48 } else {
49 print(env, "<%s>", o->type->name);
Damien660365e2013-12-17 18:27:24 +000050 }
51 }
52}
53
Damiend99b0522013-12-21 18:17:45 +000054void mp_obj_print(mp_obj_t o_in) {
55 mp_obj_print_helper(printf_wrapper, NULL, o_in);
Damien660365e2013-12-17 18:27:24 +000056}
57
Damiend99b0522013-12-21 18:17:45 +000058bool mp_obj_is_callable(mp_obj_t o_in) {
59 if (MP_OBJ_IS_SMALL_INT(o_in)) {
Damien660365e2013-12-17 18:27:24 +000060 return false;
61 } else {
Damiend99b0522013-12-21 18:17:45 +000062 mp_obj_base_t *o = o_in;
63 return o->type->call_n != NULL;
Damien660365e2013-12-17 18:27:24 +000064 }
65}
66
Damiend99b0522013-12-21 18:17:45 +000067machine_int_t mp_obj_hash(mp_obj_t o_in) {
68 if (o_in == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +000069 return 0; // needs to hash to same as the integer 0, since False==0
Damiend99b0522013-12-21 18:17:45 +000070 } else if (o_in == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +000071 return 1; // needs to hash to same as the integer 1, since True==1
Damiend99b0522013-12-21 18:17:45 +000072 } else if (MP_OBJ_IS_SMALL_INT(o_in)) {
73 return MP_OBJ_SMALL_INT_VALUE(o_in);
74 } else if (MP_OBJ_IS_TYPE(o_in, &none_type)) {
Damien660365e2013-12-17 18:27:24 +000075 return (machine_int_t)o_in;
Damiend99b0522013-12-21 18:17:45 +000076 } else if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
77 return mp_obj_str_get(o_in);
Damien660365e2013-12-17 18:27:24 +000078 } else {
79 assert(0);
80 return 0;
81 }
82}
83
84// this function implements the '==' operator (and so the inverse of '!=')
85// from the python language reference:
86// "The objects need not have the same type. If both are numbers, they are converted
87// to a common type. Otherwise, the == and != operators always consider objects of
88// different types to be unequal."
89// note also that False==0 and True==1 are true expressions
Damiend99b0522013-12-21 18:17:45 +000090bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
Damien660365e2013-12-17 18:27:24 +000091 if (o1 == o2) {
92 return true;
Damiend99b0522013-12-21 18:17:45 +000093 } else if (MP_OBJ_IS_SMALL_INT(o1) || MP_OBJ_IS_SMALL_INT(o2)) {
94 if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) {
Damien660365e2013-12-17 18:27:24 +000095 return false;
96 } else {
Damiend99b0522013-12-21 18:17:45 +000097 if (MP_OBJ_IS_SMALL_INT(o2)) {
98 mp_obj_t temp = o1; o1 = o2; o2 = temp;
Damien660365e2013-12-17 18:27:24 +000099 }
100 // o1 is the SMALL_INT, o2 is not
Damiend99b0522013-12-21 18:17:45 +0000101 mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o1);
102 if (o2 == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +0000103 return val == 0;
Damiend99b0522013-12-21 18:17:45 +0000104 } else if (o2 == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000105 return val == 1;
106 } else {
107 return false;
108 }
109 }
Damiend99b0522013-12-21 18:17:45 +0000110 } else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) {
111 return mp_obj_str_get(o1) == mp_obj_str_get(o2);
Damien660365e2013-12-17 18:27:24 +0000112 } else {
113 assert(0);
114 return false;
115 }
116}
117
Damiend99b0522013-12-21 18:17:45 +0000118bool mp_obj_less(mp_obj_t o1, mp_obj_t o2) {
119 if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) {
120 mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1);
121 mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2);
Damiena3dcd9e2013-12-17 21:35:38 +0000122 return i1 < i2;
123 } else {
124 assert(0);
125 return false;
126 }
127}
128
Damiend99b0522013-12-21 18:17:45 +0000129machine_int_t mp_obj_get_int(mp_obj_t arg) {
130 if (arg == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +0000131 return 0;
Damiend99b0522013-12-21 18:17:45 +0000132 } else if (arg == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000133 return 1;
Damiend99b0522013-12-21 18:17:45 +0000134 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
135 return MP_OBJ_SMALL_INT_VALUE(arg);
Damien George71c51812014-01-04 20:21:15 +0000136#if MICROPY_ENABLE_FLOAT
137 } else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
138 // TODO work out if this should be floor, ceil or trunc
139 return (machine_int_t)mp_obj_float_get(arg);
140#endif
Damien660365e2013-12-17 18:27:24 +0000141 } else {
Damien George71c51812014-01-04 20:21:15 +0000142 nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg)));
Damien660365e2013-12-17 18:27:24 +0000143 }
144}
145
146#if MICROPY_ENABLE_FLOAT
Damiend99b0522013-12-21 18:17:45 +0000147machine_float_t mp_obj_get_float(mp_obj_t arg) {
148 if (arg == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +0000149 return 0;
Damiend99b0522013-12-21 18:17:45 +0000150 } else if (arg == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000151 return 1;
Damiend99b0522013-12-21 18:17:45 +0000152 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
153 return MP_OBJ_SMALL_INT_VALUE(arg);
154 } else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
155 return mp_obj_float_get(arg);
Damien660365e2013-12-17 18:27:24 +0000156 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000157 nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
Damien660365e2013-12-17 18:27:24 +0000158 }
159}
160
Damiend99b0522013-12-21 18:17:45 +0000161void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
162 if (arg == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +0000163 *real = 0;
164 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000165 } else if (arg == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000166 *real = 1;
167 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000168 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
169 *real = MP_OBJ_SMALL_INT_VALUE(arg);
Damien660365e2013-12-17 18:27:24 +0000170 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000171 } else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
172 *real = mp_obj_float_get(arg);
Damien660365e2013-12-17 18:27:24 +0000173 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000174 } else if (MP_OBJ_IS_TYPE(arg, &complex_type)) {
175 mp_obj_complex_get(arg, real, imag);
Damien660365e2013-12-17 18:27:24 +0000176 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000177 nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
Damien660365e2013-12-17 18:27:24 +0000178 }
179}
180#endif
181
Damiend99b0522013-12-21 18:17:45 +0000182qstr mp_obj_get_qstr(mp_obj_t arg) {
183 if (MP_OBJ_IS_TYPE(arg, &str_type)) {
184 return mp_obj_str_get(arg);
Damien660365e2013-12-17 18:27:24 +0000185 } else {
186 assert(0);
187 return 0;
188 }
189}
190
Damiend99b0522013-12-21 18:17:45 +0000191mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) {
192 if (MP_OBJ_IS_TYPE(o_in, &tuple_type) || MP_OBJ_IS_TYPE(o_in, &list_type)) {
193 uint seq_len;
194 mp_obj_t *seq_items;
195 if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
196 mp_obj_tuple_get(o_in, &seq_len, &seq_items);
197 } else {
198 mp_obj_list_get(o_in, &seq_len, &seq_items);
Damien660365e2013-12-17 18:27:24 +0000199 }
Damiend99b0522013-12-21 18:17:45 +0000200 if (seq_len != n) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000201 nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len));
Damiend99b0522013-12-21 18:17:45 +0000202 }
203 return seq_items;
Damien660365e2013-12-17 18:27:24 +0000204 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000205 nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in)));
Damien660365e2013-12-17 18:27:24 +0000206 }
207}
208
Damiend99b0522013-12-21 18:17:45 +0000209uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index) {
210 // TODO False and True are considered 0 and 1 for indexing purposes
211 if (MP_OBJ_IS_SMALL_INT(index)) {
212 int i = MP_OBJ_SMALL_INT_VALUE(index);
213 if (i < 0) {
214 i += len;
215 }
216 if (i < 0 || i >= len) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000217 nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_IndexError, "%s index out of range", type->name));
Damiend99b0522013-12-21 18:17:45 +0000218 }
219 return i;
220 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000221 nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index)));
Damien660365e2013-12-17 18:27:24 +0000222 }
Damien660365e2013-12-17 18:27:24 +0000223}