Merge pull request #15204 from s-hadinger/berry_int64

Berry add int64 support
This commit is contained in:
s-hadinger 2022-03-21 19:49:49 +01:00 committed by GitHub
commit b5e96117ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1572 additions and 1149 deletions

View File

@ -189,6 +189,8 @@ be_extern_native_class(lv_wifi_arcs);
be_extern_native_class(lv_wifi_arcs_icon);
be_extern_native_class(lv_clock_icon);
be_extern_native_class(int64);
BERRY_LOCAL bclass_array be_class_table = {
/* first list are direct classes */
&be_native_class(tasmota),
@ -246,6 +248,9 @@ BERRY_LOCAL bclass_array be_class_table = {
#endif // USE_UFILESYS
&be_native_class(AudioOpusDecoder),
#endif // USE_I2S_AUDIO_BERRY
#ifdef USE_BERRY_INT64
&be_native_class(int64),
#endif
#if defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32)
&be_native_class(MI32),
&be_native_class(BLE),

View File

@ -1,2 +1,2 @@
#!/bin/bash
python3 tools/pycoc/main.py -o generate src default ../berry_tasmota/src ../berry_mapping/src ../../libesp32_lvgl/lv_binding_berry/src ../../libesp32_lvgl/lv_binding_berry/generate -c default/berry_conf.h
python3 tools/pycoc/main.py -o generate src default ../berry_tasmota/src ../berry_mapping/src ../berry_int64/src ../../libesp32_lvgl/lv_binding_berry/src ../../libesp32_lvgl/lv_binding_berry/generate -c default/berry_conf.h

View File

@ -132,6 +132,7 @@ extern const bcstring be_const_str__X23autoexec_X2Ebe;
extern const bcstring be_const_str__X23display_X2Eini;
extern const bcstring be_const_str__X23init_X2Ebat;
extern const bcstring be_const_str__X23preinit_X2Ebe;
extern const bcstring be_const_str__X25;
extern const bcstring be_const_str__X2502d_X25s_X2502d;
extern const bcstring be_const_str__X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d;
extern const bcstring be_const_str__X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x;
@ -139,9 +140,12 @@ extern const bcstring be_const_str__X25s_X2Eautoconf;
extern const bcstring be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B;
extern const bcstring be_const_str__X26lt_X3BNone_X26gt_X3B;
extern const bcstring be_const_str__X28_X29;
extern const bcstring be_const_str__X2A;
extern const bcstring be_const_str__X2B;
extern const bcstring be_const_str__X2C;
extern const bcstring be_const_str__X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D;
extern const bcstring be_const_str__X2D;
extern const bcstring be_const_str__X2D_X2A;
extern const bcstring be_const_str__X2D_X2D_X3A_X2D_X2D;
extern const bcstring be_const_str__X2E;
extern const bcstring be_const_str__X2E_X2E;
@ -440,6 +444,7 @@ extern const bcstring be_const_str_for;
extern const bcstring be_const_str_format;
extern const bcstring be_const_str_from_to;
extern const bcstring be_const_str_fromb64;
extern const bcstring be_const_str_frombytes;
extern const bcstring be_const_str_fromptr;
extern const bcstring be_const_str_fromstring;
extern const bcstring be_const_str_full_state;
@ -527,6 +532,7 @@ extern const bcstring be_const_str_instance;
extern const bcstring be_const_str_instance_X20required;
extern const bcstring be_const_str_instance_size;
extern const bcstring be_const_str_int;
extern const bcstring be_const_str_int64;
extern const bcstring be_const_str_internal_error;
extern const bcstring be_const_str_introspect;
extern const bcstring be_const_str_invalid_X20GPIO_X20number;
@ -852,6 +858,7 @@ extern const bcstring be_const_str_time_str;
extern const bcstring be_const_str_timer_cb;
extern const bcstring be_const_str_to_gamma;
extern const bcstring be_const_str_tob64;
extern const bcstring be_const_str_tobytes;
extern const bcstring be_const_str_toint;
extern const bcstring be_const_str_tolower;
extern const bcstring be_const_str_tomap;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_int64_map) {
{ be_const_key(_X3C, -1), be_const_ctype_func(int64_lt) },
{ be_const_key(_X2F, -1), be_const_ctype_func(int64_div) },
{ be_const_key(_p, -1), be_const_var(0) },
{ be_const_key(_X2A, -1), be_const_ctype_func(int64_mul) },
{ be_const_key(_X25, -1), be_const_ctype_func(int64_mod) },
{ be_const_key(tostring, -1), be_const_ctype_func(int64_tostring) },
{ be_const_key(_X3C_X3D, -1), be_const_ctype_func(int64_lte) },
{ be_const_key(set, -1), be_const_ctype_func(int64_set) },
{ be_const_key(frombytes, -1), be_const_ctype_func(int64_frombytes) },
{ be_const_key(toint, 3), be_const_ctype_func(int64_toint) },
{ be_const_key(_X2B, -1), be_const_ctype_func(int64_add) },
{ be_const_key(_X21_X3D, -1), be_const_ctype_func(int64_nequals) },
{ be_const_key(deinit, -1), be_const_ctype_func(int64_deinit) },
{ be_const_key(_X2D, -1), be_const_ctype_func(int64_sub) },
{ be_const_key(_X2D_X2A, 1), be_const_ctype_func(int64_neg) },
{ be_const_key(_X3D_X3D, 18), be_const_ctype_func(int64_equals) },
{ be_const_key(_X3E_X3D, 13), be_const_ctype_func(int64_gte) },
{ be_const_key(_X3E, -1), be_const_ctype_func(int64_gt) },
{ be_const_key(init, -1), be_const_ctype_func(int64_init) },
{ be_const_key(tobytes, 0), be_const_ctype_func(int64_tobytes) },
};
static be_define_const_map(
be_class_int64_map,
20
);
BE_EXPORT_VARIABLE be_define_const_class(
be_class_int64,
1,
NULL,
int64
);

View File

@ -0,0 +1,19 @@
Copyright (c) 2021 Stephan Hadinger
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,14 @@
{
"name": "Berry int64 implementation for 32 bits architceture",
"version": "1.0",
"description": "Berry int64",
"license": "MIT",
"homepage": "https://github.com/*g",
"frameworks": "arduino",
"platforms": "espressif32",
"authors":
{
"name": "Stephan Hadinger",
"maintainer": true
}
}

View File

@ -0,0 +1 @@
/* empty but used to force compilation of this library */

View File

@ -0,0 +1,210 @@
/********************************************************************
* int64 - support 64 bits int on 32 bits architecture
*
*******************************************************************/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "be_constobj.h"
#include "be_mapping.h"
#include "be_mem.h"
static void int64_toa(int64_t num, uint8_t* str) {
uint64_t sum = num;
if (num < 0) {
sum = -num;
str[0] = '-';
str++;
}
int len = 0;
do {
str[len++] = '0' + sum % 10LL;
sum /= 10LL;
} while (sum);
str[len] = '\0';
/* strrev */
int i, j;
for (i = 0, j = len - 1; i < j; i++, j--){
uint8_t a = str[i];
str[i] = str[j];
str[j] = a;
}
}
void* int64_init(bvm *vm, int32_t val) {
int64_t *i64 = (int64_t*)be_malloc(vm, sizeof(int64_t));
*i64 = (int64_t) val;
return i64;
}
BE_FUNC_CTYPE_DECLARE(int64_init, "+_p", "@[i]")
void int64_deinit(bvm *vm, int64_t *i64) {
// TODO
}
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);
return s;
}
BE_FUNC_CTYPE_DECLARE(int64_tostring, "s", ".")
int32_t int64_toint(int64_t *i64) {
return (int32_t) *i64;
}
BE_FUNC_CTYPE_DECLARE(int64_toint, "i", ".")
void int64_set(int64_t *i64, int32_t high, int32_t low) {
*i64 = ((int64_t)high << 32) | ((int64_t)low & 0xFFFFFFFF);
}
BE_FUNC_CTYPE_DECLARE(int64_set, "", ".ii")
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.
*r64 = j64 ? *i64 + *j64 : *i64;
return r64;
}
BE_FUNC_CTYPE_DECLARE(int64_add, "int64", "@(int64)(int64)")
int64_t* int64_sub(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.
*r64 = j64 ? *i64 - *j64 : *i64;
return r64;
}
BE_FUNC_CTYPE_DECLARE(int64_sub, "int64", "@(int64)(int64)")
int64_t* int64_neg(bvm *vm, int64_t *i64) {
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.
*r64 = - *i64;
return r64;
}
BE_FUNC_CTYPE_DECLARE(int64_neg, "int64", "@.")
int64_t* int64_mul(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.
*r64 = j64 ? *i64 * *j64 : 0;
return r64;
}
BE_FUNC_CTYPE_DECLARE(int64_mul, "int64", "@(int64)(int64)")
int64_t* int64_mod(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.
*r64 = j64 ? *i64 % *j64 : 0;
return r64;
}
BE_FUNC_CTYPE_DECLARE(int64_mod, "int64", "@(int64)(int64)")
int64_t* int64_div(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.
if (j64 == NULL || *j64 == 0) {
be_raise(vm, "divzero_error", "division by zero");
} else {
*r64 = *i64 / *j64;
}
return r64;
}
BE_FUNC_CTYPE_DECLARE(int64_div, "int64", "@.(int64)")
bbool int64_equals(int64_t *i64, int64_t *j64) {
// it's possible that arg j64 is nullptr, since class type does allow NULLPTR to come through.
int64_t j = 0;
if (j64) { j = *j64; }
return *i64 == j;
}
BE_FUNC_CTYPE_DECLARE(int64_equals, "b", ".(int64)")
bbool int64_nequals(int64_t *i64, int64_t *j64) {
// it's possible that arg j64 is nullptr, since class type does allow NULLPTR to come through.
int64_t j = 0;
if (j64) { j = *j64; }
return *i64 != j;
}
BE_FUNC_CTYPE_DECLARE(int64_nequals, "b", ".(int64)")
bbool int64_gt(int64_t *i64, int64_t *j64) {
// it's possible that arg j64 is nullptr, since class type does allow NULLPTR to come through.
int64_t j = 0;
if (j64) { j = *j64; }
return *i64 > j;
}
BE_FUNC_CTYPE_DECLARE(int64_gt, "b", ".(int64)")
bbool int64_gte(int64_t *i64, int64_t *j64) {
// it's possible that arg j64 is nullptr, since class type does allow NULLPTR to come through.
int64_t j = 0;
if (j64) { j = *j64; }
return *i64 >= j;
}
BE_FUNC_CTYPE_DECLARE(int64_gte, "b", ".(int64)")
bbool int64_lt(int64_t *i64, int64_t *j64) {
// it's possible that arg j64 is nullptr, since class type does allow NULLPTR to come through.
int64_t j = 0;
if (j64) { j = *j64; }
return *i64 < j;
}
BE_FUNC_CTYPE_DECLARE(int64_lt, "b", ".(int64)")
bbool int64_lte(int64_t *i64, int64_t *j64) {
// it's possible that arg j64 is nullptr, since class type does allow NULLPTR to come through.
int64_t j = 0;
if (j64) { j = *j64; }
return *i64 <= j;
}
BE_FUNC_CTYPE_DECLARE(int64_lte, "b", ".(int64)")
void* int64_tobytes(int64_t *i64, size_t *len) {
if (len) { *len = sizeof(int64_t); }
return i64;
}
BE_FUNC_CTYPE_DECLARE(int64_tobytes, "&", ".")
void int64_frombytes(int64_t *i64, uint8_t* ptr, size_t len, int32_t idx) {
serial_debug("int64_frombytes p=%p len=%i idx=%i\n", ptr, len, idx);
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; }
uint32_t usable_len = len - idx;
if (usable_len > sizeof(int64_t)) { usable_len = sizeof(int64_t); }
*i64 = 0; // start with 0
memmove(i64, ptr + idx, usable_len);
}
BE_FUNC_CTYPE_DECLARE(int64_frombytes, "", ".(bytes)~[i]")
#include "be_fixed_be_class_int64.h"
/* @const_object_info_begin
class be_class_int64 (scope: global, name: int64) {
_p, var
init, ctype_func(int64_init)
deinit, ctype_func(int64_deinit)
set, ctype_func(int64_set)
tostring, ctype_func(int64_tostring)
toint, ctype_func(int64_toint)
+, ctype_func(int64_add)
-, ctype_func(int64_sub)
*, ctype_func(int64_mul)
/, ctype_func(int64_div)
%, ctype_func(int64_mod)
-*, ctype_func(int64_neg)
==, ctype_func(int64_equals)
!=, ctype_func(int64_nequals)
>, ctype_func(int64_gt)
>=, ctype_func(int64_gte)
<, ctype_func(int64_lt)
<=, ctype_func(int64_lte)
tobytes, ctype_func(int64_tobytes)
frombytes, ctype_func(int64_frombytes)
}
@const_object_info_end */

