summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/bc.h42
-rw-r--r--py/mpconfig.h58
-rw-r--r--py/obj.c30
-rw-r--r--py/obj.h2
-rw-r--r--py/objcode.c65
-rw-r--r--py/objint_longlong.c16
-rw-r--r--py/showbc.c14
7 files changed, 200 insertions, 27 deletions
diff --git a/py/bc.h b/py/bc.h
index 718ba4a684..f24510ea7e 100644
--- a/py/bc.h
+++ b/py/bc.h
@@ -308,25 +308,35 @@ static inline void mp_module_context_alloc_tables(mp_module_context_t *context,
#endif
}
+typedef struct _mp_code_lineinfo_t {
+ size_t bc_increment;
+ size_t line_increment;
+} mp_code_lineinfo_t;
+
+static inline mp_code_lineinfo_t mp_bytecode_decode_lineinfo(const byte **line_info) {
+ mp_code_lineinfo_t result;
+ size_t c = (*line_info)[0];
+ if ((c & 0x80) == 0) {
+ // 0b0LLBBBBB encoding
+ result.bc_increment = c & 0x1f;
+ result.line_increment = c >> 5;
+ *line_info += 1;
+ } else {
+ // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
+ result.bc_increment = c & 0xf;
+ result.line_increment = ((c << 4) & 0x700) | (*line_info)[1];
+ *line_info += 2;
+ }
+ return result;
+}
+
static inline size_t mp_bytecode_get_source_line(const byte *line_info, const byte *line_info_top, size_t bc_offset) {
size_t source_line = 1;
while (line_info < line_info_top) {
- size_t c = *line_info;
- size_t b, l;
- if ((c & 0x80) == 0) {
- // 0b0LLBBBBB encoding
- b = c & 0x1f;
- l = c >> 5;
- line_info += 1;
- } else {
- // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
- b = c & 0xf;
- l = ((c << 4) & 0x700) | line_info[1];
- line_info += 2;
- }
- if (bc_offset >= b) {
- bc_offset -= b;
- source_line += l;
+ mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&line_info);
+ if (bc_offset >= decoded.bc_increment) {
+ bc_offset -= decoded.bc_increment;
+ source_line += decoded.line_increment;
} else {
// found source line corresponding to bytecode offset
break;
diff --git a/py/mpconfig.h b/py/mpconfig.h
index cf0538cae4..4c12762759 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -893,6 +893,64 @@ typedef double mp_float_t;
#define MICROPY_FULL_CHECKS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
#endif
+// Ports can choose to use timestamps based on 2000-01-01 or 1970-01-01
+// Default is timestamps based on 2000-01-01
+#if !defined(MICROPY_EPOCH_IS_2000) && !defined(MICROPY_EPOCH_IS_1970)
+#define MICROPY_EPOCH_IS_2000 (1)
+#define MICROPY_EPOCH_IS_1970 (0)
+#elif !defined(MICROPY_EPOCH_IS_1970)
+#define MICROPY_EPOCH_IS_1970 (1 - (MICROPY_EPOCH_IS_2000))
+#elif !defined(MICROPY_EPOCH_IS_2000)
+#define MICROPY_EPOCH_IS_2000 (1 - (MICROPY_EPOCH_IS_1970))
+#endif
+
+// To maintain reasonable compatibility with CPython on embedded systems,
+// and avoid breaking anytime soon, time functions are defined to work
+// at least between 1970 and 2099 (included) on any machine.
+//
+// Specific ports can enable extended date support
+// - after 2099 using MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND
+// - before 1970 using MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE
+// The largest possible range is year 1600 to year 3000
+//
+// By default, extended date support is only enabled for machines using 64 bit pointers,
+// but it can be enabled by specific ports
+#ifndef MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE
+#if MP_SSIZE_MAX > 2147483647
+#define MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE (1)
+#else
+#define MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE (0)
+#endif
+#endif
+
+// When support for dates <1970 is enabled, supporting >=2100 does not cost anything
+#ifndef MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND
+#define MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND (MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE)
+#endif
+
+// The type to be used to represent platform-specific timestamps depends on the choices above
+#define MICROPY_TIMESTAMP_IMPL_LONG_LONG (0)
+#define MICROPY_TIMESTAMP_IMPL_UINT (1)
+#define MICROPY_TIMESTAMP_IMPL_TIME_T (2)
+
+#ifndef MICROPY_TIMESTAMP_IMPL
+#if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE || MICROPY_EPOCH_IS_2000
+#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_LONG_LONG)
+#else
+#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_UINT)
+#endif
+#endif
+
+// `mp_timestamp_t` is the type that should be used by the port
+// to represent timestamps, and is referenced to the platform epoch
+#if MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_LONG_LONG
+typedef long long mp_timestamp_t;
+#elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_UINT
+typedef mp_uint_t mp_timestamp_t;
+#elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_TIME_T
+typedef time_t mp_timestamp_t;
+#endif
+
// Whether POSIX-semantics non-blocking streams are supported
#ifndef MICROPY_STREAMS_NON_BLOCK
#define MICROPY_STREAMS_NON_BLOCK (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
diff --git a/py/obj.c b/py/obj.c
index 1606ad5209..5867594607 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -314,6 +314,36 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
return val;
}
+#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
+mp_uint_t mp_obj_get_uint(mp_const_obj_t arg) {
+ if (!mp_obj_is_exact_type(arg, &mp_type_int)) {
+ mp_obj_t as_int = mp_unary_op(MP_UNARY_OP_INT_MAYBE, (mp_obj_t)arg);
+ if (as_int == MP_OBJ_NULL) {
+ mp_raise_TypeError_int_conversion(arg);
+ }
+ arg = as_int;
+ }
+ return mp_obj_int_get_uint_checked(arg);
+}
+
+long long mp_obj_get_ll(mp_const_obj_t arg) {
+ if (!mp_obj_is_exact_type(arg, &mp_type_int)) {
+ mp_obj_t as_int = mp_unary_op(MP_UNARY_OP_INT_MAYBE, (mp_obj_t)arg);
+ if (as_int == MP_OBJ_NULL) {
+ mp_raise_TypeError_int_conversion(arg);
+ }
+ arg = as_int;
+ }
+ if (mp_obj_is_small_int(arg)) {
+ return MP_OBJ_SMALL_INT_VALUE(arg);
+ } else {
+ long long res;
+ mp_obj_int_to_bytes_impl((mp_obj_t)arg, MP_ENDIANNESS_BIG, sizeof(res), (byte *)&res);
+ return res;
+ }
+}
+#endif
+
mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) {
if (mp_obj_is_int(arg)) {
return mp_obj_int_get_truncated(arg);
diff --git a/py/obj.h b/py/obj.h
index 0f87282a9f..a1df661ff0 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -1051,6 +1051,8 @@ static inline bool mp_obj_is_integer(mp_const_obj_t o) {
}
mp_int_t mp_obj_get_int(mp_const_obj_t arg);
+mp_uint_t mp_obj_get_uint(mp_const_obj_t arg);
+long long mp_obj_get_ll(mp_const_obj_t arg);
mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg);
bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value);
#if MICROPY_PY_BUILTINS_FLOAT
diff --git a/py/objcode.c b/py/objcode.c
index 9b98a69679..52df84d012 100644
--- a/py/objcode.c
+++ b/py/objcode.c
@@ -107,6 +107,67 @@ static mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) {
return o;
}
+static mp_obj_t code_colines_iter(mp_obj_t);
+static mp_obj_t code_colines_next(mp_obj_t);
+typedef struct _mp_obj_colines_iter_t {
+ mp_obj_base_t base;
+ mp_fun_1_t iternext;
+ const mp_raw_code_t *rc;
+ mp_uint_t bc;
+ mp_uint_t source_line;
+ const byte *ci;
+} mp_obj_colines_iter_t;
+
+static mp_obj_t code_colines_iter(mp_obj_t self_in) {
+ mp_obj_code_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_colines_iter_t *iter = mp_obj_malloc(mp_obj_colines_iter_t, &mp_type_polymorph_iter);
+ iter->iternext = code_colines_next;
+ iter->rc = self->rc;
+ iter->bc = 0;
+ iter->source_line = 1;
+ iter->ci = self->rc->prelude.line_info;
+ return MP_OBJ_FROM_PTR(iter);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(code_colines_obj, code_colines_iter);
+
+static mp_obj_t code_colines_next(mp_obj_t iter_in) {
+ mp_obj_colines_iter_t *iter = MP_OBJ_TO_PTR(iter_in);
+ const byte *ci_end = iter->rc->prelude.line_info_top;
+
+ mp_uint_t start = iter->bc;
+ mp_uint_t line_no = iter->source_line;
+ bool another = true;
+
+ while (another && iter->ci < ci_end) {
+ another = false;
+ mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&iter->ci);
+ iter->bc += decoded.bc_increment;
+ iter->source_line += decoded.line_increment;
+
+ if (decoded.bc_increment == 0) {
+ line_no = iter->source_line;
+ another = true;
+ } else if (decoded.line_increment == 0) {
+ another = true;
+ }
+ }
+
+ if (another) {
+ mp_uint_t prelude_size = (iter->rc->prelude.opcodes - (const byte *)iter->rc->fun_data);
+ mp_uint_t bc_end = iter->rc->fun_data_len - prelude_size;
+ if (iter->bc >= bc_end) {
+ return MP_OBJ_STOP_ITERATION;
+ } else {
+ iter->bc = bc_end;
+ }
+ }
+
+ mp_uint_t end = iter->bc;
+ mp_obj_t next[3] = {MP_OBJ_NEW_SMALL_INT(start), MP_OBJ_NEW_SMALL_INT(end), MP_OBJ_NEW_SMALL_INT(line_no)};
+
+ return mp_obj_new_tuple(MP_ARRAY_SIZE(next), next);
+}
+
static void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (dest[0] != MP_OBJ_NULL) {
// not load attribute
@@ -143,6 +204,10 @@ static void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
}
dest[0] = o->lnotab;
break;
+ case MP_QSTR_co_lines:
+ dest[0] = MP_OBJ_FROM_PTR(&code_colines_obj);
+ dest[1] = self_in;
+ break;
}
}
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 1940b81538..5b60eb65ad 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -295,6 +295,22 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
return mp_obj_int_get_truncated(self_in);
}
+mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) {
+ if (mp_obj_is_small_int(self_in)) {
+ if (MP_OBJ_SMALL_INT_VALUE(self_in) >= 0) {
+ return MP_OBJ_SMALL_INT_VALUE(self_in);
+ }
+ } else {
+ const mp_obj_int_t *self = self_in;
+ long long value = self->val;
+ mp_uint_t truncated = (mp_uint_t)value;
+ if (value >= 0 && (long long)truncated == value) {
+ return truncated;
+ }
+ }
+ mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word"));
+}
+
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) {
assert(mp_obj_is_exact_type(self_in, &mp_type_int));
diff --git a/py/showbc.c b/py/showbc.c
index 6913d18c1c..792fccd013 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -144,17 +144,9 @@ void mp_bytecode_print(const mp_print_t *print, const mp_raw_code_t *rc, size_t
mp_uint_t source_line = 1;
mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
for (const byte *ci = code_info; ci < line_info_top;) {
- if ((ci[0] & 0x80) == 0) {
- // 0b0LLBBBBB encoding
- bc += ci[0] & 0x1f;
- source_line += ci[0] >> 5;
- ci += 1;
- } else {
- // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
- bc += ci[0] & 0xf;
- source_line += ((ci[0] << 4) & 0x700) | ci[1];
- ci += 2;
- }
+ mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&ci);
+ bc += decoded.bc_increment;
+ source_line += decoded.line_increment;
mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
}
}