mirror of https://github.com/arendst/Tasmota.git
Berry improve `int64` constructor (#22172)
This commit is contained in:
parent
5d0cc8144a
commit
3f56ab68ad
|
@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Berry virtual Energy driver (#22134)
|
||||
- Support for RX8010 RTC as used in IOTTIMER (#21376)
|
||||
- ESP8266 experimental support for second I2C bus
|
||||
- Berry improve `int64` constructor
|
||||
|
||||
### Breaking Changed
|
||||
|
||||
|
|
|
@ -547,7 +547,7 @@ void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr)
|
|||
}
|
||||
|
||||
// buf_impl * bytes_realloc(bvm *vm, buf_impl *oldbuf, int32_t size)
|
||||
void bytes_realloc(bvm *vm, buf_impl * attr, int32_t size)
|
||||
void bytes_realloc(bvm *vm, buf_impl * attr, size_t size)
|
||||
{
|
||||
m_assert_not_readlonly(vm, attr);
|
||||
if (!attr->fixed && size < 4) { size = 4; }
|
||||
|
|
|
@ -110,7 +110,7 @@ struct bvm {
|
|||
struct bgc gc;
|
||||
bctypefunc ctypefunc; /* handler to ctype_func */
|
||||
bbyte compopt; /* compilation options */
|
||||
int32_t bytesmaxsize; /* max allowed size for bytes() object, default 32kb but can be increased */
|
||||
size_t bytesmaxsize; /* max allowed size for bytes() object, default 32kb but can be increased */
|
||||
bobshook obshook;
|
||||
bmicrosfnct microsfnct; /* fucntion to get time as a microsecond resolution */
|
||||
#if BE_USE_PERF_COUNTERS
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
# tests for int64 support (for int32 internal int representation)
|
||||
|
||||
assert(int(int64()) == 0)
|
||||
assert(str(int64()) == "0")
|
||||
assert(int(int64(10)) == 10)
|
||||
assert(str(int64(10)) == "10")
|
||||
assert(int(int64(-5)) == -5)
|
||||
assert(str(int64(-5)) == "-5")
|
||||
|
||||
# extended constructor
|
||||
assert(int64(35).tostring() == "35")
|
||||
assert(int64(3.5).tostring() == "3")
|
||||
assert(int64("35").tostring() == "35")
|
||||
assert(int64("20000000000").tostring() == "20000000000")
|
||||
assert(int64(true).tostring() == "1")
|
||||
assert(int64(false).tostring() == "0")
|
||||
assert(int64(int64(42)).tostring() == "42")
|
||||
# invalid
|
||||
assert(int64("").tostring() == "0")
|
||||
assert(int64(nil).tostring() == "0")
|
||||
|
||||
# testing large numbers
|
||||
assert(str(int64.fromu32(0xFFFFFFFF, 0x7FFFFFFF)) == "9223372036854775807") # max positive number
|
||||
assert(str(int64.fromu32(0x00000000, 0x80000000)) == "-9223372036854775808")
|
||||
assert(str(int64.fromu32(10,10)) == "42949672970")
|
||||
|
||||
# addition
|
||||
assert(str(int64(10) + int64(20)) == "30")
|
||||
assert(str(int64(10) + int64(-20)) == "-10")
|
||||
assert(str(int64() + int64()) == "0")
|
||||
assert(str(int64(10) + 0) == "10") # special case, do not crash if null
|
||||
|
||||
# substraction
|
||||
assert(str(int64(10) - int64(20)) == "-10")
|
||||
assert(str(int64(10) - int64(-20)) == "30")
|
||||
assert(str(int64() - int64()) == "0")
|
||||
assert(str(int64(10) - 0) == "10") # special case, do not crash if null
|
||||
|
||||
# neg
|
||||
assert(str(-int64(10)) == "-10")
|
||||
assert(str(-int64(-10)) == "10")
|
||||
assert(str(-int64()) == "0")
|
||||
|
||||
# multiplication
|
||||
assert(str(int64(10) * int64(20)) == "200")
|
||||
assert(str(int64(10) * int64(-20)) == "-200")
|
||||
assert(str(int64() * int64()) == "0")
|
||||
assert(str(int64(10) * 0) == "0") # special case, do not crash if null
|
||||
|
||||
# division
|
||||
assert(str(int64(100) / int64(20)) == "5")
|
||||
assert(str(int64(100) / int64(-20)) == "-5")
|
||||
|
||||
# modulus
|
||||
assert(str(int64(102) % int64(10)) == "2")
|
||||
|
||||
# equals
|
||||
assert((int64(10) == int64(10)) == true)
|
||||
assert((int64(10) == int64(20)) == false)
|
||||
assert((int64(10) == int64()) == false)
|
||||
assert((int64(0) == int64()) == true)
|
||||
assert((int64(0) == 0) == true)
|
||||
assert((int64(10) == 0) == false)
|
||||
|
||||
# unequals
|
||||
assert((int64(10) != int64(10)) == false)
|
||||
assert((int64(10) != int64(20)) == true)
|
||||
assert((int64(10) != int64()) == true)
|
||||
assert((int64(0) != int64()) == false)
|
||||
assert((int64(0) != 0) == false)
|
||||
assert((int64(10) != 0) == true)
|
||||
|
||||
# >
|
||||
assert((int64(10) > int64(10)) == false)
|
||||
assert((int64(10) > int64(20)) == false)
|
||||
assert((int64(20) > int64(10)) == true)
|
||||
assert((int64(10) > 0) == true)
|
||||
# >=
|
||||
assert((int64(10) >= int64(10)) == true)
|
||||
assert((int64(10) >= int64(20)) == false)
|
||||
assert((int64(20) >= int64(10)) == true)
|
||||
assert((int64(10) >= 0) == true)
|
||||
|
||||
# <
|
||||
assert((int64(10) < int64(10)) == false)
|
||||
assert((int64(10) < int64(20)) == true)
|
||||
assert((int64(20) < int64(10)) == false)
|
||||
assert((int64(10) < 0) == false)
|
||||
# <=
|
||||
assert((int64(10) <= int64(10)) == true)
|
||||
assert((int64(10) <= int64(20)) == true)
|
||||
assert((int64(20) <= int64(10)) == false)
|
||||
assert((int64(10) <= 0) == false)
|
||||
|
||||
# tobytes
|
||||
assert(int64().tobytes() == bytes("0000000000000000"))
|
||||
assert(int64(10).tobytes() == bytes("0A00000000000000"))
|
||||
a = int64.fromu32(0xFFFFFFFF, 0x7FFFFFFF) # max positive number
|
||||
assert(a.tobytes() == bytes("FFFFFFFFFFFFFF7F"))
|
||||
a = int64.fromu32(0x00000000, 0x80000000)
|
||||
assert(a.tobytes() == bytes("0000000000000080"))
|
||||
assert(int64(-1).tobytes() == bytes("FFFFFFFFFFFFFFFF"))
|
||||
|
||||
# frombytes
|
||||
assert(int64.frombytes(bytes("0A00000000000000"), 0) == bytes("0A00000000000000")) # with implicit index 0
|
||||
assert(int64.frombytes(bytes("0A00000000000000")) == bytes("0A00000000000000"))
|
||||
assert(int64.frombytes(bytes("0A00000000000000"), 1) == bytes("0000000000000000")) # index 1 and incomplete (7 bytes)
|
||||
|
||||
assert(int64.frombytes(bytes("00FFFFFFFFFFFFFFFF"), 1) == bytes("FFFFFFFFFFFFFFFF")) # index 1 and incomplete (7 bytes)
|
||||
assert(int64.frombytes(bytes("00FFFFFFFFFFFFFFFF"), -2) == bytes("FFFF000000000000")) # from end
|
||||
assert(int64.frombytes(bytes("")) == bytes("0000000000000000")) # empty
|
||||
assert(int64.frombytes(bytes(""),4) == bytes("0000000000000000")) # empty with wrong index
|
||||
|
||||
# fromu32
|
||||
assert(int64.fromu32(0).tobytes() == bytes("0000000000000000"))
|
||||
assert(int64.fromu32(0xFFFFFFFF).tobytes() == bytes("FFFFFFFF00000000"))
|
||||
assert(int64.fromu32(0xFFFFFFFF, 1).tobytes() == bytes("FFFFFFFF01000000"))
|
||||
assert(int64.fromu32(-1, 1).tobytes() == bytes("FFFFFFFF01000000"))
|
||||
assert(int64.fromu32(-1, -1).tobytes() == bytes("FFFFFFFFFFFFFFFF"))
|
||||
|
||||
# fromfloat
|
||||
assert(int64.fromfloat(3.5).tostring() == "3")
|
||||
assert(int64.fromfloat(-3.5).tostring() == "-3")
|
||||
assert(int64.fromfloat(2e10).tostring() == "20000000000") # 20000000000 does not fit in 32 bits
|
||||
|
||||
# toint64, supports int, float, bool, string, int64
|
||||
assert(int64.toint64(35).tostring() == "35")
|
||||
assert(int64.toint64(3.5).tostring() == "3")
|
||||
assert(int64.toint64("35").tostring() == "35")
|
||||
assert(int64.toint64("20000000000").tostring() == "20000000000")
|
||||
assert(int64.toint64(true).tostring() == "1")
|
||||
assert(int64.toint64(false).tostring() == "0")
|
||||
assert(int64.toint64(int64(42)).tostring() == "42")
|
||||
# invalid
|
||||
assert(int64.toint64("").tostring() == "0")
|
||||
assert(int64.toint64(nil) == nil)
|
|
@ -32,23 +32,70 @@ static void int64_toa(int64_t num, uint8_t* str) {
|
|||
}
|
||||
}
|
||||
|
||||
void* int64_init(bvm *vm, int32_t val) {
|
||||
int64_t *i64 = (int64_t*)be_malloc(vm, sizeof(int64_t));
|
||||
*i64 = (int64_t) val;
|
||||
// serial_debug("int64_init p=%p\n", i64);
|
||||
return i64;
|
||||
/* constructor*/
|
||||
static int int64_init(bvm *vm) {
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
int64_t *i64 = NULL;
|
||||
/* did we receive a pre-allocated pointer */
|
||||
if (argc > 1 && be_iscomptr(vm, 2)) {
|
||||
i64 = be_tocomptr(vm, 2);
|
||||
}
|
||||
/* or allocated */
|
||||
if (i64 == NULL) {
|
||||
i64 = (int64_t*)be_malloc(vm, sizeof(int64_t));
|
||||
if (i64 == NULL) { be_raise(vm, "memory_error", "cannot allocate buffer"); }
|
||||
*i64 = 0; // default to zero
|
||||
}
|
||||
bbool invalid_arg = bfalse;
|
||||
if (argc > 1) {
|
||||
if (be_iscomptr(vm, 2) || be_isnil(vm, 2)) {
|
||||
/* keep value */
|
||||
} else if (be_isint(vm, 2)) {
|
||||
*i64 = be_toint(vm, 2);
|
||||
} else if (be_isreal(vm, 2)) {
|
||||
*i64 = (int64_t)be_toreal(vm, 2);
|
||||
} else if (be_isstring(vm, 2)) {
|
||||
const char* s = be_tostring(vm, 2);
|
||||
*i64 = atoll(s);
|
||||
} else if (be_isbool(vm, 2)) {
|
||||
*i64 = be_tobool(vm, 2) ? 1 : 0;
|
||||
} else if (be_isinstance(vm, 2)) {
|
||||
be_getglobal(vm, "int64");
|
||||
if (be_isderived(vm, 2)) {
|
||||
be_getmember(vm, 2, "_p");
|
||||
int64_t *v64 = be_tocomptr(vm, -1);
|
||||
if (v64 != NULL) {
|
||||
*i64 = *v64;
|
||||
}
|
||||
} else {
|
||||
invalid_arg = btrue;
|
||||
}
|
||||
} else {
|
||||
invalid_arg = btrue;
|
||||
}
|
||||
}
|
||||
if (invalid_arg) {
|
||||
be_free(vm, i64, sizeof(int64_t));
|
||||
be_raise(vm, "TypeError", "unsupported argument type");
|
||||
}
|
||||
be_pushcomptr(vm, i64);
|
||||
be_setmember(vm, 1, "_p");
|
||||
be_return_nil(vm);
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(int64_init, "+_p", "@[i]")
|
||||
|
||||
void int64_deinit(bvm *vm, int64_t *i64) {
|
||||
// serial_debug("int64_deinit p=%p\n", i64);
|
||||
be_free(vm, i64, sizeof(int64_t));
|
||||
/* destructor */
|
||||
static int int64_deinit(bvm *vm) {
|
||||
be_getmember(vm, 1, "_p");
|
||||
int64_t *i64 = be_tocomptr(vm, -1);
|
||||
if (i64 != NULL) {
|
||||
be_free(vm, i64, sizeof(int64_t));
|
||||
}
|
||||
be_return_nil(vm);
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(int64_deinit, "", "@.")
|
||||
|
||||
char* int64_tostring(int64_t *i64) {
|
||||
static char s[24]; /* enough to hold max value */
|
||||
int64_toa(*i64, s);
|
||||
int64_toa(*i64, (uint8_t*)s);
|
||||
return s;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(int64_tostring, "s", ".")
|
||||
|
@ -80,6 +127,13 @@ int64_t* int64_fromu32(bvm *vm, uint32_t low, uint32_t high) {
|
|||
}
|
||||
BE_FUNC_CTYPE_DECLARE(int64_fromu32, "int64", "@i[i]")
|
||||
|
||||
int64_t* int64_fromfloat(bvm *vm, float f) {
|
||||
int64_t* r64 = (int64_t*)be_malloc(vm, sizeof(int64_t));
|
||||
*r64 = (int64_t)f;
|
||||
return r64;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(int64_fromfloat, "int64", "@f")
|
||||
|
||||
int64_t* int64_add(bvm *vm, int64_t *i64, int64_t *j64) {
|
||||
int64_t* r64 = (int64_t*)be_malloc(vm, sizeof(int64_t));
|
||||
// it's possible that arg j64 is nullptr, since class type does allow NULLPTR to come through.
|
||||
|
@ -203,7 +257,7 @@ int64_t* int64_frombytes(bvm *vm, uint8_t* ptr, size_t len, int32_t idx) {
|
|||
int64_t* r64 = (int64_t*)be_malloc(vm, sizeof(int64_t));
|
||||
if (idx < 0) { idx = len + idx; } // support negative index, counting from the end
|
||||
if (idx < 0) { idx = 0; } // sanity check
|
||||
if (idx > len) { idx = len; }
|
||||
if (idx > (int32_t)len) { idx = len; }
|
||||
uint32_t usable_len = len - idx;
|
||||
if (usable_len > sizeof(int64_t)) { usable_len = sizeof(int64_t); }
|
||||
*r64 = 0; // start with 0
|
||||
|
@ -224,10 +278,9 @@ BE_FUNC_CTYPE_DECLARE(int64_high32, "i", "(int64)")
|
|||
|
||||
/*
|
||||
|
||||
def toint64(i)
|
||||
if (type(i) == 'int') return int64.fromu32(i) end
|
||||
if (type(i) == 'instance') && isinstance(i, int64) return i end
|
||||
return nil
|
||||
def toint64(v)
|
||||
if (v == nil) return nil end
|
||||
return int64(v)
|
||||
end
|
||||
|
||||
*/
|
||||
|
@ -237,7 +290,7 @@ end
|
|||
********************************************************************/
|
||||
be_local_closure(toint64, /* name */
|
||||
be_nested_proto(
|
||||
4, /* nstack */
|
||||
3, /* nstack */
|
||||
1, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
|
@ -245,38 +298,21 @@ be_local_closure(toint64, /* name */
|
|||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 4]) { /* constants */
|
||||
/* K0 */ be_nested_str(int),
|
||||
/* K1 */ be_nested_str(int64),
|
||||
/* K2 */ be_nested_str(fromu32),
|
||||
/* K3 */ be_nested_str(instance),
|
||||
( &(const bvalue[ 1]) { /* constants */
|
||||
/* K0 */ be_nested_str(int64),
|
||||
}),
|
||||
&be_const_str_to64,
|
||||
&be_const_str_toint64,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[23]) { /* code */
|
||||
0x60040004, // 0000 GETGBL R1 G4
|
||||
0x5C080000, // 0001 MOVE R2 R0
|
||||
0x7C040200, // 0002 CALL R1 1
|
||||
0x1C040300, // 0003 EQ R1 R1 K0
|
||||
0x78060004, // 0004 JMPF R1 #000A
|
||||
0xB8060200, // 0005 GETNGBL R1 K1
|
||||
0x8C040302, // 0006 GETMET R1 R1 K2
|
||||
0x5C0C0000, // 0007 MOVE R3 R0
|
||||
0x7C040400, // 0008 CALL R1 2
|
||||
0x80040200, // 0009 RET 1 R1
|
||||
0x60040004, // 000A GETGBL R1 G4
|
||||
0x5C080000, // 000B MOVE R2 R0
|
||||
0x7C040200, // 000C CALL R1 1
|
||||
0x1C040303, // 000D EQ R1 R1 K3
|
||||
0x78060005, // 000E JMPF R1 #0015
|
||||
0x6004000F, // 000F GETGBL R1 G15
|
||||
0x5C080000, // 0010 MOVE R2 R0
|
||||
0xB80E0200, // 0011 GETNGBL R3 K1
|
||||
0x7C040400, // 0012 CALL R1 2
|
||||
0x78060000, // 0013 JMPF R1 #0015
|
||||
0x80040000, // 0014 RET 1 R0
|
||||
0x4C040000, // 0015 LDNIL R1
|
||||
0x80040200, // 0016 RET 1 R1
|
||||
( &(const binstruction[ 9]) { /* code */
|
||||
0x4C040000, // 0000 LDNIL R1
|
||||
0x1C040001, // 0001 EQ R1 R0 R1
|
||||
0x78060001, // 0002 JMPF R1 #0005
|
||||
0x4C040000, // 0003 LDNIL R1
|
||||
0x80040200, // 0004 RET 1 R1
|
||||
0xB8060000, // 0005 GETNGBL R1 K0
|
||||
0x5C080000, // 0006 MOVE R2 R0
|
||||
0x7C040200, // 0007 CALL R1 1
|
||||
0x80040200, // 0008 RET 1 R1
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -288,9 +324,10 @@ be_local_closure(toint64, /* name */
|
|||
/* @const_object_info_begin
|
||||
class be_class_int64 (scope: global, name: int64) {
|
||||
_p, var
|
||||
init, ctype_func(int64_init)
|
||||
deinit, ctype_func(int64_deinit)
|
||||
init, func(int64_init)
|
||||
deinit, func(int64_deinit)
|
||||
fromu32, static_ctype_func(int64_fromu32)
|
||||
fromfloat, static_ctype_func(int64_fromfloat)
|
||||
toint64, static_closure(toint64_closure)
|
||||
|
||||
tostring, ctype_func(int64_tostring)
|
||||
|
|
|
@ -7,6 +7,18 @@ assert(str(int64(10)) == "10")
|
|||
assert(int(int64(-5)) == -5)
|
||||
assert(str(int64(-5)) == "-5")
|
||||
|
||||
# extended constructor
|
||||
assert(int64(35).tostring() == "35")
|
||||
assert(int64(3.5).tostring() == "3")
|
||||
assert(int64("35").tostring() == "35")
|
||||
assert(int64("20000000000").tostring() == "20000000000")
|
||||
assert(int64(true).tostring() == "1")
|
||||
assert(int64(false).tostring() == "0")
|
||||
assert(int64(int64(42)).tostring() == "42")
|
||||
# invalid
|
||||
assert(int64("").tostring() == "0")
|
||||
assert(int64(nil).tostring() == "0")
|
||||
|
||||
# testing large numbers
|
||||
assert(str(int64.fromu32(0xFFFFFFFF, 0x7FFFFFFF)) == "9223372036854775807") # max positive number
|
||||
assert(str(int64.fromu32(0x00000000, 0x80000000)) == "-9223372036854775808")
|
||||
|
@ -83,10 +95,9 @@ assert((int64(10) <= 0) == false)
|
|||
# tobytes
|
||||
assert(int64().tobytes() == bytes("0000000000000000"))
|
||||
assert(int64(10).tobytes() == bytes("0A00000000000000"))
|
||||
a = int64()
|
||||
a.set(0x7FFFFFFF,0xFFFFFFFF) # max positive number
|
||||
a = int64.fromu32(0xFFFFFFFF, 0x7FFFFFFF) # max positive number
|
||||
assert(a.tobytes() == bytes("FFFFFFFFFFFFFF7F"))
|
||||
a.set(0x80000000,0x00000000)
|
||||
a = int64.fromu32(0x00000000, 0x80000000)
|
||||
assert(a.tobytes() == bytes("0000000000000080"))
|
||||
assert(int64(-1).tobytes() == bytes("FFFFFFFFFFFFFFFF"))
|
||||
|
||||
|
@ -106,3 +117,20 @@ assert(int64.fromu32(0xFFFFFFFF).tobytes() == bytes("FFFFFFFF00000000"))
|
|||
assert(int64.fromu32(0xFFFFFFFF, 1).tobytes() == bytes("FFFFFFFF01000000"))
|
||||
assert(int64.fromu32(-1, 1).tobytes() == bytes("FFFFFFFF01000000"))
|
||||
assert(int64.fromu32(-1, -1).tobytes() == bytes("FFFFFFFFFFFFFFFF"))
|
||||
|
||||
# fromfloat
|
||||
assert(int64.fromfloat(3.5).tostring() == "3")
|
||||
assert(int64.fromfloat(-3.5).tostring() == "-3")
|
||||
assert(int64.fromfloat(2e10).tostring() == "20000000000") # 20000000000 does not fit in 32 bits
|
||||
|
||||
# toint64, supports int, float, bool, string, int64
|
||||
assert(int64.toint64(35).tostring() == "35")
|
||||
assert(int64.toint64(3.5).tostring() == "3")
|
||||
assert(int64.toint64("35").tostring() == "35")
|
||||
assert(int64.toint64("20000000000").tostring() == "20000000000")
|
||||
assert(int64.toint64(true).tostring() == "1")
|
||||
assert(int64.toint64(false).tostring() == "0")
|
||||
assert(int64.toint64(int64(42)).tostring() == "42")
|
||||
# invalid
|
||||
assert(int64.toint64("").tostring() == "0")
|
||||
assert(int64.toint64(nil) == nil)
|
||||
|
|
|
@ -34,15 +34,15 @@ typedef intptr_t (*fn_any_callable)(intptr_t p0, intptr_t p1, intptr_t p2, intpt
|
|||
* On ESP32, int=32bits, real=float (32bits)
|
||||
\*********************************************************************************************/
|
||||
static intptr_t realasint(breal v) {
|
||||
intptr_t i;
|
||||
i = *((intptr_t*) &v);
|
||||
return i;
|
||||
union { breal f; bint i; } u;
|
||||
u.f = v;
|
||||
return (intptr_t)u.i;
|
||||
}
|
||||
|
||||
static breal intasreal(intptr_t v) {
|
||||
breal r;
|
||||
r = *((breal*) &v);
|
||||
return r;
|
||||
union { breal f; bint i; } u;
|
||||
u.i = (bint)v;
|
||||
return (breal)u.f;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
|
Loading…
Reference in New Issue