View File

@ -0,0 +1,115 @@
# 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")
# testing large numbers
a = int64()
a.set(0x7FFFFFFF,0xFFFFFFFF) # max positive number
assert(str(a) == "9223372036854775807")
a.set(0x80000000,0x00000000)
assert(str(a) == "-9223372036854775808")
a.set(10,10)
assert(str(a) == "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()
a.set(0x7FFFFFFF,0xFFFFFFFF) # max positive number
assert(a.tobytes() == bytes("FFFFFFFFFFFFFF7F"))
a.set(0x80000000,0x00000000)
assert(a.tobytes() == bytes("0000000000000080"))
assert(int64(-1).tobytes() == bytes("FFFFFFFFFFFFFFFF"))
# frombytes
a = int64()
a.frombytes(bytes("0A00000000000000"), 0)
assert(a.tobytes() == bytes("0A00000000000000"))
a.frombytes(bytes("0A00000000000000")) # with implicit index 0
assert(a.tobytes() == bytes("0A00000000000000"))
a.frombytes(bytes("0A00000000000000"), 1) # index 1 and incomplete (7 bytes)
assert(a.tobytes() == bytes("0000000000000000"))
a.frombytes(bytes("00FFFFFFFFFFFFFFFF"), 1) # index 1 and incomplete (7 bytes)
assert(a.tobytes() == bytes("FFFFFFFFFFFFFFFF"))
a.frombytes(bytes("00FFFFFFFFFFFFFFFF"), -2) # from end
assert(a.tobytes() == bytes("FFFF000000000000"))
a.frombytes(bytes("")) # empty
assert(a.tobytes() == bytes("0000000000000000"))
a.frombytes(bytes(""),4) # empty with wrong index
assert(a.tobytes() == bytes("0000000000000000"))

View File

@ -1022,6 +1022,7 @@
#define USE_BERRY_PSRAM // Allocate Berry memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact
#define USE_BERRY_IRAM // Allocate some data structures in IRAM (which is ususally unused) when possible and if no PSRAM is available
// #define USE_BERRY_DEBUG // Compile Berry bytecode with line number information, makes exceptions easier to debug. Adds +8% of memory consumption for compiled code
// #define USE_BERRY_INT64 // Add 64 bits integer support (+1.7KB Flash)
#define USE_WEBCLIENT // Enable `webclient` to make HTTP/HTTPS requests. Can be disabled for security reasons.
// #define USE_WEBCLIENT_HTTPS // Enable HTTPS outgoing requests based on BearSSL (much ligher then mbedTLS, 42KB vs 150KB) in insecure mode (no verification of server's certificate)
// Note that only one cipher is enabled: ECDHE_RSA_WITH_AES_128_GCM_SHA256 which is very commonly used and highly secure

View File

@ -26,6 +26,10 @@
#include "be_mapping.h"
#include "re1.5.h"
#ifdef USE_BERRY_INT64
#include "be_int64.h"
#endif
/*********************************************************************************************\
* Logging for Tasmota Berry console
*