blob: 2b834ffe437d1071b1232d5b78adeedc0f9907c6 [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
Damiend99b0522013-12-21 18:17:45 +000016mp_obj_t mp_obj_new_int(machine_int_t value) {
17 return MP_OBJ_NEW_SMALL_INT(value);
Damien660365e2013-12-17 18:27:24 +000018}
19
Damiend99b0522013-12-21 18:17:45 +000020const char *mp_obj_get_type_str(mp_obj_t o_in) {
21 if (MP_OBJ_IS_SMALL_INT(o_in)) {
Damien660365e2013-12-17 18:27:24 +000022 return "int";
23 } else {
Damiend99b0522013-12-21 18:17:45 +000024 mp_obj_base_t *o = o_in;
25 return o->type->name;
Damien660365e2013-12-17 18:27:24 +000026 }
27}
28
29void printf_wrapper(void *env, const char *fmt, ...) {
30 va_list args;
31 va_start(args, fmt);
32 vprintf(fmt, args);
33 va_end(args);
34}
35
Damiend99b0522013-12-21 18:17:45 +000036void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
37 if (MP_OBJ_IS_SMALL_INT(o_in)) {
38 print(env, "%d", (int)MP_OBJ_SMALL_INT_VALUE(o_in));
Damien660365e2013-12-17 18:27:24 +000039 } else {
Damiend99b0522013-12-21 18:17:45 +000040 mp_obj_base_t *o = o_in;
41 if (o->type->print != NULL) {
42 o->type->print(print, env, o_in);
43 } else {
44 print(env, "<%s>", o->type->name);
Damien660365e2013-12-17 18:27:24 +000045 }
46 }
47}
48
Damiend99b0522013-12-21 18:17:45 +000049void mp_obj_print(mp_obj_t o_in) {
50 mp_obj_print_helper(printf_wrapper, NULL, o_in);
Damien660365e2013-12-17 18:27:24 +000051}
52
Damiend99b0522013-12-21 18:17:45 +000053bool mp_obj_is_callable(mp_obj_t o_in) {
54 if (MP_OBJ_IS_SMALL_INT(o_in)) {
Damien660365e2013-12-17 18:27:24 +000055 return false;
56 } else {
Damiend99b0522013-12-21 18:17:45 +000057 mp_obj_base_t *o = o_in;
58 return o->type->call_n != NULL;
Damien660365e2013-12-17 18:27:24 +000059 }
60}
61
Damiend99b0522013-12-21 18:17:45 +000062machine_int_t mp_obj_hash(mp_obj_t o_in) {
63 if (o_in == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +000064 return 0; // needs to hash to same as the integer 0, since False==0
Damiend99b0522013-12-21 18:17:45 +000065 } else if (o_in == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +000066 return 1; // needs to hash to same as the integer 1, since True==1
Damiend99b0522013-12-21 18:17:45 +000067 } else if (MP_OBJ_IS_SMALL_INT(o_in)) {
68 return MP_OBJ_SMALL_INT_VALUE(o_in);
69 } else if (MP_OBJ_IS_TYPE(o_in, &none_type)) {
Damien660365e2013-12-17 18:27:24 +000070 return (machine_int_t)o_in;
Damiend99b0522013-12-21 18:17:45 +000071 } else if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
72 return mp_obj_str_get(o_in);
Damien660365e2013-12-17 18:27:24 +000073 } else {
74 assert(0);
75 return 0;
76 }
77}
78
79// this function implements the '==' operator (and so the inverse of '!=')
80// from the python language reference:
81// "The objects need not have the same type. If both are numbers, they are converted
82// to a common type. Otherwise, the == and != operators always consider objects of
83// different types to be unequal."
84// note also that False==0 and True==1 are true expressions
Damiend99b0522013-12-21 18:17:45 +000085bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
Damien660365e2013-12-17 18:27:24 +000086 if (o1 == o2) {
87 return true;
Damiend99b0522013-12-21 18:17:45 +000088 } else if (MP_OBJ_IS_SMALL_INT(o1) || MP_OBJ_IS_SMALL_INT(o2)) {
89 if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) {
Damien660365e2013-12-17 18:27:24 +000090 return false;
91 } else {
Damiend99b0522013-12-21 18:17:45 +000092 if (MP_OBJ_IS_SMALL_INT(o2)) {
93 mp_obj_t temp = o1; o1 = o2; o2 = temp;
Damien660365e2013-12-17 18:27:24 +000094 }
95 // o1 is the SMALL_INT, o2 is not
Damiend99b0522013-12-21 18:17:45 +000096 mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o1);
97 if (o2 == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +000098 return val == 0;
Damiend99b0522013-12-21 18:17:45 +000099 } else if (o2 == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000100 return val == 1;
101 } else {
102 return false;
103 }
104 }
Damiend99b0522013-12-21 18:17:45 +0000105 } else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) {
106 return mp_obj_str_get(o1) == mp_obj_str_get(o2);
Damien660365e2013-12-17 18:27:24 +0000107 } else {
108 assert(0);
109 return false;
110 }
111}
112
Damiend99b0522013-12-21 18:17:45 +0000113bool mp_obj_less(mp_obj_t o1, mp_obj_t o2) {
114 if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) {
115 mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1);
116 mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2);
Damiena3dcd9e2013-12-17 21:35:38 +0000117 return i1 < i2;
118 } else {
119 assert(0);
120 return false;
121 }
122}
123
Damiend99b0522013-12-21 18:17:45 +0000124machine_int_t mp_obj_get_int(mp_obj_t arg) {
125 if (arg == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +0000126 return 0;
Damiend99b0522013-12-21 18:17:45 +0000127 } else if (arg == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000128 return 1;
Damiend99b0522013-12-21 18:17:45 +0000129 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
130 return MP_OBJ_SMALL_INT_VALUE(arg);
Damien660365e2013-12-17 18:27:24 +0000131 } else {
132 assert(0);
133 return 0;
134 }
135}
136
137#if MICROPY_ENABLE_FLOAT
Damiend99b0522013-12-21 18:17:45 +0000138machine_float_t mp_obj_get_float(mp_obj_t arg) {
139 if (arg == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +0000140 return 0;
Damiend99b0522013-12-21 18:17:45 +0000141 } else if (arg == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000142 return 1;
Damiend99b0522013-12-21 18:17:45 +0000143 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
144 return MP_OBJ_SMALL_INT_VALUE(arg);
145 } else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
146 return mp_obj_float_get(arg);
Damien660365e2013-12-17 18:27:24 +0000147 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000148 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 +0000149 }
150}
151
Damiend99b0522013-12-21 18:17:45 +0000152void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
153 if (arg == mp_const_false) {
Damien660365e2013-12-17 18:27:24 +0000154 *real = 0;
155 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000156 } else if (arg == mp_const_true) {
Damien660365e2013-12-17 18:27:24 +0000157 *real = 1;
158 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000159 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
160 *real = MP_OBJ_SMALL_INT_VALUE(arg);
Damien660365e2013-12-17 18:27:24 +0000161 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000162 } else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
163 *real = mp_obj_float_get(arg);
Damien660365e2013-12-17 18:27:24 +0000164 *imag = 0;
Damiend99b0522013-12-21 18:17:45 +0000165 } else if (MP_OBJ_IS_TYPE(arg, &complex_type)) {
166 mp_obj_complex_get(arg, real, imag);
Damien660365e2013-12-17 18:27:24 +0000167 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000168 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 +0000169 }
170}
171#endif
172
Damiend99b0522013-12-21 18:17:45 +0000173qstr mp_obj_get_qstr(mp_obj_t arg) {
174 if (MP_OBJ_IS_TYPE(arg, &str_type)) {
175 return mp_obj_str_get(arg);
Damien660365e2013-12-17 18:27:24 +0000176 } else {
177 assert(0);
178 return 0;
179 }
180}
181
Damiend99b0522013-12-21 18:17:45 +0000182mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) {
183 if (MP_OBJ_IS_TYPE(o_in, &tuple_type) || MP_OBJ_IS_TYPE(o_in, &list_type)) {
184 uint seq_len;
185 mp_obj_t *seq_items;
186 if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
187 mp_obj_tuple_get(o_in, &seq_len, &seq_items);
188 } else {
189 mp_obj_list_get(o_in, &seq_len, &seq_items);
Damien660365e2013-12-17 18:27:24 +0000190 }
Damiend99b0522013-12-21 18:17:45 +0000191 if (seq_len != n) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000192 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 +0000193 }
194 return seq_items;
Damien660365e2013-12-17 18:27:24 +0000195 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000196 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 +0000197 }
198}
199
Damiend99b0522013-12-21 18:17:45 +0000200uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index) {
201 // TODO False and True are considered 0 and 1 for indexing purposes
202 if (MP_OBJ_IS_SMALL_INT(index)) {
203 int i = MP_OBJ_SMALL_INT_VALUE(index);
204 if (i < 0) {
205 i += len;
206 }
207 if (i < 0 || i >= len) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000208 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 +0000209 }
210 return i;
211 } else {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000212 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 +0000213 }
Damien660365e2013-12-17 18:27:24 +0000214}