From ea63c5e4801c15dc93050cf94dde34355a8281e2 Mon Sep 17 00:00:00 2001
From: Alexey Pavlov
Date: Sun, 7 Nov 2021 17:56:28 +0300
Subject: [PATCH 001/510] fix opentherm
---
tasmota/xsns_69_opentherm.ino | 20 ++++++++++++++++--
tasmota/xsns_69_opentherm_protocol.ino | 29 ++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/tasmota/xsns_69_opentherm.ino b/tasmota/xsns_69_opentherm.ino
index cfcc0384d..c94e61b59 100644
--- a/tasmota/xsns_69_opentherm.ino
+++ b/tasmota/xsns_69_opentherm.ino
@@ -16,6 +16,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+#define USE_OPENTHERM
#ifdef USE_OPENTHERM
@@ -467,8 +468,11 @@ uint8_t sns_opentherm_read_flags(char *data, uint32_t len)
// flag value, however, this command does not update the settings.
#define D_CMND_SET_HOT_WATER_ENABLED "dhw"
+// BLOR - Reset boiler
+#define D_CMND_BLLOR "blor"
+
const char kOpenThermCommands[] PROGMEM = D_PRFX_OTHERM "|" D_CMND_OTHERM_BOILER_SETPOINT "|" D_CMND_OTHERM_DHW_SETPOINT
- "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED "|" D_CMND_SET_HOT_WATER_ENABLED;
+ "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED "|" D_CMND_SET_HOT_WATER_ENABLED "|" D_CMND_BLLOR;
void (*const OpenThermCommands[])(void) PROGMEM = {
&sns_opentherm_boiler_setpoint_cmd,
@@ -476,7 +480,8 @@ void (*const OpenThermCommands[])(void) PROGMEM = {
&sns_opentherm_save_settings_cmd,
&sns_opentherm_flags_cmd,
&sns_opentherm_set_central_heating_cmd,
- &sns_opentherm_set_hot_water_cmd};
+ &sns_opentherm_set_hot_water_cmd,
+ &sns_opentherm_blor_cmd,};
void sns_opentherm_cmd(void) { }
void sns_opentherm_boiler_setpoint_cmd(void)
@@ -550,6 +555,17 @@ void sns_opentherm_set_hot_water_cmd(void)
ResponseCmndNumber(sns_ot_boiler_status.m_enableHotWater ? 1 : 0);
}
+void sns_opentherm_blor_cmd(void)
+{
+ bool query = strlen(XdrvMailbox.data) == 0;
+ bool retval = false;
+ if (!query)
+ {
+ if (atoi(XdrvMailbox.data)) retval = sns_opentherm_call_blor();
+ }
+ ResponseCmndNumber(retval);
+}
+
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
diff --git a/tasmota/xsns_69_opentherm_protocol.ino b/tasmota/xsns_69_opentherm_protocol.ino
index bc821640a..a86648849 100644
--- a/tasmota/xsns_69_opentherm_protocol.ino
+++ b/tasmota/xsns_69_opentherm_protocol.ino
@@ -16,6 +16,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+#define USE_OPENTHERM
#ifdef USE_OPENTHERM
@@ -243,6 +244,14 @@ OpenThermCommand sns_opentherm_commands[] = {
.m_ot_make_request = sns_opentherm_get_generic_u16,
.m_ot_parse_response = sns_opentherm_parse_generic_u16,
.m_ot_appent_telemetry = sns_opentherm_tele_generic_u16},
+ {// Boiler Lock-out Reset command
+ .m_command_name = "BLOR",
+ .m_command_code = (uint8_t)OpenThermMessageID::Command,
+ .m_flags = {.notSupported = 1},
+ .m_results = {{.m_u8 = 0}, {.m_u8 = 0}},
+ .m_ot_make_request = sns_opentherm_send_blor,
+ .m_ot_parse_response = sns_opentherm_parse_generic_u16,
+ .m_ot_appent_telemetry = sns_opentherm_tele_u8_u8},
};
/////////////////////////////////// Process Slave Status Flags & Control //////////////////////////////////////////////////
@@ -431,6 +440,26 @@ void sns_opentherm_tele_oem_diag(struct OpenThermCommandT *self)
ResponseAppend_P(PSTR("%d"), (int)self->m_results[0].m_u16);
}
+/////////////////////////////////// Boiler Boiler Lock-out Reset //////////////////////////////////////////////////
+unsigned long sns_opentherm_send_blor(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status)
+{
+ AddLog(LOG_LEVEL_ERROR, PSTR("[OTH]: Boiler Boiler Lock-out Reset"));
+
+ self->m_flags.notSupported = true; // Disable future calls of this command
+
+ unsigned int data = 1; //1 : “BLOR”= Boiler Lock-out Reset command
+ return OpenTherm::buildRequest(OpenThermMessageType::WRITE_DATA, OpenThermMessageID::Command, data);
+}
+bool sns_opentherm_call_blor()
+{
+ /*
+ OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command-1];
+ if (strcmp(cmd->m_command_name, "BLOR")) return false;
+ cmd->m_flags.notSupported = false;
+ return true;
+ */
+}
+
/////////////////////////////////// Generic Single Float /////////////////////////////////////////////////
unsigned long sns_opentherm_get_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *)
{
From f6211a416bc0d1b1a30f5f2d0c593a4ee9ccbbc2 Mon Sep 17 00:00:00 2001
From: Alexey Pavlov
Date: Sun, 7 Nov 2021 17:59:03 +0300
Subject: [PATCH 002/510] fix opentherm
---
tasmota/xlgt_01_ws2812.ino | 99 +++++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 1 deletion(-)
diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino
index a7e7c9927..465aba427 100644
--- a/tasmota/xlgt_01_ws2812.ino
+++ b/tasmota/xlgt_01_ws2812.ino
@@ -17,6 +17,11 @@
along with this program. If not, see .
*/
+#ifndef FIRMWARE_MINIMAL
+#define USE_LIGHT
+#define USE_WS2812
+#endif
+
#ifdef USE_LIGHT
#ifdef USE_WS2812
/*********************************************************************************************\
@@ -37,7 +42,7 @@
#define XLGT_01 1
-const uint8_t WS2812_SCHEMES = 8; // Number of WS2812 schemes
+const uint8_t WS2812_SCHEMES = 10; // Number of WS2812 schemes
const char kWs2812Commands[] PROGMEM = "|" // No prefix
D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ;
@@ -289,6 +294,93 @@ void Ws2812Clock(void)
Ws2812StripShow();
}
+#define pow2(x) ((x)*(x))
+#define pow3(x) ((x)*pow2(x))
+#define pow4(x) (pow2(x)*pow2(x))
+
+void Ws2812RunningStrip(int scheme)
+{
+#if (USE_WS2812_CTYPE > NEO_3LED)
+ RgbwColor c;
+ c.W = 0;
+#else
+ RgbColor c(Settings->light_dimmer);
+#endif
+
+ static uint32_t timer_counter = 0;
+ static uint32_t last_timer_counter = timer_counter;
+ if (Settings->light_rotation%2) timer_counter--;
+ else timer_counter++;
+
+ uint32_t width = Settings->ws_width[WS_MINUTE]?Settings->ws_width[WS_MINUTE]:1;
+ uint32_t repeat = 1;//kWsRepeat[Settings->light_width]; // number of scheme.count per ledcount
+ uint32_t range = (uint32_t)ceil((float)Settings->light_pixels / (float)repeat);
+ uint32_t speed = Settings->light_speed; //((Settings->light_speed * 2) -1) * (STATES / 10); //
+ static uint32_t offset = 0;
+
+ if (scheme==WS2812_SCHEMES-1) {
+ if (timer_counter/speed!=last_timer_counter/speed) {
+ offset = random(range);
+ last_timer_counter = timer_counter;
+ }
+ } else {
+ offset = speed > 0 ? timer_counter / speed : 0;
+ }
+
+ //WsColor oldColor, currentColor;
+ //Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset);
+ //currentColor = oldColor;
+ int power = Settings->ws_width[WS_SECOND];
+ int max_input = pow(width, power);
+ float dimmer = 100 / (float)Settings->light_dimmer;
+
+ uint32_t target = offset % Settings->light_pixels;
+
+ for (uint32_t i = 0; i < Settings->light_pixels; i++) {
+ int delta = targetlight_color[0] / pow(delta+1, power);
+ float fmyGrn = Settings->light_color[1] / pow(delta+1, power);
+ float fmyBlu = Settings->light_color[2] / pow(delta+1, power);
+ /*
+ float fmyRed = (float)wsmap(max_input-pow(delta+1, power), 0, max_input, 0, Settings->light_color[0]);
+ float fmyGrn = (float)wsmap(max_input-pow(delta+1, power), 0, max_input, 0, Settings->light_color[1]);
+ float fmyBlu = (float)wsmap(max_input-pow(delta+1, power), 0, max_input, 0, Settings->light_color[2]);
+ */
+
+ c.R = (uint8_t)fmyRed/dimmer;
+ c.G = (uint8_t)fmyGrn/dimmer;
+ c.B = (uint8_t)fmyBlu/dimmer;
+ }
+ else {
+ c.R = 0 ;
+ c.G = 0 ;
+ c.B = 0 ;
+ }
+
+ if (Settings->light_width==2) {
+ c.R = Settings->light_color[0]/dimmer - c.R;
+ c.G = Settings->light_color[1]/dimmer - c.G;
+ c.B = Settings->light_color[2]/dimmer - c.B;
+ } else if (Settings->ws_width[WS_MINUTE]==3) {
+ c.R = max(100 - c.R,0);
+ c.G = max(100 - c.G,0);
+ c.B = max(100 - c.B,0);
+ }
+
+ strip->SetPixelColor(i, c);
+/*
+ // Blend old and current color based on time for smooth movement.
+ c.R = wsmap(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red);
+ c.G = wsmap(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green);
+ c.B = wsmap(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue);
+ strip->SetPixelColor(i, c);
+ oldColor = currentColor;
+ */
+ }
+ Ws2812StripShow();
+}
+
void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i)
{
/*
@@ -495,6 +587,11 @@ void Ws2812ShowScheme(void)
Ws2812.show_next = 0;
}
break;
+ case WS2812_SCHEMES-2: // Running strip
+ case WS2812_SCHEMES-1: // Running strip
+ Ws2812RunningStrip(scheme);
+ Ws2812.show_next = 1;
+ break;
default:
if (1 == Settings->light_fade) {
Ws2812Gradient(scheme -1);
From e5d176f6f42b7dcaaa587d69092b12a18e8ffe68 Mon Sep 17 00:00:00 2001
From: Michael
Date: Fri, 19 Nov 2021 11:45:07 +0100
Subject: [PATCH 003/510] init first LED
---
tasmota/xdsp_19_max7219_matrix.ino | 275 +++++++++++++++++++++++++++++
1 file changed, 275 insertions(+)
create mode 100644 tasmota/xdsp_19_max7219_matrix.ino
diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino
new file mode 100644
index 000000000..97c20f00b
--- /dev/null
+++ b/tasmota/xdsp_19_max7219_matrix.ino
@@ -0,0 +1,275 @@
+/*
+ xdsp_19_max7219_matrix.ino.ino - Support for MAX7219 based dot matrix displays for Tasmota
+
+ Copyright (C) 2021 Michael Beuss
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef USE_DISPLAY
+#ifdef USE_DISPLAY_MAX7219_MATRIX
+/*********************************************************************************************\
+ This driver enables the display of ascii text on MAX7219 based LED dot matrix modules.
+
+ Connect the MAX7219 display module's pins to any free GPIOs of the ESP8266 or ESP32 module
+ and assign the pins as follows from Tasmota's GUI:
+
+ DIN hardware pin --> "MAX7219 DIN"
+ CS hardware pin --> "MAX7219 CS"
+ CLK hardware pin --> "MAX7219 CLK"
+
+ Once the GPIO configuration is saved and the ESP8266/ESP32 module restarts,
+ set the Display Model to 19 and Display Mode to 0
+ using the command "Backlog DisplayModel 15 ; DisplayMode 0"
+
+ If your display is a TM1637 with 6 digits, set Display Width to the number of digits your
+ display has, using the command "DisplayWidth 6".
+
+ After the ESP8266/ESP32 module restarts again, turn ON the display with the command "Power 1"
+
+ Now, the following "Display" commands can be used:
+
+
+ DisplayClear
+
+ Clears the display, command: "DisplayClear"
+
+
+ DisplayNumber num [,position {0-(Settings->display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]]
+
+ Clears and then displays number without decimal. command e.g., "DisplayNumber 1234"
+ Control 'leading zeros', 'length' and 'position' with "DisplayNumber 1234, , , "
+ 'leading zeros' can be 1 or 0 (default), 'length' can be 1 to Settings->display_width, 'position' can be 0 (left-most) to Settings->display_width (right-most).
+ See function description below for more details.
+
+ DisplayNumberNC num [,position {0-(Settings->display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]]
+
+ Display integer number as above, but without clearing first. e.g., "DisplayNumberNC 1234". Usage is same as above.
+
+
+
+ DisplayFloat num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]]
+
+ Clears and then displays float (with decimal point) command e.g., "DisplayFloat 12.34"
+ See function description below for more details.
+
+
+
+ DisplayFloatNC num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]]
+
+ Displays float (with decimal point) as above, but without clearing first. command e.g., "DisplayFloatNC 12.34"
+ See function description below for more details.
+
+
+
+ DisplayRaw position {0-(Settings->display_width-1)},length {1 to Settings->display_width}, num1 [, num2[, num3[, num4[, ...upto Settings->display_width numbers]]]]]
+
+ Takes upto Settings->display_width comma-separated integers (0-255) and displays raw segments. Each number represents a
+ 7-segment digit. Each 8-bit number represents individual segments of a digit.
+ For example, the command "DisplayRaw 0, 4, 255, 255, 255, 255" would display "[8.8.8.8.]"
+
+
+
+ DisplayText text [, position {0-(Settings->display_width-1)} [,length {1 to Settings->display_width}]]
+
+ Clears and then displays basic text. command e.g., "DisplayText ajith vasudevan"
+ Control 'length' and 'position' with "DisplayText , , "
+ 'length' can be 1 to Settings->display_width, 'position' can be 0 (left-most) to Settings->display_width-1 (right-most)
+ A caret(^) symbol in the text input is dispayed as the degrees(°) symbol. This is useful for displaying Temperature!
+ For example, the command "DisplayText 22.5^" will display "22.5°".
+
+
+ DisplayTextNC text [, position {0-Settings->display_width-1} [,length {1 to Settings->display_width}]]
+
+ Clears first, then displays text. Usage is same as above.
+
+
+
+ DisplayScrollText text [, num_loops]
+
+ Displays scrolling text indefinitely, until another Display- command (other than DisplayScrollText
+ or DisplayScrollDelay is issued). Optionally, stop scrolling after num_loops iterations.
+
+
+
+ DisplayScrollDelay delay {0-15} // default = 4
+
+ Sets the speed of text scroll. Smaller delay = faster scrolling.
+
+
+
+ DisplayLevel num {0-100}
+
+ Display a horizontal bar graph (0-100) command e.g., "DisplayLevel 50" will display [|||| ]
+
+
+
+ DisplayClock 1|2|0
+
+ Displays a clock.
+ Commands "DisplayClock 1" // 12 hr format
+ "DisplayClock 2" // 24 hr format
+ "DisplayClock 0" // turn off clock
+
+
+In addition, setting DisplayMode to 1 shows the time, setting it to 2 shows the date
+and setting it to 3 alternates between time and date.
+
+
+
+\*********************************************************************************************/
+
+#define XDSP_19 19
+#define CMD_MAX_LEN 55
+
+
+#include
+
+LedControl *max7219_Matrix;
+bool max2791Matrix_init_done = false;
+byte modulesPerRow = 4;
+
+
+bool MAX7291Matrix_init(void)
+{
+ if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS))
+ {
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init GPIO pins missing DIN, CLK or CS"));
+ return false; // ensure necessariy pins are configurated
+ }
+
+ Settings->display_model = XDSP_19;
+ Settings->display_cols[0] = Settings->display_width;
+ Settings->display_height = 1;
+ Settings->display_rows = Settings->display_height;
+ max7219_Matrix = new LedControl(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), modulesPerRow);
+ MAX7291Matrix_On(true);
+ MAX7291Matrix_Clear();
+ MAX7291Matrix_Dim();
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init"));
+ max2791Matrix_init_done = true;
+
+ max7219_Matrix->setLed(0, 3, 3, true);
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: setLed 3,3"));
+ return true;
+}
+
+bool MAX7291Matrix_On( bool on )
+{
+ for (int addr = 0; addr < modulesPerRow; addr++)
+ {
+ max7219_Matrix->shutdown (addr, !on); // false: on, true: off
+ }
+ AddLog(LOG_LEVEL_INFO, PSTR("MTX: On %d"), on);
+ return true;
+
+}
+
+bool MAX7291Matrix_Dim(void)
+{
+ int dim = GetDisplayDimmer16();
+ for (int addr = 0; addr < modulesPerRow; addr++)
+ {
+ max7219_Matrix->setIntensity(addr, dim); // 1..15
+ }
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: Dim %d"), dim);
+ return true;
+}
+
+// /*********************************************************************************************\
+// * Clears the display
+// * Command: DisplayClear
+// \*********************************************************************************************/
+bool MAX7291Matrix_Clear(void)
+{
+ for(int addr=0; addrclearDisplay(addr);
+ }
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: Clear"));
+ return true;
+}
+
+// /*********************************************************************************************\
+// * Clears the display
+// * Command: DisplayText
+// \*********************************************************************************************/
+bool MAX7291Matrix_Text()
+{
+ char sString[CMD_MAX_LEN + 1];
+ subStr(sString, XdrvMailbox.data, ",", 1);
+ MAX7291Matrix_Clear;
+ AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: sString %s"), sString);
+
+ // test
+ uint8_t length = strlen(sString);
+ //if(length > modulesPerRow)
+ length = modulesPerRow;
+
+ for(int addr = 0; addrsetLed(addr, 0, 1, true);
+ AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: setLed() %d, 0, 1)"), addr);
+ }
+
+ return true;
+}
+
+bool Xdsp19(uint8_t function)
+{
+ bool result = false;
+
+
+ if (FUNC_DISPLAY_INIT_DRIVER == function)
+ {
+ result = MAX7291Matrix_init();
+ }
+ else{
+ //if (max2791Matrix_init_done && (XDSP_19 == Settings->display_model)) {
+ switch (function) {
+ case FUNC_DISPLAY_MODEL:
+ result = true;
+ break;
+ case FUNC_DISPLAY_CLEAR:
+ result = MAX7291Matrix_Clear();
+ break;
+ case FUNC_DISPLAY_DIM:
+ result = MAX7291Matrix_Dim();
+ break;
+ case FUNC_DISPLAY_SEVENSEG_TEXT:
+ case FUNC_DISPLAY_SEVENSEG_TEXTNC:
+ case FUNC_DISPLAY_NUMBER:
+ case FUNC_DISPLAY_NUMBERNC:
+ case FUNC_DISPLAY_FLOAT:
+ case FUNC_DISPLAY_FLOATNC:
+ case FUNC_DISPLAY_RAW:
+ case FUNC_DISPLAY_LEVEL:
+ case FUNC_DISPLAY_SCROLLTEXT:
+ case FUNC_DISPLAY_CLOCK:
+ case FUNC_DISPLAY_DRAW_STRING:
+ result = MAX7291Matrix_Text();
+ break;
+ case FUNC_DISPLAY_EVERY_50_MSECOND:
+ case FUNC_DISPLAY_EVERY_SECOND:
+ // ignore
+ return false;
+ default:
+ result = false;
+ }
+ }
+ return result;
+}
+
+
+
+#endif // USE_DISPLAY_MAX7219_MATRIX
+#endif // USE_DISPLAY
From b3dd33f2488184076eceadaffabaca24f8fd8dd5 Mon Sep 17 00:00:00 2001
From: Michael
Date: Fri, 19 Nov 2021 11:47:00 +0100
Subject: [PATCH 004/510] first init
---
tasmota/tasmota_template.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h
index 0de887e9c..e3f3256fc 100644
--- a/tasmota/tasmota_template.h
+++ b/tasmota/tasmota_template.h
@@ -520,6 +520,15 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_SSD1331_CS),
AGPIO(GPIO_SSD1331_DC),
#endif // USE_DISPLAY_SSD1331
+
+#ifdef USE_DISPLAY_MAX7219_MATRIX
+ #undef USE_DISPLAY_MAX7219
+ #undef USE_DISPLAY_TM1637
+ AGPIO(GPIO_MAX7219CLK),
+ AGPIO(GPIO_MAX7219DIN),
+ AGPIO(GPIO_MAX7219CS),
+#endif // USE_DISPLAY_MAX7219_MATRIX
+
#ifdef USE_DISPLAY_TM1637
AGPIO(GPIO_TM1637CLK),
AGPIO(GPIO_TM1637DIO),
From 532e5069468f6aff76cf9d8dd2140bdb60b6fab8 Mon Sep 17 00:00:00 2001
From: Michael
Date: Sat, 20 Nov 2021 17:28:38 +0100
Subject: [PATCH 005/510] use LedMatrix 1234
---
lib/lib_display/LedControl/src/LedMatrix.cpp | 186 +++++++++++++++++++
lib/lib_display/LedControl/src/LedMatrix.h | 124 +++++++++++++
tasmota/xdsp_19_max7219_matrix.ino | 152 +++++++--------
3 files changed, 373 insertions(+), 89 deletions(-)
create mode 100644 lib/lib_display/LedControl/src/LedMatrix.cpp
create mode 100644 lib/lib_display/LedControl/src/LedMatrix.h
diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp
new file mode 100644
index 000000000..427ae8c52
--- /dev/null
+++ b/lib/lib_display/LedControl/src/LedMatrix.cpp
@@ -0,0 +1,186 @@
+/*
+ * LedMatrix.h - Extends the Library LedControl for multiple LED dot matrix modules, based on MAX7219/MAX7221
+ * Copyright (c) 2021 Michael Beuss
+ *
+ * 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:
+ *
+ * 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.
+ */
+
+#include "LedMatrix.h"
+
+// public
+LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows)
+{
+ if (colums * rows > MATRIX_MAX_MODULES)
+ {
+ // dimension exeeds maximum buffer size
+ if (colums >= MATRIX_MAX_MODULES)
+ {
+ colums = MATRIX_MAX_MODULES;
+ rows = 1;
+ }
+ else
+ {
+ rows = MATRIX_MAX_MODULES / colums;
+ }
+ }
+
+ modulesPerRow = colums;
+ modulesPerCol = rows;
+ width = colums * 8;
+ height = rows * 8;
+ modules = colums * rows;
+ moduleOrientation = ORIENTATION_UPSIDE_DOWN;
+ ledControl = new LedControl(dataPin, clkPin, csPin, modules);
+ shutdown(false); // false: on, true: off
+ clear();
+ setIntensity(7);
+}
+
+bool LedMatrix::clear(void)
+{
+ for (int i = 0; i < MATRIX_BUFFER_SIZE; i++)
+ {
+ buffer[i] = 0;
+ }
+ for (int addr = 0; addr < modules; addr++)
+ {
+ ledControl->clearDisplay(addr);
+ }
+ return true;
+}
+
+bool LedMatrix::setIntensity(byte dim)
+{
+ for (int addr = 0; addr < modules; addr++)
+ {
+ ledControl->setIntensity(addr, dim); // 1..15
+ }
+ return true;
+}
+
+bool LedMatrix::setOrientation(ModuleOrientation orientation)
+{
+ moduleOrientation = orientation;
+ return true;
+}
+
+bool LedMatrix::setPixel(int x, int y, bool on)
+{
+ if (x >= width || y >= height)
+ return false;
+
+ int modul_col = x / 8; // x pos divided by 8 is the index of the modul to the right
+ int buffer_pos = modul_col + y * width / 8;
+ byte buffer_byte = 8 >> (x % 8);
+ if (on)
+ {
+ buffer[buffer_pos] |= buffer_byte; // set bit
+ }
+ else
+ {
+ buffer[buffer_pos] &= ~buffer_byte; // reset bit
+ }
+ refreshByteOfBuffer(buffer_pos);
+ return true;
+}
+
+void LedMatrix::test()
+{
+ const static byte testMatrix[] PROGMEM = {
+ B00000010, B00111100, B00111100, B00001000,
+ B00000110, B01000010, B01000010, B00010000,
+ B00001010, B00000010, B00000010, B00100000,
+ B00000010, B00000100, B00001100, B01000100,
+ B00000010, B00011000, B00000010, B01111110,
+ B00000010, B00100000, B01000010, B00000100,
+ B00000000, B11111110, B00111100, B00000100,
+ B00000000, B00000000, B00000000, B00000000,
+ };
+ for (int i = 0; i < 32; i++)
+ {
+ buffer[i] = testMatrix[i];
+ }
+ refresh();
+}
+
+// private
+bool LedMatrix::shutdown(bool b)
+{
+ for (int addr = 0; addr < modules; addr++)
+ {
+ ledControl->shutdown(addr, b); // b: false: on, true: off
+ }
+ return true;
+}
+
+void LedMatrix::refresh()
+{
+ for (int i = 0; i < modulesPerRow * height; i++)
+ {
+ refreshByteOfBuffer(i);
+ }
+}
+
+void LedMatrix::refreshByteOfBuffer(int i)
+{
+ int line = i / modulesPerRow;
+ int addr = line / 8 + i % modulesPerRow;
+ byte b = buffer[i];
+ if (moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN)
+ {
+ int rowOfAddr = 0;
+ if (moduleOrientation == ORIENTATION_NORMAL)
+ {
+ rowOfAddr = line % 8; // ORIENTATION_NORMAL
+ }
+ else
+ {
+ rowOfAddr = 7 - line % 8; // ORIENTATION_UPSIDE_DOWN
+ b = revereBitorder(b);
+ }
+ ledControl->setRow(addr, rowOfAddr, b);
+ }
+ else
+ {
+ // ORIENTATION_TURN_RIGHT or ORIENTATION_TURN_LEFT
+ int colOfAddr = 0;
+ if (moduleOrientation == ORIENTATION_TURN_LEFT)
+ {
+ colOfAddr = line % 8; // ORIENTATION_TURN_LEFT
+ }
+ else
+ {
+ colOfAddr = 7 - line % 8; // ORIENTATION_TURN_RIGHT
+ b = revereBitorder(b);
+ }
+ ledControl->setColumn(addr, colOfAddr, b);
+ }
+}
+
+byte LedMatrix::revereBitorder (byte b)
+{
+ const static byte lookup[] PROGMEM = {
+ 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
+ 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf,
+ };
+ return (lookup[b & 0b1111] << 4) | lookup[b >> 4];
+}
diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h
new file mode 100644
index 000000000..f439e5d05
--- /dev/null
+++ b/lib/lib_display/LedControl/src/LedMatrix.h
@@ -0,0 +1,124 @@
+/*
+ * LedMatrix.h - Extends the Library LedControl for multiple LED dot matrix modules, based on MAX7219/MAX7221
+ * Copyright (c) 2021 Michael Beuss
+ *
+ * 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:
+ *
+ * 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.
+ */
+
+#ifndef LedMatrix_h
+#define LedMatrix_h
+
+#include
+
+#define MATRIX_MAX_MODULES 32
+#define MATRIX_BUFFER_SIZE MATRIX_MAX_MODULES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
+
+
+/**
+ * @brief LedMatric controls multiple 8x8 LED dot matrx modules.
+ * All modules in rows and clolums together build a common matrix.
+ *
+ */
+class LedMatrix
+{
+ public:
+ enum ModuleOrientation // orientation of 8x8 LED dot matrix mdules (first module is top left)
+ {
+ ORIENTATION_NORMAL, // first pixel is on top left, no turn is necessary
+ ORIENTATION_TURN_RIGHT, // first pixel is on bottom left, for correction it has to turn 90° right
+ ORIENTATION_UPSIDE_DOWN, // first pixel is on bottom right, fpr correction it has to turn 180°
+ ORIENTATION_TURN_LEFT, // first pixel is on top right, for correction is has to turn 90° left.
+ };
+
+ private:
+ unsigned int modulesPerRow;
+ unsigned int modulesPerCol;
+ unsigned int width; // matrix width [pixel]
+ unsigned int height; // matrix height [pixel]
+ unsigned int modules; // number of 8x8 mudules
+ ModuleOrientation moduleOrientation;
+ byte buffer[MATRIX_BUFFER_SIZE];
+ LedControl* ledControl;
+
+
+ public:
+ /**
+ * @brief Construct a new Led Matrix object
+ *
+ * @param colums of 8x8 LED dot matrix modules
+ * @param rows of 8x8 LED dot matrix modules
+ */
+ LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows);
+
+ /**
+ * @brief Set all LEDs off.
+ *
+ */
+ bool clear(void);
+
+ /**
+ * @brief Set the brightness of the display
+ *
+ * @param dim 0..15
+ */
+ bool setIntensity(byte dim);
+
+ /**
+ * @brief Switches the display on or off
+ *
+ * @param on true: on false: off
+ */
+ void power( bool on );
+
+ /**
+ * @brief Set the orientation of the 8x8 LED dot matrix module
+ *
+ * @param orientation
+ */
+ bool setOrientation(ModuleOrientation orientation);
+
+ /**
+ * @brief Set the Pixel object
+ *
+ * @param x horizontal position from left
+ * @param y vertical position from top
+ * @param on true: on, false: off
+ */
+ bool setPixel( int x, int y, bool on);
+ void test();
+
+ private:
+ bool shutdown(bool b);
+
+ /**
+ * @brief sends the changed content of the buffer to the display
+ *
+ */
+ void refresh();
+
+ void refreshByteOfBuffer( int i);
+
+ byte revereBitorder (byte b);
+
+};
+
+#endif //LedMatrix_h
\ No newline at end of file
diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino
index 97c20f00b..da3177f59 100644
--- a/tasmota/xdsp_19_max7219_matrix.ino
+++ b/tasmota/xdsp_19_max7219_matrix.ino
@@ -133,70 +133,45 @@ and setting it to 3 alternates between time and date.
#define XDSP_19 19
#define CMD_MAX_LEN 55
+#include
-#include
-
-LedControl *max7219_Matrix;
+LedMatrix *max7219_Matrix;
bool max2791Matrix_init_done = false;
byte modulesPerRow = 4;
-
+byte modulesPerCol = 1;
bool MAX7291Matrix_init(void)
{
if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS))
{
- AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init GPIO pins missing DIN, CLK or CS"));
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init GPIO pins missing DIN:%d, CLK:%d, CS:%d"), Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS) );
return false; // ensure necessariy pins are configurated
}
Settings->display_model = XDSP_19;
+ if (Settings->display_width) // [pixel]
+ {
+ modulesPerRow = (Settings->display_width - 1) / 8 + 1;
+ }
+ Settings->display_width = 8 * modulesPerRow;
Settings->display_cols[0] = Settings->display_width;
- Settings->display_height = 1;
+ if (Settings->display_height) // [pixel]
+ {
+ modulesPerCol = (Settings->display_height - 1) / 8 + 1;
+ }
+ Settings->display_height = 8 * modulesPerCol;
Settings->display_rows = Settings->display_height;
- max7219_Matrix = new LedControl(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), modulesPerRow);
- MAX7291Matrix_On(true);
- MAX7291Matrix_Clear();
- MAX7291Matrix_Dim();
- AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init"));
+ Settings->display_cols[1] = Settings->display_height;
+ max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), modulesPerRow, modulesPerCol);
+ int intensity = GetDisplayDimmer16(); // 0..15
+ max7219_Matrix->setIntensity(intensity);
+ int orientation = Settings->display_rotate;
+ max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)orientation );
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init %dx%d modules, orientation: %d, intensity: %d"), modulesPerRow , modulesPerCol, orientation, intensity);
max2791Matrix_init_done = true;
- max7219_Matrix->setLed(0, 3, 3, true);
- AddLog(LOG_LEVEL_INFO, PSTR("DSP: setLed 3,3"));
- return true;
-}
-
-bool MAX7291Matrix_On( bool on )
-{
- for (int addr = 0; addr < modulesPerRow; addr++)
- {
- max7219_Matrix->shutdown (addr, !on); // false: on, true: off
- }
- AddLog(LOG_LEVEL_INFO, PSTR("MTX: On %d"), on);
- return true;
-
-}
-
-bool MAX7291Matrix_Dim(void)
-{
- int dim = GetDisplayDimmer16();
- for (int addr = 0; addr < modulesPerRow; addr++)
- {
- max7219_Matrix->setIntensity(addr, dim); // 1..15
- }
- AddLog(LOG_LEVEL_INFO, PSTR("DSP: Dim %d"), dim);
- return true;
-}
-
-// /*********************************************************************************************\
-// * Clears the display
-// * Command: DisplayClear
-// \*********************************************************************************************/
-bool MAX7291Matrix_Clear(void)
-{
- for(int addr=0; addrclearDisplay(addr);
- }
- AddLog(LOG_LEVEL_INFO, PSTR("DSP: Clear"));
+ max7219_Matrix->test();
+ AddLog(LOG_LEVEL_INFO, PSTR("DSP: display test"));
return true;
}
@@ -208,17 +183,18 @@ bool MAX7291Matrix_Text()
{
char sString[CMD_MAX_LEN + 1];
subStr(sString, XdrvMailbox.data, ",", 1);
- MAX7291Matrix_Clear;
+ max7219_Matrix->clear();
AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: sString %s"), sString);
// test
uint8_t length = strlen(sString);
- //if(length > modulesPerRow)
- length = modulesPerRow;
+ //if(length > modulesPerRow)
+ length = modulesPerRow;
- for(int addr = 0; addrsetLed(addr, 0, 1, true);
- AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: setLed() %d, 0, 1)"), addr);
+ for (int addr = 0; addr < length; addr++)
+ {
+ max7219_Matrix->setPixel(addr, addr, true);
+ AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: setPixel() %d, %d)"), addr, addr);
}
return true;
@@ -226,50 +202,48 @@ bool MAX7291Matrix_Text()
bool Xdsp19(uint8_t function)
{
- bool result = false;
-
+ bool result = false;
if (FUNC_DISPLAY_INIT_DRIVER == function)
{
result = MAX7291Matrix_init();
}
- else{
- //if (max2791Matrix_init_done && (XDSP_19 == Settings->display_model)) {
- switch (function) {
- case FUNC_DISPLAY_MODEL:
- result = true;
- break;
- case FUNC_DISPLAY_CLEAR:
- result = MAX7291Matrix_Clear();
- break;
- case FUNC_DISPLAY_DIM:
- result = MAX7291Matrix_Dim();
- break;
- case FUNC_DISPLAY_SEVENSEG_TEXT:
- case FUNC_DISPLAY_SEVENSEG_TEXTNC:
- case FUNC_DISPLAY_NUMBER:
- case FUNC_DISPLAY_NUMBERNC:
- case FUNC_DISPLAY_FLOAT:
- case FUNC_DISPLAY_FLOATNC:
- case FUNC_DISPLAY_RAW:
- case FUNC_DISPLAY_LEVEL:
- case FUNC_DISPLAY_SCROLLTEXT:
- case FUNC_DISPLAY_CLOCK:
- case FUNC_DISPLAY_DRAW_STRING:
- result = MAX7291Matrix_Text();
- break;
- case FUNC_DISPLAY_EVERY_50_MSECOND:
- case FUNC_DISPLAY_EVERY_SECOND:
- // ignore
- return false;
- default:
- result = false;
+ else if (max7219_Matrix && (XDSP_19 == Settings->display_model))
+ {
+ switch (function)
+ {
+ case FUNC_DISPLAY_MODEL:
+ result = true;
+ break;
+ case FUNC_DISPLAY_CLEAR:
+ result = max7219_Matrix->clear();
+ break;
+ case FUNC_DISPLAY_DIM:
+ result = max7219_Matrix->setIntensity(GetDisplayDimmer16());
+ break;
+ case FUNC_DISPLAY_SEVENSEG_TEXT:
+ case FUNC_DISPLAY_SEVENSEG_TEXTNC:
+ case FUNC_DISPLAY_NUMBER:
+ case FUNC_DISPLAY_NUMBERNC:
+ case FUNC_DISPLAY_FLOAT:
+ case FUNC_DISPLAY_FLOATNC:
+ case FUNC_DISPLAY_RAW:
+ case FUNC_DISPLAY_LEVEL:
+ case FUNC_DISPLAY_SCROLLTEXT:
+ case FUNC_DISPLAY_CLOCK:
+ case FUNC_DISPLAY_DRAW_STRING:
+ result = MAX7291Matrix_Text();
+ break;
+ case FUNC_DISPLAY_EVERY_50_MSECOND:
+ case FUNC_DISPLAY_EVERY_SECOND:
+ // ignore
+ return false;
+ default:
+ result = false;
}
}
return result;
}
-
-
#endif // USE_DISPLAY_MAX7219_MATRIX
#endif // USE_DISPLAY
From 917777d2c50deda43c19c1671c38527b882820bc Mon Sep 17 00:00:00 2001
From: Michael
Date: Tue, 23 Nov 2021 14:46:19 +0100
Subject: [PATCH 006/510] first scroll
---
lib/lib_display/LedControl/src/LedMatrix.cpp | 144 +++++++++-
lib/lib_display/LedControl/src/LedMatrix.h | 55 +++-
.../LedControl/src/font_5x8_horizontal_MSB.h | 264 ++++++++++++++++++
.../LedControl/src/font_6x8_horizontal_MSB.h | 264 ++++++++++++++++++
tasmota/xdsp_19_max7219_matrix.ino | 36 +--
5 files changed, 716 insertions(+), 47 deletions(-)
create mode 100644 lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
create mode 100644 lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h
diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp
index 427ae8c52..19ac0dcb2 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.cpp
+++ b/lib/lib_display/LedControl/src/LedMatrix.cpp
@@ -25,6 +25,7 @@
*/
#include "LedMatrix.h"
+#include "font_6x8_horizontal_MSB.h"
// public
LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows)
@@ -45,22 +46,116 @@ LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, un
modulesPerRow = colums;
modulesPerCol = rows;
- width = colums * 8;
- height = rows * 8;
+ displayWidth = colums * 8;
+ displayHeight = rows * 8;
modules = colums * rows;
moduleOrientation = ORIENTATION_UPSIDE_DOWN;
ledControl = new LedControl(dataPin, clkPin, csPin, modules);
+ textBuf[0] = 0;
+ textWidth = 0;
+ textPosX = 0;
+ textPosY = 0;
+ appendTextBuf[0] = 0;
+ setScrollAppendText(" ");
shutdown(false); // false: on, true: off
clear();
setIntensity(7);
}
+bool LedMatrix::drawText( const char *str)
+{
+ strncpy(textBuf, str, TEXT_BUFFER_SIZE -1);
+ textPosX = 0;
+ textPosY = 0;
+ textWidth = strlen(textBuf) * charWidth;
+ if(textWidth < displayWidth)
+ {
+ textPosX = (displayWidth - textWidth) / 2; // center
+ }
+ else
+ {
+ // The text ist longer than the display width. Scrolling is needed.
+ // Append a space between end of text and the beginning of the repeting text.
+ appendSpace();
+ }
+ clear();
+ drawTextAt(textBuf, textPosX, textPosY);
+ refresh(); // refresh display with new string content
+ return true;
+}
+
+bool LedMatrix::drawTextAt( const char *str, const int x, const int y )
+{
+ // draw character by character
+ unsigned int len = strlen(str);
+ int xPos = x;
+ for (unsigned int i = 0; i < len; i++)
+ {
+ drawCharAt(str[i], xPos, y);
+ xPos += charWidth;
+ }
+ return true;
+}
+
+bool LedMatrix::scrollText()
+{
+ if(textWidth < displayWidth) return false; // do not scroll when text fits into the display
+
+ textPosX--;
+ if(textPosX + textWidth < 0)
+ {
+ textPosX = 0; // start from the beginning after text scrolled out of display;
+ }
+ drawTextAt(textBuf, textPosX, textPosY);
+
+ int startOfRepeatingTextPos = textPosX + textWidth;
+ if(startOfRepeatingTextPos < displayWidth)
+ {
+ // Draw repeating text.
+ drawTextAt(textBuf, startOfRepeatingTextPos, textPosY);
+ }
+ refresh();
+ return true;
+}
+
+bool LedMatrix::drawCharAt( char c, const int x, const int y)
+{
+ // ignore when the character position is not visible on the display
+ bool visible = (
+ x > 0 - (int)charWidth && x < (int)displayWidth &&
+ y > 0 - (int)charHeight && y < (int)displayHeight
+ );
+ if (!visible) return false;
+
+ // ignore the leading bits above charWidth of the font definition
+ static const byte charOffset = 8 - charWidth;
+
+ for (byte charY = 0; charY < charHeight; charY++)
+ {
+ char pixelRow = (font[c][charY]) << charOffset; // skip the first bits when the character width is smaller than 8 pixel
+ for (byte charX = 0; charX < charWidth; charX++)
+ {
+ bool pixel = (pixelRow & 0x80); // pixel=true when upper bit is set
+ setPixel(x + charX, y + charY, pixel);
+ pixelRow = pixelRow << 1; // next pixel
+ }
+ }
+ return true;
+}
+
+bool LedMatrix::clearDisplay(void)
+{
+ textBuf[0] = 0;
+ memset(textBuf, 0, TEXT_BUFFER_SIZE);
+ textWidth = 0;
+ clear();
+ return true;
+}
+
+
bool LedMatrix::clear(void)
{
- for (int i = 0; i < MATRIX_BUFFER_SIZE; i++)
- {
- buffer[i] = 0;
- }
+ memset(buffer, 0, MATRIX_BUFFER_SIZE);
for (int addr = 0; addr < modules; addr++)
{
ledControl->clearDisplay(addr);
@@ -83,14 +178,20 @@ bool LedMatrix::setOrientation(ModuleOrientation orientation)
return true;
}
-bool LedMatrix::setPixel(int x, int y, bool on)
+bool LedMatrix::setScrollAppendText(const char* append )
{
- if (x >= width || y >= height)
+ strncpy(appendTextBuf, append, TEXT_APPEND_BUFFER_SIZE -1);
+ return (strlen(append) < TEXT_APPEND_BUFFER_SIZE);
+}
+
+bool LedMatrix::setPixel(const int x, const int y, bool on)
+{
+ if (x >= displayWidth || y >= displayHeight)
return false;
int modul_col = x / 8; // x pos divided by 8 is the index of the modul to the right
- int buffer_pos = modul_col + y * width / 8;
- byte buffer_byte = 8 >> (x % 8);
+ int buffer_pos = modul_col + y * modulesPerRow;
+ byte buffer_byte = 0x80 >> (x % 8);
if (on)
{
buffer[buffer_pos] |= buffer_byte; // set bit
@@ -99,12 +200,12 @@ bool LedMatrix::setPixel(int x, int y, bool on)
{
buffer[buffer_pos] &= ~buffer_byte; // reset bit
}
- refreshByteOfBuffer(buffer_pos);
return true;
}
void LedMatrix::test()
{
+ /*
const static byte testMatrix[] PROGMEM = {
B00000010, B00111100, B00111100, B00001000,
B00000110, B01000010, B01000010, B00010000,
@@ -112,7 +213,7 @@ void LedMatrix::test()
B00000010, B00000100, B00001100, B01000100,
B00000010, B00011000, B00000010, B01111110,
B00000010, B00100000, B01000010, B00000100,
- B00000000, B11111110, B00111100, B00000100,
+ B00000000, B01111110, B00111100, B00000100,
B00000000, B00000000, B00000000, B00000000,
};
for (int i = 0; i < 32; i++)
@@ -120,6 +221,17 @@ void LedMatrix::test()
buffer[i] = testMatrix[i];
}
refresh();
+ */
+ drawText("1234567890");
+ delay(1000);
+ for( int i=0; i<320; i++)
+ {
+ delay(50);
+ scrollText();
+ }
+ //drawCharAt(0x31, 1, 0);
+ //setPixel(1,30);
+ //refresh();
}
// private
@@ -134,7 +246,7 @@ bool LedMatrix::shutdown(bool b)
void LedMatrix::refresh()
{
- for (int i = 0; i < modulesPerRow * height; i++)
+ for (int i = 0; i < modulesPerRow * displayHeight; i++)
{
refreshByteOfBuffer(i);
}
@@ -184,3 +296,9 @@ byte LedMatrix::revereBitorder (byte b)
};
return (lookup[b & 0b1111] << 4) | lookup[b >> 4];
}
+
+void LedMatrix::appendSpace()
+{
+ strncat(textBuf, appendTextBuf, TEXT_BUFFER_SIZE -1);
+ textWidth = strlen(textBuf) * charWidth;
+}
diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h
index f439e5d05..586a06146 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.h
+++ b/lib/lib_display/LedControl/src/LedMatrix.h
@@ -31,6 +31,8 @@
#define MATRIX_MAX_MODULES 32
#define MATRIX_BUFFER_SIZE MATRIX_MAX_MODULES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
+#define TEXT_BUFFER_SIZE 256
+#define TEXT_APPEND_BUFFER_SIZE 16
/**
@@ -52,12 +54,19 @@ class LedMatrix
private:
unsigned int modulesPerRow;
unsigned int modulesPerCol;
- unsigned int width; // matrix width [pixel]
- unsigned int height; // matrix height [pixel]
+ unsigned int displayWidth; // matrix width [pixel]
+ unsigned int displayHeight; // matrix height [pixel]
unsigned int modules; // number of 8x8 mudules
ModuleOrientation moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
LedControl* ledControl;
+ const unsigned int charWidth = 6;
+ const unsigned int charHeight = 8;
+ char textBuf[TEXT_BUFFER_SIZE];
+ char appendTextBuf[TEXT_APPEND_BUFFER_SIZE];
+ unsigned int textWidth; // width of text [pixel]
+ int textPosX; // horizontal pixel position of scrolling text
+ int textPosY; // vertical pixelposition of scrolling text;
public:
@@ -73,7 +82,7 @@ class LedMatrix
* @brief Set all LEDs off.
*
*/
- bool clear(void);
+ bool clearDisplay(void);
/**
* @brief Set the brightness of the display
@@ -82,6 +91,13 @@ class LedMatrix
*/
bool setIntensity(byte dim);
+ /**
+ * @brief Set the a pending string to the scrolling text to set a distance to te repeating text. Usually some spaces.
+ *
+ * @param append text to append to the scrolling text before repeating.
+ */
+ bool setScrollAppendText(const char* append );
+
/**
* @brief Switches the display on or off
*
@@ -96,6 +112,32 @@ class LedMatrix
*/
bool setOrientation(ModuleOrientation orientation);
+ /**
+ * @brief draw a string to the display.
+ * When the text fits into the size of the display, it will be shown in the center.
+ * When the text is longer than than the display width, it can be scrolled per pixel with function scrollText().
+ *
+ * @param str string to display
+ */
+ bool drawText( const char *str );
+
+ /**
+ * @brief dwaws a character string to the display. The position (x,y) is used for the upper left pixtel of the text.
+ * Existing text before the x position will not be cleared.
+ *
+ * @param str string to display
+ * @param x horizantal pixel position to start with string (default 0)
+ * @param y vertical pixel position for the top position of the string (default 0)
+ */
+ bool drawTextAt( const char *str, const int x, const int y );
+
+ /**
+ * @brief Scroll the current teext one picel to the left.
+ * Repeat with from start when end of text reached.
+ *
+ */
+ bool scrollText();
+
/**
* @brief Set the Pixel object
*
@@ -103,11 +145,14 @@ class LedMatrix
* @param y vertical position from top
* @param on true: on, false: off
*/
- bool setPixel( int x, int y, bool on);
+ bool setPixel( const int x, const int y, bool on=true);
void test();
private:
+ bool drawCharAt( char c, int x, int y );
+
bool shutdown(bool b);
+ bool clear(void);
/**
* @brief sends the changed content of the buffer to the display
@@ -119,6 +164,8 @@ class LedMatrix
byte revereBitorder (byte b);
+ void appendSpace();
+
};
#endif //LedMatrix_h
\ No newline at end of file
diff --git a/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h b/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
new file mode 100644
index 000000000..56df774a4
--- /dev/null
+++ b/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
@@ -0,0 +1,264 @@
+// 5x8 ascii font
+#ifndef font_5x8_horizontal_MSB_h
+#define font_5x8_horizontal_MSB_h
+
+const char font[256][8]={
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
+{0x0E,0x11,0x1B,0x11,0x1F,0x0E,0x00,0x00}, // 0x01
+{0x0E,0x15,0x1F,0x11,0x1F,0x0E,0x00,0x00}, // 0x02
+{0x0A,0x1F,0x1F,0x1F,0x0E,0x04,0x00,0x00}, // 0x03
+{0x04,0x04,0x0E,0x1F,0x0E,0x04,0x04,0x00}, // 0x04
+{0x04,0x0E,0x04,0x1F,0x15,0x04,0x0E,0x00}, // 0x05
+{0x04,0x0E,0x1F,0x1F,0x15,0x04,0x0E,0x00}, // 0x06
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
+{0x03,0x03,0x0E,0x11,0x11,0x11,0x0E,0x00}, // 0x0B
+{0x0E,0x11,0x11,0x11,0x0E,0x04,0x0E,0x04}, // 0x0C
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
+{0x03,0x0F,0x09,0x09,0x0B,0x1B,0x18,0x00}, // 0x0E
+{0x00,0x15,0x0E,0x1B,0x0E,0x15,0x00,0x00}, // 0x0F
+{0x00,0x10,0x1C,0x1F,0x1C,0x10,0x00,0x00}, // 0x10
+{0x00,0x01,0x07,0x1F,0x07,0x01,0x00,0x00}, // 0x11
+{0x04,0x0E,0x04,0x04,0x04,0x0E,0x04,0x00}, // 0x12
+{0x00,0x0A,0x0A,0x0A,0x00,0x0A,0x00,0x00}, // 0x13
+{0x0E,0x1A,0x1A,0x0A,0x0A,0x0A,0x0A,0x00}, // 0x14
+{0x06,0x08,0x04,0x0A,0x04,0x02,0x0C,0x00}, // 0x15
+{0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,0x00}, // 0x16
+{0x04,0x0E,0x04,0x0E,0x04,0x00,0x0E,0x00}, // 0x17
+{0x04,0x0E,0x04,0x04,0x04,0x04,0x04,0x00}, // 0x18
+{0x04,0x04,0x04,0x04,0x04,0x0E,0x04,0x00}, // 0x19
+{0x00,0x00,0x02,0x0F,0x02,0x00,0x00,0x00}, // 0x1A
+{0x00,0x00,0x04,0x0F,0x04,0x00,0x00,0x00}, // 0x1B
+{0x00,0x00,0x08,0x08,0x08,0x0F,0x00,0x00}, // 0x1C
+{0x00,0x00,0x0A,0x1F,0x0A,0x00,0x00,0x00}, // 0x1D
+{0x00,0x04,0x04,0x0E,0x0E,0x1F,0x00,0x00}, // 0x1E
+{0x00,0x1F,0x0E,0x0E,0x04,0x04,0x00,0x00}, // 0x1F
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
+{0x04,0x04,0x04,0x04,0x00,0x04,0x00,0x00}, // 0x21
+{0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22
+{0x00,0x05,0x1F,0x0A,0x1F,0x14,0x00,0x00}, // 0x23
+{0x04,0x0E,0x0C,0x04,0x06,0x0E,0x04,0x00}, // 0x24
+{0x09,0x15,0x0E,0x0E,0x15,0x12,0x00,0x00}, // 0x25
+{0x04,0x0A,0x0C,0x15,0x12,0x0D,0x00,0x00}, // 0x26
+{0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x27
+{0x03,0x04,0x08,0x08,0x08,0x04,0x03,0x00}, // 0x28
+{0x18,0x04,0x02,0x02,0x02,0x04,0x18,0x00}, // 0x29
+{0x04,0x0A,0x04,0x0A,0x00,0x00,0x00,0x00}, // 0x2A
+{0x00,0x00,0x00,0x04,0x0E,0x04,0x00,0x00}, // 0x2B
+{0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x08}, // 0x2C
+{0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0x2D
+{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00}, // 0x2E
+{0x01,0x02,0x02,0x04,0x04,0x08,0x08,0x00}, // 0x2F
+{0x06,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0x30
+{0x04,0x0C,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0x31
+{0x0C,0x02,0x02,0x04,0x08,0x0E,0x00,0x00}, // 0x32
+{0x0C,0x02,0x0C,0x02,0x02,0x0C,0x00,0x00}, // 0x33
+{0x02,0x06,0x0A,0x0F,0x02,0x02,0x00,0x00}, // 0x34
+{0x0E,0x08,0x0C,0x02,0x02,0x0C,0x00,0x00}, // 0x35
+{0x06,0x08,0x0E,0x09,0x09,0x06,0x00,0x00}, // 0x36
+{0x0F,0x01,0x02,0x04,0x04,0x04,0x00,0x00}, // 0x37
+{0x06,0x09,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x38
+{0x06,0x09,0x09,0x07,0x01,0x06,0x00,0x00}, // 0x39
+{0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00}, // 0x3A
+{0x00,0x00,0x04,0x00,0x00,0x04,0x04,0x08}, // 0x3B
+{0x00,0x01,0x02,0x0C,0x02,0x01,0x00,0x00}, // 0x3C
+{0x00,0x00,0x0F,0x00,0x0F,0x00,0x00,0x00}, // 0x3D
+{0x00,0x08,0x04,0x03,0x04,0x08,0x00,0x00}, // 0x3E
+{0x0E,0x01,0x02,0x04,0x00,0x04,0x00,0x00}, // 0x3F
+{0x06,0x09,0x13,0x15,0x17,0x10,0x0F,0x00}, // 0x40
+{0x00,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0x41
+{0x00,0x0E,0x0A,0x0C,0x0A,0x0E,0x00,0x00}, // 0x42
+{0x00,0x07,0x08,0x08,0x08,0x07,0x00,0x00}, // 0x43
+{0x00,0x0E,0x09,0x09,0x09,0x0E,0x00,0x00}, // 0x44
+{0x00,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0x45
+{0x00,0x0E,0x08,0x0E,0x08,0x08,0x00,0x00}, // 0x46
+{0x00,0x07,0x08,0x0B,0x09,0x07,0x00,0x00}, // 0x47
+{0x00,0x09,0x09,0x0F,0x09,0x09,0x00,0x00}, // 0x48
+{0x00,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0x49
+{0x00,0x0E,0x02,0x02,0x02,0x0C,0x00,0x00}, // 0x4A
+{0x00,0x09,0x0A,0x0C,0x0A,0x09,0x00,0x00}, // 0x4B
+{0x00,0x08,0x08,0x08,0x08,0x0F,0x00,0x00}, // 0x4C
+{0x00,0x11,0x1B,0x15,0x15,0x11,0x00,0x00}, // 0x4D
+{0x00,0x09,0x0D,0x0B,0x09,0x09,0x00,0x00}, // 0x4E
+{0x00,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0x4F
+{0x00,0x0E,0x09,0x0E,0x08,0x08,0x00,0x00}, // 0x50
+{0x00,0x0E,0x11,0x11,0x11,0x0E,0x02,0x01}, // 0x51
+{0x00,0x0C,0x0A,0x0C,0x0A,0x09,0x00,0x00}, // 0x52
+{0x00,0x06,0x08,0x04,0x02,0x0C,0x00,0x00}, // 0x53
+{0x00,0x1F,0x04,0x04,0x04,0x04,0x00,0x00}, // 0x54
+{0x00,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0x55
+{0x00,0x09,0x09,0x09,0x06,0x06,0x00,0x00}, // 0x56
+{0x00,0x11,0x15,0x15,0x0A,0x0A,0x00,0x00}, // 0x57
+{0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00}, // 0x58
+{0x00,0x11,0x0A,0x04,0x04,0x04,0x00,0x00}, // 0x59
+{0x00,0x0F,0x01,0x06,0x08,0x0F,0x00,0x00}, // 0x5A
+{0x06,0x04,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x5B
+{0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00}, // 0x5C
+{0x0C,0x04,0x04,0x04,0x04,0x04,0x0C,0x00}, // 0x5D
+{0x04,0x0A,0x0A,0x11,0x11,0x00,0x00,0x00}, // 0x5E
+{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00}, // 0x5F
+{0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60
+{0x00,0x00,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x61
+{0x08,0x08,0x0E,0x09,0x09,0x0E,0x00,0x00}, // 0x62
+{0x00,0x00,0x06,0x08,0x08,0x06,0x00,0x00}, // 0x63
+{0x02,0x02,0x0E,0x12,0x12,0x0E,0x00,0x00}, // 0x64
+{0x00,0x00,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x65
+{0x03,0x04,0x0F,0x04,0x04,0x04,0x00,0x00}, // 0x66
+{0x00,0x00,0x07,0x09,0x0F,0x01,0x0E,0x00}, // 0x67
+{0x08,0x08,0x0A,0x0D,0x09,0x09,0x00,0x00}, // 0x68
+{0x04,0x00,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x69
+{0x02,0x00,0x0E,0x02,0x02,0x02,0x0C,0x00}, // 0x6A
+{0x08,0x08,0x0A,0x0C,0x0A,0x09,0x00,0x00}, // 0x6B
+{0x0C,0x04,0x04,0x04,0x04,0x04,0x00,0x00}, // 0x6C
+{0x00,0x00,0x15,0x1F,0x15,0x15,0x00,0x00}, // 0x6D
+{0x00,0x00,0x0A,0x0D,0x09,0x09,0x00,0x00}, // 0x6E
+{0x00,0x00,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x6F
+{0x00,0x00,0x0E,0x09,0x09,0x0E,0x08,0x00}, // 0x70
+{0x00,0x00,0x0E,0x12,0x12,0x0E,0x02,0x00}, // 0x71
+{0x00,0x00,0x0A,0x0C,0x08,0x08,0x00,0x00}, // 0x72
+{0x00,0x00,0x06,0x0C,0x02,0x0C,0x00,0x00}, // 0x73
+{0x00,0x04,0x0F,0x04,0x04,0x02,0x00,0x00}, // 0x74
+{0x00,0x00,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x75
+{0x00,0x00,0x09,0x09,0x06,0x06,0x00,0x00}, // 0x76
+{0x00,0x00,0x15,0x15,0x0E,0x0A,0x00,0x00}, // 0x77
+{0x00,0x00,0x09,0x06,0x06,0x09,0x00,0x00}, // 0x78
+{0x00,0x00,0x09,0x09,0x06,0x06,0x1C,0x00}, // 0x79
+{0x00,0x00,0x0E,0x06,0x08,0x0E,0x00,0x00}, // 0x7A
+{0x02,0x04,0x04,0x08,0x04,0x04,0x02,0x00}, // 0x7B
+{0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00}, // 0x7C
+{0x08,0x04,0x04,0x02,0x04,0x04,0x08,0x00}, // 0x7D
+{0x00,0x00,0x00,0x0D,0x12,0x00,0x00,0x00}, // 0x7E
+{0x00,0x04,0x0A,0x0A,0x0A,0x0E,0x00,0x00}, // 0x7F
+{0x00,0x07,0x08,0x08,0x08,0x07,0x02,0x04}, // 0x80
+{0x09,0x00,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x81
+{0x01,0x02,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x82
+{0x06,0x09,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x83
+{0x0A,0x00,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x84
+{0x10,0x08,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x85
+{0x04,0x0A,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x86
+{0x00,0x00,0x06,0x08,0x08,0x06,0x02,0x04}, // 0x87
+{0x06,0x09,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x88
+{0x0A,0x00,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x89
+{0x10,0x08,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x8A
+{0x0A,0x00,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x8B
+{0x06,0x09,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x8C
+{0x10,0x08,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x8D
+{0x0A,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0x8E
+{0x04,0x0A,0x04,0x0A,0x1F,0x11,0x00,0x00}, // 0x8F
+{0x01,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0x90
+{0x00,0x00,0x1A,0x07,0x1C,0x13,0x00,0x00}, // 0x91
+{0x00,0x07,0x0A,0x0B,0x1E,0x13,0x00,0x00}, // 0x92
+{0x0C,0x12,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x93
+{0x09,0x00,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x94
+{0x10,0x08,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x95
+{0x0C,0x12,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x96
+{0x08,0x04,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x97
+{0x09,0x00,0x09,0x09,0x06,0x06,0x1C,0x00}, // 0x98
+{0x11,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0x99
+{0x12,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0x9A
+{0x00,0x01,0x06,0x0B,0x0D,0x06,0x08,0x00}, // 0x9B
+{0x00,0x04,0x08,0x0C,0x18,0x0E,0x00,0x00}, // 0x9C
+{0x01,0x0E,0x13,0x15,0x19,0x0E,0x10,0x00}, // 0x9D
+{0x00,0x00,0x09,0x06,0x06,0x09,0x00,0x00}, // 0x9E
+{0x02,0x04,0x04,0x0E,0x04,0x04,0x08,0x00}, // 0x9F
+{0x01,0x02,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0xA0
+{0x01,0x02,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0xA1
+{0x01,0x02,0x06,0x09,0x09,0x06,0x00,0x00}, // 0xA2
+{0x01,0x02,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0xA3
+{0x0F,0x00,0x0A,0x0D,0x09,0x09,0x00,0x00}, // 0xA4
+{0x1F,0x09,0x0D,0x0B,0x09,0x09,0x00,0x00}, // 0xA5
+{0x0C,0x02,0x0E,0x0A,0x0E,0x00,0x00,0x00}, // 0xA6
+{0x04,0x0A,0x0A,0x0A,0x04,0x00,0x00,0x00}, // 0xA7
+{0x00,0x04,0x00,0x04,0x04,0x02,0x0C,0x00}, // 0xA8
+{0x0E,0x17,0x17,0x15,0x17,0x0E,0x00,0x00}, // 0xA9
+{0x00,0x00,0x00,0x0E,0x02,0x02,0x00,0x00}, // 0xAA
+{0x19,0x0A,0x0F,0x05,0x0A,0x13,0x00,0x00}, // 0xAB
+{0x19,0x0A,0x0A,0x05,0x0B,0x11,0x00,0x00}, // 0xAC
+{0x00,0x00,0x04,0x00,0x04,0x04,0x04,0x00}, // 0xAD
+{0x00,0x05,0x0A,0x14,0x0A,0x05,0x00,0x00}, // 0xAE
+{0x00,0x14,0x0A,0x05,0x0A,0x14,0x00,0x00}, // 0xAF
+{0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00}, // 0xB0
+{0x15,0x0A,0x15,0x0A,0x15,0x0A,0x15,0x0A}, // 0xB1
+{0x1F,0x15,0x1F,0x15,0x1F,0x15,0x1F,0x15}, // 0xB2
+{0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}, // 0xB3
+{0x04,0x04,0x04,0x1C,0x04,0x04,0x04,0x04}, // 0xB4
+{0x02,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0xB5
+{0x06,0x09,0x04,0x0A,0x1F,0x11,0x00,0x00}, // 0xB6
+{0x08,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0xB7
+{0x0E,0x11,0x17,0x15,0x17,0x11,0x0E,0x00}, // 0xB8
+{0x0A,0x0A,0x1A,0x02,0x1A,0x0A,0x0A,0x0A}, // 0xB9
+{0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A}, // 0xBA
+{0x00,0x00,0x1E,0x02,0x1A,0x0A,0x0A,0x0A}, // 0xBB
+{0x0A,0x0A,0x1A,0x02,0x1E,0x00,0x00,0x00}, // 0xBC
+{0x00,0x04,0x0E,0x08,0x0E,0x04,0x00,0x00}, // 0xBD
+{0x00,0x11,0x0A,0x04,0x0E,0x04,0x00,0x00}, // 0xBE
+{0x00,0x00,0x00,0x1C,0x04,0x04,0x04,0x04}, // 0xBF
+{0x04,0x04,0x04,0x07,0x00,0x00,0x00,0x00}, // 0xC0
+{0x04,0x04,0x04,0x1F,0x00,0x00,0x00,0x00}, // 0xC1
+{0x00,0x00,0x00,0x1F,0x04,0x04,0x04,0x04}, // 0xC2
+{0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04}, // 0xC3
+{0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00}, // 0xC4
+{0x04,0x04,0x04,0x1F,0x04,0x04,0x04,0x04}, // 0xC5
+{0x0D,0x12,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0xC6
+{0x0D,0x12,0x04,0x0A,0x1F,0x11,0x00,0x00}, // 0xC7
+{0x0A,0x0A,0x0B,0x08,0x0F,0x00,0x00,0x00}, // 0xC8
+{0x00,0x00,0x0F,0x08,0x0B,0x0A,0x0A,0x0A}, // 0xC9
+{0x0A,0x0A,0x1B,0x00,0x1F,0x00,0x00,0x00}, // 0xCA
+{0x00,0x00,0x1F,0x00,0x1B,0x0A,0x0A,0x0A}, // 0xCB
+{0x0A,0x0A,0x0B,0x08,0x0B,0x0A,0x0A,0x0A}, // 0xCC
+{0x00,0x00,0x1F,0x00,0x1F,0x00,0x00,0x00}, // 0xCD
+{0x0A,0x0A,0x1B,0x00,0x1B,0x0A,0x0A,0x0A}, // 0xCE
+{0x00,0x11,0x0E,0x0A,0x0E,0x11,0x00,0x00}, // 0xCF
+{0x1E,0x04,0x0E,0x12,0x12,0x0C,0x00,0x00}, // 0xD0
+{0x00,0x0E,0x09,0x1D,0x09,0x0E,0x00,0x00}, // 0xD1
+{0x0E,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0xD2
+{0x11,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0xD3
+{0x10,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0xD4
+{0x00,0x00,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0xD5
+{0x01,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xD6
+{0x0E,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xD7
+{0x11,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xD8
+{0x04,0x04,0x04,0x1C,0x00,0x00,0x00,0x00}, // 0xD9
+{0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04}, // 0xDA
+{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, // 0xDB
+{0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F}, // 0xDC
+{0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x04}, // 0xDD
+{0x10,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xDE
+{0x1F,0x1F,0x1F,0x1F,0x00,0x00,0x00,0x00}, // 0xDF
+{0x01,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE0
+{0x04,0x0A,0x0A,0x0A,0x09,0x0A,0x00,0x00}, // 0xE1
+{0x0E,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE2
+{0x10,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE3
+{0x0D,0x12,0x06,0x09,0x09,0x06,0x00,0x00}, // 0xE4
+{0x1E,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE5
+{0x00,0x00,0x09,0x09,0x0B,0x0D,0x08,0x00}, // 0xE6
+{0x08,0x08,0x0E,0x09,0x09,0x0E,0x08,0x00}, // 0xE7
+{0x00,0x08,0x0E,0x09,0x0E,0x08,0x00,0x00}, // 0xE8
+{0x01,0x12,0x12,0x12,0x12,0x0C,0x00,0x00}, // 0xE9
+{0x0F,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0xEA
+{0x10,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0xEB
+{0x01,0x02,0x09,0x09,0x06,0x06,0x18,0x00}, // 0xEC
+{0x02,0x15,0x0A,0x04,0x04,0x04,0x00,0x00}, // 0xED
+{0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEE
+{0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEF
+{0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0xF0
+{0x00,0x00,0x04,0x0E,0x04,0x0E,0x00,0x00}, // 0xF1
+{0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x1F}, // 0xF2
+{0x19,0x1A,0x0A,0x1D,0x0B,0x11,0x00,0x00}, // 0xF3
+{0x0E,0x1A,0x1A,0x0A,0x0A,0x0A,0x0A,0x00}, // 0xF4
+{0x06,0x08,0x04,0x0A,0x04,0x02,0x0C,0x00}, // 0xF5
+{0x00,0x04,0x00,0x0E,0x00,0x04,0x00,0x00}, // 0xF6
+{0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x08}, // 0xF7
+{0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00}, // 0xF8
+{0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF9
+{0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00}, // 0xFA
+{0x0C,0x04,0x04,0x04,0x0E,0x00,0x00,0x00}, // 0xFB
+{0x0C,0x02,0x0C,0x02,0x0C,0x00,0x00,0x00}, // 0xFC
+{0x0C,0x02,0x04,0x08,0x0E,0x00,0x00,0x00}, // 0xFD
+{0x00,0x00,0x0F,0x0F,0x0F,0x0F,0x00,0x00}, // 0xFE
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
+};
+
+#endif // font_5x8_horizontal_MSB_h
\ No newline at end of file
diff --git a/lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h b/lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h
new file mode 100644
index 000000000..cc3a323cc
--- /dev/null
+++ b/lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h
@@ -0,0 +1,264 @@
+// 6x8 ascii font
+#ifndef font_6x8_horizontal_MSB_h
+#define font_6x8_horizontal_MSB_h
+
+const char font[256][8]={
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
+{0x0E,0x11,0x1B,0x11,0x15,0x11,0x0E,0x00}, // 0x01
+{0x0E,0x1F,0x15,0x1F,0x11,0x1F,0x0E,0x00}, // 0x02
+{0x00,0x0A,0x1F,0x1F,0x1F,0x0E,0x04,0x00}, // 0x03
+{0x00,0x04,0x0E,0x1F,0x1F,0x0E,0x04,0x00}, // 0x04
+{0x04,0x0E,0x0E,0x04,0x1F,0x1F,0x04,0x00}, // 0x05
+{0x00,0x04,0x0E,0x1F,0x1F,0x04,0x0E,0x00}, // 0x06
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
+{0x00,0x07,0x03,0x0D,0x12,0x12,0x0C,0x00}, // 0x0B
+{0x0E,0x11,0x11,0x0E,0x04,0x0E,0x04,0x00}, // 0x0C
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
+{0x03,0x0D,0x0B,0x0D,0x0B,0x1B,0x18,0x00}, // 0x0E
+{0x00,0x15,0x0E,0x1B,0x0E,0x15,0x00,0x00}, // 0x0F
+{0x08,0x0C,0x0E,0x0F,0x0E,0x0C,0x08,0x00}, // 0x10
+{0x02,0x06,0x0E,0x1E,0x0E,0x06,0x02,0x00}, // 0x11
+{0x04,0x0E,0x1F,0x04,0x1F,0x0E,0x04,0x00}, // 0x12
+{0x0A,0x0A,0x0A,0x0A,0x0A,0x00,0x0A,0x00}, // 0x13
+{0x0F,0x15,0x15,0x0D,0x05,0x05,0x05,0x00}, // 0x14
+{0x0E,0x11,0x0C,0x0A,0x06,0x11,0x0E,0x00}, // 0x15
+{0x00,0x00,0x00,0x00,0x00,0x1E,0x1E,0x00}, // 0x16
+{0x04,0x0E,0x1F,0x04,0x1F,0x0E,0x04,0x0E}, // 0x17
+{0x04,0x0E,0x1F,0x04,0x04,0x04,0x04,0x00}, // 0x18
+{0x04,0x04,0x04,0x04,0x1F,0x0E,0x04,0x00}, // 0x19
+{0x00,0x04,0x06,0x1F,0x06,0x04,0x00,0x00}, // 0x1A
+{0x00,0x04,0x0C,0x1F,0x0C,0x04,0x00,0x00}, // 0x1B
+{0x00,0x00,0x00,0x10,0x10,0x10,0x1F,0x00}, // 0x1C
+{0x00,0x0A,0x0A,0x1F,0x0A,0x0A,0x00,0x00}, // 0x1D
+{0x04,0x04,0x0E,0x0E,0x1F,0x1F,0x00,0x00}, // 0x1E
+{0x1F,0x1F,0x0E,0x0E,0x04,0x04,0x00,0x00}, // 0x1F
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
+{0x04,0x0E,0x0E,0x04,0x04,0x00,0x04,0x00}, // 0x21
+{0x1B,0x1B,0x12,0x00,0x00,0x00,0x00,0x00}, // 0x22
+{0x00,0x0A,0x1F,0x0A,0x0A,0x1F,0x0A,0x00}, // 0x23
+{0x08,0x0E,0x10,0x0C,0x02,0x1C,0x04,0x00}, // 0x24
+{0x19,0x19,0x02,0x04,0x08,0x13,0x13,0x00}, // 0x25
+{0x08,0x14,0x14,0x08,0x15,0x12,0x0D,0x00}, // 0x26
+{0x0C,0x0C,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x27
+{0x04,0x08,0x08,0x08,0x08,0x08,0x04,0x00}, // 0x28
+{0x08,0x04,0x04,0x04,0x04,0x04,0x08,0x00}, // 0x29
+{0x00,0x0A,0x0E,0x1F,0x0E,0x0A,0x00,0x00}, // 0x2A
+{0x00,0x04,0x04,0x1F,0x04,0x04,0x00,0x00}, // 0x2B
+{0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x08}, // 0x2C
+{0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00}, // 0x2D
+{0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x00}, // 0x2E
+{0x00,0x01,0x02,0x04,0x08,0x10,0x00,0x00}, // 0x2F
+{0x0E,0x11,0x13,0x15,0x19,0x11,0x0E,0x00}, // 0x30
+{0x04,0x0C,0x04,0x04,0x04,0x04,0x0E,0x00}, // 0x31
+{0x0E,0x11,0x01,0x06,0x08,0x10,0x1F,0x00}, // 0x32
+{0x0E,0x11,0x01,0x0E,0x01,0x11,0x0E,0x00}, // 0x33
+{0x02,0x06,0x0A,0x12,0x1F,0x02,0x02,0x00}, // 0x34
+{0x1F,0x10,0x10,0x1E,0x01,0x11,0x0E,0x00}, // 0x35
+{0x06,0x08,0x10,0x1E,0x11,0x11,0x0E,0x00}, // 0x36
+{0x1F,0x01,0x02,0x04,0x08,0x08,0x08,0x00}, // 0x37
+{0x0E,0x11,0x11,0x0E,0x11,0x11,0x0E,0x00}, // 0x38
+{0x0E,0x11,0x11,0x0F,0x01,0x02,0x0C,0x00}, // 0x39
+{0x00,0x00,0x0C,0x0C,0x00,0x0C,0x0C,0x00}, // 0x3A
+{0x00,0x00,0x0C,0x0C,0x00,0x0C,0x0C,0x08}, // 0x3B
+{0x02,0x04,0x08,0x10,0x08,0x04,0x02,0x00}, // 0x3C
+{0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00}, // 0x3D
+{0x08,0x04,0x02,0x01,0x02,0x04,0x08,0x00}, // 0x3E
+{0x0E,0x11,0x01,0x06,0x04,0x00,0x04,0x00}, // 0x3F
+{0x0E,0x11,0x17,0x15,0x17,0x10,0x0E,0x00}, // 0x40
+{0x0E,0x11,0x11,0x11,0x1F,0x11,0x11,0x00}, // 0x41
+{0x1E,0x11,0x11,0x1E,0x11,0x11,0x1E,0x00}, // 0x42
+{0x0E,0x11,0x10,0x10,0x10,0x11,0x0E,0x00}, // 0x43
+{0x1E,0x11,0x11,0x11,0x11,0x11,0x1E,0x00}, // 0x44
+{0x1F,0x10,0x10,0x1E,0x10,0x10,0x1F,0x00}, // 0x45
+{0x1F,0x10,0x10,0x1E,0x10,0x10,0x10,0x00}, // 0x46
+{0x0E,0x11,0x10,0x17,0x11,0x11,0x0F,0x00}, // 0x47
+{0x11,0x11,0x11,0x1F,0x11,0x11,0x11,0x00}, // 0x48
+{0x0E,0x04,0x04,0x04,0x04,0x04,0x0E,0x00}, // 0x49
+{0x01,0x01,0x01,0x01,0x11,0x11,0x0E,0x00}, // 0x4A
+{0x11,0x12,0x14,0x18,0x14,0x12,0x11,0x00}, // 0x4B
+{0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0x00}, // 0x4C
+{0x11,0x1B,0x15,0x11,0x11,0x11,0x11,0x00}, // 0x4D
+{0x11,0x19,0x15,0x13,0x11,0x11,0x11,0x00}, // 0x4E
+{0x0E,0x11,0x11,0x11,0x11,0x11,0x0E,0x00}, // 0x4F
+{0x1E,0x11,0x11,0x1E,0x10,0x10,0x10,0x00}, // 0x50
+{0x0E,0x11,0x11,0x11,0x15,0x12,0x0D,0x00}, // 0x51
+{0x1E,0x11,0x11,0x1E,0x12,0x11,0x11,0x00}, // 0x52
+{0x0E,0x11,0x10,0x0E,0x01,0x11,0x0E,0x00}, // 0x53
+{0x1F,0x04,0x04,0x04,0x04,0x04,0x04,0x00}, // 0x54
+{0x11,0x11,0x11,0x11,0x11,0x11,0x0E,0x00}, // 0x55
+{0x11,0x11,0x11,0x11,0x11,0x0A,0x04,0x00}, // 0x56
+{0x11,0x11,0x15,0x15,0x15,0x15,0x0A,0x00}, // 0x57
+{0x11,0x11,0x0A,0x04,0x0A,0x11,0x11,0x00}, // 0x58
+{0x11,0x11,0x11,0x0A,0x04,0x04,0x04,0x00}, // 0x59
+{0x1E,0x02,0x04,0x08,0x10,0x10,0x1E,0x00}, // 0x5A
+{0x0E,0x08,0x08,0x08,0x08,0x08,0x0E,0x00}, // 0x5B
+{0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00}, // 0x5C
+{0x0E,0x02,0x02,0x02,0x02,0x02,0x0E,0x00}, // 0x5D
+{0x04,0x0A,0x11,0x00,0x00,0x00,0x00,0x00}, // 0x5E
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F}, // 0x5F
+{0x0C,0x0C,0x04,0x00,0x00,0x00,0x00,0x00}, // 0x60
+{0x00,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x61
+{0x10,0x10,0x1E,0x11,0x11,0x11,0x1E,0x00}, // 0x62
+{0x00,0x00,0x0E,0x11,0x10,0x11,0x0E,0x00}, // 0x63
+{0x01,0x01,0x0F,0x11,0x11,0x11,0x0F,0x00}, // 0x64
+{0x00,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x65
+{0x06,0x08,0x08,0x1E,0x08,0x08,0x08,0x00}, // 0x66
+{0x00,0x00,0x0F,0x11,0x11,0x0F,0x01,0x0E}, // 0x67
+{0x10,0x10,0x1C,0x12,0x12,0x12,0x12,0x00}, // 0x68
+{0x04,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x69
+{0x02,0x00,0x06,0x02,0x02,0x02,0x12,0x0C}, // 0x6A
+{0x10,0x10,0x12,0x14,0x18,0x14,0x12,0x00}, // 0x6B
+{0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x6C
+{0x00,0x00,0x1A,0x15,0x15,0x11,0x11,0x00}, // 0x6D
+{0x00,0x00,0x1C,0x12,0x12,0x12,0x12,0x00}, // 0x6E
+{0x00,0x00,0x0E,0x11,0x11,0x11,0x0E,0x00}, // 0x6F
+{0x00,0x00,0x1E,0x11,0x11,0x11,0x1E,0x10}, // 0x70
+{0x00,0x00,0x0F,0x11,0x11,0x11,0x0F,0x01}, // 0x71
+{0x00,0x00,0x16,0x09,0x08,0x08,0x1C,0x00}, // 0x72
+{0x00,0x00,0x0E,0x10,0x0E,0x01,0x0E,0x00}, // 0x73
+{0x00,0x08,0x1E,0x08,0x08,0x0A,0x04,0x00}, // 0x74
+{0x00,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x75
+{0x00,0x00,0x11,0x11,0x11,0x0A,0x04,0x00}, // 0x76
+{0x00,0x00,0x11,0x11,0x15,0x1F,0x0A,0x00}, // 0x77
+{0x00,0x00,0x12,0x12,0x0C,0x12,0x12,0x00}, // 0x78
+{0x00,0x00,0x12,0x12,0x12,0x0E,0x04,0x18}, // 0x79
+{0x00,0x00,0x1E,0x02,0x0C,0x10,0x1E,0x00}, // 0x7A
+{0x06,0x08,0x08,0x18,0x08,0x08,0x06,0x00}, // 0x7B
+{0x04,0x04,0x04,0x00,0x04,0x04,0x04,0x00}, // 0x7C
+{0x0C,0x02,0x02,0x03,0x02,0x02,0x0C,0x00}, // 0x7D
+{0x0A,0x14,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7E
+{0x04,0x0E,0x1B,0x11,0x11,0x1F,0x00,0x00}, // 0x7F
+{0x0E,0x11,0x10,0x10,0x11,0x0E,0x04,0x0C}, // 0x80
+{0x12,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x81
+{0x03,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x82
+{0x0E,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x83
+{0x0A,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x84
+{0x0C,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x85
+{0x0E,0x0A,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x86
+{0x00,0x0E,0x11,0x10,0x11,0x0E,0x04,0x0C}, // 0x87
+{0x0E,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x88
+{0x0A,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x89
+{0x0C,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x8A
+{0x0A,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8B
+{0x0E,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8C
+{0x08,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8D
+{0x0A,0x00,0x04,0x0A,0x11,0x1F,0x11,0x00}, // 0x8E
+{0x0E,0x0A,0x0E,0x1B,0x11,0x1F,0x11,0x00}, // 0x8F
+{0x03,0x00,0x1F,0x10,0x1E,0x10,0x1F,0x00}, // 0x90
+{0x00,0x00,0x1E,0x05,0x1F,0x14,0x0F,0x00}, // 0x91
+{0x0F,0x14,0x14,0x1F,0x14,0x14,0x17,0x00}, // 0x92
+{0x0E,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x93
+{0x0A,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x94
+{0x18,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x95
+{0x0E,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x96
+{0x18,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x97
+{0x0A,0x00,0x12,0x12,0x12,0x0E,0x04,0x18}, // 0x98
+{0x12,0x0C,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0x99
+{0x0A,0x00,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0x9A
+{0x00,0x00,0x01,0x0E,0x16,0x1A,0x1C,0x20}, // 0x9B
+{0x06,0x09,0x08,0x1E,0x08,0x09,0x17,0x00}, // 0x9C
+{0x0F,0x13,0x15,0x15,0x15,0x19,0x1E,0x00}, // 0x9D
+{0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00}, // 0x9E
+{0x02,0x05,0x04,0x0E,0x04,0x04,0x14,0x08}, // 0x9F
+{0x06,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0xA0
+{0x06,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0xA1
+{0x06,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0xA2
+{0x06,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0xA3
+{0x0A,0x14,0x00,0x1C,0x12,0x12,0x12,0x00}, // 0xA4
+{0x0A,0x14,0x00,0x12,0x1A,0x16,0x12,0x00}, // 0xA5
+{0x0E,0x01,0x0F,0x11,0x0F,0x00,0x0F,0x00}, // 0xA6
+{0x0C,0x12,0x12,0x12,0x0C,0x00,0x1E,0x00}, // 0xA7
+{0x04,0x00,0x04,0x0C,0x10,0x11,0x0E,0x00}, // 0xA8
+{0x1E,0x25,0x2B,0x2D,0x2B,0x21,0x1E,0x00}, // 0xA9
+{0x00,0x00,0x3F,0x01,0x01,0x00,0x00,0x00}, // 0xAA
+{0x10,0x12,0x14,0x0E,0x11,0x02,0x07,0x00}, // 0xAB
+{0x10,0x12,0x14,0x0B,0x15,0x07,0x01,0x00}, // 0xAC
+{0x04,0x00,0x04,0x04,0x0E,0x0E,0x04,0x00}, // 0xAD
+{0x00,0x00,0x09,0x12,0x09,0x00,0x00,0x00}, // 0xAE
+{0x00,0x00,0x12,0x09,0x12,0x00,0x00,0x00}, // 0xAF
+{0x15,0x00,0x2A,0x00,0x15,0x00,0x2A,0x00}, // 0xB0
+{0x15,0x2A,0x15,0x2A,0x15,0x2A,0x15,0x2A}, // 0xB1
+{0x2A,0x3F,0x15,0x3F,0x2A,0x3F,0x15,0x3F}, // 0xB2
+{0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}, // 0xB3
+{0x04,0x04,0x04,0x3C,0x04,0x04,0x04,0x04}, // 0xB4
+{0x06,0x00,0x04,0x0A,0x11,0x1F,0x11,0x00}, // 0xB5
+{0x0E,0x00,0x04,0x0A,0x11,0x1F,0x11,0x00}, // 0xB6
+{0x0C,0x00,0x04,0x0A,0x11,0x1F,0x11,0x00}, // 0xB7
+{0x1E,0x21,0x2D,0x29,0x2D,0x21,0x1E,0x00}, // 0xB8
+{0x14,0x34,0x04,0x34,0x14,0x14,0x14,0x14}, // 0xB9
+{0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14}, // 0xBA
+{0x00,0x3C,0x04,0x34,0x14,0x14,0x14,0x14}, // 0xBB
+{0x14,0x34,0x04,0x3C,0x00,0x00,0x00,0x00}, // 0xBC
+{0x00,0x04,0x0E,0x10,0x10,0x0E,0x04,0x00}, // 0xBD
+{0x11,0x0A,0x04,0x1F,0x04,0x1F,0x04,0x00}, // 0xBE
+{0x00,0x00,0x00,0x3C,0x04,0x04,0x04,0x04}, // 0xBF
+{0x04,0x04,0x04,0x07,0x00,0x00,0x00,0x00}, // 0xC0
+{0x04,0x04,0x04,0x3F,0x00,0x00,0x00,0x00}, // 0xC1
+{0x00,0x00,0x00,0x3F,0x04,0x04,0x04,0x04}, // 0xC2
+{0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04}, // 0xC3
+{0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00}, // 0xC4
+{0x04,0x04,0x04,0x3F,0x04,0x04,0x04,0x04}, // 0xC5
+{0x05,0x0A,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0xC6
+{0x05,0x0A,0x04,0x0A,0x11,0x1F,0x11,0x00}, // 0xC7
+{0x14,0x17,0x10,0x1F,0x00,0x00,0x00,0x00}, // 0xC8
+{0x00,0x1F,0x10,0x17,0x14,0x14,0x14,0x14}, // 0xC9
+{0x14,0x37,0x00,0x3F,0x00,0x00,0x00,0x00}, // 0xCA
+{0x00,0x3F,0x00,0x37,0x14,0x14,0x14,0x14}, // 0xCB
+{0x14,0x17,0x10,0x17,0x14,0x14,0x14,0x14}, // 0xCC
+{0x00,0x3F,0x00,0x3F,0x00,0x00,0x00,0x00}, // 0xCD
+{0x14,0x37,0x00,0x37,0x14,0x14,0x14,0x14}, // 0xCE
+{0x11,0x0E,0x11,0x11,0x11,0x0E,0x11,0x00}, // 0xCF
+{0x0C,0x10,0x08,0x04,0x0E,0x12,0x0C,0x00}, // 0xD0
+{0x0E,0x09,0x09,0x1D,0x09,0x09,0x0E,0x00}, // 0xD1
+{0x0E,0x00,0x1F,0x10,0x1E,0x10,0x1F,0x00}, // 0xD2
+{0x0A,0x00,0x1F,0x10,0x1E,0x10,0x1F,0x00}, // 0xD3
+{0x0C,0x00,0x1F,0x10,0x1E,0x10,0x1F,0x00}, // 0xD4
+{0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00}, // 0xD5
+{0x06,0x00,0x0E,0x04,0x04,0x04,0x0E,0x00}, // 0xD6
+{0x0E,0x00,0x0E,0x04,0x04,0x04,0x0E,0x00}, // 0xD7
+{0x0A,0x00,0x0E,0x04,0x04,0x04,0x0E,0x00}, // 0xD8
+{0x04,0x04,0x04,0x3C,0x00,0x00,0x00,0x00}, // 0xD9
+{0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04}, // 0xDA
+{0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F}, // 0xDB
+{0x00,0x00,0x00,0x00,0x3F,0x3F,0x3F,0x3F}, // 0xDC
+{0x04,0x04,0x04,0x00,0x04,0x04,0x04,0x00}, // 0xDD
+{0x0C,0x00,0x0E,0x04,0x04,0x04,0x0E,0x00}, // 0xDE
+{0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00}, // 0xDF
+{0x06,0x0C,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0xE0
+{0x00,0x1C,0x12,0x1C,0x12,0x12,0x1C,0x10}, // 0xE1
+{0x0E,0x0C,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0xE2
+{0x18,0x0C,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0xE3
+{0x0A,0x14,0x00,0x0C,0x12,0x12,0x0C,0x00}, // 0xE4
+{0x0A,0x14,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0xE5
+{0x00,0x00,0x12,0x12,0x12,0x1C,0x10,0x10}, // 0xE6
+{0x00,0x18,0x10,0x1C,0x12,0x1C,0x10,0x18}, // 0xE7
+{0x18,0x10,0x1C,0x12,0x12,0x1C,0x10,0x18}, // 0xE8
+{0x06,0x00,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0xE9
+{0x0E,0x00,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0xEA
+{0x18,0x00,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0xEB
+{0x06,0x00,0x12,0x12,0x12,0x0E,0x04,0x18}, // 0xEC
+{0x06,0x00,0x11,0x0A,0x04,0x04,0x04,0x00}, // 0xED
+{0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEE
+{0x0C,0x0C,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xEF
+{0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0xF0
+{0x00,0x04,0x0E,0x04,0x00,0x0E,0x00,0x00}, // 0xF1
+{0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00}, // 0xF2
+{0x30,0x1A,0x34,0x0B,0x15,0x07,0x01,0x00}, // 0xF3
+{0x0F,0x15,0x15,0x0D,0x05,0x05,0x05,0x00}, // 0xF4
+{0x0E,0x11,0x0C,0x0A,0x06,0x11,0x0E,0x00}, // 0xF5
+{0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x00}, // 0xF6
+{0x00,0x00,0x00,0x0E,0x06,0x00,0x00,0x00}, // 0xF7
+{0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00}, // 0xF8
+{0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x00}, // 0xF9
+{0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00}, // 0xFA
+{0x08,0x18,0x08,0x08,0x00,0x00,0x00,0x00}, // 0xFB
+{0x1C,0x08,0x0C,0x18,0x00,0x00,0x00,0x00}, // 0xFC
+{0x18,0x04,0x08,0x1C,0x00,0x00,0x00,0x00}, // 0xFD
+{0x00,0x00,0x1E,0x1E,0x1E,0x1E,0x00,0x00}, // 0xFE
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
+};
+
+#endif
\ No newline at end of file
diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino
index da3177f59..bbd0a069d 100644
--- a/tasmota/xdsp_19_max7219_matrix.ino
+++ b/tasmota/xdsp_19_max7219_matrix.ino
@@ -175,31 +175,6 @@ bool MAX7291Matrix_init(void)
return true;
}
-// /*********************************************************************************************\
-// * Clears the display
-// * Command: DisplayText
-// \*********************************************************************************************/
-bool MAX7291Matrix_Text()
-{
- char sString[CMD_MAX_LEN + 1];
- subStr(sString, XdrvMailbox.data, ",", 1);
- max7219_Matrix->clear();
- AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: sString %s"), sString);
-
- // test
- uint8_t length = strlen(sString);
- //if(length > modulesPerRow)
- length = modulesPerRow;
-
- for (int addr = 0; addr < length; addr++)
- {
- max7219_Matrix->setPixel(addr, addr, true);
- AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: setPixel() %d, %d)"), addr, addr);
- }
-
- return true;
-}
-
bool Xdsp19(uint8_t function)
{
bool result = false;
@@ -216,7 +191,7 @@ bool Xdsp19(uint8_t function)
result = true;
break;
case FUNC_DISPLAY_CLEAR:
- result = max7219_Matrix->clear();
+ result = max7219_Matrix->clearDisplay();
break;
case FUNC_DISPLAY_DIM:
result = max7219_Matrix->setIntensity(GetDisplayDimmer16());
@@ -232,12 +207,13 @@ bool Xdsp19(uint8_t function)
case FUNC_DISPLAY_SCROLLTEXT:
case FUNC_DISPLAY_CLOCK:
case FUNC_DISPLAY_DRAW_STRING:
- result = MAX7291Matrix_Text();
+ result = max7219_Matrix->drawText(dsp_str);
+ break;
+ case FUNC_DISPLAY_EVERY_SECOND:
+ //result = max7219_Matrix->scrollText();
break;
case FUNC_DISPLAY_EVERY_50_MSECOND:
- case FUNC_DISPLAY_EVERY_SECOND:
- // ignore
- return false;
+ result = max7219_Matrix->scrollText();
default:
result = false;
}
From c4a4bb0ff8ed1cae90237587cbcae0ba091295b8 Mon Sep 17 00:00:00 2001
From: Michael
Date: Tue, 23 Nov 2021 23:08:05 +0100
Subject: [PATCH 007/510] scroll works
---
lib/lib_display/LedControl/src/LedMatrix.cpp | 11 +-
lib/lib_display/LedControl/src/LedMatrix.h | 6 +-
tasmota/tasmota_template.h | 1 +
tasmota/xdsp_19_max7219_matrix.ino | 110 +++++++++++++++----
4 files changed, 102 insertions(+), 26 deletions(-)
diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp
index 19ac0dcb2..80ded02e2 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.cpp
+++ b/lib/lib_display/LedControl/src/LedMatrix.cpp
@@ -62,6 +62,11 @@ LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, un
setIntensity(7);
}
+void LedMatrix::power(bool on)
+{
+ shutdown(!on); // shut down on power off
+}
+
bool LedMatrix::drawText( const char *str)
{
strncpy(textBuf, str, TEXT_BUFFER_SIZE -1);
@@ -70,6 +75,7 @@ bool LedMatrix::drawText( const char *str)
textWidth = strlen(textBuf) * charWidth;
if(textWidth < displayWidth)
{
+ clear();
textPosX = (displayWidth - textWidth) / 2; // center
}
else
@@ -78,7 +84,6 @@ bool LedMatrix::drawText( const char *str)
// Append a space between end of text and the beginning of the repeting text.
appendSpace();
}
- clear();
drawTextAt(textBuf, textPosX, textPosY);
refresh(); // refresh display with new string content
return true;
@@ -102,7 +107,7 @@ bool LedMatrix::scrollText()
if(textWidth < displayWidth) return false; // do not scroll when text fits into the display
textPosX--;
- if(textPosX + textWidth < 0)
+ if(textPosX + textWidth < (int)0)
{
textPosX = 0; // start from the beginning after text scrolled out of display;
}
@@ -255,7 +260,7 @@ void LedMatrix::refresh()
void LedMatrix::refreshByteOfBuffer(int i)
{
int line = i / modulesPerRow;
- int addr = line / 8 + i % modulesPerRow;
+ int addr = (line / 8) * modulesPerRow + i % modulesPerRow;
byte b = buffer[i];
if (moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN)
{
diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h
index 586a06146..1d251030b 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.h
+++ b/lib/lib_display/LedControl/src/LedMatrix.h
@@ -60,11 +60,11 @@ class LedMatrix
ModuleOrientation moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
LedControl* ledControl;
- const unsigned int charWidth = 6;
- const unsigned int charHeight = 8;
+ const int charWidth = 6;
+ const int charHeight = 8;
char textBuf[TEXT_BUFFER_SIZE];
char appendTextBuf[TEXT_APPEND_BUFFER_SIZE];
- unsigned int textWidth; // width of text [pixel]
+ int textWidth; // width of text [pixel]
int textPosX; // horizontal pixel position of scrolling text
int textPosY; // vertical pixelposition of scrolling text;
diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h
index e3f3256fc..13fdf23e4 100644
--- a/tasmota/tasmota_template.h
+++ b/tasmota/tasmota_template.h
@@ -524,6 +524,7 @@ const uint16_t kGpioNiceList[] PROGMEM = {
#ifdef USE_DISPLAY_MAX7219_MATRIX
#undef USE_DISPLAY_MAX7219
#undef USE_DISPLAY_TM1637
+ #define USE_DISPLAY_MODES1TO5
AGPIO(GPIO_MAX7219CLK),
AGPIO(GPIO_MAX7219DIN),
AGPIO(GPIO_MAX7219CS),
diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino
index bbd0a069d..ec82420e2 100644
--- a/tasmota/xdsp_19_max7219_matrix.ino
+++ b/tasmota/xdsp_19_max7219_matrix.ino
@@ -131,16 +131,22 @@ and setting it to 3 alternates between time and date.
\*********************************************************************************************/
#define XDSP_19 19
-#define CMD_MAX_LEN 55
+#include
#include
-LedMatrix *max7219_Matrix;
-bool max2791Matrix_init_done = false;
-byte modulesPerRow = 4;
-byte modulesPerCol = 1;
+LedMatrix *max7219_Matrix = nullptr;
+bool max2791Matrix_initDriver_done = false;
+struct
+{
+ byte modulesPerRow = 4;
+ byte modulesPerCol = 1;
+ bool show_clock = false;
+ const char* timeFormat;
-bool MAX7291Matrix_init(void)
+} LedMatrix_settings;
+
+bool MAX7291Matrix_initDriver(void)
{
if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS))
{
@@ -151,27 +157,79 @@ bool MAX7291Matrix_init(void)
Settings->display_model = XDSP_19;
if (Settings->display_width) // [pixel]
{
- modulesPerRow = (Settings->display_width - 1) / 8 + 1;
+ LedMatrix_settings.modulesPerRow = (Settings->display_width - 1) / 8 + 1;
}
- Settings->display_width = 8 * modulesPerRow;
+ Settings->display_width = 8 * LedMatrix_settings.modulesPerRow;
Settings->display_cols[0] = Settings->display_width;
if (Settings->display_height) // [pixel]
{
- modulesPerCol = (Settings->display_height - 1) / 8 + 1;
+ LedMatrix_settings.modulesPerCol = (Settings->display_height - 1) / 8 + 1;
}
- Settings->display_height = 8 * modulesPerCol;
+ Settings->display_height = 8 * LedMatrix_settings. modulesPerCol;
Settings->display_rows = Settings->display_height;
Settings->display_cols[1] = Settings->display_height;
- max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), modulesPerRow, modulesPerCol);
+ max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol);
+ max2791Matrix_initDriver_done = true;
+
+ return MAX7291Matrix_init();
+}
+
+bool MAX7291Matrix_init(void)
+{
int intensity = GetDisplayDimmer16(); // 0..15
max7219_Matrix->setIntensity(intensity);
int orientation = Settings->display_rotate;
max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)orientation );
- AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init %dx%d modules, orientation: %d, intensity: %d"), modulesPerRow , modulesPerCol, orientation, intensity);
- max2791Matrix_init_done = true;
+ AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_init %dx%d modules, orientation: %d, intensity: %d"), LedMatrix_settings.modulesPerRow , LedMatrix_settings.modulesPerCol, orientation, intensity);
- max7219_Matrix->test();
- AddLog(LOG_LEVEL_INFO, PSTR("DSP: display test"));
+ //max7219_Matrix->test();
+ AddLog(LOG_LEVEL_INFO, PSTR("MTX: display test"));
+ return true;
+}
+
+bool MAX7291Matrix_clock(void)
+{
+ LedMatrix_settings.show_clock = XdrvMailbox.payload;
+ if (ArgC() == 0)
+ XdrvMailbox.payload = 1;
+ if (XdrvMailbox.payload > 1)
+ {
+ LedMatrix_settings.timeFormat = "%H:%M";
+ if(LedMatrix_settings.modulesPerRow > 6)
+ {
+ LedMatrix_settings.timeFormat = "%H:%M:%S";
+ }
+ XdrvMailbox.payload = 2;
+ }
+ else
+ {
+ LedMatrix_settings.timeFormat = "%I:%M";
+ if(LedMatrix_settings.modulesPerRow > 6)
+ {
+ LedMatrix_settings.timeFormat = "%I:%M:%S";
+ }
+ XdrvMailbox.payload = 1;
+ }
+
+ AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: LedMatrix_settings.show_clock %d, timeFormat %s"), LedMatrix_settings.show_clock, LedMatrix_settings.timeFormat);
+
+ //max7219_Matrix->clearDisplay();
+ MAX7291Matrix_showTime();
+ return true;
+}
+
+bool MAX7291Matrix_showTime()
+{
+ time_t rawtime;
+ struct tm *timeinfo;
+ char timeStr[10];
+
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime(timeStr, 10, LedMatrix_settings.timeFormat, timeinfo);
+ //AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: showTime:%s"), timeStr);
+
+ max7219_Matrix->drawText(timeStr);
return true;
}
@@ -179,14 +237,20 @@ bool Xdsp19(uint8_t function)
{
bool result = false;
- if (FUNC_DISPLAY_INIT_DRIVER == function)
+ if (FUNC_DISPLAY_INIT_DRIVER == function && !max2791Matrix_initDriver_done )
{
- result = MAX7291Matrix_init();
+ result = MAX7291Matrix_initDriver();
}
- else if (max7219_Matrix && (XDSP_19 == Settings->display_model))
+ else if (max2791Matrix_initDriver_done && max7219_Matrix && (XDSP_19 == Settings->display_model))
{
switch (function)
{
+ case FUNC_DISPLAY_INIT:
+ result = MAX7291Matrix_init();
+ break;
+ case FUNC_DISPLAY_POWER:
+ max7219_Matrix->power(disp_power!=0);
+ break;
case FUNC_DISPLAY_MODEL:
result = true;
break;
@@ -196,6 +260,9 @@ bool Xdsp19(uint8_t function)
case FUNC_DISPLAY_DIM:
result = max7219_Matrix->setIntensity(GetDisplayDimmer16());
break;
+ case FUNC_DISPLAY_CLOCK:
+ result = MAX7291Matrix_clock();
+ break;
case FUNC_DISPLAY_SEVENSEG_TEXT:
case FUNC_DISPLAY_SEVENSEG_TEXTNC:
case FUNC_DISPLAY_NUMBER:
@@ -205,12 +272,15 @@ bool Xdsp19(uint8_t function)
case FUNC_DISPLAY_RAW:
case FUNC_DISPLAY_LEVEL:
case FUNC_DISPLAY_SCROLLTEXT:
- case FUNC_DISPLAY_CLOCK:
case FUNC_DISPLAY_DRAW_STRING:
result = max7219_Matrix->drawText(dsp_str);
break;
case FUNC_DISPLAY_EVERY_SECOND:
- //result = max7219_Matrix->scrollText();
+ if (LedMatrix_settings.show_clock)
+ {
+ result = MAX7291Matrix_showTime();
+ }
+
break;
case FUNC_DISPLAY_EVERY_50_MSECOND:
result = max7219_Matrix->scrollText();
From f2f6eba00989f03a403f5652d93746ab24adfd9d Mon Sep 17 00:00:00 2001
From: Michael
Date: Wed, 24 Nov 2021 17:24:40 +0100
Subject: [PATCH 008/510] ready for ESP32
---
lib/lib_display/LedControl/src/LedMatrix.cpp | 119 +++-----
lib/lib_display/LedControl/src/LedMatrix.h | 208 +++++++-------
.../LedControl/src/font_5x8_horizontal_MSB.h | 3 +
.../LedControl/src/font_6x8_horizontal_MSB.h | 3 +
.../src/font_8x8_horizontal_latin_MSB.h | 265 ++++++++++++++++++
tasmota/tasmota_template.h | 1 -
tasmota/xdsp_19_max7219_matrix.ino | 201 +++++++------
7 files changed, 515 insertions(+), 285 deletions(-)
create mode 100644 lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h
diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp
index 80ded02e2..b4fb8c260 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.cpp
+++ b/lib/lib_display/LedControl/src/LedMatrix.cpp
@@ -1,5 +1,5 @@
/*
- * LedMatrix.h - Extends the Library LedControl for multiple LED dot matrix modules, based on MAX7219/MAX7221
+ * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix modules, based on MAX7219/MAX7221
* Copyright (c) 2021 Michael Beuss
*
* Permission is hereby granted, free of charge, to any person
@@ -25,7 +25,9 @@
*/
#include "LedMatrix.h"
+//#include "font_5x8_horizontal_MSB.h"
#include "font_6x8_horizontal_MSB.h"
+//#include "font_8x8_horizontal_latin_MSB.h"
// public
LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows)
@@ -44,13 +46,15 @@ LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, un
}
}
+ charWidth = font_char_width; // defined in header file of font
+ charHeight = font_char_height; // defined in header file of font
modulesPerRow = colums;
modulesPerCol = rows;
displayWidth = colums * 8;
displayHeight = rows * 8;
modules = colums * rows;
- moduleOrientation = ORIENTATION_UPSIDE_DOWN;
- ledControl = new LedControl(dataPin, clkPin, csPin, modules);
+ moduleOrientation = ORIENTATION_UPSIDE_DOWN; // use setOrientation() to turn it
+ ledControl = new LedControl(dataPin, clkPin, csPin, modules); // initializes all connected LED matrix modules
textBuf[0] = 0;
textWidth = 0;
textPosX = 0;
@@ -62,11 +66,6 @@ LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, un
setIntensity(7);
}
-void LedMatrix::power(bool on)
-{
- shutdown(!on); // shut down on power off
-}
-
bool LedMatrix::drawText( const char *str)
{
strncpy(textBuf, str, TEXT_BUFFER_SIZE -1);
@@ -75,6 +74,7 @@ bool LedMatrix::drawText( const char *str)
textWidth = strlen(textBuf) * charWidth;
if(textWidth < displayWidth)
{
+ // text fits into the display, place it into the center
clear();
textPosX = (displayWidth - textWidth) / 2; // center
}
@@ -85,7 +85,7 @@ bool LedMatrix::drawText( const char *str)
appendSpace();
}
drawTextAt(textBuf, textPosX, textPosY);
- refresh(); // refresh display with new string content
+ refresh(); // refresh display with the new drawed string content
return true;
}
@@ -116,36 +116,16 @@ bool LedMatrix::scrollText()
int startOfRepeatingTextPos = textPosX + textWidth;
if(startOfRepeatingTextPos < displayWidth)
{
- // Draw repeating text.
+ // draw repeating text
drawTextAt(textBuf, startOfRepeatingTextPos, textPosY);
}
refresh();
return true;
}
-bool LedMatrix::drawCharAt( char c, const int x, const int y)
+void LedMatrix::power(bool on)
{
- // ignore when the character position is not visible on the display
- bool visible = (
- x > 0 - (int)charWidth && x < (int)displayWidth &&
- y > 0 - (int)charHeight && y < (int)displayHeight
- );
- if (!visible) return false;
-
- // ignore the leading bits above charWidth of the font definition
- static const byte charOffset = 8 - charWidth;
-
- for (byte charY = 0; charY < charHeight; charY++)
- {
- char pixelRow = (font[c][charY]) << charOffset; // skip the first bits when the character width is smaller than 8 pixel
- for (byte charX = 0; charX < charWidth; charX++)
- {
- bool pixel = (pixelRow & 0x80); // pixel=true when upper bit is set
- setPixel(x + charX, y + charY, pixel);
- pixelRow = pixelRow << 1; // next pixel
- }
- }
- return true;
+ shutdown(!on); // power(false) shuts down the display with shutdown(true)
}
bool LedMatrix::clearDisplay(void)
@@ -157,17 +137,6 @@ bool LedMatrix::clearDisplay(void)
return true;
}
-
-bool LedMatrix::clear(void)
-{
- memset(buffer, 0, MATRIX_BUFFER_SIZE);
- for (int addr = 0; addr < modules; addr++)
- {
- ledControl->clearDisplay(addr);
- }
- return true;
-}
-
bool LedMatrix::setIntensity(byte dim)
{
for (int addr = 0; addr < modules; addr++)
@@ -208,38 +177,40 @@ bool LedMatrix::setPixel(const int x, const int y, bool on)
return true;
}
-void LedMatrix::test()
+void LedMatrix::refresh()
{
- /*
- const static byte testMatrix[] PROGMEM = {
- B00000010, B00111100, B00111100, B00001000,
- B00000110, B01000010, B01000010, B00010000,
- B00001010, B00000010, B00000010, B00100000,
- B00000010, B00000100, B00001100, B01000100,
- B00000010, B00011000, B00000010, B01111110,
- B00000010, B00100000, B01000010, B00000100,
- B00000000, B01111110, B00111100, B00000100,
- B00000000, B00000000, B00000000, B00000000,
- };
- for (int i = 0; i < 32; i++)
+ for (int i = 0; i < modulesPerRow * displayHeight; i++)
{
- buffer[i] = testMatrix[i];
+ refreshByteOfBuffer(i);
}
- refresh();
- */
- drawText("1234567890");
- delay(1000);
- for( int i=0; i<320; i++)
- {
- delay(50);
- scrollText();
- }
- //drawCharAt(0x31, 1, 0);
- //setPixel(1,30);
- //refresh();
}
-// private
+// private functions
+bool LedMatrix::drawCharAt( char c, const int x, const int y)
+{
+ // ignore when the character position is not visible on the display
+ bool visible = (
+ x > 0 - (int)charWidth && x < (int)displayWidth &&
+ y > 0 - (int)charHeight && y < (int)displayHeight
+ );
+ if (!visible) return false;
+
+ // ignore the leading bits above charWidth of the font definition
+ static const byte charOffset = 8 - charWidth;
+
+ for (byte charY = 0; charY < charHeight; charY++)
+ {
+ char pixelRow = (font[c][charY]) << charOffset; // skip the first bits when the character width is smaller than 8 pixel
+ for (byte charX = 0; charX < charWidth; charX++)
+ {
+ bool pixel = (pixelRow & 0x80); // pixel=true when upper bit is set
+ setPixel(x + charX, y + charY, pixel);
+ pixelRow = pixelRow << 1; // next pixel
+ }
+ }
+ return true;
+}
+
bool LedMatrix::shutdown(bool b)
{
for (int addr = 0; addr < modules; addr++)
@@ -249,12 +220,14 @@ bool LedMatrix::shutdown(bool b)
return true;
}
-void LedMatrix::refresh()
+bool LedMatrix::clear(void)
{
- for (int i = 0; i < modulesPerRow * displayHeight; i++)
+ memset(buffer, 0, MATRIX_BUFFER_SIZE);
+ for (int addr = 0; addr < modules; addr++)
{
- refreshByteOfBuffer(i);
+ ledControl->clearDisplay(addr);
}
+ return true;
}
void LedMatrix::refreshByteOfBuffer(int i)
diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h
index 1d251030b..efb50b8e3 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.h
+++ b/lib/lib_display/LedControl/src/LedMatrix.h
@@ -1,5 +1,5 @@
/*
- * LedMatrix.h - Extends the Library LedControl for multiple LED dot matrix modules, based on MAX7219/MAX7221
+ * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix modules, based on MAX7219/MAX7221
* Copyright (c) 2021 Michael Beuss
*
* Permission is hereby granted, free of charge, to any person
@@ -29,21 +29,21 @@
#include
-#define MATRIX_MAX_MODULES 32
+#define MATRIX_MAX_MODULES 32 // maximum number of modules that can be used
#define MATRIX_BUFFER_SIZE MATRIX_MAX_MODULES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
-#define TEXT_BUFFER_SIZE 256
-#define TEXT_APPEND_BUFFER_SIZE 16
+#define TEXT_BUFFER_SIZE 256 // maximum text length that can be scrolled
+#define TEXT_APPEND_BUFFER_SIZE 16 // used for characters that are appended to the scroll text, before it repeats
/**
* @brief LedMatric controls multiple 8x8 LED dot matrx modules.
- * All modules in rows and clolums together build a common matrix.
+ * All modules in rows and clolums together build a common display pixel matrix.
*
*/
class LedMatrix
{
public:
- enum ModuleOrientation // orientation of 8x8 LED dot matrix mdules (first module is top left)
+ enum ModuleOrientation // orientation of 8x8 LED dot matrix mdules (first module starts at top left)
{
ORIENTATION_NORMAL, // first pixel is on top left, no turn is necessary
ORIENTATION_TURN_RIGHT, // first pixel is on bottom left, for correction it has to turn 90° right
@@ -51,6 +51,100 @@ class LedMatrix
ORIENTATION_TURN_LEFT, // first pixel is on top right, for correction is has to turn 90° left.
};
+ public:
+ /**
+ * @brief Construct a new LED Matrix object
+ *
+ * @param colums of 8x8 LED dot matrix modules
+ * @param rows of 8x8 LED dot matrix modules
+ */
+ LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows);
+
+ /**
+ * @brief Draws a string to the display.
+ * When the text fits into the display, it will be shown in the center.
+ * When the text is longer than than the display width, it can be scrolled per pixel with function scrollText().
+ *
+ * @param str string to display
+ */
+ bool drawText( const char *str );
+
+ /**
+ * @brief Dwaws a character string to a defined display position. The position (x,y) is used for the upper left pixel of the text.
+ * Existing text before the x position will not be cleared. Use refresh() after all text parts are drawed.
+ *
+ * @param str string to display
+ * @param x horizantal pixel position to start with string (0 is most left)
+ * @param y vertical pixel position for the top position of the string (0 is top)
+ */
+ bool drawTextAt( const char *str, const int x, const int y );
+
+ /**
+ * @brief Scroll the current text one pixel to the left.
+ * Repeat with from start when end of text reached. This function can be called every 50 ms to get a propper scroll speed.
+ *
+ */
+ bool scrollText();
+
+ /**
+ * @brief switches the display on or off
+ *
+ * @param on true: on false: off
+ */
+
+ void power( bool on );
+
+ /**
+ * @brief cleares the display and text buffer
+ *
+ */
+ bool clearDisplay(void);
+
+ /**
+ * @brief Set the brightness of the display
+ *
+ * @param dim 0..15 (0: dark .. 15: light)
+ */
+ bool setIntensity(byte dim);
+
+ /**
+ * @brief Set the orientation of the 8x8 LED dot matrix module
+ *
+ * @param orientation
+ */
+ bool setOrientation(ModuleOrientation orientation);
+
+ /**
+ * @brief Set ap pixel at a defined position.
+ * After all Pixels are set, call refresh() to send it to the display.
+ *
+ * @param x horizontal position from left
+ * @param y vertical position from top
+ * @param on true: on, false: off
+ */
+
+ /**
+ * @brief Set the a pending string to the scrolling text to set a distance to the repeating text. Usually some spaces are used.
+ *
+ * @param append text to append to the scrolling text before repeating.
+ */
+ bool setScrollAppendText(const char* append );
+
+ bool setPixel( const int x, const int y, bool on=true);
+ /**
+ * @brief sends the changed content of the buffer to the display
+ *
+ */
+ void refresh();
+
+ private:
+ bool drawCharAt( char c, int x, int y ); // Draws a character to a defined position
+ bool shutdown(bool b); // shutdown(true) switches the display off. Text and pixels can be set while it is off. shutdown(false) switches the display on.
+ bool clear(void); // clears the display content
+ void refreshByteOfBuffer( int i); // sends one byte of the buffer to the display. This updates an 8 pixel row of one matrix module.
+ byte revereBitorder(byte b); // returnes the byte in the reverse bit order.
+ void appendSpace(); // appends characters to the end of the text to get a distance to the repeating scroll text
+
private:
unsigned int modulesPerRow;
unsigned int modulesPerCol;
@@ -60,112 +154,14 @@ class LedMatrix
ModuleOrientation moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
LedControl* ledControl;
- const int charWidth = 6;
- const int charHeight = 8;
+ int charWidth;
+ int charHeight;
char textBuf[TEXT_BUFFER_SIZE];
char appendTextBuf[TEXT_APPEND_BUFFER_SIZE];
int textWidth; // width of text [pixel]
int textPosX; // horizontal pixel position of scrolling text
int textPosY; // vertical pixelposition of scrolling text;
-
- public:
- /**
- * @brief Construct a new Led Matrix object
- *
- * @param colums of 8x8 LED dot matrix modules
- * @param rows of 8x8 LED dot matrix modules
- */
- LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows);
-
- /**
- * @brief Set all LEDs off.
- *
- */
- bool clearDisplay(void);
-
- /**
- * @brief Set the brightness of the display
- *
- * @param dim 0..15
- */
- bool setIntensity(byte dim);
-
- /**
- * @brief Set the a pending string to the scrolling text to set a distance to te repeating text. Usually some spaces.
- *
- * @param append text to append to the scrolling text before repeating.
- */
- bool setScrollAppendText(const char* append );
-
- /**
- * @brief Switches the display on or off
- *
- * @param on true: on false: off
- */
- void power( bool on );
-
- /**
- * @brief Set the orientation of the 8x8 LED dot matrix module
- *
- * @param orientation
- */
- bool setOrientation(ModuleOrientation orientation);
-
- /**
- * @brief draw a string to the display.
- * When the text fits into the size of the display, it will be shown in the center.
- * When the text is longer than than the display width, it can be scrolled per pixel with function scrollText().
- *
- * @param str string to display
- */
- bool drawText( const char *str );
-
- /**
- * @brief dwaws a character string to the display. The position (x,y) is used for the upper left pixtel of the text.
- * Existing text before the x position will not be cleared.
- *
- * @param str string to display
- * @param x horizantal pixel position to start with string (default 0)
- * @param y vertical pixel position for the top position of the string (default 0)
- */
- bool drawTextAt( const char *str, const int x, const int y );
-
- /**
- * @brief Scroll the current teext one picel to the left.
- * Repeat with from start when end of text reached.
- *
- */
- bool scrollText();
-
- /**
- * @brief Set the Pixel object
- *
- * @param x horizontal position from left
- * @param y vertical position from top
- * @param on true: on, false: off
- */
- bool setPixel( const int x, const int y, bool on=true);
- void test();
-
- private:
- bool drawCharAt( char c, int x, int y );
-
- bool shutdown(bool b);
- bool clear(void);
-
- /**
- * @brief sends the changed content of the buffer to the display
- *
- */
- void refresh();
-
- void refreshByteOfBuffer( int i);
-
- byte revereBitorder (byte b);
-
- void appendSpace();
-
};
#endif //LedMatrix_h
\ No newline at end of file
diff --git a/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h b/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
index 56df774a4..da3becc4e 100644
--- a/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
+++ b/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
@@ -2,6 +2,9 @@
#ifndef font_5x8_horizontal_MSB_h
#define font_5x8_horizontal_MSB_h
+const unsigned int font_char_width = 5;
+const unsigned int font_char_height = 8;
+
const char font[256][8]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
{0x0E,0x11,0x1B,0x11,0x1F,0x0E,0x00,0x00}, // 0x01
diff --git a/lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h b/lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h
index cc3a323cc..e5c522cd4 100644
--- a/lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h
+++ b/lib/lib_display/LedControl/src/font_6x8_horizontal_MSB.h
@@ -2,6 +2,9 @@
#ifndef font_6x8_horizontal_MSB_h
#define font_6x8_horizontal_MSB_h
+const unsigned int font_char_width = 6;
+const unsigned int font_char_height = 8;
+
const char font[256][8]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
{0x0E,0x11,0x1B,0x11,0x15,0x11,0x0E,0x00}, // 0x01
diff --git a/lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h b/lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h
new file mode 100644
index 000000000..e1a8af7ae
--- /dev/null
+++ b/lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h
@@ -0,0 +1,265 @@
+#ifndef font_8x8_horizontal_latin_MSB_h
+#define font_8x8_horizontal_latin_MSB_h
+
+const unsigned int font_char_width = 8;
+const unsigned int font_char_height = 8;
+
+const char font[256][8]={
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
+{0x0E,0x11,0x1B,0x11,0x15,0x11,0x0E,0x00}, // 0x01
+{0x0E,0x1F,0x15,0x1F,0x11,0x1F,0x0E,0x00}, // 0x02
+{0x00,0x0A,0x1F,0x1F,0x1F,0x0E,0x04,0x00}, // 0x03
+{0x00,0x04,0x0E,0x1F,0x1F,0x0E,0x04,0x00}, // 0x04
+{0x04,0x0E,0x0E,0x04,0x1F,0x1F,0x04,0x00}, // 0x05
+{0x00,0x04,0x0E,0x1F,0x1F,0x04,0x0E,0x00}, // 0x06
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
+{0x00,0x07,0x03,0x0D,0x12,0x12,0x0C,0x00}, // 0x0B
+{0x0E,0x11,0x11,0x0E,0x04,0x0E,0x04,0x00}, // 0x0C
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
+{0x03,0x0D,0x0B,0x0D,0x0B,0x1B,0x18,0x00}, // 0x0E
+{0x00,0x15,0x0E,0x1B,0x0E,0x15,0x00,0x00}, // 0x0F
+{0x08,0x0C,0x0E,0x0F,0x0E,0x0C,0x08,0x00}, // 0x10
+{0x02,0x06,0x0E,0x1E,0x0E,0x06,0x02,0x00}, // 0x11
+{0x04,0x0E,0x1F,0x04,0x1F,0x0E,0x04,0x00}, // 0x12
+{0x0A,0x0A,0x0A,0x0A,0x0A,0x00,0x0A,0x00}, // 0x13
+{0x0F,0x15,0x15,0x0D,0x05,0x05,0x05,0x00}, // 0x14
+{0x0E,0x11,0x0C,0x0A,0x06,0x11,0x0E,0x00}, // 0x15
+{0x00,0x00,0x00,0x00,0x00,0x1E,0x1E,0x00}, // 0x16
+{0x04,0x0E,0x1F,0x04,0x1F,0x0E,0x04,0x0E}, // 0x17
+{0x04,0x0E,0x1F,0x04,0x04,0x04,0x04,0x00}, // 0x18
+{0x04,0x04,0x04,0x04,0x1F,0x0E,0x04,0x00}, // 0x19
+{0x00,0x04,0x06,0x1F,0x06,0x04,0x00,0x00}, // 0x1A
+{0x00,0x04,0x0C,0x1F,0x0C,0x04,0x00,0x00}, // 0x1B
+{0x00,0x00,0x00,0x10,0x10,0x10,0x1F,0x00}, // 0x1C
+{0x00,0x0A,0x0A,0x1F,0x0A,0x0A,0x00,0x00}, // 0x1D
+{0x04,0x04,0x0E,0x0E,0x1F,0x1F,0x00,0x00}, // 0x1E
+{0x1F,0x1F,0x0E,0x0E,0x04,0x04,0x00,0x00}, // 0x1F
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
+ { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
+ { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
+ { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
+ { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
+ { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
+ { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
+ { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
+ { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
+ { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
+ { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
+ { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
+ { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
+ { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
+ { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
+ { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
+ { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
+ { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
+ { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
+ { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
+ { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
+ { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
+ { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
+ { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
+ { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
+ { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (;)
+ { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
+ { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
+ { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
+ { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
+ { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
+ { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
+ { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
+ { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
+ { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
+ { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
+ { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
+ { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
+ { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
+ { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
+ { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
+ { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
+ { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
+ { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
+ { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
+ { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
+ { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
+ { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
+ { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
+ { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
+ { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
+ { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
+ { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
+ { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
+ { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
+ { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
+ { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
+ { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
+ { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
+ { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
+ { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
+ { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
+ { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
+ { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
+ { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
+ { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
+ { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
+ { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
+ { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
+ { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
+ { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
+ { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
+ { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
+ { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
+ { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
+ { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
+ { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
+ { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
+ { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
+ { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
+ { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
+ { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
+ { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
+ { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007F{0x0E,0x11,0x10,0x10,0x11,0x0E,0x04,0x0C}, // 0x80
+{0x12,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x81
+{0x03,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x82
+{0x0E,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x83
+{0x0A,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x84
+{0x0C,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x85
+{0x0E,0x0A,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x86
+{0x00,0x0E,0x11,0x10,0x11,0x0E,0x04,0x0C}, // 0x87
+{0x0E,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x88
+{0x0A,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x89
+{0x0C,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x8A
+{0x0A,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8B
+{0x0E,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8C
+{0x08,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8D
+{0x0A,0x00,0x04,0x0A,0x11,0x1F,0x11,0x00}, // 0x8E
+{0x0E,0x0A,0x0E,0x1B,0x11,0x1F,0x11,0x00}, // 0x8F
+{0x03,0x00,0x1F,0x10,0x1E,0x10,0x1F,0x00}, // 0x90
+{0x00,0x00,0x1E,0x05,0x1F,0x14,0x0F,0x00}, // 0x91
+{0x0F,0x14,0x14,0x1F,0x14,0x14,0x17,0x00}, // 0x92
+{0x0E,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x93
+{0x0A,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x94
+{0x18,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x95
+{0x0E,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x96
+{0x18,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x97
+{0x0A,0x00,0x12,0x12,0x12,0x0E,0x04,0x18}, // 0x98
+{0x12,0x0C,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0x99
+{0x0A,0x00,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0x9A
+{0x00,0x00,0x01,0x0E,0x16,0x1A,0x1C,0x20}, // 0x9B
+{0x06,0x09,0x08,0x1E,0x08,0x09,0x17,0x00}, // 0x9C
+{0x0F,0x13,0x15,0x15,0x15,0x19,0x1E,0x00}, // 0x9D
+{0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00}, // 0x9E
+{0x02,0x05,0x04,0x0E,0x04,0x04,0x14,0x08}, // 0x9F
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A0 (no break space)
+ { 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+00A1 (inverted !)
+ { 0x18, 0x18, 0x7E, 0x03, 0x03, 0x7E, 0x18, 0x18}, // U+00A2 (dollarcents)
+ { 0x1C, 0x36, 0x26, 0x0F, 0x06, 0x67, 0x3F, 0x00}, // U+00A3 (pound sterling)
+ { 0x00, 0x00, 0x63, 0x3E, 0x36, 0x3E, 0x63, 0x00}, // U+00A4 (currency mark)
+ { 0x33, 0x33, 0x1E, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C}, // U+00A5 (yen)
+ { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+00A6 (broken pipe)
+ { 0x7C, 0xC6, 0x1C, 0x36, 0x36, 0x1C, 0x33, 0x1E}, // U+00A7 (paragraph)
+ { 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A8 (diaeresis)
+ { 0x3C, 0x42, 0x99, 0x85, 0x85, 0x99, 0x42, 0x3C}, // U+00A9 (copyright symbol)
+ { 0x3C, 0x36, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00}, // U+00AA (superscript a)
+ { 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, // U+00AB (<<)
+ { 0x00, 0x00, 0x00, 0x3F, 0x30, 0x30, 0x00, 0x00}, // U+00AC (gun pointing left)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AD (soft hyphen)
+ { 0x3C, 0x42, 0x9D, 0xA5, 0x9D, 0xA5, 0x42, 0x3C}, // U+00AE (registered symbol)
+ { 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AF (macron)
+ { 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B0 (degree)
+ { 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00}, // U+00B1 (plusminus)
+ { 0x1C, 0x30, 0x18, 0x0C, 0x3C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 2)
+ { 0x1C, 0x30, 0x18, 0x30, 0x1C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 3)
+ { 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00B2 (aigu)
+ { 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x03}, // U+00B5 (mu)
+ { 0xFE, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0x00}, // U+00B6 (pilcrow)
+ { 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, // U+00B7 (central dot)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1E}, // U+00B8 (cedille)
+ { 0x08, 0x0C, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B9 (superscript 1)
+ { 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00BA (superscript 0)
+ { 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, // U+00BB (>>)
+ { 0xC3, 0x63, 0x33, 0xBD, 0xEC, 0xF6, 0xF3, 0x03}, // U+00BC (1/4)
+ { 0xC3, 0x63, 0x33, 0x7B, 0xCC, 0x66, 0x33, 0xF0}, // U+00BD (1/2)
+ { 0x03, 0xC4, 0x63, 0xB4, 0xDB, 0xAC, 0xE6, 0x80}, // U+00BE (3/4)
+ { 0x0C, 0x00, 0x0C, 0x06, 0x03, 0x33, 0x1E, 0x00}, // U+00BF (inverted ?)
+ { 0x07, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C0 (A grave)
+ { 0x70, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C1 (A aigu)
+ { 0x1C, 0x36, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C2 (A circumflex)
+ { 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C3 (A ~)
+ { 0x63, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x00}, // U+00C4 (A umlaut)
+ { 0x0C, 0x0C, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x00}, // U+00C5 (A ring)
+ { 0x7C, 0x36, 0x33, 0x7F, 0x33, 0x33, 0x73, 0x00}, // U+00C6 (AE)
+ { 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x18, 0x30, 0x1E}, // U+00C7 (C cedille)
+ { 0x07, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C8 (E grave)
+ { 0x38, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C9 (E aigu)
+ { 0x0C, 0x12, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CA (E circumflex)
+ { 0x36, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CB (E umlaut)
+ { 0x07, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CC (I grave)
+ { 0x38, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CD (I aigu)
+ { 0x0C, 0x12, 0x00, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CE (I circumflex)
+ { 0x33, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CF (I umlaut)
+ { 0x3F, 0x66, 0x6F, 0x6F, 0x66, 0x66, 0x3F, 0x00}, // U+00D0 (Eth)
+ { 0x3F, 0x00, 0x33, 0x37, 0x3F, 0x3B, 0x33, 0x00}, // U+00D1 (N ~)
+ { 0x0E, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D2 (O grave)
+ { 0x70, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D3 (O aigu)
+ { 0x3C, 0x66, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D4 (O circumflex)
+ { 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x63, 0x3E, 0x00}, // U+00D5 (O ~)
+ { 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+00D6 (O umlaut)
+ { 0x00, 0x36, 0x1C, 0x08, 0x1C, 0x36, 0x00, 0x00}, // U+00D7 (multiplicative x)
+ { 0x5C, 0x36, 0x73, 0x7B, 0x6F, 0x36, 0x1D, 0x00}, // U+00D8 (O stroke)
+ { 0x0E, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00D9 (U grave)
+ { 0x70, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DA (U aigu)
+ { 0x3C, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DB (U circumflex)
+ { 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+00DC (U umlaut)
+ { 0x70, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x00}, // U+00DD (Y aigu)
+ { 0x0F, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+00DE (Thorn)
+ { 0x00, 0x1E, 0x33, 0x1F, 0x33, 0x1F, 0x03, 0x03}, // U+00DF (beta)
+ { 0x07, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E0 (a grave)
+ { 0x38, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E1 (a aigu)
+ { 0x7E, 0xC3, 0x3C, 0x60, 0x7C, 0x66, 0xFC, 0x00}, // U+00E2 (a circumflex)
+ { 0x6E, 0x3B, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E3 (a ~)
+ { 0x33, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E4 (a umlaut)
+ { 0x0C, 0x0C, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E5 (a ring)
+ { 0x00, 0x00, 0xFE, 0x30, 0xFE, 0x33, 0xFE, 0x00}, // U+00E6 (ae)
+ { 0x00, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+00E7 (c cedille)
+ { 0x07, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E8 (e grave)
+ { 0x38, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E9 (e aigu)
+ { 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00}, // U+00EA (e circumflex)
+ { 0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00EB (e umlaut)
+ { 0x07, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EC (i grave)
+ { 0x1C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00ED (i augu)
+ { 0x3E, 0x63, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EE (i circumflex)
+ { 0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EF (i umlaut)
+ { 0x1B, 0x0E, 0x1B, 0x30, 0x3E, 0x33, 0x1E, 0x00}, // U+00F0 (eth)
+ { 0x00, 0x1F, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x00}, // U+00F1 (n ~)
+ { 0x00, 0x07, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F2 (o grave)
+ { 0x00, 0x38, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F3 (o aigu)
+ { 0x1E, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F4 (o circumflex)
+ { 0x6E, 0x3B, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F5 (o ~)
+ { 0x00, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F6 (o umlaut)
+ { 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00}, // U+00F7 (division)
+ { 0x00, 0x60, 0x3C, 0x76, 0x7E, 0x6E, 0x3C, 0x06}, // U+00F8 (o stroke)
+ { 0x00, 0x07, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00F9 (u grave)
+ { 0x00, 0x38, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FA (u aigu)
+ { 0x1E, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FB (u circumflex)
+ { 0x00, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FC (u umlaut)
+ { 0x00, 0x38, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+00FD (y aigu)
+ { 0x00, 0x00, 0x06, 0x3E, 0x66, 0x3E, 0x06, 0x00}, // U+00FE (thorn)
+ { 0x00, 0x33, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F} // U+00FF (y umlaut)
+};
+
+#endif
\ No newline at end of file
diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h
index 13fdf23e4..e3f3256fc 100644
--- a/tasmota/tasmota_template.h
+++ b/tasmota/tasmota_template.h
@@ -524,7 +524,6 @@ const uint16_t kGpioNiceList[] PROGMEM = {
#ifdef USE_DISPLAY_MAX7219_MATRIX
#undef USE_DISPLAY_MAX7219
#undef USE_DISPLAY_TM1637
- #define USE_DISPLAY_MODES1TO5
AGPIO(GPIO_MAX7219CLK),
AGPIO(GPIO_MAX7219DIN),
AGPIO(GPIO_MAX7219CS),
diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino
index ec82420e2..3ec3ac332 100644
--- a/tasmota/xdsp_19_max7219_matrix.ino
+++ b/tasmota/xdsp_19_max7219_matrix.ino
@@ -1,5 +1,5 @@
/*
- xdsp_19_max7219_matrix.ino.ino - Support for MAX7219 based dot matrix displays for Tasmota
+ xdsp_19_max7219_matrix.ino.ino - Support for MAX7219 based 8x8 dot matrix displays for Tasmota
Copyright (C) 2021 Michael Beuss
@@ -20,111 +20,63 @@
#ifdef USE_DISPLAY
#ifdef USE_DISPLAY_MAX7219_MATRIX
/*********************************************************************************************\
- This driver enables the display of ascii text on MAX7219 based LED dot matrix modules.
+ This driver enables the display of ascii text on MAX7219 based 8x8 LED dot matrix modules (1088AS).
- Connect the MAX7219 display module's pins to any free GPIOs of the ESP8266 or ESP32 module
- and assign the pins as follows from Tasmota's GUI:
+ Connect the MAX7219 display module's pins to any free GPIOs of the ESP8266 or ESP32 module.
+ VCC should be 5V. Depending on the number of used modules and the brightness, the used current can be more than 500 mA.
+
+ Connect the 5 outgoing pins (VCC, GND, DI, CS, CLK) of the first module to the next one.
+ With this you can connect up to 32 modules.
+ To extend the display hieght, multiple rows are supported. Each module row starts from left to right.
+
+ Assign the pins as follows from Tasmota's GUI:
DIN hardware pin --> "MAX7219 DIN"
CS hardware pin --> "MAX7219 CS"
CLK hardware pin --> "MAX7219 CLK"
+
Once the GPIO configuration is saved and the ESP8266/ESP32 module restarts,
set the Display Model to 19 and Display Mode to 0
- using the command "Backlog DisplayModel 15 ; DisplayMode 0"
- If your display is a TM1637 with 6 digits, set Display Width to the number of digits your
- display has, using the command "DisplayWidth 6".
+ Depending on order oth the wired 8x8 matrix modules you have got a display of size pixel_width x pixel_height.
+ The size has to be set with the commands "DisplayWidth " and "DisplayHeight "
After the ESP8266/ESP32 module restarts again, turn ON the display with the command "Power 1"
+
Now, the following "Display" commands can be used:
+ DisplayText text
+ Sends the text to the display.
+ If the text fits into the display, it is shown in the center.
+ Otherwise it scrolls to the left and repeats as long it is cleared or new "DisplayText" overwrites it.
+
+ DisplayDimmer [0..100]
+ Sets the intensity of the display.
+
+ Power [ON|OFF]
+ Sitches the display on or off. When "off", the display buffer is not cleared and will be shown again when after "Power ON".
+ Other display commands are still active when off.
DisplayClear
+ Clears the display
- Clears the display, command: "DisplayClear"
+ DisplayScrollDelay [0..15] // default = 0
+ Sets the speed of text scroll. Smaller delay = faster scrolling.
+ The maximum scroll speed is 50ms per pixel on DisplayScrollDelay 0.
+ DisplayWidth [8..256]
+ Sets the pixel width of the display (8x number of modules in a row)
- DisplayNumber num [,position {0-(Settings->display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]]
+ DisplayHeight [8..256]
+ Sets the pixel height of the display (8x number of module rows)
- Clears and then displays number without decimal. command e.g., "DisplayNumber 1234"
- Control 'leading zeros', 'length' and 'position' with "DisplayNumber 1234, , , "
- 'leading zeros' can be 1 or 0 (default), 'length' can be 1 to Settings->display_width, 'position' can be 0 (left-most) to Settings->display_width (right-most).
- See function description below for more details.
-
- DisplayNumberNC num [,position {0-(Settings->display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]]
-
- Display integer number as above, but without clearing first. e.g., "DisplayNumberNC 1234". Usage is same as above.
-
-
-
- DisplayFloat num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]]
-
- Clears and then displays float (with decimal point) command e.g., "DisplayFloat 12.34"
- See function description below for more details.
-
-
-
- DisplayFloatNC num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]]
-
- Displays float (with decimal point) as above, but without clearing first. command e.g., "DisplayFloatNC 12.34"
- See function description below for more details.
-
-
-
- DisplayRaw position {0-(Settings->display_width-1)},length {1 to Settings->display_width}, num1 [, num2[, num3[, num4[, ...upto Settings->display_width numbers]]]]]
-
- Takes upto Settings->display_width comma-separated integers (0-255) and displays raw segments. Each number represents a
- 7-segment digit. Each 8-bit number represents individual segments of a digit.
- For example, the command "DisplayRaw 0, 4, 255, 255, 255, 255" would display "[8.8.8.8.]"
-
-
-
- DisplayText text [, position {0-(Settings->display_width-1)} [,length {1 to Settings->display_width}]]
-
- Clears and then displays basic text. command e.g., "DisplayText ajith vasudevan"
- Control 'length' and 'position' with "DisplayText , , "
- 'length' can be 1 to Settings->display_width, 'position' can be 0 (left-most) to Settings->display_width-1 (right-most)
- A caret(^) symbol in the text input is dispayed as the degrees(°) symbol. This is useful for displaying Temperature!
- For example, the command "DisplayText 22.5^" will display "22.5°".
-
-
- DisplayTextNC text [, position {0-Settings->display_width-1} [,length {1 to Settings->display_width}]]
-
- Clears first, then displays text. Usage is same as above.
-
-
-
- DisplayScrollText text [, num_loops]
-
- Displays scrolling text indefinitely, until another Display- command (other than DisplayScrollText
- or DisplayScrollDelay is issued). Optionally, stop scrolling after num_loops iterations.
-
-
-
- DisplayScrollDelay delay {0-15} // default = 4
-
- Sets the speed of text scroll. Smaller delay = faster scrolling.
-
-
-
- DisplayLevel num {0-100}
-
- Display a horizontal bar graph (0-100) command e.g., "DisplayLevel 50" will display [|||| ]
-
-
-
- DisplayClock 1|2|0
-
- Displays a clock.
- Commands "DisplayClock 1" // 12 hr format
- "DisplayClock 2" // 24 hr format
- "DisplayClock 0" // turn off clock
-
-
-In addition, setting DisplayMode to 1 shows the time, setting it to 2 shows the date
-and setting it to 3 alternates between time and date.
+ DisplayClock [0|1|2]
+ Displays a clock.
+ Commands "DisplayClock 1" // 12 hr format
+ "DisplayClock 2" // 24 hr format
+ "DisplayClock 0" // turn off clock
@@ -132,20 +84,26 @@ and setting it to 3 alternates between time and date.
#define XDSP_19 19
-#include
#include
+#ifdef USE_DISPLAY_MODES1TO5
+#include
+#endif
+
LedMatrix *max7219_Matrix = nullptr;
bool max2791Matrix_initDriver_done = false;
struct
{
byte modulesPerRow = 4;
byte modulesPerCol = 1;
+ byte scroll_delay = 0;
+ byte scroll_iteration = 0;
bool show_clock = false;
- const char* timeFormat;
+ const char *timeFormat;
} LedMatrix_settings;
+// FUNC_DISPLAY_INIT_DRIVER
bool MAX7291Matrix_initDriver(void)
{
if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS))
@@ -174,6 +132,7 @@ bool MAX7291Matrix_initDriver(void)
return MAX7291Matrix_init();
}
+// FUNC_DISPLAY_INIT
bool MAX7291Matrix_init(void)
{
int intensity = GetDisplayDimmer16(); // 0..15
@@ -187,6 +146,39 @@ bool MAX7291Matrix_init(void)
return true;
}
+// FUNC_DISPLAY_SCROLLDELAY
+bool MAX7291Matrix_scrollDelay(void)
+{
+ if (ArgC() == 0)
+ {
+ XdrvMailbox.payload = LedMatrix_settings.scroll_delay;
+ return true;
+ }
+ if (LedMatrix_settings.scroll_delay < 0)
+ LedMatrix_settings.scroll_delay = 0;
+ LedMatrix_settings.scroll_delay = XdrvMailbox.payload;
+ return true;
+}
+
+// FUNC_DISPLAY_EVERY_50_MSECOND
+bool MAX7291Matrix_scrollText(void)
+{
+ // This function is called every 50 ms.
+ // scroll_delay defines the number of cycles to be ignored until the display scrolls by one pixel to the left.
+ // e.g. scrall_delay = 4 causes a scroll each 200 ms.
+ LedMatrix_settings.scroll_iteration++;
+ if (LedMatrix_settings.scroll_delay)
+ LedMatrix_settings.scroll_iteration = LedMatrix_settings.scroll_iteration % LedMatrix_settings.scroll_delay;
+ else
+ LedMatrix_settings.scroll_iteration = 0;
+ if (LedMatrix_settings.scroll_iteration)
+ return false;
+
+ return max7219_Matrix->scrollText();
+}
+
+#ifdef USE_DISPLAY_MODES1TO5
+// FUNC_DISPLAY_CLOCK
bool MAX7291Matrix_clock(void)
{
LedMatrix_settings.show_clock = XdrvMailbox.payload;
@@ -213,11 +205,11 @@ bool MAX7291Matrix_clock(void)
AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: LedMatrix_settings.show_clock %d, timeFormat %s"), LedMatrix_settings.show_clock, LedMatrix_settings.timeFormat);
- //max7219_Matrix->clearDisplay();
MAX7291Matrix_showTime();
return true;
}
+// FUNC_DISPLAY_EVERY_SECOND
bool MAX7291Matrix_showTime()
{
time_t rawtime;
@@ -227,11 +219,12 @@ bool MAX7291Matrix_showTime()
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(timeStr, 10, LedMatrix_settings.timeFormat, timeinfo);
- //AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: showTime:%s"), timeStr);
max7219_Matrix->drawText(timeStr);
return true;
}
+#endif // USE_DISPLAY_MODES1TO5
+
bool Xdsp19(uint8_t function)
{
@@ -260,30 +253,28 @@ bool Xdsp19(uint8_t function)
case FUNC_DISPLAY_DIM:
result = max7219_Matrix->setIntensity(GetDisplayDimmer16());
break;
- case FUNC_DISPLAY_CLOCK:
- result = MAX7291Matrix_clock();
- break;
- case FUNC_DISPLAY_SEVENSEG_TEXT:
- case FUNC_DISPLAY_SEVENSEG_TEXTNC:
- case FUNC_DISPLAY_NUMBER:
- case FUNC_DISPLAY_NUMBERNC:
- case FUNC_DISPLAY_FLOAT:
- case FUNC_DISPLAY_FLOATNC:
- case FUNC_DISPLAY_RAW:
- case FUNC_DISPLAY_LEVEL:
- case FUNC_DISPLAY_SCROLLTEXT:
case FUNC_DISPLAY_DRAW_STRING:
result = max7219_Matrix->drawText(dsp_str);
break;
+ case FUNC_DISPLAY_SCROLLDELAY:
+ result = MAX7291Matrix_scrollDelay();
+ break;
+ case FUNC_DISPLAY_EVERY_50_MSECOND:
+ result = MAX7291Matrix_scrollText();
+ break;
+
+#ifdef USE_DISPLAY_MODES1TO5
+ case FUNC_DISPLAY_CLOCK:
+ result = MAX7291Matrix_clock();
+ break;
case FUNC_DISPLAY_EVERY_SECOND:
if (LedMatrix_settings.show_clock)
{
result = MAX7291Matrix_showTime();
}
-
break;
- case FUNC_DISPLAY_EVERY_50_MSECOND:
- result = max7219_Matrix->scrollText();
+#endif // USE_DISPLAY_MODES1TO5
+
default:
result = false;
}
From 71f1c1775fc44f20d535c572ead9efe94f50eeda Mon Sep 17 00:00:00 2001
From: Alexey Pavlov
Date: Sun, 7 Nov 2021 17:56:28 +0300
Subject: [PATCH 009/510] fix opentherm
---
tasmota/xsns_69_opentherm.ino | 20 ++++++++++++++++--
tasmota/xsns_69_opentherm_protocol.ino | 29 ++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/tasmota/xsns_69_opentherm.ino b/tasmota/xsns_69_opentherm.ino
index cfcc0384d..c94e61b59 100644
--- a/tasmota/xsns_69_opentherm.ino
+++ b/tasmota/xsns_69_opentherm.ino
@@ -16,6 +16,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+#define USE_OPENTHERM
#ifdef USE_OPENTHERM
@@ -467,8 +468,11 @@ uint8_t sns_opentherm_read_flags(char *data, uint32_t len)
// flag value, however, this command does not update the settings.
#define D_CMND_SET_HOT_WATER_ENABLED "dhw"
+// BLOR - Reset boiler
+#define D_CMND_BLLOR "blor"
+
const char kOpenThermCommands[] PROGMEM = D_PRFX_OTHERM "|" D_CMND_OTHERM_BOILER_SETPOINT "|" D_CMND_OTHERM_DHW_SETPOINT
- "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED "|" D_CMND_SET_HOT_WATER_ENABLED;
+ "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED "|" D_CMND_SET_HOT_WATER_ENABLED "|" D_CMND_BLLOR;
void (*const OpenThermCommands[])(void) PROGMEM = {
&sns_opentherm_boiler_setpoint_cmd,
@@ -476,7 +480,8 @@ void (*const OpenThermCommands[])(void) PROGMEM = {
&sns_opentherm_save_settings_cmd,
&sns_opentherm_flags_cmd,
&sns_opentherm_set_central_heating_cmd,
- &sns_opentherm_set_hot_water_cmd};
+ &sns_opentherm_set_hot_water_cmd,
+ &sns_opentherm_blor_cmd,};
void sns_opentherm_cmd(void) { }
void sns_opentherm_boiler_setpoint_cmd(void)
@@ -550,6 +555,17 @@ void sns_opentherm_set_hot_water_cmd(void)
ResponseCmndNumber(sns_ot_boiler_status.m_enableHotWater ? 1 : 0);
}
+void sns_opentherm_blor_cmd(void)
+{
+ bool query = strlen(XdrvMailbox.data) == 0;
+ bool retval = false;
+ if (!query)
+ {
+ if (atoi(XdrvMailbox.data)) retval = sns_opentherm_call_blor();
+ }
+ ResponseCmndNumber(retval);
+}
+
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
diff --git a/tasmota/xsns_69_opentherm_protocol.ino b/tasmota/xsns_69_opentherm_protocol.ino
index bc821640a..a86648849 100644
--- a/tasmota/xsns_69_opentherm_protocol.ino
+++ b/tasmota/xsns_69_opentherm_protocol.ino
@@ -16,6 +16,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+#define USE_OPENTHERM
#ifdef USE_OPENTHERM
@@ -243,6 +244,14 @@ OpenThermCommand sns_opentherm_commands[] = {
.m_ot_make_request = sns_opentherm_get_generic_u16,
.m_ot_parse_response = sns_opentherm_parse_generic_u16,
.m_ot_appent_telemetry = sns_opentherm_tele_generic_u16},
+ {// Boiler Lock-out Reset command
+ .m_command_name = "BLOR",
+ .m_command_code = (uint8_t)OpenThermMessageID::Command,
+ .m_flags = {.notSupported = 1},
+ .m_results = {{.m_u8 = 0}, {.m_u8 = 0}},
+ .m_ot_make_request = sns_opentherm_send_blor,
+ .m_ot_parse_response = sns_opentherm_parse_generic_u16,
+ .m_ot_appent_telemetry = sns_opentherm_tele_u8_u8},
};
/////////////////////////////////// Process Slave Status Flags & Control //////////////////////////////////////////////////
@@ -431,6 +440,26 @@ void sns_opentherm_tele_oem_diag(struct OpenThermCommandT *self)
ResponseAppend_P(PSTR("%d"), (int)self->m_results[0].m_u16);
}
+/////////////////////////////////// Boiler Boiler Lock-out Reset //////////////////////////////////////////////////
+unsigned long sns_opentherm_send_blor(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status)
+{
+ AddLog(LOG_LEVEL_ERROR, PSTR("[OTH]: Boiler Boiler Lock-out Reset"));
+
+ self->m_flags.notSupported = true; // Disable future calls of this command
+
+ unsigned int data = 1; //1 : “BLOR”= Boiler Lock-out Reset command
+ return OpenTherm::buildRequest(OpenThermMessageType::WRITE_DATA, OpenThermMessageID::Command, data);
+}
+bool sns_opentherm_call_blor()
+{
+ /*
+ OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command-1];
+ if (strcmp(cmd->m_command_name, "BLOR")) return false;
+ cmd->m_flags.notSupported = false;
+ return true;
+ */
+}
+
/////////////////////////////////// Generic Single Float /////////////////////////////////////////////////
unsigned long sns_opentherm_get_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *)
{
From af14b4943525264c27ea0e4eada391b83352c4bb Mon Sep 17 00:00:00 2001
From: Alexey Pavlov
Date: Sun, 28 Nov 2021 18:44:10 +0300
Subject: [PATCH 010/510] merge conflict
---
tasmota/xlgt_01_ws2812.ino | 99 +++++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 1 deletion(-)
diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino
index 3a9e396f3..f2c8b0610 100644
--- a/tasmota/xlgt_01_ws2812.ino
+++ b/tasmota/xlgt_01_ws2812.ino
@@ -17,6 +17,11 @@
along with this program. If not, see .
*/
+#ifndef FIRMWARE_MINIMAL
+#define USE_LIGHT
+#define USE_WS2812
+#endif
+
#ifdef USE_LIGHT
#ifdef USE_WS2812
/*********************************************************************************************\
@@ -37,7 +42,7 @@
#define XLGT_01 1
-const uint8_t WS2812_SCHEMES = 9; // Number of WS2812 schemes
+const uint8_t WS2812_SCHEMES = 10; // Number of WS2812 schemes
const char kWs2812Commands[] PROGMEM = "|" // No prefix
D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH "|" D_CMND_STEPPIXELS ;
@@ -291,6 +296,93 @@ void Ws2812Clock(void)
Ws2812StripShow();
}
+#define pow2(x) ((x)*(x))
+#define pow3(x) ((x)*pow2(x))
+#define pow4(x) (pow2(x)*pow2(x))
+
+void Ws2812RunningStrip(int scheme)
+{
+#if (USE_WS2812_CTYPE > NEO_3LED)
+ RgbwColor c;
+ c.W = 0;
+#else
+ RgbColor c(Settings->light_dimmer);
+#endif
+
+ static uint32_t timer_counter = 0;
+ static uint32_t last_timer_counter = timer_counter;
+ if (Settings->light_rotation%2) timer_counter--;
+ else timer_counter++;
+
+ uint32_t width = Settings->ws_width[WS_MINUTE]?Settings->ws_width[WS_MINUTE]:1;
+ uint32_t repeat = 1;//kWsRepeat[Settings->light_width]; // number of scheme.count per ledcount
+ uint32_t range = (uint32_t)ceil((float)Settings->light_pixels / (float)repeat);
+ uint32_t speed = Settings->light_speed; //((Settings->light_speed * 2) -1) * (STATES / 10); //
+ static uint32_t offset = 0;
+
+ if (scheme==WS2812_SCHEMES-1) {
+ if (timer_counter/speed!=last_timer_counter/speed) {
+ offset = random(range);
+ last_timer_counter = timer_counter;
+ }
+ } else {
+ offset = speed > 0 ? timer_counter / speed : 0;
+ }
+
+ //WsColor oldColor, currentColor;
+ //Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset);
+ //currentColor = oldColor;
+ int power = Settings->ws_width[WS_SECOND];
+ int max_input = pow(width, power);
+ float dimmer = 100 / (float)Settings->light_dimmer;
+
+ uint32_t target = offset % Settings->light_pixels;
+
+ for (uint32_t i = 0; i < Settings->light_pixels; i++) {
+ int delta = targetlight_color[0] / pow(delta+1, power);
+ float fmyGrn = Settings->light_color[1] / pow(delta+1, power);
+ float fmyBlu = Settings->light_color[2] / pow(delta+1, power);
+ /*
+ float fmyRed = (float)wsmap(max_input-pow(delta+1, power), 0, max_input, 0, Settings->light_color[0]);
+ float fmyGrn = (float)wsmap(max_input-pow(delta+1, power), 0, max_input, 0, Settings->light_color[1]);
+ float fmyBlu = (float)wsmap(max_input-pow(delta+1, power), 0, max_input, 0, Settings->light_color[2]);
+ */
+
+ c.R = (uint8_t)fmyRed/dimmer;
+ c.G = (uint8_t)fmyGrn/dimmer;
+ c.B = (uint8_t)fmyBlu/dimmer;
+ }
+ else {
+ c.R = 0 ;
+ c.G = 0 ;
+ c.B = 0 ;
+ }
+
+ if (Settings->light_width==2) {
+ c.R = Settings->light_color[0]/dimmer - c.R;
+ c.G = Settings->light_color[1]/dimmer - c.G;
+ c.B = Settings->light_color[2]/dimmer - c.B;
+ } else if (Settings->ws_width[WS_MINUTE]==3) {
+ c.R = max(100 - c.R,0);
+ c.G = max(100 - c.G,0);
+ c.B = max(100 - c.B,0);
+ }
+
+ strip->SetPixelColor(i, c);
+/*
+ // Blend old and current color based on time for smooth movement.
+ c.R = wsmap(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red);
+ c.G = wsmap(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green);
+ c.B = wsmap(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue);
+ strip->SetPixelColor(i, c);
+ oldColor = currentColor;
+ */
+ }
+ Ws2812StripShow();
+}
+
void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i)
{
/*
@@ -588,6 +680,11 @@ void Ws2812ShowScheme(void)
Ws2812.show_next = 0;
}
break;
+ case WS2812_SCHEMES-2: // Running strip
+ case WS2812_SCHEMES-1: // Running strip
+ Ws2812RunningStrip(scheme);
+ Ws2812.show_next = 1;
+ break;
default:
if(Settings->light_step_pixels > 0){
Ws2812Steps(scheme -1);
From 5b3266e7ca90dfdbe750a6be746b14f6de24f884 Mon Sep 17 00:00:00 2001
From: Michael
Date: Mon, 29 Nov 2021 15:27:55 +0100
Subject: [PATCH 011/510] Support for more than 8 matrix devices
---
lib/lib_display/LedControl/src/LedControl.cpp | 37 ++-
lib/lib_display/LedControl/src/LedControl.h | 20 +-
lib/lib_display/LedControl/src/LedMatrix.cpp | 24 +-
lib/lib_display/LedControl/src/LedMatrix.h | 13 +-
.../LedControl/src/font_5x8_horizontal_MSB.h | 267 ------------------
.../src/font_8x8_horizontal_latin_MSB.h | 265 -----------------
tasmota/xdsp_19_max7219_matrix.ino | 89 ++++--
7 files changed, 129 insertions(+), 586 deletions(-)
delete mode 100644 lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
delete mode 100644 lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h
diff --git a/lib/lib_display/LedControl/src/LedControl.cpp b/lib/lib_display/LedControl/src/LedControl.cpp
index e43211fd8..11e7a2908 100644
--- a/lib/lib_display/LedControl/src/LedControl.cpp
+++ b/lib/lib_display/LedControl/src/LedControl.cpp
@@ -47,16 +47,16 @@ LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
SPI_MOSI=dataPin;
SPI_CLK=clkPin;
SPI_CS=csPin;
- if(numDevices<=0 || numDevices>8 )
- numDevices=8;
- maxDevices=numDevices;
+ if (numDevices <= 0 || numDevices > MAX72XX_MAX_DEVICES)
+ numDevices = MAX72XX_MAX_DEVICES;
+ maxDevices = numDevices;
pinMode(SPI_MOSI,OUTPUT);
pinMode(SPI_CLK,OUTPUT);
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
- for(int i=0;i<64;i++)
- status[i]=0x00;
+ for (int i = 0; i < 8 * MAX72XX_MAX_DEVICES; i++)
+ status[i] = 0x00;
for(int i=0;i 7)
+ return;
+ for (int addr = 0; addr < maxDevices; addr++)
+ status[addr * 8 + row] = value[addr];
+ spiTransferLong(row + 1, value);
+}
+
void LedControl::setColumn(int addr, int col, byte value) {
byte val;
@@ -195,7 +204,7 @@ void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data)
int maxbytes=maxDevices*2;
for(int i=0;i 0; i--)
+ shiftOut(SPI_MOSI, SPI_CLK, MSBFIRST, spidata[i - 1]);
+ //latch the data onto the display
+ digitalWrite(SPI_CS, HIGH);
+}
diff --git a/lib/lib_display/LedControl/src/LedControl.h b/lib/lib_display/LedControl/src/LedControl.h
index f8180d07d..31fed9ffe 100644
--- a/lib/lib_display/LedControl/src/LedControl.h
+++ b/lib/lib_display/LedControl/src/LedControl.h
@@ -35,6 +35,10 @@
#include
#endif
+#ifndef MAX72XX_MAX_DEVICES
+#define MAX72XX_MAX_DEVICES 32 // maximum number of devices based on MXA7219/MAX7221
+#endif
+
/*
* Segments to be switched on for characters and digits on
* 7-Segment Displays
@@ -61,12 +65,14 @@ const static byte charTable [] PROGMEM = {
class LedControl {
private :
/* The array for shifting the data to the devices */
- byte spidata[16];
- /* Send out a single command to the device */
+ byte spidata[2 * MAX72XX_MAX_DEVICES];
+ /* Send out a single command to one device */
void spiTransfer(int addr, byte opcode, byte data);
+ /* Send out a command with the same opcode to all devices */
+ void spiTransferLong(byte opcode, const byte* data);
/* We keep track of the led-status for all 8 devices in this array */
- byte status[64];
+ byte status[8 * MAX72XX_MAX_DEVICES];
/* Data is shifted out of this pin*/
int SPI_MOSI;
/* The clock is signaled on this pin */
@@ -149,6 +155,14 @@ class LedControl {
*/
void setRow(int addr, int row, byte value);
+ /**
+ * @brief Set data for the same row of all devices
+ *
+ * @param row [0..8]
+ * @param value array of bytes, one for each device
+ */
+ void setRowLong(int row, byte* value);
+
/*
* Set all 8 Led's in a column to a new state
* Params:
diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp
index b4fb8c260..1579e0852 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.cpp
+++ b/lib/lib_display/LedControl/src/LedMatrix.cpp
@@ -32,17 +32,17 @@
// public
LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows)
{
- if (colums * rows > MATRIX_MAX_MODULES)
+ if (colums * rows > MAX72XX_MAX_DEVICES)
{
// dimension exeeds maximum buffer size
- if (colums >= MATRIX_MAX_MODULES)
+ if (colums >= MAX72XX_MAX_DEVICES)
{
- colums = MATRIX_MAX_MODULES;
+ colums = MAX72XX_MAX_DEVICES;
rows = 1;
}
else
{
- rows = MATRIX_MAX_MODULES / colums;
+ rows = MAX72XX_MAX_DEVICES / colums;
}
}
@@ -66,7 +66,7 @@ LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, un
setIntensity(7);
}
-bool LedMatrix::drawText( const char *str)
+bool LedMatrix::drawText( const char *str, bool clearBefore)
{
strncpy(textBuf, str, TEXT_BUFFER_SIZE -1);
textPosX = 0;
@@ -75,7 +75,7 @@ bool LedMatrix::drawText( const char *str)
if(textWidth < displayWidth)
{
// text fits into the display, place it into the center
- clear();
+ if(clearBefore) clear();
textPosX = (displayWidth - textWidth) / 2; // center
}
else
@@ -146,9 +146,13 @@ bool LedMatrix::setIntensity(byte dim)
return true;
}
-bool LedMatrix::setOrientation(ModuleOrientation orientation)
+bool LedMatrix::setOrientation(LedMatrix::ModuleOrientation orientation)
{
- moduleOrientation = orientation;
+ if(moduleOrientation != orientation)
+ {
+ moduleOrientation = orientation;
+ refresh();
+ }
return true;
}
@@ -268,9 +272,9 @@ void LedMatrix::refreshByteOfBuffer(int i)
byte LedMatrix::revereBitorder (byte b)
{
- const static byte lookup[] PROGMEM = {
+ static const byte lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
- 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf,
+ 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
};
return (lookup[b & 0b1111] << 4) | lookup[b >> 4];
}
diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h
index efb50b8e3..b369173d0 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.h
+++ b/lib/lib_display/LedControl/src/LedMatrix.h
@@ -29,8 +29,7 @@
#include
-#define MATRIX_MAX_MODULES 32 // maximum number of modules that can be used
-#define MATRIX_BUFFER_SIZE MATRIX_MAX_MODULES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
+#define MATRIX_BUFFER_SIZE MAX72XX_MAX_DEVICES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
#define TEXT_BUFFER_SIZE 256 // maximum text length that can be scrolled
#define TEXT_APPEND_BUFFER_SIZE 16 // used for characters that are appended to the scroll text, before it repeats
@@ -66,12 +65,14 @@ class LedMatrix
* When the text is longer than than the display width, it can be scrolled per pixel with function scrollText().
*
* @param str string to display
+ * @param clearBefore true (default) clears old display content before, false: do not clear display before
*/
- bool drawText( const char *str );
+ bool drawText( const char *str, bool clearBefore = true );
/**
* @brief Dwaws a character string to a defined display position. The position (x,y) is used for the upper left pixel of the text.
- * Existing text before the x position will not be cleared. Use refresh() after all text parts are drawed.
+ * Existing content outside the drawing text area will not be cleared. But you can use clearDisplay() before.
+ * Use refresh() after all text parts are drawed.
*
* @param str string to display
* @param x horizantal pixel position to start with string (0 is most left)
@@ -112,7 +113,7 @@ class LedMatrix
*
* @param orientation
*/
- bool setOrientation(ModuleOrientation orientation);
+ bool setOrientation(LedMatrix::ModuleOrientation orientation);
/**
* @brief Set ap pixel at a defined position.
@@ -151,7 +152,7 @@ class LedMatrix
unsigned int displayWidth; // matrix width [pixel]
unsigned int displayHeight; // matrix height [pixel]
unsigned int modules; // number of 8x8 mudules
- ModuleOrientation moduleOrientation;
+ uint8_t moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
LedControl* ledControl;
int charWidth;
diff --git a/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h b/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
deleted file mode 100644
index da3becc4e..000000000
--- a/lib/lib_display/LedControl/src/font_5x8_horizontal_MSB.h
+++ /dev/null
@@ -1,267 +0,0 @@
-// 5x8 ascii font
-#ifndef font_5x8_horizontal_MSB_h
-#define font_5x8_horizontal_MSB_h
-
-const unsigned int font_char_width = 5;
-const unsigned int font_char_height = 8;
-
-const char font[256][8]={
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
-{0x0E,0x11,0x1B,0x11,0x1F,0x0E,0x00,0x00}, // 0x01
-{0x0E,0x15,0x1F,0x11,0x1F,0x0E,0x00,0x00}, // 0x02
-{0x0A,0x1F,0x1F,0x1F,0x0E,0x04,0x00,0x00}, // 0x03
-{0x04,0x04,0x0E,0x1F,0x0E,0x04,0x04,0x00}, // 0x04
-{0x04,0x0E,0x04,0x1F,0x15,0x04,0x0E,0x00}, // 0x05
-{0x04,0x0E,0x1F,0x1F,0x15,0x04,0x0E,0x00}, // 0x06
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
-{0x03,0x03,0x0E,0x11,0x11,0x11,0x0E,0x00}, // 0x0B
-{0x0E,0x11,0x11,0x11,0x0E,0x04,0x0E,0x04}, // 0x0C
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
-{0x03,0x0F,0x09,0x09,0x0B,0x1B,0x18,0x00}, // 0x0E
-{0x00,0x15,0x0E,0x1B,0x0E,0x15,0x00,0x00}, // 0x0F
-{0x00,0x10,0x1C,0x1F,0x1C,0x10,0x00,0x00}, // 0x10
-{0x00,0x01,0x07,0x1F,0x07,0x01,0x00,0x00}, // 0x11
-{0x04,0x0E,0x04,0x04,0x04,0x0E,0x04,0x00}, // 0x12
-{0x00,0x0A,0x0A,0x0A,0x00,0x0A,0x00,0x00}, // 0x13
-{0x0E,0x1A,0x1A,0x0A,0x0A,0x0A,0x0A,0x00}, // 0x14
-{0x06,0x08,0x04,0x0A,0x04,0x02,0x0C,0x00}, // 0x15
-{0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,0x00}, // 0x16
-{0x04,0x0E,0x04,0x0E,0x04,0x00,0x0E,0x00}, // 0x17
-{0x04,0x0E,0x04,0x04,0x04,0x04,0x04,0x00}, // 0x18
-{0x04,0x04,0x04,0x04,0x04,0x0E,0x04,0x00}, // 0x19
-{0x00,0x00,0x02,0x0F,0x02,0x00,0x00,0x00}, // 0x1A
-{0x00,0x00,0x04,0x0F,0x04,0x00,0x00,0x00}, // 0x1B
-{0x00,0x00,0x08,0x08,0x08,0x0F,0x00,0x00}, // 0x1C
-{0x00,0x00,0x0A,0x1F,0x0A,0x00,0x00,0x00}, // 0x1D
-{0x00,0x04,0x04,0x0E,0x0E,0x1F,0x00,0x00}, // 0x1E
-{0x00,0x1F,0x0E,0x0E,0x04,0x04,0x00,0x00}, // 0x1F
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
-{0x04,0x04,0x04,0x04,0x00,0x04,0x00,0x00}, // 0x21
-{0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22
-{0x00,0x05,0x1F,0x0A,0x1F,0x14,0x00,0x00}, // 0x23
-{0x04,0x0E,0x0C,0x04,0x06,0x0E,0x04,0x00}, // 0x24
-{0x09,0x15,0x0E,0x0E,0x15,0x12,0x00,0x00}, // 0x25
-{0x04,0x0A,0x0C,0x15,0x12,0x0D,0x00,0x00}, // 0x26
-{0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x27
-{0x03,0x04,0x08,0x08,0x08,0x04,0x03,0x00}, // 0x28
-{0x18,0x04,0x02,0x02,0x02,0x04,0x18,0x00}, // 0x29
-{0x04,0x0A,0x04,0x0A,0x00,0x00,0x00,0x00}, // 0x2A
-{0x00,0x00,0x00,0x04,0x0E,0x04,0x00,0x00}, // 0x2B
-{0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x08}, // 0x2C
-{0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0x2D
-{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00}, // 0x2E
-{0x01,0x02,0x02,0x04,0x04,0x08,0x08,0x00}, // 0x2F
-{0x06,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0x30
-{0x04,0x0C,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0x31
-{0x0C,0x02,0x02,0x04,0x08,0x0E,0x00,0x00}, // 0x32
-{0x0C,0x02,0x0C,0x02,0x02,0x0C,0x00,0x00}, // 0x33
-{0x02,0x06,0x0A,0x0F,0x02,0x02,0x00,0x00}, // 0x34
-{0x0E,0x08,0x0C,0x02,0x02,0x0C,0x00,0x00}, // 0x35
-{0x06,0x08,0x0E,0x09,0x09,0x06,0x00,0x00}, // 0x36
-{0x0F,0x01,0x02,0x04,0x04,0x04,0x00,0x00}, // 0x37
-{0x06,0x09,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x38
-{0x06,0x09,0x09,0x07,0x01,0x06,0x00,0x00}, // 0x39
-{0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00}, // 0x3A
-{0x00,0x00,0x04,0x00,0x00,0x04,0x04,0x08}, // 0x3B
-{0x00,0x01,0x02,0x0C,0x02,0x01,0x00,0x00}, // 0x3C
-{0x00,0x00,0x0F,0x00,0x0F,0x00,0x00,0x00}, // 0x3D
-{0x00,0x08,0x04,0x03,0x04,0x08,0x00,0x00}, // 0x3E
-{0x0E,0x01,0x02,0x04,0x00,0x04,0x00,0x00}, // 0x3F
-{0x06,0x09,0x13,0x15,0x17,0x10,0x0F,0x00}, // 0x40
-{0x00,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0x41
-{0x00,0x0E,0x0A,0x0C,0x0A,0x0E,0x00,0x00}, // 0x42
-{0x00,0x07,0x08,0x08,0x08,0x07,0x00,0x00}, // 0x43
-{0x00,0x0E,0x09,0x09,0x09,0x0E,0x00,0x00}, // 0x44
-{0x00,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0x45
-{0x00,0x0E,0x08,0x0E,0x08,0x08,0x00,0x00}, // 0x46
-{0x00,0x07,0x08,0x0B,0x09,0x07,0x00,0x00}, // 0x47
-{0x00,0x09,0x09,0x0F,0x09,0x09,0x00,0x00}, // 0x48
-{0x00,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0x49
-{0x00,0x0E,0x02,0x02,0x02,0x0C,0x00,0x00}, // 0x4A
-{0x00,0x09,0x0A,0x0C,0x0A,0x09,0x00,0x00}, // 0x4B
-{0x00,0x08,0x08,0x08,0x08,0x0F,0x00,0x00}, // 0x4C
-{0x00,0x11,0x1B,0x15,0x15,0x11,0x00,0x00}, // 0x4D
-{0x00,0x09,0x0D,0x0B,0x09,0x09,0x00,0x00}, // 0x4E
-{0x00,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0x4F
-{0x00,0x0E,0x09,0x0E,0x08,0x08,0x00,0x00}, // 0x50
-{0x00,0x0E,0x11,0x11,0x11,0x0E,0x02,0x01}, // 0x51
-{0x00,0x0C,0x0A,0x0C,0x0A,0x09,0x00,0x00}, // 0x52
-{0x00,0x06,0x08,0x04,0x02,0x0C,0x00,0x00}, // 0x53
-{0x00,0x1F,0x04,0x04,0x04,0x04,0x00,0x00}, // 0x54
-{0x00,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0x55
-{0x00,0x09,0x09,0x09,0x06,0x06,0x00,0x00}, // 0x56
-{0x00,0x11,0x15,0x15,0x0A,0x0A,0x00,0x00}, // 0x57
-{0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00}, // 0x58
-{0x00,0x11,0x0A,0x04,0x04,0x04,0x00,0x00}, // 0x59
-{0x00,0x0F,0x01,0x06,0x08,0x0F,0x00,0x00}, // 0x5A
-{0x06,0x04,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x5B
-{0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00}, // 0x5C
-{0x0C,0x04,0x04,0x04,0x04,0x04,0x0C,0x00}, // 0x5D
-{0x04,0x0A,0x0A,0x11,0x11,0x00,0x00,0x00}, // 0x5E
-{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00}, // 0x5F
-{0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60
-{0x00,0x00,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x61
-{0x08,0x08,0x0E,0x09,0x09,0x0E,0x00,0x00}, // 0x62
-{0x00,0x00,0x06,0x08,0x08,0x06,0x00,0x00}, // 0x63
-{0x02,0x02,0x0E,0x12,0x12,0x0E,0x00,0x00}, // 0x64
-{0x00,0x00,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x65
-{0x03,0x04,0x0F,0x04,0x04,0x04,0x00,0x00}, // 0x66
-{0x00,0x00,0x07,0x09,0x0F,0x01,0x0E,0x00}, // 0x67
-{0x08,0x08,0x0A,0x0D,0x09,0x09,0x00,0x00}, // 0x68
-{0x04,0x00,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x69
-{0x02,0x00,0x0E,0x02,0x02,0x02,0x0C,0x00}, // 0x6A
-{0x08,0x08,0x0A,0x0C,0x0A,0x09,0x00,0x00}, // 0x6B
-{0x0C,0x04,0x04,0x04,0x04,0x04,0x00,0x00}, // 0x6C
-{0x00,0x00,0x15,0x1F,0x15,0x15,0x00,0x00}, // 0x6D
-{0x00,0x00,0x0A,0x0D,0x09,0x09,0x00,0x00}, // 0x6E
-{0x00,0x00,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x6F
-{0x00,0x00,0x0E,0x09,0x09,0x0E,0x08,0x00}, // 0x70
-{0x00,0x00,0x0E,0x12,0x12,0x0E,0x02,0x00}, // 0x71
-{0x00,0x00,0x0A,0x0C,0x08,0x08,0x00,0x00}, // 0x72
-{0x00,0x00,0x06,0x0C,0x02,0x0C,0x00,0x00}, // 0x73
-{0x00,0x04,0x0F,0x04,0x04,0x02,0x00,0x00}, // 0x74
-{0x00,0x00,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x75
-{0x00,0x00,0x09,0x09,0x06,0x06,0x00,0x00}, // 0x76
-{0x00,0x00,0x15,0x15,0x0E,0x0A,0x00,0x00}, // 0x77
-{0x00,0x00,0x09,0x06,0x06,0x09,0x00,0x00}, // 0x78
-{0x00,0x00,0x09,0x09,0x06,0x06,0x1C,0x00}, // 0x79
-{0x00,0x00,0x0E,0x06,0x08,0x0E,0x00,0x00}, // 0x7A
-{0x02,0x04,0x04,0x08,0x04,0x04,0x02,0x00}, // 0x7B
-{0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00}, // 0x7C
-{0x08,0x04,0x04,0x02,0x04,0x04,0x08,0x00}, // 0x7D
-{0x00,0x00,0x00,0x0D,0x12,0x00,0x00,0x00}, // 0x7E
-{0x00,0x04,0x0A,0x0A,0x0A,0x0E,0x00,0x00}, // 0x7F
-{0x00,0x07,0x08,0x08,0x08,0x07,0x02,0x04}, // 0x80
-{0x09,0x00,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x81
-{0x01,0x02,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x82
-{0x06,0x09,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x83
-{0x0A,0x00,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x84
-{0x10,0x08,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x85
-{0x04,0x0A,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0x86
-{0x00,0x00,0x06,0x08,0x08,0x06,0x02,0x04}, // 0x87
-{0x06,0x09,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x88
-{0x0A,0x00,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x89
-{0x10,0x08,0x04,0x0E,0x08,0x06,0x00,0x00}, // 0x8A
-{0x0A,0x00,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x8B
-{0x06,0x09,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x8C
-{0x10,0x08,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0x8D
-{0x0A,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0x8E
-{0x04,0x0A,0x04,0x0A,0x1F,0x11,0x00,0x00}, // 0x8F
-{0x01,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0x90
-{0x00,0x00,0x1A,0x07,0x1C,0x13,0x00,0x00}, // 0x91
-{0x00,0x07,0x0A,0x0B,0x1E,0x13,0x00,0x00}, // 0x92
-{0x0C,0x12,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x93
-{0x09,0x00,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x94
-{0x10,0x08,0x06,0x09,0x09,0x06,0x00,0x00}, // 0x95
-{0x0C,0x12,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x96
-{0x08,0x04,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0x97
-{0x09,0x00,0x09,0x09,0x06,0x06,0x1C,0x00}, // 0x98
-{0x11,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0x99
-{0x12,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0x9A
-{0x00,0x01,0x06,0x0B,0x0D,0x06,0x08,0x00}, // 0x9B
-{0x00,0x04,0x08,0x0C,0x18,0x0E,0x00,0x00}, // 0x9C
-{0x01,0x0E,0x13,0x15,0x19,0x0E,0x10,0x00}, // 0x9D
-{0x00,0x00,0x09,0x06,0x06,0x09,0x00,0x00}, // 0x9E
-{0x02,0x04,0x04,0x0E,0x04,0x04,0x08,0x00}, // 0x9F
-{0x01,0x02,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0xA0
-{0x01,0x02,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0xA1
-{0x01,0x02,0x06,0x09,0x09,0x06,0x00,0x00}, // 0xA2
-{0x01,0x02,0x09,0x09,0x0B,0x05,0x00,0x00}, // 0xA3
-{0x0F,0x00,0x0A,0x0D,0x09,0x09,0x00,0x00}, // 0xA4
-{0x1F,0x09,0x0D,0x0B,0x09,0x09,0x00,0x00}, // 0xA5
-{0x0C,0x02,0x0E,0x0A,0x0E,0x00,0x00,0x00}, // 0xA6
-{0x04,0x0A,0x0A,0x0A,0x04,0x00,0x00,0x00}, // 0xA7
-{0x00,0x04,0x00,0x04,0x04,0x02,0x0C,0x00}, // 0xA8
-{0x0E,0x17,0x17,0x15,0x17,0x0E,0x00,0x00}, // 0xA9
-{0x00,0x00,0x00,0x0E,0x02,0x02,0x00,0x00}, // 0xAA
-{0x19,0x0A,0x0F,0x05,0x0A,0x13,0x00,0x00}, // 0xAB
-{0x19,0x0A,0x0A,0x05,0x0B,0x11,0x00,0x00}, // 0xAC
-{0x00,0x00,0x04,0x00,0x04,0x04,0x04,0x00}, // 0xAD
-{0x00,0x05,0x0A,0x14,0x0A,0x05,0x00,0x00}, // 0xAE
-{0x00,0x14,0x0A,0x05,0x0A,0x14,0x00,0x00}, // 0xAF
-{0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00}, // 0xB0
-{0x15,0x0A,0x15,0x0A,0x15,0x0A,0x15,0x0A}, // 0xB1
-{0x1F,0x15,0x1F,0x15,0x1F,0x15,0x1F,0x15}, // 0xB2
-{0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}, // 0xB3
-{0x04,0x04,0x04,0x1C,0x04,0x04,0x04,0x04}, // 0xB4
-{0x02,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0xB5
-{0x06,0x09,0x04,0x0A,0x1F,0x11,0x00,0x00}, // 0xB6
-{0x08,0x04,0x0A,0x0A,0x1F,0x11,0x00,0x00}, // 0xB7
-{0x0E,0x11,0x17,0x15,0x17,0x11,0x0E,0x00}, // 0xB8
-{0x0A,0x0A,0x1A,0x02,0x1A,0x0A,0x0A,0x0A}, // 0xB9
-{0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A}, // 0xBA
-{0x00,0x00,0x1E,0x02,0x1A,0x0A,0x0A,0x0A}, // 0xBB
-{0x0A,0x0A,0x1A,0x02,0x1E,0x00,0x00,0x00}, // 0xBC
-{0x00,0x04,0x0E,0x08,0x0E,0x04,0x00,0x00}, // 0xBD
-{0x00,0x11,0x0A,0x04,0x0E,0x04,0x00,0x00}, // 0xBE
-{0x00,0x00,0x00,0x1C,0x04,0x04,0x04,0x04}, // 0xBF
-{0x04,0x04,0x04,0x07,0x00,0x00,0x00,0x00}, // 0xC0
-{0x04,0x04,0x04,0x1F,0x00,0x00,0x00,0x00}, // 0xC1
-{0x00,0x00,0x00,0x1F,0x04,0x04,0x04,0x04}, // 0xC2
-{0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04}, // 0xC3
-{0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00}, // 0xC4
-{0x04,0x04,0x04,0x1F,0x04,0x04,0x04,0x04}, // 0xC5
-{0x0D,0x12,0x0C,0x02,0x0E,0x0F,0x00,0x00}, // 0xC6
-{0x0D,0x12,0x04,0x0A,0x1F,0x11,0x00,0x00}, // 0xC7
-{0x0A,0x0A,0x0B,0x08,0x0F,0x00,0x00,0x00}, // 0xC8
-{0x00,0x00,0x0F,0x08,0x0B,0x0A,0x0A,0x0A}, // 0xC9
-{0x0A,0x0A,0x1B,0x00,0x1F,0x00,0x00,0x00}, // 0xCA
-{0x00,0x00,0x1F,0x00,0x1B,0x0A,0x0A,0x0A}, // 0xCB
-{0x0A,0x0A,0x0B,0x08,0x0B,0x0A,0x0A,0x0A}, // 0xCC
-{0x00,0x00,0x1F,0x00,0x1F,0x00,0x00,0x00}, // 0xCD
-{0x0A,0x0A,0x1B,0x00,0x1B,0x0A,0x0A,0x0A}, // 0xCE
-{0x00,0x11,0x0E,0x0A,0x0E,0x11,0x00,0x00}, // 0xCF
-{0x1E,0x04,0x0E,0x12,0x12,0x0C,0x00,0x00}, // 0xD0
-{0x00,0x0E,0x09,0x1D,0x09,0x0E,0x00,0x00}, // 0xD1
-{0x0E,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0xD2
-{0x11,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0xD3
-{0x10,0x0E,0x08,0x0E,0x08,0x0E,0x00,0x00}, // 0xD4
-{0x00,0x00,0x0C,0x04,0x04,0x04,0x00,0x00}, // 0xD5
-{0x01,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xD6
-{0x0E,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xD7
-{0x11,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xD8
-{0x04,0x04,0x04,0x1C,0x00,0x00,0x00,0x00}, // 0xD9
-{0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04}, // 0xDA
-{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, // 0xDB
-{0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F}, // 0xDC
-{0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x04}, // 0xDD
-{0x10,0x0E,0x04,0x04,0x04,0x0E,0x00,0x00}, // 0xDE
-{0x1F,0x1F,0x1F,0x1F,0x00,0x00,0x00,0x00}, // 0xDF
-{0x01,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE0
-{0x04,0x0A,0x0A,0x0A,0x09,0x0A,0x00,0x00}, // 0xE1
-{0x0E,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE2
-{0x10,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE3
-{0x0D,0x12,0x06,0x09,0x09,0x06,0x00,0x00}, // 0xE4
-{0x1E,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00}, // 0xE5
-{0x00,0x00,0x09,0x09,0x0B,0x0D,0x08,0x00}, // 0xE6
-{0x08,0x08,0x0E,0x09,0x09,0x0E,0x08,0x00}, // 0xE7
-{0x00,0x08,0x0E,0x09,0x0E,0x08,0x00,0x00}, // 0xE8
-{0x01,0x12,0x12,0x12,0x12,0x0C,0x00,0x00}, // 0xE9
-{0x0F,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0xEA
-{0x10,0x09,0x09,0x09,0x09,0x06,0x00,0x00}, // 0xEB
-{0x01,0x02,0x09,0x09,0x06,0x06,0x18,0x00}, // 0xEC
-{0x02,0x15,0x0A,0x04,0x04,0x04,0x00,0x00}, // 0xED
-{0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEE
-{0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEF
-{0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0xF0
-{0x00,0x00,0x04,0x0E,0x04,0x0E,0x00,0x00}, // 0xF1
-{0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x1F}, // 0xF2
-{0x19,0x1A,0x0A,0x1D,0x0B,0x11,0x00,0x00}, // 0xF3
-{0x0E,0x1A,0x1A,0x0A,0x0A,0x0A,0x0A,0x00}, // 0xF4
-{0x06,0x08,0x04,0x0A,0x04,0x02,0x0C,0x00}, // 0xF5
-{0x00,0x04,0x00,0x0E,0x00,0x04,0x00,0x00}, // 0xF6
-{0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x08}, // 0xF7
-{0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00}, // 0xF8
-{0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF9
-{0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00}, // 0xFA
-{0x0C,0x04,0x04,0x04,0x0E,0x00,0x00,0x00}, // 0xFB
-{0x0C,0x02,0x0C,0x02,0x0C,0x00,0x00,0x00}, // 0xFC
-{0x0C,0x02,0x04,0x08,0x0E,0x00,0x00,0x00}, // 0xFD
-{0x00,0x00,0x0F,0x0F,0x0F,0x0F,0x00,0x00}, // 0xFE
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
-};
-
-#endif // font_5x8_horizontal_MSB_h
\ No newline at end of file
diff --git a/lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h b/lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h
deleted file mode 100644
index e1a8af7ae..000000000
--- a/lib/lib_display/LedControl/src/font_8x8_horizontal_latin_MSB.h
+++ /dev/null
@@ -1,265 +0,0 @@
-#ifndef font_8x8_horizontal_latin_MSB_h
-#define font_8x8_horizontal_latin_MSB_h
-
-const unsigned int font_char_width = 8;
-const unsigned int font_char_height = 8;
-
-const char font[256][8]={
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
-{0x0E,0x11,0x1B,0x11,0x15,0x11,0x0E,0x00}, // 0x01
-{0x0E,0x1F,0x15,0x1F,0x11,0x1F,0x0E,0x00}, // 0x02
-{0x00,0x0A,0x1F,0x1F,0x1F,0x0E,0x04,0x00}, // 0x03
-{0x00,0x04,0x0E,0x1F,0x1F,0x0E,0x04,0x00}, // 0x04
-{0x04,0x0E,0x0E,0x04,0x1F,0x1F,0x04,0x00}, // 0x05
-{0x00,0x04,0x0E,0x1F,0x1F,0x04,0x0E,0x00}, // 0x06
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
-{0x00,0x07,0x03,0x0D,0x12,0x12,0x0C,0x00}, // 0x0B
-{0x0E,0x11,0x11,0x0E,0x04,0x0E,0x04,0x00}, // 0x0C
-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
-{0x03,0x0D,0x0B,0x0D,0x0B,0x1B,0x18,0x00}, // 0x0E
-{0x00,0x15,0x0E,0x1B,0x0E,0x15,0x00,0x00}, // 0x0F
-{0x08,0x0C,0x0E,0x0F,0x0E,0x0C,0x08,0x00}, // 0x10
-{0x02,0x06,0x0E,0x1E,0x0E,0x06,0x02,0x00}, // 0x11
-{0x04,0x0E,0x1F,0x04,0x1F,0x0E,0x04,0x00}, // 0x12
-{0x0A,0x0A,0x0A,0x0A,0x0A,0x00,0x0A,0x00}, // 0x13
-{0x0F,0x15,0x15,0x0D,0x05,0x05,0x05,0x00}, // 0x14
-{0x0E,0x11,0x0C,0x0A,0x06,0x11,0x0E,0x00}, // 0x15
-{0x00,0x00,0x00,0x00,0x00,0x1E,0x1E,0x00}, // 0x16
-{0x04,0x0E,0x1F,0x04,0x1F,0x0E,0x04,0x0E}, // 0x17
-{0x04,0x0E,0x1F,0x04,0x04,0x04,0x04,0x00}, // 0x18
-{0x04,0x04,0x04,0x04,0x1F,0x0E,0x04,0x00}, // 0x19
-{0x00,0x04,0x06,0x1F,0x06,0x04,0x00,0x00}, // 0x1A
-{0x00,0x04,0x0C,0x1F,0x0C,0x04,0x00,0x00}, // 0x1B
-{0x00,0x00,0x00,0x10,0x10,0x10,0x1F,0x00}, // 0x1C
-{0x00,0x0A,0x0A,0x1F,0x0A,0x0A,0x00,0x00}, // 0x1D
-{0x04,0x04,0x0E,0x0E,0x1F,0x1F,0x00,0x00}, // 0x1E
-{0x1F,0x1F,0x0E,0x0E,0x04,0x04,0x00,0x00}, // 0x1F
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
- { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
- { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
- { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
- { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
- { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
- { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
- { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
- { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
- { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
- { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
- { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
- { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
- { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
- { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
- { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
- { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
- { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
- { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
- { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
- { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
- { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
- { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
- { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
- { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
- { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (;)
- { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
- { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
- { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
- { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
- { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
- { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
- { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
- { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
- { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
- { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
- { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
- { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
- { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
- { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
- { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
- { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
- { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
- { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
- { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
- { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
- { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
- { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
- { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
- { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
- { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
- { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
- { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
- { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
- { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
- { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
- { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
- { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
- { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
- { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
- { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
- { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
- { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
- { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
- { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
- { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
- { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
- { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
- { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
- { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
- { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
- { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
- { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
- { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
- { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
- { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
- { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
- { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
- { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
- { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
- { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
- { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
- { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
- { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
- { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
- { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
- { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
- { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
- { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
- { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
- { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
- { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007F{0x0E,0x11,0x10,0x10,0x11,0x0E,0x04,0x0C}, // 0x80
-{0x12,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x81
-{0x03,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x82
-{0x0E,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x83
-{0x0A,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x84
-{0x0C,0x00,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x85
-{0x0E,0x0A,0x0E,0x01,0x0F,0x11,0x0F,0x00}, // 0x86
-{0x00,0x0E,0x11,0x10,0x11,0x0E,0x04,0x0C}, // 0x87
-{0x0E,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x88
-{0x0A,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x89
-{0x0C,0x00,0x0E,0x11,0x1E,0x10,0x0E,0x00}, // 0x8A
-{0x0A,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8B
-{0x0E,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8C
-{0x08,0x00,0x04,0x04,0x04,0x04,0x06,0x00}, // 0x8D
-{0x0A,0x00,0x04,0x0A,0x11,0x1F,0x11,0x00}, // 0x8E
-{0x0E,0x0A,0x0E,0x1B,0x11,0x1F,0x11,0x00}, // 0x8F
-{0x03,0x00,0x1F,0x10,0x1E,0x10,0x1F,0x00}, // 0x90
-{0x00,0x00,0x1E,0x05,0x1F,0x14,0x0F,0x00}, // 0x91
-{0x0F,0x14,0x14,0x1F,0x14,0x14,0x17,0x00}, // 0x92
-{0x0E,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x93
-{0x0A,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x94
-{0x18,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00}, // 0x95
-{0x0E,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x96
-{0x18,0x00,0x12,0x12,0x12,0x16,0x0A,0x00}, // 0x97
-{0x0A,0x00,0x12,0x12,0x12,0x0E,0x04,0x18}, // 0x98
-{0x12,0x0C,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0x99
-{0x0A,0x00,0x12,0x12,0x12,0x12,0x0C,0x00}, // 0x9A
-{0x00,0x00,0x01,0x0E,0x16,0x1A,0x1C,0x20}, // 0x9B
-{0x06,0x09,0x08,0x1E,0x08,0x09,0x17,0x00}, // 0x9C
-{0x0F,0x13,0x15,0x15,0x15,0x19,0x1E,0x00}, // 0x9D
-{0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00}, // 0x9E
-{0x02,0x05,0x04,0x0E,0x04,0x04,0x14,0x08}, // 0x9F
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A0 (no break space)
- { 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+00A1 (inverted !)
- { 0x18, 0x18, 0x7E, 0x03, 0x03, 0x7E, 0x18, 0x18}, // U+00A2 (dollarcents)
- { 0x1C, 0x36, 0x26, 0x0F, 0x06, 0x67, 0x3F, 0x00}, // U+00A3 (pound sterling)
- { 0x00, 0x00, 0x63, 0x3E, 0x36, 0x3E, 0x63, 0x00}, // U+00A4 (currency mark)
- { 0x33, 0x33, 0x1E, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C}, // U+00A5 (yen)
- { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+00A6 (broken pipe)
- { 0x7C, 0xC6, 0x1C, 0x36, 0x36, 0x1C, 0x33, 0x1E}, // U+00A7 (paragraph)
- { 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A8 (diaeresis)
- { 0x3C, 0x42, 0x99, 0x85, 0x85, 0x99, 0x42, 0x3C}, // U+00A9 (copyright symbol)
- { 0x3C, 0x36, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00}, // U+00AA (superscript a)
- { 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, // U+00AB (<<)
- { 0x00, 0x00, 0x00, 0x3F, 0x30, 0x30, 0x00, 0x00}, // U+00AC (gun pointing left)
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AD (soft hyphen)
- { 0x3C, 0x42, 0x9D, 0xA5, 0x9D, 0xA5, 0x42, 0x3C}, // U+00AE (registered symbol)
- { 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AF (macron)
- { 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B0 (degree)
- { 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00}, // U+00B1 (plusminus)
- { 0x1C, 0x30, 0x18, 0x0C, 0x3C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 2)
- { 0x1C, 0x30, 0x18, 0x30, 0x1C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 3)
- { 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00B2 (aigu)
- { 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x03}, // U+00B5 (mu)
- { 0xFE, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0x00}, // U+00B6 (pilcrow)
- { 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, // U+00B7 (central dot)
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1E}, // U+00B8 (cedille)
- { 0x08, 0x0C, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B9 (superscript 1)
- { 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00BA (superscript 0)
- { 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, // U+00BB (>>)
- { 0xC3, 0x63, 0x33, 0xBD, 0xEC, 0xF6, 0xF3, 0x03}, // U+00BC (1/4)
- { 0xC3, 0x63, 0x33, 0x7B, 0xCC, 0x66, 0x33, 0xF0}, // U+00BD (1/2)
- { 0x03, 0xC4, 0x63, 0xB4, 0xDB, 0xAC, 0xE6, 0x80}, // U+00BE (3/4)
- { 0x0C, 0x00, 0x0C, 0x06, 0x03, 0x33, 0x1E, 0x00}, // U+00BF (inverted ?)
- { 0x07, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C0 (A grave)
- { 0x70, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C1 (A aigu)
- { 0x1C, 0x36, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C2 (A circumflex)
- { 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C3 (A ~)
- { 0x63, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x00}, // U+00C4 (A umlaut)
- { 0x0C, 0x0C, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x00}, // U+00C5 (A ring)
- { 0x7C, 0x36, 0x33, 0x7F, 0x33, 0x33, 0x73, 0x00}, // U+00C6 (AE)
- { 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x18, 0x30, 0x1E}, // U+00C7 (C cedille)
- { 0x07, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C8 (E grave)
- { 0x38, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C9 (E aigu)
- { 0x0C, 0x12, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CA (E circumflex)
- { 0x36, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CB (E umlaut)
- { 0x07, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CC (I grave)
- { 0x38, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CD (I aigu)
- { 0x0C, 0x12, 0x00, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CE (I circumflex)
- { 0x33, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CF (I umlaut)
- { 0x3F, 0x66, 0x6F, 0x6F, 0x66, 0x66, 0x3F, 0x00}, // U+00D0 (Eth)
- { 0x3F, 0x00, 0x33, 0x37, 0x3F, 0x3B, 0x33, 0x00}, // U+00D1 (N ~)
- { 0x0E, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D2 (O grave)
- { 0x70, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D3 (O aigu)
- { 0x3C, 0x66, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D4 (O circumflex)
- { 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x63, 0x3E, 0x00}, // U+00D5 (O ~)
- { 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+00D6 (O umlaut)
- { 0x00, 0x36, 0x1C, 0x08, 0x1C, 0x36, 0x00, 0x00}, // U+00D7 (multiplicative x)
- { 0x5C, 0x36, 0x73, 0x7B, 0x6F, 0x36, 0x1D, 0x00}, // U+00D8 (O stroke)
- { 0x0E, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00D9 (U grave)
- { 0x70, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DA (U aigu)
- { 0x3C, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DB (U circumflex)
- { 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+00DC (U umlaut)
- { 0x70, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x00}, // U+00DD (Y aigu)
- { 0x0F, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+00DE (Thorn)
- { 0x00, 0x1E, 0x33, 0x1F, 0x33, 0x1F, 0x03, 0x03}, // U+00DF (beta)
- { 0x07, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E0 (a grave)
- { 0x38, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E1 (a aigu)
- { 0x7E, 0xC3, 0x3C, 0x60, 0x7C, 0x66, 0xFC, 0x00}, // U+00E2 (a circumflex)
- { 0x6E, 0x3B, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E3 (a ~)
- { 0x33, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E4 (a umlaut)
- { 0x0C, 0x0C, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E5 (a ring)
- { 0x00, 0x00, 0xFE, 0x30, 0xFE, 0x33, 0xFE, 0x00}, // U+00E6 (ae)
- { 0x00, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+00E7 (c cedille)
- { 0x07, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E8 (e grave)
- { 0x38, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E9 (e aigu)
- { 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00}, // U+00EA (e circumflex)
- { 0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00EB (e umlaut)
- { 0x07, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EC (i grave)
- { 0x1C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00ED (i augu)
- { 0x3E, 0x63, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EE (i circumflex)
- { 0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EF (i umlaut)
- { 0x1B, 0x0E, 0x1B, 0x30, 0x3E, 0x33, 0x1E, 0x00}, // U+00F0 (eth)
- { 0x00, 0x1F, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x00}, // U+00F1 (n ~)
- { 0x00, 0x07, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F2 (o grave)
- { 0x00, 0x38, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F3 (o aigu)
- { 0x1E, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F4 (o circumflex)
- { 0x6E, 0x3B, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F5 (o ~)
- { 0x00, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F6 (o umlaut)
- { 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00}, // U+00F7 (division)
- { 0x00, 0x60, 0x3C, 0x76, 0x7E, 0x6E, 0x3C, 0x06}, // U+00F8 (o stroke)
- { 0x00, 0x07, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00F9 (u grave)
- { 0x00, 0x38, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FA (u aigu)
- { 0x1E, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FB (u circumflex)
- { 0x00, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FC (u umlaut)
- { 0x00, 0x38, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+00FD (y aigu)
- { 0x00, 0x00, 0x06, 0x3E, 0x66, 0x3E, 0x06, 0x00}, // U+00FE (thorn)
- { 0x00, 0x33, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F} // U+00FF (y umlaut)
-};
-
-#endif
\ No newline at end of file
diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino
index 3ec3ac332..82a4a24bb 100644
--- a/tasmota/xdsp_19_max7219_matrix.ino
+++ b/tasmota/xdsp_19_max7219_matrix.ino
@@ -113,22 +113,31 @@ bool MAX7291Matrix_initDriver(void)
}
Settings->display_model = XDSP_19;
+ renderer = nullptr; // renderer not yet used
if (Settings->display_width) // [pixel]
{
LedMatrix_settings.modulesPerRow = (Settings->display_width - 1) / 8 + 1;
}
Settings->display_width = 8 * LedMatrix_settings.modulesPerRow;
- Settings->display_cols[0] = Settings->display_width;
+ Settings->display_cols[0] = LedMatrix_settings.modulesPerRow;
if (Settings->display_height) // [pixel]
{
LedMatrix_settings.modulesPerCol = (Settings->display_height - 1) / 8 + 1;
}
- Settings->display_height = 8 * LedMatrix_settings. modulesPerCol;
- Settings->display_rows = Settings->display_height;
- Settings->display_cols[1] = Settings->display_height;
+ Settings->display_height = 8 * LedMatrix_settings.modulesPerCol;
+ Settings->display_rows = LedMatrix_settings.modulesPerCol;
+ Settings->display_cols[1] = LedMatrix_settings.modulesPerCol;
max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol);
+ if( LedMatrix_settings.show_clock == 0)
+ {
+ Settings->display_mode = 0; // text mode
+ }
+ else{
+ Settings->display_mode = 1; // clock mode
+ }
max2791Matrix_initDriver_done = true;
+ AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_initDriver DIN:%d CLK:%d CS:%d size(%dx%d)"), Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol);
return MAX7291Matrix_init();
}
@@ -137,12 +146,17 @@ bool MAX7291Matrix_init(void)
{
int intensity = GetDisplayDimmer16(); // 0..15
max7219_Matrix->setIntensity(intensity);
- int orientation = Settings->display_rotate;
- max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)orientation );
- AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_init %dx%d modules, orientation: %d, intensity: %d"), LedMatrix_settings.modulesPerRow , LedMatrix_settings.modulesPerCol, orientation, intensity);
-
- //max7219_Matrix->test();
- AddLog(LOG_LEVEL_INFO, PSTR("MTX: display test"));
+ if(Settings->display_rotate <= 3)
+ {
+ max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)Settings->display_rotate );
+ }
+ else
+ {
+ // default for most 32x8 modules
+ Settings->display_rotate = LedMatrix::ORIENTATION_UPSIDE_DOWN;
+ max7219_Matrix->setOrientation( LedMatrix::ORIENTATION_UPSIDE_DOWN );
+ }
+ AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_init orientation: %d, intensity: %d"), Settings->display_rotate, intensity);
return true;
}
@@ -183,28 +197,38 @@ bool MAX7291Matrix_clock(void)
{
LedMatrix_settings.show_clock = XdrvMailbox.payload;
if (ArgC() == 0)
- XdrvMailbox.payload = 1;
- if (XdrvMailbox.payload > 1)
- {
- LedMatrix_settings.timeFormat = "%H:%M";
- if(LedMatrix_settings.modulesPerRow > 6)
- {
- LedMatrix_settings.timeFormat = "%H:%M:%S";
- }
XdrvMailbox.payload = 2;
- }
- else
- {
- LedMatrix_settings.timeFormat = "%I:%M";
- if(LedMatrix_settings.modulesPerRow > 6)
+ switch(XdrvMailbox.payload)
{
- LedMatrix_settings.timeFormat = "%I:%M:%S";
+ case 0:
+ // no clock, switch to text mode
+ Settings->display_mode = 0;
+ return true;
+ case 1:
+ // 12 h clock
+ LedMatrix_settings.timeFormat = "%I:%M";
+ if(LedMatrix_settings.modulesPerRow > 6)
+ {
+ LedMatrix_settings.timeFormat = "%I:%M:%S";
+ }
+ Settings->display_mode = 1;
+ break;
+ case 2:
+ // 24 h clock
+ LedMatrix_settings.timeFormat = "%H:%M";
+ if(LedMatrix_settings.modulesPerRow > 6)
+ {
+ LedMatrix_settings.timeFormat = "%H:%M:%S";
+ }
+ Settings->display_mode = 1;
+ break;
+ default:
+ return false;
}
- XdrvMailbox.payload = 1;
- }
AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: LedMatrix_settings.show_clock %d, timeFormat %s"), LedMatrix_settings.show_clock, LedMatrix_settings.timeFormat);
+ max7219_Matrix->clearDisplay();
MAX7291Matrix_showTime();
return true;
}
@@ -220,7 +244,7 @@ bool MAX7291Matrix_showTime()
timeinfo = localtime(&rawtime);
strftime(timeStr, 10, LedMatrix_settings.timeFormat, timeinfo);
- max7219_Matrix->drawText(timeStr);
+ max7219_Matrix->drawText(timeStr, false); // false: do not clear desplay on update to prevent flicker
return true;
}
#endif // USE_DISPLAY_MODES1TO5
@@ -254,7 +278,16 @@ bool Xdsp19(uint8_t function)
result = max7219_Matrix->setIntensity(GetDisplayDimmer16());
break;
case FUNC_DISPLAY_DRAW_STRING:
- result = max7219_Matrix->drawText(dsp_str);
+ case FUNC_DISPLAY_SCROLLTEXT:
+ case FUNC_DISPLAY_SEVENSEG_TEXT:
+ Settings->display_mode = 0; // text mode
+ LedMatrix_settings.show_clock = 0; // disable clock mode
+ result = max7219_Matrix->drawText(XdrvMailbox.data, true); // true: clears display before drawing text
+ break;
+ case FUNC_DISPLAY_SEVENSEG_TEXTNC:
+ Settings->display_mode = 0; // text mode
+ LedMatrix_settings.show_clock = 0; // disable clock mode
+ result = max7219_Matrix->drawText(XdrvMailbox.data, false); // false: does not clear display before drawing text
break;
case FUNC_DISPLAY_SCROLLDELAY:
result = MAX7291Matrix_scrollDelay();
From 09974f8873fa1ffdb8eeb19f4568e6dec31b7ed1 Mon Sep 17 00:00:00 2001
From: Michael
Date: Tue, 30 Nov 2021 14:18:26 +0100
Subject: [PATCH 012/510] Command for all Modules at once
---
lib/lib_display/LedControl/src/LedControl.cpp | 67 ++++++++++++++-----
lib/lib_display/LedControl/src/LedControl.h | 9 ++-
lib/lib_display/LedControl/src/LedMatrix.cpp | 56 +++++++++++++---
lib/lib_display/LedControl/src/LedMatrix.h | 1 +
4 files changed, 104 insertions(+), 29 deletions(-)
diff --git a/lib/lib_display/LedControl/src/LedControl.cpp b/lib/lib_display/LedControl/src/LedControl.cpp
index 11e7a2908..baaa3802c 100644
--- a/lib/lib_display/LedControl/src/LedControl.cpp
+++ b/lib/lib_display/LedControl/src/LedControl.cpp
@@ -55,18 +55,20 @@ LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
- for (int i = 0; i < 8 * MAX72XX_MAX_DEVICES; i++)
- status[i] = 0x00;
- for(int i=0;i=maxDevices)
return;
@@ -89,6 +96,13 @@ void LedControl::setScanLimit(int addr, int limit) {
spiTransfer(addr, OP_SCANLIMIT,limit);
}
+void LedControl::setScanLimit_allDevices(int limit) {
+ if(limit <0 || limit>8) return;
+
+ memset(deviceDataBuff, (byte)limit, maxDevices);
+ spiTransfer_allDevices(OP_SCANLIMIT,deviceDataBuff);
+}
+
void LedControl::setIntensity(int addr, int intensity) {
if(addr<0 || addr>=maxDevices)
return;
@@ -96,6 +110,15 @@ void LedControl::setIntensity(int addr, int intensity) {
spiTransfer(addr, OP_INTENSITY,intensity);
}
+void LedControl::setIntensity_allDevices(int intensity)
+{
+ if (intensity < 0 | intensity > 15)
+ return;
+
+ memset(deviceDataBuff, (byte)intensity, maxDevices);
+ spiTransfer_allDevices(OP_INTENSITY, deviceDataBuff);
+}
+
void LedControl::clearDisplay(int addr) {
int offset;
@@ -108,6 +131,16 @@ void LedControl::clearDisplay(int addr) {
}
}
+void LedControl::clearDisplay_allDevices()
+{
+ memset(status, (byte)0, 8 * maxDevices);
+ memset(deviceDataBuff, (byte)0, maxDevices);
+ for (int row = 0; row < 8; row++)
+ {
+ spiTransfer_allDevices(row + 1, deviceDataBuff);
+ }
+}
+
void LedControl::setLed(int addr, int row, int column, boolean state) {
int offset;
byte val=0x00;
@@ -138,13 +171,13 @@ void LedControl::setRow(int addr, int row, byte value) {
spiTransfer(addr, row+1,status[offset+row]);
}
-void LedControl::setRowLong(int row, byte *value)
+void LedControl::setRow_allDevices(int row, byte *value)
{
if (row < 0 || row > 7)
return;
for (int addr = 0; addr < maxDevices; addr++)
status[addr * 8 + row] = value[addr];
- spiTransferLong(row + 1, value);
+ spiTransfer_allDevices(row + 1, value);
}
void LedControl::setColumn(int addr, int col, byte value) {
@@ -217,7 +250,7 @@ void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data)
digitalWrite(SPI_CS,HIGH);
}
-void LedControl::spiTransferLong(byte opcode, const byte* data) {
+void LedControl::spiTransfer_allDevices(byte opcode, const byte* data) {
//Create an array with the data to shift out
for (int addr = 0; addr < maxDevices; addr++)
{
@@ -227,8 +260,8 @@ void LedControl::spiTransferLong(byte opcode, const byte* data) {
//enable the line
digitalWrite(SPI_CS, LOW);
//Now shift out the data
- for (int i = maxDevices * 2; i > 0; i--)
- shiftOut(SPI_MOSI, SPI_CLK, MSBFIRST, spidata[i - 1]);
+ for (int i = maxDevices * 2 -1; i >= 0; i--)
+ shiftOut(SPI_MOSI, SPI_CLK, MSBFIRST, spidata[i]);
//latch the data onto the display
digitalWrite(SPI_CS, HIGH);
}
diff --git a/lib/lib_display/LedControl/src/LedControl.h b/lib/lib_display/LedControl/src/LedControl.h
index 31fed9ffe..4fc7523df 100644
--- a/lib/lib_display/LedControl/src/LedControl.h
+++ b/lib/lib_display/LedControl/src/LedControl.h
@@ -69,10 +69,11 @@ class LedControl {
/* Send out a single command to one device */
void spiTransfer(int addr, byte opcode, byte data);
/* Send out a command with the same opcode to all devices */
- void spiTransferLong(byte opcode, const byte* data);
+ void spiTransfer_allDevices(byte opcode, const byte* data);
/* We keep track of the led-status for all 8 devices in this array */
byte status[8 * MAX72XX_MAX_DEVICES];
+ byte deviceDataBuff[MAX72XX_MAX_DEVICES];
/* Data is shifted out of this pin*/
int SPI_MOSI;
/* The clock is signaled on this pin */
@@ -108,6 +109,7 @@ class LedControl {
* for normal operation.
*/
void shutdown(int addr, bool status);
+ void shutdown_allDevices( bool status);
/*
* Set the number of digits (or rows) to be displayed.
@@ -118,6 +120,7 @@ class LedControl {
* limit number of digits to be displayed (1..8)
*/
void setScanLimit(int addr, int limit);
+ void setScanLimit_allDevices(int limit);
/*
* Set the brightness of the display.
@@ -126,6 +129,7 @@ class LedControl {
* intensity the brightness of the display. (0..15)
*/
void setIntensity(int addr, int intensity);
+ void setIntensity_allDevices(int intensity);
/*
* Switch all Leds on the display off.
@@ -133,6 +137,7 @@ class LedControl {
* addr address of the display to control
*/
void clearDisplay(int addr);
+ void clearDisplay_allDevices();
/*
* Set the status of a single Led.
@@ -161,7 +166,7 @@ class LedControl {
* @param row [0..8]
* @param value array of bytes, one for each device
*/
- void setRowLong(int row, byte* value);
+ void setRow_allDevices(int row, byte* value);
/*
* Set all 8 Led's in a column to a new state
diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp
index 1579e0852..59882cd15 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.cpp
+++ b/lib/lib_display/LedControl/src/LedMatrix.cpp
@@ -139,10 +139,7 @@ bool LedMatrix::clearDisplay(void)
bool LedMatrix::setIntensity(byte dim)
{
- for (int addr = 0; addr < modules; addr++)
- {
- ledControl->setIntensity(addr, dim); // 1..15
- }
+ ledControl->setIntensity_allDevices(dim); // 1..15
return true;
}
@@ -183,9 +180,51 @@ bool LedMatrix::setPixel(const int x, const int y, bool on)
void LedMatrix::refresh()
{
- for (int i = 0; i < modulesPerRow * displayHeight; i++)
+ int col = 0;
+ int pixelRow = 0;
+ int bufPos = 0;
+ int deviceRow = 0;
+ for(int ledRow = 7; ledRow >= 0; ledRow--) // refresh from buttom to top
{
- refreshByteOfBuffer(i);
+ for( int addr = 0; addr < modules; addr++)
+ {
+ switch(moduleOrientation)
+ {
+ case ORIENTATION_NORMAL:
+ col = addr % modulesPerRow;
+ pixelRow = (addr / modulesPerRow) * 8 + ledRow;
+ bufPos = pixelRow * modulesPerRow + col;
+ deviceDataBuff[addr] = buffer[bufPos];
+ deviceRow = ledRow;
+ break;
+ case ORIENTATION_UPSIDE_DOWN:
+ col = addr % modulesPerRow;
+ pixelRow = (addr / modulesPerRow) * 8 + deviceRow;
+ bufPos = pixelRow * modulesPerRow + col;
+ deviceDataBuff[addr] = revereBitorder(buffer[bufPos]); // mirror
+ deviceRow = 7 - ledRow; // upside down
+ break;
+ }
+ if(moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN)
+ {
+ col = addr % modulesPerRow;
+ pixelRow = (addr / modulesPerRow) * 8 + ledRow;
+ bufPos = pixelRow * modulesPerRow + col;
+ if(moduleOrientation == ORIENTATION_NORMAL)
+ {
+ // ORIENTATION_NORMAL
+ deviceDataBuff[addr] = buffer[bufPos];
+ deviceRow = ledRow;
+ }
+ else
+ {
+ // ORIENTATION_UPSIDE_DOWN
+ deviceDataBuff[addr] = revereBitorder(buffer[bufPos]); // mirror
+ deviceRow = 7 - ledRow; // upside down
+ }
+ }
+ }
+ ledControl->setRow_allDevices(deviceRow, deviceDataBuff); // upside down
}
}
@@ -227,10 +266,7 @@ bool LedMatrix::shutdown(bool b)
bool LedMatrix::clear(void)
{
memset(buffer, 0, MATRIX_BUFFER_SIZE);
- for (int addr = 0; addr < modules; addr++)
- {
- ledControl->clearDisplay(addr);
- }
+ ledControl->clearDisplay_allDevices();
return true;
}
diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h
index b369173d0..9fee69a5f 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.h
+++ b/lib/lib_display/LedControl/src/LedMatrix.h
@@ -154,6 +154,7 @@ class LedMatrix
unsigned int modules; // number of 8x8 mudules
uint8_t moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
+ byte deviceDataBuff[MAX72XX_MAX_DEVICES];
LedControl* ledControl;
int charWidth;
int charHeight;
From 306ed0d2dd8040f7f56eaba24a9ea3cf8b0925cc Mon Sep 17 00:00:00 2001
From: Michael
Date: Fri, 3 Dec 2021 16:50:55 +0100
Subject: [PATCH 013/510] max7219 dot matrix ready for pull request
---
lib/lib_display/LedControl/src/LedControl.cpp | 82 ++-------
lib/lib_display/LedControl/src/LedControl.h | 25 +--
lib/lib_display/LedControl/src/LedMatrix.cpp | 173 +++++++++---------
lib/lib_display/LedControl/src/LedMatrix.h | 59 ++++--
tasmota/xdsp_19_max7219_matrix.ino | 20 +-
5 files changed, 162 insertions(+), 197 deletions(-)
diff --git a/lib/lib_display/LedControl/src/LedControl.cpp b/lib/lib_display/LedControl/src/LedControl.cpp
index baaa3802c..5807aa6af 100644
--- a/lib/lib_display/LedControl/src/LedControl.cpp
+++ b/lib/lib_display/LedControl/src/LedControl.cpp
@@ -47,28 +47,26 @@ LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
SPI_MOSI=dataPin;
SPI_CLK=clkPin;
SPI_CS=csPin;
- if (numDevices <= 0 || numDevices > MAX72XX_MAX_DEVICES)
- numDevices = MAX72XX_MAX_DEVICES;
+ if(numDevices<=0 || numDevices>8 )
+ numDevices=8;
maxDevices = numDevices;
pinMode(SPI_MOSI,OUTPUT);
pinMode(SPI_CLK,OUTPUT);
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
-
- memset(status, (byte)0, 8 * MAX72XX_MAX_DEVICES);
- memset(deviceDataBuff, (byte)0, MAX72XX_MAX_DEVICES);
-
- // display test
- spiTransfer_allDevices(OP_DISPLAYTEST, deviceDataBuff);
+ for(int i=0;i<64;i++)
+ status[i]=0x00;
+ for(int i=0;i=maxDevices)
return;
@@ -96,13 +89,6 @@ void LedControl::setScanLimit(int addr, int limit) {
spiTransfer(addr, OP_SCANLIMIT,limit);
}
-void LedControl::setScanLimit_allDevices(int limit) {
- if(limit <0 || limit>8) return;
-
- memset(deviceDataBuff, (byte)limit, maxDevices);
- spiTransfer_allDevices(OP_SCANLIMIT,deviceDataBuff);
-}
-
void LedControl::setIntensity(int addr, int intensity) {
if(addr<0 || addr>=maxDevices)
return;
@@ -110,15 +96,6 @@ void LedControl::setIntensity(int addr, int intensity) {
spiTransfer(addr, OP_INTENSITY,intensity);
}
-void LedControl::setIntensity_allDevices(int intensity)
-{
- if (intensity < 0 | intensity > 15)
- return;
-
- memset(deviceDataBuff, (byte)intensity, maxDevices);
- spiTransfer_allDevices(OP_INTENSITY, deviceDataBuff);
-}
-
void LedControl::clearDisplay(int addr) {
int offset;
@@ -131,16 +108,6 @@ void LedControl::clearDisplay(int addr) {
}
}
-void LedControl::clearDisplay_allDevices()
-{
- memset(status, (byte)0, 8 * maxDevices);
- memset(deviceDataBuff, (byte)0, maxDevices);
- for (int row = 0; row < 8; row++)
- {
- spiTransfer_allDevices(row + 1, deviceDataBuff);
- }
-}
-
void LedControl::setLed(int addr, int row, int column, boolean state) {
int offset;
byte val=0x00;
@@ -171,15 +138,6 @@ void LedControl::setRow(int addr, int row, byte value) {
spiTransfer(addr, row+1,status[offset+row]);
}
-void LedControl::setRow_allDevices(int row, byte *value)
-{
- if (row < 0 || row > 7)
- return;
- for (int addr = 0; addr < maxDevices; addr++)
- status[addr * 8 + row] = value[addr];
- spiTransfer_allDevices(row + 1, value);
-}
-
void LedControl::setColumn(int addr, int col, byte value) {
byte val;
@@ -237,7 +195,7 @@ void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data)
int maxbytes=maxDevices*2;
for(int i=0;i= 0; i--)
- shiftOut(SPI_MOSI, SPI_CLK, MSBFIRST, spidata[i]);
- //latch the data onto the display
- digitalWrite(SPI_CS, HIGH);
-}
+
diff --git a/lib/lib_display/LedControl/src/LedControl.h b/lib/lib_display/LedControl/src/LedControl.h
index 4fc7523df..f8180d07d 100644
--- a/lib/lib_display/LedControl/src/LedControl.h
+++ b/lib/lib_display/LedControl/src/LedControl.h
@@ -35,10 +35,6 @@
#include
#endif
-#ifndef MAX72XX_MAX_DEVICES
-#define MAX72XX_MAX_DEVICES 32 // maximum number of devices based on MXA7219/MAX7221
-#endif
-
/*
* Segments to be switched on for characters and digits on
* 7-Segment Displays
@@ -65,15 +61,12 @@ const static byte charTable [] PROGMEM = {
class LedControl {
private :
/* The array for shifting the data to the devices */
- byte spidata[2 * MAX72XX_MAX_DEVICES];
- /* Send out a single command to one device */
+ byte spidata[16];
+ /* Send out a single command to the device */
void spiTransfer(int addr, byte opcode, byte data);
- /* Send out a command with the same opcode to all devices */
- void spiTransfer_allDevices(byte opcode, const byte* data);
/* We keep track of the led-status for all 8 devices in this array */
- byte status[8 * MAX72XX_MAX_DEVICES];
- byte deviceDataBuff[MAX72XX_MAX_DEVICES];
+ byte status[64];
/* Data is shifted out of this pin*/
int SPI_MOSI;
/* The clock is signaled on this pin */
@@ -109,7 +102,6 @@ class LedControl {
* for normal operation.
*/
void shutdown(int addr, bool status);
- void shutdown_allDevices( bool status);
/*
* Set the number of digits (or rows) to be displayed.
@@ -120,7 +112,6 @@ class LedControl {
* limit number of digits to be displayed (1..8)
*/
void setScanLimit(int addr, int limit);
- void setScanLimit_allDevices(int limit);
/*
* Set the brightness of the display.
@@ -129,7 +120,6 @@ class LedControl {
* intensity the brightness of the display. (0..15)
*/
void setIntensity(int addr, int intensity);
- void setIntensity_allDevices(int intensity);
/*
* Switch all Leds on the display off.
@@ -137,7 +127,6 @@ class LedControl {
* addr address of the display to control
*/
void clearDisplay(int addr);
- void clearDisplay_allDevices();
/*
* Set the status of a single Led.
@@ -160,14 +149,6 @@ class LedControl {
*/
void setRow(int addr, int row, byte value);
- /**
- * @brief Set data for the same row of all devices
- *
- * @param row [0..8]
- * @param value array of bytes, one for each device
- */
- void setRow_allDevices(int row, byte* value);
-
/*
* Set all 8 Led's in a column to a new state
* Params:
diff --git a/lib/lib_display/LedControl/src/LedMatrix.cpp b/lib/lib_display/LedControl/src/LedMatrix.cpp
index 59882cd15..929a09418 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.cpp
+++ b/lib/lib_display/LedControl/src/LedMatrix.cpp
@@ -1,5 +1,5 @@
/*
- * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix modules, based on MAX7219/MAX7221
+ * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix maxDevices, based on MAX7219/MAX7221
* Copyright (c) 2021 Michael Beuss
*
* Permission is hereby granted, free of charge, to any person
@@ -29,7 +29,26 @@
#include "font_6x8_horizontal_MSB.h"
//#include "font_8x8_horizontal_latin_MSB.h"
-// public
+//the opcodes for the MAX7221 and MAX7219
+#define OP_NOOP 0
+#define OP_DIGIT0 1
+#define OP_DIGIT1 2
+#define OP_DIGIT2 3
+#define OP_DIGIT3 4
+#define OP_DIGIT4 5
+#define OP_DIGIT5 6
+#define OP_DIGIT6 7
+#define OP_DIGIT7 8
+#define OP_DECODEMODE 9
+#define OP_INTENSITY 10
+#define OP_SCANLIMIT 11
+#define OP_SHUTDOWN 12
+#define OP_DISPLAYTEST 15
+
+// test
+#include "LedControl.h"
+LedControl* ledControl = nullptr;
+// end text
LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows)
{
if (colums * rows > MAX72XX_MAX_DEVICES)
@@ -52,22 +71,36 @@ LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, un
modulesPerCol = rows;
displayWidth = colums * 8;
displayHeight = rows * 8;
- modules = colums * rows;
+ maxDevices = colums * rows;
moduleOrientation = ORIENTATION_UPSIDE_DOWN; // use setOrientation() to turn it
- ledControl = new LedControl(dataPin, clkPin, csPin, modules); // initializes all connected LED matrix modules
textBuf[0] = 0;
textWidth = 0;
textPosX = 0;
textPosY = 0;
appendTextBuf[0] = 0;
setScrollAppendText(" ");
- shutdown(false); // false: on, true: off
- clear();
- setIntensity(7);
+
+ // initialize all connected MAX7219/MAX7221 devices
+ SPI_MOSI = dataPin;
+ SPI_CLK = clkPin;
+ SPI_CS = csPin;
+ pinMode(SPI_MOSI, OUTPUT);
+ pinMode(SPI_CLK, OUTPUT);
+ pinMode(SPI_CS, OUTPUT);
+ SPI_MOSI = dataPin;
+
+ //spiTransfer_value(OP_DISPLAYTEST, 0); // display test
+ spiTransfer_value(OP_SCANLIMIT, 7); // scanlimit is set to max on startup
+ spiTransfer_value(OP_DECODEMODE, 0); // decode is done in source
+ clearDisplay();
+ //spiTransfer_value(OP_SHUTDOWN, 0); //we go into shutdown-mode (LEDs off) on startup
+ setIntensity(7); // initialize with the half of the maximum intensity [0..15]
+ power(true); // power on;
}
bool LedMatrix::drawText( const char *str, bool clearBefore)
{
+ if(clearBefore) clearDisplay();
strncpy(textBuf, str, TEXT_BUFFER_SIZE -1);
textPosX = 0;
textPosY = 0;
@@ -75,7 +108,6 @@ bool LedMatrix::drawText( const char *str, bool clearBefore)
if(textWidth < displayWidth)
{
// text fits into the display, place it into the center
- if(clearBefore) clear();
textPosX = (displayWidth - textWidth) / 2; // center
}
else
@@ -125,21 +157,29 @@ bool LedMatrix::scrollText()
void LedMatrix::power(bool on)
{
- shutdown(!on); // power(false) shuts down the display with shutdown(true)
+ byte value = 0; // 0: shutdown
+ if(on) value = 1; // 1: power on
+ spiTransfer_value(OP_SHUTDOWN, value); // power(false) shuts down the display
}
bool LedMatrix::clearDisplay(void)
{
- textBuf[0] = 0;
memset(textBuf, 0, TEXT_BUFFER_SIZE);
textWidth = 0;
- clear();
+ memset(buffer, 0, MATRIX_BUFFER_SIZE);
+ for (int row = 0; row < 8; row++)
+ {
+ spiTransfer_value(row + 1, 0);
+ }
return true;
}
-bool LedMatrix::setIntensity(byte dim)
+bool LedMatrix::setIntensity(byte intensity)
{
- ledControl->setIntensity_allDevices(dim); // 1..15
+ if (intensity < 0 || intensity > 15)
+ return false;
+
+ spiTransfer_value(OP_INTENSITY, intensity);
return true;
}
@@ -186,25 +226,8 @@ void LedMatrix::refresh()
int deviceRow = 0;
for(int ledRow = 7; ledRow >= 0; ledRow--) // refresh from buttom to top
{
- for( int addr = 0; addr < modules; addr++)
+ for( int addr = 0; addr < maxDevices; addr++)
{
- switch(moduleOrientation)
- {
- case ORIENTATION_NORMAL:
- col = addr % modulesPerRow;
- pixelRow = (addr / modulesPerRow) * 8 + ledRow;
- bufPos = pixelRow * modulesPerRow + col;
- deviceDataBuff[addr] = buffer[bufPos];
- deviceRow = ledRow;
- break;
- case ORIENTATION_UPSIDE_DOWN:
- col = addr % modulesPerRow;
- pixelRow = (addr / modulesPerRow) * 8 + deviceRow;
- bufPos = pixelRow * modulesPerRow + col;
- deviceDataBuff[addr] = revereBitorder(buffer[bufPos]); // mirror
- deviceRow = 7 - ledRow; // upside down
- break;
- }
if(moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN)
{
col = addr % modulesPerRow;
@@ -224,7 +247,7 @@ void LedMatrix::refresh()
}
}
}
- ledControl->setRow_allDevices(deviceRow, deviceDataBuff); // upside down
+ setRow_allDevices(deviceRow, deviceDataBuff);
}
}
@@ -254,58 +277,6 @@ bool LedMatrix::drawCharAt( char c, const int x, const int y)
return true;
}
-bool LedMatrix::shutdown(bool b)
-{
- for (int addr = 0; addr < modules; addr++)
- {
- ledControl->shutdown(addr, b); // b: false: on, true: off
- }
- return true;
-}
-
-bool LedMatrix::clear(void)
-{
- memset(buffer, 0, MATRIX_BUFFER_SIZE);
- ledControl->clearDisplay_allDevices();
- return true;
-}
-
-void LedMatrix::refreshByteOfBuffer(int i)
-{
- int line = i / modulesPerRow;
- int addr = (line / 8) * modulesPerRow + i % modulesPerRow;
- byte b = buffer[i];
- if (moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN)
- {
- int rowOfAddr = 0;
- if (moduleOrientation == ORIENTATION_NORMAL)
- {
- rowOfAddr = line % 8; // ORIENTATION_NORMAL
- }
- else
- {
- rowOfAddr = 7 - line % 8; // ORIENTATION_UPSIDE_DOWN
- b = revereBitorder(b);
- }
- ledControl->setRow(addr, rowOfAddr, b);
- }
- else
- {
- // ORIENTATION_TURN_RIGHT or ORIENTATION_TURN_LEFT
- int colOfAddr = 0;
- if (moduleOrientation == ORIENTATION_TURN_LEFT)
- {
- colOfAddr = line % 8; // ORIENTATION_TURN_LEFT
- }
- else
- {
- colOfAddr = 7 - line % 8; // ORIENTATION_TURN_RIGHT
- b = revereBitorder(b);
- }
- ledControl->setColumn(addr, colOfAddr, b);
- }
-}
-
byte LedMatrix::revereBitorder (byte b)
{
static const byte lookup[16] = {
@@ -320,3 +291,37 @@ void LedMatrix::appendSpace()
strncat(textBuf, appendTextBuf, TEXT_BUFFER_SIZE -1);
textWidth = strlen(textBuf) * charWidth;
}
+
+void LedMatrix::setRow_allDevices(int row, byte *data)
+{
+ if (row < 0 || row > 7)
+ return;
+ spiTransfer_array(row + 1, data);
+}
+
+void LedMatrix::spiTransfer_array(byte opcode, const byte* data) {
+ // create an array with the data to shift out
+ for (int addr = 0; addr < maxDevices; addr++)
+ {
+ spidata[addr * 2 + 1] = opcode;
+ spidata[addr * 2] = data[addr];
+ }
+ // enable the line
+ digitalWrite(SPI_CS, LOW);
+ // shift out the data
+ for (int i = maxDevices * 2 -1; i >= 0; i--)
+ {
+ shiftOut(SPI_MOSI, SPI_CLK, MSBFIRST, spidata[i]);
+ }
+ // latch the data onto the display
+ digitalWrite(SPI_CS, HIGH);
+}
+
+void LedMatrix::spiTransfer_value(byte opcode, byte value)
+{
+ memset(deviceDataBuff, (byte)value, maxDevices);
+ spiTransfer_array(opcode, deviceDataBuff);
+}
+
+
+
diff --git a/lib/lib_display/LedControl/src/LedMatrix.h b/lib/lib_display/LedControl/src/LedMatrix.h
index 9fee69a5f..aec15d052 100644
--- a/lib/lib_display/LedControl/src/LedMatrix.h
+++ b/lib/lib_display/LedControl/src/LedMatrix.h
@@ -1,5 +1,5 @@
/*
- * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix modules, based on MAX7219/MAX7221
+ * LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix devices, based on MAX7219/MAX7221
* Copyright (c) 2021 Michael Beuss
*
* Permission is hereby granted, free of charge, to any person
@@ -27,16 +27,27 @@
#ifndef LedMatrix_h
#define LedMatrix_h
-#include
+#include
+
+#if (ARDUINO >= 100)
+#include
+#else
+#include
+#endif
+
+#ifndef MAX72XX_MAX_DEVICES
+#define MAX72XX_MAX_DEVICES 32 // maximum number of devices based on MXA7219/MAX7221
+#endif
#define MATRIX_BUFFER_SIZE MAX72XX_MAX_DEVICES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
#define TEXT_BUFFER_SIZE 256 // maximum text length that can be scrolled
#define TEXT_APPEND_BUFFER_SIZE 16 // used for characters that are appended to the scroll text, before it repeats
+#define SPI_BUFFER_SIZE MAX72XX_MAX_DEVICES * 2 // buffer size fort shifting commands to all devices (2 bytes each)
/**
- * @brief LedMatric controls multiple 8x8 LED dot matrx modules.
- * All modules in rows and clolums together build a common display pixel matrix.
+ * @brief LedMatrix controls multiple 8x8 LED dot matrx devices.
+ * All devices in rows and clolums together build a common display pixel matrix.
*
*/
class LedMatrix
@@ -54,8 +65,8 @@ class LedMatrix
/**
* @brief Construct a new LED Matrix object
*
- * @param colums of 8x8 LED dot matrix modules
- * @param rows of 8x8 LED dot matrix modules
+ * @param colums of 8x8 LED dot matrix devices
+ * @param rows of 8x8 LED dot matrix devices
*/
LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows);
@@ -139,23 +150,48 @@ class LedMatrix
void refresh();
private:
+
bool drawCharAt( char c, int x, int y ); // Draws a character to a defined position
- bool shutdown(bool b); // shutdown(true) switches the display off. Text and pixels can be set while it is off. shutdown(false) switches the display on.
- bool clear(void); // clears the display content
- void refreshByteOfBuffer( int i); // sends one byte of the buffer to the display. This updates an 8 pixel row of one matrix module.
byte revereBitorder(byte b); // returnes the byte in the reverse bit order.
void appendSpace(); // appends characters to the end of the text to get a distance to the repeating scroll text
+ // device contrl MAX7219/MAX7221
+ /**
+ * @brief Set data for the same row of all devices
+ *
+ * @param row [0..8]
+ * @param value array of bytes, one for each device
+ */
+ void setRow_allDevices(int row, byte* value);
+
+ /* Send out a command with the same opcode to all devices */
+ /**
+ * @brief sends opcode with specific data values to each device
+ *
+ * @param opcode
+ * @param data array of byte values (data[0] is the value for the first device)
+ */
+ void spiTransfer_array(byte opcode, const byte* data);
+
+ /**
+ * @brief sends opcode with same value to all devices
+ */
+ void spiTransfer_value(byte opcode, byte value);
+
+
private:
+ int SPI_MOSI; // Data is shifted out of this pin
+ int SPI_CLK; // The clock is signaled on this pin
+ int SPI_CS; // This one is driven LOW for chip selectzion
+
unsigned int modulesPerRow;
unsigned int modulesPerCol;
unsigned int displayWidth; // matrix width [pixel]
unsigned int displayHeight; // matrix height [pixel]
- unsigned int modules; // number of 8x8 mudules
+ int maxDevices; // number of used 8x8 devices
uint8_t moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
byte deviceDataBuff[MAX72XX_MAX_DEVICES];
- LedControl* ledControl;
int charWidth;
int charHeight;
char textBuf[TEXT_BUFFER_SIZE];
@@ -163,6 +199,7 @@ class LedMatrix
int textWidth; // width of text [pixel]
int textPosX; // horizontal pixel position of scrolling text
int textPosY; // vertical pixelposition of scrolling text;
+ byte spidata[SPI_BUFFER_SIZE]; // The array for shifting the data to the devices
};
diff --git a/tasmota/xdsp_19_max7219_matrix.ino b/tasmota/xdsp_19_max7219_matrix.ino
index 82a4a24bb..ecf500670 100644
--- a/tasmota/xdsp_19_max7219_matrix.ino
+++ b/tasmota/xdsp_19_max7219_matrix.ino
@@ -128,13 +128,6 @@ bool MAX7291Matrix_initDriver(void)
Settings->display_rows = LedMatrix_settings.modulesPerCol;
Settings->display_cols[1] = LedMatrix_settings.modulesPerCol;
max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol);
- if( LedMatrix_settings.show_clock == 0)
- {
- Settings->display_mode = 0; // text mode
- }
- else{
- Settings->display_mode = 1; // clock mode
- }
max2791Matrix_initDriver_done = true;
AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_initDriver DIN:%d CLK:%d CS:%d size(%dx%d)"), Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol);
@@ -144,8 +137,13 @@ bool MAX7291Matrix_initDriver(void)
// FUNC_DISPLAY_INIT
bool MAX7291Matrix_init(void)
{
+ Settings->display_mode = 0; // text mode
+ LedMatrix_settings.show_clock = 0; // no clock
+
int intensity = GetDisplayDimmer16(); // 0..15
max7219_Matrix->setIntensity(intensity);
+
+ max7219_Matrix->power(true); // power on
if(Settings->display_rotate <= 3)
{
max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)Settings->display_rotate );
@@ -223,6 +221,8 @@ bool MAX7291Matrix_clock(void)
Settings->display_mode = 1;
break;
default:
+ //LedMatrix_settings.timeFormat = XdrvMailbox.payload;
+ //Settings->display_mode = 1;
return false;
}
@@ -280,13 +280,11 @@ bool Xdsp19(uint8_t function)
case FUNC_DISPLAY_DRAW_STRING:
case FUNC_DISPLAY_SCROLLTEXT:
case FUNC_DISPLAY_SEVENSEG_TEXT:
- Settings->display_mode = 0; // text mode
- LedMatrix_settings.show_clock = 0; // disable clock mode
+ if(Settings->display_mode != 0) MAX7291Matrix_init();
result = max7219_Matrix->drawText(XdrvMailbox.data, true); // true: clears display before drawing text
break;
case FUNC_DISPLAY_SEVENSEG_TEXTNC:
- Settings->display_mode = 0; // text mode
- LedMatrix_settings.show_clock = 0; // disable clock mode
+ if(Settings->display_mode != 0) MAX7291Matrix_init();
result = max7219_Matrix->drawText(XdrvMailbox.data, false); // false: does not clear display before drawing text
break;
case FUNC_DISPLAY_SCROLLDELAY:
From 732c7a4116198c3229f2b44f3c8ee14169e5d375 Mon Sep 17 00:00:00 2001
From: gemu2015
Date: Wed, 8 Dec 2021 16:28:29 +0100
Subject: [PATCH 014/510] new functions and housekeeping
---
tasmota/xdrv_10_scripter.ino | 696 ++++++++++++++++++++++++-----------
1 file changed, 471 insertions(+), 225 deletions(-)
diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino
index d5a2c5bdb..f744d850b 100755
--- a/tasmota/xdrv_10_scripter.ino
+++ b/tasmota/xdrv_10_scripter.ino
@@ -116,6 +116,9 @@ uint32_t DecodeLightId(uint32_t hue_id);
#define UNISHOXRSIZE 2560
#endif
+#ifndef MAX_EXT_ARRAYS
+#define MAX_EXT_ARRAYS 5
+#endif
#ifndef STASK_PRIO
#define STASK_PRIO 1
@@ -1163,6 +1166,22 @@ float *Get_MFAddr(uint8_t index, uint16_t *len, uint16_t *ipos) {
char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, struct GVARS *gv);
+char *get_array_by_name(char *lp, float **fp, uint16_t *alen) {
+ struct T_INDEX ind;
+ uint8_t vtype;
+ lp = isvar(lp, &vtype, &ind, 0, 0, 0);
+ if (vtype==VAR_NV) return 0;
+ if (vtype&STYPE) return 0;
+ uint16_t index = glob_script_mem.type[ind.index].index;
+
+ if (glob_script_mem.type[ind.index].bits.is_filter) {
+ float *fa = Get_MFAddr(index, alen, 0);
+ *fp = fa;
+ return lp;
+ }
+ *fp = 0;
+ return lp;
+}
float *get_array_by_name(char *name, uint16_t *alen) {
struct T_INDEX ind;
@@ -1281,6 +1300,133 @@ float DoMedian5(uint8_t index, float in) {
return median_array(mf->buffer, MEDIAN_SIZE);
}
+
+#ifdef USE_FEXTRACT
+// convert tasmota time stamp to ul seconds
+uint32_t tstamp2l(char *ts) {
+uint16_t year;
+uint8_t month;
+uint8_t day;
+uint8_t hour;
+uint8_t mins;
+uint8_t secs;
+
+ if (strchr(ts, 'T')) {
+ // 2020-12-16T15:36:41
+ year = strtol(ts, &ts, 10);
+ if (year < 2020 || year > 2040) {
+ year = 2020;
+ }
+ year -= 2000;
+ ts++;
+ month = strtol(ts, &ts, 10);
+ ts++;
+ day = strtol(ts, &ts, 10);
+ ts++;
+ hour = strtol(ts, &ts, 10);
+ ts++;
+ mins = strtol(ts, &ts, 10);
+ ts++;
+ secs = strtol(ts, &ts, 10);
+ } else {
+ // german excel fromat 16.12.20 15:36
+ day = strtol(ts, &ts, 10);
+ ts++;
+ month = strtol(ts, &ts, 10);
+ ts++;
+ year = strtol(ts, &ts, 10);
+ ts++;
+ hour = strtol(ts, &ts, 10);
+ ts++;
+ mins = strtol(ts, &ts, 10);
+ secs = 0;
+ }
+ return (year*365*86400)+(month*31*86400)+(day*86400)+(hour*3600)+(mins*60)+secs;
+}
+
+// assume 1. entry is timestamp, others are tab delimited values until LF
+// file refernece, from timestamp, to timestampm, column offset, array pointers, array lenght, number of arrays
+int32_t extract_from_file(uint8_t fref, char *ts_from, char *ts_to, uint8_t coffs, float **a_ptr, uint16_t *a_len, uint8_t numa, int16_t accum) {
+ if (!glob_script_mem.file_flags[fref].is_open) return -1;
+ char rstr[32];
+ uint8_t sindex = 0;
+ uint8_t colpos = 0;
+ uint8_t range = 0;
+ uint32_t tsfrom = tstamp2l(ts_from);
+ uint32_t tsto = tstamp2l(ts_to);
+ uint16_t lines = 0;
+ uint16_t rlines = 0;
+ float summs[numa];
+ uint16_t accnt[numa];
+ for (uint8_t cnt = 0; cnt < numa; cnt++) {
+ summs[cnt] = 0;
+ accnt[cnt] = 0;
+ }
+ uint8_t dflg = 1;
+ if (accum < 0) {
+ dflg = 0;
+ accum = -accum;
+ }
+ if (accum == 0) accum = 1;
+ while (glob_script_mem.files[fref].available()) {
+ // scan through file
+ uint8_t buff[2], iob;
+ glob_script_mem.files[fref].read(buff, 1);
+ iob = buff[0];
+ if (iob == '\t' || iob == ',' || iob == '\n') {
+ rstr[sindex] = 0;
+ sindex = 0;
+ if (colpos == 0) {
+ // timestamp 2020-12-16T15:36:41
+ // decompose timestamps
+ uint32_t cts = tstamp2l(rstr);
+ if (cts > tsto) break;
+ if (cts >= tsfrom && cts <= tsto) {
+ // we want this range
+ range = 1;
+ rlines++;
+ } else {
+ range = 0;
+ }
+ } else {
+ // data columns
+ if (range) {
+ uint8_t curpos = colpos - coffs;
+ if (colpos >= coffs && curpos < numa) {
+ if (a_len[curpos]) {
+ float fval = CharToFloat(rstr);
+ //AddLog(LOG_LEVEL_INFO, PSTR("cpos %d colp %d numa %d - %s %d"),curpos, colpos, a_len[curpos], rstr, (uint32_t)fval);
+ summs[curpos] += fval;
+ accnt[curpos] += 1;
+ if (accnt[curpos] == accum) {
+ if (dflg) {
+ *a_ptr[curpos]++ = summs[curpos] / accum;
+ } else {
+ *a_ptr[curpos]++ = summs[curpos];
+ }
+ summs[curpos] = 0;
+ accnt[curpos] = 0;
+ a_len[curpos]--;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ colpos++;
+ if (iob == '\n') {
+ colpos = 0;
+ lines ++;
+ }
+ }
+ rstr[sindex] = iob;
+ sindex++;
+ }
+ return rlines;
+}
+#endif // USE_FEXTRACT
+
#ifdef USE_LIGHT
uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value) {
float r = 0, g = 0, b = 0;
@@ -1782,26 +1928,20 @@ chknext:
if (!strncmp(vname, "acos(", 5)) {
lp=GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
fvar = acosf(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif
if (!strncmp(vname, "abs(", 4)) {
lp=GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
fvar = fabs(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "asc(", 4)) {
char str[SCRIPT_MAXSSIZE];
lp = GetStringArgument(lp + 4, OPER_EQU, str, gv);
fvar = str[0];
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "adc(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
@@ -1831,6 +1971,26 @@ chknext:
len = 0;
goto exit;
}
+ if (!strncmp(vname, "acp(", 4)) {
+ lp += 4;
+ SCRIPT_SKIP_SPACES
+ uint16_t alend;
+ fvar = -1;
+ float *fpd;
+ lp = get_array_by_name(lp, &fpd, &alend);
+ SCRIPT_SKIP_SPACES
+ uint16_t alens;
+ float *fps;
+ lp = get_array_by_name(lp, &fps, &alens);
+ SCRIPT_SKIP_SPACES
+ if (alend != alens) {
+ fvar = -1;
+ } else {
+ memcpy(fpd, fps, alend * sizeof(float));
+ fvar = 0;
+ }
+ goto nfuncexit;
+ }
break;
case 'b':
@@ -1887,9 +2047,7 @@ chknext:
float fvar1;
lp = GetNumericArgument(lp, OPER_EQU, &fvar1, gv);
fvar = Core2SetAxpPin(fvar, fvar1);
- lp++;
- len=0;
- goto exit;
+ goto nfuncexit;
}
#endif // USE_M5STACK_CORE2
@@ -1906,10 +2064,8 @@ chknext:
if (*lp!=')') {
lp = GetNumericArgument(lp, OPER_EQU, &prio, gv);
}
- lp++;
fvar = scripter_create_task(fvar, fvar1, fvar2, prio);
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //USE_SCRIPT_TASK
#endif //ESP32
@@ -1917,9 +2073,7 @@ chknext:
if (!strncmp(vname, "cos(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
fvar = cosf(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif
break;
@@ -1997,9 +2151,7 @@ chknext:
fvar = 99999;
break;
}
- len = 0;
- lp++;
- goto exit;
+ goto nfuncexit;
}
#endif //USE_ENERGY_SENSOR
break;
@@ -2065,9 +2217,7 @@ chknext:
break;
}
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "fc(", 3)) {
lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, gv);
@@ -2081,9 +2231,7 @@ chknext:
glob_script_mem.file_flags[ind].is_open = 0;
}
fvar = 0;
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "ff(", 3)) {
lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, gv);
@@ -2091,9 +2239,7 @@ chknext:
if (ind>=SFS_MAX) ind = SFS_MAX - 1;
glob_script_mem.files[ind].flush();
fvar = 0;
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "fw(", 3)) {
char str[SCRIPT_MAXSSIZE];
@@ -2107,10 +2253,24 @@ chknext:
} else {
fvar = 0;
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
+ if (!strncmp(vname, "fwb(", 4)) {
+ lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
+ uint8_t buf[2];
+ buf[0] = fvar;
+ SCRIPT_SKIP_SPACES
+ lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv);
+ uint8_t ind = fvar;
+ if (ind>=SFS_MAX) ind = SFS_MAX - 1;
+ if (glob_script_mem.file_flags[ind].is_open) {
+ fvar = glob_script_mem.files[ind].write(buf, 1);
+ } else {
+ fvar = 0;
+ }
+ goto nfuncexit;
+ }
+
if (!strncmp(vname, "fr(", 3)) {
struct T_INDEX ind;
uint8_t vtype;
@@ -2184,14 +2344,75 @@ chknext:
len = 0;
goto exit;
}
+ if (!strncmp(vname, "frb(", 4)) {
+ lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv);
+ uint8_t ind = fvar;
+ if (ind>=SFS_MAX) ind = SFS_MAX - 1;
+ if (glob_script_mem.file_flags[ind].is_open) {
+ uint8_t buf[2];
+ buf[0] = 0;
+ glob_script_mem.files[ind].read(buf, 1);
+ fvar = buf[0];
+ } else {
+ fvar = 0;
+ }
+ goto nfuncexit;
+ }
+ if (!strncmp(vname, "fa(", 3)) {
+ lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, gv);
+ uint8_t ind = fvar;
+ if (ind>=SFS_MAX) ind = SFS_MAX - 1;
+ if (glob_script_mem.file_flags[ind].is_open) {
+ fvar = glob_script_mem.files[ind].available();
+ } else {
+ fvar = -1;
+ }
+ goto nfuncexit;
+ }
+ if (!strncmp(vname, "fs(", 3)) {
+ lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, gv);
+ uint8_t ind = fvar;
+ SCRIPT_SKIP_SPACES
+ lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv);
+ SCRIPT_SKIP_SPACES
+ if (ind>=SFS_MAX) ind = SFS_MAX - 1;
+ if (glob_script_mem.file_flags[ind].is_open) {
+ fvar = glob_script_mem.files[ind].seek(fvar, fs::SeekMode::SeekCur);
+ } else {
+ fvar = -1;
+ }
+ goto nfuncexit;
+ }
+ if (!strncmp(vname, "fz(", 3)) {
+ lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, gv);
+ SCRIPT_SKIP_SPACES
+ uint8_t ind = fvar;
+ if (ind>=SFS_MAX) ind = SFS_MAX - 1;
+ if (glob_script_mem.file_flags[ind].is_open) {
+ fvar = glob_script_mem.files[ind].size();
+ } else {
+ fvar = -1;
+ }
+ goto nfuncexit;
+ }
if (!strncmp(vname, "fd(", 3)) {
char str[glob_script_mem.max_ssize + 1];
lp = GetStringArgument(lp + 3, OPER_EQU, str, 0);
ufsp->remove(str);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
+#ifdef USE_UFILESYS
+ if (!strncmp(vname, "frw(", 4)) {
+ // read file from web
+ lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
+ SCRIPT_SKIP_SPACES
+ char url[SCRIPT_MAXSSIZE];
+ lp = ForceStringVar(lp, url);
+ SCRIPT_SKIP_SPACES
+ fvar = url2file(fvar, url);
+ goto nfuncexit;
+ }
+#endif
#if defined(ESP32) && defined(USE_WEBCAM)
if (!strncmp(vname, "fwp(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
@@ -2215,9 +2436,7 @@ chknext:
} else {
fvar = 0;
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //ESP32 && USE_WEBCAM
#ifdef USE_SCRIPT_FATFS_EXT
@@ -2240,17 +2459,13 @@ chknext:
}
ef.close();
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "fmd(", 4)) {
char str[glob_script_mem.max_ssize + 1];
lp = GetStringArgument(lp + 4, OPER_EQU, str, 0);
fvar = ufsp->mkdir(str);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "fmt(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
@@ -2259,64 +2474,99 @@ chknext:
} else {
//SD.format();
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "frd(", 4)) {
char str[glob_script_mem.max_ssize + 1];
lp = GetStringArgument(lp + 4, OPER_EQU, str, 0);
fvar = ufsp->rmdir(str);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "fx(", 3)) {
char str[glob_script_mem.max_ssize + 1];
lp = GetStringArgument(lp + 3, OPER_EQU, str, 0);
if (ufsp->exists(str)) fvar = 1;
else fvar = 0;
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "fsi(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
fvar = UfsInfo(fvar, 0);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
- if (!strncmp(vname, "fwa(", 4)) {
- struct T_INDEX ind;
- uint8_t vtype;
- lp = isvar(lp + 4, &vtype, &ind, 0, 0, gv);
- if (vtype!=VAR_NV && (vtype&STYPE)==0 && glob_script_mem.type[ind.index].bits.is_filter) {
- // found array as result
+#ifdef USE_FEXTRACT
+ if (!strncmp(vname, "fxt(", 4)) {
+ // extract from file
+ lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
+ SCRIPT_SKIP_SPACES
+ uint8_t fref = fvar;
- } else {
- // error
+ //2020-12-16T14:30:00
+ char ts_from[24];
+ lp = GetStringArgument(lp, OPER_EQU, ts_from, 0);
+ SCRIPT_SKIP_SPACES
+
+ char ts_to[24];
+ lp = GetStringArgument(lp, OPER_EQU, ts_to, 0);
+ SCRIPT_SKIP_SPACES
+
+ lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv);
+ SCRIPT_SKIP_SPACES
+ uint8_t coffs = fvar;
+
+ lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv);
+ SCRIPT_SKIP_SPACES
+ int16_t accum = fvar;
+
+ uint16_t a_len[MAX_EXT_ARRAYS];
+ float *a_ptr[MAX_EXT_ARRAYS];
+
+ uint8_t index = 0;
+ while (index < MAX_EXT_ARRAYS) {
+ lp = get_array_by_name(lp, &a_ptr[index], &a_len[index]);
+ SCRIPT_SKIP_SPACES
+ index++;
+ if (*lp == ')' || *lp == '\n') {
+ break;
+ }
+ }
+ fvar = extract_from_file(fref, ts_from, ts_to, coffs, a_ptr, a_len, index, accum);
+ goto nfuncexit;
+ }
+#endif // USE_FEXTRACT
+ if (!strncmp(vname, "fwa(", 4)) {
+ uint16_t alen;
+ float *fa;
+ lp = get_array_by_name(lp + 4, &fa, &alen);
+ if (!fa) {
fvar = 0;
goto exit;
}
-
- while (*lp==' ') lp++;
+ SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv);
+ SCRIPT_SKIP_SPACES
+ uint8_t append = 0;
+ if (*lp == 'a') {
+ lp++;
+ append = 1;
+ }
uint8_t index = fvar;
- if (index>=SFS_MAX) index = SFS_MAX - 1;
+ if (index >= SFS_MAX) index = SFS_MAX - 1;
if (glob_script_mem.file_flags[index].is_open) {
- uint16_t len = 0;
- float *fa = Get_MFAddr(glob_script_mem.type[ind.index].index, &len, 0);
char dstr[24];
- for (uint32_t cnt = 0; cnt=SFS_MAX) find = SFS_MAX - 1;
+ SCRIPT_SKIP_SPACES
+
+ if (find >= SFS_MAX) find = SFS_MAX - 1;
char str[glob_script_mem.max_ssize + 1];
if (glob_script_mem.file_flags[find].is_open) {
- uint16_t len = 0;
- float *fa = Get_MFAddr(glob_script_mem.type[ind.index].index, &len, 0);
- char dstr[24];
- for (uint32_t cnt = 0; cnt=glob_script_mem.max_ssize - 1) break;
+ first = 1;
+ slen++;
+ if (slen >= glob_script_mem.max_ssize - 1) break;
}
}
*cp = 0;
@@ -2370,9 +2618,7 @@ chknext:
} else {
fvar = 0;
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif // USE_SCRIPT_FATFS_EXT
@@ -2382,10 +2628,8 @@ chknext:
lp = GetStringArgument(lp + 4, OPER_EQU, str, 0);
if (lknum<1 || lknum>2) lknum = 1;
strlcpy(glob_script_mem.flink[lknum - 1], str, 14);
- lp++;
fvar = 0;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "fsm", 3)) {
fvar=(uint32_t)ufsp;
@@ -2501,9 +2745,7 @@ chknext:
char path[SCRIPT_MAXSSIZE];
lp = GetStringArgument(lp, OPER_EQU, path, 0);
fvar = call2https(host, path);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //SCRIPT_GET_HTTPS_JP
break;
@@ -2539,9 +2781,36 @@ chknext:
char str[SCRIPT_MAXSSIZE];
lp = GetStringArgument(lp + 3, OPER_EQU, str, 0);
fvar = strtol(str, NULL, 16);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
+ }
+ if (!strncmp(vname, "hf(", 3)) {
+ char str[SCRIPT_MAXSSIZE];
+ lp = GetStringArgument(lp + 3, OPER_EQU, str, 0);
+ SCRIPT_SKIP_SPACES
+ if (strlen(str) != 8) {
+ fvar = -1;
+ } else {
+ uint8_t *ucp = (uint8_t*)&fvar;
+ uint8_t rflg = 0;
+ if (*lp=='r') {
+ rflg = 1;
+ ucp += sizeof(float);
+ lp++;
+ }
+ char substr[3];
+ char *cp = str;
+ for (uint32_t cnt = 0; cnt < 4; cnt++) {
+ substr[0] = *cp++;
+ substr[1] = *cp++;
+ substr[2] = 0;
+ if (!rflg) {
+ *ucp++ = strtol(substr, NULL, 16);
+ } else {
+ *--ucp = strtol(substr, NULL, 16);
+ }
+ }
+ }
+ goto nfuncexit;
}
if (!strncmp(vname, "http(", 5)) {
char host[SCRIPT_MAXSSIZE];
@@ -2551,9 +2820,7 @@ chknext:
lp = GetStringArgument(lp, OPER_EQU, request, 0);
SCRIPT_SKIP_SPACES
fvar = http_req(host, request);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#ifdef USE_LIGHT
if (!strncmp(vname, "hsvrgb(", 7)) {
@@ -2571,9 +2838,7 @@ chknext:
if (fvar3<0 || fvar3>100) fvar3 = 0;
fvar = HSVToRGB(fvar, fvar2, fvar3);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //USE_LIGHT
@@ -2588,9 +2853,7 @@ chknext:
glob_script_mem.homekit_running == false;
}
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif
break;
@@ -2608,16 +2871,12 @@ chknext:
} else {
fvar = -1;
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "int(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
fvar = floor(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "is(", 3)) {
lp = isargs(lp + 3, 0);
@@ -2662,9 +2921,7 @@ chknext:
}
lp = GetNumericArgument(lp + 1, OPER_EQU, &fvar, gv);
fvar = script_i2c(0, fvar, bus);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "iw", 2)) {
uint8_t bytes = 1;
@@ -2681,9 +2938,7 @@ chknext:
float fvar2;
lp = GetNumericArgument(lp, OPER_EQU, &fvar2, gv);
fvar = script_i2c(9 + bytes, fvar, fvar2);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "ir", 2)) {
uint8_t bytes = 1;
@@ -2696,9 +2951,7 @@ chknext:
}
lp = GetNumericArgument(lp + 1, OPER_EQU, &fvar, gv);
fvar = script_i2c(2, fvar, bytes);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif // USE_SCRIPT_I2C
break;
@@ -2728,9 +2981,7 @@ chknext:
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
SCRIPT_SKIP_SPACES
fvar = lvgl_test(&lp, fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif // USE_LVGL
break;
@@ -2743,17 +2994,13 @@ chknext:
float fvar2;
lp = GetNumericArgument(lp, OPER_EQU, &fvar2, gv);
fvar = DoMedian5(fvar1, fvar2);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#ifdef USE_ANGLE_FUNC
if (!strncmp(vname, "mpt(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
fvar = MeasurePulseTime(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //USE_ANGLE_FUNC
if (!strncmp(vname, "micros", 6)) {
@@ -2911,10 +3158,8 @@ chknext:
// arg2
float fvar2;
lp = GetNumericArgument(lp, OPER_EQU, &fvar2, gv);
- lp++;
fvar = FastPrecisePowf(fvar1, fvar2);
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "pwr[", 4)) {
GetNumericArgument(vname + 4, OPER_EQU, &fvar, gv);
@@ -2998,10 +3243,8 @@ chknext:
if (!strncmp(vname, "sl(", 3)) {
char str[SCRIPT_MAXSSIZE];
lp = GetStringArgument(lp + 3, OPER_EQU, str, 0);
- lp++;
- len = 0;
fvar = strlen(str);
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "sb(", 3)) {
char str[SCRIPT_MAXSSIZE];
@@ -3081,9 +3324,7 @@ chknext:
if (fvar>240) fvar = 240;
setCpuFrequencyMhz(fvar);
fvar = getCpuFrequencyMhz();
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //ESP32
#ifdef USE_TTGO_WATCH
@@ -3091,9 +3332,7 @@ chknext:
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
SCRIPT_SKIP_SPACES
TTGO_Sleep(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //USE_TTGO_WATCH
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
@@ -3124,16 +3363,12 @@ chknext:
if (!strncmp(vname, "sin(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
fvar = sinf(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "sqrt(", 5)) {
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
fvar = sqrtf(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //USE_ANGLE_FUNC
@@ -3142,9 +3377,7 @@ chknext:
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
SCRIPT_SKIP_SPACES
fvar = SML_GetVal(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "sml(", 4)) {
float fvar1;
@@ -3177,9 +3410,7 @@ chknext:
fvar = 0;
#endif //ED300L
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "smlj", 4)) {
fvar = sml_json_enable;
@@ -3190,16 +3421,12 @@ chknext:
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
if (fvar < 1) fvar = 1;
SML_Decode(fvar - 1);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "smlv[", 5)) {
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
fvar = sml_getv(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //USE_SML_M
@@ -3261,9 +3488,7 @@ chknext:
fvar = -2;
}
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "sw(", 3)) {
char str[SCRIPT_MAXSSIZE];
@@ -3273,9 +3498,7 @@ chknext:
glob_script_mem.sp->write(str, strlen(str));
fvar = 0;
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "swb(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0);
@@ -3284,18 +3507,14 @@ chknext:
glob_script_mem.sp->write((uint8_t)fvar);
fvar = 0;
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "sa(", 3)) {
fvar = -1;
if (glob_script_mem.sp) {
fvar = glob_script_mem.sp->available();
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "srb(", 3)) {
fvar = -1;
@@ -3305,9 +3524,7 @@ chknext:
fvar = glob_script_mem.sp->read();
}
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "sp(", 3)) {
fvar = -1;
@@ -3317,9 +3534,7 @@ chknext:
fvar = glob_script_mem.sp->peek();
}
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "sr(", 3)) {
uint16_t size = glob_script_mem.max_ssize;
@@ -3396,33 +3611,25 @@ chknext:
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
if (fvar<10) fvar = 10;
Script_ticker1.attach_ms(fvar, Script_ticker1_end);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "ts2(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
if (fvar<10) fvar = 10;
Script_ticker2.attach_ms(fvar, Script_ticker2_end);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "ts3(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
if (fvar<10) fvar = 10;
Script_ticker3.attach_ms(fvar, Script_ticker3_end);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
if (!strncmp(vname, "ts4(", 4)) {
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
if (fvar<10) fvar = 10;
Script_ticker4.attach_ms(fvar, Script_ticker4_end);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif // USE_SCRIPT_TIMER
@@ -3462,10 +3669,8 @@ chknext:
}
accu += ESP.getCycleCount()-cycles;
}
- lp++;
- len = 0;
fvar = accu / 1000;
- goto exit;
+ goto nfuncexit;
}
#endif
@@ -3478,9 +3683,7 @@ chknext:
lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv);
SCRIPT_SKIP_SPACES
fvar = get_tpars(index - 1, fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif
break;
@@ -3570,9 +3773,7 @@ chknext:
default:
fvar = 0;
}
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif //ESP32, USE_WEBCAM
#if defined(USE_TTGO_WATCH) && defined(USE_BMA423)
@@ -3589,9 +3790,7 @@ chknext:
if (!strncmp(vname, "wtch(", 5)) {
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
fvar = Touch_Status(fvar);
- lp++;
- len = 0;
- goto exit;
+ goto nfuncexit;
}
#endif // USE_FT5206
if (!strncmp(vname, "wm", 2)) {
@@ -3638,6 +3837,9 @@ notfound:
glob_script_mem.var_not_found = 1;
return lp;
// return constant numbers
+nfuncexit:
+ lp++;
+ len = 0;
exit:
if (fp) *fp = fvar;
*vtype = NUM_RES;
@@ -6770,6 +6972,7 @@ char buff[512];
if (renderer && renderer->framebuffer) {
uint8_t *bp = renderer->framebuffer;
uint8_t *lbuf = (uint8_t*)special_malloc(Settings->display_width * 3 + 2);
+ memset(lbuf, 0, Settings->display_width * 3);
if (!lbuf) return;
uint8_t dmflg = 0;
if (renderer->disp_bpp & 0x40) dmflg = 1;
@@ -6808,11 +7011,12 @@ char buff[512];
} else {
pixel = *bp & 0xf;
}
+ pixel *= 15;
+ *--lbp = pixel;
+ *--lbp = pixel;
+ *--lbp = pixel;
}
- pixel *= 15;
- *--lbp = pixel;
- *--lbp = pixel;
- *--lbp = pixel;
+
} else {
for (uint32_t cnt = 0; cnt <= 1; cnt++) {
if (!(cnt & 1)) {
@@ -7941,18 +8145,20 @@ void script_task2(void *arg) {
}
}
}
-uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) {
+uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, int32_t prio) {
//return 0;
BaseType_t res = 0;
if (core > 1) { core = 1; }
- if (num == 1) {
- if (esp32_tasks[0].task_t) { vTaskDelete(esp32_tasks[0].task_t); }
- res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &esp32_tasks[0].task_t, core);
- esp32_tasks[0].task_timer = time;
- } else {
- if (esp32_tasks[1].task_t) { vTaskDelete(esp32_tasks[1].task_t); }
- res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &esp32_tasks[1].task_t, core);
- esp32_tasks[1].task_timer = time;
+ if (num < 1) { num = 1; }
+ if (num > 2) { num = 2; }
+ num--;
+ if (esp32_tasks[num].task_t) {
+ vTaskDelete(esp32_tasks[num].task_t);
+ esp32_tasks[num].task_t = 0;
+ }
+ if (prio >= 0) {
+ res = xTaskCreatePinnedToCore(script_task1, num==0?"T1":"T2", STASK_STACK, NULL, prio, &esp32_tasks[num].task_t, core);
+ esp32_tasks[num].task_timer = time;
}
return res;
}
@@ -7977,7 +8183,7 @@ void script_task2(void *arg) {
}
}
-uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) {
+uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, int32_t prio) {
//return 0;
BaseType_t res = 0;
if (core > 1) { core = 1; }
@@ -7997,6 +8203,42 @@ uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32
#endif // USE_SCRIPT_TASK
#endif // ESP32
+
+#ifdef USE_UFILESYS
+// read http content to file
+int32_t url2file(uint8_t fref, char *url) {
+ WiFiClient http_client;
+ HTTPClient http;
+ int32_t httpCode = 0;
+ char hbuff[128];
+ strcpy(hbuff, "http://");
+ strcat(hbuff, url);
+ http.begin(http_client, UrlEncode(hbuff));
+ httpCode = http.GET();
+ if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
+ WiFiClient *stream = http.getStreamPtr();
+ int32_t len = http.getSize();
+ if (len < 0) len = 99999999;
+ uint8_t buff[512];
+ while (http.connected() && (len > 0)) {
+ size_t size = stream->available();
+ if (size) {
+ if (size > sizeof(buff)) {
+ size = sizeof(buff);
+ }
+ uint32_t read = stream->readBytes(buff, size);
+ glob_script_mem.files[fref].write(buff, read);
+ len -= read;
+ }
+ delayMicroseconds(1);
+ }
+ }
+ http.end();
+ http_client.stop();
+ return httpCode;
+}
+#endif
+
int32_t http_req(char *host, char *request) {
WiFiClient http_client;
HTTPClient http;
@@ -8613,6 +8855,10 @@ int32_t retval = 0;
case 7:
retval = Settings->timer[index].arm;
break;
+ case 8:
+ retval = Settings->flag3.timers_enable;
+ break;
+
}
return retval;
}
From 6301b598f5e70dd345e463253dcf6538a706aeea Mon Sep 17 00:00:00 2001
From: gemu2015
Date: Wed, 8 Dec 2021 16:30:11 +0100
Subject: [PATCH 015/510] =d fix, trx list allow split lines
---
tasmota/xsns_53_sml.ino | 76 ++++++++++++++++++++++++++++++++++-------
1 file changed, 64 insertions(+), 12 deletions(-)
diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino
index 7674f5cf0..d001af112 100755
--- a/tasmota/xsns_53_sml.ino
+++ b/tasmota/xsns_53_sml.ino
@@ -1555,16 +1555,22 @@ void SML_Decode(uint8_t index) {
double vdiff = meter_vars[ind - 1] - dvalues[dindex];
dvalues[dindex] = meter_vars[ind - 1];
double dres = (double)360000.0 * vdiff / ((double)dtime / 10000.0);
-#ifdef USE_SML_MEDIAN_FILTER
- if (meter_desc_p[mindex].flag & 16) {
- meter_vars[vindex] = sml_median(&sml_mf[vindex], dres);
- } else {
- meter_vars[vindex] = dres;
- }
-#else
- meter_vars[vindex] = dres;
-#endif
+ dvalid[vindex] += 1;
+
+ if (dvalid[vindex] >= 2) {
+ // differece is only valid after 2. calculation
+ dvalid[vindex] = 2;
+#ifdef USE_SML_MEDIAN_FILTER
+ if (meter_desc_p[mindex].flag & 16) {
+ meter_vars[vindex] = sml_median(&sml_mf[vindex], dres);
+ } else {
+ meter_vars[vindex] = dres;
+ }
+#else
+ meter_vars[vindex] = dres;
+#endif
+ }
mp=strchr(mp,'@');
if (mp) {
mp++;
@@ -1573,7 +1579,7 @@ void SML_Decode(uint8_t index) {
SML_Immediate_MQTT((const char*)mp, vindex, mindex);
}
}
- dvalid[vindex] = 1;
+ //dvalid[vindex] = 1;
dindex++;
}
} else if (*mp == 'h') {
@@ -2212,7 +2218,9 @@ uint8_t *script_meter;
#ifdef SML_REPLACE_VARS
+#ifndef SML_SRCBSIZE
#define SML_SRCBSIZE 256
+#endif
uint32_t SML_getlinelen(char *lp) {
uint32_t cnt;
@@ -2404,10 +2412,53 @@ dddef_exit:
script_meter_desc[index].tsecs = strtol(lp, &lp, 10);
if (*lp == ',') {
lp++;
- char txbuff[256];
+#if 1
+ // look ahead
+ uint16_t txlen = 0;
+ uint16_t tx_entries = 1;
+ char *txp = lp;
+ while (*txp) {
+ if (*txp == ',') tx_entries++;
+ if (*txp == SCRIPT_EOL) {
+ if (tx_entries > 1) {
+ if (*(txp - 1) != ',' ) {
+ break;
+ }
+ // line ends with ,
+ } else {
+ // single entry
+ break;
+ }
+ }
+ txp++;
+ txlen++;
+ }
+ if (txlen) {
+ script_meter_desc[index].txmem = (char*)calloc(txlen + 2, 1);
+ if (script_meter_desc[index].txmem) {
+ // now copy send blocks
+ char *txp = lp;
+ uint16_t tind = 0;
+ for (uint32_t cnt = 0; cnt < txlen; cnt++) {
+ if (*txp == SCRIPT_EOL) {
+ txp++;
+ } else {
+ script_meter_desc[index].txmem[tind] = *txp++;
+ tind++;
+ }
+ }
+ }
+ //AddLog(LOG_LEVEL_INFO, PSTR(">>> %s - %d"), script_meter_desc[index].txmem, txlen);
+ script_meter_desc[index].index = 0;
+ script_meter_desc[index].max_index = tx_entries;
+ sml_send_blocks++;
+ lp += txlen;
+ }
+#else
+ char txbuff[SML_SRCBSIZE];
uint32_t txlen = 0, tx_entries = 1;
for (uint32_t cnt = 0; cnt < sizeof(txbuff); cnt++) {
- if (*lp == SCRIPT_EOL) {
+ if (*lp == SCRIPT_EOL && *(lp - 1) != ',' ) {
txbuff[cnt] = 0;
txlen = cnt;
break;
@@ -2424,6 +2475,7 @@ dddef_exit:
script_meter_desc[index].max_index = tx_entries;
sml_send_blocks++;
}
+#endif
}
}
if (*lp == SCRIPT_EOL) lp--;
From 153e5c29988bfe98d65fe12577ab405cbce9ea7c Mon Sep 17 00:00:00 2001
From: gemu2015
Date: Wed, 8 Dec 2021 16:32:02 +0100
Subject: [PATCH 016/510] configurable text sfac
---
tasmota/xdrv_13_display.ino | 13 ++++++++++---
tasmota/xdsp_17_universal.ino | 20 ++++++++++----------
2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino
index 4b4a988cf..ffded1fde 100755
--- a/tasmota/xdrv_13_display.ino
+++ b/tasmota/xdrv_13_display.ino
@@ -96,6 +96,11 @@ void Get_display(uint8_t index) {
}
#endif // USE_MULTI_DISPLAY
+#ifndef TXT_MAX_SFAC
+#define TXT_MAX_SFAC 4
+#endif // TXT_MAX_SFAC
+
+
const uint8_t DISPLAY_MAX_DRIVERS = 32; // Max number of display drivers/models supported by xdsp_interface.ino
const uint8_t DISPLAY_MAX_COLS = 64; // Max number of columns allowed with command DisplayCols
const uint8_t DISPLAY_MAX_ROWS = 64; // Max number of lines allowed with command DisplayRows
@@ -875,9 +880,11 @@ void DisplayText(void)
break;
case 's':
// size sx
- if (renderer) renderer->setTextSize(*cp&7);
+ var = atoiv(cp, &temp);
+ if (temp > TXT_MAX_SFAC) temp = TXT_MAX_SFAC;
+ if (renderer) renderer->setTextSize(temp);
//else DisplaySetSize(*cp&3);
- cp += 1;
+ cp+=var;
break;
case 'f':
// font sx
@@ -2011,7 +2018,7 @@ void CmndDisplayDimmer(void) {
}
void CmndDisplaySize(void) {
- if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
+ if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= TXT_MAX_SFAC)) {
Settings->display_size = XdrvMailbox.payload;
if (renderer) renderer->setTextSize(Settings->display_size);
//else DisplaySetSize(Settings->display_size);
diff --git a/tasmota/xdsp_17_universal.ino b/tasmota/xdsp_17_universal.ino
index b80205029..a37d5af5e 100644
--- a/tasmota/xdsp_17_universal.ino
+++ b/tasmota/xdsp_17_universal.ino
@@ -55,7 +55,7 @@ void Core2DisplayDim(uint8_t dim);
#ifndef DISP_DESC_FILE
//#define DISP_DESC_FILE "/dispdesc.txt"
#define DISP_DESC_FILE "/display.ini"
-#endif
+#endif // DISP_DESC_FILE
/*********************************************************************************************/
#ifdef DSP_ROM_DESC
@@ -95,7 +95,7 @@ int8_t cs;
AddLog(LOG_LEVEL_INFO, PSTR("DSP: File descriptor used"));
}
}
-#endif
+#endif // USE_UFILESYS
#ifdef USE_SCRIPT
@@ -212,8 +212,8 @@ int8_t cs;
replacepin(&cp, Pin(GPIO_SPI_CLK, 1));
replacepin(&cp, Pin(GPIO_SPI_MOSI, 1));
replacepin(&cp, Pin(GPIO_SPI_DC, 1));
- replacepin(&cp, Pin(GPIO_BACKLIGHT, 1));
- replacepin(&cp, Pin(GPIO_OLED_RESET, 1));
+ replacepin(&cp, Pin(GPIO_BACKLIGHT));
+ replacepin(&cp, Pin(GPIO_OLED_RESET));
replacepin(&cp, Pin(GPIO_SPI_MISO, 1));
} else {
// soft spi pins
@@ -280,9 +280,9 @@ int8_t cs;
else FT5206_Touch_Init(Wire1);
#else
if (!wire_n) FT5206_Touch_Init(Wire);
-#endif
+#endif // ESP32
}
-#endif
+#endif // USE_FT5206
#ifdef USE_XPT2046
cp = strstr(ddesc, ":TS,");
@@ -291,7 +291,7 @@ int8_t cs;
uint8_t touch_cs = replacepin(&cp, Pin(GPIO_XPT2046_CS));
XPT2046_Touch_Init(touch_cs);
}
-#endif
+#endif // USE_XPT2046
uint8_t inirot = Settings->display_rotate;
@@ -314,18 +314,18 @@ int8_t cs;
#ifdef USE_M5STACK_CORE2
renderer->SetPwrCB(Core2DisplayPower);
renderer->SetDimCB(Core2DisplayDim);
-#endif
+#endif // USE_M5STACK_CORE2
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings->display_size, inirot, Settings->display_font);
Settings->display_width = renderer->width();
Settings->display_height = renderer->height();
-
+
ApplyDisplayDimmer();
#ifdef SHOW_SPLASH
renderer->Splash();
-#endif
+#endif // SHOW_SPLASH
udisp_init_done = true;
AddLog(LOG_LEVEL_INFO, PSTR("DSP: %s!"), renderer->devname());
From ba3ca8f905275f4ab733689f4ea49231e1951b7b Mon Sep 17 00:00:00 2001
From: gemu2015
Date: Wed, 8 Dec 2021 16:34:00 +0100
Subject: [PATCH 017/510] dma default off
---
lib/lib_display/UDisplay/uDisplay.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp
index 6f48d5796..8414795e0 100755
--- a/lib/lib_display/UDisplay/uDisplay.cpp
+++ b/lib/lib_display/UDisplay/uDisplay.cpp
@@ -76,6 +76,9 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
uint8_t section = 0;
dsp_ncmds = 0;
lut_num = 0;
+ lvgl_param.data = 0;
+ lvgl_param.fluslines = 40;
+
for (uint32_t cnt = 0; cnt < 5; cnt++) {
lut_cnt[cnt] = 0;
lut_cmd[cnt] = 0xff;
From a06c01cd91d4d6543a74b194e000f58c35edf927 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Wed, 8 Dec 2021 16:49:35 +0100
Subject: [PATCH 018/510] Bump version 10.1.0.1
---
CHANGELOG.md | 12 +++++++---
README.md | 2 +-
RELEASENOTES.md | 46 ++++-----------------------------------
tasmota/tasmota_version.h | 2 +-
4 files changed, 15 insertions(+), 47 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 05b3373ea..76a9f1b05 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,15 @@ All notable changes to this project will be documented in this file.
## [Unreleased] - Development
-## [10.0.0.4]
+## [10.1.0.1]
+
+## [Released]
+
+## [10.1.0] 20211208
+- Release Noelle
+
+
+## [10.0.0.4] 20211208
### Added
- (Internal) Support for FUNC_BUTTON_MULTI_PRESSED in (light)drivers
- Support for GPE Multi color smart light as sold by Action in the Netherlands
@@ -78,8 +86,6 @@ All notable changes to this project will be documented in this file.
- Discovery of shutters (#13572)
- ESP32-C3 OneWire as used by DS18x20 (#13583)
-## [Released]
-
## [10.0.0] 20211019
- Release Norman
diff --git a/README.md b/README.md
index 111536ba8..b41539308 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Easy initial installation of Tasmota can be performed using the [Tasmota WebInst
## Development
-[![Dev Version](https://img.shields.io/badge/development%20version-v10.0.x.x-blue.svg)](https://github.com/arendst/Tasmota)
+[![Dev Version](https://img.shields.io/badge/development%20version-v10.1.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/)
[![Tasmota CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22)
[![Tasmota ESP32 CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20ESP32%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22)
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 3c72eaded..e7b2dcdb3 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -66,12 +66,12 @@ Latest released binaries can be downloaded from
- http://ota.tasmota.com/tasmota/release
Historical binaries can be downloaded from
-- http://ota.tasmota.com/tasmota/release-10.0.0
+- http://ota.tasmota.com/tasmota/release-10.1.0
The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz``
### ESP32 based
-The following binary downloads have been compiled with ESP32/Arduino library core version **1.0.7.4**.
+The following binary downloads have been compiled with ESP32/Arduino library core version **2.0.1.1**.
- **tasmota32.bin** = The Tasmota version with most drivers including additional sensors and KNX for 4M+ flash. **RECOMMENDED RELEASE BINARY**
- **tasmota32c3.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C3 and 4M+ flash.
@@ -90,7 +90,7 @@ Latest released binaries can be downloaded from
- http://ota.tasmota.com/tasmota32/release
Historical binaries can be downloaded from
-- http://ota.tasmota.com/tasmota32/release-10.0.0
+- http://ota.tasmota.com/tasmota32/release-10.1.0
The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota32/release/tasmota32.bin``
@@ -100,51 +100,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
[Complete list](BUILDS.md) of available feature and sensors.
-## Changelog v10.0.0.4
+## Changelog v10.1.0.1
### Added
-- Support for 1 second heartbeat GPIO
-- Support for FUNC_BUTTON_MULTI_PRESSED in (light)drivers
-- Command ``TcpConfig`` for TCPBridge protocol configuration [#13565](https://github.com/arendst/Tasmota/issues/13565)
-- Support for HDC2010 temperature/humidity sensor by Luc Boudreau [#13633](https://github.com/arendst/Tasmota/issues/13633)
-- WS2812 scheme 13 stairs effect [#13595](https://github.com/arendst/Tasmota/issues/13595)
-- Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages [#13750](https://github.com/arendst/Tasmota/issues/13750)
-- Support for GPE Multi color smart light as sold by Action in the Netherlands
-- Shutter support for venetian blinds with tilt control
-- Support for 74xx595 8-bit shift registers [#13921](https://github.com/arendst/Tasmota/issues/13921)
-- ESP32 Autoconfiguration
-- ESP32 Preliminary support for Tasmota Apps (.tapp extesions)
-- ESP32 OTA over HTTPS
-- ESP32 HTTPS support to ``WebQuery``
-- ESP32 Berry support for neopixel (WS2812, SK6812)
-- ESP32 Berry ``import re`` regex module
-- ESP32 Berry add module ``python_compat`` to be closer to Python syntax [#13428](https://github.com/arendst/Tasmota/issues/13428)
-- ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) [#13447](https://github.com/arendst/Tasmota/issues/13447)
### Breaking Changed
-- ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8
### Changed
-- IRremoteESP8266 library from v2.7.20 to v2.8.0
-- ESP32 core library from v1.0.7.4 to v2.0.1.1
-- ESP32-C3 core library from v2.0.0-post to consolidated ESP32 core library
-- ESP32 NimBLE to v.1.3.3
-- ESP32 toolchains changed from 8.4.0-2021r1 to 8.4.0-2021r2
-- Range conversion edge values
-- ESP8266 Gratuitous ARP enabled and set to 60 seconds [#13623](https://github.com/arendst/Tasmota/issues/13623)
-- File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427)
-- MQTT TLS dual mode (CA or fingeprint) in same firmware, ``SetOption132 1`` to force fingerprint
-- ESP32 Ethernet hostname ending in ``_eth`` to ``-eth`` according to RFC952
### Fixed
-- Initial reset RTC memory based variables like EnergyToday and EnergyTotal
-- SML compile error [#13441](https://github.com/arendst/Tasmota/issues/13441)
-- GUI checkbox MQTT TLS not saved regression from v9.2.0.3 [#13442](https://github.com/arendst/Tasmota/issues/13442)
-- Discovery of shutters [#13572](https://github.com/arendst/Tasmota/issues/13572)
-- Tuya dimmer range issue [#13849](https://github.com/arendst/Tasmota/issues/13849)
-- ESP32 Telegram compile error [#13435](https://github.com/arendst/Tasmota/issues/13435)
-- ESP32-C3 OneWire as used by DS18x20 [#13583](https://github.com/arendst/Tasmota/issues/13583)
-- ESP32 analog NTC temperature calculation [#13703](https://github.com/arendst/Tasmota/issues/13703)
-- ESP32 compile error BLE EQ3 driver with core 2.0.x [#13948](https://github.com/arendst/Tasmota/issues/13948)
### Removed
-- ILI9488 driver in favour of Universal Display driver [#13719](https://github.com/arendst/Tasmota/issues/13719)
diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h
index be18bd75e..d03c4e088 100644
--- a/tasmota/tasmota_version.h
+++ b/tasmota/tasmota_version.h
@@ -20,6 +20,6 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
-const uint32_t VERSION = 0x0A000004;
+const uint32_t VERSION = 0x0A010001;
#endif // _TASMOTA_VERSION_H_
From 79b534d239ad8be233f6c15af1ee4b56b5e8bf24 Mon Sep 17 00:00:00 2001
From: tony-fav <42725386+tony-fav@users.noreply.github.com>
Date: Wed, 8 Dec 2021 13:09:54 -0500
Subject: [PATCH 019/510] Enable SetOption92 for platforms beyond ESP8266
---
tasmota/xdrv_04_light.ino | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino
index f032b8b67..b05386f4a 100644
--- a/tasmota/xdrv_04_light.ino
+++ b/tasmota/xdrv_04_light.ino
@@ -1855,10 +1855,12 @@ bool isChannelGammaCorrected(uint32_t channel) {
if (channel >= Light.subtype) { return false; } // Out of range
#ifdef ESP8266
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings->flag4.pwm_ct_mode)) {
+#else
+ if (Settings->flag4.pwm_ct_mode) {
+#endif // ESP8266
if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } // PMW reserved for CT
if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } // PMW reserved for CT
}
-#endif // ESP8266
return true;
}
@@ -1866,10 +1868,12 @@ bool isChannelGammaCorrected(uint32_t channel) {
bool isChannelCT(uint32_t channel) {
#ifdef ESP8266
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings->flag4.pwm_ct_mode)) {
+#else
+ if (Settings->flag4.pwm_ct_mode) {
+#endif // ESP8266
if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } // PMW reserved for CT
if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } // PMW reserved for CT
}
-#endif // ESP8266
return false;
}
@@ -2159,9 +2163,12 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) {
// Now we know ct_10 and white_bri10 (gamma corrected if needed)
-#ifdef ESP8266
if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) {
+#ifdef ESP8266
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings->flag4.pwm_ct_mode)) { // channel 1 is the color tone, mapped to cold channel (0..255)
+#else
+ if (Settings->flag4.pwm_ct_mode) { // channel 1 is the color tone, mapped to cold channel (0..255)
+#endif // ESP8266
pwm_ct = true;
// Xiaomi Philips bulbs follow a different scheme:
// channel 0=intensity, channel1=temperature
@@ -2170,7 +2177,6 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) {
return false; // avoid any interference
}
}
-#endif // ESP8266
// Now see if we need to mix RGB and White
// Valid only for LST_RGBW, LST_RGBCW, SetOption105 1, and white is zero (see doc)
From 696e33a6772bb928eb93939f108dd7815319fd3f Mon Sep 17 00:00:00 2001
From: Max
Date: Thu, 9 Dec 2021 11:26:54 +0300
Subject: [PATCH 020/510] MI_HM10 added support Mi Scale
1. Added Mi Scale v1/Mi Scale v2 support via BLE advertising packets
2. Added features "scale" and "impedance" to features list
---
tasmota/xsns_62_MI_HM10.ino | 246 +++++++++++++++++++++++++++++++++++-
1 file changed, 239 insertions(+), 7 deletions(-)
diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino
index f9afa1d84..fcded93cd 100644
--- a/tasmota/xsns_62_MI_HM10.ino
+++ b/tasmota/xsns_62_MI_HM10.ino
@@ -131,6 +131,37 @@ struct cg_packet_t {
uint8_t bat;
};
};
+
+struct MiScaleV1Packet_t {
+ //uint8_t size; // = 14
+ //uint8_t uid; // = 0x16, 16-bit UUID
+ //uint16_t UUID; // = 0x181D
+ uint8_t status; // bit 0 lbs, 4 jin, 5, stabilized, 7, weight removed
+ uint16_t weight;
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+};
+
+struct MiScaleV2Packet_t {
+ //uint8_t size; // = 17
+ //uint8_t uid; // = 0x16, 16-bit UUID
+ //uint16_t UUID; // = 0x181B
+ uint8_t weight_unit;
+ uint8_t status;
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ uint16_t impedance;
+ uint16_t weight;
+};
+
#pragma pack(0)
struct scan_entry_t {
@@ -175,6 +206,8 @@ struct mi_sensor_t{
uint32_t NMT:1;
uint32_t PIR:1;
uint32_t Btn:1;
+ uint32_t scale:1;
+ uint32_t impedance:1;
};
uint32_t raw;
} feature;
@@ -191,6 +224,7 @@ struct mi_sensor_t{
uint32_t motion:1;
uint32_t noMotion:1;
uint32_t Btn:1;
+ uint32_t scale:1;
};
uint32_t raw;
} eventType;
@@ -213,10 +247,46 @@ struct mi_sensor_t{
uint32_t NMT; // no motion time in seconds for the MJYD2S
};
uint16_t Btn;
+ struct {
+ uint8_t has_impedance;
+ uint8_t impedance_stabilized;
+ uint8_t weight_stabilized;
+ uint8_t weight_removed;
+ char weight_unit[4]; // kg, lbs, jin or empty when unknown
+ float weight;
+ uint16_t impedance;
+ struct {
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ } datetime;
+ };
};
union {
uint8_t bat; // many values seem to be hard-coded garbage (LYWSD0x, GCD1)
};
+/* union {
+ struct {
+ uint8_t has_impedance;
+ uint8_t impedance_stabilized;
+ uint8_t weight_stabilized;
+ uint8_t weight_removed;
+ char weight_unit[4]; // kg, lbs, jin or empty when unknown
+ float weight;
+ uint16_t impedance;
+ struct {
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ } datetime;
+ };
+ } scale;*/
};
struct {
@@ -284,6 +354,12 @@ const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}";
const char kHM10_Commands[] PROGMEM = D_CMND_HM10"|"
"Scan|AT|Period|Baud|Time|Auto|Page|Beacon|Block|Option";
+const char HTTP_MISCALE_WEIGHT[] PROGMEM = "{s}%s" " Weight" "{m}%*_f %s{e}";
+const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s" " Impedance" "{m}%u{e}";
+const char HTTP_MISCALE_WEIGHT_REMOVED[] PROGMEM = "{s}%s" " Weight removed" "{m}%s{e}";
+const char HTTP_MISCALE_STABILIZED[] PROGMEM = "{s}%s" " Stabilized" "{m}%s{e}";
+
+
void (*const HM10_Commands[])(void) PROGMEM = { &CmndHM10Scan, &CmndHM10AT, &CmndHM10Period, &CmndHM10Baud, &CmndHM10Time, &CmndHM10Auto, &CmndHM10Page, &CmndHM10Beacon, &CmndHM10Block, &CmndHM10Option };
@@ -299,8 +375,10 @@ void (*const HM10_Commands[])(void) PROGMEM = { &CmndHM10Scan, &CmndHM10AT, &Cmn
#define MHOC401 10
#define MHOC303 11
#define ATC 12
+#define MI_SCALE_V1 13
+#define MI_SCALE_V2 14
-#define HM10_TYPES 12 //count this manually
+#define HM10_TYPES 14 //count this manually
const uint16_t kHM10SlaveID[HM10_TYPES]={
0x0098, // Flora
@@ -314,7 +392,9 @@ const uint16_t kHM10SlaveID[HM10_TYPES]={
0x0153, // yee-rc
0x0387, // MHO-C401
0x06d3, // MHO-C303
- 0x0a1c // ATC -> this is a fake ID
+ 0x0a1c, // ATC -> this is a fake ID
+ 0x181d, // Mi Scale V1
+ 0x181b // Mi Scale V2
};
const char kHM10DeviceType1[] PROGMEM = "Flora";
@@ -329,8 +409,10 @@ const char kHM10DeviceType9[] PROGMEM = "YEERC";
const char kHM10DeviceType10[] PROGMEM ="MHOC401";
const char kHM10DeviceType11[] PROGMEM ="MHOC303";
const char kHM10DeviceType12[] PROGMEM ="ATC";
+const char kHM10DeviceType13[] PROGMEM ="MISCALEV1";
+const char kHM10DeviceType14[] PROGMEM ="MISCALEV2";
-const char * kHM10DeviceType[] PROGMEM = {kHM10DeviceType1,kHM10DeviceType2,kHM10DeviceType3,kHM10DeviceType4,kHM10DeviceType5,kHM10DeviceType6,kHM10DeviceType7,kHM10DeviceType8,kHM10DeviceType9,kHM10DeviceType10,kHM10DeviceType11,kHM10DeviceType12};
+const char * kHM10DeviceType[] PROGMEM = {kHM10DeviceType1,kHM10DeviceType2,kHM10DeviceType3,kHM10DeviceType4,kHM10DeviceType5,kHM10DeviceType6,kHM10DeviceType7,kHM10DeviceType8,kHM10DeviceType9,kHM10DeviceType10,kHM10DeviceType11,kHM10DeviceType12,kHM10DeviceType13,kHM10DeviceType14};
/*********************************************************************************************\
* enumerations
@@ -599,6 +681,13 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, int _rssi){
case YEERC:
_newSensor.feature.Btn=1;
break;
+ case MI_SCALE_V1:
+ _newSensor.feature.scale=1;
+ break;
+ case MI_SCALE_V2:
+ _newSensor.feature.scale=1;
+ _newSensor.feature.impedance=1;
+ break;
default:
_newSensor.hum=NAN;
_newSensor.feature.temp=1;
@@ -804,6 +893,102 @@ void HM10parseCGD1Packet(char * _buf, uint32_t _slot){ // no MiBeacon
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
}
+void HM10ParseMiScalePacket(char * _buf, uint32_t _slot, uint16_t _type){
+//void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t *addr, int RSSI, int UUID){
+ MiScaleV1Packet_t *_packetV1 = (MiScaleV1Packet_t*)_buf;
+ MiScaleV2Packet_t *_packetV2 = (MiScaleV2Packet_t*)_buf;
+
+ // Mi Scale V1
+ if (_type == 0x181d){ // 14-1-1-2
+
+ if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
+ DEBUG_SENSOR_LOG(PSTR("HM10: %s: at slot %u"), kHM10DeviceType[MIBLEsensors[_slot].type-1],_slot);
+
+ MIBLEsensors[_slot].eventType.scale = 1;
+
+ MIBLEsensors[_slot].weight_stabilized = (_packetV1->status & (1 << 5)) ? 1 : 0;
+ MIBLEsensors[_slot].weight_removed = (_packetV1->status & (1 << 7)) ? 1 : 0;
+
+ if (_packetV1->status & (1 << 0)) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
+ MIBLEsensors[_slot].weight = (float)_packetV1->weight / 100.0f;
+ } else if(_packetV1->status & (1 << 4)) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
+ MIBLEsensors[_slot].weight = (float)_packetV1->weight / 100.0f;
+ } else {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
+ MIBLEsensors[_slot].weight = (float)_packetV1->weight / 200.0f;
+ }
+
+ if (MIBLEsensors[_slot].weight_removed) {
+ MIBLEsensors[_slot].weight = 0.0f;
+ }
+ // Can be changed to memcpy or smthng else ?
+ MIBLEsensors[_slot].datetime.year = _packetV2->year;
+ MIBLEsensors[_slot].datetime.month = _packetV2->month;
+ MIBLEsensors[_slot].datetime.day = _packetV2->day;
+ MIBLEsensors[_slot].datetime.hour = _packetV2->hour;
+ MIBLEsensors[_slot].datetime.minute = _packetV2->minute;
+ MIBLEsensors[_slot].datetime.second = _packetV2->second;
+
+ MIBLEsensors[_slot].shallSendMQTT = 1;
+ bool triggerTele = MIBLEsensors[_slot].weight_stabilized && ! MIBLEsensors[_slot].weight_removed && MIBLEsensors[_slot].weight > 0;
+
+ if(HM10.option.directBridgeMode || triggerTele) HM10.mode.shallTriggerTele = 1;
+ }
+ }
+
+ // Mi Scale V2
+ else if (_type == 0x181b){ // 17-1-1-2
+
+ if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
+ DEBUG_SENSOR_LOG(PSTR("HM10: %s: at slot %u"), kHM10DeviceType[MIBLEsensors[_slot].type-1],_slot);
+
+ MIBLEsensors[_slot].eventType.scale = 1;
+
+ MIBLEsensors[_slot].has_impedance = (_packetV2->status & (1 << 1)) ? 1 : 0;
+ MIBLEsensors[_slot].weight_stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
+ MIBLEsensors[_slot].impedance_stabilized = (_packetV2->status & (1 << 1)) ? 1 : 0;
+ MIBLEsensors[_slot].weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
+
+ if (_packetV2->weight_unit & (1 << 4)) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
+ } else if(_packetV2->weight_unit == 3) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
+ } else if(_packetV2->weight_unit == 2) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 200.0f;
+ } else {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR(""));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
+ }
+
+ if (MIBLEsensors[_slot].weight_removed) {
+ MIBLEsensors[_slot].weight = 0.0f;
+ MIBLEsensors[_slot].impedance = 0;
+ }
+ else if (MIBLEsensors[_slot].has_impedance) {
+ MIBLEsensors[_slot].impedance = _packetV2->impedance;
+ }
+ // Can be changed to memcpy or smthng else ?
+ MIBLEsensors[_slot].datetime.year = _packetV2->year;
+ MIBLEsensors[_slot].datetime.month = _packetV2->month;
+ MIBLEsensors[_slot].datetime.day = _packetV2->day;
+ MIBLEsensors[_slot].datetime.hour = _packetV2->hour;
+ MIBLEsensors[_slot].datetime.minute = _packetV2->minute;
+ MIBLEsensors[_slot].datetime.second = _packetV2->second;
+
+ MIBLEsensors[_slot].shallSendMQTT = 1;
+
+ bool triggerTele = MIBLEsensors[_slot].weight_stabilized && ! MIBLEsensors[_slot].weight_removed && MIBLEsensors[_slot].weight > 0;
+ if(HM10.option.directBridgeMode || triggerTele) HM10.mode.shallTriggerTele = 1;
+ }
+ }
+}
+
+
void HM10ParseResponse(char *buf, uint16_t bufsize) {
if (!strncmp(buf,"HMSoft",6)) { //8
const char* _fw = "000";
@@ -1168,12 +1353,15 @@ bool HM10SerialHandleFeedback(){ // every 50 milliseconds
}
uint16_t _type = (uint8_t)HM10.rxAdvertisement.svcData[5]*256 + (uint8_t)HM10.rxAdvertisement.svcData[4];
// AddLog(LOG_LEVEL_DEBUG, PSTR("%04x %02x %04x %04x %04x"),HM10.rxAdvertisement.UUID,HM10.rxAdvertisement.TX,HM10.rxAdvertisement.CID,HM10.rxAdvertisement.SVC, _type);
+ DEBUG_SENSOR_LOG(PSTR("HM10: UUID %04x, TX: %02x, CID: %04x, SVC: %04x"), HM10.rxAdvertisement.UUID,HM10.rxAdvertisement.TX,HM10.rxAdvertisement.CID,HM10.rxAdvertisement.SVC);
if(HM10.rxAdvertisement.SVC==0x181a) _type = 0xa1c;
else if(HM10.rxAdvertisement.SVC==0xfdcd) _type = 0x0576;
+ else if(HM10.rxAdvertisement.SVC==0x181b || HM10.rxAdvertisement.SVC==0x181d) _type = 0x181b;
uint16_t _slot = MIBLEgetSensorSlot(HM10.rxAdvertisement.MAC, _type, HM10.rxAdvertisement.RSSI);
if(_slot!=0xff){
if (_type==0xa1c) HM10parseATC((char*)HM10.rxAdvertisement.svcData+2,_slot);
else if (_type==0x0576) HM10parseCGD1Packet((char*)HM10.rxAdvertisement.svcData+2,_slot);
+ else if (_type==0x181b) HM10ParseMiScalePacket((char*)HM10.rxAdvertisement.svcData+2,_slot, _type);
else HM10parseMiBeacon((char*)HM10.rxAdvertisement.svcData+2,_slot);
}
else{
@@ -1425,10 +1613,10 @@ void HM10_TaskEvery100ms(){
// AddLog(LOG_LEVEL_DEBUG, PSTR("%sFound done HM10_TASK"),D_CMND_HM10);
// AddLog(LOG_LEVEL_DEBUG, PSTR("%snext slot:%u, i: %u"),D_CMND_HM10, HM10_TASK_LIST[i+1][0],i);
if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { // check the next entry and if there is none
- DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10);
- DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i);
+ DEBUG_SENSOR_LOG(PSTR("%s: no Tasks left"),D_CMND_HM10);
+ DEBUG_SENSOR_LOG(PSTR("%s: HM10_TASK_DONE current slot %u"),D_CMND_HM10, i);
for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { // do a clean-up:
- DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j);
+ DEBUG_SENSOR_LOG(PSTR("%s: HM10_TASK cleanup slot %u"),D_CMND_HM10, j);
HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; // reset all task entries
HM10_TASK_LIST[j][1] = 0; // reset all delays
}
@@ -1927,6 +2115,39 @@ void HM10Show(bool json)
}
}
}
+ //Scale
+ if (MIBLEsensors[i].feature.scale){
+ if(MIBLEsensors[i].eventType.scale || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate
+ #ifdef USE_HOME_ASSISTANT
+ ||(hass_mode==2)
+ #endif //USE_HOME_ASSISTANT
+ ){
+ HM10ShowContinuation(&commaflg);
+ ResponseAppend_P(PSTR("\"weight_removed\":%u"), MIBLEsensors[i].weight_removed);
+ HM10ShowContinuation(&commaflg);
+ ResponseAppend_P(PSTR("\"weight_stabilized\":%u"), MIBLEsensors[i].weight_stabilized);
+ HM10ShowContinuation(&commaflg);
+ ResponseAppend_P(PSTR("\"weight_unit\":\"%s\""), MIBLEsensors[i].weight_unit);
+ HM10ShowContinuation(&commaflg);
+ ResponseAppend_P(PSTR("\"" D_JSON_WEIGHT "\":%*_f"),Settings->flag2.weight_resolution, &MIBLEsensors[i].weight);
+ HM10ShowContinuation(&commaflg);
+ ResponseAppend_P(PSTR("\"datetime\":\"%02u/%02u/%04u %02u:%02u:%02u\"")
+ , MIBLEsensors[i].datetime.day
+ , MIBLEsensors[i].datetime.month
+ , MIBLEsensors[i].datetime.year
+ , MIBLEsensors[i].datetime.hour
+ , MIBLEsensors[i].datetime.minute
+ , MIBLEsensors[i].datetime.second
+ );
+ }
+ }
+ if (MIBLEsensors[i].feature.impedance){
+ HM10ShowContinuation(&commaflg);
+ ResponseAppend_P(PSTR("\"impedance\":%u"), MIBLEsensors[i].has_impedance ? MIBLEsensors[i].impedance : 0);
+ HM10ShowContinuation(&commaflg);
+ ResponseAppend_P(PSTR("\"impedance_stabilized\":%u"), MIBLEsensors[i].impedance_stabilized);
+ }
+
if (HM10.option.showRSSI) {
HM10ShowContinuation(&commaflg);
ResponseAppend_P(PSTR("\"RSSI\":%d"), MIBLEsensors[i].rssi);
@@ -1992,7 +2213,18 @@ void HM10Show(bool json)
WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].fertility);
}
}
- if (MIBLEsensors[i].type>FLORA){ // everything "above" Flora
+ if (MIBLEsensors[i].type==MI_SCALE_V1 || MIBLEsensors[i].type==MI_SCALE_V2){
+
+ if (MIBLEsensors[i].feature.scale){
+ WSContentSend_PD(HTTP_MISCALE_WEIGHT, kHM10DeviceType[MIBLEsensors[i].type-1], Settings->flag2.weight_resolution, &MIBLEsensors[i].weight, MIBLEsensors[i].weight_unit);
+ WSContentSend_PD(HTTP_MISCALE_WEIGHT_REMOVED, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].weight_removed ? PSTR("yes") : PSTR("no"));
+ WSContentSend_PD(HTTP_MISCALE_STABILIZED, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].weight_stabilized ? PSTR("yes") : PSTR("no"));
+ }
+ if (MIBLEsensors[i].feature.impedance){
+ WSContentSend_PD(HTTP_MISCALE_IMPEDANCE, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].has_impedance ? MIBLEsensors[i].impedance : 0);
+ }
+ }
+ else if (MIBLEsensors[i].type>FLORA){ // everything "above" Flora
if(!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)){
WSContentSend_THD(kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum);
}
From 4cd926e0087b918c95510f95d2a5846134c9f750 Mon Sep 17 00:00:00 2001
From: Stephan Hadinger
Date: Thu, 9 Dec 2021 19:37:00 +0100
Subject: [PATCH 021/510] Berry pycoc optimization
---
lib/libesp32/Berry/Makefile | 5 +-
lib/libesp32/Berry/default/be_animate_lib.c | 248 +-
lib/libesp32/Berry/default/be_autoconf_lib.c | 548 +--
lib/libesp32/Berry/default/be_display_lib.c | 4 +-
lib/libesp32/Berry/default/be_driverlib.c | 62 +-
lib/libesp32/Berry/default/be_energylib.c | 216 +-
.../Berry/default/be_i2c_axp192_lib.c | 260 +-
lib/libesp32/Berry/default/be_i2c_driverlib.c | 154 +-
.../Berry/default/be_leds_animator_lib.c | 122 +-
lib/libesp32/Berry/default/be_leds_lib.c | 522 +--
lib/libesp32/Berry/default/be_leds_ntv_lib.c | 10 +-
.../Berry/default/be_lvgl_clock_icon_lib.c | 122 +-
lib/libesp32/Berry/default/be_lvgl_glob_lib.c | 312 +-
.../Berry/default/be_lvgl_signal_arcs_lib.c | 136 +-
.../Berry/default/be_lvgl_signal_bars_lib.c | 140 +-
.../default/be_lvgl_wifi_arcs_icon_lib.c | 42 +-
.../Berry/default/be_lvgl_wifi_arcs_lib.c | 52 +-
.../default/be_lvgl_wifi_bars_icon_lib.c | 42 +-
.../Berry/default/be_lvgl_wifi_bars_lib.c | 52 +-
lib/libesp32/Berry/default/be_modtab.c | 4 +-
lib/libesp32/Berry/default/be_persist_lib.c | 218 +-
lib/libesp32/Berry/default/be_python_compat.c | 38 +-
lib/libesp32/Berry/default/be_tapp_lib.c | 48 +-
lib/libesp32/Berry/default/be_tasmotalib.c | 3056 +++++++++--------
lib/libesp32/Berry/default/be_timer_class.c | 88 +-
lib/libesp32/Berry/default/be_unishox_lib.c | 8 +-
lib/libesp32/Berry/default/be_wirelib.c | 26 +-
.../Berry/default/embedded/i2c_driver.be | 2 +-
lib/libesp32/Berry/generate/be_const_strtab.h | 1073 ++++--
.../Berry/generate/be_const_strtab_def.h | 1570 ++++++---
.../generate/be_fixed_be_class_I2C_Driver.h | 27 -
.../generate/be_fixed_be_class_aes_gcm.h | 4 +-
.../be_fixed_be_class_audio_file_source.h | 2 +-
.../be_fixed_be_class_audio_generator.h | 2 +-
.../generate/be_fixed_be_class_audio_output.h | 2 +-
.../Berry/generate/be_fixed_be_class_bytes.h | 14 +-
.../Berry/generate/be_fixed_be_class_list.h | 10 +-
.../Berry/generate/be_fixed_be_class_map.h | 2 +-
.../Berry/generate/be_fixed_be_class_md5.h | 2 +-
.../generate/be_fixed_be_class_tasmota.h | 58 +-
.../be_fixed_be_class_tasmota_onewire.h | 2 +-
.../be_fixed_be_class_tasmota_serial.h | 2 +-
.../generate/be_fixed_be_class_webclient.h | 4 +-
lib/libesp32/Berry/generate/be_fixed_energy.h | 21 -
lib/libesp32/Berry/generate/be_fixed_global.h | 2 +-
lib/libesp32/Berry/src/be_byteslib.c | 154 +-
lib/libesp32/Berry/src/be_constobj.h | 6 +
lib/libesp32/Berry/src/be_solidifylib.c | 91 +-
lib/libesp32/Berry/src/berry.h | 4 +-
.../Berry/tools/pycoc/block_builder.py | 152 +
lib/libesp32/Berry/tools/pycoc/coc_parser.py | 146 +
lib/libesp32/Berry/tools/pycoc/coc_string.py | 40 +
.../Berry/tools/pycoc/coc_string_test.py | 18 +
lib/libesp32/Berry/tools/pycoc/hash_map.py | 162 +
lib/libesp32/Berry/tools/pycoc/macro_table.py | 50 +
lib/libesp32/Berry/tools/pycoc/main.py | 64 +
lib/libesp32/Berry/tools/pycoc/str_build.py | 123 +
.../Zip-readonly-FS/src/ZipReadFS.cpp | 14 +-
tasmota/xdrv_52_3_berry_display.ino | 4 +-
tasmota/xdrv_52_3_berry_unishox.ino | 8 +-
60 files changed, 6073 insertions(+), 4297 deletions(-)
delete mode 100644 lib/libesp32/Berry/generate/be_fixed_be_class_I2C_Driver.h
delete mode 100644 lib/libesp32/Berry/generate/be_fixed_energy.h
create mode 100644 lib/libesp32/Berry/tools/pycoc/block_builder.py
create mode 100644 lib/libesp32/Berry/tools/pycoc/coc_parser.py
create mode 100644 lib/libesp32/Berry/tools/pycoc/coc_string.py
create mode 100644 lib/libesp32/Berry/tools/pycoc/coc_string_test.py
create mode 100644 lib/libesp32/Berry/tools/pycoc/hash_map.py
create mode 100644 lib/libesp32/Berry/tools/pycoc/macro_table.py
create mode 100644 lib/libesp32/Berry/tools/pycoc/main.py
create mode 100644 lib/libesp32/Berry/tools/pycoc/str_build.py
diff --git a/lib/libesp32/Berry/Makefile b/lib/libesp32/Berry/Makefile
index 531661bc2..f9d61125d 100644
--- a/lib/libesp32/Berry/Makefile
+++ b/lib/libesp32/Berry/Makefile
@@ -10,6 +10,8 @@ SRCPATH = src default
GENERATE = generate
CONFIG = default/berry_conf.h
COC = tools/coc/coc
+PY = python3
+PYCOC = tools/pycoc/main.py
CONST_TAB = $(GENERATE)/be_const_strtab.h
MAKE_COC = $(MAKE) -C tools/coc
@@ -18,6 +20,7 @@ ifeq ($(OS), Windows_NT) # Windows
LFLAGS += -Wl,--out-implib,berry.lib # export symbols lib for dll linked
TARGET := $(TARGET).exe
COC := $(COC).exe
+ PY := $(PY).exe
else
CFLAGS += -DUSE_READLINE_LIB
LIBS += -lreadline -ldl
@@ -92,7 +95,7 @@ uninstall:
prebuild: $(COC) $(GENERATE)
$(MSG) [Prebuild] generate resources
- $(Q) $(COC) -o $(GENERATE) $(SRCPATH) -c $(CONFIG)
+ $(Q) $(PY) $(PYCOC) -o $(GENERATE) $(SRCPATH) -c $(CONFIG)
$(MSG) done
clean:
diff --git a/lib/libesp32/Berry/default/be_animate_lib.c b/lib/libesp32/Berry/default/be_animate_lib.c
index db6052653..398f87b66 100644
--- a/lib/libesp32/Berry/default/be_animate_lib.c
+++ b/lib/libesp32/Berry/default/be_animate_lib.c
@@ -20,17 +20,17 @@ be_local_closure(Animate_rotate_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("closure", 1548407746, 7),
- /* K2 */ be_nested_string("code", -114201356, 4),
- /* K3 */ be_nested_string("push", -2022703139, 4),
- /* K4 */ be_nested_string("animate", -409180496, 7),
- /* K5 */ be_nested_string("ins_ramp", 1068049360, 8),
- /* K6 */ be_nested_string("ins_goto", 1342843963, 8),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(closure),
+ /* K2 */ be_nested_str(code),
+ /* K3 */ be_nested_str(push),
+ /* K4 */ be_nested_str(animate),
+ /* K5 */ be_nested_str(ins_ramp),
+ /* K6 */ be_nested_str(ins_goto),
/* K7 */ be_const_int(0),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[25]) { /* code */
0x60140003, // 0000 GETGBL R5 G3
0x5C180000, // 0001 MOVE R6 R0
@@ -72,9 +72,9 @@ be_local_class(Animate_rotate,
&be_class_Animate_engine,
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_rotate_init_closure) },
+ { be_const_key(init, -1), be_const_closure(Animate_rotate_init_closure) },
})),
- (be_nested_const_str("Animate_rotate", -787188142, 14))
+ be_str_literal("Animate_rotate")
);
/********************************************************************
@@ -91,15 +91,15 @@ be_local_closure(Animate_from_to_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("closure", 1548407746, 7),
- /* K2 */ be_nested_string("code", -114201356, 4),
- /* K3 */ be_nested_string("push", -2022703139, 4),
- /* K4 */ be_nested_string("animate", -409180496, 7),
- /* K5 */ be_nested_string("ins_ramp", 1068049360, 8),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(closure),
+ /* K2 */ be_nested_str(code),
+ /* K3 */ be_nested_str(push),
+ /* K4 */ be_nested_str(animate),
+ /* K5 */ be_nested_str(ins_ramp),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[16]) { /* code */
0x60140003, // 0000 GETGBL R5 G3
0x5C180000, // 0001 MOVE R6 R0
@@ -132,9 +132,9 @@ be_local_class(Animate_from_to,
&be_class_Animate_engine,
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_from_to_init_closure) },
+ { be_const_key(init, -1), be_const_closure(Animate_from_to_init_closure) },
})),
- (be_nested_const_str("Animate_from_to", 1699049867, 15))
+ be_str_literal("Animate_from_to")
);
/********************************************************************
@@ -151,18 +151,18 @@ be_local_closure(Animate_back_forth_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 9]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("closure", 1548407746, 7),
- /* K2 */ be_nested_string("code", -114201356, 4),
- /* K3 */ be_nested_string("push", -2022703139, 4),
- /* K4 */ be_nested_string("animate", -409180496, 7),
- /* K5 */ be_nested_string("ins_ramp", 1068049360, 8),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(closure),
+ /* K2 */ be_nested_str(code),
+ /* K3 */ be_nested_str(push),
+ /* K4 */ be_nested_str(animate),
+ /* K5 */ be_nested_str(ins_ramp),
/* K6 */ be_const_int(2),
- /* K7 */ be_nested_string("ins_goto", 1342843963, 8),
+ /* K7 */ be_nested_str(ins_goto),
/* K8 */ be_const_int(0),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[34]) { /* code */
0x60140003, // 0000 GETGBL R5 G3
0x5C180000, // 0001 MOVE R6 R0
@@ -213,9 +213,9 @@ be_local_class(Animate_back_forth,
&be_class_Animate_engine,
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_back_forth_init_closure) },
+ { be_const_key(init, -1), be_const_closure(Animate_back_forth_init_closure) },
})),
- (be_nested_const_str("Animate_back_forth", 5319526, 18))
+ be_str_literal("Animate_back_forth")
);
/********************************************************************
@@ -232,12 +232,12 @@ be_local_closure(Animate_ins_goto_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("pc_rel", 991921176, 6),
- /* K1 */ be_nested_string("pc_abs", 920256495, 6),
- /* K2 */ be_nested_string("duration", 799079693, 8),
+ /* K0 */ be_nested_str(pc_rel),
+ /* K1 */ be_nested_str(pc_abs),
+ /* K2 */ be_nested_str(duration),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x90020202, // 0001 SETMBR R0 K1 R2
@@ -257,12 +257,12 @@ be_local_class(Animate_ins_goto,
NULL,
be_nested_map(4,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("pc_rel", 991921176, 6, -1), be_const_var(0) },
- { be_nested_key("duration", 799079693, 8, -1), be_const_var(2) },
- { be_nested_key("pc_abs", 920256495, 6, -1), be_const_var(1) },
- { be_nested_key("init", 380752755, 4, 2), be_const_closure(Animate_ins_goto_init_closure) },
+ { be_const_key(pc_rel, -1), be_const_var(0) },
+ { be_const_key(duration, -1), be_const_var(2) },
+ { be_const_key(pc_abs, -1), be_const_var(1) },
+ { be_const_key(init, 2), be_const_closure(Animate_ins_goto_init_closure) },
})),
- (be_nested_const_str("Animate_ins_goto", 1667367043, 16))
+ be_str_literal("Animate_ins_goto")
);
/********************************************************************
@@ -279,12 +279,12 @@ be_local_closure(Animate_ins_ramp_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("a", -468965076, 1),
- /* K1 */ be_nested_string("b", -418632219, 1),
- /* K2 */ be_nested_string("duration", 799079693, 8),
+ /* K0 */ be_nested_str(a),
+ /* K1 */ be_nested_str(b),
+ /* K2 */ be_nested_str(duration),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x90020202, // 0001 SETMBR R0 K1 R2
@@ -304,12 +304,12 @@ be_local_class(Animate_ins_ramp,
NULL,
be_nested_map(4,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("a", -468965076, 1, -1), be_const_var(0) },
- { be_nested_key("b", -418632219, 1, 2), be_const_var(1) },
- { be_nested_key("duration", 799079693, 8, -1), be_const_var(2) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_ins_ramp_init_closure) },
+ { be_const_key(a, -1), be_const_var(0) },
+ { be_const_key(b, 2), be_const_var(1) },
+ { be_const_key(duration, -1), be_const_var(2) },
+ { be_const_key(init, -1), be_const_closure(Animate_ins_ramp_init_closure) },
})),
- (be_nested_const_str("Animate_ins_ramp", 785058280, 16))
+ be_str_literal("Animate_ins_ramp")
);
/********************************************************************
@@ -326,15 +326,15 @@ be_local_closure(Animate_engine_run, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
- /* K1 */ be_nested_string("millis", 1214679063, 6),
- /* K2 */ be_nested_string("value", 1113510858, 5),
- /* K3 */ be_nested_string("ins_time", -1314721743, 8),
- /* K4 */ be_nested_string("running", 343848780, 7),
- /* K5 */ be_nested_string("add_driver", 1654458371, 10),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(millis),
+ /* K2 */ be_nested_str(value),
+ /* K3 */ be_nested_str(ins_time),
+ /* K4 */ be_nested_str(running),
+ /* K5 */ be_nested_str(add_driver),
}),
- (be_nested_const_str("run", 718098122, 3)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_run,
+ &be_const_str_solidified,
( &(const binstruction[19]) { /* code */
0x4C0C0000, // 0000 LDNIL R3
0x1C0C0203, // 0001 EQ R3 R1 R3
@@ -375,14 +375,14 @@ be_local_closure(Animate_engine_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("code", -114201356, 4),
- /* K1 */ be_nested_string("pc", 1313756516, 2),
+ /* K0 */ be_nested_str(code),
+ /* K1 */ be_nested_str(pc),
/* K2 */ be_const_int(0),
- /* K3 */ be_nested_string("ins_time", -1314721743, 8),
- /* K4 */ be_nested_string("running", 343848780, 7),
+ /* K3 */ be_nested_str(ins_time),
+ /* K4 */ be_nested_str(running),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x60040012, // 0000 GETGBL R1 G18
0x7C040000, // 0001 CALL R1 0
@@ -412,12 +412,12 @@ be_local_closure(Animate_engine_autorun, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("run", 718098122, 3),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("add_driver", 1654458371, 10),
+ /* K0 */ be_nested_str(run),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(add_driver),
}),
- (be_nested_const_str("autorun", 1447527407, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_autorun,
+ &be_const_str_solidified,
( &(const binstruction[ 9]) { /* code */
0x8C0C0100, // 0000 GETMET R3 R0 K0
0x5C140200, // 0001 MOVE R5 R1
@@ -448,12 +448,12 @@ be_local_closure(Animate_engine_stop, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("running", 343848780, 7),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("remove_driver", 1030243768, 13),
+ /* K0 */ be_nested_str(running),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(remove_driver),
}),
- (be_nested_const_str("stop", -883741979, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_stop,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x50040000, // 0000 LDBOOL R1 0 0
0x90020001, // 0001 SETMBR R0 K0 R1
@@ -482,10 +482,10 @@ be_local_closure(Animate_engine_is_running, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("running", 343848780, 7),
+ /* K0 */ be_nested_str(running),
}),
- (be_nested_const_str("is_running", -2068120035, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_is_running,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x80040200, // 0001 RET 1 R1
@@ -509,10 +509,10 @@ be_local_closure(Animate_engine_every_50ms, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("animate", -409180496, 7),
+ /* K0 */ be_nested_str(animate),
}),
- (be_nested_const_str("every_50ms", -1911083288, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_every_50ms,
+ &be_const_str_solidified,
( &(const binstruction[ 3]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x7C040200, // 0001 CALL R1 1
@@ -537,31 +537,31 @@ be_local_closure(Animate_engine_animate, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[22]) { /* constants */
- /* K0 */ be_nested_string("running", 343848780, 7),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("millis", 1214679063, 6),
- /* K3 */ be_nested_string("ins_time", -1314721743, 8),
- /* K4 */ be_nested_string("pc", 1313756516, 2),
- /* K5 */ be_nested_string("code", -114201356, 4),
+ /* K0 */ be_nested_str(running),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(millis),
+ /* K3 */ be_nested_str(ins_time),
+ /* K4 */ be_nested_str(pc),
+ /* K5 */ be_nested_str(code),
/* K6 */ be_const_int(0),
- /* K7 */ be_nested_string("internal_error", -1775809127, 14),
- /* K8 */ be_nested_string("Animate pc is out of range", 1854929421, 26),
- /* K9 */ be_nested_string("animate", -409180496, 7),
- /* K10 */ be_nested_string("ins_ramp", 1068049360, 8),
- /* K11 */ be_nested_string("closure", 1548407746, 7),
- /* K12 */ be_nested_string("duration", 799079693, 8),
- /* K13 */ be_nested_string("value", 1113510858, 5),
- /* K14 */ be_nested_string("scale_uint", -1204156202, 10),
- /* K15 */ be_nested_string("a", -468965076, 1),
- /* K16 */ be_nested_string("b", -418632219, 1),
+ /* K7 */ be_nested_str(internal_error),
+ /* K8 */ be_nested_str(Animate_X20pc_X20is_X20out_X20of_X20range),
+ /* K9 */ be_nested_str(animate),
+ /* K10 */ be_nested_str(ins_ramp),
+ /* K11 */ be_nested_str(closure),
+ /* K12 */ be_nested_str(duration),
+ /* K13 */ be_nested_str(value),
+ /* K14 */ be_nested_str(scale_uint),
+ /* K15 */ be_nested_str(a),
+ /* K16 */ be_nested_str(b),
/* K17 */ be_const_int(1),
- /* K18 */ be_nested_string("ins_goto", 1342843963, 8),
- /* K19 */ be_nested_string("pc_rel", 991921176, 6),
- /* K20 */ be_nested_string("pc_abs", 920256495, 6),
- /* K21 */ be_nested_string("unknown instruction", 1093911841, 19),
+ /* K18 */ be_nested_str(ins_goto),
+ /* K19 */ be_nested_str(pc_rel),
+ /* K20 */ be_nested_str(pc_abs),
+ /* K21 */ be_nested_str(unknown_X20instruction),
}),
- (be_nested_const_str("animate", -409180496, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_animate,
+ &be_const_str_solidified,
( &(const binstruction[99]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x740A0000, // 0001 JMPT R2 #0003
@@ -676,21 +676,21 @@ be_local_class(Animate_engine,
NULL,
be_nested_map(13,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("code", -114201356, 4, -1), be_const_var(0) },
- { be_nested_key("run", 718098122, 3, 4), be_const_closure(Animate_engine_run_closure) },
- { be_nested_key("running", 343848780, 7, 8), be_const_var(4) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_engine_init_closure) },
- { be_nested_key("autorun", 1447527407, 7, -1), be_const_closure(Animate_engine_autorun_closure) },
- { be_nested_key("value", 1113510858, 5, -1), be_const_var(5) },
- { be_nested_key("stop", -883741979, 4, 3), be_const_closure(Animate_engine_stop_closure) },
- { be_nested_key("pc", 1313756516, 2, -1), be_const_var(2) },
- { be_nested_key("is_running", -2068120035, 10, 11), be_const_closure(Animate_engine_is_running_closure) },
- { be_nested_key("every_50ms", -1911083288, 10, 10), be_const_closure(Animate_engine_every_50ms_closure) },
- { be_nested_key("animate", -409180496, 7, -1), be_const_closure(Animate_engine_animate_closure) },
- { be_nested_key("closure", 1548407746, 7, -1), be_const_var(1) },
- { be_nested_key("ins_time", -1314721743, 8, 9), be_const_var(3) },
+ { be_const_key(code, -1), be_const_var(0) },
+ { be_const_key(run, 4), be_const_closure(Animate_engine_run_closure) },
+ { be_const_key(running, 8), be_const_var(4) },
+ { be_const_key(init, -1), be_const_closure(Animate_engine_init_closure) },
+ { be_const_key(autorun, -1), be_const_closure(Animate_engine_autorun_closure) },
+ { be_const_key(value, -1), be_const_var(5) },
+ { be_const_key(stop, 3), be_const_closure(Animate_engine_stop_closure) },
+ { be_const_key(pc, -1), be_const_var(2) },
+ { be_const_key(is_running, 11), be_const_closure(Animate_engine_is_running_closure) },
+ { be_const_key(every_50ms, 10), be_const_closure(Animate_engine_every_50ms_closure) },
+ { be_const_key(animate, -1), be_const_closure(Animate_engine_animate_closure) },
+ { be_const_key(closure, -1), be_const_var(1) },
+ { be_const_key(ins_time, 9), be_const_var(3) },
})),
- (be_nested_const_str("Animate_engine", 1498417667, 14))
+ be_str_literal("Animate_engine")
);
/********************************************************************
@@ -700,12 +700,12 @@ be_local_module(animate,
"animate",
be_nested_map(6,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("rotate", -1510671094, 6, 2), be_const_class(be_class_Animate_rotate) },
- { be_nested_key("from_to", 21625507, 7, 3), be_const_class(be_class_Animate_from_to) },
- { be_nested_key("back_forth", -1629925234, 10, -1), be_const_class(be_class_Animate_back_forth) },
- { be_nested_key("ins_goto", 1342843963, 8, -1), be_const_class(be_class_Animate_ins_goto) },
- { be_nested_key("ins_ramp", 1068049360, 8, -1), be_const_class(be_class_Animate_ins_ramp) },
- { be_nested_key("engine", -301606853, 6, -1), be_const_class(be_class_Animate_engine) },
+ { be_const_key(rotate, 2), be_const_class(be_class_Animate_rotate) },
+ { be_const_key(from_to, 3), be_const_class(be_class_Animate_from_to) },
+ { be_const_key(back_forth, -1), be_const_class(be_class_Animate_back_forth) },
+ { be_const_key(ins_goto, -1), be_const_class(be_class_Animate_ins_goto) },
+ { be_const_key(ins_ramp, -1), be_const_class(be_class_Animate_ins_ramp) },
+ { be_const_key(engine, -1), be_const_class(be_class_Animate_engine) },
}))
);
BE_EXPORT_VARIABLE be_define_const_native_module(animate);
diff --git a/lib/libesp32/Berry/default/be_autoconf_lib.c b/lib/libesp32/Berry/default/be_autoconf_lib.c
index 3d864a988..da41707c7 100644
--- a/lib/libesp32/Berry/default/be_autoconf_lib.c
+++ b/lib/libesp32/Berry/default/be_autoconf_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: page_autoconf_ctl
********************************************************************/
-be_local_closure(page_autoconf_ctl, /* name */
+be_local_closure(Autoconf_page_autoconf_ctl, /* name */
be_nested_proto(
13, /* nstack */
1, /* argc */
@@ -21,50 +21,50 @@ be_local_closure(page_autoconf_ctl, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[41]) { /* constants */
- /* K0 */ be_nested_string("webserver", 1572454038, 9),
- /* K1 */ be_nested_string("string", 398550328, 6),
- /* K2 */ be_nested_string("path", -2071507658, 4),
- /* K3 */ be_nested_string("check_privileged_access", -602033328, 23),
- /* K4 */ be_nested_string("has_arg", 424878688, 7),
- /* K5 */ be_nested_string("reapply", -516027964, 7),
- /* K6 */ be_nested_string("tasmota", 424643812, 7),
- /* K7 */ be_nested_string("log", 1062293841, 3),
- /* K8 */ be_nested_string("CFG: removing first time marker", 2125556683, 31),
+ /* K0 */ be_nested_str(webserver),
+ /* K1 */ be_nested_str(string),
+ /* K2 */ be_nested_str(path),
+ /* K3 */ be_nested_str(check_privileged_access),
+ /* K4 */ be_nested_str(has_arg),
+ /* K5 */ be_nested_str(reapply),
+ /* K6 */ be_nested_str(tasmota),
+ /* K7 */ be_nested_str(log),
+ /* K8 */ be_nested_str(CFG_X3A_X20removing_X20first_X20time_X20marker),
/* K9 */ be_const_int(2),
- /* K10 */ be_nested_string("clear_first_time", 632769909, 16),
- /* K11 */ be_nested_string("redirect", 389758641, 8),
- /* K12 */ be_nested_string("/?rst=", 580074707, 6),
- /* K13 */ be_nested_string("zip", -1417514060, 3),
- /* K14 */ be_nested_string("CFG: removing autoconf files", -280262326, 28),
- /* K15 */ be_nested_string("delete_all_configs", -1912899718, 18),
- /* K16 */ be_nested_string("arg", 1047474471, 3),
- /* K17 */ be_nested_string("reset", 1695364032, 5),
- /* K18 */ be_nested_string("format", -1180859054, 6),
- /* K19 */ be_nested_string("https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", -1551440987, 70),
- /* K20 */ be_nested_string("arch", -1342162999, 4),
- /* K21 */ be_nested_string("CFG: downloading '%s'", 589480701, 21),
- /* K22 */ be_nested_string("%s.autoconf", -734583772, 11),
- /* K23 */ be_nested_string("webclient", -218578150, 9),
- /* K24 */ be_nested_string("begin", 1748273790, 5),
- /* K25 */ be_nested_string("GET", -1763262857, 3),
- /* K26 */ be_nested_string("return code=%i", 2127454401, 14),
- /* K27 */ be_nested_string("connection_error", 1358926260, 16),
- /* K28 */ be_nested_string("write_file", -1117308417, 10),
- /* K29 */ be_nested_string("close", 667630371, 5),
- /* K30 */ be_nested_string("value_error", 773297791, 11),
- /* K31 */ be_nested_string("Unknown command", 1830905432, 15),
- /* K32 */ be_nested_string("CFG: Exception> '%s' - %s", 1228874553, 25),
- /* K33 */ be_nested_string("content_start", -1357458227, 13),
- /* K34 */ be_nested_string("Parameter error", -454925258, 15),
- /* K35 */ be_nested_string("content_send_style", 1087907647, 18),
- /* K36 */ be_nested_string("content_send", 1673733649, 12),
- /* K37 */ be_nested_string("Exception:
'%s'
%s
", -42402214, 59),
- /* K38 */ be_nested_string("content_button", 1956476087, 14),
- /* K39 */ be_nested_string("BUTTON_CONFIGURATION", 70820856, 20),
- /* K40 */ be_nested_string("content_stop", 658554751, 12),
+ /* K10 */ be_nested_str(clear_first_time),
+ /* K11 */ be_nested_str(redirect),
+ /* K12 */ be_nested_str(_X2F_X3Frst_X3D),
+ /* K13 */ be_nested_str(zip),
+ /* K14 */ be_nested_str(CFG_X3A_X20removing_X20autoconf_X20files),
+ /* K15 */ be_nested_str(delete_all_configs),
+ /* K16 */ be_nested_str(arg),
+ /* K17 */ be_nested_str(reset),
+ /* K18 */ be_nested_str(format),
+ /* K19 */ be_nested_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf),
+ /* K20 */ be_nested_str(arch),
+ /* K21 */ be_nested_str(CFG_X3A_X20downloading_X20_X27_X25s_X27),
+ /* K22 */ be_nested_str(_X25s_X2Eautoconf),
+ /* K23 */ be_nested_str(webclient),
+ /* K24 */ be_nested_str(begin),
+ /* K25 */ be_nested_str(GET),
+ /* K26 */ be_nested_str(return_X20code_X3D_X25i),
+ /* K27 */ be_nested_str(connection_error),
+ /* K28 */ be_nested_str(write_file),
+ /* K29 */ be_nested_str(close),
+ /* K30 */ be_nested_str(value_error),
+ /* K31 */ be_nested_str(Unknown_X20command),
+ /* K32 */ be_nested_str(CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
+ /* K33 */ be_nested_str(content_start),
+ /* K34 */ be_nested_str(Parameter_X20error),
+ /* K35 */ be_nested_str(content_send_style),
+ /* K36 */ be_nested_str(content_send),
+ /* K37 */ be_nested_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E),
+ /* K38 */ be_nested_str(content_button),
+ /* K39 */ be_nested_str(BUTTON_CONFIGURATION),
+ /* K40 */ be_nested_str(content_stop),
}),
- (be_nested_const_str("page_autoconf_ctl", -1841585800, 17)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_page_autoconf_ctl,
+ &be_const_str_solidified,
( &(const binstruction[117]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xA40A0200, // 0001 IMPORT R2 K1
@@ -192,7 +192,7 @@ be_local_closure(page_autoconf_ctl, /* name */
/********************************************************************
** Solidified function: autoexec
********************************************************************/
-be_local_closure(autoexec, /* name */
+be_local_closure(Autoconf_autoexec, /* name */
be_nested_proto(
9, /* nstack */
1, /* argc */
@@ -203,41 +203,41 @@ be_local_closure(autoexec, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[32]) { /* constants */
- /* K0 */ be_nested_string("_archive", -290407892, 8),
- /* K1 */ be_nested_string("path", -2071507658, 4),
- /* K2 */ be_nested_string("#init.bat", -997372219, 9),
- /* K3 */ be_nested_string("is_first_time", 275242384, 13),
- /* K4 */ be_nested_string("exists", 1002329533, 6),
- /* K5 */ be_nested_string("set_first_time", -1183719746, 14),
- /* K6 */ be_nested_string("run_bat", -1758063998, 7),
- /* K7 */ be_nested_string("tasmota", 424643812, 7),
- /* K8 */ be_nested_string("log", 1062293841, 3),
- /* K9 */ be_nested_string("CFG: 'init.bat' done, restarting", 1569670677, 32),
+ /* K0 */ be_nested_str(_archive),
+ /* K1 */ be_nested_str(path),
+ /* K2 */ be_nested_str(_X23init_X2Ebat),
+ /* K3 */ be_nested_str(is_first_time),
+ /* K4 */ be_nested_str(exists),
+ /* K5 */ be_nested_str(set_first_time),
+ /* K6 */ be_nested_str(run_bat),
+ /* K7 */ be_nested_str(tasmota),
+ /* K8 */ be_nested_str(log),
+ /* K9 */ be_nested_str(CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting),
/* K10 */ be_const_int(2),
- /* K11 */ be_nested_string("cmd", -158181397, 3),
- /* K12 */ be_nested_string("Restart 1", -790511441, 9),
- /* K13 */ be_nested_string("#display.ini", 182218220, 12),
- /* K14 */ be_nested_string("gpio", -1656812038, 4),
- /* K15 */ be_nested_string("pin_used", -261112684, 8),
- /* K16 */ be_nested_string("OPTION_A", 1133299440, 8),
- /* K17 */ be_nested_string("display.ini", -1648793295, 11),
- /* K18 */ be_nested_string("CFG: skipping 'display.ini' because already present in file-system", -329418032, 66),
- /* K19 */ be_nested_string("display", 1164572437, 7),
- /* K20 */ be_nested_string("r", -150190315, 1),
- /* K21 */ be_nested_string("read", -824204347, 4),
- /* K22 */ be_nested_string("close", 667630371, 5),
- /* K23 */ be_nested_string("start", 1697318111, 5),
- /* K24 */ be_nested_string("#autoexec.bat", -912076799, 13),
- /* K25 */ be_nested_string("CFG: running ", -1816632762, 13),
+ /* K11 */ be_nested_str(cmd),
+ /* K12 */ be_nested_str(Restart_X201),
+ /* K13 */ be_nested_str(_X23display_X2Eini),
+ /* K14 */ be_nested_str(gpio),
+ /* K15 */ be_nested_str(pin_used),
+ /* K16 */ be_nested_str(OPTION_A),
+ /* K17 */ be_nested_str(display_X2Eini),
+ /* K18 */ be_nested_str(CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem),
+ /* K19 */ be_nested_str(display),
+ /* K20 */ be_nested_str(r),
+ /* K21 */ be_nested_str(read),
+ /* K22 */ be_nested_str(close),
+ /* K23 */ be_nested_str(start),
+ /* K24 */ be_nested_str(_X23autoexec_X2Ebat),
+ /* K25 */ be_nested_str(CFG_X3A_X20running_X20),
/* K26 */ be_const_int(3),
- /* K27 */ be_nested_string("CFG: ran ", -715396824, 10),
- /* K28 */ be_nested_string("#autoexec.be", 1181757091, 12),
- /* K29 */ be_nested_string("CFG: loading ", -284605793, 13),
- /* K30 */ be_nested_string("load", -435725847, 4),
- /* K31 */ be_nested_string("CFG: loaded ", -584693758, 13),
+ /* K27 */ be_nested_str(CFG_X3A_X20ran_X20_X20),
+ /* K28 */ be_nested_str(_X23autoexec_X2Ebe),
+ /* K29 */ be_nested_str(CFG_X3A_X20loading_X20),
+ /* K30 */ be_nested_str(load),
+ /* K31 */ be_nested_str(CFG_X3A_X20loaded_X20_X20),
}),
- (be_nested_const_str("autoexec", -618105405, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_autoexec,
+ &be_const_str_solidified,
( &(const binstruction[107]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x4C080000, // 0001 LDNIL R2
@@ -355,7 +355,7 @@ be_local_closure(autoexec, /* name */
/********************************************************************
** Solidified function: run_bat
********************************************************************/
-be_local_closure(run_bat, /* name */
+be_local_closure(Autoconf_run_bat, /* name */
be_nested_proto(
13, /* nstack */
2, /* argc */
@@ -366,19 +366,19 @@ be_local_closure(run_bat, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_string("string", 398550328, 6),
- /* K1 */ be_nested_string("r", -150190315, 1),
- /* K2 */ be_nested_string("readline", 1212709927, 8),
+ /* K0 */ be_nested_str(string),
+ /* K1 */ be_nested_str(r),
+ /* K2 */ be_nested_str(readline),
/* K3 */ be_const_int(0),
- /* K4 */ be_nested_string("\n", 252472541, 1),
- /* K5 */ be_nested_string("tasmota", 424643812, 7),
- /* K6 */ be_nested_string("cmd", -158181397, 3),
- /* K7 */ be_nested_string("close", 667630371, 5),
- /* K8 */ be_nested_string("format", -1180859054, 6),
- /* K9 */ be_nested_string("CFG: could not run %s (%s - %s)", 1428829580, 31),
+ /* K4 */ be_nested_str(_X0A),
+ /* K5 */ be_nested_str(tasmota),
+ /* K6 */ be_nested_str(cmd),
+ /* K7 */ be_nested_str(close),
+ /* K8 */ be_nested_str(format),
+ /* K9 */ be_nested_str(CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29),
}),
- (be_nested_const_str("run_bat", -1758063998, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_run_bat,
+ &be_const_str_solidified,
( &(const binstruction[54]) { /* code */
0xA40A0000, // 0000 IMPORT R2 K0
0x4C0C0000, // 0001 LDNIL R3
@@ -443,7 +443,7 @@ be_local_closure(run_bat, /* name */
/********************************************************************
** Solidified function: page_autoconf_mgr
********************************************************************/
-be_local_closure(page_autoconf_mgr, /* name */
+be_local_closure(Autoconf_page_autoconf_mgr, /* name */
be_nested_proto(
19, /* nstack */
1, /* argc */
@@ -454,48 +454,48 @@ be_local_closure(page_autoconf_mgr, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[39]) { /* constants */
- /* K0 */ be_nested_string("webserver", 1572454038, 9),
- /* K1 */ be_nested_string("string", 398550328, 6),
- /* K2 */ be_nested_string("check_privileged_access", -602033328, 23),
- /* K3 */ be_nested_string("content_start", -1357458227, 13),
- /* K4 */ be_nested_string("Auto-configuration", 1665006109, 18),
- /* K5 */ be_nested_string("content_send_style", 1087907647, 18),
- /* K6 */ be_nested_string("content_send", 1673733649, 12),
- /* K7 */ be_nested_string(" (This feature requires an internet connection)
", -1575700810, 74),
- /* K8 */ be_nested_string("get_current_module_path", -1088293888, 23),
- /* K9 */ be_nested_string("tr", 1195724803, 2),
- /* K10 */ be_nested_string("get_current_module_name", -1915696556, 23),
- /* K11 */ be_nested_string("_", -636741266, 1),
- /* K12 */ be_nested_string(" ", 621580159, 1),
- /* K13 */ be_nested_string("_error", 1132109656, 6),
- /* K14 */ be_nested_string("<Error: apply new or remove>", -1439459347, 34),
- /* K15 */ be_nested_string("<None>", -1692801798, 12),
- /* K16 */ be_nested_string("
", -748395557, 11),
- /* K24 */ be_nested_string("", 2052843416, 25),
- /* K25 */ be_nested_string("", 1926223891, 80),
- /* K26 */ be_nested_string("", 452285201, 120),
+ /* K0 */ be_nested_str(webserver),
+ /* K1 */ be_nested_str(content_send),
+ /* K2 */ be_nested_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
}),
- (be_nested_const_str("web_add_config_button", 639674325, 21)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_web_add_config_button,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x8C080301, // 0001 GETMET R2 R1 K1
@@ -916,7 +916,7 @@ be_local_closure(web_add_config_button, /* name */
/********************************************************************
** Solidified function: is_first_time
********************************************************************/
-be_local_closure(is_first_time, /* name */
+be_local_closure(Autoconf_is_first_time, /* name */
be_nested_proto(
5, /* nstack */
1, /* argc */
@@ -927,12 +927,12 @@ be_local_closure(is_first_time, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("path", -2071507658, 4),
- /* K1 */ be_nested_string("exists", 1002329533, 6),
- /* K2 */ be_nested_string("/.autoconf", -2082892903, 10),
+ /* K0 */ be_nested_str(path),
+ /* K1 */ be_nested_str(exists),
+ /* K2 */ be_nested_str(_X2F_X2Eautoconf),
}),
- (be_nested_const_str("is_first_time", 275242384, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_is_first_time,
+ &be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x8C080301, // 0001 GETMET R2 R1 K1
@@ -951,7 +951,7 @@ be_local_closure(is_first_time, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(Autoconf_init, /* name */
be_nested_proto(
12, /* nstack */
1, /* argc */
@@ -962,26 +962,26 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[17]) { /* constants */
- /* K0 */ be_nested_str_literal("path"),
- /* K1 */ be_nested_str_literal("string"),
- /* K2 */ be_nested_str_literal("listdir"),
- /* K3 */ be_nested_str_literal("/"),
- /* K4 */ be_nested_str_literal("tasmota"),
- /* K5 */ be_nested_str_literal("add_driver"),
+ /* K0 */ be_nested_str(path),
+ /* K1 */ be_nested_str(string),
+ /* K2 */ be_nested_str(listdir),
+ /* K3 */ be_nested_str(_X2F),
+ /* K4 */ be_nested_str(tasmota),
+ /* K5 */ be_nested_str(add_driver),
/* K6 */ be_const_int(0),
- /* K7 */ be_nested_str_literal("find"),
- /* K8 */ be_nested_str_literal(".autoconf"),
- /* K9 */ be_nested_str_literal("format"),
- /* K10 */ be_nested_str_literal("CFG: multiple autoconf files found, aborting ('%s' + '%s')"),
- /* K11 */ be_nested_str_literal("_error"),
+ /* K7 */ be_nested_str(find),
+ /* K8 */ be_nested_str(_X2Eautoconf),
+ /* K9 */ be_nested_str(format),
+ /* K10 */ be_nested_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29),
+ /* K11 */ be_nested_str(_error),
/* K12 */ be_const_int(1),
- /* K13 */ be_nested_str_literal("log"),
- /* K14 */ be_nested_str_literal("CFG: no '*.autoconf' file found"),
+ /* K13 */ be_nested_str(log),
+ /* K14 */ be_nested_str(CFG_X3A_X20no_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found),
/* K15 */ be_const_int(2),
- /* K16 */ be_nested_str_literal("_archive"),
+ /* K16 */ be_nested_str(_archive),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[51]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xA40A0200, // 0001 IMPORT R2 K1
@@ -1043,7 +1043,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: preinit
********************************************************************/
-be_local_closure(preinit, /* name */
+be_local_closure(Autoconf_preinit, /* name */
be_nested_proto(
7, /* nstack */
1, /* argc */
@@ -1054,19 +1054,19 @@ be_local_closure(preinit, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_string("_archive", -290407892, 8),
- /* K1 */ be_nested_string("path", -2071507658, 4),
- /* K2 */ be_nested_string("#preinit.be", 687035716, 11),
- /* K3 */ be_nested_string("exists", 1002329533, 6),
- /* K4 */ be_nested_string("tasmota", 424643812, 7),
- /* K5 */ be_nested_string("log", 1062293841, 3),
- /* K6 */ be_nested_string("CFG: loading ", -284605793, 13),
+ /* K0 */ be_nested_str(_archive),
+ /* K1 */ be_nested_str(path),
+ /* K2 */ be_nested_str(_X23preinit_X2Ebe),
+ /* K3 */ be_nested_str(exists),
+ /* K4 */ be_nested_str(tasmota),
+ /* K5 */ be_nested_str(log),
+ /* K6 */ be_nested_str(CFG_X3A_X20loading_X20),
/* K7 */ be_const_int(3),
- /* K8 */ be_nested_string("load", -435725847, 4),
- /* K9 */ be_nested_string("CFG: loaded ", -584693758, 13),
+ /* K8 */ be_nested_str(load),
+ /* K9 */ be_nested_str(CFG_X3A_X20loaded_X20_X20),
}),
- (be_nested_const_str("preinit", -1572960196, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_preinit,
+ &be_const_str_solidified,
( &(const binstruction[26]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x4C080000, // 0001 LDNIL R2
@@ -1103,7 +1103,7 @@ be_local_closure(preinit, /* name */
/********************************************************************
** Solidified function: reset
********************************************************************/
-be_local_closure(reset, /* name */
+be_local_closure(Autoconf_reset, /* name */
be_nested_proto(
12, /* nstack */
1, /* argc */
@@ -1114,22 +1114,22 @@ be_local_closure(reset, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[13]) { /* constants */
- /* K0 */ be_nested_string("path", -2071507658, 4),
- /* K1 */ be_nested_string("string", 398550328, 6),
- /* K2 */ be_nested_string("listdir", 2005220720, 7),
- /* K3 */ be_nested_string("/", 705468254, 1),
+ /* K0 */ be_nested_str(path),
+ /* K1 */ be_nested_str(string),
+ /* K2 */ be_nested_str(listdir),
+ /* K3 */ be_nested_str(_X2F),
/* K4 */ be_const_int(0),
- /* K5 */ be_nested_string("find", -1108310694, 4),
- /* K6 */ be_nested_string(".autoconf", -1770288208, 9),
- /* K7 */ be_nested_string("remove", -611183107, 6),
- /* K8 */ be_nested_string("format", -1180859054, 6),
- /* K9 */ be_nested_string("CFG: removed file '%s'", 2048602473, 22),
+ /* K5 */ be_nested_str(find),
+ /* K6 */ be_nested_str(_X2Eautoconf),
+ /* K7 */ be_nested_str(remove),
+ /* K8 */ be_nested_str(format),
+ /* K9 */ be_nested_str(CFG_X3A_X20removed_X20file_X20_X27_X25s_X27),
/* K10 */ be_const_int(1),
- /* K11 */ be_nested_string("_archive", -290407892, 8),
- /* K12 */ be_nested_string("_error", 1132109656, 6),
+ /* K11 */ be_nested_str(_archive),
+ /* K12 */ be_nested_str(_error),
}),
- (be_nested_const_str("reset", 1695364032, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_reset,
+ &be_const_str_solidified,
( &(const binstruction[35]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xA40A0200, // 0001 IMPORT R2 K1
@@ -1175,7 +1175,7 @@ be_local_closure(reset, /* name */
/********************************************************************
** Solidified function: web_add_handler
********************************************************************/
-be_local_closure(web_add_handler, /* name */
+be_local_closure(Autoconf_web_add_handler, /* name */
be_nested_proto(
7, /* nstack */
1, /* argc */
@@ -1196,10 +1196,10 @@ be_local_closure(web_add_handler, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("page_autoconf_mgr", -651030265, 17),
+ /* K0 */ be_nested_str(page_autoconf_mgr),
}),
- (be_nested_const_str("", 607256038, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__X3Clambda_X3E,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x68000000, // 0000 GETUPV R0 U0
0x8C000100, // 0001 GETMET R0 R0 K0
@@ -1219,10 +1219,10 @@ be_local_closure(web_add_handler, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("page_autoconf_ctl", -1841585800, 17),
+ /* K0 */ be_nested_str(page_autoconf_ctl),
}),
- (be_nested_const_str("", 607256038, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__X3Clambda_X3E,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x68000000, // 0000 GETUPV R0 U0
0x8C000100, // 0001 GETMET R0 R0 K0
@@ -1233,14 +1233,14 @@ be_local_closure(web_add_handler, /* name */
}),
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("webserver", 1572454038, 9),
- /* K1 */ be_nested_string("on", 1630810064, 2),
- /* K2 */ be_nested_string("/ac", -390315318, 3),
- /* K3 */ be_nested_string("HTTP_GET", 1722467738, 8),
- /* K4 */ be_nested_string("HTTP_POST", 1999554144, 9),
+ /* K0 */ be_nested_str(webserver),
+ /* K1 */ be_nested_str(on),
+ /* K2 */ be_nested_str(_X2Fac),
+ /* K3 */ be_nested_str(HTTP_GET),
+ /* K4 */ be_nested_str(HTTP_POST),
}),
- (be_nested_const_str("web_add_handler", -304792334, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_web_add_handler,
+ &be_const_str_solidified,
( &(const binstruction[13]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x8C080301, // 0001 GETMET R2 R1 K1
@@ -1264,7 +1264,7 @@ be_local_closure(web_add_handler, /* name */
/********************************************************************
** Solidified function: clear_first_time
********************************************************************/
-be_local_closure(clear_first_time, /* name */
+be_local_closure(Autoconf_clear_first_time, /* name */
be_nested_proto(
5, /* nstack */
1, /* argc */
@@ -1275,12 +1275,12 @@ be_local_closure(clear_first_time, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("path", -2071507658, 4),
- /* K1 */ be_nested_string("remove", -611183107, 6),
- /* K2 */ be_nested_string("/.autoconf", -2082892903, 10),
+ /* K0 */ be_nested_str(path),
+ /* K1 */ be_nested_str(remove),
+ /* K2 */ be_nested_str(_X2F_X2Eautoconf),
}),
- (be_nested_const_str("clear_first_time", 632769909, 16)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear_first_time,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x8C080301, // 0001 GETMET R2 R1 K1
@@ -1296,7 +1296,7 @@ be_local_closure(clear_first_time, /* name */
/********************************************************************
** Solidified function: get_current_module_path
********************************************************************/
-be_local_closure(get_current_module_path, /* name */
+be_local_closure(Autoconf_get_current_module_path, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
@@ -1307,10 +1307,10 @@ be_local_closure(get_current_module_path, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("_archive", -290407892, 8),
+ /* K0 */ be_nested_str(_archive),
}),
- (be_nested_const_str("get_current_module_path", -1088293888, 23)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_current_module_path,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x80040200, // 0001 RET 1 R1
@@ -1328,26 +1328,26 @@ be_local_class(Autoconf,
NULL,
be_nested_map(18,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("page_autoconf_ctl", -1841585800, 17, -1), be_const_closure(page_autoconf_ctl_closure) },
- { be_nested_key("autoexec", -618105405, 8, -1), be_const_closure(autoexec_closure) },
- { be_nested_key("run_bat", -1758063998, 7, 6), be_const_closure(run_bat_closure) },
- { be_nested_key("page_autoconf_mgr", -651030265, 17, -1), be_const_closure(page_autoconf_mgr_closure) },
- { be_nested_key("get_current_module_name", -1915696556, 23, -1), be_const_closure(get_current_module_name_closure) },
- { be_nested_key("delete_all_configs", -1912899718, 18, 13), be_const_closure(delete_all_configs_closure) },
- { be_nested_key("set_first_time", -1183719746, 14, -1), be_const_closure(set_first_time_closure) },
- { be_nested_key("load_templates", -781097163, 14, -1), be_const_closure(load_templates_closure) },
- { be_nested_key("_archive", -290407892, 8, -1), be_const_var(0) },
- { be_nested_key("web_add_config_button", 639674325, 21, -1), be_const_closure(web_add_config_button_closure) },
- { be_nested_key("is_first_time", 275242384, 13, -1), be_const_closure(is_first_time_closure) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
- { be_nested_key("preinit", -1572960196, 7, 5), be_const_closure(preinit_closure) },
- { be_nested_key("reset", 1695364032, 5, 17), be_const_closure(reset_closure) },
- { be_nested_key("web_add_handler", -304792334, 15, 4), be_const_closure(web_add_handler_closure) },
- { be_nested_key("clear_first_time", 632769909, 16, 11), be_const_closure(clear_first_time_closure) },
- { be_nested_key("_error", 1132109656, 6, -1), be_const_var(1) },
- { be_nested_key("get_current_module_path", -1088293888, 23, -1), be_const_closure(get_current_module_path_closure) },
+ { be_const_key(page_autoconf_ctl, -1), be_const_closure(Autoconf_page_autoconf_ctl_closure) },
+ { be_const_key(autoexec, -1), be_const_closure(Autoconf_autoexec_closure) },
+ { be_const_key(run_bat, 17), be_const_closure(Autoconf_run_bat_closure) },
+ { be_const_key(page_autoconf_mgr, -1), be_const_closure(Autoconf_page_autoconf_mgr_closure) },
+ { be_const_key(get_current_module_path, 13), be_const_closure(Autoconf_get_current_module_path_closure) },
+ { be_const_key(preinit, -1), be_const_closure(Autoconf_preinit_closure) },
+ { be_const_key(clear_first_time, -1), be_const_closure(Autoconf_clear_first_time_closure) },
+ { be_const_key(load_templates, -1), be_const_closure(Autoconf_load_templates_closure) },
+ { be_const_key(_archive, -1), be_const_var(0) },
+ { be_const_key(web_add_config_button, -1), be_const_closure(Autoconf_web_add_config_button_closure) },
+ { be_const_key(is_first_time, -1), be_const_closure(Autoconf_is_first_time_closure) },
+ { be_const_key(web_add_handler, -1), be_const_closure(Autoconf_web_add_handler_closure) },
+ { be_const_key(delete_all_configs, 4), be_const_closure(Autoconf_delete_all_configs_closure) },
+ { be_const_key(reset, 5), be_const_closure(Autoconf_reset_closure) },
+ { be_const_key(get_current_module_name, 11), be_const_closure(Autoconf_get_current_module_name_closure) },
+ { be_const_key(init, 6), be_const_closure(Autoconf_init_closure) },
+ { be_const_key(_error, -1), be_const_var(1) },
+ { be_const_key(set_first_time, -1), be_const_closure(Autoconf_set_first_time_closure) },
})),
- (be_nested_const_str("Autoconf", 984011268, 8))
+ be_str_literal("Autoconf")
);
/********************************************************************
@@ -1366,8 +1366,8 @@ be_local_closure(_anonymous_, /* name */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_const_class(be_class_Autoconf),
}),
- (be_nested_const_str("_anonymous_", 1957281476, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__anonymous_,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x58040000, // 0000 LDCONST R1 K0
0xB4000000, // 0001 CLASS K0
@@ -1387,7 +1387,7 @@ be_local_module(autoconf,
"autoconf",
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(_anonymous__closure) },
+ { be_const_key(init, -1), be_const_closure(_anonymous__closure) },
}))
);
BE_EXPORT_VARIABLE be_define_const_native_module(autoconf);
diff --git a/lib/libesp32/Berry/default/be_display_lib.c b/lib/libesp32/Berry/default/be_display_lib.c
index 2d8bf9ff7..3943396fc 100644
--- a/lib/libesp32/Berry/default/be_display_lib.c
+++ b/lib/libesp32/Berry/default/be_display_lib.c
@@ -11,7 +11,7 @@
// Tasmota specific
-extern int be_disp_start(bvm *vm);
+extern int be_ntv_display_start(bvm *vm);
/********************************************************************
** Solidified module: display
@@ -20,7 +20,7 @@ be_local_module(display,
"display",
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("start", 1697318111, 5, -1), be_const_func(be_disp_start) },
+ { be_const_key(start, -1), be_const_func(be_ntv_display_start) },
}))
);
BE_EXPORT_VARIABLE be_define_const_native_module(display);
diff --git a/lib/libesp32/Berry/default/be_driverlib.c b/lib/libesp32/Berry/default/be_driverlib.c
index 13f1d211e..45a611382 100644
--- a/lib/libesp32/Berry/default/be_driverlib.c
+++ b/lib/libesp32/Berry/default/be_driverlib.c
@@ -9,7 +9,7 @@
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(Driver_init, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
@@ -20,8 +20,8 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
@@ -33,7 +33,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: get_tasmota
********************************************************************/
-be_local_closure(get_tasmota, /* name */
+be_local_closure(Driver_get_tasmota, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
@@ -44,10 +44,10 @@ be_local_closure(get_tasmota, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
+ /* K0 */ be_nested_str(tasmota),
}),
- (be_nested_const_str("get_tasmota", 334356779, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_tasmota,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x80040200, // 0001 RET 1 R1
@@ -60,7 +60,7 @@ be_local_closure(get_tasmota, /* name */
/********************************************************************
** Solidified function: add_cmd
********************************************************************/
-be_local_closure(add_cmd, /* name */
+be_local_closure(Driver_add_cmd, /* name */
be_nested_proto(
7, /* nstack */
3, /* argc */
@@ -82,8 +82,8 @@ be_local_closure(add_cmd, /* name */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
- (be_nested_const_str("", 607256038, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__X3Clambda_X3E,
+ &be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x68100000, // 0000 GETUPV R4 U0
0x68140001, // 0001 GETUPV R5 U1
@@ -98,11 +98,11 @@ be_local_closure(add_cmd, /* name */
}),
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
- /* K1 */ be_nested_string("add_cmd", -933336417, 7),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(add_cmd),
}),
- (be_nested_const_str("add_cmd", -933336417, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_add_cmd,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0xB80E0000, // 0000 GETNGBL R3 K0
0x8C0C0701, // 0001 GETMET R3 R3 K1
@@ -125,24 +125,24 @@ be_local_class(Driver,
NULL,
be_nested_map(16,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("web_add_main_button", -334599632, 19, 14), be_const_var(4) },
- { be_nested_key("web_add_console_button", -813531104, 22, -1), be_const_var(7) },
- { be_nested_key("web_add_management_button", -1556090110, 25, 8), be_const_var(5) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
- { be_nested_key("json_append", -1292948012, 11, -1), be_const_var(10) },
- { be_nested_key("web_add_config_button", 639674325, 21, 7), be_const_var(6) },
- { be_nested_key("every_100ms", 1546407804, 11, -1), be_const_var(1) },
- { be_nested_key("display", 1164572437, 7, -1), be_const_var(12) },
- { be_nested_key("web_add_button", -757092238, 14, 13), be_const_var(3) },
- { be_nested_key("every_second", 2075451465, 12, -1), be_const_var(0) },
- { be_nested_key("save_before_restart", 1253239338, 19, -1), be_const_var(8) },
- { be_nested_key("get_tasmota", 334356779, 11, -1), be_const_closure(get_tasmota_closure) },
- { be_nested_key("web_sensor", -1394870324, 10, 6), be_const_var(9) },
- { be_nested_key("web_add_handler", -304792334, 15, -1), be_const_var(2) },
- { be_nested_key("button_pressed", 1694209616, 14, 1), be_const_var(11) },
- { be_nested_key("add_cmd", -933336417, 7, -1), be_const_closure(add_cmd_closure) },
+ { be_const_key(web_add_main_button, 14), be_const_var(4) },
+ { be_const_key(web_add_console_button, -1), be_const_var(7) },
+ { be_const_key(web_add_management_button, 8), be_const_var(5) },
+ { be_const_key(init, -1), be_const_closure(Driver_init_closure) },
+ { be_const_key(json_append, -1), be_const_var(10) },
+ { be_const_key(web_add_config_button, 7), be_const_var(6) },
+ { be_const_key(every_100ms, -1), be_const_var(1) },
+ { be_const_key(display, -1), be_const_var(12) },
+ { be_const_key(web_add_button, 13), be_const_var(3) },
+ { be_const_key(every_second, -1), be_const_var(0) },
+ { be_const_key(save_before_restart, -1), be_const_var(8) },
+ { be_const_key(get_tasmota, -1), be_const_closure(Driver_get_tasmota_closure) },
+ { be_const_key(web_sensor, 6), be_const_var(9) },
+ { be_const_key(web_add_handler, -1), be_const_var(2) },
+ { be_const_key(button_pressed, 1), be_const_var(11) },
+ { be_const_key(add_cmd, -1), be_const_closure(Driver_add_cmd_closure) },
})),
- (be_nested_const_str("Driver", -718580993, 6))
+ be_str_literal("Driver")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_energylib.c b/lib/libesp32/Berry/default/be_energylib.c
index e115a8507..cbdddbfca 100644
--- a/lib/libesp32/Berry/default/be_energylib.c
+++ b/lib/libesp32/Berry/default/be_energylib.c
@@ -12,32 +12,127 @@
extern struct ENERGY Energy;
/*
+_energy = nil # avoid compilation error
+energy = module("energy")
+energy._ptr = nil
+
def init(m)
import global
global._energy = energy_struct(m._ptr)
return m
end
+energy.init = init
def read()
return _energy.tomap()
end
+energy.read = read
def member(k)
return _energy.(k)
end
+energy.member = member
def setmember(k, v)
_energy.(k) = v
end
+energy.setmember = setmember
import solidify
-solidify.dump(m.init)
+solidify.dump(energy)
*/
+
+/********************************************************************
+** Solidified function: member
+********************************************************************/
+be_local_closure(energy_member, /* name */
+ be_nested_proto(
+ 2, /* nstack */
+ 1, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 1]) { /* constants */
+ /* K0 */ be_nested_str(_energy),
+ }),
+ &be_const_str_member,
+ &be_const_str_solidified,
+ ( &(const binstruction[ 3]) { /* code */
+ 0xB8060000, // 0000 GETNGBL R1 K0
+ 0x88040200, // 0001 GETMBR R1 R1 R0
+ 0x80040200, // 0002 RET 1 R1
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: setmember
+********************************************************************/
+be_local_closure(energy_setmember, /* name */
+ be_nested_proto(
+ 3, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 1]) { /* constants */
+ /* K0 */ be_nested_str(_energy),
+ }),
+ &be_const_str_setmember,
+ &be_const_str_solidified,
+ ( &(const binstruction[ 3]) { /* code */
+ 0xB80A0000, // 0000 GETNGBL R2 K0
+ 0x90080001, // 0001 SETMBR R2 R0 R1
+ 0x80000000, // 0002 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: read
+********************************************************************/
+be_local_closure(energy_read, /* name */
+ be_nested_proto(
+ 2, /* nstack */
+ 0, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 2]) { /* constants */
+ /* K0 */ be_nested_str(_energy),
+ /* K1 */ be_nested_str(tomap),
+ }),
+ &be_const_str_read,
+ &be_const_str_solidified,
+ ( &(const binstruction[ 4]) { /* code */
+ 0xB8020000, // 0000 GETNGBL R0 K0
+ 0x8C000101, // 0001 GETMET R0 R0 K1
+ 0x7C000200, // 0002 CALL R0 1
+ 0x80040000, // 0003 RET 1 R0
+ })
+ )
+);
+/*******************************************************************/
+
+
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(energy_init, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -48,13 +143,13 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_string("global", 503252654, 6),
- /* K1 */ be_nested_string("_energy", 535372070, 7),
- /* K2 */ be_nested_string("energy_struct", 1655792843, 13),
- /* K3 */ be_nested_string("_ptr", 306235816, 4),
+ /* K0 */ be_nested_str(global),
+ /* K1 */ be_nested_str(_energy),
+ /* K2 */ be_nested_str(energy_struct),
+ /* K3 */ be_nested_str(_ptr),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xB80A0400, // 0001 GETNGBL R2 K2
@@ -69,100 +164,23 @@ be_local_closure(init, /* name */
/********************************************************************
-** Solidified function: read
+** Solidified module: energy
********************************************************************/
-be_local_closure(read, /* name */
- be_nested_proto(
- 2, /* nstack */
- 0, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("_energy", 535372070, 7),
- /* K1 */ be_nested_string("tomap", 612167626, 5),
- }),
- (be_nested_const_str("", 1160973142, 11)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[ 4]) { /* code */
- 0xB8020000, // 0000 GETNGBL R0 K0
- 0x8C000101, // 0001 GETMET R0 R0 K1
- 0x7C000200, // 0002 CALL R0 1
- 0x80040000, // 0003 RET 1 R0
- })
- )
+be_local_module(energy,
+ "energy",
+ be_nested_map(5,
+ ( (struct bmapnode*) &(const bmapnode[]) {
+ { be_const_key(init, -1), be_const_closure(energy_init_closure) },
+ { be_const_key(member, 2), be_const_closure(energy_member_closure) },
+ { be_const_key(_ptr, 3), be_const_comptr(&Energy) },
+ { be_const_key(setmember, -1), be_const_closure(energy_setmember_closure) },
+ { be_const_key(read, -1), be_const_closure(energy_read_closure) },
+ }))
);
-/*******************************************************************/
-
-/********************************************************************
-** Solidified function: member
-********************************************************************/
-be_local_closure(member, /* name */
- be_nested_proto(
- 2, /* nstack */
- 1, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("_energy", 535372070, 7),
- }),
- (be_nested_const_str("member", 719708611, 6)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[ 3]) { /* code */
- 0xB8060000, // 0000 GETNGBL R1 K0
- 0x88040200, // 0001 GETMBR R1 R1 R0
- 0x80040200, // 0002 RET 1 R1
- })
- )
-);
-/*******************************************************************/
+BE_EXPORT_VARIABLE be_define_const_native_module(energy);
+/********************************************************************/
-/********************************************************************
-** Solidified function: setmember
-********************************************************************/
-be_local_closure(setmember, /* name */
- be_nested_proto(
- 3, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("_energy", 535372070, 7),
- }),
- (be_nested_const_str("setmember", 1432909441, 9)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[ 3]) { /* code */
- 0xB80A0000, // 0000 GETNGBL R2 K0
- 0x90080001, // 0001 SETMBR R2 R0 R1
- 0x80000000, // 0002 RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/* @const_object_info_begin
-module energy (scope: global) {
- _ptr, comptr(&Energy)
- init, closure(init_closure)
-
- read, closure(read_closure)
- member, closure(member_closure)
- setmember, closure(setmember_closure)
-}
-@const_object_info_end */
-#include "../generate/be_fixed_energy.h"
+// { be_const_key(_ptr, 3), be_const_comptr(&Energy) }, /* patch */
#endif // USE_ENERGY_SENSOR
\ No newline at end of file
diff --git a/lib/libesp32/Berry/default/be_i2c_axp192_lib.c b/lib/libesp32/Berry/default/be_i2c_axp192_lib.c
index 7449780d6..4f9f02307 100644
--- a/lib/libesp32/Berry/default/be_i2c_axp192_lib.c
+++ b/lib/libesp32/Berry/default/be_i2c_axp192_lib.c
@@ -6,7 +6,7 @@
/********************************************************************
** Solidified function: get_warning_level
********************************************************************/
-be_local_closure(get_warning_level, /* name */
+be_local_closure(AXP192_get_warning_level, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -17,11 +17,11 @@ be_local_closure(get_warning_level, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read12", -3890326, 6),
+ /* K0 */ be_nested_str(read12),
/* K1 */ be_const_int(1),
}),
- (be_nested_const_str("get_warning_level", 1737834441, 17)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_warning_level,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0046, // 0001 LDINT R3 71
@@ -37,7 +37,7 @@ be_local_closure(get_warning_level, /* name */
/********************************************************************
** Solidified function: get_vbus_current
********************************************************************/
-be_local_closure(get_vbus_current, /* name */
+be_local_closure(AXP192_get_vbus_current, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -48,11 +48,11 @@ be_local_closure(get_vbus_current, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read12", -3890326, 6),
+ /* K0 */ be_nested_str(read12),
/* K1 */ be_const_real_hex(0x3EC00000),
}),
- (be_nested_const_str("get_vbus_current", 1205347942, 16)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_vbus_current,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E005B, // 0001 LDINT R3 92
@@ -68,7 +68,7 @@ be_local_closure(get_vbus_current, /* name */
/********************************************************************
** Solidified function: set_chg_current
********************************************************************/
-be_local_closure(set_chg_current, /* name */
+be_local_closure(AXP192_set_chg_current, /* name */
be_nested_proto(
8, /* nstack */
2, /* argc */
@@ -79,11 +79,11 @@ be_local_closure(set_chg_current, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("write8", -1160975764, 6),
- /* K1 */ be_nested_string("read8", -1492179129, 5),
+ /* K0 */ be_nested_str(write8),
+ /* K1 */ be_nested_str(read8),
}),
- (be_nested_const_str("set_chg_current", 336304386, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_chg_current,
+ &be_const_str_solidified,
( &(const binstruction[12]) { /* code */
0x8C080100, // 0000 GETMET R2 R0 K0
0x54120032, // 0001 LDINT R4 51
@@ -106,7 +106,7 @@ be_local_closure(set_chg_current, /* name */
/********************************************************************
** Solidified function: get_bat_current
********************************************************************/
-be_local_closure(get_bat_current, /* name */
+be_local_closure(AXP192_get_bat_current, /* name */
be_nested_proto(
5, /* nstack */
1, /* argc */
@@ -117,11 +117,11 @@ be_local_closure(get_bat_current, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read13", 12887293, 6),
+ /* K0 */ be_nested_str(read13),
/* K1 */ be_const_real_hex(0x3F000000),
}),
- (be_nested_const_str("get_bat_current", 1912106073, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_bat_current,
+ &be_const_str_solidified,
( &(const binstruction[ 9]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0079, // 0001 LDINT R3 122
@@ -141,7 +141,7 @@ be_local_closure(get_bat_current, /* name */
/********************************************************************
** Solidified function: get_bat_power
********************************************************************/
-be_local_closure(get_bat_power, /* name */
+be_local_closure(AXP192_get_bat_power, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -152,11 +152,11 @@ be_local_closure(get_bat_power, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read24", 1808533811, 6),
+ /* K0 */ be_nested_str(read24),
/* K1 */ be_const_real_hex(0x3A102DE1),
}),
- (be_nested_const_str("get_bat_power", -1227592443, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_bat_power,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E006F, // 0001 LDINT R3 112
@@ -172,7 +172,7 @@ be_local_closure(get_bat_power, /* name */
/********************************************************************
** Solidified function: json_append
********************************************************************/
-be_local_closure(json_append, /* name */
+be_local_closure(AXP192_json_append, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
@@ -183,10 +183,10 @@ be_local_closure(json_append, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
+ /* K0 */ be_nested_str(wire),
}),
- (be_nested_const_str("json_append", -1292948012, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_json_append,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x74060001, // 0001 JMPT R1 #0004
@@ -202,7 +202,7 @@ be_local_closure(json_append, /* name */
/********************************************************************
** Solidified function: get_vbus_voltage
********************************************************************/
-be_local_closure(get_vbus_voltage, /* name */
+be_local_closure(AXP192_get_vbus_voltage, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -213,11 +213,11 @@ be_local_closure(get_vbus_voltage, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read12", -3890326, 6),
+ /* K0 */ be_nested_str(read12),
/* K1 */ be_const_real_hex(0x3ADED28A),
}),
- (be_nested_const_str("get_vbus_voltage", -1896756895, 16)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_vbus_voltage,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0059, // 0001 LDINT R3 90
@@ -233,7 +233,7 @@ be_local_closure(get_vbus_voltage, /* name */
/********************************************************************
** Solidified function: get_temp
********************************************************************/
-be_local_closure(get_temp, /* name */
+be_local_closure(AXP192_get_temp, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -244,12 +244,12 @@ be_local_closure(get_temp, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("read12", -3890326, 6),
+ /* K0 */ be_nested_str(read12),
/* K1 */ be_const_real_hex(0x3DCCCCCD),
/* K2 */ be_const_real_hex(0x4310B333),
}),
- (be_nested_const_str("get_temp", -924047810, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_temp,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E005D, // 0001 LDINT R3 94
@@ -266,7 +266,7 @@ be_local_closure(get_temp, /* name */
/********************************************************************
** Solidified function: battery_present
********************************************************************/
-be_local_closure(battery_present, /* name */
+be_local_closure(AXP192_battery_present, /* name */
be_nested_proto(
6, /* nstack */
1, /* argc */
@@ -277,13 +277,13 @@ be_local_closure(battery_present, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read", -824204347, 4),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(1),
}),
- (be_nested_const_str("battery_present", -706570238, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_battery_present,
+ &be_const_str_solidified,
( &(const binstruction[15]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -309,7 +309,7 @@ be_local_closure(battery_present, /* name */
/********************************************************************
** Solidified function: get_aps_voltage
********************************************************************/
-be_local_closure(get_aps_voltage, /* name */
+be_local_closure(AXP192_get_aps_voltage, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -320,11 +320,11 @@ be_local_closure(get_aps_voltage, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read12", -3890326, 6),
+ /* K0 */ be_nested_str(read12),
/* K1 */ be_const_real_hex(0x3AB78035),
}),
- (be_nested_const_str("get_aps_voltage", -2001930861, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_aps_voltage,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E007D, // 0001 LDINT R3 126
@@ -340,7 +340,7 @@ be_local_closure(get_aps_voltage, /* name */
/********************************************************************
** Solidified function: set_dcdc_enable
********************************************************************/
-be_local_closure(set_dcdc_enable, /* name */
+be_local_closure(AXP192_set_dcdc_enable, /* name */
be_nested_proto(
8, /* nstack */
3, /* argc */
@@ -352,13 +352,13 @@ be_local_closure(set_dcdc_enable, /* name */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
/* K0 */ be_const_int(1),
- /* K1 */ be_nested_string("write_bit", -1633976860, 9),
+ /* K1 */ be_nested_str(write_bit),
/* K2 */ be_const_int(0),
/* K3 */ be_const_int(2),
/* K4 */ be_const_int(3),
}),
- (be_nested_const_str("set_dcdc_enable", 1594690786, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_dcdc_enable,
+ &be_const_str_solidified,
( &(const binstruction[22]) { /* code */
0x1C0C0300, // 0000 EQ R3 R1 K0
0x780E0004, // 0001 JMPF R3 #0007
@@ -391,7 +391,7 @@ be_local_closure(set_dcdc_enable, /* name */
/********************************************************************
** Solidified function: set_ldo_voltage
********************************************************************/
-be_local_closure(set_ldo_voltage, /* name */
+be_local_closure(AXP192_set_ldo_voltage, /* name */
be_nested_proto(
9, /* nstack */
3, /* argc */
@@ -403,12 +403,12 @@ be_local_closure(set_ldo_voltage, /* name */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_const_int(2),
- /* K1 */ be_nested_string("write8", -1160975764, 6),
- /* K2 */ be_nested_string("read8", -1492179129, 5),
+ /* K1 */ be_nested_str(write8),
+ /* K2 */ be_nested_str(read8),
/* K3 */ be_const_int(3),
}),
- (be_nested_const_str("set_ldo_voltage", -204466136, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_ldo_voltage,
+ &be_const_str_solidified,
( &(const binstruction[39]) { /* code */
0x540E0CE3, // 0000 LDINT R3 3300
0x240C0403, // 0001 GT R3 R2 R3
@@ -458,7 +458,7 @@ be_local_closure(set_ldo_voltage, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(AXP192_init, /* name */
be_nested_proto(
5, /* nstack */
1, /* argc */
@@ -469,12 +469,12 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("I2C_Driver", 1714501658, 10),
- /* K1 */ be_nested_string("init", 380752755, 4),
- /* K2 */ be_nested_string("AXP192", 757230128, 6),
+ /* K0 */ be_nested_str(I2C_Driver),
+ /* K1 */ be_nested_str(init),
+ /* K2 */ be_nested_str(AXP192),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 9]) { /* code */
0x60040003, // 0000 GETGBL R1 G3
0x5C080000, // 0001 MOVE R2 R0
@@ -494,7 +494,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: get_bat_voltage
********************************************************************/
-be_local_closure(get_bat_voltage, /* name */
+be_local_closure(AXP192_get_bat_voltage, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -505,11 +505,11 @@ be_local_closure(get_bat_voltage, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read12", -3890326, 6),
+ /* K0 */ be_nested_str(read12),
/* K1 */ be_const_real_hex(0x3A902DE0),
}),
- (be_nested_const_str("get_bat_voltage", 706676538, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_bat_voltage,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0077, // 0001 LDINT R3 120
@@ -525,7 +525,7 @@ be_local_closure(get_bat_voltage, /* name */
/********************************************************************
** Solidified function: set_ldo_enable
********************************************************************/
-be_local_closure(set_ldo_enable, /* name */
+be_local_closure(AXP192_set_ldo_enable, /* name */
be_nested_proto(
8, /* nstack */
3, /* argc */
@@ -537,11 +537,11 @@ be_local_closure(set_ldo_enable, /* name */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_const_int(2),
- /* K1 */ be_nested_string("write_bit", -1633976860, 9),
+ /* K1 */ be_nested_str(write_bit),
/* K2 */ be_const_int(3),
}),
- (be_nested_const_str("set_ldo_enable", -1378465255, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_ldo_enable,
+ &be_const_str_solidified,
( &(const binstruction[15]) { /* code */
0x1C0C0300, // 0000 EQ R3 R1 K0
0x780E0004, // 0001 JMPF R3 #0007
@@ -567,7 +567,7 @@ be_local_closure(set_ldo_enable, /* name */
/********************************************************************
** Solidified function: set_dc_voltage
********************************************************************/
-be_local_closure(set_dc_voltage, /* name */
+be_local_closure(AXP192_set_dc_voltage, /* name */
be_nested_proto(
11, /* nstack */
3, /* argc */
@@ -582,11 +582,11 @@ be_local_closure(set_dc_voltage, /* name */
/* K1 */ be_const_int(3),
/* K2 */ be_const_int(0),
/* K3 */ be_const_int(2),
- /* K4 */ be_nested_string("write8", -1160975764, 6),
- /* K5 */ be_nested_string("read8", -1492179129, 5),
+ /* K4 */ be_nested_str(write8),
+ /* K5 */ be_nested_str(read8),
}),
- (be_nested_const_str("set_dc_voltage", -2112985360, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_dc_voltage,
+ &be_const_str_solidified,
( &(const binstruction[48]) { /* code */
0x140C0300, // 0000 LT R3 R1 K0
0x740E0001, // 0001 JMPT R3 #0004
@@ -645,7 +645,7 @@ be_local_closure(set_dc_voltage, /* name */
/********************************************************************
** Solidified function: write_gpio
********************************************************************/
-be_local_closure(write_gpio, /* name */
+be_local_closure(AXP192_write_gpio, /* name */
be_nested_proto(
8, /* nstack */
3, /* argc */
@@ -658,11 +658,11 @@ be_local_closure(write_gpio, /* name */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_const_int(0),
/* K1 */ be_const_int(2),
- /* K2 */ be_nested_string("write_bit", -1633976860, 9),
+ /* K2 */ be_nested_str(write_bit),
/* K3 */ be_const_int(3),
}),
- (be_nested_const_str("write_gpio", -2027026962, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_write_gpio,
+ &be_const_str_solidified,
( &(const binstruction[21]) { /* code */
0x280C0300, // 0000 GE R3 R1 K0
0x780E0007, // 0001 JMPF R3 #000A
@@ -694,7 +694,7 @@ be_local_closure(write_gpio, /* name */
/********************************************************************
** Solidified function: web_sensor
********************************************************************/
-be_local_closure(web_sensor, /* name */
+be_local_closure(AXP192_web_sensor, /* name */
be_nested_proto(
11, /* nstack */
1, /* argc */
@@ -705,23 +705,23 @@ be_local_closure(web_sensor, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[14]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("string", 398550328, 6),
- /* K2 */ be_nested_string("format", -1180859054, 6),
- /* K3 */ be_nested_string("{s}VBus Voltage{m}%.3f V{e}", 165651270, 27),
- /* K4 */ be_nested_string("{s}VBus Current{m}%.1f mA{e}", 1032721155, 28),
- /* K5 */ be_nested_string("{s}Batt Voltage{m}%.3f V{e}", -1110659097, 27),
- /* K6 */ be_nested_string("{s}Batt Current{m}%.1f mA{e}", 866537156, 28),
- /* K7 */ be_nested_string("{s}Temp AXP{m}%.1f °C{e}", -1990510004, 25),
- /* K8 */ be_nested_string("get_vbus_voltage", -1896756895, 16),
- /* K9 */ be_nested_string("get_bat_voltage", 706676538, 15),
- /* K10 */ be_nested_string("get_bat_current", 1912106073, 15),
- /* K11 */ be_nested_string("get_temp", -924047810, 8),
- /* K12 */ be_nested_string("tasmota", 424643812, 7),
- /* K13 */ be_nested_string("web_send_decimal", 1407210204, 16),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(string),
+ /* K2 */ be_nested_str(format),
+ /* K3 */ be_nested_str(_X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D),
+ /* K4 */ be_nested_str(_X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D),
+ /* K5 */ be_nested_str(_X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D),
+ /* K6 */ be_nested_str(_X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D),
+ /* K7 */ be_nested_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_XB0C_X7Be_X7D),
+ /* K8 */ be_nested_str(get_vbus_voltage),
+ /* K9 */ be_nested_str(get_bat_voltage),
+ /* K10 */ be_nested_str(get_bat_current),
+ /* K11 */ be_nested_str(get_temp),
+ /* K12 */ be_nested_str(tasmota),
+ /* K13 */ be_nested_str(web_send_decimal),
}),
- (be_nested_const_str("web_sensor", -1394870324, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_web_sensor,
+ &be_const_str_solidified,
( &(const binstruction[26]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x74060001, // 0001 JMPT R1 #0004
@@ -758,7 +758,7 @@ be_local_closure(web_sensor, /* name */
/********************************************************************
** Solidified function: get_bat_charge_current
********************************************************************/
-be_local_closure(get_bat_charge_current, /* name */
+be_local_closure(AXP192_get_bat_charge_current, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -769,11 +769,11 @@ be_local_closure(get_bat_charge_current, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("read13", 12887293, 6),
+ /* K0 */ be_nested_str(read13),
/* K1 */ be_const_real_hex(0x3F000000),
}),
- (be_nested_const_str("get_bat_charge_current", 1385293050, 22)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_bat_charge_current,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0079, // 0001 LDINT R3 122
@@ -789,7 +789,7 @@ be_local_closure(get_bat_charge_current, /* name */
/********************************************************************
** Solidified function: get_battery_chargin_status
********************************************************************/
-be_local_closure(get_battery_chargin_status, /* name */
+be_local_closure(AXP192_get_battery_chargin_status, /* name */
be_nested_proto(
6, /* nstack */
1, /* argc */
@@ -800,13 +800,13 @@ be_local_closure(get_battery_chargin_status, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read", -824204347, 4),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(1),
}),
- (be_nested_const_str("get_battery_chargin_status", -2061725725, 26)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_battery_chargin_status,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -824,7 +824,7 @@ be_local_closure(get_battery_chargin_status, /* name */
/********************************************************************
** Solidified function: get_input_power_status
********************************************************************/
-be_local_closure(get_input_power_status, /* name */
+be_local_closure(AXP192_get_input_power_status, /* name */
be_nested_proto(
6, /* nstack */
1, /* argc */
@@ -835,14 +835,14 @@ be_local_closure(get_input_power_status, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read", -824204347, 4),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(0),
/* K4 */ be_const_int(1),
}),
- (be_nested_const_str("get_input_power_status", -192138119, 22)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_input_power_status,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -866,29 +866,29 @@ be_local_class(AXP192,
&be_class_I2C_Driver,
be_nested_map(21,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("get_warning_level", 1737834441, 17, -1), be_const_closure(get_warning_level_closure) },
- { be_nested_key("get_vbus_current", 1205347942, 16, -1), be_const_closure(get_vbus_current_closure) },
- { be_nested_key("set_chg_current", 336304386, 15, 14), be_const_closure(set_chg_current_closure) },
- { be_nested_key("get_bat_current", 1912106073, 15, -1), be_const_closure(get_bat_current_closure) },
- { be_nested_key("get_bat_power", -1227592443, 13, 9), be_const_closure(get_bat_power_closure) },
- { be_nested_key("json_append", -1292948012, 11, -1), be_const_closure(json_append_closure) },
- { be_nested_key("get_vbus_voltage", -1896756895, 16, -1), be_const_closure(get_vbus_voltage_closure) },
- { be_nested_key("get_temp", -924047810, 8, -1), be_const_closure(get_temp_closure) },
- { be_nested_key("battery_present", -706570238, 15, -1), be_const_closure(battery_present_closure) },
- { be_nested_key("get_aps_voltage", -2001930861, 15, -1), be_const_closure(get_aps_voltage_closure) },
- { be_nested_key("set_dcdc_enable", 1594690786, 15, -1), be_const_closure(set_dcdc_enable_closure) },
- { be_nested_key("set_ldo_voltage", -204466136, 15, 7), be_const_closure(set_ldo_voltage_closure) },
- { be_nested_key("init", 380752755, 4, 2), be_const_closure(init_closure) },
- { be_nested_key("get_bat_voltage", 706676538, 15, 18), be_const_closure(get_bat_voltage_closure) },
- { be_nested_key("set_ldo_enable", -1378465255, 14, -1), be_const_closure(set_ldo_enable_closure) },
- { be_nested_key("set_dc_voltage", -2112985360, 14, 13), be_const_closure(set_dc_voltage_closure) },
- { be_nested_key("write_gpio", -2027026962, 10, -1), be_const_closure(write_gpio_closure) },
- { be_nested_key("web_sensor", -1394870324, 10, -1), be_const_closure(web_sensor_closure) },
- { be_nested_key("get_bat_charge_current", 1385293050, 22, 19), be_const_closure(get_bat_charge_current_closure) },
- { be_nested_key("get_battery_chargin_status", -2061725725, 26, -1), be_const_closure(get_battery_chargin_status_closure) },
- { be_nested_key("get_input_power_status", -192138119, 22, -1), be_const_closure(get_input_power_status_closure) },
+ { be_const_key(get_warning_level, -1), be_const_closure(AXP192_get_warning_level_closure) },
+ { be_const_key(get_vbus_current, -1), be_const_closure(AXP192_get_vbus_current_closure) },
+ { be_const_key(get_aps_voltage, -1), be_const_closure(AXP192_get_aps_voltage_closure) },
+ { be_const_key(get_bat_current, -1), be_const_closure(AXP192_get_bat_current_closure) },
+ { be_const_key(get_bat_power, 2), be_const_closure(AXP192_get_bat_power_closure) },
+ { be_const_key(json_append, -1), be_const_closure(AXP192_json_append_closure) },
+ { be_const_key(get_vbus_voltage, -1), be_const_closure(AXP192_get_vbus_voltage_closure) },
+ { be_const_key(get_battery_chargin_status, 9), be_const_closure(AXP192_get_battery_chargin_status_closure) },
+ { be_const_key(battery_present, -1), be_const_closure(AXP192_battery_present_closure) },
+ { be_const_key(get_bat_charge_current, 14), be_const_closure(AXP192_get_bat_charge_current_closure) },
+ { be_const_key(set_dcdc_enable, -1), be_const_closure(AXP192_set_dcdc_enable_closure) },
+ { be_const_key(get_temp, 19), be_const_closure(AXP192_get_temp_closure) },
+ { be_const_key(set_chg_current, 13), be_const_closure(AXP192_set_chg_current_closure) },
+ { be_const_key(set_ldo_enable, 18), be_const_closure(AXP192_set_ldo_enable_closure) },
+ { be_const_key(set_dc_voltage, -1), be_const_closure(AXP192_set_dc_voltage_closure) },
+ { be_const_key(get_bat_voltage, 7), be_const_closure(AXP192_get_bat_voltage_closure) },
+ { be_const_key(write_gpio, -1), be_const_closure(AXP192_write_gpio_closure) },
+ { be_const_key(web_sensor, -1), be_const_closure(AXP192_web_sensor_closure) },
+ { be_const_key(init, -1), be_const_closure(AXP192_init_closure) },
+ { be_const_key(set_ldo_voltage, -1), be_const_closure(AXP192_set_ldo_voltage_closure) },
+ { be_const_key(get_input_power_status, -1), be_const_closure(AXP192_get_input_power_status_closure) },
})),
- (be_nested_const_str("AXP192", 757230128, 6))
+ be_str_literal("AXP192")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_i2c_driverlib.c b/lib/libesp32/Berry/default/be_i2c_driverlib.c
index f1cedfe8b..45f829e19 100644
--- a/lib/libesp32/Berry/default/be_i2c_driverlib.c
+++ b/lib/libesp32/Berry/default/be_i2c_driverlib.c
@@ -9,12 +9,10 @@
*******************************************************************/
#include "be_constobj.h"
-extern bclass* be_class_Driver; // Parent class
-
/********************************************************************
** Solidified function: read32
********************************************************************/
-be_local_closure(read32, /* name */
+be_local_closure(I2C_Driver_read32, /* name */
be_nested_proto(
7, /* nstack */
2, /* argc */
@@ -25,16 +23,16 @@ be_local_closure(read32, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read_bytes", -718234123, 10),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read_bytes),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(0),
/* K4 */ be_const_int(1),
/* K5 */ be_const_int(2),
/* K6 */ be_const_int(3),
}),
- (be_nested_const_str("read32", 1741276240, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_read32,
+ &be_const_str_solidified,
( &(const binstruction[20]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -65,7 +63,7 @@ be_local_closure(read32, /* name */
/********************************************************************
** Solidified function: write8
********************************************************************/
-be_local_closure(write8, /* name */
+be_local_closure(I2C_Driver_write8, /* name */
be_nested_proto(
9, /* nstack */
3, /* argc */
@@ -76,13 +74,13 @@ be_local_closure(write8, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("write", -1104765092, 5),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(write),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(1),
}),
- (be_nested_const_str("write8", -1160975764, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_write8,
+ &be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x880C0100, // 0000 GETMBR R3 R0 K0
0x8C0C0701, // 0001 GETMET R3 R3 K1
@@ -101,7 +99,7 @@ be_local_closure(write8, /* name */
/********************************************************************
** Solidified function: read12
********************************************************************/
-be_local_closure(read12, /* name */
+be_local_closure(I2C_Driver_read12, /* name */
be_nested_proto(
7, /* nstack */
2, /* argc */
@@ -112,15 +110,15 @@ be_local_closure(read12, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read_bytes", -718234123, 10),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read_bytes),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(2),
/* K4 */ be_const_int(0),
/* K5 */ be_const_int(1),
}),
- (be_nested_const_str("read12", -3890326, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_read12,
+ &be_const_str_solidified,
( &(const binstruction[12]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -143,7 +141,7 @@ be_local_closure(read12, /* name */
/********************************************************************
** Solidified function: write_bit
********************************************************************/
-be_local_closure(write_bit, /* name */
+be_local_closure(I2C_Driver_write_bit, /* name */
be_nested_proto(
11, /* nstack */
4, /* argc */
@@ -156,11 +154,11 @@ be_local_closure(write_bit, /* name */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_const_int(0),
/* K1 */ be_const_int(1),
- /* K2 */ be_nested_string("write8", -1160975764, 6),
- /* K3 */ be_nested_string("read8", -1492179129, 5),
+ /* K2 */ be_nested_str(write8),
+ /* K3 */ be_nested_str(read8),
}),
- (be_nested_const_str("write_bit", -1633976860, 9)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_write_bit,
+ &be_const_str_solidified,
( &(const binstruction[26]) { /* code */
0x14100500, // 0000 LT R4 R2 K0
0x74120002, // 0001 JMPT R4 #0005
@@ -197,7 +195,7 @@ be_local_closure(write_bit, /* name */
/********************************************************************
** Solidified function: read24
********************************************************************/
-be_local_closure(read24, /* name */
+be_local_closure(I2C_Driver_read24, /* name */
be_nested_proto(
7, /* nstack */
2, /* argc */
@@ -208,16 +206,16 @@ be_local_closure(read24, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read_bytes", -718234123, 10),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read_bytes),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(3),
/* K4 */ be_const_int(0),
/* K5 */ be_const_int(1),
/* K6 */ be_const_int(2),
}),
- (be_nested_const_str("read24", 1808533811, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_read24,
+ &be_const_str_solidified,
( &(const binstruction[16]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -244,7 +242,7 @@ be_local_closure(read24, /* name */
/********************************************************************
** Solidified function: read8
********************************************************************/
-be_local_closure(read8, /* name */
+be_local_closure(I2C_Driver_read8, /* name */
be_nested_proto(
7, /* nstack */
2, /* argc */
@@ -255,13 +253,13 @@ be_local_closure(read8, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read", -824204347, 4),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(1),
}),
- (be_nested_const_str("read8", -1492179129, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_read8,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -279,7 +277,7 @@ be_local_closure(read8, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(I2C_Driver_init, /* name */
be_nested_proto(
10, /* nstack */
4, /* argc */
@@ -290,19 +288,19 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_string("get_tasmota", 334356779, 11),
- /* K1 */ be_nested_string("i2c_enabled", 218388101, 11),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
- /* K3 */ be_nested_string("wire", -212213352, 4),
- /* K4 */ be_nested_string("wire_scan", -1623691416, 9),
- /* K5 */ be_nested_string("function", -1630125495, 8),
- /* K6 */ be_nested_string("name", -1925595674, 4),
- /* K7 */ be_nested_string("I2C:", 813483371, 4),
- /* K8 */ be_nested_string("detected on bus", 1432002650, 15),
- /* K9 */ be_nested_string("bus", 1607822841, 3),
+ /* K0 */ be_nested_str(get_tasmota),
+ /* K1 */ be_nested_str(i2c_enabled),
+ /* K2 */ be_nested_str(addr),
+ /* K3 */ be_nested_str(wire),
+ /* K4 */ be_nested_str(wire_scan),
+ /* K5 */ be_nested_str(function),
+ /* K6 */ be_nested_str(name),
+ /* K7 */ be_nested_str(I2C_X3A),
+ /* K8 */ be_nested_str(detected_X20on_X20bus),
+ /* K9 */ be_nested_str(bus),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[44]) { /* code */
0x8C100100, // 0000 GETMET R4 R0 K0
0x7C100200, // 0001 CALL R4 1
@@ -357,7 +355,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: read13
********************************************************************/
-be_local_closure(read13, /* name */
+be_local_closure(I2C_Driver_read13, /* name */
be_nested_proto(
7, /* nstack */
2, /* argc */
@@ -368,15 +366,15 @@ be_local_closure(read13, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_string("wire", -212213352, 4),
- /* K1 */ be_nested_string("read_bytes", -718234123, 10),
- /* K2 */ be_nested_string("addr", 1087856498, 4),
+ /* K0 */ be_nested_str(wire),
+ /* K1 */ be_nested_str(read_bytes),
+ /* K2 */ be_nested_str(addr),
/* K3 */ be_const_int(2),
/* K4 */ be_const_int(0),
/* K5 */ be_const_int(1),
}),
- (be_nested_const_str("read13", 12887293, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_read13,
+ &be_const_str_solidified,
( &(const binstruction[12]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -395,27 +393,33 @@ be_local_closure(read13, /* name */
);
/*******************************************************************/
-#include "../generate/be_fixed_be_class_I2C_Driver.h"
-void be_load_driver_i2c_lib(bvm *vm) {
+/********************************************************************
+** Solidified class: I2C_Driver
+********************************************************************/
+be_local_class(I2C_Driver,
+ 3,
+ NULL,
+ be_nested_map(11,
+ ( (struct bmapnode*) &(const bmapnode[]) {
+ { be_const_key(read32, -1), be_const_closure(I2C_Driver_read32_closure) },
+ { be_const_key(write8, 6), be_const_closure(I2C_Driver_write8_closure) },
+ { be_const_key(name, -1), be_const_var(2) },
+ { be_const_key(addr, 8), be_const_var(1) },
+ { be_const_key(read12, -1), be_const_closure(I2C_Driver_read12_closure) },
+ { be_const_key(wire, 10), be_const_var(0) },
+ { be_const_key(read13, -1), be_const_closure(I2C_Driver_read13_closure) },
+ { be_const_key(read24, -1), be_const_closure(I2C_Driver_read24_closure) },
+ { be_const_key(read8, -1), be_const_closure(I2C_Driver_read8_closure) },
+ { be_const_key(init, -1), be_const_closure(I2C_Driver_init_closure) },
+ { be_const_key(write_bit, -1), be_const_closure(I2C_Driver_write_bit_closure) },
+ })),
+ be_str_literal("I2C_Driver")
+);
+/*******************************************************************/
+
+void be_load_I2C_Driver_class(bvm *vm) {
be_pushntvclass(vm, &be_class_I2C_Driver);
be_setglobal(vm, "I2C_Driver");
be_pop(vm, 1);
}
-/* @const_object_info_begin
-
-class be_class_I2C_Driver (scope: global, name: I2C_Driver, super: be_class_Driver) {
- wire, var
- addr, var
- name, var
-
- init, closure(init_closure)
- write8, closure(write8_closure)
- write_bit, closure(write_bit_closure)
- read8, closure(read8_closure)
- read12, closure(read12_closure)
- read13, closure(read13_closure)
- read24, closure(read24_closure)
- read32, closure(read32_closure)
-}
-@const_object_info_end */
diff --git a/lib/libesp32/Berry/default/be_leds_animator_lib.c b/lib/libesp32/Berry/default/be_leds_animator_lib.c
index c5783edb9..bd82193b9 100644
--- a/lib/libesp32/Berry/default/be_leds_animator_lib.c
+++ b/lib/libesp32/Berry/default/be_leds_animator_lib.c
@@ -20,17 +20,17 @@ be_local_closure(Leds_animator_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
- /* K0 */ be_nested_string("strip", -48555823, 5),
- /* K1 */ be_nested_string("bri", 2112284244, 3),
- /* K2 */ be_nested_string("running", 343848780, 7),
- /* K3 */ be_nested_string("pixel_count", -1855836553, 11),
- /* K4 */ be_nested_string("animators", 279858213, 9),
- /* K5 */ be_nested_string("clear", 1550717474, 5),
- /* K6 */ be_nested_string("tasmota", 424643812, 7),
- /* K7 */ be_nested_string("add_driver", 1654458371, 10),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(bri),
+ /* K2 */ be_nested_str(running),
+ /* K3 */ be_nested_str(pixel_count),
+ /* K4 */ be_nested_str(animators),
+ /* K5 */ be_nested_str(clear),
+ /* K6 */ be_nested_str(tasmota),
+ /* K7 */ be_nested_str(add_driver),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x540A0031, // 0001 LDINT R2 50
@@ -70,10 +70,10 @@ be_local_closure(Leds_animator_set_bri, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("bri", 2112284244, 3),
+ /* K0 */ be_nested_str(bri),
}),
- (be_nested_const_str("set_bri", -1505848517, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_bri,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x80000000, // 0001 RET 0
@@ -97,10 +97,10 @@ be_local_closure(Leds_animator_stop, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("running", 343848780, 7),
+ /* K0 */ be_nested_str(running),
}),
- (be_nested_const_str("stop", -883741979, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_stop,
+ &be_const_str_solidified,
( &(const binstruction[ 3]) { /* code */
0x50040000, // 0000 LDBOOL R1 0 0
0x90020001, // 0001 SETMBR R0 K0 R1
@@ -125,8 +125,8 @@ be_local_closure(Leds_animator_animate, /* name */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
- (be_nested_const_str("animate", -409180496, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_animate,
+ &be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
@@ -149,11 +149,11 @@ be_local_closure(Leds_animator_remove, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
- /* K1 */ be_nested_string("remove_driver", 1030243768, 13),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(remove_driver),
}),
- (be_nested_const_str("remove", -611183107, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_remove,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -180,16 +180,16 @@ be_local_closure(Leds_animator_every_50ms, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("running", 343848780, 7),
+ /* K0 */ be_nested_str(running),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_string("animators", 279858213, 9),
- /* K3 */ be_nested_string("is_running", -2068120035, 10),
- /* K4 */ be_nested_string("animate", -409180496, 7),
+ /* K2 */ be_nested_str(animators),
+ /* K3 */ be_nested_str(is_running),
+ /* K4 */ be_nested_str(animate),
/* K5 */ be_const_int(1),
- /* K6 */ be_nested_string("remove", -611183107, 6),
+ /* K6 */ be_nested_str(remove),
}),
- (be_nested_const_str("every_50ms", -1911083288, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_every_50ms,
+ &be_const_str_solidified,
( &(const binstruction[25]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060015, // 0001 JMPF R1 #0018
@@ -236,10 +236,10 @@ be_local_closure(Leds_animator_get_bri, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("bri", 2112284244, 3),
+ /* K0 */ be_nested_str(bri),
}),
- (be_nested_const_str("get_bri", 2041809895, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_bri,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x80040400, // 0001 RET 1 R2
@@ -263,10 +263,10 @@ be_local_closure(Leds_animator_start, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("running", 343848780, 7),
+ /* K0 */ be_nested_str(running),
}),
- (be_nested_const_str("start", 1697318111, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_start,
+ &be_const_str_solidified,
( &(const binstruction[ 3]) { /* code */
0x50040200, // 0000 LDBOOL R1 1 0
0x90020001, // 0001 SETMBR R0 K0 R1
@@ -291,12 +291,12 @@ be_local_closure(Leds_animator_add_anim, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("animators", 279858213, 9),
- /* K1 */ be_nested_string("push", -2022703139, 4),
- /* K2 */ be_nested_string("run", 718098122, 3),
+ /* K0 */ be_nested_str(animators),
+ /* K1 */ be_nested_str(push),
+ /* K2 */ be_nested_str(run),
}),
- (be_nested_const_str("add_anim", -314304628, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_add_anim,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -325,12 +325,12 @@ be_local_closure(Leds_animator_clear, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("stop", -883741979, 4),
- /* K1 */ be_nested_string("strip", -48555823, 5),
- /* K2 */ be_nested_string("clear", 1550717474, 5),
+ /* K0 */ be_nested_str(stop),
+ /* K1 */ be_nested_str(strip),
+ /* K2 */ be_nested_str(clear),
}),
- (be_nested_const_str("clear", 1550717474, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x7C040200, // 0001 CALL R1 1
@@ -352,23 +352,23 @@ be_local_class(Leds_animator,
NULL,
be_nested_map(15,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, 7), be_const_closure(Leds_animator_init_closure) },
- { be_nested_key("set_bri", -1505848517, 7, -1), be_const_closure(Leds_animator_set_bri_closure) },
- { be_nested_key("stop", -883741979, 4, -1), be_const_closure(Leds_animator_stop_closure) },
- { be_nested_key("strip", -48555823, 5, 4), be_const_var(0) },
- { be_nested_key("animators", 279858213, 9, 12), be_const_var(4) },
- { be_nested_key("animate", -409180496, 7, -1), be_const_closure(Leds_animator_animate_closure) },
- { be_nested_key("remove", -611183107, 6, -1), be_const_closure(Leds_animator_remove_closure) },
- { be_nested_key("running", 343848780, 7, -1), be_const_var(3) },
- { be_nested_key("every_50ms", -1911083288, 10, -1), be_const_closure(Leds_animator_every_50ms_closure) },
- { be_nested_key("bri", 2112284244, 3, 6), be_const_var(2) },
- { be_nested_key("get_bri", 2041809895, 7, -1), be_const_closure(Leds_animator_get_bri_closure) },
- { be_nested_key("start", 1697318111, 5, -1), be_const_closure(Leds_animator_start_closure) },
- { be_nested_key("add_anim", -314304628, 8, 13), be_const_closure(Leds_animator_add_anim_closure) },
- { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_var(1) },
- { be_nested_key("clear", 1550717474, 5, 1), be_const_closure(Leds_animator_clear_closure) },
+ { be_const_key(init, 12), be_const_closure(Leds_animator_init_closure) },
+ { be_const_key(clear, -1), be_const_closure(Leds_animator_clear_closure) },
+ { be_const_key(stop, -1), be_const_closure(Leds_animator_stop_closure) },
+ { be_const_key(strip, 4), be_const_var(0) },
+ { be_const_key(pixel_count, 6), be_const_var(1) },
+ { be_const_key(animate, -1), be_const_closure(Leds_animator_animate_closure) },
+ { be_const_key(add_anim, 13), be_const_closure(Leds_animator_add_anim_closure) },
+ { be_const_key(bri, -1), be_const_var(2) },
+ { be_const_key(every_50ms, -1), be_const_closure(Leds_animator_every_50ms_closure) },
+ { be_const_key(remove, 7), be_const_closure(Leds_animator_remove_closure) },
+ { be_const_key(get_bri, -1), be_const_closure(Leds_animator_get_bri_closure) },
+ { be_const_key(start, -1), be_const_closure(Leds_animator_start_closure) },
+ { be_const_key(running, -1), be_const_var(3) },
+ { be_const_key(animators, -1), be_const_var(4) },
+ { be_const_key(set_bri, 1), be_const_closure(Leds_animator_set_bri_closure) },
})),
- (be_nested_const_str("Leds_animator", 142168673, 13))
+ be_str_literal("Leds_animator")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_leds_lib.c b/lib/libesp32/Berry/default/be_leds_lib.c
index 06e322c13..58b0a991e 100644
--- a/lib/libesp32/Berry/default/be_leds_lib.c
+++ b/lib/libesp32/Berry/default/be_leds_lib.c
@@ -20,11 +20,11 @@ be_local_closure(Leds_matrix_pixel_count, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("w"),
- /* K1 */ be_nested_str_literal("h"),
+ /* K0 */ be_nested_str(w),
+ /* K1 */ be_nested_str(h),
}),
- (be_nested_const_str("pixel_count", -1855836553, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixel_count,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x88080101, // 0001 GETMBR R2 R0 K1
@@ -50,10 +50,10 @@ be_local_closure(Leds_matrix_set_alternate, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("alternate"),
+ /* K0 */ be_nested_str(alternate),
}),
- (be_nested_const_str("set_alternate", 1709680562, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_alternate,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x80000000, // 0001 RET 0
@@ -77,11 +77,11 @@ be_local_closure(Leds_matrix_pixel_size, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("pixel_size"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(pixel_size),
}),
- (be_nested_const_str("pixel_size", -2085831511, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixel_size,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -107,12 +107,12 @@ be_local_closure(Leds_matrix_set_pixel_color, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("set_pixel_color"),
- /* K2 */ be_nested_str_literal("offset"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(set_pixel_color),
+ /* K2 */ be_nested_str(offset),
}),
- (be_nested_const_str("set_pixel_color", 1275248356, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_pixel_color,
+ &be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x88100100, // 0000 GETMBR R4 R0 K0
0x8C100901, // 0001 GETMET R4 R4 K1
@@ -142,17 +142,17 @@ be_local_closure(Leds_matrix_set_matrix_pixel_color, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
- /* K0 */ be_nested_str_literal("alternate"),
+ /* K0 */ be_nested_str(alternate),
/* K1 */ be_const_int(2),
- /* K2 */ be_nested_str_literal("strip"),
- /* K3 */ be_nested_str_literal("set_pixel_color"),
- /* K4 */ be_nested_str_literal("w"),
- /* K5 */ be_nested_str_literal("h"),
+ /* K2 */ be_nested_str(strip),
+ /* K3 */ be_nested_str(set_pixel_color),
+ /* K4 */ be_nested_str(w),
+ /* K5 */ be_nested_str(h),
/* K6 */ be_const_int(1),
- /* K7 */ be_nested_str_literal("offset"),
+ /* K7 */ be_nested_str(offset),
}),
- (be_nested_const_str("set_matrix_pixel_color", 1197149462, 22)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_matrix_pixel_color,
+ &be_const_str_solidified,
( &(const binstruction[29]) { /* code */
0x88140100, // 0000 GETMBR R5 R0 K0
0x7816000F, // 0001 JMPF R5 #0012
@@ -203,16 +203,16 @@ be_local_closure(Leds_matrix_show, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_str_literal("offset"),
+ /* K0 */ be_nested_str(offset),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_str_literal("w"),
- /* K3 */ be_nested_str_literal("h"),
- /* K4 */ be_nested_str_literal("strip"),
- /* K5 */ be_nested_str_literal("leds"),
- /* K6 */ be_nested_str_literal("show"),
+ /* K2 */ be_nested_str(w),
+ /* K3 */ be_nested_str(h),
+ /* K4 */ be_nested_str(strip),
+ /* K5 */ be_nested_str(leds),
+ /* K6 */ be_nested_str(show),
}),
- (be_nested_const_str("show", -1454906820, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_show,
+ &be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0x60080017, // 0000 GETGBL R2 G23
0x5C0C0200, // 0001 MOVE R3 R1
@@ -252,11 +252,11 @@ be_local_closure(Leds_matrix_is_dirty, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("is_dirty"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(is_dirty),
}),
- (be_nested_const_str("is_dirty", 418034110, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_is_dirty,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -283,15 +283,15 @@ be_local_closure(Leds_matrix_clear_to, /* name */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
/* K0 */ be_const_int(0),
- /* K1 */ be_nested_str_literal("w"),
- /* K2 */ be_nested_str_literal("h"),
- /* K3 */ be_nested_str_literal("strip"),
- /* K4 */ be_nested_str_literal("set_pixel_color"),
- /* K5 */ be_nested_str_literal("offset"),
+ /* K1 */ be_nested_str(w),
+ /* K2 */ be_nested_str(h),
+ /* K3 */ be_nested_str(strip),
+ /* K4 */ be_nested_str(set_pixel_color),
+ /* K5 */ be_nested_str(offset),
/* K6 */ be_const_int(1),
}),
- (be_nested_const_str("clear_to", -766965166, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear_to,
+ &be_const_str_solidified,
( &(const binstruction[16]) { /* code */
0x580C0000, // 0000 LDCONST R3 K0
0x88100101, // 0001 GETMBR R4 R0 K1
@@ -329,12 +329,12 @@ be_local_closure(Leds_matrix_clear, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("clear_to"),
+ /* K0 */ be_nested_str(clear_to),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_str_literal("show"),
+ /* K2 */ be_nested_str(show),
}),
- (be_nested_const_str("clear", 1550717474, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
@@ -362,8 +362,8 @@ be_local_closure(Leds_matrix_pixels_buffer, /* name */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
- (be_nested_const_str("pixels_buffer", 1229555807, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixels_buffer,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x4C040000, // 0000 LDNIL R1
0x80040200, // 0001 RET 1 R1
@@ -387,14 +387,14 @@ be_local_closure(Leds_matrix_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("offset"),
- /* K2 */ be_nested_str_literal("h"),
- /* K3 */ be_nested_str_literal("w"),
- /* K4 */ be_nested_str_literal("alternate"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(offset),
+ /* K2 */ be_nested_str(h),
+ /* K3 */ be_nested_str(w),
+ /* K4 */ be_nested_str(alternate),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x90020204, // 0001 SETMBR R0 K1 R4
@@ -423,11 +423,11 @@ be_local_closure(Leds_matrix_dirty, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("dirty"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(dirty),
}),
- (be_nested_const_str("dirty", -1627386213, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_dirty,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -453,12 +453,12 @@ be_local_closure(Leds_matrix_get_pixel_color, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("get_pixel_color"),
- /* K2 */ be_nested_str_literal("offseta"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(get_pixel_color),
+ /* K2 */ be_nested_str(offseta),
}),
- (be_nested_const_str("get_pixel_color", 337490048, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_pixel_color,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -486,10 +486,10 @@ be_local_closure(Leds_matrix_get_alternate, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("alternate"),
+ /* K0 */ be_nested_str(alternate),
}),
- (be_nested_const_str("get_alternate", 1450148894, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_alternate,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x80040200, // 0001 RET 1 R1
@@ -513,8 +513,8 @@ be_local_closure(Leds_matrix_begin, /* name */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
- (be_nested_const_str("begin", 1748273790, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_begin,
+ &be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
@@ -537,11 +537,11 @@ be_local_closure(Leds_matrix_can_show, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("can_show"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(can_show),
}),
- (be_nested_const_str("can_show", 960091187, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_can_show,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -561,27 +561,27 @@ be_local_class(Leds_matrix,
NULL,
be_nested_map(21,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(Leds_matrix_pixel_count_closure) },
- { be_nested_key("h", -317966505, 1, 6), be_const_var(2) },
- { be_nested_key("set_alternate", 1709680562, 13, 7), be_const_closure(Leds_matrix_set_alternate_closure) },
- { be_nested_key("pixel_size", -2085831511, 10, 16), be_const_closure(Leds_matrix_pixel_size_closure) },
- { be_nested_key("set_pixel_color", 1275248356, 15, 19), be_const_closure(Leds_matrix_set_pixel_color_closure) },
- { be_nested_key("set_matrix_pixel_color", 1197149462, 22, 10), be_const_closure(Leds_matrix_set_matrix_pixel_color_closure) },
- { be_nested_key("show", -1454906820, 4, -1), be_const_closure(Leds_matrix_show_closure) },
- { be_nested_key("alternate", 1140253277, 9, -1), be_const_var(4) },
- { be_nested_key("strip", -48555823, 5, -1), be_const_var(0) },
- { be_nested_key("clear_to", -766965166, 8, -1), be_const_closure(Leds_matrix_clear_to_closure) },
- { be_nested_key("w", -234078410, 1, 15), be_const_var(3) },
- { be_nested_key("pixels_buffer", 1229555807, 13, -1), be_const_closure(Leds_matrix_pixels_buffer_closure) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(Leds_matrix_init_closure) },
- { be_nested_key("dirty", -1627386213, 5, -1), be_const_closure(Leds_matrix_dirty_closure) },
- { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_matrix_get_pixel_color_closure) },
- { be_nested_key("get_alternate", 1450148894, 13, 17), be_const_closure(Leds_matrix_get_alternate_closure) },
- { be_nested_key("offset", 348705738, 6, 8), be_const_var(1) },
- { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(Leds_matrix_clear_closure) },
- { be_nested_key("begin", 1748273790, 5, -1), be_const_closure(Leds_matrix_begin_closure) },
- { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_matrix_is_dirty_closure) },
- { be_nested_key("can_show", 960091187, 8, -1), be_const_closure(Leds_matrix_can_show_closure) },
+ { be_const_key(pixel_count, -1), be_const_closure(Leds_matrix_pixel_count_closure) },
+ { be_const_key(h, 6), be_const_var(2) },
+ { be_const_key(set_alternate, 7), be_const_closure(Leds_matrix_set_alternate_closure) },
+ { be_const_key(pixel_size, 16), be_const_closure(Leds_matrix_pixel_size_closure) },
+ { be_const_key(set_pixel_color, 19), be_const_closure(Leds_matrix_set_pixel_color_closure) },
+ { be_const_key(set_matrix_pixel_color, 10), be_const_closure(Leds_matrix_set_matrix_pixel_color_closure) },
+ { be_const_key(show, -1), be_const_closure(Leds_matrix_show_closure) },
+ { be_const_key(alternate, -1), be_const_var(4) },
+ { be_const_key(strip, -1), be_const_var(0) },
+ { be_const_key(clear_to, -1), be_const_closure(Leds_matrix_clear_to_closure) },
+ { be_const_key(w, 15), be_const_var(3) },
+ { be_const_key(pixels_buffer, -1), be_const_closure(Leds_matrix_pixels_buffer_closure) },
+ { be_const_key(init, -1), be_const_closure(Leds_matrix_init_closure) },
+ { be_const_key(dirty, -1), be_const_closure(Leds_matrix_dirty_closure) },
+ { be_const_key(get_pixel_color, -1), be_const_closure(Leds_matrix_get_pixel_color_closure) },
+ { be_const_key(get_alternate, 17), be_const_closure(Leds_matrix_get_alternate_closure) },
+ { be_const_key(offset, 8), be_const_var(1) },
+ { be_const_key(clear, -1), be_const_closure(Leds_matrix_clear_closure) },
+ { be_const_key(begin, -1), be_const_closure(Leds_matrix_begin_closure) },
+ { be_const_key(is_dirty, -1), be_const_closure(Leds_matrix_is_dirty_closure) },
+ { be_const_key(can_show, -1), be_const_closure(Leds_matrix_can_show_closure) },
})),
be_str_literal("Leds_matrix")
);
@@ -601,13 +601,13 @@ be_local_closure(Leds_create_matrix, /* name */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
/* K0 */ be_const_int(0),
- /* K1 */ be_nested_str_literal("leds"),
- /* K2 */ be_nested_str_literal("value_error"),
- /* K3 */ be_nested_str_literal("out of range"),
+ /* K1 */ be_nested_str(leds),
+ /* K2 */ be_nested_str(value_error),
+ /* K3 */ be_nested_str(out_X20of_X20range),
/* K4 */ be_const_class(be_class_Leds_matrix),
}),
- (be_nested_const_str("create_matrix", -766781373, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_create_matrix,
+ &be_const_str_solidified,
( &(const binstruction[37]) { /* code */
0x60100009, // 0000 GETGBL R4 G9
0x5C140600, // 0001 MOVE R5 R3
@@ -666,11 +666,11 @@ be_local_closure(Leds_begin, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
/* K1 */ be_const_int(1),
}),
- (be_nested_const_str("begin", 1748273790, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_begin,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
@@ -696,16 +696,16 @@ be_local_closure(Leds_to_gamma, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_str_literal("tasmota"),
- /* K1 */ be_nested_str_literal("scale_uint"),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(scale_uint),
/* K2 */ be_const_int(0),
/* K3 */ be_const_int(16711680),
- /* K4 */ be_nested_str_literal("gamma"),
- /* K5 */ be_nested_str_literal("light"),
- /* K6 */ be_nested_str_literal("gamma8"),
+ /* K4 */ be_nested_str(gamma),
+ /* K5 */ be_nested_str(light),
+ /* K6 */ be_nested_str(gamma8),
}),
- (be_nested_const_str("to_gamma", 1597139862, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_to_gamma,
+ &be_const_str_solidified,
( &(const binstruction[67]) { /* code */
0x4C0C0000, // 0000 LDNIL R3
0x200C0403, // 0001 NE R3 R2 R3
@@ -794,10 +794,10 @@ be_local_closure(Leds_pixel_count, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
}),
- (be_nested_const_str("pixel_count", -1855836553, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixel_count,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0007, // 0001 LDINT R3 8
@@ -823,12 +823,12 @@ be_local_closure(Leds_matrix, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("Leds"),
- /* K1 */ be_nested_str_literal("create_matrix"),
+ /* K0 */ be_nested_str(Leds),
+ /* K1 */ be_nested_str(create_matrix),
/* K2 */ be_const_int(0),
}),
- (be_nested_const_str("matrix", 365099244, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_matrix,
+ &be_const_str_solidified,
( &(const binstruction[11]) { /* code */
0xB8120000, // 0000 GETNGBL R4 K0
0x08140001, // 0001 MUL R5 R0 R1
@@ -861,10 +861,10 @@ be_local_closure(Leds_pixel_size, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
}),
- (be_nested_const_str("pixel_size", -2085831511, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixel_size,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0006, // 0001 LDINT R3 7
@@ -890,10 +890,10 @@ be_local_closure(Leds_pixels_buffer, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
}),
- (be_nested_const_str("pixels_buffer", 1229555807, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixels_buffer,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0005, // 0001 LDINT R3 6
@@ -919,10 +919,10 @@ be_local_closure(Leds_get_pixel_color, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
}),
- (be_nested_const_str("get_pixel_color", 337490048, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_pixel_color,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C080100, // 0000 GETMET R2 R0 K0
0x5412000A, // 0001 LDINT R4 11
@@ -949,11 +949,11 @@ be_local_closure(Leds_set_pixel_color, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
- /* K1 */ be_nested_str_literal("to_gamma"),
+ /* K0 */ be_nested_str(call_native),
+ /* K1 */ be_nested_str(to_gamma),
}),
- (be_nested_const_str("set_pixel_color", 1275248356, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_pixel_color,
+ &be_const_str_solidified,
( &(const binstruction[ 9]) { /* code */
0x8C100100, // 0000 GETMET R4 R0 K0
0x541A0009, // 0001 LDINT R6 10
@@ -984,10 +984,10 @@ be_local_closure(Leds_is_dirty, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
}),
- (be_nested_const_str("is_dirty", 418034110, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_is_dirty,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0003, // 0001 LDINT R3 4
@@ -1013,21 +1013,21 @@ be_local_closure(Leds_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[12]) { /* constants */
- /* K0 */ be_nested_str_literal("gamma"),
- /* K1 */ be_nested_str_literal("leds"),
- /* K2 */ be_nested_str_literal("pin"),
- /* K3 */ be_nested_str_literal("WS2812"),
+ /* K0 */ be_nested_str(gamma),
+ /* K1 */ be_nested_str(leds),
+ /* K2 */ be_nested_str(pin),
+ /* K3 */ be_nested_str(WS2812),
/* K4 */ be_const_int(0),
- /* K5 */ be_nested_str_literal("valuer_error"),
- /* K6 */ be_nested_str_literal("no GPIO specified for neopixelbus"),
- /* K7 */ be_nested_str_literal("ctor"),
- /* K8 */ be_nested_str_literal("_p"),
- /* K9 */ be_nested_str_literal("internal_error"),
- /* K10 */ be_nested_str_literal("couldn't not initialize noepixelbus"),
- /* K11 */ be_nested_str_literal("begin"),
+ /* K5 */ be_nested_str(valuer_error),
+ /* K6 */ be_nested_str(no_X20GPIO_X20specified_X20for_X20neopixelbus),
+ /* K7 */ be_nested_str(ctor),
+ /* K8 */ be_nested_str(_p),
+ /* K9 */ be_nested_str(internal_error),
+ /* K10 */ be_nested_str(couldn_X27t_X20not_X20initialize_X20noepixelbus),
+ /* K11 */ be_nested_str(begin),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[36]) { /* code */
0x50140200, // 0000 LDBOOL R5 1 0
0x90020005, // 0001 SETMBR R0 K0 R5
@@ -1085,11 +1085,11 @@ be_local_closure(Leds_clear_to, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
- /* K1 */ be_nested_str_literal("to_gamma"),
+ /* K0 */ be_nested_str(call_native),
+ /* K1 */ be_nested_str(to_gamma),
}),
- (be_nested_const_str("clear_to", -766965166, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear_to,
+ &be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x8C0C0100, // 0000 GETMET R3 R0 K0
0x54160008, // 0001 LDINT R5 9
@@ -1119,11 +1119,11 @@ be_local_closure(Leds_can_show, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
/* K1 */ be_const_int(3),
}),
- (be_nested_const_str("can_show", 960091187, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_can_show,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
@@ -1149,12 +1149,12 @@ be_local_closure(Leds_clear, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("clear_to"),
+ /* K0 */ be_nested_str(clear_to),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_str_literal("show"),
+ /* K2 */ be_nested_str(show),
}),
- (be_nested_const_str("clear", 1550717474, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
@@ -1182,11 +1182,11 @@ be_local_closure(Leds_show, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
/* K1 */ be_const_int(2),
}),
- (be_nested_const_str("show", -1454906820, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_show,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
@@ -1212,11 +1212,11 @@ be_local_closure(Leds_ctor, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
/* K1 */ be_const_int(0),
}),
- (be_nested_const_str("ctor", 375399343, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_ctor,
+ &be_const_str_solidified,
( &(const binstruction[16]) { /* code */
0x4C100000, // 0000 LDNIL R4
0x1C100604, // 0001 EQ R4 R3 R4
@@ -1254,10 +1254,10 @@ be_local_closure(Leds_dirty, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("call_native"),
+ /* K0 */ be_nested_str(call_native),
}),
- (be_nested_const_str("dirty", -1627386213, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_dirty,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0004, // 0001 LDINT R3 5
@@ -1283,12 +1283,12 @@ be_local_closure(Leds_segment_get_pixel_color, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("get_pixel_color"),
- /* K2 */ be_nested_str_literal("offseta"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(get_pixel_color),
+ /* K2 */ be_nested_str(offseta),
}),
- (be_nested_const_str("get_pixel_color", 337490048, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_pixel_color,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -1317,14 +1317,14 @@ be_local_closure(Leds_segment_clear_to, /* name */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_const_int(0),
- /* K1 */ be_nested_str_literal("leds"),
- /* K2 */ be_nested_str_literal("strip"),
- /* K3 */ be_nested_str_literal("set_pixel_color"),
- /* K4 */ be_nested_str_literal("offset"),
+ /* K1 */ be_nested_str(leds),
+ /* K2 */ be_nested_str(strip),
+ /* K3 */ be_nested_str(set_pixel_color),
+ /* K4 */ be_nested_str(offset),
/* K5 */ be_const_int(1),
}),
- (be_nested_const_str("clear_to", -766965166, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear_to,
+ &be_const_str_solidified,
( &(const binstruction[14]) { /* code */
0x580C0000, // 0000 LDCONST R3 K0
0x88100101, // 0001 GETMBR R4 R0 K1
@@ -1360,11 +1360,11 @@ be_local_closure(Leds_segment_can_show, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("can_show"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(can_show),
}),
- (be_nested_const_str("can_show", 960091187, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_can_show,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -1390,12 +1390,12 @@ be_local_closure(Leds_segment_set_pixel_color, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("set_pixel_color"),
- /* K2 */ be_nested_str_literal("offset"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(set_pixel_color),
+ /* K2 */ be_nested_str(offset),
}),
- (be_nested_const_str("set_pixel_color", 1275248356, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_pixel_color,
+ &be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x88100100, // 0000 GETMBR R4 R0 K0
0x8C100901, // 0001 GETMET R4 R4 K1
@@ -1425,12 +1425,12 @@ be_local_closure(Leds_segment_clear, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("clear_to"),
+ /* K0 */ be_nested_str(clear_to),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_str_literal("show"),
+ /* K2 */ be_nested_str(show),
}),
- (be_nested_const_str("clear", 1550717474, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_clear,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
@@ -1458,8 +1458,8 @@ be_local_closure(Leds_segment_begin, /* name */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
- (be_nested_const_str("begin", 1748273790, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_begin,
+ &be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
@@ -1482,10 +1482,10 @@ be_local_closure(Leds_segment_pixel_count, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_str_literal("leds"),
+ /* K0 */ be_nested_str(leds),
}),
- (be_nested_const_str("pixel_count", -1855836553, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixel_count,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x80040200, // 0001 RET 1 R1
@@ -1509,12 +1509,12 @@ be_local_closure(Leds_segment_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("offset"),
- /* K2 */ be_nested_str_literal("leds"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(offset),
+ /* K2 */ be_nested_str(leds),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x60100009, // 0001 GETGBL R4 G9
@@ -1546,11 +1546,11 @@ be_local_closure(Leds_segment_pixel_size, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("pixel_size"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(pixel_size),
}),
- (be_nested_const_str("pixel_size", -2085831511, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixel_size,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -1576,11 +1576,11 @@ be_local_closure(Leds_segment_dirty, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("dirty"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(dirty),
}),
- (be_nested_const_str("dirty", -1627386213, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_dirty,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -1606,14 +1606,14 @@ be_local_closure(Leds_segment_show, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_str_literal("offset"),
+ /* K0 */ be_nested_str(offset),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_str_literal("leds"),
- /* K3 */ be_nested_str_literal("strip"),
- /* K4 */ be_nested_str_literal("show"),
+ /* K2 */ be_nested_str(leds),
+ /* K3 */ be_nested_str(strip),
+ /* K4 */ be_nested_str(show),
}),
- (be_nested_const_str("show", -1454906820, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_show,
+ &be_const_str_solidified,
( &(const binstruction[16]) { /* code */
0x60080017, // 0000 GETGBL R2 G23
0x5C0C0200, // 0001 MOVE R3 R1
@@ -1651,11 +1651,11 @@ be_local_closure(Leds_segment_is_dirty, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("strip"),
- /* K1 */ be_nested_str_literal("is_dirty"),
+ /* K0 */ be_nested_str(strip),
+ /* K1 */ be_nested_str(is_dirty),
}),
- (be_nested_const_str("is_dirty", 418034110, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_is_dirty,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -1681,8 +1681,8 @@ be_local_closure(Leds_segment_pixels_buffer, /* name */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
- (be_nested_const_str("pixels_buffer", 1229555807, 13)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_pixels_buffer,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x4C040000, // 0000 LDNIL R1
0x80040200, // 0001 RET 1 R1
@@ -1700,22 +1700,22 @@ be_local_class(Leds_segment,
NULL,
be_nested_map(16,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_segment_get_pixel_color_closure) },
- { be_nested_key("strip", -48555823, 5, -1), be_const_var(0) },
- { be_nested_key("clear_to", -766965166, 8, 5), be_const_closure(Leds_segment_clear_to_closure) },
- { be_nested_key("can_show", 960091187, 8, 13), be_const_closure(Leds_segment_can_show_closure) },
- { be_nested_key("set_pixel_color", 1275248356, 15, -1), be_const_closure(Leds_segment_set_pixel_color_closure) },
- { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(Leds_segment_clear_closure) },
- { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_segment_is_dirty_closure) },
- { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(Leds_segment_pixel_count_closure) },
- { be_nested_key("leds", 558858555, 4, -1), be_const_var(2) },
- { be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(Leds_segment_pixel_size_closure) },
- { be_nested_key("offset", 348705738, 6, -1), be_const_var(1) },
- { be_nested_key("dirty", -1627386213, 5, 8), be_const_closure(Leds_segment_dirty_closure) },
- { be_nested_key("show", -1454906820, 4, -1), be_const_closure(Leds_segment_show_closure) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(Leds_segment_init_closure) },
- { be_nested_key("begin", 1748273790, 5, 6), be_const_closure(Leds_segment_begin_closure) },
- { be_nested_key("pixels_buffer", 1229555807, 13, -1), be_const_closure(Leds_segment_pixels_buffer_closure) },
+ { be_const_key(get_pixel_color, -1), be_const_closure(Leds_segment_get_pixel_color_closure) },
+ { be_const_key(strip, -1), be_const_var(0) },
+ { be_const_key(clear_to, 5), be_const_closure(Leds_segment_clear_to_closure) },
+ { be_const_key(can_show, 13), be_const_closure(Leds_segment_can_show_closure) },
+ { be_const_key(set_pixel_color, -1), be_const_closure(Leds_segment_set_pixel_color_closure) },
+ { be_const_key(clear, -1), be_const_closure(Leds_segment_clear_closure) },
+ { be_const_key(is_dirty, -1), be_const_closure(Leds_segment_is_dirty_closure) },
+ { be_const_key(pixel_count, -1), be_const_closure(Leds_segment_pixel_count_closure) },
+ { be_const_key(leds, -1), be_const_var(2) },
+ { be_const_key(pixel_size, -1), be_const_closure(Leds_segment_pixel_size_closure) },
+ { be_const_key(offset, -1), be_const_var(1) },
+ { be_const_key(dirty, 8), be_const_closure(Leds_segment_dirty_closure) },
+ { be_const_key(show, -1), be_const_closure(Leds_segment_show_closure) },
+ { be_const_key(init, -1), be_const_closure(Leds_segment_init_closure) },
+ { be_const_key(begin, 6), be_const_closure(Leds_segment_begin_closure) },
+ { be_const_key(pixels_buffer, -1), be_const_closure(Leds_segment_pixels_buffer_closure) },
})),
be_str_literal("Leds_segment")
);
@@ -1734,14 +1734,14 @@ be_local_closure(Leds_create_segment, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_str_literal("leds"),
+ /* K0 */ be_nested_str(leds),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_str_literal("value_error"),
- /* K3 */ be_nested_str_literal("out of range"),
+ /* K2 */ be_nested_str(value_error),
+ /* K3 */ be_nested_str(out_X20of_X20range),
/* K4 */ be_const_class(be_class_Leds_segment),
}),
- (be_nested_const_str("create_segment", -431444577, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_create_segment,
+ &be_const_str_solidified,
( &(const binstruction[23]) { /* code */
0x600C0009, // 0000 GETGBL R3 G9
0x5C100200, // 0001 MOVE R4 R1
@@ -1781,26 +1781,26 @@ be_local_class(Leds,
&be_class_Leds_ntv,
be_nested_map(20,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(Leds_pixel_count_closure) },
- { be_nested_key("dirty", -1627386213, 5, 6), be_const_closure(Leds_dirty_closure) },
- { be_nested_key("to_gamma", 1597139862, 8, -1), be_const_closure(Leds_to_gamma_closure) },
- { be_nested_key("create_matrix", -766781373, 13, 1), be_const_closure(Leds_create_matrix_closure) },
- { be_nested_key("matrix", 365099244, 6, -1), be_const_static_closure(Leds_matrix_closure) },
- { be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(Leds_pixel_size_closure) },
- { be_nested_key("ctor", 375399343, 4, 0), be_const_closure(Leds_ctor_closure) },
- { be_nested_key("pixels_buffer", 1229555807, 13, 13), be_const_closure(Leds_pixels_buffer_closure) },
- { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_get_pixel_color_closure) },
- { be_nested_key("show", -1454906820, 4, -1), be_const_closure(Leds_show_closure) },
- { be_nested_key("begin", 1748273790, 5, 17), be_const_closure(Leds_begin_closure) },
- { be_nested_key("leds", 558858555, 4, -1), be_const_var(1) },
- { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(Leds_clear_closure) },
- { be_nested_key("can_show", 960091187, 8, -1), be_const_closure(Leds_can_show_closure) },
- { be_nested_key("gamma", -802614262, 5, 12), be_const_var(0) },
- { be_nested_key("init", 380752755, 4, 11), be_const_closure(Leds_init_closure) },
- { be_nested_key("set_pixel_color", 1275248356, 15, 9), be_const_closure(Leds_set_pixel_color_closure) },
- { be_nested_key("clear_to", -766965166, 8, 18), be_const_closure(Leds_clear_to_closure) },
- { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_is_dirty_closure) },
- { be_nested_key("create_segment", -431444577, 14, -1), be_const_closure(Leds_create_segment_closure) },
+ { be_const_key(pixel_count, -1), be_const_closure(Leds_pixel_count_closure) },
+ { be_const_key(dirty, 6), be_const_closure(Leds_dirty_closure) },
+ { be_const_key(to_gamma, -1), be_const_closure(Leds_to_gamma_closure) },
+ { be_const_key(create_matrix, 1), be_const_closure(Leds_create_matrix_closure) },
+ { be_const_key(matrix, -1), be_const_static_closure(Leds_matrix_closure) },
+ { be_const_key(pixel_size, -1), be_const_closure(Leds_pixel_size_closure) },
+ { be_const_key(ctor, 0), be_const_closure(Leds_ctor_closure) },
+ { be_const_key(pixels_buffer, 13), be_const_closure(Leds_pixels_buffer_closure) },
+ { be_const_key(get_pixel_color, -1), be_const_closure(Leds_get_pixel_color_closure) },
+ { be_const_key(show, -1), be_const_closure(Leds_show_closure) },
+ { be_const_key(begin, 17), be_const_closure(Leds_begin_closure) },
+ { be_const_key(leds, -1), be_const_var(1) },
+ { be_const_key(clear, -1), be_const_closure(Leds_clear_closure) },
+ { be_const_key(can_show, -1), be_const_closure(Leds_can_show_closure) },
+ { be_const_key(gamma, 12), be_const_var(0) },
+ { be_const_key(init, 11), be_const_closure(Leds_init_closure) },
+ { be_const_key(set_pixel_color, 9), be_const_closure(Leds_set_pixel_color_closure) },
+ { be_const_key(clear_to, 18), be_const_closure(Leds_clear_to_closure) },
+ { be_const_key(is_dirty, -1), be_const_closure(Leds_is_dirty_closure) },
+ { be_const_key(create_segment, -1), be_const_closure(Leds_create_segment_closure) },
})),
be_str_literal("Leds")
);
diff --git a/lib/libesp32/Berry/default/be_leds_ntv_lib.c b/lib/libesp32/Berry/default/be_leds_ntv_lib.c
index 357786978..4d5b07bb6 100644
--- a/lib/libesp32/Berry/default/be_leds_ntv_lib.c
+++ b/lib/libesp32/Berry/default/be_leds_ntv_lib.c
@@ -30,11 +30,11 @@ be_local_class(Leds_ntv,
NULL,
be_nested_map(5,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("call_native", 1389147405, 11, -1), be_const_func(be_neopixelbus_call_native) },
- { be_nested_key("_t", 1527481326, 2, -1), be_const_var(1) },
- { be_nested_key("_p", 1594591802, 2, 3), be_const_var(0) },
- { be_nested_key("SK6812_GRBW", 81157857, 11, 4), be_const_int(2) },
- { be_nested_key("WS2812_GRB", 1736405692, 10, -1), be_const_int(1) },
+ { be_const_key(call_native, -1), be_const_func(be_neopixelbus_call_native) },
+ { be_const_key(_t, -1), be_const_var(1) },
+ { be_const_key(_p, 3), be_const_var(0) },
+ { be_const_key(SK6812_GRBW, 4), be_const_int(2) },
+ { be_const_key(WS2812_GRB, -1), be_const_int(1) },
})),
be_str_literal("Leds_ntv")
);
diff --git a/lib/libesp32/Berry/default/be_lvgl_clock_icon_lib.c b/lib/libesp32/Berry/default/be_lvgl_clock_icon_lib.c
index 4cef73ac9..c9cf7f207 100644
--- a/lib/libesp32/Berry/default/be_lvgl_clock_icon_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_clock_icon_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: set_time
********************************************************************/
-be_local_closure(set_time, /* name */
+be_local_closure(lv_clock_icon_set_time, /* name */
be_nested_proto(
11, /* nstack */
4, /* argc */
@@ -21,19 +21,19 @@ be_local_closure(set_time, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_string("string", 398550328, 6),
- /* K1 */ be_nested_string("hour", -1241306097, 4),
- /* K2 */ be_nested_string("minute", 954666857, 6),
- /* K3 */ be_nested_string("sec", -1155074638, 3),
- /* K4 */ be_nested_string("format", -1180859054, 6),
- /* K5 */ be_nested_string("%02d%s%02d", 1587999717, 10),
+ /* K0 */ be_nested_str(string),
+ /* K1 */ be_nested_str(hour),
+ /* K2 */ be_nested_str(minute),
+ /* K3 */ be_nested_str(sec),
+ /* K4 */ be_nested_str(format),
+ /* K5 */ be_nested_str(_X2502d_X25s_X2502d),
/* K6 */ be_const_int(2),
- /* K7 */ be_nested_string(":", 1057798253, 1),
- /* K8 */ be_nested_string(" ", 621580159, 1),
- /* K9 */ be_nested_string("set_text", 1849641155, 8),
+ /* K7 */ be_nested_str(_X3A),
+ /* K8 */ be_nested_str(_X20),
+ /* K9 */ be_nested_str(set_text),
}),
- (be_nested_const_str("set_time", 900236405, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_time,
+ &be_const_str_solidified,
( &(const binstruction[27]) { /* code */
0xA4120000, // 0000 IMPORT R4 K0
0x88140101, // 0001 GETMBR R5 R0 K1
@@ -71,7 +71,7 @@ be_local_closure(set_time, /* name */
/********************************************************************
** Solidified function: every_second
********************************************************************/
-be_local_closure(every_second, /* name */
+be_local_closure(lv_clock_icon_every_second, /* name */
be_nested_proto(
7, /* nstack */
1, /* argc */
@@ -82,18 +82,18 @@ be_local_closure(every_second, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 9]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
- /* K1 */ be_nested_string("time_dump", -964556549, 9),
- /* K2 */ be_nested_string("rtc", 1070575216, 3),
- /* K3 */ be_nested_string("local", -1673304312, 5),
- /* K4 */ be_nested_string("year", -1367388900, 4),
- /* K5 */ be_nested_string("set_time", 900236405, 8),
- /* K6 */ be_nested_string("hour", -1241306097, 4),
- /* K7 */ be_nested_string("min", -913357481, 3),
- /* K8 */ be_nested_string("sec", -1155074638, 3),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(time_dump),
+ /* K2 */ be_nested_str(rtc),
+ /* K3 */ be_nested_str(local),
+ /* K4 */ be_nested_str(year),
+ /* K5 */ be_nested_str(set_time),
+ /* K6 */ be_nested_str(hour),
+ /* K7 */ be_nested_str(min),
+ /* K8 */ be_nested_str(sec),
}),
- (be_nested_const_str("every_second", 2075451465, 12)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_every_second,
+ &be_const_str_solidified,
( &(const binstruction[17]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -121,7 +121,7 @@ be_local_closure(every_second, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(lv_clock_icon_init, /* name */
be_nested_proto(
11, /* nstack */
2, /* argc */
@@ -132,31 +132,31 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[22]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("lv", 1529997255, 2),
- /* K2 */ be_nested_string("seg7_font", -195276607, 9),
- /* K3 */ be_nested_string("set_style_text_font", 1028590019, 19),
- /* K4 */ be_nested_string("PART_MAIN", -1821475788, 9),
- /* K5 */ be_nested_string("STATE_DEFAULT", 712406428, 13),
- /* K6 */ be_nested_string("get_height", -723211773, 10),
- /* K7 */ be_nested_string("set_text", 1849641155, 8),
- /* K8 */ be_nested_string("--:--", 1370615441, 5),
- /* K9 */ be_nested_string("refr_size", 1958144468, 9),
- /* K10 */ be_nested_string("get_width", -1001549996, 9),
- /* K11 */ be_nested_string("set_y", 1866178391, 5),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(lv),
+ /* K2 */ be_nested_str(seg7_font),
+ /* K3 */ be_nested_str(set_style_text_font),
+ /* K4 */ be_nested_str(PART_MAIN),
+ /* K5 */ be_nested_str(STATE_DEFAULT),
+ /* K6 */ be_nested_str(get_height),
+ /* K7 */ be_nested_str(set_text),
+ /* K8 */ be_nested_str(_X2D_X2D_X3A_X2D_X2D),
+ /* K9 */ be_nested_str(refr_size),
+ /* K10 */ be_nested_str(get_width),
+ /* K11 */ be_nested_str(set_y),
/* K12 */ be_const_int(2),
- /* K13 */ be_nested_string("get_style_pad_right", -1144679830, 19),
- /* K14 */ be_nested_string("set_x", 1849400772, 5),
+ /* K13 */ be_nested_str(get_style_pad_right),
+ /* K14 */ be_nested_str(set_x),
/* K15 */ be_const_int(3),
- /* K16 */ be_nested_string("set_style_pad_right", -980898242, 19),
- /* K17 */ be_nested_string("set_style_bg_color", 1689513089, 18),
- /* K18 */ be_nested_string("color", 1031692888, 5),
- /* K19 */ be_nested_string("COLOR_BLACK", 264427940, 11),
- /* K20 */ be_nested_string("tasmota", 424643812, 7),
- /* K21 */ be_nested_string("add_driver", 1654458371, 10),
+ /* K16 */ be_nested_str(set_style_pad_right),
+ /* K17 */ be_nested_str(set_style_bg_color),
+ /* K18 */ be_nested_str(color),
+ /* K19 */ be_nested_str(COLOR_BLACK),
+ /* K20 */ be_nested_str(tasmota),
+ /* K21 */ be_nested_str(add_driver),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[82]) { /* code */
0x60080003, // 0000 GETGBL R2 G3
0x5C0C0000, // 0001 MOVE R3 R0
@@ -249,7 +249,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: del
********************************************************************/
-be_local_closure(del, /* name */
+be_local_closure(lv_clock_icon_del, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -260,12 +260,12 @@ be_local_closure(del, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("del", -816214454, 3),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("remove_driver", 1030243768, 13),
+ /* K0 */ be_nested_str(del),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(remove_driver),
}),
- (be_nested_const_str("del", -816214454, 3)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_del,
+ &be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x60040003, // 0000 GETGBL R1 G3
0x5C080000, // 0001 MOVE R2 R0
@@ -292,15 +292,15 @@ be_local_class(lv_clock_icon,
&be_class_lv_label,
be_nested_map(7,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("sec", -1155074638, 3, -1), be_const_var(2) },
- { be_nested_key("hour", -1241306097, 4, -1), be_const_var(0) },
- { be_nested_key("set_time", 900236405, 8, 6), be_const_closure(set_time_closure) },
- { be_nested_key("every_second", 2075451465, 12, -1), be_const_closure(every_second_closure) },
- { be_nested_key("minute", 954666857, 6, -1), be_const_var(1) },
- { be_nested_key("init", 380752755, 4, 2), be_const_closure(init_closure) },
- { be_nested_key("del", -816214454, 3, -1), be_const_closure(del_closure) },
+ { be_const_key(sec, -1), be_const_var(2) },
+ { be_const_key(hour, -1), be_const_var(0) },
+ { be_const_key(set_time, 6), be_const_closure(lv_clock_icon_set_time_closure) },
+ { be_const_key(every_second, -1), be_const_closure(lv_clock_icon_every_second_closure) },
+ { be_const_key(minute, -1), be_const_var(1) },
+ { be_const_key(init, 2), be_const_closure(lv_clock_icon_init_closure) },
+ { be_const_key(del, -1), be_const_closure(lv_clock_icon_del_closure) },
})),
- (be_nested_const_str("lv_clock_icon", -1037751086, 13))
+ be_str_literal("lv_clock_icon")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_lvgl_glob_lib.c b/lib/libesp32/Berry/default/be_lvgl_glob_lib.c
index 31619f1c4..01bd4ed1d 100644
--- a/lib/libesp32/Berry/default/be_lvgl_glob_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_glob_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: get_object_from_ptr
********************************************************************/
-be_local_closure(get_object_from_ptr, /* name */
+be_local_closure(LVGL_glob_get_object_from_ptr, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -21,11 +21,11 @@ be_local_closure(get_object_from_ptr, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("cb_obj", 1195696482, 6),
- /* K1 */ be_nested_string("find", -1108310694, 4),
+ /* K0 */ be_nested_str(cb_obj),
+ /* K1 */ be_nested_str(find),
}),
- (be_nested_const_str("get_object_from_ptr", -1949948095, 19)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_object_from_ptr,
+ &be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x4C0C0000, // 0001 LDNIL R3
@@ -46,7 +46,7 @@ be_local_closure(get_object_from_ptr, /* name */
/********************************************************************
** Solidified function: widget_event_impl
********************************************************************/
-be_local_closure(widget_event_impl, /* name */
+be_local_closure(LVGL_glob_widget_event_impl, /* name */
be_nested_proto(
12, /* nstack */
3, /* argc */
@@ -57,18 +57,18 @@ be_local_closure(widget_event_impl, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 9]) { /* constants */
- /* K0 */ be_nested_string("introspect", 164638290, 10),
- /* K1 */ be_nested_string("lv", 1529997255, 2),
- /* K2 */ be_nested_string("lv_obj_class", -255311002, 12),
- /* K3 */ be_nested_string("lv_event", -1860877328, 8),
- /* K4 */ be_nested_string("target", 845187144, 6),
- /* K5 */ be_nested_string("get_object_from_ptr", -1949948095, 19),
- /* K6 */ be_nested_string("instance", 193386898, 8),
- /* K7 */ be_nested_string("get", 1410115415, 3),
- /* K8 */ be_nested_string("widget_event", 1951408186, 12),
+ /* K0 */ be_nested_str(introspect),
+ /* K1 */ be_nested_str(lv),
+ /* K2 */ be_nested_str(lv_obj_class),
+ /* K3 */ be_nested_str(lv_event),
+ /* K4 */ be_nested_str(target),
+ /* K5 */ be_nested_str(get_object_from_ptr),
+ /* K6 */ be_nested_str(instance),
+ /* K7 */ be_nested_str(get),
+ /* K8 */ be_nested_str(widget_event),
}),
- (be_nested_const_str("widget_event_impl", -2116536735, 17)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_widget_event_impl,
+ &be_const_str_solidified,
( &(const binstruction[30]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0xB8120200, // 0001 GETNGBL R4 K1
@@ -109,7 +109,7 @@ be_local_closure(widget_event_impl, /* name */
/********************************************************************
** Solidified function: lvgl_event_dispatch
********************************************************************/
-be_local_closure(lvgl_event_dispatch, /* name */
+be_local_closure(LVGL_glob_lvgl_event_dispatch, /* name */
be_nested_proto(
10, /* nstack */
2, /* argc */
@@ -120,16 +120,16 @@ be_local_closure(lvgl_event_dispatch, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("introspect", 164638290, 10),
- /* K1 */ be_nested_string("lv", 1529997255, 2),
- /* K2 */ be_nested_string("lv_event", -1860877328, 8),
- /* K3 */ be_nested_string("toptr", -915119842, 5),
- /* K4 */ be_nested_string("target", 845187144, 6),
- /* K5 */ be_nested_string("cb_event_closure", -466699971, 16),
- /* K6 */ be_nested_string("get_object_from_ptr", -1949948095, 19),
+ /* K0 */ be_nested_str(introspect),
+ /* K1 */ be_nested_str(lv),
+ /* K2 */ be_nested_str(lv_event),
+ /* K3 */ be_nested_str(toptr),
+ /* K4 */ be_nested_str(target),
+ /* K5 */ be_nested_str(cb_event_closure),
+ /* K6 */ be_nested_str(get_object_from_ptr),
}),
- (be_nested_const_str("lvgl_event_dispatch", 2104396622, 19)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_lvgl_event_dispatch,
+ &be_const_str_solidified,
( &(const binstruction[20]) { /* code */
0xA40A0000, // 0000 IMPORT R2 K0
0xB80E0200, // 0001 GETNGBL R3 K1
@@ -160,7 +160,7 @@ be_local_closure(lvgl_event_dispatch, /* name */
/********************************************************************
** Solidified function: widget_dtor_impl
********************************************************************/
-be_local_closure(widget_dtor_impl, /* name */
+be_local_closure(LVGL_glob_widget_dtor_impl, /* name */
be_nested_proto(
10, /* nstack */
3, /* argc */
@@ -171,16 +171,16 @@ be_local_closure(widget_dtor_impl, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("introspect", 164638290, 10),
- /* K1 */ be_nested_string("lv", 1529997255, 2),
- /* K2 */ be_nested_string("lv_obj_class", -255311002, 12),
- /* K3 */ be_nested_string("get_object_from_ptr", -1949948095, 19),
- /* K4 */ be_nested_string("instance", 193386898, 8),
- /* K5 */ be_nested_string("get", 1410115415, 3),
- /* K6 */ be_nested_string("widget_destructor", -87578951, 17),
+ /* K0 */ be_nested_str(introspect),
+ /* K1 */ be_nested_str(lv),
+ /* K2 */ be_nested_str(lv_obj_class),
+ /* K3 */ be_nested_str(get_object_from_ptr),
+ /* K4 */ be_nested_str(instance),
+ /* K5 */ be_nested_str(get),
+ /* K6 */ be_nested_str(widget_destructor),
}),
- (be_nested_const_str("widget_dtor_impl", 520430610, 16)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_widget_dtor_impl,
+ &be_const_str_solidified,
( &(const binstruction[22]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0xB8120200, // 0001 GETNGBL R4 K1
@@ -213,7 +213,7 @@ be_local_closure(widget_dtor_impl, /* name */
/********************************************************************
** Solidified function: register_obj
********************************************************************/
-be_local_closure(register_obj, /* name */
+be_local_closure(LVGL_glob_register_obj, /* name */
be_nested_proto(
4, /* nstack */
2, /* argc */
@@ -224,11 +224,11 @@ be_local_closure(register_obj, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("cb_obj", 1195696482, 6),
- /* K1 */ be_nested_string("_p", 1594591802, 2),
+ /* K0 */ be_nested_str(cb_obj),
+ /* K1 */ be_nested_str(_p),
}),
- (be_nested_const_str("register_obj", -312352526, 12)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_register_obj,
+ &be_const_str_solidified,
( &(const binstruction[13]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x4C0C0000, // 0001 LDNIL R3
@@ -252,7 +252,7 @@ be_local_closure(register_obj, /* name */
/********************************************************************
** Solidified function: gen_cb
********************************************************************/
-be_local_closure(gen_cb, /* name */
+be_local_closure(LVGL_glob_gen_cb, /* name */
be_nested_proto(
8, /* nstack */
5, /* argc */
@@ -273,10 +273,10 @@ be_local_closure(gen_cb, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("lvgl_event_dispatch", 2104396622, 19),
+ /* K0 */ be_nested_str(lvgl_event_dispatch),
}),
- (be_nested_const_str("", 607256038, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__X3Clambda_X3E,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x68040000, // 0000 GETUPV R1 U0
0x8C040300, // 0001 GETMET R1 R1 K0
@@ -288,17 +288,17 @@ be_local_closure(gen_cb, /* name */
}),
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
- /* K0 */ be_nested_string("lv_event_cb", -1814236280, 11),
- /* K1 */ be_nested_string("cb_event_closure", -466699971, 16),
- /* K2 */ be_nested_string("event_cb", -1166269279, 8),
- /* K3 */ be_nested_string("tasmota", 424643812, 7),
- /* K4 */ be_nested_string("gen_cb", -1049739745, 6),
- /* K5 */ be_nested_string("register_obj", -312352526, 12),
- /* K6 */ be_nested_string("null_cb", -1961430836, 7),
- /* K7 */ be_nested_string("cb_do_nothing", 1488730702, 13),
+ /* K0 */ be_nested_str(lv_event_cb),
+ /* K1 */ be_nested_str(cb_event_closure),
+ /* K2 */ be_nested_str(event_cb),
+ /* K3 */ be_nested_str(tasmota),
+ /* K4 */ be_nested_str(gen_cb),
+ /* K5 */ be_nested_str(register_obj),
+ /* K6 */ be_nested_str(null_cb),
+ /* K7 */ be_nested_str(cb_do_nothing),
}),
- (be_nested_const_str("gen_cb", -1049739745, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_gen_cb,
+ &be_const_str_solidified,
( &(const binstruction[41]) { /* code */
0x1C140300, // 0000 EQ R5 R1 K0
0x78160018, // 0001 JMPF R5 #001B
@@ -350,7 +350,7 @@ be_local_closure(gen_cb, /* name */
/********************************************************************
** Solidified function: deregister_obj
********************************************************************/
-be_local_closure(deregister_obj, /* name */
+be_local_closure(LVGL_glob_deregister_obj, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -361,12 +361,12 @@ be_local_closure(deregister_obj, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("cb_obj", 1195696482, 6),
- /* K1 */ be_nested_string("remove", -611183107, 6),
- /* K2 */ be_nested_string("cb_event_closure", -466699971, 16),
+ /* K0 */ be_nested_str(cb_obj),
+ /* K1 */ be_nested_str(remove),
+ /* K2 */ be_nested_str(cb_event_closure),
}),
- (be_nested_const_str("deregister_obj", -385000303, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_deregister_obj,
+ &be_const_str_solidified,
( &(const binstruction[17]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x4C0C0000, // 0001 LDNIL R3
@@ -394,7 +394,7 @@ be_local_closure(deregister_obj, /* name */
/********************************************************************
** Solidified function: widget_cb
********************************************************************/
-be_local_closure(widget_cb, /* name */
+be_local_closure(LVGL_glob_widget_cb, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -415,10 +415,10 @@ be_local_closure(widget_cb, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("widget_ctor_impl", 194252479, 16),
+ /* K0 */ be_nested_str(widget_ctor_impl),
}),
- (be_nested_const_str("", 607256038, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__X3Clambda_X3E,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x68080000, // 0000 GETUPV R2 U0
0x8C080500, // 0001 GETMET R2 R2 K0
@@ -440,10 +440,10 @@ be_local_closure(widget_cb, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("widget_dtor_impl", 520430610, 16),
+ /* K0 */ be_nested_str(widget_dtor_impl),
}),
- (be_nested_const_str("", 607256038, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__X3Clambda_X3E,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x68080000, // 0000 GETUPV R2 U0
0x8C080500, // 0001 GETMET R2 R2 K0
@@ -465,10 +465,10 @@ be_local_closure(widget_cb, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("widget_event_impl", -2116536735, 17),
+ /* K0 */ be_nested_str(widget_event_impl),
}),
- (be_nested_const_str("", 607256038, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__X3Clambda_X3E,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x68080000, // 0000 GETUPV R2 U0
0x8C080500, // 0001 GETMET R2 R2 K0
@@ -481,24 +481,24 @@ be_local_closure(widget_cb, /* name */
}),
1, /* has constants */
( &(const bvalue[15]) { /* constants */
- /* K0 */ be_nested_string("widget_ctor_cb", 876007560, 14),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("gen_cb", -1049739745, 6),
- /* K3 */ be_nested_string("widget_dtor_cb", -1143421451, 14),
- /* K4 */ be_nested_string("widget_event_cb", 1508466754, 15),
- /* K5 */ be_nested_string("widget_struct_default", 781673633, 21),
- /* K6 */ be_nested_string("lv", 1529997255, 2),
- /* K7 */ be_nested_string("lv_obj_class", -255311002, 12),
- /* K8 */ be_nested_string("lv_obj", -37134147, 6),
- /* K9 */ be_nested_string("_class", -1562820946, 6),
- /* K10 */ be_nested_string("copy", -446502332, 4),
- /* K11 */ be_nested_string("base_class", 1107737279, 10),
- /* K12 */ be_nested_string("constructor_cb", -1805861999, 14),
- /* K13 */ be_nested_string("destructor_cb", 1930283190, 13),
- /* K14 */ be_nested_string("event_cb", -1166269279, 8),
+ /* K0 */ be_nested_str(widget_ctor_cb),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(gen_cb),
+ /* K3 */ be_nested_str(widget_dtor_cb),
+ /* K4 */ be_nested_str(widget_event_cb),
+ /* K5 */ be_nested_str(widget_struct_default),
+ /* K6 */ be_nested_str(lv),
+ /* K7 */ be_nested_str(lv_obj_class),
+ /* K8 */ be_nested_str(lv_obj),
+ /* K9 */ be_nested_str(_class),
+ /* K10 */ be_nested_str(copy),
+ /* K11 */ be_nested_str(base_class),
+ /* K12 */ be_nested_str(constructor_cb),
+ /* K13 */ be_nested_str(destructor_cb),
+ /* K14 */ be_nested_str(event_cb),
}),
- (be_nested_const_str("widget_cb", -1531384241, 9)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_widget_cb,
+ &be_const_str_solidified,
( &(const binstruction[56]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x4C080000, // 0001 LDNIL R2
@@ -565,7 +565,7 @@ be_local_closure(widget_cb, /* name */
/********************************************************************
** Solidified function: _anonymous_
********************************************************************/
-be_local_closure(_anonymous_, /* name */
+be_local_closure(LVGL_glob__anonymous_, /* name */
be_nested_proto(
2, /* nstack */
0, /* argc */
@@ -576,10 +576,10 @@ be_local_closure(_anonymous_, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("LVG: call to unsupported callback", 504176819, 33),
+ /* K0 */ be_nested_str(LVG_X3A_X20call_X20to_X20unsupported_X20callback),
}),
- (be_nested_const_str("_anonymous_", 1957281476, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__anonymous_,
+ &be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x60000001, // 0000 GETGBL R0 G1
0x58040000, // 0001 LDCONST R1 K0
@@ -594,7 +594,7 @@ be_local_closure(_anonymous_, /* name */
/********************************************************************
** Solidified function: create_custom_widget
********************************************************************/
-be_local_closure(create_custom_widget, /* name */
+be_local_closure(LVGL_glob_create_custom_widget, /* name */
be_nested_proto(
10, /* nstack */
3, /* argc */
@@ -605,36 +605,36 @@ be_local_closure(create_custom_widget, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[27]) { /* constants */
- /* K0 */ be_nested_string("introspect", 164638290, 10),
- /* K1 */ be_nested_string("lv", 1529997255, 2),
- /* K2 */ be_nested_string("lv_obj", -37134147, 6),
- /* K3 */ be_nested_string("value_error", 773297791, 11),
- /* K4 */ be_nested_string("arg must be a subclass of lv_obj", 1641882079, 32),
- /* K5 */ be_nested_string("widget_struct_by_class", -488593454, 22),
- /* K6 */ be_nested_string("find", -1108310694, 4),
- /* K7 */ be_nested_string("widget_cb", -1531384241, 9),
- /* K8 */ be_nested_string("widget_struct_default", 781673633, 21),
- /* K9 */ be_nested_string("copy", -446502332, 4),
- /* K10 */ be_nested_string("base_class", 1107737279, 10),
- /* K11 */ be_nested_string("_class", -1562820946, 6),
- /* K12 */ be_nested_string("get", 1410115415, 3),
- /* K13 */ be_nested_string("widget_width_def", -308888434, 16),
- /* K14 */ be_nested_string("width_def", 1143717879, 9),
- /* K15 */ be_nested_string("widget_height_def", -1163299483, 17),
- /* K16 */ be_nested_string("height_def", -1946728458, 10),
- /* K17 */ be_nested_string("widget_editable", -473174010, 15),
- /* K18 */ be_nested_string("editable", 60532369, 8),
- /* K19 */ be_nested_string("widget_group_def", 1246968785, 16),
- /* K20 */ be_nested_string("group_def", 1524213328, 9),
- /* K21 */ be_nested_string("widget_instance_size", 2055354779, 20),
- /* K22 */ be_nested_string("instance_size", -14697778, 13),
- /* K23 */ be_nested_string("obj_class_create_obj", -990576664, 20),
- /* K24 */ be_nested_string("_p", 1594591802, 2),
- /* K25 */ be_nested_string("register_obj", -312352526, 12),
- /* K26 */ be_nested_string("class_init_obj", 178410604, 14),
+ /* K0 */ be_nested_str(introspect),
+ /* K1 */ be_nested_str(lv),
+ /* K2 */ be_nested_str(lv_obj),
+ /* K3 */ be_nested_str(value_error),
+ /* K4 */ be_nested_str(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj),
+ /* K5 */ be_nested_str(widget_struct_by_class),
+ /* K6 */ be_nested_str(find),
+ /* K7 */ be_nested_str(widget_cb),
+ /* K8 */ be_nested_str(widget_struct_default),
+ /* K9 */ be_nested_str(copy),
+ /* K10 */ be_nested_str(base_class),
+ /* K11 */ be_nested_str(_class),
+ /* K12 */ be_nested_str(get),
+ /* K13 */ be_nested_str(widget_width_def),
+ /* K14 */ be_nested_str(width_def),
+ /* K15 */ be_nested_str(widget_height_def),
+ /* K16 */ be_nested_str(height_def),
+ /* K17 */ be_nested_str(widget_editable),
+ /* K18 */ be_nested_str(editable),
+ /* K19 */ be_nested_str(widget_group_def),
+ /* K20 */ be_nested_str(group_def),
+ /* K21 */ be_nested_str(widget_instance_size),
+ /* K22 */ be_nested_str(instance_size),
+ /* K23 */ be_nested_str(obj_class_create_obj),
+ /* K24 */ be_nested_str(_p),
+ /* K25 */ be_nested_str(register_obj),
+ /* K26 */ be_nested_str(class_init_obj),
}),
- (be_nested_const_str("create_custom_widget", 1140594778, 20)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_create_custom_widget,
+ &be_const_str_solidified,
( &(const binstruction[86]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0x6010000F, // 0001 GETGBL R4 G15
@@ -731,7 +731,7 @@ be_local_closure(create_custom_widget, /* name */
/********************************************************************
** Solidified function: widget_ctor_impl
********************************************************************/
-be_local_closure(widget_ctor_impl, /* name */
+be_local_closure(LVGL_glob_widget_ctor_impl, /* name */
be_nested_proto(
10, /* nstack */
3, /* argc */
@@ -742,18 +742,18 @@ be_local_closure(widget_ctor_impl, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 9]) { /* constants */
- /* K0 */ be_nested_string("introspect", 164638290, 10),
- /* K1 */ be_nested_string("lv", 1529997255, 2),
- /* K2 */ be_nested_string("lv_obj_class", -255311002, 12),
- /* K3 */ be_nested_string("get_object_from_ptr", -1949948095, 19),
- /* K4 */ be_nested_string("cb_obj", 1195696482, 6),
- /* K5 */ be_nested_string("find", -1108310694, 4),
- /* K6 */ be_nested_string("instance", 193386898, 8),
- /* K7 */ be_nested_string("get", 1410115415, 3),
- /* K8 */ be_nested_string("widget_constructor", -1751181362, 18),
+ /* K0 */ be_nested_str(introspect),
+ /* K1 */ be_nested_str(lv),
+ /* K2 */ be_nested_str(lv_obj_class),
+ /* K3 */ be_nested_str(get_object_from_ptr),
+ /* K4 */ be_nested_str(cb_obj),
+ /* K5 */ be_nested_str(find),
+ /* K6 */ be_nested_str(instance),
+ /* K7 */ be_nested_str(get),
+ /* K8 */ be_nested_str(widget_constructor),
}),
- (be_nested_const_str("widget_ctor_impl", 194252479, 16)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_widget_ctor_impl,
+ &be_const_str_solidified,
( &(const binstruction[29]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0xB8120200, // 0001 GETNGBL R4 K1
@@ -798,28 +798,28 @@ be_local_class(LVGL_glob,
NULL,
be_nested_map(20,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("widget_ctor_cb", 876007560, 14, 9), be_const_var(4) },
- { be_nested_key("get_object_from_ptr", -1949948095, 19, 4), be_const_closure(get_object_from_ptr_closure) },
- { be_nested_key("cb_obj", 1195696482, 6, 7), be_const_var(0) },
- { be_nested_key("widget_struct_by_class", -488593454, 22, -1), be_const_var(8) },
- { be_nested_key("widget_event_impl", -2116536735, 17, -1), be_const_closure(widget_event_impl_closure) },
- { be_nested_key("widget_dtor_cb", -1143421451, 14, 6), be_const_var(5) },
- { be_nested_key("cb_event_closure", -466699971, 16, -1), be_const_var(1) },
- { be_nested_key("lvgl_event_dispatch", 2104396622, 19, 16), be_const_closure(lvgl_event_dispatch_closure) },
- { be_nested_key("widget_dtor_impl", 520430610, 16, -1), be_const_closure(widget_dtor_impl_closure) },
- { be_nested_key("null_cb", -1961430836, 7, -1), be_const_var(3) },
- { be_nested_key("register_obj", -312352526, 12, 8), be_const_closure(register_obj_closure) },
- { be_nested_key("gen_cb", -1049739745, 6, -1), be_const_closure(gen_cb_closure) },
- { be_nested_key("widget_struct_default", 781673633, 21, -1), be_const_var(7) },
- { be_nested_key("deregister_obj", -385000303, 14, 12), be_const_closure(deregister_obj_closure) },
- { be_nested_key("widget_event_cb", 1508466754, 15, -1), be_const_var(6) },
- { be_nested_key("widget_cb", -1531384241, 9, -1), be_const_closure(widget_cb_closure) },
- { be_nested_key("cb_do_nothing", 1488730702, 13, 3), be_const_closure(_anonymous__closure) },
- { be_nested_key("event_cb", -1166269279, 8, -1), be_const_var(2) },
- { be_nested_key("create_custom_widget", 1140594778, 20, -1), be_const_closure(create_custom_widget_closure) },
- { be_nested_key("widget_ctor_impl", 194252479, 16, -1), be_const_closure(widget_ctor_impl_closure) },
+ { be_const_key(widget_ctor_cb, 9), be_const_var(4) },
+ { be_const_key(get_object_from_ptr, 4), be_const_closure(LVGL_glob_get_object_from_ptr_closure) },
+ { be_const_key(cb_obj, 7), be_const_var(0) },
+ { be_const_key(widget_struct_by_class, -1), be_const_var(8) },
+ { be_const_key(widget_event_impl, -1), be_const_closure(LVGL_glob_widget_event_impl_closure) },
+ { be_const_key(widget_dtor_cb, 6), be_const_var(5) },
+ { be_const_key(cb_event_closure, -1), be_const_var(1) },
+ { be_const_key(lvgl_event_dispatch, 16), be_const_closure(LVGL_glob_lvgl_event_dispatch_closure) },
+ { be_const_key(widget_dtor_impl, -1), be_const_closure(LVGL_glob_widget_dtor_impl_closure) },
+ { be_const_key(null_cb, -1), be_const_var(3) },
+ { be_const_key(register_obj, 8), be_const_closure(LVGL_glob_register_obj_closure) },
+ { be_const_key(gen_cb, -1), be_const_closure(LVGL_glob_gen_cb_closure) },
+ { be_const_key(widget_struct_default, -1), be_const_var(7) },
+ { be_const_key(deregister_obj, 12), be_const_closure(LVGL_glob_deregister_obj_closure) },
+ { be_const_key(widget_event_cb, -1), be_const_var(6) },
+ { be_const_key(widget_cb, -1), be_const_closure(LVGL_glob_widget_cb_closure) },
+ { be_const_key(cb_do_nothing, 3), be_const_closure(LVGL_glob__anonymous__closure) },
+ { be_const_key(event_cb, -1), be_const_var(2) },
+ { be_const_key(create_custom_widget, -1), be_const_closure(LVGL_glob_create_custom_widget_closure) },
+ { be_const_key(widget_ctor_impl, -1), be_const_closure(LVGL_glob_widget_ctor_impl_closure) },
})),
- (be_nested_const_str("LVGL_glob", 315437079, 9))
+ be_str_literal("LVGL_glob")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_lvgl_signal_arcs_lib.c b/lib/libesp32/Berry/default/be_lvgl_signal_arcs_lib.c
index f3452ba57..a127cddd9 100644
--- a/lib/libesp32/Berry/default/be_lvgl_signal_arcs_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_signal_arcs_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: set_percentage
********************************************************************/
-be_local_closure(set_percentage, /* name */
+be_local_closure(lv_signal_arcs_set_percentage, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -21,12 +21,12 @@ be_local_closure(set_percentage, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("percentage", -1756136011, 10),
+ /* K0 */ be_nested_str(percentage),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_string("invalidate", -1645232368, 10),
+ /* K2 */ be_nested_str(invalidate),
}),
- (be_nested_const_str("set_percentage", -1342944572, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_percentage,
+ &be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x540E0018, // 0001 LDINT R3 25
@@ -55,7 +55,7 @@ be_local_closure(set_percentage, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(lv_signal_arcs_init, /* name */
be_nested_proto(
6, /* nstack */
2, /* argc */
@@ -66,19 +66,19 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_string("_lvgl", -1605747813, 5),
- /* K1 */ be_nested_string("create_custom_widget", 1140594778, 20),
- /* K2 */ be_nested_string("percentage", -1756136011, 10),
- /* K3 */ be_nested_string("p1", -1605446022, 2),
- /* K4 */ be_nested_string("lv", 1529997255, 2),
- /* K5 */ be_nested_string("point", 414084241, 5),
- /* K6 */ be_nested_string("p2", -1622223641, 2),
- /* K7 */ be_nested_string("area", -1693507260, 4),
- /* K8 */ be_nested_string("line_dsc", -200476318, 8),
- /* K9 */ be_nested_string("draw_line_dsc", -74291093, 13),
+ /* K0 */ be_nested_str(_lvgl),
+ /* K1 */ be_nested_str(create_custom_widget),
+ /* K2 */ be_nested_str(percentage),
+ /* K3 */ be_nested_str(p1),
+ /* K4 */ be_nested_str(lv),
+ /* K5 */ be_nested_str(point),
+ /* K6 */ be_nested_str(p2),
+ /* K7 */ be_nested_str(area),
+ /* K8 */ be_nested_str(line_dsc),
+ /* K9 */ be_nested_str(draw_line_dsc),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[24]) { /* code */
0xB80A0000, // 0000 GETNGBL R2 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -113,7 +113,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: widget_event
********************************************************************/
-be_local_closure(widget_event, /* name */
+be_local_closure(lv_signal_arcs_widget_event, /* name */
be_nested_proto(
28, /* nstack */
3, /* argc */
@@ -134,8 +134,8 @@ be_local_closure(widget_event, /* name */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_const_int(1),
}),
- (be_nested_const_str("atleast1", 1956331672, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_atleast1,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x28040100, // 0000 GE R1 R0 K0
0x78060001, // 0001 JMPF R1 #0004
@@ -148,44 +148,44 @@ be_local_closure(widget_event, /* name */
}),
1, /* has constants */
( &(const bvalue[35]) { /* constants */
- /* K0 */ be_nested_string("lv", 1529997255, 2),
- /* K1 */ be_nested_string("obj_event_base", 1624064363, 14),
- /* K2 */ be_nested_string("RES_OK", 1233817284, 6),
- /* K3 */ be_nested_string("code", -114201356, 4),
- /* K4 */ be_nested_string("math", -293037681, 4),
- /* K5 */ be_nested_string("get_height", -723211773, 10),
- /* K6 */ be_nested_string("get_width", -1001549996, 9),
+ /* K0 */ be_nested_str(lv),
+ /* K1 */ be_nested_str(obj_event_base),
+ /* K2 */ be_nested_str(RES_OK),
+ /* K3 */ be_nested_str(code),
+ /* K4 */ be_nested_str(math),
+ /* K5 */ be_nested_str(get_height),
+ /* K6 */ be_nested_str(get_width),
/* K7 */ be_const_int(2),
/* K8 */ be_const_int(3),
- /* K9 */ be_nested_string("EVENT_DRAW_MAIN", 1955620614, 15),
- /* K10 */ be_nested_string("area", -1693507260, 4),
- /* K11 */ be_nested_string("param", 1309554226, 5),
- /* K12 */ be_nested_string("get_coords", 1044089006, 10),
- /* K13 */ be_nested_string("x1", 274927234, 2),
- /* K14 */ be_nested_string("y1", -1939865569, 2),
- /* K15 */ be_nested_string("draw_line_dsc_init", -428273650, 18),
- /* K16 */ be_nested_string("line_dsc", -200476318, 8),
- /* K17 */ be_nested_string("init_draw_line_dsc", -1787031256, 18),
- /* K18 */ be_nested_string("PART_MAIN", -1821475788, 9),
- /* K19 */ be_nested_string("round_start", -1345482912, 11),
+ /* K9 */ be_nested_str(EVENT_DRAW_MAIN),
+ /* K10 */ be_nested_str(area),
+ /* K11 */ be_nested_str(param),
+ /* K12 */ be_nested_str(get_coords),
+ /* K13 */ be_nested_str(x1),
+ /* K14 */ be_nested_str(y1),
+ /* K15 */ be_nested_str(draw_line_dsc_init),
+ /* K16 */ be_nested_str(line_dsc),
+ /* K17 */ be_nested_str(init_draw_line_dsc),
+ /* K18 */ be_nested_str(PART_MAIN),
+ /* K19 */ be_nested_str(round_start),
/* K20 */ be_const_int(1),
- /* K21 */ be_nested_string("round_end", 985288225, 9),
- /* K22 */ be_nested_string("width", -1786286561, 5),
- /* K23 */ be_nested_string("get_style_line_color", 805371932, 20),
- /* K24 */ be_nested_string("STATE_DEFAULT", 712406428, 13),
- /* K25 */ be_nested_string("get_style_bg_color", 964794381, 18),
- /* K26 */ be_nested_string("deg", -967213025, 3),
- /* K27 */ be_nested_string("acos", 1006755615, 4),
- /* K28 */ be_nested_string("p1", -1605446022, 2),
- /* K29 */ be_nested_string("x", -49524601, 1),
- /* K30 */ be_nested_string("y", -66302220, 1),
- /* K31 */ be_nested_string("color", 1031692888, 5),
- /* K32 */ be_nested_string("percentage", -1756136011, 10),
- /* K33 */ be_nested_string("draw_arc", 1828251676, 8),
+ /* K21 */ be_nested_str(round_end),
+ /* K22 */ be_nested_str(width),
+ /* K23 */ be_nested_str(get_style_line_color),
+ /* K24 */ be_nested_str(STATE_DEFAULT),
+ /* K25 */ be_nested_str(get_style_bg_color),
+ /* K26 */ be_nested_str(deg),
+ /* K27 */ be_nested_str(acos),
+ /* K28 */ be_nested_str(p1),
+ /* K29 */ be_nested_str(x),
+ /* K30 */ be_nested_str(y),
+ /* K31 */ be_nested_str(color),
+ /* K32 */ be_nested_str(percentage),
+ /* K33 */ be_nested_str(draw_arc),
/* K34 */ be_const_int(0),
}),
- (be_nested_const_str("widget_event", 1951408186, 12)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_widget_event,
+ &be_const_str_solidified,
( &(const binstruction[182]) { /* code */
0xB80E0000, // 0000 GETNGBL R3 K0
0x8C0C0701, // 0001 GETMET R3 R3 K1
@@ -378,7 +378,7 @@ be_local_closure(widget_event, /* name */
/********************************************************************
** Solidified function: get_percentage
********************************************************************/
-be_local_closure(get_percentage, /* name */
+be_local_closure(lv_signal_arcs_get_percentage, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
@@ -389,10 +389,10 @@ be_local_closure(get_percentage, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("percentage", -1756136011, 10),
+ /* K0 */ be_nested_str(percentage),
}),
- (be_nested_const_str("get_percentage", -1414483304, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_percentage,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x80040200, // 0001 RET 1 R1
@@ -411,17 +411,17 @@ be_local_class(lv_signal_arcs,
&be_class_lv_obj,
be_nested_map(9,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("percentage", -1756136011, 10, 4), be_const_var(0) },
- { be_nested_key("p1", -1605446022, 2, 3), be_const_var(1) },
- { be_nested_key("p2", -1622223641, 2, -1), be_const_var(2) },
- { be_nested_key("area", -1693507260, 4, -1), be_const_var(3) },
- { be_nested_key("line_dsc", -200476318, 8, -1), be_const_var(4) },
- { be_nested_key("set_percentage", -1342944572, 14, -1), be_const_closure(set_percentage_closure) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
- { be_nested_key("widget_event", 1951408186, 12, -1), be_const_closure(widget_event_closure) },
- { be_nested_key("get_percentage", -1414483304, 14, 5), be_const_closure(get_percentage_closure) },
+ { be_const_key(percentage, 4), be_const_var(0) },
+ { be_const_key(p1, 3), be_const_var(1) },
+ { be_const_key(p2, -1), be_const_var(2) },
+ { be_const_key(area, -1), be_const_var(3) },
+ { be_const_key(line_dsc, -1), be_const_var(4) },
+ { be_const_key(set_percentage, -1), be_const_closure(lv_signal_arcs_set_percentage_closure) },
+ { be_const_key(init, -1), be_const_closure(lv_signal_arcs_init_closure) },
+ { be_const_key(widget_event, -1), be_const_closure(lv_signal_arcs_widget_event_closure) },
+ { be_const_key(get_percentage, 5), be_const_closure(lv_signal_arcs_get_percentage_closure) },
})),
- (be_nested_const_str("lv_signal_arcs", -1455810308, 14))
+ be_str_literal("lv_signal_arcs")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_lvgl_signal_bars_lib.c b/lib/libesp32/Berry/default/be_lvgl_signal_bars_lib.c
index 161afc65d..18452ae34 100644
--- a/lib/libesp32/Berry/default/be_lvgl_signal_bars_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_signal_bars_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: set_percentage
********************************************************************/
-be_local_closure(set_percentage, /* name */
+be_local_closure(lv_signal_bars_set_percentage, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -21,12 +21,12 @@ be_local_closure(set_percentage, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("percentage", -1756136011, 10),
+ /* K0 */ be_nested_str(percentage),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_string("invalidate", -1645232368, 10),
+ /* K2 */ be_nested_str(invalidate),
}),
- (be_nested_const_str("set_percentage", -1342944572, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_set_percentage,
+ &be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x540E0013, // 0001 LDINT R3 20
@@ -55,7 +55,7 @@ be_local_closure(set_percentage, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(lv_signal_bars_init, /* name */
be_nested_proto(
6, /* nstack */
2, /* argc */
@@ -66,19 +66,19 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_string("_lvgl", -1605747813, 5),
- /* K1 */ be_nested_string("create_custom_widget", 1140594778, 20),
- /* K2 */ be_nested_string("percentage", -1756136011, 10),
- /* K3 */ be_nested_string("p1", -1605446022, 2),
- /* K4 */ be_nested_string("lv", 1529997255, 2),
- /* K5 */ be_nested_string("point", 414084241, 5),
- /* K6 */ be_nested_string("p2", -1622223641, 2),
- /* K7 */ be_nested_string("area", -1693507260, 4),
- /* K8 */ be_nested_string("line_dsc", -200476318, 8),
- /* K9 */ be_nested_string("draw_line_dsc", -74291093, 13),
+ /* K0 */ be_nested_str(_lvgl),
+ /* K1 */ be_nested_str(create_custom_widget),
+ /* K2 */ be_nested_str(percentage),
+ /* K3 */ be_nested_str(p1),
+ /* K4 */ be_nested_str(lv),
+ /* K5 */ be_nested_str(point),
+ /* K6 */ be_nested_str(p2),
+ /* K7 */ be_nested_str(area),
+ /* K8 */ be_nested_str(line_dsc),
+ /* K9 */ be_nested_str(draw_line_dsc),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[24]) { /* code */
0xB80A0000, // 0000 GETNGBL R2 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -113,7 +113,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: widget_event
********************************************************************/
-be_local_closure(widget_event, /* name */
+be_local_closure(lv_signal_bars_widget_event, /* name */
be_nested_proto(
23, /* nstack */
3, /* argc */
@@ -134,8 +134,8 @@ be_local_closure(widget_event, /* name */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_const_int(1),
}),
- (be_nested_const_str("atleast1", 1956331672, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_atleast1,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x28040100, // 0000 GE R1 R0 K0
0x78060001, // 0001 JMPF R1 #0004
@@ -148,46 +148,46 @@ be_local_closure(widget_event, /* name */
}),
1, /* has constants */
( &(const bvalue[37]) { /* constants */
- /* K0 */ be_nested_string("lv", 1529997255, 2),
- /* K1 */ be_nested_string("obj_event_base", 1624064363, 14),
- /* K2 */ be_nested_string("RES_OK", 1233817284, 6),
- /* K3 */ be_nested_string("code", -114201356, 4),
- /* K4 */ be_nested_string("get_height", -723211773, 10),
- /* K5 */ be_nested_string("get_width", -1001549996, 9),
+ /* K0 */ be_nested_str(lv),
+ /* K1 */ be_nested_str(obj_event_base),
+ /* K2 */ be_nested_str(RES_OK),
+ /* K3 */ be_nested_str(code),
+ /* K4 */ be_nested_str(get_height),
+ /* K5 */ be_nested_str(get_width),
/* K6 */ be_const_int(3),
/* K7 */ be_const_int(2),
- /* K8 */ be_nested_string("EVENT_DRAW_MAIN", 1955620614, 15),
- /* K9 */ be_nested_string("area", -1693507260, 4),
- /* K10 */ be_nested_string("param", 1309554226, 5),
- /* K11 */ be_nested_string("get_coords", 1044089006, 10),
- /* K12 */ be_nested_string("x1", 274927234, 2),
- /* K13 */ be_nested_string("y1", -1939865569, 2),
- /* K14 */ be_nested_string("draw_line_dsc_init", -428273650, 18),
- /* K15 */ be_nested_string("line_dsc", -200476318, 8),
- /* K16 */ be_nested_string("init_draw_line_dsc", -1787031256, 18),
- /* K17 */ be_nested_string("PART_MAIN", -1821475788, 9),
- /* K18 */ be_nested_string("round_start", -1345482912, 11),
+ /* K8 */ be_nested_str(EVENT_DRAW_MAIN),
+ /* K9 */ be_nested_str(area),
+ /* K10 */ be_nested_str(param),
+ /* K11 */ be_nested_str(get_coords),
+ /* K12 */ be_nested_str(x1),
+ /* K13 */ be_nested_str(y1),
+ /* K14 */ be_nested_str(draw_line_dsc_init),
+ /* K15 */ be_nested_str(line_dsc),
+ /* K16 */ be_nested_str(init_draw_line_dsc),
+ /* K17 */ be_nested_str(PART_MAIN),
+ /* K18 */ be_nested_str(round_start),
/* K19 */ be_const_int(1),
- /* K20 */ be_nested_string("round_end", 985288225, 9),
- /* K21 */ be_nested_string("width", -1786286561, 5),
- /* K22 */ be_nested_string("get_style_line_color", 805371932, 20),
- /* K23 */ be_nested_string("STATE_DEFAULT", 712406428, 13),
- /* K24 */ be_nested_string("get_style_bg_color", 964794381, 18),
- /* K25 */ be_nested_string("event_send", 598925582, 10),
- /* K26 */ be_nested_string("EVENT_DRAW_PART_BEGIN", -903102272, 21),
+ /* K20 */ be_nested_str(round_end),
+ /* K21 */ be_nested_str(width),
+ /* K22 */ be_nested_str(get_style_line_color),
+ /* K23 */ be_nested_str(STATE_DEFAULT),
+ /* K24 */ be_nested_str(get_style_bg_color),
+ /* K25 */ be_nested_str(event_send),
+ /* K26 */ be_nested_str(EVENT_DRAW_PART_BEGIN),
/* K27 */ be_const_int(0),
- /* K28 */ be_nested_string("color", 1031692888, 5),
- /* K29 */ be_nested_string("percentage", -1756136011, 10),
- /* K30 */ be_nested_string("p1", -1605446022, 2),
- /* K31 */ be_nested_string("y", -66302220, 1),
- /* K32 */ be_nested_string("x", -49524601, 1),
- /* K33 */ be_nested_string("p2", -1622223641, 2),
- /* K34 */ be_nested_string("draw_line", 1634465686, 9),
- /* K35 */ be_nested_string("stop_iteration", -121173395, 14),
- /* K36 */ be_nested_string("EVENT_DRAW_PART_END", -993342004, 19),
+ /* K28 */ be_nested_str(color),
+ /* K29 */ be_nested_str(percentage),
+ /* K30 */ be_nested_str(p1),
+ /* K31 */ be_nested_str(y),
+ /* K32 */ be_nested_str(x),
+ /* K33 */ be_nested_str(p2),
+ /* K34 */ be_nested_str(draw_line),
+ /* K35 */ be_nested_str(stop_iteration),
+ /* K36 */ be_nested_str(EVENT_DRAW_PART_END),
}),
- (be_nested_const_str("widget_event", 1951408186, 12)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_widget_event,
+ &be_const_str_solidified,
( &(const binstruction[138]) { /* code */
0xB80E0000, // 0000 GETNGBL R3 K0
0x8C0C0701, // 0001 GETMET R3 R3 K1
@@ -336,7 +336,7 @@ be_local_closure(widget_event, /* name */
/********************************************************************
** Solidified function: get_percentage
********************************************************************/
-be_local_closure(get_percentage, /* name */
+be_local_closure(lv_signal_bars_get_percentage, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
@@ -347,10 +347,10 @@ be_local_closure(get_percentage, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_nested_string("percentage", -1756136011, 10),
+ /* K0 */ be_nested_str(percentage),
}),
- (be_nested_const_str("get_percentage", -1414483304, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_get_percentage,
+ &be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x80040200, // 0001 RET 1 R1
@@ -369,17 +369,17 @@ be_local_class(lv_signal_bars,
&be_class_lv_obj,
be_nested_map(9,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("percentage", -1756136011, 10, 4), be_const_var(0) },
- { be_nested_key("p1", -1605446022, 2, 3), be_const_var(1) },
- { be_nested_key("p2", -1622223641, 2, -1), be_const_var(2) },
- { be_nested_key("area", -1693507260, 4, -1), be_const_var(3) },
- { be_nested_key("line_dsc", -200476318, 8, -1), be_const_var(4) },
- { be_nested_key("set_percentage", -1342944572, 14, -1), be_const_closure(set_percentage_closure) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
- { be_nested_key("widget_event", 1951408186, 12, -1), be_const_closure(widget_event_closure) },
- { be_nested_key("get_percentage", -1414483304, 14, 5), be_const_closure(get_percentage_closure) },
+ { be_const_key(percentage, 4), be_const_var(0) },
+ { be_const_key(p1, 3), be_const_var(1) },
+ { be_const_key(p2, -1), be_const_var(2) },
+ { be_const_key(area, -1), be_const_var(3) },
+ { be_const_key(line_dsc, -1), be_const_var(4) },
+ { be_const_key(set_percentage, -1), be_const_closure(lv_signal_bars_set_percentage_closure) },
+ { be_const_key(init, -1), be_const_closure(lv_signal_bars_init_closure) },
+ { be_const_key(widget_event, -1), be_const_closure(lv_signal_bars_widget_event_closure) },
+ { be_const_key(get_percentage, 5), be_const_closure(lv_signal_bars_get_percentage_closure) },
})),
- (be_nested_const_str("lv_signal_bars", -780994737, 14))
+ be_str_literal("lv_signal_bars")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_icon_lib.c b/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_icon_lib.c
index 9a2c742ff..d8fe9ce08 100644
--- a/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_icon_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_icon_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(lv_wifi_arcs_icon_init, /* name */
be_nested_proto(
10, /* nstack */
2, /* argc */
@@ -21,27 +21,27 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[18]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("set_style_line_color", -629728320, 20),
- /* K2 */ be_nested_string("lv", 1529997255, 2),
- /* K3 */ be_nested_string("color", 1031692888, 5),
- /* K4 */ be_nested_string("COLOR_WHITE", -1758096026, 11),
- /* K5 */ be_nested_string("PART_MAIN", -1821475788, 9),
- /* K6 */ be_nested_string("STATE_DEFAULT", 712406428, 13),
- /* K7 */ be_nested_string("set_style_bg_color", 1689513089, 18),
- /* K8 */ be_nested_string("COLOR_BLACK", 264427940, 11),
- /* K9 */ be_nested_string("get_height", -723211773, 10),
- /* K10 */ be_nested_string("get_style_pad_right", -1144679830, 19),
- /* K11 */ be_nested_string("set_height", 1080207399, 10),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(set_style_line_color),
+ /* K2 */ be_nested_str(lv),
+ /* K3 */ be_nested_str(color),
+ /* K4 */ be_nested_str(COLOR_WHITE),
+ /* K5 */ be_nested_str(PART_MAIN),
+ /* K6 */ be_nested_str(STATE_DEFAULT),
+ /* K7 */ be_nested_str(set_style_bg_color),
+ /* K8 */ be_nested_str(COLOR_BLACK),
+ /* K9 */ be_nested_str(get_height),
+ /* K10 */ be_nested_str(get_style_pad_right),
+ /* K11 */ be_nested_str(set_height),
/* K12 */ be_const_int(3),
- /* K13 */ be_nested_string("set_width", 484671920, 9),
- /* K14 */ be_nested_string("set_x", 1849400772, 5),
- /* K15 */ be_nested_string("get_width", -1001549996, 9),
- /* K16 */ be_nested_string("set_style_pad_right", -980898242, 19),
+ /* K13 */ be_nested_str(set_width),
+ /* K14 */ be_nested_str(set_x),
+ /* K15 */ be_nested_str(get_width),
+ /* K16 */ be_nested_str(set_style_pad_right),
/* K17 */ be_const_int(1),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[67]) { /* code */
0x60080003, // 0000 GETGBL R2 G3
0x5C0C0000, // 0001 MOVE R3 R0
@@ -125,9 +125,9 @@ be_local_class(lv_wifi_arcs_icon,
&be_class_lv_wifi_arcs,
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
+ { be_const_key(init, -1), be_const_closure(lv_wifi_arcs_icon_init_closure) },
})),
- (be_nested_const_str("lv_wifi_arcs_icon", 1507982909, 17))
+ be_str_literal("lv_wifi_arcs_icon")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_lib.c b/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_lib.c
index 59132af9e..57cbf18a9 100644
--- a/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_wifi_arcs_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: every_second
********************************************************************/
-be_local_closure(every_second, /* name */
+be_local_closure(lv_wifi_arcs_every_second, /* name */
be_nested_proto(
7, /* nstack */
1, /* argc */
@@ -21,16 +21,16 @@ be_local_closure(every_second, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
- /* K1 */ be_nested_string("wifi", 120087624, 4),
- /* K2 */ be_nested_string("find", -1108310694, 4),
- /* K3 */ be_nested_string("quality", -1697296346, 7),
- /* K4 */ be_nested_string("ip", 1261996636, 2),
- /* K5 */ be_nested_string("set_percentage", -1342944572, 14),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(wifi),
+ /* K2 */ be_nested_str(find),
+ /* K3 */ be_nested_str(quality),
+ /* K4 */ be_nested_str(ip),
+ /* K5 */ be_nested_str(set_percentage),
/* K6 */ be_const_int(0),
}),
- (be_nested_const_str("every_second", 2075451465, 12)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_every_second,
+ &be_const_str_solidified,
( &(const binstruction[23]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -64,7 +64,7 @@ be_local_closure(every_second, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(lv_wifi_arcs_init, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -75,14 +75,14 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("add_driver", 1654458371, 10),
- /* K3 */ be_nested_string("set_percentage", -1342944572, 14),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(add_driver),
+ /* K3 */ be_nested_str(set_percentage),
/* K4 */ be_const_int(0),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[14]) { /* code */
0x60080003, // 0000 GETGBL R2 G3
0x5C0C0000, // 0001 MOVE R3 R0
@@ -107,7 +107,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: del
********************************************************************/
-be_local_closure(del, /* name */
+be_local_closure(lv_wifi_arcs_del, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -118,12 +118,12 @@ be_local_closure(del, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("del", -816214454, 3),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("remove_driver", 1030243768, 13),
+ /* K0 */ be_nested_str(del),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(remove_driver),
}),
- (be_nested_const_str("del", -816214454, 3)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_del,
+ &be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x60040003, // 0000 GETGBL R1 G3
0x5C080000, // 0001 MOVE R2 R0
@@ -150,11 +150,11 @@ be_local_class(lv_wifi_arcs,
&be_class_lv_signal_arcs,
be_nested_map(3,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("every_second", 2075451465, 12, 1), be_const_closure(every_second_closure) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
- { be_nested_key("del", -816214454, 3, -1), be_const_closure(del_closure) },
+ { be_const_key(every_second, 1), be_const_closure(lv_wifi_arcs_every_second_closure) },
+ { be_const_key(init, -1), be_const_closure(lv_wifi_arcs_init_closure) },
+ { be_const_key(del, -1), be_const_closure(lv_wifi_arcs_del_closure) },
})),
- (be_nested_const_str("lv_wifi_arcs", 2082091963, 12))
+ be_str_literal("lv_wifi_arcs")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_bars_icon_lib.c b/lib/libesp32/Berry/default/be_lvgl_wifi_bars_icon_lib.c
index 9adcdeba5..a1cf693e5 100644
--- a/lib/libesp32/Berry/default/be_lvgl_wifi_bars_icon_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_wifi_bars_icon_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(lv_wifi_bars_icon_init, /* name */
be_nested_proto(
9, /* nstack */
2, /* argc */
@@ -21,26 +21,26 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[17]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("set_style_line_color", -629728320, 20),
- /* K2 */ be_nested_string("lv", 1529997255, 2),
- /* K3 */ be_nested_string("color", 1031692888, 5),
- /* K4 */ be_nested_string("COLOR_WHITE", -1758096026, 11),
- /* K5 */ be_nested_string("PART_MAIN", -1821475788, 9),
- /* K6 */ be_nested_string("STATE_DEFAULT", 712406428, 13),
- /* K7 */ be_nested_string("set_style_bg_color", 1689513089, 18),
- /* K8 */ be_nested_string("COLOR_BLACK", 264427940, 11),
- /* K9 */ be_nested_string("get_height", -723211773, 10),
- /* K10 */ be_nested_string("get_style_pad_right", -1144679830, 19),
- /* K11 */ be_nested_string("set_height", 1080207399, 10),
- /* K12 */ be_nested_string("set_width", 484671920, 9),
- /* K13 */ be_nested_string("set_x", 1849400772, 5),
- /* K14 */ be_nested_string("get_width", -1001549996, 9),
- /* K15 */ be_nested_string("set_style_pad_right", -980898242, 19),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(set_style_line_color),
+ /* K2 */ be_nested_str(lv),
+ /* K3 */ be_nested_str(color),
+ /* K4 */ be_nested_str(COLOR_WHITE),
+ /* K5 */ be_nested_str(PART_MAIN),
+ /* K6 */ be_nested_str(STATE_DEFAULT),
+ /* K7 */ be_nested_str(set_style_bg_color),
+ /* K8 */ be_nested_str(COLOR_BLACK),
+ /* K9 */ be_nested_str(get_height),
+ /* K10 */ be_nested_str(get_style_pad_right),
+ /* K11 */ be_nested_str(set_height),
+ /* K12 */ be_nested_str(set_width),
+ /* K13 */ be_nested_str(set_x),
+ /* K14 */ be_nested_str(get_width),
+ /* K15 */ be_nested_str(set_style_pad_right),
/* K16 */ be_const_int(1),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[64]) { /* code */
0x60080003, // 0000 GETGBL R2 G3
0x5C0C0000, // 0001 MOVE R3 R0
@@ -121,9 +121,9 @@ be_local_class(lv_wifi_bars_icon,
&be_class_lv_wifi_bars,
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
+ { be_const_key(init, -1), be_const_closure(lv_wifi_bars_icon_init_closure) },
})),
- (be_nested_const_str("lv_wifi_bars_icon", -1489151756, 17))
+ be_str_literal("lv_wifi_bars_icon")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_lvgl_wifi_bars_lib.c b/lib/libesp32/Berry/default/be_lvgl_wifi_bars_lib.c
index 9bbb51bf0..c61cb2bb3 100644
--- a/lib/libesp32/Berry/default/be_lvgl_wifi_bars_lib.c
+++ b/lib/libesp32/Berry/default/be_lvgl_wifi_bars_lib.c
@@ -10,7 +10,7 @@
/********************************************************************
** Solidified function: every_second
********************************************************************/
-be_local_closure(every_second, /* name */
+be_local_closure(lv_wifi_bars_every_second, /* name */
be_nested_proto(
7, /* nstack */
1, /* argc */
@@ -21,16 +21,16 @@ be_local_closure(every_second, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
- /* K1 */ be_nested_string("wifi", 120087624, 4),
- /* K2 */ be_nested_string("find", -1108310694, 4),
- /* K3 */ be_nested_string("quality", -1697296346, 7),
- /* K4 */ be_nested_string("ip", 1261996636, 2),
- /* K5 */ be_nested_string("set_percentage", -1342944572, 14),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(wifi),
+ /* K2 */ be_nested_str(find),
+ /* K3 */ be_nested_str(quality),
+ /* K4 */ be_nested_str(ip),
+ /* K5 */ be_nested_str(set_percentage),
/* K6 */ be_const_int(0),
}),
- (be_nested_const_str("every_second", 2075451465, 12)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_every_second,
+ &be_const_str_solidified,
( &(const binstruction[23]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -64,7 +64,7 @@ be_local_closure(every_second, /* name */
/********************************************************************
** Solidified function: init
********************************************************************/
-be_local_closure(init, /* name */
+be_local_closure(lv_wifi_bars_init, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -75,14 +75,14 @@ be_local_closure(init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("init", 380752755, 4),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("add_driver", 1654458371, 10),
- /* K3 */ be_nested_string("set_percentage", -1342944572, 14),
+ /* K0 */ be_nested_str(init),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(add_driver),
+ /* K3 */ be_nested_str(set_percentage),
/* K4 */ be_const_int(0),
}),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[14]) { /* code */
0x60080003, // 0000 GETGBL R2 G3
0x5C0C0000, // 0001 MOVE R3 R0
@@ -107,7 +107,7 @@ be_local_closure(init, /* name */
/********************************************************************
** Solidified function: del
********************************************************************/
-be_local_closure(del, /* name */
+be_local_closure(lv_wifi_bars_del, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
@@ -118,12 +118,12 @@ be_local_closure(del, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("del", -816214454, 3),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("remove_driver", 1030243768, 13),
+ /* K0 */ be_nested_str(del),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(remove_driver),
}),
- (be_nested_const_str("del", -816214454, 3)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_del,
+ &be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x60040003, // 0000 GETGBL R1 G3
0x5C080000, // 0001 MOVE R2 R0
@@ -150,11 +150,11 @@ be_local_class(lv_wifi_bars,
&be_class_lv_signal_bars,
be_nested_map(3,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("every_second", 2075451465, 12, 1), be_const_closure(every_second_closure) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
- { be_nested_key("del", -816214454, 3, -1), be_const_closure(del_closure) },
+ { be_const_key(every_second, 1), be_const_closure(lv_wifi_bars_every_second_closure) },
+ { be_const_key(init, -1), be_const_closure(lv_wifi_bars_init_closure) },
+ { be_const_key(del, -1), be_const_closure(lv_wifi_bars_del_closure) },
})),
- (be_nested_const_str("lv_wifi_bars", 2109539196, 12))
+ be_str_literal("lv_wifi_bars")
);
/*******************************************************************/
diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c
index 0c54ce990..5f4279c27 100644
--- a/lib/libesp32/Berry/default/be_modtab.c
+++ b/lib/libesp32/Berry/default/be_modtab.c
@@ -131,7 +131,7 @@ extern void be_load_onewirelib(bvm *vm);
extern void be_load_serial_lib(bvm *vm);
extern void be_load_Driver_class(bvm *vm);
extern void be_load_Timer_class(bvm *vm);
-extern void be_load_driver_i2c_lib(bvm *vm);
+extern void be_load_I2C_Driver_class(bvm *vm);
extern void be_load_AXP192_class(bvm *vm);
extern void be_load_md5_lib(bvm *vm);
extern void be_load_webclient_lib(bvm *vm);
@@ -181,7 +181,7 @@ BERRY_API void be_load_custom_libs(bvm *vm)
#endif
#ifdef USE_I2C
be_load_wirelib(vm);
- be_load_driver_i2c_lib(vm);
+ be_load_I2C_Driver_class(vm);
be_load_AXP192_class(vm);
#endif // USE_I2C
#ifdef USE_ENERGY_SENSOR
diff --git a/lib/libesp32/Berry/default/be_persist_lib.c b/lib/libesp32/Berry/default/be_persist_lib.c
index 4684283d4..0581081c7 100644
--- a/lib/libesp32/Berry/default/be_persist_lib.c
+++ b/lib/libesp32/Berry/default/be_persist_lib.c
@@ -21,19 +21,19 @@ be_local_closure(Persist_json_fdump_map, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_str_literal("json"),
- /* K1 */ be_nested_str_literal("write"),
- /* K2 */ be_nested_str_literal("{"),
- /* K3 */ be_nested_str_literal("keys"),
- /* K4 */ be_nested_str_literal("dump"),
- /* K5 */ be_nested_str_literal(":"),
- /* K6 */ be_nested_str_literal("json_fdump_any"),
- /* K7 */ be_nested_str_literal(","),
- /* K8 */ be_nested_str_literal("stop_iteration"),
- /* K9 */ be_nested_str_literal("}"),
+ /* K0 */ be_nested_str(json),
+ /* K1 */ be_nested_str(write),
+ /* K2 */ be_nested_str(_X7B),
+ /* K3 */ be_nested_str(keys),
+ /* K4 */ be_nested_str(dump),
+ /* K5 */ be_nested_str(_X3A),
+ /* K6 */ be_nested_str(json_fdump_any),
+ /* K7 */ be_nested_str(_X2C),
+ /* K8 */ be_nested_str(stop_iteration),
+ /* K9 */ be_nested_str(_X7D),
}),
- (be_nested_const_str("json_fdump_map", -203012643, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_json_fdump_map,
+ &be_const_str_solidified,
( &(const binstruction[41]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0x8C100301, // 0001 GETMET R4 R1 K1
@@ -96,11 +96,11 @@ be_local_closure(Persist_setmember, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("_p"),
- /* K1 */ be_nested_str_literal("_dirty"),
+ /* K0 */ be_nested_str(_p),
+ /* K1 */ be_nested_str(_dirty),
}),
- (be_nested_const_str("setmember", 1432909441, 9)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_setmember,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x880C0100, // 0000 GETMBR R3 R0 K0
0x980C0202, // 0001 SETIDX R3 R1 R2
@@ -127,11 +127,11 @@ be_local_closure(Persist_zero, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("_p"),
- /* K1 */ be_nested_str_literal("_dirty"),
+ /* K0 */ be_nested_str(_p),
+ /* K1 */ be_nested_str(_dirty),
}),
- (be_nested_const_str("zero", -1955600541, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_zero,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x60040013, // 0000 GETGBL R1 G19
0x7C040000, // 0001 CALL R1 0
@@ -159,11 +159,11 @@ be_local_closure(Persist_member, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("_p"),
- /* K1 */ be_nested_str_literal("find"),
+ /* K0 */ be_nested_str(_p),
+ /* K1 */ be_nested_str(find),
}),
- (be_nested_const_str("member", 719708611, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_member,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -190,14 +190,14 @@ be_local_closure(Persist_json_fdump, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_str_literal("json"),
- /* K1 */ be_nested_str_literal("_p"),
- /* K2 */ be_nested_str_literal("json_fdump_map"),
- /* K3 */ be_nested_str_literal("internal_error"),
- /* K4 */ be_nested_str_literal("persist._p is not a map"),
+ /* K0 */ be_nested_str(json),
+ /* K1 */ be_nested_str(_p),
+ /* K2 */ be_nested_str(json_fdump_map),
+ /* K3 */ be_nested_str(internal_error),
+ /* K4 */ be_nested_str(persist_X2E_p_X20is_X20not_X20a_X20map),
}),
- (be_nested_const_str("json_fdump", 1694216580, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_json_fdump,
+ &be_const_str_solidified,
( &(const binstruction[13]) { /* code */
0xA40A0000, // 0000 IMPORT R2 K0
0x600C000F, // 0001 GETGBL R3 G15
@@ -232,12 +232,12 @@ be_local_closure(Persist_remove, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_str_literal("_p"),
- /* K1 */ be_nested_str_literal("remove"),
- /* K2 */ be_nested_str_literal("_dirty"),
+ /* K0 */ be_nested_str(_p),
+ /* K1 */ be_nested_str(remove),
+ /* K2 */ be_nested_str(_dirty),
}),
- (be_nested_const_str("remove", -611183107, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_remove,
+ &be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -266,14 +266,14 @@ be_local_closure(Persist_json_fdump_any, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_str_literal("json"),
- /* K1 */ be_nested_str_literal("json_fdump_map"),
- /* K2 */ be_nested_str_literal("json_fdump_list"),
- /* K3 */ be_nested_str_literal("write"),
- /* K4 */ be_nested_str_literal("dump"),
+ /* K0 */ be_nested_str(json),
+ /* K1 */ be_nested_str(json_fdump_map),
+ /* K2 */ be_nested_str(json_fdump_list),
+ /* K3 */ be_nested_str(write),
+ /* K4 */ be_nested_str(dump),
}),
- (be_nested_const_str("json_fdump_any", -946337911, 14)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_json_fdump_any,
+ &be_const_str_solidified,
( &(const binstruction[27]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0x6010000F, // 0001 GETGBL R4 G15
@@ -322,16 +322,16 @@ be_local_closure(Persist_save, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_str_literal("_filename"),
- /* K1 */ be_nested_str_literal("w"),
- /* K2 */ be_nested_str_literal("json_fdump"),
- /* K3 */ be_nested_str_literal("close"),
- /* K4 */ be_nested_str_literal("write"),
- /* K5 */ be_nested_str_literal("{}"),
- /* K6 */ be_nested_str_literal("_dirty"),
+ /* K0 */ be_nested_str(_filename),
+ /* K1 */ be_nested_str(w),
+ /* K2 */ be_nested_str(json_fdump),
+ /* K3 */ be_nested_str(close),
+ /* K4 */ be_nested_str(write),
+ /* K5 */ be_nested_str(_X7B_X7D),
+ /* K6 */ be_nested_str(_dirty),
}),
- (be_nested_const_str("save", -855671224, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_save,
+ &be_const_str_solidified,
( &(const binstruction[37]) { /* code */
0x4C040000, // 0000 LDNIL R1
0xA802000B, // 0001 EXBLK 0 #000E
@@ -390,21 +390,21 @@ be_local_closure(Persist_load, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[12]) { /* constants */
- /* K0 */ be_nested_str_literal("json"),
- /* K1 */ be_nested_str_literal("path"),
- /* K2 */ be_nested_str_literal("exists"),
- /* K3 */ be_nested_str_literal("_filename"),
- /* K4 */ be_nested_str_literal("r"),
- /* K5 */ be_nested_str_literal("load"),
- /* K6 */ be_nested_str_literal("read"),
- /* K7 */ be_nested_str_literal("close"),
- /* K8 */ be_nested_str_literal("_p"),
- /* K9 */ be_nested_str_literal("BRY: failed to load _persist.json"),
- /* K10 */ be_nested_str_literal("_dirty"),
- /* K11 */ be_nested_str_literal("save"),
+ /* K0 */ be_nested_str(json),
+ /* K1 */ be_nested_str(path),
+ /* K2 */ be_nested_str(exists),
+ /* K3 */ be_nested_str(_filename),
+ /* K4 */ be_nested_str(r),
+ /* K5 */ be_nested_str(load),
+ /* K6 */ be_nested_str(read),
+ /* K7 */ be_nested_str(close),
+ /* K8 */ be_nested_str(_p),
+ /* K9 */ be_nested_str(BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson),
+ /* K10 */ be_nested_str(_dirty),
+ /* K11 */ be_nested_str(save),
}),
- (be_nested_const_str("load", -435725847, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_load,
+ &be_const_str_solidified,
( &(const binstruction[49]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xA40A0200, // 0001 IMPORT R2 K1
@@ -475,11 +475,11 @@ be_local_closure(Persist_find, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("_p"),
- /* K1 */ be_nested_str_literal("find"),
+ /* K0 */ be_nested_str(_p),
+ /* K1 */ be_nested_str(find),
}),
- (be_nested_const_str("find", -1108310694, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_find,
+ &be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x880C0100, // 0000 GETMBR R3 R0 K0
0x8C0C0701, // 0001 GETMET R3 R3 K1
@@ -507,15 +507,15 @@ be_local_closure(Persist_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_str_literal("_filename"),
- /* K1 */ be_nested_str_literal("_persist.json"),
- /* K2 */ be_nested_str_literal("_p"),
- /* K3 */ be_nested_str_literal("copy"),
- /* K4 */ be_nested_str_literal("load"),
- /* K5 */ be_nested_str_literal("_dirty"),
+ /* K0 */ be_nested_str(_filename),
+ /* K1 */ be_nested_str(_persist_X2Ejson),
+ /* K2 */ be_nested_str(_p),
+ /* K3 */ be_nested_str(copy),
+ /* K4 */ be_nested_str(load),
+ /* K5 */ be_nested_str(_dirty),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[20]) { /* code */
0x90020101, // 0000 SETMBR R0 K0 K1
0x6008000F, // 0001 GETGBL R2 G15
@@ -557,17 +557,17 @@ be_local_closure(Persist_json_fdump_list, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
- /* K0 */ be_nested_str_literal("json"),
- /* K1 */ be_nested_str_literal("write"),
- /* K2 */ be_nested_str_literal("["),
+ /* K0 */ be_nested_str(json),
+ /* K1 */ be_nested_str(write),
+ /* K2 */ be_nested_str(_X5B),
/* K3 */ be_const_int(0),
- /* K4 */ be_nested_str_literal(","),
- /* K5 */ be_nested_str_literal("json_fdump_any"),
+ /* K4 */ be_nested_str(_X2C),
+ /* K5 */ be_nested_str(json_fdump_any),
/* K6 */ be_const_int(1),
- /* K7 */ be_nested_str_literal("]"),
+ /* K7 */ be_nested_str(_X5D),
}),
- (be_nested_const_str("json_fdump_list", -391087443, 15)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_json_fdump_list,
+ &be_const_str_solidified,
( &(const binstruction[25]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0x8C100301, // 0001 GETMET R4 R1 K1
@@ -614,11 +614,11 @@ be_local_closure(Persist_has, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("_p"),
- /* K1 */ be_nested_str_literal("has"),
+ /* K0 */ be_nested_str(_p),
+ /* K1 */ be_nested_str(has),
}),
- (be_nested_const_str("has", -306245661, 3)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_has,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
@@ -639,22 +639,22 @@ be_local_class(Persist,
NULL,
be_nested_map(16,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("has", -306245661, 3, 6), be_const_closure(Persist_has_closure) },
- { be_nested_key("setmember", 1432909441, 9, -1), be_const_closure(Persist_setmember_closure) },
- { be_nested_key("remove", -611183107, 6, -1), be_const_closure(Persist_remove_closure) },
- { be_nested_key("zero", -1955600541, 4, 0), be_const_closure(Persist_zero_closure) },
- { be_nested_key("json_fdump", 1694216580, 10, -1), be_const_closure(Persist_json_fdump_closure) },
- { be_nested_key("json_fdump_list", -391087443, 15, 2), be_const_closure(Persist_json_fdump_list_closure) },
- { be_nested_key("init", 380752755, 4, 15), be_const_closure(Persist_init_closure) },
- { be_nested_key("find", -1108310694, 4, -1), be_const_closure(Persist_find_closure) },
- { be_nested_key("save", -855671224, 4, -1), be_const_closure(Persist_save_closure) },
- { be_nested_key("json_fdump_any", -946337911, 14, 12), be_const_closure(Persist_json_fdump_any_closure) },
- { be_nested_key("_p", 1594591802, 2, 7), be_const_var(1) },
- { be_nested_key("_filename", 1430813195, 9, -1), be_const_var(0) },
- { be_nested_key("load", -435725847, 4, -1), be_const_closure(Persist_load_closure) },
- { be_nested_key("json_fdump_map", -203012643, 14, 5), be_const_closure(Persist_json_fdump_map_closure) },
- { be_nested_key("_dirty", 283846766, 6, -1), be_const_var(2) },
- { be_nested_key("member", 719708611, 6, -1), be_const_closure(Persist_member_closure) },
+ { be_const_key(has, 6), be_const_closure(Persist_has_closure) },
+ { be_const_key(setmember, -1), be_const_closure(Persist_setmember_closure) },
+ { be_const_key(remove, -1), be_const_closure(Persist_remove_closure) },
+ { be_const_key(zero, 0), be_const_closure(Persist_zero_closure) },
+ { be_const_key(json_fdump, -1), be_const_closure(Persist_json_fdump_closure) },
+ { be_const_key(json_fdump_list, 2), be_const_closure(Persist_json_fdump_list_closure) },
+ { be_const_key(init, 15), be_const_closure(Persist_init_closure) },
+ { be_const_key(find, -1), be_const_closure(Persist_find_closure) },
+ { be_const_key(save, -1), be_const_closure(Persist_save_closure) },
+ { be_const_key(json_fdump_any, 12), be_const_closure(Persist_json_fdump_any_closure) },
+ { be_const_key(_p, 7), be_const_var(1) },
+ { be_const_key(_filename, -1), be_const_var(0) },
+ { be_const_key(load, -1), be_const_closure(Persist_load_closure) },
+ { be_const_key(json_fdump_map, 5), be_const_closure(Persist_json_fdump_map_closure) },
+ { be_const_key(_dirty, -1), be_const_var(2) },
+ { be_const_key(member, -1), be_const_closure(Persist_member_closure) },
})),
be_str_literal("Persist")
);
@@ -675,8 +675,8 @@ be_local_closure(persist__anonymous_, /* name */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_const_class(be_class_Persist),
}),
- (be_nested_const_str("_anonymous_", 1957281476, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__anonymous_,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x58040000, // 0000 LDCONST R1 K0
0xB4000000, // 0001 CLASS K0
@@ -696,7 +696,7 @@ be_local_module(persist,
"persist",
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(persist__anonymous__closure) },
+ { be_const_key(init, -1), be_const_closure(persist__anonymous__closure) },
}))
);
BE_EXPORT_VARIABLE be_define_const_native_module(persist);
diff --git a/lib/libesp32/Berry/default/be_python_compat.c b/lib/libesp32/Berry/default/be_python_compat.c
index 7213c10ad..5b3ec64d0 100644
--- a/lib/libesp32/Berry/default/be_python_compat.c
+++ b/lib/libesp32/Berry/default/be_python_compat.c
@@ -8,7 +8,7 @@
/********************************************************************
** Solidified function: _anonymous_
********************************************************************/
-be_local_closure(_anonymous_, /* name */
+be_local_closure(python_compat__anonymous_, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
@@ -19,25 +19,25 @@ be_local_closure(_anonymous_, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("global", 503252654, 6),
- /* K1 */ be_nested_string("True", -841064955, 4),
- /* K2 */ be_nested_string("False", -1753917960, 5),
- /* K3 */ be_nested_string("None", 810547195, 4),
- /* K4 */ be_nested_string("b", -418632219, 1),
+ /* K0 */ be_nested_str(global),
+ /* K1 */ be_nested_str(True),
+ /* K2 */ be_nested_str(False),
+ /* K3 */ be_nested_str(None),
+ /* K4 */ be_nested_str(b),
}),
- (be_nested_const_str("_anonymous_", 1957281476, 11)),
- (be_nested_const_str("python_compat.be", -225667571, 16)),
+ &be_const_str__anonymous_,
+ &be_const_str_solidified,
( &(const binstruction[10]) { /* code */
- 0xA4060000, // 0000 IMPORT R1 K0
- 0x50080200, // 0001 LDBOOL R2 1 0
- 0x90060202, // 0002 SETMBR R1 K1 R2
- 0x50080000, // 0003 LDBOOL R2 0 0
- 0x90060402, // 0004 SETMBR R1 K2 R2
- 0x4C080000, // 0005 LDNIL R2
- 0x90060602, // 0006 SETMBR R1 K3 R2
- 0x60080015, // 0007 GETGBL R2 G21
- 0x90060802, // 0008 SETMBR R1 K4 R2
- 0x80040000, // 0009 RET 1 R0
+ 0xA4060000, // 0000 IMPORT R1 K0
+ 0x50080200, // 0001 LDBOOL R2 1 0
+ 0x90060202, // 0002 SETMBR R1 K1 R2
+ 0x50080000, // 0003 LDBOOL R2 0 0
+ 0x90060402, // 0004 SETMBR R1 K2 R2
+ 0x4C080000, // 0005 LDNIL R2
+ 0x90060602, // 0006 SETMBR R1 K3 R2
+ 0x60080015, // 0007 GETGBL R2 G21
+ 0x90060802, // 0008 SETMBR R1 K4 R2
+ 0x80040000, // 0009 RET 1 R0
})
)
);
@@ -51,7 +51,7 @@ be_local_module(python_compat,
"python_compat",
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(_anonymous__closure) },
+ { be_const_key(init, -1), be_const_closure(python_compat__anonymous__closure) },
}))
);
BE_EXPORT_VARIABLE be_define_const_native_module(python_compat);
diff --git a/lib/libesp32/Berry/default/be_tapp_lib.c b/lib/libesp32/Berry/default/be_tapp_lib.c
index 47ef170f7..1a312d110 100644
--- a/lib/libesp32/Berry/default/be_tapp_lib.c
+++ b/lib/libesp32/Berry/default/be_tapp_lib.c
@@ -20,11 +20,11 @@ be_local_closure(Tapp_init, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_str_literal("tasmota"),
- /* K1 */ be_nested_str_literal("add_driver"),
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(add_driver),
}),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_init,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
@@ -51,24 +51,24 @@ be_local_closure(Tapp_autoexec, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[15]) { /* constants */
- /* K0 */ be_nested_str_literal("path"),
- /* K1 */ be_nested_str_literal("string"),
- /* K2 */ be_nested_str_literal("listdir"),
- /* K3 */ be_nested_str_literal("/"),
- /* K4 */ be_nested_str_literal("find"),
- /* K5 */ be_nested_str_literal(".tapp"),
+ /* K0 */ be_nested_str(path),
+ /* K1 */ be_nested_str(string),
+ /* K2 */ be_nested_str(listdir),
+ /* K3 */ be_nested_str(_X2F),
+ /* K4 */ be_nested_str(find),
+ /* K5 */ be_nested_str(_X2Etapp),
/* K6 */ be_const_int(0),
- /* K7 */ be_nested_str_literal("tasmota"),
- /* K8 */ be_nested_str_literal("log"),
- /* K9 */ be_nested_str_literal("format"),
- /* K10 */ be_nested_str_literal("TAP: found Tasmota App '%s'"),
+ /* K7 */ be_nested_str(tasmota),
+ /* K8 */ be_nested_str(log),
+ /* K9 */ be_nested_str(format),
+ /* K10 */ be_nested_str(TAP_X3A_X20found_X20Tasmota_X20App_X20_X27_X25s_X27),
/* K11 */ be_const_int(2),
- /* K12 */ be_nested_str_literal("load"),
- /* K13 */ be_nested_str_literal("#autoexec.be"),
- /* K14 */ be_nested_str_literal("stop_iteration"),
+ /* K12 */ be_nested_str(load),
+ /* K13 */ be_nested_str(_X23autoexec_X2Ebe),
+ /* K14 */ be_nested_str(stop_iteration),
}),
- (be_nested_const_str("autoexec", -618105405, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_autoexec,
+ &be_const_str_solidified,
( &(const binstruction[34]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xA40A0200, // 0001 IMPORT R2 K1
@@ -118,8 +118,8 @@ be_local_class(Tapp,
NULL,
be_nested_map(2,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("autoexec", -618105405, 8, -1), be_const_closure(Tapp_autoexec_closure) },
- { be_nested_key("init", 380752755, 4, 0), be_const_closure(Tapp_init_closure) },
+ { be_const_key(autoexec, -1), be_const_closure(Tapp_autoexec_closure) },
+ { be_const_key(init, 0), be_const_closure(Tapp_init_closure) },
})),
be_str_literal("Tapp")
);
@@ -140,8 +140,8 @@ be_local_closure(tapp__anonymous_, /* name */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_const_class(be_class_Tapp),
}),
- (be_nested_const_str("_anonymous_", 1957281476, 11)),
- ((bstring*) &be_const_str_input),
+ &be_const_str__anonymous_,
+ &be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x58040000, // 0000 LDCONST R1 K0
0xB4000000, // 0001 CLASS K0
@@ -161,7 +161,7 @@ be_local_module(tapp,
"tapp",
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(tapp__anonymous__closure) },
+ { be_const_key(init, -1), be_const_closure(tapp__anonymous__closure) },
}))
);
BE_EXPORT_VARIABLE be_define_const_native_module(tapp);
diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c
index a5c0307b8..b073287f4 100644
--- a/lib/libesp32/Berry/default/be_tasmotalib.c
+++ b/lib/libesp32/Berry/default/be_tasmotalib.c
@@ -53,161 +53,11 @@ extern int l_getswitch(bvm *vm);
extern int l_i2cenabled(bvm *vm);
-// KV class
-/********************************************************************
-** Solidified function: init
-********************************************************************/
-be_local_closure(kv_init, /* name */
- be_nested_proto(
- 3, /* nstack */
- 3, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("k", -301188886, 1),
- /* K1 */ be_nested_string("v", -217300791, 1),
- }),
- ((bstring*) &be_const_str_init),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[ 3]) { /* code */
- 0x90020001, // 0000 SETMBR R0 K0 R1
- 0x90020202, // 0001 SETMBR R0 K1 R2
- 0x80000000, // 0002 RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified class: KV
-********************************************************************/
-be_local_class(KV,
- 2,
- NULL,
- be_nested_map(3,
- ( (struct bmapnode*) &(const bmapnode[]) {
- { be_nested_key("k", -301188886, 1, 2), be_const_var(0) },
- { be_nested_key("v", -217300791, 1, -1), be_const_var(1) },
- { be_nested_key("init", 380752755, 4, -1), be_const_closure(kv_init_closure) },
- })),
- (be_nested_const_str("KV", 955173972, 2))
-);
-
-/********************************************************************
-** Solidified function: kv
-********************************************************************/
-be_local_closure(kv, /* name */
- be_nested_proto(
- 7, /* nstack */
- 3, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 1]) { /* constants */
- /* K0 */ be_const_class(be_class_KV),
- }),
- (be_nested_const_str("kv", 1497177492, 2)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[ 7]) { /* code */
- 0x580C0000, // 0000 LDCONST R3 K0
- 0xB4000000, // 0001 CLASS K0
- 0x5C100600, // 0002 MOVE R4 R3
- 0x5C140200, // 0003 MOVE R5 R1
- 0x5C180400, // 0004 MOVE R6 R2
- 0x7C100400, // 0005 CALL R4 2
- 0x80040800, // 0006 RET 1 R4
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: init
-********************************************************************/
-be_local_closure(init, /* name */
- be_nested_proto(
- 7, /* nstack */
- 1, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[15]) { /* constants */
- /* K0 */ be_nested_str_literal("global"),
- /* K1 */ be_nested_str_literal("ctypes_bytes_dyn"),
- /* K2 */ be_nested_str_literal("_global_addr"),
- /* K3 */ be_nested_str_literal("_global_def"),
- /* K4 */ be_nested_str_literal("introspect"),
- /* K5 */ be_nested_str_literal("_settings_ptr"),
- /* K6 */ be_nested_str_literal("get"),
- /* K7 */ be_const_int(0),
- /* K8 */ be_nested_str_literal("settings"),
- /* K9 */ be_nested_str_literal("toptr"),
- /* K10 */ be_nested_str_literal("_settings_def"),
- /* K11 */ be_nested_str_literal("wd"),
- /* K12 */ be_nested_str_literal(""),
- /* K13 */ be_nested_str_literal("_debug_present"),
- /* K14 */ be_nested_str_literal("debug"),
- }),
- (be_nested_const_str("init", 380752755, 4)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[36]) { /* code */
- 0xB8060200, // 0000 GETNGBL R1 K1
- 0x88080102, // 0001 GETMBR R2 R0 K2
- 0x880C0103, // 0002 GETMBR R3 R0 K3
- 0x7C040400, // 0003 CALL R1 2
- 0x90020001, // 0004 SETMBR R0 K0 R1
- 0xA4060800, // 0005 IMPORT R1 K4
- 0x60080015, // 0006 GETGBL R2 G21
- 0x880C0105, // 0007 GETMBR R3 R0 K5
- 0x54120003, // 0008 LDINT R4 4
- 0x7C080400, // 0009 CALL R2 2
- 0x8C080506, // 000A GETMET R2 R2 K6
- 0x58100007, // 000B LDCONST R4 K7
- 0x54160003, // 000C LDINT R5 4
- 0x7C080600, // 000D CALL R2 3
- 0x780A0006, // 000E JMPF R2 #0016
- 0xB80E0200, // 000F GETNGBL R3 K1
- 0x8C100309, // 0010 GETMET R4 R1 K9
- 0x5C180400, // 0011 MOVE R6 R2
- 0x7C100400, // 0012 CALL R4 2
- 0x8814010A, // 0013 GETMBR R5 R0 K10
- 0x7C0C0400, // 0014 CALL R3 2
- 0x90021003, // 0015 SETMBR R0 K8 R3
- 0x9002170C, // 0016 SETMBR R0 K11 K12
- 0x500C0000, // 0017 LDBOOL R3 0 0
- 0x90021A03, // 0018 SETMBR R0 K13 R3
- 0xA8020004, // 0019 EXBLK 0 #001F
- 0xA40E1C00, // 001A IMPORT R3 K14
- 0x50100200, // 001B LDBOOL R4 1 0
- 0x90021A04, // 001C SETMBR R0 K13 R4
- 0xA8040001, // 001D EXBLK 1 1
- 0x70020003, // 001E JMP #0023
- 0xAC0C0000, // 001F CATCH R3 0 0
- 0x70020000, // 0020 JMP #0022
- 0x70020000, // 0021 JMP #0023
- 0xB0080000, // 0022 RAISE 2 R0 R0
- 0x80000000, // 0023 RET 0
- })
- )
-);
-/*******************************************************************/
/********************************************************************
** Solidified function: add_driver
********************************************************************/
-be_local_closure(add_driver, /* name */
+be_local_closure(Tasmota_add_driver, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -218,24 +68,24 @@ be_local_closure(add_driver, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("_drivers", -1034638311, 8),
- /* K1 */ be_nested_string("push", -2022703139, 4),
+ /* K0 */ be_nested_str(_drivers),
+ /* K1 */ be_nested_str(push),
}),
- (be_nested_const_str("add_driver", 1654458371, 10)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_add_driver,
+ &be_const_str_solidified,
( &(const binstruction[12]) { /* code */
- 0x88080100, // 0000 GETMBR R2 R0 K0
- 0x780A0004, // 0001 JMPF R2 #0007
- 0x88080100, // 0002 GETMBR R2 R0 K0
- 0x8C080501, // 0003 GETMET R2 R2 K1
- 0x5C100200, // 0004 MOVE R4 R1
- 0x7C080400, // 0005 CALL R2 2
- 0x70020003, // 0006 JMP #000B
- 0x60080012, // 0007 GETGBL R2 G18
- 0x7C080000, // 0008 CALL R2 0
- 0x400C0401, // 0009 CONNECT R3 R2 R1
- 0x90020002, // 000A SETMBR R0 K0 R2
- 0x80000000, // 000B RET 0
+ 0x88080100, // 0000 GETMBR R2 R0 K0
+ 0x780A0004, // 0001 JMPF R2 #0007
+ 0x88080100, // 0002 GETMBR R2 R0 K0
+ 0x8C080501, // 0003 GETMET R2 R2 K1
+ 0x5C100200, // 0004 MOVE R4 R1
+ 0x7C080400, // 0005 CALL R2 2
+ 0x70020003, // 0006 JMP #000B
+ 0x60080012, // 0007 GETGBL R2 G18
+ 0x7C080000, // 0008 CALL R2 0
+ 0x400C0401, // 0009 CONNECT R3 R2 R1
+ 0x90020002, // 000A SETMBR R0 K0 R2
+ 0x80000000, // 000B RET 0
})
)
);
@@ -243,77 +93,12 @@ be_local_closure(add_driver, /* name */
/********************************************************************
-** Solidified function: gen_cb
+** Solidified function: gc
********************************************************************/
-be_local_closure(gen_cb, /* name */
+be_local_closure(Tasmota_gc, /* name */
be_nested_proto(
- 7, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("_cb", -251666929, 3),
- /* K1 */ be_const_int(0),
- /* K2 */ be_nested_string("find", -1108310694, 4),
- /* K3 */ be_nested_string("_get_cb", 1448849122, 7),
- /* K4 */ be_nested_string("stop_iteration", -121173395, 14),
- /* K5 */ be_nested_string("internal_error", -1775809127, 14),
- /* K6 */ be_nested_string("No callback available", 633786138, 21),
- }),
- (be_nested_const_str("gen_cb", -1049739745, 6)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[34]) { /* code */
- 0x88080100, // 0000 GETMBR R2 R0 K0
- 0x4C0C0000, // 0001 LDNIL R3
- 0x1C080403, // 0002 EQ R2 R2 R3
- 0x780A0002, // 0003 JMPF R2 #0007
- 0x60080013, // 0004 GETGBL R2 G19
- 0x7C080000, // 0005 CALL R2 0
- 0x90020002, // 0006 SETMBR R0 K0 R2
- 0x60080010, // 0007 GETGBL R2 G16
- 0x540E0012, // 0008 LDINT R3 19
- 0x400E0203, // 0009 CONNECT R3 K1 R3
- 0x7C080200, // 000A CALL R2 1
- 0xA8020010, // 000B EXBLK 0 #001D
- 0x5C0C0400, // 000C MOVE R3 R2
- 0x7C0C0000, // 000D CALL R3 0
- 0x88100100, // 000E GETMBR R4 R0 K0
- 0x8C100902, // 000F GETMET R4 R4 K2
- 0x5C180600, // 0010 MOVE R6 R3
- 0x7C100400, // 0011 CALL R4 2
- 0x4C140000, // 0012 LDNIL R5
- 0x1C100805, // 0013 EQ R4 R4 R5
- 0x78120006, // 0014 JMPF R4 #001C
- 0x88100100, // 0015 GETMBR R4 R0 K0
- 0x98100601, // 0016 SETIDX R4 R3 R1
- 0x8C100103, // 0017 GETMET R4 R0 K3
- 0x5C180600, // 0018 MOVE R6 R3
- 0x7C100400, // 0019 CALL R4 2
- 0xA8040001, // 001A EXBLK 1 1
- 0x80040800, // 001B RET 1 R4
- 0x7001FFEE, // 001C JMP #000C
- 0x58080004, // 001D LDCONST R2 K4
- 0xAC080200, // 001E CATCH R2 1 0
- 0xB0080000, // 001F RAISE 2 R0 R0
- 0xB0060B06, // 0020 RAISE 1 K5 K6
- 0x80000000, // 0021 RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: set_light
-********************************************************************/
-be_local_closure(set_light, /* name */
- be_nested_proto(
- 8, /* nstack */
- 3, /* argc */
+ 4, /* nstack */
+ 1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
@@ -321,776 +106,19 @@ be_local_closure(set_light, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("tasmota.set_light() is deprecated, use light.set()", 2124937871, 50),
- /* K1 */ be_nested_string("light", -493019601, 5),
- /* K2 */ be_nested_string("set", -970520829, 3),
+ /* K0 */ be_nested_str(gc),
+ /* K1 */ be_nested_str(collect),
+ /* K2 */ be_nested_str(allocated),
}),
- (be_nested_const_str("set_light", -1118891144, 9)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[18]) { /* code */
- 0x600C0001, // 0000 GETGBL R3 G1
- 0x58100000, // 0001 LDCONST R4 K0
- 0x7C0C0200, // 0002 CALL R3 1
- 0xA40E0200, // 0003 IMPORT R3 K1
- 0x4C100000, // 0004 LDNIL R4
- 0x20100404, // 0005 NE R4 R2 R4
- 0x78120005, // 0006 JMPF R4 #000D
- 0x8C100702, // 0007 GETMET R4 R3 K2
- 0x5C180200, // 0008 MOVE R6 R1
- 0x5C1C0400, // 0009 MOVE R7 R2
- 0x7C100600, // 000A CALL R4 3
- 0x80040800, // 000B RET 1 R4
- 0x70020003, // 000C JMP #0011
- 0x8C100702, // 000D GETMET R4 R3 K2
- 0x5C180200, // 000E MOVE R6 R1
- 0x7C100400, // 000F CALL R4 2
- 0x80040800, // 0010 RET 1 R4
- 0x80000000, // 0011 RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: remove_rule
-********************************************************************/
-be_local_closure(remove_rule, /* name */
- be_nested_proto(
- 6, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("_rules", -28750191, 6),
- /* K1 */ be_const_int(0),
- /* K2 */ be_nested_string("k", -301188886, 1),
- /* K3 */ be_nested_string("remove", -611183107, 6),
- /* K4 */ be_const_int(1),
- }),
- (be_nested_const_str("remove_rule", -838755968, 11)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[21]) { /* code */
- 0x88080100, // 0000 GETMBR R2 R0 K0
- 0x780A0011, // 0001 JMPF R2 #0014
- 0x58080001, // 0002 LDCONST R2 K1
- 0x600C000C, // 0003 GETGBL R3 G12
- 0x88100100, // 0004 GETMBR R4 R0 K0
- 0x7C0C0200, // 0005 CALL R3 1
- 0x140C0403, // 0006 LT R3 R2 R3
- 0x780E000B, // 0007 JMPF R3 #0014
- 0x880C0100, // 0008 GETMBR R3 R0 K0
- 0x940C0602, // 0009 GETIDX R3 R3 R2
- 0x880C0702, // 000A GETMBR R3 R3 K2
- 0x1C0C0601, // 000B EQ R3 R3 R1
- 0x780E0004, // 000C JMPF R3 #0012
- 0x880C0100, // 000D GETMBR R3 R0 K0
- 0x8C0C0703, // 000E GETMET R3 R3 K3
- 0x5C140400, // 000F MOVE R5 R2
- 0x7C0C0400, // 0010 CALL R3 2
- 0x70020000, // 0011 JMP #0013
- 0x00080504, // 0012 ADD R2 R2 K4
- 0x7001FFEE, // 0013 JMP #0003
- 0x80000000, // 0014 RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: add_cmd
-********************************************************************/
-be_local_closure(add_cmd, /* name */
- be_nested_proto(
- 5, /* nstack */
- 3, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_string("_ccmd", -2131545883, 5),
- /* K1 */ be_nested_string("function", -1630125495, 8),
- /* K2 */ be_nested_string("value_error", 773297791, 11),
- /* K3 */ be_nested_string("the second argument is not a function", -340392827, 37),
- }),
- (be_nested_const_str("add_cmd", -933336417, 7)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[15]) { /* code */
- 0x880C0100, // 0000 GETMBR R3 R0 K0
- 0x740E0002, // 0001 JMPT R3 #0005
- 0x600C0013, // 0002 GETGBL R3 G19
- 0x7C0C0000, // 0003 CALL R3 0
- 0x90020003, // 0004 SETMBR R0 K0 R3
- 0x600C0004, // 0005 GETGBL R3 G4
- 0x5C100400, // 0006 MOVE R4 R2
- 0x7C0C0200, // 0007 CALL R3 1
- 0x1C0C0701, // 0008 EQ R3 R3 K1
- 0x780E0002, // 0009 JMPF R3 #000D
- 0x880C0100, // 000A GETMBR R3 R0 K0
- 0x980C0202, // 000B SETIDX R3 R1 R2
- 0x70020000, // 000C JMP #000E
- 0xB0060503, // 000D RAISE 1 K2 K3
- 0x80000000, // 000E RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: wire_scan
-********************************************************************/
-be_local_closure(wire_scan, /* name */
- be_nested_proto(
- 6, /* nstack */
- 3, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("i2c_enabled", 218388101, 11),
- /* K1 */ be_nested_string("wire1", -1082245877, 5),
- /* K2 */ be_nested_string("enabled", 49525662, 7),
- /* K3 */ be_nested_string("detect", 8884370, 6),
- /* K4 */ be_nested_string("wire2", -1065468258, 5),
- }),
- (be_nested_const_str("wire_scan", -1623691416, 9)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[33]) { /* code */
- 0x4C0C0000, // 0000 LDNIL R3
- 0x200C0403, // 0001 NE R3 R2 R3
- 0x780E0005, // 0002 JMPF R3 #0009
- 0x8C0C0100, // 0003 GETMET R3 R0 K0
- 0x5C140400, // 0004 MOVE R5 R2
- 0x7C0C0400, // 0005 CALL R3 2
- 0x740E0001, // 0006 JMPT R3 #0009
- 0x4C0C0000, // 0007 LDNIL R3
- 0x80040600, // 0008 RET 1 R3
- 0x880C0101, // 0009 GETMBR R3 R0 K1
- 0x8C0C0702, // 000A GETMET R3 R3 K2
- 0x7C0C0200, // 000B CALL R3 1
- 0x780E0006, // 000C JMPF R3 #0014
- 0x880C0101, // 000D GETMBR R3 R0 K1
- 0x8C0C0703, // 000E GETMET R3 R3 K3
- 0x5C140200, // 000F MOVE R5 R1
- 0x7C0C0400, // 0010 CALL R3 2
- 0x780E0001, // 0011 JMPF R3 #0014
- 0x880C0101, // 0012 GETMBR R3 R0 K1
- 0x80040600, // 0013 RET 1 R3
- 0x880C0104, // 0014 GETMBR R3 R0 K4
- 0x8C0C0702, // 0015 GETMET R3 R3 K2
- 0x7C0C0200, // 0016 CALL R3 1
- 0x780E0006, // 0017 JMPF R3 #001F
- 0x880C0104, // 0018 GETMBR R3 R0 K4
- 0x8C0C0703, // 0019 GETMET R3 R3 K3
- 0x5C140200, // 001A MOVE R5 R1
- 0x7C0C0400, // 001B CALL R3 2
- 0x780E0001, // 001C JMPF R3 #001F
- 0x880C0104, // 001D GETMBR R3 R0 K4
- 0x80040600, // 001E RET 1 R3
- 0x4C0C0000, // 001F LDNIL R3
- 0x80040600, // 0020 RET 1 R3
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: find_key_i
-********************************************************************/
-be_local_closure(find_key_i, /* name */
- be_nested_proto(
- 10, /* nstack */
- 3, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("string", 398550328, 6),
- /* K1 */ be_nested_string("toupper", -602983720, 7),
- /* K2 */ be_nested_string("keys", -112588595, 4),
- /* K3 */ be_nested_string("?", 973910158, 1),
- /* K4 */ be_nested_string("stop_iteration", -121173395, 14),
- }),
- (be_nested_const_str("find_key_i", 850136726, 10)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[30]) { /* code */
- 0xA40E0000, // 0000 IMPORT R3 K0
- 0x8C100701, // 0001 GETMET R4 R3 K1
- 0x5C180400, // 0002 MOVE R6 R2
- 0x7C100400, // 0003 CALL R4 2
- 0x6014000F, // 0004 GETGBL R5 G15
- 0x5C180200, // 0005 MOVE R6 R1
- 0x601C0013, // 0006 GETGBL R7 G19
- 0x7C140400, // 0007 CALL R5 2
- 0x78160013, // 0008 JMPF R5 #001D
- 0x60140010, // 0009 GETGBL R5 G16
- 0x8C180302, // 000A GETMET R6 R1 K2
- 0x7C180200, // 000B CALL R6 1
- 0x7C140200, // 000C CALL R5 1
- 0xA802000B, // 000D EXBLK 0 #001A
- 0x5C180A00, // 000E MOVE R6 R5
- 0x7C180000, // 000F CALL R6 0
- 0x8C1C0701, // 0010 GETMET R7 R3 K1
- 0x5C240C00, // 0011 MOVE R9 R6
- 0x7C1C0400, // 0012 CALL R7 2
- 0x1C1C0E04, // 0013 EQ R7 R7 R4
- 0x741E0001, // 0014 JMPT R7 #0017
- 0x1C1C0503, // 0015 EQ R7 R2 K3
- 0x781E0001, // 0016 JMPF R7 #0019
- 0xA8040001, // 0017 EXBLK 1 1
- 0x80040C00, // 0018 RET 1 R6
- 0x7001FFF3, // 0019 JMP #000E
- 0x58140004, // 001A LDCONST R5 K4
- 0xAC140200, // 001B CATCH R5 1 0
- 0xB0080000, // 001C RAISE 2 R0 R0
- 0x80000000, // 001D RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: chars_in_string
-********************************************************************/
-be_local_closure(chars_in_string, /* name */
- be_nested_proto(
- 10, /* nstack */
- 4, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_const_int(0),
- /* K1 */ be_const_int(1),
- }),
- (be_nested_const_str("chars_in_string", -1146182164, 15)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[31]) { /* code */
- 0x780E0001, // 0000 JMPF R3 #0003
- 0x50100200, // 0001 LDBOOL R4 1 0
- 0x70020000, // 0002 JMP #0004
- 0x50100000, // 0003 LDBOOL R4 0 0
- 0x58140000, // 0004 LDCONST R5 K0
- 0x6018000C, // 0005 GETGBL R6 G12
- 0x5C1C0200, // 0006 MOVE R7 R1
- 0x7C180200, // 0007 CALL R6 1
- 0x14180A06, // 0008 LT R6 R5 R6
- 0x781A0012, // 0009 JMPF R6 #001D
- 0x50180000, // 000A LDBOOL R6 0 0
- 0x581C0000, // 000B LDCONST R7 K0
- 0x6020000C, // 000C GETGBL R8 G12
- 0x5C240400, // 000D MOVE R9 R2
- 0x7C200200, // 000E CALL R8 1
- 0x14200E08, // 000F LT R8 R7 R8
- 0x78220006, // 0010 JMPF R8 #0018
- 0x94200205, // 0011 GETIDX R8 R1 R5
- 0x94240407, // 0012 GETIDX R9 R2 R7
- 0x1C201009, // 0013 EQ R8 R8 R9
- 0x78220000, // 0014 JMPF R8 #0016
- 0x50180200, // 0015 LDBOOL R6 1 0
- 0x001C0F01, // 0016 ADD R7 R7 K1
- 0x7001FFF3, // 0017 JMP #000C
- 0x20200806, // 0018 NE R8 R4 R6
- 0x78220000, // 0019 JMPF R8 #001B
- 0x80040A00, // 001A RET 1 R5
- 0x00140B01, // 001B ADD R5 R5 K1
- 0x7001FFE7, // 001C JMP #0005
- 0x5419FFFE, // 001D LDINT R6 -1
- 0x80040C00, // 001E RET 1 R6
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: set_timer
-********************************************************************/
-be_local_closure(set_timer, /* name */
- be_nested_proto(
- 10, /* nstack */
- 4, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_string("_timers", -1694866380, 7),
- /* K1 */ be_nested_string("push", -2022703139, 4),
- /* K2 */ be_nested_string("Timer", -346839614, 5),
- /* K3 */ be_nested_string("millis", 1214679063, 6),
- }),
- (be_nested_const_str("set_timer", 2135414533, 9)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[16]) { /* code */
- 0x88100100, // 0000 GETMBR R4 R0 K0
- 0x74120002, // 0001 JMPT R4 #0005
- 0x60100012, // 0002 GETGBL R4 G18
- 0x7C100000, // 0003 CALL R4 0
- 0x90020004, // 0004 SETMBR R0 K0 R4
- 0x88100100, // 0005 GETMBR R4 R0 K0
- 0x8C100901, // 0006 GETMET R4 R4 K1
- 0xB81A0400, // 0007 GETNGBL R6 K2
- 0x8C1C0103, // 0008 GETMET R7 R0 K3
- 0x5C240200, // 0009 MOVE R9 R1
- 0x7C1C0400, // 000A CALL R7 2
- 0x5C200400, // 000B MOVE R8 R2
- 0x5C240600, // 000C MOVE R9 R3
- 0x7C180600, // 000D CALL R6 3
- 0x7C100400, // 000E CALL R4 2
- 0x80000000, // 000F RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: add_rule
-********************************************************************/
-be_local_closure(add_rule, /* name */
- be_nested_proto(
- 9, /* nstack */
- 3, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_string("_rules", -28750191, 6),
- /* K1 */ be_nested_string("function", -1630125495, 8),
- /* K2 */ be_nested_string("push", -2022703139, 4),
- /* K3 */ be_nested_string("kv", 1497177492, 2),
- /* K4 */ be_nested_string("value_error", 773297791, 11),
- /* K5 */ be_nested_string("the second argument is not a function", -340392827, 37),
- }),
- (be_nested_const_str("add_rule", 596540743, 8)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[20]) { /* code */
- 0x880C0100, // 0000 GETMBR R3 R0 K0
- 0x740E0002, // 0001 JMPT R3 #0005
- 0x600C0012, // 0002 GETGBL R3 G18
- 0x7C0C0000, // 0003 CALL R3 0
- 0x90020003, // 0004 SETMBR R0 K0 R3
- 0x600C0004, // 0005 GETGBL R3 G4
- 0x5C100400, // 0006 MOVE R4 R2
- 0x7C0C0200, // 0007 CALL R3 1
- 0x1C0C0701, // 0008 EQ R3 R3 K1
- 0x780E0007, // 0009 JMPF R3 #0012
- 0x880C0100, // 000A GETMBR R3 R0 K0
- 0x8C0C0702, // 000B GETMET R3 R3 K2
- 0x8C140103, // 000C GETMET R5 R0 K3
- 0x5C1C0200, // 000D MOVE R7 R1
- 0x5C200400, // 000E MOVE R8 R2
- 0x7C140600, // 000F CALL R5 3
- 0x7C0C0400, // 0010 CALL R3 2
- 0x70020000, // 0011 JMP #0013
- 0xB0060905, // 0012 RAISE 1 K4 K5
- 0x80000000, // 0013 RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: run_deferred
-********************************************************************/
-be_local_closure(run_deferred, /* name */
- be_nested_proto(
- 6, /* nstack */
- 1, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 8]) { /* constants */
- /* K0 */ be_nested_string("_timers", -1694866380, 7),
- /* K1 */ be_const_int(0),
- /* K2 */ be_nested_string("size", 597743964, 4),
- /* K3 */ be_nested_string("time_reached", 2075136773, 12),
- /* K4 */ be_nested_string("due", -399437003, 3),
- /* K5 */ be_nested_string("f", -485742695, 1),
- /* K6 */ be_nested_string("remove", -611183107, 6),
- /* K7 */ be_const_int(1),
- }),
- (be_nested_const_str("run_deferred", 371594696, 12)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[27]) { /* code */
- 0x88040100, // 0000 GETMBR R1 R0 K0
- 0x78060017, // 0001 JMPF R1 #001A
- 0x58040001, // 0002 LDCONST R1 K1
- 0x88080100, // 0003 GETMBR R2 R0 K0
- 0x8C080502, // 0004 GETMET R2 R2 K2
- 0x7C080200, // 0005 CALL R2 1
- 0x14080202, // 0006 LT R2 R1 R2
- 0x780A0011, // 0007 JMPF R2 #001A
- 0x8C080103, // 0008 GETMET R2 R0 K3
- 0x88100100, // 0009 GETMBR R4 R0 K0
- 0x94100801, // 000A GETIDX R4 R4 R1
- 0x88100904, // 000B GETMBR R4 R4 K4
- 0x7C080400, // 000C CALL R2 2
- 0x780A0009, // 000D JMPF R2 #0018
- 0x88080100, // 000E GETMBR R2 R0 K0
- 0x94080401, // 000F GETIDX R2 R2 R1
- 0x88080505, // 0010 GETMBR R2 R2 K5
- 0x880C0100, // 0011 GETMBR R3 R0 K0
- 0x8C0C0706, // 0012 GETMET R3 R3 K6
- 0x5C140200, // 0013 MOVE R5 R1
- 0x7C0C0400, // 0014 CALL R3 2
- 0x5C0C0400, // 0015 MOVE R3 R2
- 0x7C0C0000, // 0016 CALL R3 0
- 0x70020000, // 0017 JMP #0019
- 0x00040307, // 0018 ADD R1 R1 K7
- 0x7001FFE8, // 0019 JMP #0003
- 0x80000000, // 001A RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: cmd
-********************************************************************/
-be_local_closure(cmd, /* name */
- be_nested_proto(
- 5, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("cmd_res", 921166762, 7),
- /* K1 */ be_nested_string("_cmd", -875145154, 4),
- }),
- (be_nested_const_str("cmd", -158181397, 3)),
- (be_nested_const_str("tasmota.be", 1128870755, 10)),
- ( &(const binstruction[14]) { /* code */
- 0x50080200, // 0000 LDBOOL R2 1 0
- 0x90020002, // 0001 SETMBR R0 K0 R2
- 0x8C080101, // 0002 GETMET R2 R0 K1
- 0x5C100200, // 0003 MOVE R4 R1
- 0x7C080400, // 0004 CALL R2 2
- 0x4C080000, // 0005 LDNIL R2
- 0x880C0100, // 0006 GETMBR R3 R0 K0
- 0x50100200, // 0007 LDBOOL R4 1 0
- 0x200C0604, // 0008 NE R3 R3 R4
- 0x780E0000, // 0009 JMPF R3 #000B
- 0x88080100, // 000A GETMBR R2 R0 K0
- 0x4C0C0000, // 000B LDNIL R3
- 0x90020003, // 000C SETMBR R0 K0 R3
- 0x80040400, // 000D RET 1 R2
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: time_str
-********************************************************************/
-be_local_closure(time_str, /* name */
- be_nested_proto(
- 13, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[10]) { /* constants */
- /* K0 */ be_nested_string("string", 398550328, 6),
- /* K1 */ be_nested_string("time_dump", -964556549, 9),
- /* K2 */ be_nested_string("format", -1180859054, 6),
- /* K3 */ be_nested_string("%04d-%02d-%02dT%02d:%02d:%02d", -869438695, 29),
- /* K4 */ be_nested_string("year", -1367388900, 4),
- /* K5 */ be_nested_string("month", -696646139, 5),
- /* K6 */ be_nested_string("day", -464576003, 3),
- /* K7 */ be_nested_string("hour", -1241306097, 4),
- /* K8 */ be_nested_string("min", -913357481, 3),
- /* K9 */ be_nested_string("sec", -1155074638, 3),
- }),
- (be_nested_const_str("time_str", -1681139684, 8)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[14]) { /* code */
- 0xA40A0000, // 0000 IMPORT R2 K0
- 0x8C0C0101, // 0001 GETMET R3 R0 K1
- 0x5C140200, // 0002 MOVE R5 R1
- 0x7C0C0400, // 0003 CALL R3 2
- 0x8C100502, // 0004 GETMET R4 R2 K2
- 0x58180003, // 0005 LDCONST R6 K3
- 0x941C0704, // 0006 GETIDX R7 R3 K4
- 0x94200705, // 0007 GETIDX R8 R3 K5
- 0x94240706, // 0008 GETIDX R9 R3 K6
- 0x94280707, // 0009 GETIDX R10 R3 K7
- 0x942C0708, // 000A GETIDX R11 R3 K8
- 0x94300709, // 000B GETIDX R12 R3 K9
- 0x7C101000, // 000C CALL R4 8
- 0x80040800, // 000D RET 1 R4
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: load
-********************************************************************/
-be_local_closure(load, /* name */
- be_nested_proto(
- 21, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 1, /* has sup protos */
- ( &(const struct bproto*[ 2]) {
- be_nested_proto(
- 6, /* nstack */
- 1, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_str_literal("sys"),
- /* K1 */ be_nested_str_literal("path"),
- /* K2 */ be_nested_str_literal("find"),
- /* K3 */ be_nested_str_literal("push"),
- }),
- (be_nested_const_str("push_path", 1155254157, 9)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[13]) { /* code */
- 0xA4060000, // 0000 IMPORT R1 K0
- 0x8C080301, // 0001 GETMET R2 R1 K1
- 0x7C080200, // 0002 CALL R2 1
- 0x8C0C0502, // 0003 GETMET R3 R2 K2
- 0x5C140000, // 0004 MOVE R5 R0
- 0x7C0C0400, // 0005 CALL R3 2
- 0x4C100000, // 0006 LDNIL R4
- 0x1C0C0604, // 0007 EQ R3 R3 R4
- 0x780E0002, // 0008 JMPF R3 #000C
- 0x8C0C0503, // 0009 GETMET R3 R2 K3
- 0x5C140000, // 000A MOVE R5 R0
- 0x7C0C0400, // 000B CALL R3 2
- 0x80000000, // 000C RET 0
- })
- ),
- be_nested_proto(
- 7, /* nstack */
- 1, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 4]) { /* constants */
- /* K0 */ be_nested_str_literal("sys"),
- /* K1 */ be_nested_str_literal("path"),
- /* K2 */ be_nested_str_literal("find"),
- /* K3 */ be_nested_str_literal("remove"),
- }),
- (be_nested_const_str("pop_path", -1891723298, 8)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[13]) { /* code */
- 0xA4060000, // 0000 IMPORT R1 K0
- 0x8C080301, // 0001 GETMET R2 R1 K1
- 0x7C080200, // 0002 CALL R2 1
- 0x8C0C0502, // 0003 GETMET R3 R2 K2
- 0x5C140000, // 0004 MOVE R5 R0
- 0x7C0C0400, // 0005 CALL R3 2
- 0x4C100000, // 0006 LDNIL R4
- 0x20100604, // 0007 NE R4 R3 R4
- 0x78120002, // 0008 JMPF R4 #000C
- 0x8C100503, // 0009 GETMET R4 R2 K3
- 0x5C180600, // 000A MOVE R6 R3
- 0x7C100400, // 000B CALL R4 2
- 0x80000000, // 000C RET 0
- })
- ),
- }),
- 1, /* has constants */
- ( &(const bvalue[21]) { /* constants */
- /* K0 */ be_nested_str_literal("string"),
- /* K1 */ be_nested_str_literal("path"),
- /* K2 */ be_const_int(0),
- /* K3 */ be_nested_str_literal("/"),
- /* K4 */ be_nested_str_literal("split"),
- /* K5 */ be_nested_str_literal("#"),
- /* K6 */ be_const_int(1),
- /* K7 */ be_nested_str_literal("find"),
- /* K8 */ be_nested_str_literal("."),
- /* K9 */ be_nested_str_literal(".be"),
- /* K10 */ be_nested_str_literal(".bec"),
- /* K11 */ be_nested_str_literal("io_error"),
- /* K12 */ be_nested_str_literal("file extension is not '.be' or '.bec'"),
- /* K13 */ be_nested_str_literal("last_modified"),
- /* K14 */ be_nested_str_literal("c"),
- /* K15 */ be_nested_str_literal("wd"),
- /* K16 */ be_nested_str_literal(""),
- /* K17 */ be_nested_str_literal("file"),
- /* K18 */ be_nested_str_literal("save"),
- /* K19 */ be_nested_str_literal("format"),
- /* K20 */ be_nested_str_literal("BRY: could not save compiled file %s (%s)"),
- }),
- (be_nested_const_str("load", -435725847, 4)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[121]) { /* code */
- 0x84080000, // 0000 CLOSURE R2 P0
- 0x840C0001, // 0001 CLOSURE R3 P1
- 0xA4120000, // 0002 IMPORT R4 K0
- 0xA4160200, // 0003 IMPORT R5 K1
- 0x6018000C, // 0004 GETGBL R6 G12
- 0x5C1C0200, // 0005 MOVE R7 R1
- 0x7C180200, // 0006 CALL R6 1
- 0x1C180D02, // 0007 EQ R6 R6 K2
- 0x781A0001, // 0008 JMPF R6 #000B
- 0x50180000, // 0009 LDBOOL R6 0 0
- 0x80040C00, // 000A RET 1 R6
- 0x94180302, // 000B GETIDX R6 R1 K2
- 0x20180D03, // 000C NE R6 R6 K3
- 0x781A0000, // 000D JMPF R6 #000F
- 0x00060601, // 000E ADD R1 K3 R1
- 0x8C180904, // 000F GETMET R6 R4 K4
- 0x5C200200, // 0010 MOVE R8 R1
- 0x58240005, // 0011 LDCONST R9 K5
- 0x7C180600, // 0012 CALL R6 3
- 0x941C0D02, // 0013 GETIDX R7 R6 K2
- 0x5421FFFE, // 0014 LDINT R8 -1
- 0x94200C08, // 0015 GETIDX R8 R6 R8
- 0x6024000C, // 0016 GETGBL R9 G12
- 0x5C280C00, // 0017 MOVE R10 R6
- 0x7C240200, // 0018 CALL R9 1
- 0x24241306, // 0019 GT R9 R9 K6
- 0x8C280907, // 001A GETMET R10 R4 K7
- 0x5C301000, // 001B MOVE R12 R8
- 0x58340008, // 001C LDCONST R13 K8
- 0x7C280600, // 001D CALL R10 3
- 0x14281502, // 001E LT R10 R10 K2
- 0x782A0001, // 001F JMPF R10 #0022
- 0x00040309, // 0020 ADD R1 R1 K9
- 0x00201109, // 0021 ADD R8 R8 K9
- 0x5429FFFC, // 0022 LDINT R10 -3
- 0x542DFFFE, // 0023 LDINT R11 -1
- 0x4028140B, // 0024 CONNECT R10 R10 R11
- 0x9428100A, // 0025 GETIDX R10 R8 R10
- 0x1C281509, // 0026 EQ R10 R10 K9
- 0x542DFFFB, // 0027 LDINT R11 -4
- 0x5431FFFE, // 0028 LDINT R12 -1
- 0x402C160C, // 0029 CONNECT R11 R11 R12
- 0x942C100B, // 002A GETIDX R11 R8 R11
- 0x1C2C170A, // 002B EQ R11 R11 K10
- 0x5C301400, // 002C MOVE R12 R10
- 0x74320002, // 002D JMPT R12 #0031
- 0x5C301600, // 002E MOVE R12 R11
- 0x74320000, // 002F JMPT R12 #0031
- 0xB006170C, // 0030 RAISE 1 K11 K12
- 0x8C300B0D, // 0031 GETMET R12 R5 K13
- 0x5C380E00, // 0032 MOVE R14 R7
- 0x7C300400, // 0033 CALL R12 2
- 0x782E0005, // 0034 JMPF R11 #003B
- 0x4C340000, // 0035 LDNIL R13
- 0x1C34180D, // 0036 EQ R13 R12 R13
- 0x78360001, // 0037 JMPF R13 #003A
- 0x50340000, // 0038 LDBOOL R13 0 0
- 0x80041A00, // 0039 RET 1 R13
- 0x70020013, // 003A JMP #004F
- 0x8C340B0D, // 003B GETMET R13 R5 K13
- 0x003C030E, // 003C ADD R15 R1 K14
- 0x7C340400, // 003D CALL R13 2
- 0x4C380000, // 003E LDNIL R14
- 0x1C38180E, // 003F EQ R14 R12 R14
- 0x783A0004, // 0040 JMPF R14 #0046
- 0x4C380000, // 0041 LDNIL R14
- 0x1C381A0E, // 0042 EQ R14 R13 R14
- 0x783A0001, // 0043 JMPF R14 #0046
- 0x50380000, // 0044 LDBOOL R14 0 0
- 0x80041C00, // 0045 RET 1 R14
- 0x4C380000, // 0046 LDNIL R14
- 0x20381A0E, // 0047 NE R14 R13 R14
- 0x783A0005, // 0048 JMPF R14 #004F
- 0x4C380000, // 0049 LDNIL R14
- 0x1C38180E, // 004A EQ R14 R12 R14
- 0x743A0001, // 004B JMPT R14 #004E
- 0x28381A0C, // 004C GE R14 R13 R12
- 0x783A0000, // 004D JMPF R14 #004F
- 0x502C0200, // 004E LDBOOL R11 1 0
- 0x78260005, // 004F JMPF R9 #0056
- 0x00340F05, // 0050 ADD R13 R7 K5
- 0x90021E0D, // 0051 SETMBR R0 K15 R13
- 0x5C340400, // 0052 MOVE R13 R2
- 0x8838010F, // 0053 GETMBR R14 R0 K15
- 0x7C340200, // 0054 CALL R13 1
- 0x70020000, // 0055 JMP #0057
- 0x90021F10, // 0056 SETMBR R0 K15 K16
- 0x6034000D, // 0057 GETGBL R13 G13
- 0x5C380200, // 0058 MOVE R14 R1
- 0x583C0011, // 0059 LDCONST R15 K17
- 0x7C340400, // 005A CALL R13 2
- 0x5C381600, // 005B MOVE R14 R11
- 0x743A0013, // 005C JMPT R14 #0071
- 0x5C381200, // 005D MOVE R14 R9
- 0x743A0011, // 005E JMPT R14 #0071
- 0xA8020005, // 005F EXBLK 0 #0066
- 0x8C380112, // 0060 GETMET R14 R0 K18
- 0x0040030E, // 0061 ADD R16 R1 K14
- 0x5C441A00, // 0062 MOVE R17 R13
- 0x7C380600, // 0063 CALL R14 3
- 0xA8040001, // 0064 EXBLK 1 1
- 0x7002000A, // 0065 JMP #0071
- 0xAC380001, // 0066 CATCH R14 0 1
- 0x70020007, // 0067 JMP #0070
- 0x603C0001, // 0068 GETGBL R15 G1
- 0x8C400913, // 0069 GETMET R16 R4 K19
- 0x58480014, // 006A LDCONST R18 K20
- 0x004C030E, // 006B ADD R19 R1 K14
- 0x5C501C00, // 006C MOVE R20 R14
- 0x7C400800, // 006D CALL R16 4
- 0x7C3C0200, // 006E CALL R15 1
- 0x70020000, // 006F JMP #0071
- 0xB0080000, // 0070 RAISE 2 R0 R0
- 0x5C381A00, // 0071 MOVE R14 R13
- 0x7C380000, // 0072 CALL R14 0
- 0x78260002, // 0073 JMPF R9 #0077
- 0x5C380600, // 0074 MOVE R14 R3
- 0x003C0F05, // 0075 ADD R15 R7 K5
- 0x7C380200, // 0076 CALL R14 1
- 0x50380200, // 0077 LDBOOL R14 1 0
- 0x80041C00, // 0078 RET 1 R14
+ &be_const_str_gc,
+ &be_const_str_solidified,
+ ( &(const binstruction[ 6]) { /* code */
+ 0xA4060000, // 0000 IMPORT R1 K0
+ 0x8C080301, // 0001 GETMET R2 R1 K1
+ 0x7C080200, // 0002 CALL R2 1
+ 0x8C080302, // 0003 GETMET R2 R1 K2
+ 0x7C080200, // 0004 CALL R2 1
+ 0x80040400, // 0005 RET 1 R2
})
)
);
@@ -1100,7 +128,7 @@ be_local_closure(load, /* name */
/********************************************************************
** Solidified function: find_op
********************************************************************/
-be_local_closure(find_op, /* name */
+be_local_closure(Tasmota_find_op, /* name */
be_nested_proto(
13, /* nstack */
2, /* argc */
@@ -1111,357 +139,58 @@ be_local_closure(find_op, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_string("string", 398550328, 6),
- /* K1 */ be_nested_string("=<>!", -1630497019, 4),
- /* K2 */ be_nested_string("chars_in_string", -1146182164, 15),
+ /* K0 */ be_nested_str(string),
+ /* K1 */ be_nested_str(_X3D_X3C_X3E_X21),
+ /* K2 */ be_nested_str(chars_in_string),
/* K3 */ be_const_int(0),
- /* K4 */ be_nested_string("split", -2017972765, 5),
+ /* K4 */ be_nested_str(split),
/* K5 */ be_const_int(1),
}),
- (be_nested_const_str("find_op", -528253920, 7)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_find_op,
+ &be_const_str_solidified,
( &(const binstruction[42]) { /* code */
- 0xA40A0000, // 0000 IMPORT R2 K0
- 0x580C0001, // 0001 LDCONST R3 K1
- 0x8C100102, // 0002 GETMET R4 R0 K2
- 0x5C180200, // 0003 MOVE R6 R1
- 0x5C1C0600, // 0004 MOVE R7 R3
- 0x7C100600, // 0005 CALL R4 3
- 0x28140903, // 0006 GE R5 R4 K3
- 0x78160019, // 0007 JMPF R5 #0022
- 0x8C140504, // 0008 GETMET R5 R2 K4
- 0x5C1C0200, // 0009 MOVE R7 R1
- 0x5C200800, // 000A MOVE R8 R4
- 0x7C140600, // 000B CALL R5 3
- 0x94180B03, // 000C GETIDX R6 R5 K3
- 0x941C0B05, // 000D GETIDX R7 R5 K5
- 0x8C200102, // 000E GETMET R8 R0 K2
- 0x5C280E00, // 000F MOVE R10 R7
- 0x5C2C0600, // 0010 MOVE R11 R3
- 0x50300200, // 0011 LDBOOL R12 1 0
- 0x7C200800, // 0012 CALL R8 4
- 0x5C101000, // 0013 MOVE R4 R8
- 0x28200903, // 0014 GE R8 R4 K3
- 0x7822000B, // 0015 JMPF R8 #0022
- 0x8C200504, // 0016 GETMET R8 R2 K4
- 0x5C280E00, // 0017 MOVE R10 R7
- 0x5C2C0800, // 0018 MOVE R11 R4
- 0x7C200600, // 0019 CALL R8 3
- 0x94241103, // 001A GETIDX R9 R8 K3
- 0x94281105, // 001B GETIDX R10 R8 K5
- 0x602C0012, // 001C GETGBL R11 G18
- 0x7C2C0000, // 001D CALL R11 0
- 0x40301606, // 001E CONNECT R12 R11 R6
- 0x40301609, // 001F CONNECT R12 R11 R9
- 0x4030160A, // 0020 CONNECT R12 R11 R10
- 0x80041600, // 0021 RET 1 R11
- 0x60140012, // 0022 GETGBL R5 G18
- 0x7C140000, // 0023 CALL R5 0
- 0x40180A01, // 0024 CONNECT R6 R5 R1
- 0x4C180000, // 0025 LDNIL R6
- 0x40180A06, // 0026 CONNECT R6 R5 R6
- 0x4C180000, // 0027 LDNIL R6
- 0x40180A06, // 0028 CONNECT R6 R5 R6
- 0x80040A00, // 0029 RET 1 R5
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: remove_timer
-********************************************************************/
-be_local_closure(remove_timer, /* name */
- be_nested_proto(
- 6, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 7]) { /* constants */
- /* K0 */ be_nested_string("tasmota", 424643812, 7),
- /* K1 */ be_nested_string("_timers", -1694866380, 7),
- /* K2 */ be_const_int(0),
- /* K3 */ be_nested_string("size", 597743964, 4),
- /* K4 */ be_nested_string("id", 926444256, 2),
- /* K5 */ be_nested_string("remove", -611183107, 6),
- /* K6 */ be_const_int(1),
- }),
- (be_nested_const_str("remove_timer", -153495081, 12)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[23]) { /* code */
- 0xB80A0000, // 0000 GETNGBL R2 K0
- 0x88080501, // 0001 GETMBR R2 R2 K1
- 0x780A0012, // 0002 JMPF R2 #0016
- 0x58080002, // 0003 LDCONST R2 K2
- 0xB80E0000, // 0004 GETNGBL R3 K0
- 0x880C0701, // 0005 GETMBR R3 R3 K1
- 0x8C0C0703, // 0006 GETMET R3 R3 K3
- 0x7C0C0200, // 0007 CALL R3 1
- 0x140C0403, // 0008 LT R3 R2 R3
- 0x780E000B, // 0009 JMPF R3 #0016
- 0x880C0101, // 000A GETMBR R3 R0 K1
- 0x940C0602, // 000B GETIDX R3 R3 R2
- 0x880C0704, // 000C GETMBR R3 R3 K4
- 0x1C0C0601, // 000D EQ R3 R3 R1
- 0x780E0004, // 000E JMPF R3 #0014
- 0x880C0101, // 000F GETMBR R3 R0 K1
- 0x8C0C0705, // 0010 GETMET R3 R3 K5
- 0x5C140400, // 0011 MOVE R5 R2
- 0x7C0C0400, // 0012 CALL R3 2
- 0x70020000, // 0013 JMP #0015
- 0x00080506, // 0014 ADD R2 R2 K6
- 0x7001FFED, // 0015 JMP #0004
- 0x80000000, // 0016 RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: get_light
-********************************************************************/
-be_local_closure(get_light, /* name */
- be_nested_proto(
- 6, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("tasmota.get_light() is deprecated, use light.get()", -769213649, 50),
- /* K1 */ be_nested_string("light", -493019601, 5),
- /* K2 */ be_nested_string("get", 1410115415, 3),
- }),
- (be_nested_const_str("get_light", 381930476, 9)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[16]) { /* code */
- 0x60080001, // 0000 GETGBL R2 G1
- 0x580C0000, // 0001 LDCONST R3 K0
- 0x7C080200, // 0002 CALL R2 1
- 0xA40A0200, // 0003 IMPORT R2 K1
- 0x4C0C0000, // 0004 LDNIL R3
- 0x200C0203, // 0005 NE R3 R1 R3
- 0x780E0004, // 0006 JMPF R3 #000C
- 0x8C0C0502, // 0007 GETMET R3 R2 K2
- 0x5C140200, // 0008 MOVE R5 R1
- 0x7C0C0400, // 0009 CALL R3 2
- 0x80040600, // 000A RET 1 R3
- 0x70020002, // 000B JMP #000F
- 0x8C0C0502, // 000C GETMET R3 R2 K2
- 0x7C0C0200, // 000D CALL R3 1
- 0x80040600, // 000E RET 1 R3
- 0x80000000, // 000F RET 0
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: exec_rules
-********************************************************************/
-be_local_closure(exec_rules, /* name */
- be_nested_proto(
- 12, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[12]) { /* constants */
- /* K0 */ be_nested_string("_rules", -28750191, 6),
- /* K1 */ be_nested_string("cmd_res", 921166762, 7),
- /* K2 */ be_nested_string("json", 916562499, 4),
- /* K3 */ be_nested_string("load", -435725847, 4),
- /* K4 */ be_nested_string("log", 1062293841, 3),
- /* K5 */ be_nested_string("BRY: ERROR, bad json: ", -1579831487, 22),
- /* K6 */ be_const_int(3),
- /* K7 */ be_const_int(0),
- /* K8 */ be_nested_string("try_rule", 1986449405, 8),
- /* K9 */ be_nested_string("k", -301188886, 1),
- /* K10 */ be_nested_string("v", -217300791, 1),
- /* K11 */ be_const_int(1),
- }),
- (be_nested_const_str("exec_rules", 1445221092, 10)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[48]) { /* code */
- 0x88080100, // 0000 GETMBR R2 R0 K0
- 0x740A0003, // 0001 JMPT R2 #0006
- 0x88080101, // 0002 GETMBR R2 R0 K1
- 0x4C0C0000, // 0003 LDNIL R3
- 0x20080403, // 0004 NE R2 R2 R3
- 0x780A0027, // 0005 JMPF R2 #002E
- 0xA40A0400, // 0006 IMPORT R2 K2
- 0x8C0C0503, // 0007 GETMET R3 R2 K3
- 0x5C140200, // 0008 MOVE R5 R1
- 0x7C0C0400, // 0009 CALL R3 2
- 0x50100000, // 000A LDBOOL R4 0 0
- 0x4C140000, // 000B LDNIL R5
- 0x1C140605, // 000C EQ R5 R3 R5
- 0x78160004, // 000D JMPF R5 #0013
- 0x8C140104, // 000E GETMET R5 R0 K4
- 0x001E0A01, // 000F ADD R7 K5 R1
- 0x58200006, // 0010 LDCONST R8 K6
- 0x7C140600, // 0011 CALL R5 3
- 0x5C0C0200, // 0012 MOVE R3 R1
- 0x88140101, // 0013 GETMBR R5 R0 K1
- 0x4C180000, // 0014 LDNIL R6
- 0x20140A06, // 0015 NE R5 R5 R6
- 0x78160000, // 0016 JMPF R5 #0018
- 0x90020203, // 0017 SETMBR R0 K1 R3
- 0x88140100, // 0018 GETMBR R5 R0 K0
- 0x78160012, // 0019 JMPF R5 #002D
- 0x58140007, // 001A LDCONST R5 K7
- 0x6018000C, // 001B GETGBL R6 G12
- 0x881C0100, // 001C GETMBR R7 R0 K0
- 0x7C180200, // 001D CALL R6 1
- 0x14180A06, // 001E LT R6 R5 R6
- 0x781A000C, // 001F JMPF R6 #002D
- 0x88180100, // 0020 GETMBR R6 R0 K0
- 0x94180C05, // 0021 GETIDX R6 R6 R5
- 0x8C1C0108, // 0022 GETMET R7 R0 K8
- 0x5C240600, // 0023 MOVE R9 R3
- 0x88280D09, // 0024 GETMBR R10 R6 K9
- 0x882C0D0A, // 0025 GETMBR R11 R6 K10
- 0x7C1C0800, // 0026 CALL R7 4
- 0x741E0001, // 0027 JMPT R7 #002A
- 0x74120000, // 0028 JMPT R4 #002A
- 0x50100001, // 0029 LDBOOL R4 0 1
- 0x50100200, // 002A LDBOOL R4 1 0
- 0x00140B0B, // 002B ADD R5 R5 K11
- 0x7001FFED, // 002C JMP #001B
- 0x80040800, // 002D RET 1 R4
- 0x50080000, // 002E LDBOOL R2 0 0
- 0x80040400, // 002F RET 1 R2
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: exec_tele
-********************************************************************/
-be_local_closure(exec_tele, /* name */
- be_nested_proto(
- 12, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[12]) { /* constants */
- /* K0 */ be_nested_string("_rules", -28750191, 6),
- /* K1 */ be_nested_string("json", 916562499, 4),
- /* K2 */ be_nested_string("load", -435725847, 4),
- /* K3 */ be_nested_string("log", 1062293841, 3),
- /* K4 */ be_nested_string("BRY: ERROR, bad json: ", -1579831487, 22),
- /* K5 */ be_const_int(3),
- /* K6 */ be_nested_string("Tele", 1329980653, 4),
- /* K7 */ be_const_int(0),
- /* K8 */ be_nested_string("try_rule", 1986449405, 8),
- /* K9 */ be_nested_string("k", -301188886, 1),
- /* K10 */ be_nested_string("v", -217300791, 1),
- /* K11 */ be_const_int(1),
- }),
- (be_nested_const_str("exec_tele", 1020751601, 9)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[41]) { /* code */
- 0x88080100, // 0000 GETMBR R2 R0 K0
- 0x780A0024, // 0001 JMPF R2 #0027
- 0xA40A0200, // 0002 IMPORT R2 K1
- 0x8C0C0502, // 0003 GETMET R3 R2 K2
- 0x5C140200, // 0004 MOVE R5 R1
- 0x7C0C0400, // 0005 CALL R3 2
- 0x50100000, // 0006 LDBOOL R4 0 0
- 0x4C140000, // 0007 LDNIL R5
- 0x1C140605, // 0008 EQ R5 R3 R5
- 0x78160004, // 0009 JMPF R5 #000F
- 0x8C140103, // 000A GETMET R5 R0 K3
- 0x001E0801, // 000B ADD R7 K4 R1
- 0x58200005, // 000C LDCONST R8 K5
- 0x7C140600, // 000D CALL R5 3
- 0x5C0C0200, // 000E MOVE R3 R1
- 0x60140013, // 000F GETGBL R5 G19
- 0x7C140000, // 0010 CALL R5 0
- 0x98160C03, // 0011 SETIDX R5 K6 R3
- 0x5C0C0A00, // 0012 MOVE R3 R5
- 0x58140007, // 0013 LDCONST R5 K7
- 0x6018000C, // 0014 GETGBL R6 G12
- 0x881C0100, // 0015 GETMBR R7 R0 K0
- 0x7C180200, // 0016 CALL R6 1
- 0x14180A06, // 0017 LT R6 R5 R6
- 0x781A000C, // 0018 JMPF R6 #0026
- 0x88180100, // 0019 GETMBR R6 R0 K0
- 0x94180C05, // 001A GETIDX R6 R6 R5
- 0x8C1C0108, // 001B GETMET R7 R0 K8
- 0x5C240600, // 001C MOVE R9 R3
- 0x88280D09, // 001D GETMBR R10 R6 K9
- 0x882C0D0A, // 001E GETMBR R11 R6 K10
- 0x7C1C0800, // 001F CALL R7 4
- 0x741E0001, // 0020 JMPT R7 #0023
- 0x74120000, // 0021 JMPT R4 #0023
- 0x50100001, // 0022 LDBOOL R4 0 1
- 0x50100200, // 0023 LDBOOL R4 1 0
- 0x00140B0B, // 0024 ADD R5 R5 K11
- 0x7001FFED, // 0025 JMP #0014
- 0x80040800, // 0026 RET 1 R4
- 0x50080000, // 0027 LDBOOL R2 0 0
- 0x80040400, // 0028 RET 1 R2
- })
- )
-);
-/*******************************************************************/
-
-
-/********************************************************************
-** Solidified function: remove_driver
-********************************************************************/
-be_local_closure(remove_driver, /* name */
- be_nested_proto(
- 6, /* nstack */
- 2, /* argc */
- 0, /* varg */
- 0, /* has upvals */
- NULL, /* no upvals */
- 0, /* has sup protos */
- NULL, /* no sub protos */
- 1, /* has constants */
- ( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("_drivers", -1034638311, 8),
- /* K1 */ be_nested_string("find", -1108310694, 4),
- /* K2 */ be_nested_string("pop", 1362321360, 3),
- }),
- (be_nested_const_str("remove_driver", 1030243768, 13)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[14]) { /* code */
- 0x88080100, // 0000 GETMBR R2 R0 K0
- 0x780A000A, // 0001 JMPF R2 #000D
- 0x88080100, // 0002 GETMBR R2 R0 K0
- 0x8C080501, // 0003 GETMET R2 R2 K1
- 0x5C100200, // 0004 MOVE R4 R1
- 0x7C080400, // 0005 CALL R2 2
- 0x4C0C0000, // 0006 LDNIL R3
- 0x200C0403, // 0007 NE R3 R2 R3
- 0x780E0003, // 0008 JMPF R3 #000D
- 0x880C0100, // 0009 GETMBR R3 R0 K0
- 0x8C0C0702, // 000A GETMET R3 R3 K2
- 0x5C140400, // 000B MOVE R5 R2
- 0x7C0C0400, // 000C CALL R3 2
- 0x80000000, // 000D RET 0
+ 0xA40A0000, // 0000 IMPORT R2 K0
+ 0x580C0001, // 0001 LDCONST R3 K1
+ 0x8C100102, // 0002 GETMET R4 R0 K2
+ 0x5C180200, // 0003 MOVE R6 R1
+ 0x5C1C0600, // 0004 MOVE R7 R3
+ 0x7C100600, // 0005 CALL R4 3
+ 0x28140903, // 0006 GE R5 R4 K3
+ 0x78160019, // 0007 JMPF R5 #0022
+ 0x8C140504, // 0008 GETMET R5 R2 K4
+ 0x5C1C0200, // 0009 MOVE R7 R1
+ 0x5C200800, // 000A MOVE R8 R4
+ 0x7C140600, // 000B CALL R5 3
+ 0x94180B03, // 000C GETIDX R6 R5 K3
+ 0x941C0B05, // 000D GETIDX R7 R5 K5
+ 0x8C200102, // 000E GETMET R8 R0 K2
+ 0x5C280E00, // 000F MOVE R10 R7
+ 0x5C2C0600, // 0010 MOVE R11 R3
+ 0x50300200, // 0011 LDBOOL R12 1 0
+ 0x7C200800, // 0012 CALL R8 4
+ 0x5C101000, // 0013 MOVE R4 R8
+ 0x28200903, // 0014 GE R8 R4 K3
+ 0x7822000B, // 0015 JMPF R8 #0022
+ 0x8C200504, // 0016 GETMET R8 R2 K4
+ 0x5C280E00, // 0017 MOVE R10 R7
+ 0x5C2C0800, // 0018 MOVE R11 R4
+ 0x7C200600, // 0019 CALL R8 3
+ 0x94241103, // 001A GETIDX R9 R8 K3
+ 0x94281105, // 001B GETIDX R10 R8 K5
+ 0x602C0012, // 001C GETGBL R11 G18
+ 0x7C2C0000, // 001D CALL R11 0
+ 0x40301606, // 001E CONNECT R12 R11 R6
+ 0x40301609, // 001F CONNECT R12 R11 R9
+ 0x4030160A, // 0020 CONNECT R12 R11 R10
+ 0x80041600, // 0021 RET 1 R11
+ 0x60140012, // 0022 GETGBL R5 G18
+ 0x7C140000, // 0023 CALL R5 0
+ 0x40180A01, // 0024 CONNECT R6 R5 R1
+ 0x4C180000, // 0025 LDNIL R6
+ 0x40180A06, // 0026 CONNECT R6 R5 R6
+ 0x4C180000, // 0027 LDNIL R6
+ 0x40180A06, // 0028 CONNECT R6 R5 R6
+ 0x80040A00, // 0029 RET 1 R5
})
)
);
@@ -1471,7 +200,7 @@ be_local_closure(remove_driver, /* name */
/********************************************************************
** Solidified function: try_rule
********************************************************************/
-be_local_closure(try_rule, /* name */
+be_local_closure(Tasmota_try_rule, /* name */
be_nested_proto(
15, /* nstack */
4, /* argc */
@@ -1482,25 +211,25 @@ be_local_closure(try_rule, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[16]) { /* constants */
- /* K0 */ be_nested_string("string", 398550328, 6),
- /* K1 */ be_nested_string("find_op", -528253920, 7),
- /* K2 */ be_nested_string("split", -2017972765, 5),
+ /* K0 */ be_nested_str(string),
+ /* K1 */ be_nested_str(find_op),
+ /* K2 */ be_nested_str(split),
/* K3 */ be_const_int(0),
- /* K4 */ be_nested_string("#", 638357778, 1),
- /* K5 */ be_nested_string("find_key_i", 850136726, 10),
+ /* K4 */ be_nested_str(_X23),
+ /* K5 */ be_nested_str(find_key_i),
/* K6 */ be_const_int(1),
/* K7 */ be_const_int(2),
- /* K8 */ be_nested_string("==", -1863000881, 2),
- /* K9 */ be_nested_string("!==", 559817114, 3),
- /* K10 */ be_nested_string("=", 940354920, 1),
- /* K11 */ be_nested_string("!=", -1866252285, 2),
- /* K12 */ be_nested_string(">", 990687777, 1),
- /* K13 */ be_nested_string(">=", 284975636, 2),
- /* K14 */ be_nested_string("<", 957132539, 1),
- /* K15 */ be_nested_string("<=", -1795743310, 2),
+ /* K8 */ be_nested_str(_X3D_X3D),
+ /* K9 */ be_nested_str(_X21_X3D_X3D),
+ /* K10 */ be_nested_str(_X3D),
+ /* K11 */ be_nested_str(_X21_X3D),
+ /* K12 */ be_nested_str(_X3E),
+ /* K13 */ be_nested_str(_X3E_X3D),
+ /* K14 */ be_nested_str(_X3C),
+ /* K15 */ be_nested_str(_X3C_X3D),
}),
- (be_nested_const_str("try_rule", 1986449405, 8)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_try_rule,
+ &be_const_str_solidified,
( &(const binstruction[141]) { /* code */
0xA4120000, // 0000 IMPORT R4 K0
0x8C140101, // 0001 GETMET R5 R0 K1
@@ -1650,46 +379,64 @@ be_local_closure(try_rule, /* name */
/********************************************************************
-** Solidified function: cb_dispatch
+** Solidified function: gen_cb
********************************************************************/
-be_local_closure(cb_dispatch, /* name */
+be_local_closure(Tasmota_gen_cb, /* name */
be_nested_proto(
- 12, /* nstack */
- 6, /* argc */
+ 7, /* nstack */
+ 2, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
- ( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("_cb", -251666929, 3),
+ ( &(const bvalue[ 7]) { /* constants */
+ /* K0 */ be_nested_str(_cb),
/* K1 */ be_const_int(0),
- /* K2 */ be_nested_string("find", -1108310694, 4),
+ /* K2 */ be_nested_str(find),
+ /* K3 */ be_nested_str(_get_cb),
+ /* K4 */ be_nested_str(stop_iteration),
+ /* K5 */ be_nested_str(internal_error),
+ /* K6 */ be_nested_str(No_X20callback_X20available),
}),
- (be_nested_const_str("cb_dispatch", 1741510499, 11)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[20]) { /* code */
- 0x88180100, // 0000 GETMBR R6 R0 K0
- 0x4C1C0000, // 0001 LDNIL R7
- 0x1C180C07, // 0002 EQ R6 R6 R7
- 0x781A0000, // 0003 JMPF R6 #0005
- 0x80060200, // 0004 RET 1 K1
- 0x88180100, // 0005 GETMBR R6 R0 K0
- 0x8C180D02, // 0006 GETMET R6 R6 K2
- 0x5C200200, // 0007 MOVE R8 R1
- 0x7C180400, // 0008 CALL R6 2
- 0x4C1C0000, // 0009 LDNIL R7
- 0x201C0C07, // 000A NE R7 R6 R7
- 0x781E0006, // 000B JMPF R7 #0013
- 0x5C1C0C00, // 000C MOVE R7 R6
- 0x5C200400, // 000D MOVE R8 R2
- 0x5C240600, // 000E MOVE R9 R3
- 0x5C280800, // 000F MOVE R10 R4
- 0x5C2C0A00, // 0010 MOVE R11 R5
- 0x7C1C0800, // 0011 CALL R7 4
- 0x80040E00, // 0012 RET 1 R7
- 0x80060200, // 0013 RET 1 K1
+ &be_const_str_gen_cb,
+ &be_const_str_solidified,
+ ( &(const binstruction[34]) { /* code */
+ 0x88080100, // 0000 GETMBR R2 R0 K0
+ 0x4C0C0000, // 0001 LDNIL R3
+ 0x1C080403, // 0002 EQ R2 R2 R3
+ 0x780A0002, // 0003 JMPF R2 #0007
+ 0x60080013, // 0004 GETGBL R2 G19
+ 0x7C080000, // 0005 CALL R2 0
+ 0x90020002, // 0006 SETMBR R0 K0 R2
+ 0x60080010, // 0007 GETGBL R2 G16
+ 0x540E0012, // 0008 LDINT R3 19
+ 0x400E0203, // 0009 CONNECT R3 K1 R3
+ 0x7C080200, // 000A CALL R2 1
+ 0xA8020010, // 000B EXBLK 0 #001D
+ 0x5C0C0400, // 000C MOVE R3 R2
+ 0x7C0C0000, // 000D CALL R3 0
+ 0x88100100, // 000E GETMBR R4 R0 K0
+ 0x8C100902, // 000F GETMET R4 R4 K2
+ 0x5C180600, // 0010 MOVE R6 R3
+ 0x7C100400, // 0011 CALL R4 2
+ 0x4C140000, // 0012 LDNIL R5
+ 0x1C100805, // 0013 EQ R4 R4 R5
+ 0x78120006, // 0014 JMPF R4 #001C
+ 0x88100100, // 0015 GETMBR R4 R0 K0
+ 0x98100601, // 0016 SETIDX R4 R3 R1
+ 0x8C100103, // 0017 GETMET R4 R0 K3
+ 0x5C180600, // 0018 MOVE R6 R3
+ 0x7C100400, // 0019 CALL R4 2
+ 0xA8040001, // 001A EXBLK 1 1
+ 0x80040800, // 001B RET 1 R4
+ 0x7001FFEE, // 001C JMP #000C
+ 0x58080004, // 001D LDCONST R2 K4
+ 0xAC080200, // 001E CATCH R2 1 0
+ 0xB0080000, // 001F RAISE 2 R0 R0
+ 0xB0060B06, // 0020 RAISE 1 K5 K6
+ 0x80000000, // 0021 RET 0
})
)
);
@@ -1697,12 +444,12 @@ be_local_closure(cb_dispatch, /* name */
/********************************************************************
-** Solidified function: gc
+** Solidified function: set_light
********************************************************************/
-be_local_closure(gc, /* name */
+be_local_closure(Tasmota_set_light, /* name */
be_nested_proto(
- 4, /* nstack */
- 1, /* argc */
+ 8, /* nstack */
+ 3, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
@@ -1710,19 +457,208 @@ be_local_closure(gc, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
- /* K0 */ be_nested_string("gc", 1042313471, 2),
- /* K1 */ be_nested_string("collect", -1895928271, 7),
- /* K2 */ be_nested_string("allocated", 429986098, 9),
+ /* K0 */ be_nested_str(tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29),
+ /* K1 */ be_nested_str(light),
+ /* K2 */ be_nested_str(set),
}),
- (be_nested_const_str("gc", 1042313471, 2)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[ 6]) { /* code */
- 0xA4060000, // 0000 IMPORT R1 K0
- 0x8C080301, // 0001 GETMET R2 R1 K1
- 0x7C080200, // 0002 CALL R2 1
- 0x8C080302, // 0003 GETMET R2 R1 K2
- 0x7C080200, // 0004 CALL R2 1
- 0x80040400, // 0005 RET 1 R2
+ &be_const_str_set_light,
+ &be_const_str_solidified,
+ ( &(const binstruction[18]) { /* code */
+ 0x600C0001, // 0000 GETGBL R3 G1
+ 0x58100000, // 0001 LDCONST R4 K0
+ 0x7C0C0200, // 0002 CALL R3 1
+ 0xA40E0200, // 0003 IMPORT R3 K1
+ 0x4C100000, // 0004 LDNIL R4
+ 0x20100404, // 0005 NE R4 R2 R4
+ 0x78120005, // 0006 JMPF R4 #000D
+ 0x8C100702, // 0007 GETMET R4 R3 K2
+ 0x5C180200, // 0008 MOVE R6 R1
+ 0x5C1C0400, // 0009 MOVE R7 R2
+ 0x7C100600, // 000A CALL R4 3
+ 0x80040800, // 000B RET 1 R4
+ 0x70020003, // 000C JMP #0011
+ 0x8C100702, // 000D GETMET R4 R3 K2
+ 0x5C180200, // 000E MOVE R6 R1
+ 0x7C100400, // 000F CALL R4 2
+ 0x80040800, // 0010 RET 1 R4
+ 0x80000000, // 0011 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: exec_tele
+********************************************************************/
+be_local_closure(Tasmota_exec_tele, /* name */
+ be_nested_proto(
+ 12, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[12]) { /* constants */
+ /* K0 */ be_nested_str(_rules),
+ /* K1 */ be_nested_str(json),
+ /* K2 */ be_nested_str(load),
+ /* K3 */ be_nested_str(log),
+ /* K4 */ be_nested_str(BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20),
+ /* K5 */ be_const_int(3),
+ /* K6 */ be_nested_str(Tele),
+ /* K7 */ be_const_int(0),
+ /* K8 */ be_nested_str(try_rule),
+ /* K9 */ be_nested_str(k),
+ /* K10 */ be_nested_str(v),
+ /* K11 */ be_const_int(1),
+ }),
+ &be_const_str_exec_tele,
+ &be_const_str_solidified,
+ ( &(const binstruction[41]) { /* code */
+ 0x88080100, // 0000 GETMBR R2 R0 K0
+ 0x780A0024, // 0001 JMPF R2 #0027
+ 0xA40A0200, // 0002 IMPORT R2 K1
+ 0x8C0C0502, // 0003 GETMET R3 R2 K2
+ 0x5C140200, // 0004 MOVE R5 R1
+ 0x7C0C0400, // 0005 CALL R3 2
+ 0x50100000, // 0006 LDBOOL R4 0 0
+ 0x4C140000, // 0007 LDNIL R5
+ 0x1C140605, // 0008 EQ R5 R3 R5
+ 0x78160004, // 0009 JMPF R5 #000F
+ 0x8C140103, // 000A GETMET R5 R0 K3
+ 0x001E0801, // 000B ADD R7 K4 R1
+ 0x58200005, // 000C LDCONST R8 K5
+ 0x7C140600, // 000D CALL R5 3
+ 0x5C0C0200, // 000E MOVE R3 R1
+ 0x60140013, // 000F GETGBL R5 G19
+ 0x7C140000, // 0010 CALL R5 0
+ 0x98160C03, // 0011 SETIDX R5 K6 R3
+ 0x5C0C0A00, // 0012 MOVE R3 R5
+ 0x58140007, // 0013 LDCONST R5 K7
+ 0x6018000C, // 0014 GETGBL R6 G12
+ 0x881C0100, // 0015 GETMBR R7 R0 K0
+ 0x7C180200, // 0016 CALL R6 1
+ 0x14180A06, // 0017 LT R6 R5 R6
+ 0x781A000C, // 0018 JMPF R6 #0026
+ 0x88180100, // 0019 GETMBR R6 R0 K0
+ 0x94180C05, // 001A GETIDX R6 R6 R5
+ 0x8C1C0108, // 001B GETMET R7 R0 K8
+ 0x5C240600, // 001C MOVE R9 R3
+ 0x88280D09, // 001D GETMBR R10 R6 K9
+ 0x882C0D0A, // 001E GETMBR R11 R6 K10
+ 0x7C1C0800, // 001F CALL R7 4
+ 0x741E0001, // 0020 JMPT R7 #0023
+ 0x74120000, // 0021 JMPT R4 #0023
+ 0x50100001, // 0022 LDBOOL R4 0 1
+ 0x50100200, // 0023 LDBOOL R4 1 0
+ 0x00140B0B, // 0024 ADD R5 R5 K11
+ 0x7001FFED, // 0025 JMP #0014
+ 0x80040800, // 0026 RET 1 R4
+ 0x50080000, // 0027 LDBOOL R2 0 0
+ 0x80040400, // 0028 RET 1 R2
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: run_deferred
+********************************************************************/
+be_local_closure(Tasmota_run_deferred, /* name */
+ be_nested_proto(
+ 6, /* nstack */
+ 1, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 8]) { /* constants */
+ /* K0 */ be_nested_str(_timers),
+ /* K1 */ be_const_int(0),
+ /* K2 */ be_nested_str(size),
+ /* K3 */ be_nested_str(time_reached),
+ /* K4 */ be_nested_str(due),
+ /* K5 */ be_nested_str(f),
+ /* K6 */ be_nested_str(remove),
+ /* K7 */ be_const_int(1),
+ }),
+ &be_const_str_run_deferred,
+ &be_const_str_solidified,
+ ( &(const binstruction[27]) { /* code */
+ 0x88040100, // 0000 GETMBR R1 R0 K0
+ 0x78060017, // 0001 JMPF R1 #001A
+ 0x58040001, // 0002 LDCONST R1 K1
+ 0x88080100, // 0003 GETMBR R2 R0 K0
+ 0x8C080502, // 0004 GETMET R2 R2 K2
+ 0x7C080200, // 0005 CALL R2 1
+ 0x14080202, // 0006 LT R2 R1 R2
+ 0x780A0011, // 0007 JMPF R2 #001A
+ 0x8C080103, // 0008 GETMET R2 R0 K3
+ 0x88100100, // 0009 GETMBR R4 R0 K0
+ 0x94100801, // 000A GETIDX R4 R4 R1
+ 0x88100904, // 000B GETMBR R4 R4 K4
+ 0x7C080400, // 000C CALL R2 2
+ 0x780A0009, // 000D JMPF R2 #0018
+ 0x88080100, // 000E GETMBR R2 R0 K0
+ 0x94080401, // 000F GETIDX R2 R2 R1
+ 0x88080505, // 0010 GETMBR R2 R2 K5
+ 0x880C0100, // 0011 GETMBR R3 R0 K0
+ 0x8C0C0706, // 0012 GETMET R3 R3 K6
+ 0x5C140200, // 0013 MOVE R5 R1
+ 0x7C0C0400, // 0014 CALL R3 2
+ 0x5C0C0400, // 0015 MOVE R3 R2
+ 0x7C0C0000, // 0016 CALL R3 0
+ 0x70020000, // 0017 JMP #0019
+ 0x00040307, // 0018 ADD R1 R1 K7
+ 0x7001FFE8, // 0019 JMP #0003
+ 0x80000000, // 001A RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: remove_driver
+********************************************************************/
+be_local_closure(Tasmota_remove_driver, /* name */
+ be_nested_proto(
+ 6, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 3]) { /* constants */
+ /* K0 */ be_nested_str(_drivers),
+ /* K1 */ be_nested_str(find),
+ /* K2 */ be_nested_str(pop),
+ }),
+ &be_const_str_remove_driver,
+ &be_const_str_solidified,
+ ( &(const binstruction[14]) { /* code */
+ 0x88080100, // 0000 GETMBR R2 R0 K0
+ 0x780A000A, // 0001 JMPF R2 #000D
+ 0x88080100, // 0002 GETMBR R2 R0 K0
+ 0x8C080501, // 0003 GETMET R2 R2 K1
+ 0x5C100200, // 0004 MOVE R4 R1
+ 0x7C080400, // 0005 CALL R2 2
+ 0x4C0C0000, // 0006 LDNIL R3
+ 0x200C0403, // 0007 NE R3 R2 R3
+ 0x780E0003, // 0008 JMPF R3 #000D
+ 0x880C0100, // 0009 GETMBR R3 R0 K0
+ 0x8C0C0702, // 000A GETMET R3 R3 K2
+ 0x5C140400, // 000B MOVE R5 R2
+ 0x7C0C0400, // 000C CALL R3 2
+ 0x80000000, // 000D RET 0
})
)
);
@@ -1732,7 +668,7 @@ be_local_closure(gc, /* name */
/********************************************************************
** Solidified function: event
********************************************************************/
-be_local_closure(event, /* name */
+be_local_closure(Tasmota_event, /* name */
be_nested_proto(
20, /* nstack */
6, /* argc */
@@ -1743,32 +679,32 @@ be_local_closure(event, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[23]) { /* constants */
- /* K0 */ be_nested_string("introspect", 164638290, 10),
- /* K1 */ be_nested_string("string", 398550328, 6),
- /* K2 */ be_nested_string("every_50ms", -1911083288, 10),
- /* K3 */ be_nested_string("run_deferred", 371594696, 12),
- /* K4 */ be_nested_string("cmd", -158181397, 3),
- /* K5 */ be_nested_string("exec_cmd", 493567399, 8),
- /* K6 */ be_nested_string("tele", -820509235, 4),
- /* K7 */ be_nested_string("exec_tele", 1020751601, 9),
- /* K8 */ be_nested_string("rule", -64077613, 4),
- /* K9 */ be_nested_string("exec_rules", 1445221092, 10),
- /* K10 */ be_nested_string("gc", 1042313471, 2),
- /* K11 */ be_nested_string("_drivers", -1034638311, 8),
+ /* K0 */ be_nested_str(introspect),
+ /* K1 */ be_nested_str(string),
+ /* K2 */ be_nested_str(every_50ms),
+ /* K3 */ be_nested_str(run_deferred),
+ /* K4 */ be_nested_str(cmd),
+ /* K5 */ be_nested_str(exec_cmd),
+ /* K6 */ be_nested_str(tele),
+ /* K7 */ be_nested_str(exec_tele),
+ /* K8 */ be_nested_str(rule),
+ /* K9 */ be_nested_str(exec_rules),
+ /* K10 */ be_nested_str(gc),
+ /* K11 */ be_nested_str(_drivers),
/* K12 */ be_const_int(0),
- /* K13 */ be_nested_string("get", 1410115415, 3),
- /* K14 */ be_nested_string("function", -1630125495, 8),
- /* K15 */ be_nested_string("format", -1180859054, 6),
- /* K16 */ be_nested_string("BRY: Exception> '%s' - %s", -2047976332, 25),
- /* K17 */ be_nested_string("debug", 1483009432, 5),
- /* K18 */ be_nested_string("traceback", -909779187, 9),
+ /* K13 */ be_nested_str(get),
+ /* K14 */ be_nested_str(function),
+ /* K15 */ be_nested_str(format),
+ /* K16 */ be_nested_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
+ /* K17 */ be_nested_str(debug),
+ /* K18 */ be_nested_str(traceback),
/* K19 */ be_const_int(1),
- /* K20 */ be_nested_string("save_before_restart", 1253239338, 19),
- /* K21 */ be_nested_string("persist", -377883517, 7),
- /* K22 */ be_nested_string("save", -855671224, 4),
+ /* K20 */ be_nested_str(save_before_restart),
+ /* K21 */ be_nested_str(persist),
+ /* K22 */ be_nested_str(save),
}),
- (be_nested_const_str("event", -30355297, 5)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_event,
+ &be_const_str_solidified,
( &(const binstruction[91]) { /* code */
0xA41A0000, // 0000 IMPORT R6 K0
0xA41E0200, // 0001 IMPORT R7 K1
@@ -1868,9 +804,593 @@ be_local_closure(event, /* name */
/********************************************************************
-** Solidified function: remove_cmd
+** Solidified function: find_key_i
********************************************************************/
-be_local_closure(remove_cmd, /* name */
+be_local_closure(Tasmota_find_key_i, /* name */
+ be_nested_proto(
+ 10, /* nstack */
+ 3, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 5]) { /* constants */
+ /* K0 */ be_nested_str(string),
+ /* K1 */ be_nested_str(toupper),
+ /* K2 */ be_nested_str(keys),
+ /* K3 */ be_nested_str(_X3F),
+ /* K4 */ be_nested_str(stop_iteration),
+ }),
+ &be_const_str_find_key_i,
+ &be_const_str_solidified,
+ ( &(const binstruction[30]) { /* code */
+ 0xA40E0000, // 0000 IMPORT R3 K0
+ 0x8C100701, // 0001 GETMET R4 R3 K1
+ 0x5C180400, // 0002 MOVE R6 R2
+ 0x7C100400, // 0003 CALL R4 2
+ 0x6014000F, // 0004 GETGBL R5 G15
+ 0x5C180200, // 0005 MOVE R6 R1
+ 0x601C0013, // 0006 GETGBL R7 G19
+ 0x7C140400, // 0007 CALL R5 2
+ 0x78160013, // 0008 JMPF R5 #001D
+ 0x60140010, // 0009 GETGBL R5 G16
+ 0x8C180302, // 000A GETMET R6 R1 K2
+ 0x7C180200, // 000B CALL R6 1
+ 0x7C140200, // 000C CALL R5 1
+ 0xA802000B, // 000D EXBLK 0 #001A
+ 0x5C180A00, // 000E MOVE R6 R5
+ 0x7C180000, // 000F CALL R6 0
+ 0x8C1C0701, // 0010 GETMET R7 R3 K1
+ 0x5C240C00, // 0011 MOVE R9 R6
+ 0x7C1C0400, // 0012 CALL R7 2
+ 0x1C1C0E04, // 0013 EQ R7 R7 R4
+ 0x741E0001, // 0014 JMPT R7 #0017
+ 0x1C1C0503, // 0015 EQ R7 R2 K3
+ 0x781E0001, // 0016 JMPF R7 #0019
+ 0xA8040001, // 0017 EXBLK 1 1
+ 0x80040C00, // 0018 RET 1 R6
+ 0x7001FFF3, // 0019 JMP #000E
+ 0x58140004, // 001A LDCONST R5 K4
+ 0xAC140200, // 001B CATCH R5 1 0
+ 0xB0080000, // 001C RAISE 2 R0 R0
+ 0x80000000, // 001D RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: wire_scan
+********************************************************************/
+be_local_closure(Tasmota_wire_scan, /* name */
+ be_nested_proto(
+ 6, /* nstack */
+ 3, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 5]) { /* constants */
+ /* K0 */ be_nested_str(i2c_enabled),
+ /* K1 */ be_nested_str(wire1),
+ /* K2 */ be_nested_str(enabled),
+ /* K3 */ be_nested_str(detect),
+ /* K4 */ be_nested_str(wire2),
+ }),
+ &be_const_str_wire_scan,
+ &be_const_str_solidified,
+ ( &(const binstruction[33]) { /* code */
+ 0x4C0C0000, // 0000 LDNIL R3
+ 0x200C0403, // 0001 NE R3 R2 R3
+ 0x780E0005, // 0002 JMPF R3 #0009
+ 0x8C0C0100, // 0003 GETMET R3 R0 K0
+ 0x5C140400, // 0004 MOVE R5 R2
+ 0x7C0C0400, // 0005 CALL R3 2
+ 0x740E0001, // 0006 JMPT R3 #0009
+ 0x4C0C0000, // 0007 LDNIL R3
+ 0x80040600, // 0008 RET 1 R3
+ 0x880C0101, // 0009 GETMBR R3 R0 K1
+ 0x8C0C0702, // 000A GETMET R3 R3 K2
+ 0x7C0C0200, // 000B CALL R3 1
+ 0x780E0006, // 000C JMPF R3 #0014
+ 0x880C0101, // 000D GETMBR R3 R0 K1
+ 0x8C0C0703, // 000E GETMET R3 R3 K3
+ 0x5C140200, // 000F MOVE R5 R1
+ 0x7C0C0400, // 0010 CALL R3 2
+ 0x780E0001, // 0011 JMPF R3 #0014
+ 0x880C0101, // 0012 GETMBR R3 R0 K1
+ 0x80040600, // 0013 RET 1 R3
+ 0x880C0104, // 0014 GETMBR R3 R0 K4
+ 0x8C0C0702, // 0015 GETMET R3 R3 K2
+ 0x7C0C0200, // 0016 CALL R3 1
+ 0x780E0006, // 0017 JMPF R3 #001F
+ 0x880C0104, // 0018 GETMBR R3 R0 K4
+ 0x8C0C0703, // 0019 GETMET R3 R3 K3
+ 0x5C140200, // 001A MOVE R5 R1
+ 0x7C0C0400, // 001B CALL R3 2
+ 0x780E0001, // 001C JMPF R3 #001F
+ 0x880C0104, // 001D GETMBR R3 R0 K4
+ 0x80040600, // 001E RET 1 R3
+ 0x4C0C0000, // 001F LDNIL R3
+ 0x80040600, // 0020 RET 1 R3
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: init
+********************************************************************/
+be_local_closure(Tasmota_init, /* name */
+ be_nested_proto(
+ 7, /* nstack */
+ 1, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[15]) { /* constants */
+ /* K0 */ be_nested_str(global),
+ /* K1 */ be_nested_str(ctypes_bytes_dyn),
+ /* K2 */ be_nested_str(_global_addr),
+ /* K3 */ be_nested_str(_global_def),
+ /* K4 */ be_nested_str(introspect),
+ /* K5 */ be_nested_str(_settings_ptr),
+ /* K6 */ be_nested_str(get),
+ /* K7 */ be_const_int(0),
+ /* K8 */ be_nested_str(settings),
+ /* K9 */ be_nested_str(toptr),
+ /* K10 */ be_nested_str(_settings_def),
+ /* K11 */ be_nested_str(wd),
+ /* K12 */ be_nested_str(),
+ /* K13 */ be_nested_str(_debug_present),
+ /* K14 */ be_nested_str(debug),
+ }),
+ &be_const_str_init,
+ &be_const_str_solidified,
+ ( &(const binstruction[36]) { /* code */
+ 0xB8060200, // 0000 GETNGBL R1 K1
+ 0x88080102, // 0001 GETMBR R2 R0 K2
+ 0x880C0103, // 0002 GETMBR R3 R0 K3
+ 0x7C040400, // 0003 CALL R1 2
+ 0x90020001, // 0004 SETMBR R0 K0 R1
+ 0xA4060800, // 0005 IMPORT R1 K4
+ 0x60080015, // 0006 GETGBL R2 G21
+ 0x880C0105, // 0007 GETMBR R3 R0 K5
+ 0x54120003, // 0008 LDINT R4 4
+ 0x7C080400, // 0009 CALL R2 2
+ 0x8C080506, // 000A GETMET R2 R2 K6
+ 0x58100007, // 000B LDCONST R4 K7
+ 0x54160003, // 000C LDINT R5 4
+ 0x7C080600, // 000D CALL R2 3
+ 0x780A0006, // 000E JMPF R2 #0016
+ 0xB80E0200, // 000F GETNGBL R3 K1
+ 0x8C100309, // 0010 GETMET R4 R1 K9
+ 0x5C180400, // 0011 MOVE R6 R2
+ 0x7C100400, // 0012 CALL R4 2
+ 0x8814010A, // 0013 GETMBR R5 R0 K10
+ 0x7C0C0400, // 0014 CALL R3 2
+ 0x90021003, // 0015 SETMBR R0 K8 R3
+ 0x9002170C, // 0016 SETMBR R0 K11 K12
+ 0x500C0000, // 0017 LDBOOL R3 0 0
+ 0x90021A03, // 0018 SETMBR R0 K13 R3
+ 0xA8020004, // 0019 EXBLK 0 #001F
+ 0xA40E1C00, // 001A IMPORT R3 K14
+ 0x50100200, // 001B LDBOOL R4 1 0
+ 0x90021A04, // 001C SETMBR R0 K13 R4
+ 0xA8040001, // 001D EXBLK 1 1
+ 0x70020003, // 001E JMP #0023
+ 0xAC0C0000, // 001F CATCH R3 0 0
+ 0x70020000, // 0020 JMP #0022
+ 0x70020000, // 0021 JMP #0023
+ 0xB0080000, // 0022 RAISE 2 R0 R0
+ 0x80000000, // 0023 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: time_str
+********************************************************************/
+be_local_closure(Tasmota_time_str, /* name */
+ be_nested_proto(
+ 13, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[10]) { /* constants */
+ /* K0 */ be_nested_str(string),
+ /* K1 */ be_nested_str(time_dump),
+ /* K2 */ be_nested_str(format),
+ /* K3 */ be_nested_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d),
+ /* K4 */ be_nested_str(year),
+ /* K5 */ be_nested_str(month),
+ /* K6 */ be_nested_str(day),
+ /* K7 */ be_nested_str(hour),
+ /* K8 */ be_nested_str(min),
+ /* K9 */ be_nested_str(sec),
+ }),
+ &be_const_str_time_str,
+ &be_const_str_solidified,
+ ( &(const binstruction[14]) { /* code */
+ 0xA40A0000, // 0000 IMPORT R2 K0
+ 0x8C0C0101, // 0001 GETMET R3 R0 K1
+ 0x5C140200, // 0002 MOVE R5 R1
+ 0x7C0C0400, // 0003 CALL R3 2
+ 0x8C100502, // 0004 GETMET R4 R2 K2
+ 0x58180003, // 0005 LDCONST R6 K3
+ 0x941C0704, // 0006 GETIDX R7 R3 K4
+ 0x94200705, // 0007 GETIDX R8 R3 K5
+ 0x94240706, // 0008 GETIDX R9 R3 K6
+ 0x94280707, // 0009 GETIDX R10 R3 K7
+ 0x942C0708, // 000A GETIDX R11 R3 K8
+ 0x94300709, // 000B GETIDX R12 R3 K9
+ 0x7C101000, // 000C CALL R4 8
+ 0x80040800, // 000D RET 1 R4
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: remove_rule
+********************************************************************/
+be_local_closure(Tasmota_remove_rule, /* name */
+ be_nested_proto(
+ 6, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 5]) { /* constants */
+ /* K0 */ be_nested_str(_rules),
+ /* K1 */ be_const_int(0),
+ /* K2 */ be_nested_str(k),
+ /* K3 */ be_nested_str(remove),
+ /* K4 */ be_const_int(1),
+ }),
+ &be_const_str_remove_rule,
+ &be_const_str_solidified,
+ ( &(const binstruction[21]) { /* code */
+ 0x88080100, // 0000 GETMBR R2 R0 K0
+ 0x780A0011, // 0001 JMPF R2 #0014
+ 0x58080001, // 0002 LDCONST R2 K1
+ 0x600C000C, // 0003 GETGBL R3 G12
+ 0x88100100, // 0004 GETMBR R4 R0 K0
+ 0x7C0C0200, // 0005 CALL R3 1
+ 0x140C0403, // 0006 LT R3 R2 R3
+ 0x780E000B, // 0007 JMPF R3 #0014
+ 0x880C0100, // 0008 GETMBR R3 R0 K0
+ 0x940C0602, // 0009 GETIDX R3 R3 R2
+ 0x880C0702, // 000A GETMBR R3 R3 K2
+ 0x1C0C0601, // 000B EQ R3 R3 R1
+ 0x780E0004, // 000C JMPF R3 #0012
+ 0x880C0100, // 000D GETMBR R3 R0 K0
+ 0x8C0C0703, // 000E GETMET R3 R3 K3
+ 0x5C140400, // 000F MOVE R5 R2
+ 0x7C0C0400, // 0010 CALL R3 2
+ 0x70020000, // 0011 JMP #0013
+ 0x00080504, // 0012 ADD R2 R2 K4
+ 0x7001FFEE, // 0013 JMP #0003
+ 0x80000000, // 0014 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: load
+********************************************************************/
+be_local_closure(Tasmota_load, /* name */
+ be_nested_proto(
+ 21, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 1, /* has sup protos */
+ ( &(const struct bproto*[ 2]) {
+ be_nested_proto(
+ 6, /* nstack */
+ 1, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 4]) { /* constants */
+ /* K0 */ be_nested_str(sys),
+ /* K1 */ be_nested_str(path),
+ /* K2 */ be_nested_str(find),
+ /* K3 */ be_nested_str(push),
+ }),
+ &be_const_str_push_path,
+ &be_const_str_solidified,
+ ( &(const binstruction[13]) { /* code */
+ 0xA4060000, // 0000 IMPORT R1 K0
+ 0x8C080301, // 0001 GETMET R2 R1 K1
+ 0x7C080200, // 0002 CALL R2 1
+ 0x8C0C0502, // 0003 GETMET R3 R2 K2
+ 0x5C140000, // 0004 MOVE R5 R0
+ 0x7C0C0400, // 0005 CALL R3 2
+ 0x4C100000, // 0006 LDNIL R4
+ 0x1C0C0604, // 0007 EQ R3 R3 R4
+ 0x780E0002, // 0008 JMPF R3 #000C
+ 0x8C0C0503, // 0009 GETMET R3 R2 K3
+ 0x5C140000, // 000A MOVE R5 R0
+ 0x7C0C0400, // 000B CALL R3 2
+ 0x80000000, // 000C RET 0
+ })
+ ),
+ be_nested_proto(
+ 7, /* nstack */
+ 1, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 4]) { /* constants */
+ /* K0 */ be_nested_str(sys),
+ /* K1 */ be_nested_str(path),
+ /* K2 */ be_nested_str(find),
+ /* K3 */ be_nested_str(remove),
+ }),
+ &be_const_str_pop_path,
+ &be_const_str_solidified,
+ ( &(const binstruction[13]) { /* code */
+ 0xA4060000, // 0000 IMPORT R1 K0
+ 0x8C080301, // 0001 GETMET R2 R1 K1
+ 0x7C080200, // 0002 CALL R2 1
+ 0x8C0C0502, // 0003 GETMET R3 R2 K2
+ 0x5C140000, // 0004 MOVE R5 R0
+ 0x7C0C0400, // 0005 CALL R3 2
+ 0x4C100000, // 0006 LDNIL R4
+ 0x20100604, // 0007 NE R4 R3 R4
+ 0x78120002, // 0008 JMPF R4 #000C
+ 0x8C100503, // 0009 GETMET R4 R2 K3
+ 0x5C180600, // 000A MOVE R6 R3
+ 0x7C100400, // 000B CALL R4 2
+ 0x80000000, // 000C RET 0
+ })
+ ),
+ }),
+ 1, /* has constants */
+ ( &(const bvalue[21]) { /* constants */
+ /* K0 */ be_nested_str(string),
+ /* K1 */ be_nested_str(path),
+ /* K2 */ be_const_int(0),
+ /* K3 */ be_nested_str(_X2F),
+ /* K4 */ be_nested_str(split),
+ /* K5 */ be_nested_str(_X23),
+ /* K6 */ be_const_int(1),
+ /* K7 */ be_nested_str(find),
+ /* K8 */ be_nested_str(_X2E),
+ /* K9 */ be_nested_str(_X2Ebe),
+ /* K10 */ be_nested_str(_X2Ebec),
+ /* K11 */ be_nested_str(io_error),
+ /* K12 */ be_nested_str(file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27),
+ /* K13 */ be_nested_str(last_modified),
+ /* K14 */ be_nested_str(c),
+ /* K15 */ be_nested_str(wd),
+ /* K16 */ be_nested_str(),
+ /* K17 */ be_nested_str(file),
+ /* K18 */ be_nested_str(save),
+ /* K19 */ be_nested_str(format),
+ /* K20 */ be_nested_str(BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29),
+ }),
+ &be_const_str_load,
+ &be_const_str_solidified,
+ ( &(const binstruction[121]) { /* code */
+ 0x84080000, // 0000 CLOSURE R2 P0
+ 0x840C0001, // 0001 CLOSURE R3 P1
+ 0xA4120000, // 0002 IMPORT R4 K0
+ 0xA4160200, // 0003 IMPORT R5 K1
+ 0x6018000C, // 0004 GETGBL R6 G12
+ 0x5C1C0200, // 0005 MOVE R7 R1
+ 0x7C180200, // 0006 CALL R6 1
+ 0x1C180D02, // 0007 EQ R6 R6 K2
+ 0x781A0001, // 0008 JMPF R6 #000B
+ 0x50180000, // 0009 LDBOOL R6 0 0
+ 0x80040C00, // 000A RET 1 R6
+ 0x94180302, // 000B GETIDX R6 R1 K2
+ 0x20180D03, // 000C NE R6 R6 K3
+ 0x781A0000, // 000D JMPF R6 #000F
+ 0x00060601, // 000E ADD R1 K3 R1
+ 0x8C180904, // 000F GETMET R6 R4 K4
+ 0x5C200200, // 0010 MOVE R8 R1
+ 0x58240005, // 0011 LDCONST R9 K5
+ 0x7C180600, // 0012 CALL R6 3
+ 0x941C0D02, // 0013 GETIDX R7 R6 K2
+ 0x5421FFFE, // 0014 LDINT R8 -1
+ 0x94200C08, // 0015 GETIDX R8 R6 R8
+ 0x6024000C, // 0016 GETGBL R9 G12
+ 0x5C280C00, // 0017 MOVE R10 R6
+ 0x7C240200, // 0018 CALL R9 1
+ 0x24241306, // 0019 GT R9 R9 K6
+ 0x8C280907, // 001A GETMET R10 R4 K7
+ 0x5C301000, // 001B MOVE R12 R8
+ 0x58340008, // 001C LDCONST R13 K8
+ 0x7C280600, // 001D CALL R10 3
+ 0x14281502, // 001E LT R10 R10 K2
+ 0x782A0001, // 001F JMPF R10 #0022
+ 0x00040309, // 0020 ADD R1 R1 K9
+ 0x00201109, // 0021 ADD R8 R8 K9
+ 0x5429FFFC, // 0022 LDINT R10 -3
+ 0x542DFFFE, // 0023 LDINT R11 -1
+ 0x4028140B, // 0024 CONNECT R10 R10 R11
+ 0x9428100A, // 0025 GETIDX R10 R8 R10
+ 0x1C281509, // 0026 EQ R10 R10 K9
+ 0x542DFFFB, // 0027 LDINT R11 -4
+ 0x5431FFFE, // 0028 LDINT R12 -1
+ 0x402C160C, // 0029 CONNECT R11 R11 R12
+ 0x942C100B, // 002A GETIDX R11 R8 R11
+ 0x1C2C170A, // 002B EQ R11 R11 K10
+ 0x5C301400, // 002C MOVE R12 R10
+ 0x74320002, // 002D JMPT R12 #0031
+ 0x5C301600, // 002E MOVE R12 R11
+ 0x74320000, // 002F JMPT R12 #0031
+ 0xB006170C, // 0030 RAISE 1 K11 K12
+ 0x8C300B0D, // 0031 GETMET R12 R5 K13
+ 0x5C380E00, // 0032 MOVE R14 R7
+ 0x7C300400, // 0033 CALL R12 2
+ 0x782E0005, // 0034 JMPF R11 #003B
+ 0x4C340000, // 0035 LDNIL R13
+ 0x1C34180D, // 0036 EQ R13 R12 R13
+ 0x78360001, // 0037 JMPF R13 #003A
+ 0x50340000, // 0038 LDBOOL R13 0 0
+ 0x80041A00, // 0039 RET 1 R13
+ 0x70020013, // 003A JMP #004F
+ 0x8C340B0D, // 003B GETMET R13 R5 K13
+ 0x003C030E, // 003C ADD R15 R1 K14
+ 0x7C340400, // 003D CALL R13 2
+ 0x4C380000, // 003E LDNIL R14
+ 0x1C38180E, // 003F EQ R14 R12 R14
+ 0x783A0004, // 0040 JMPF R14 #0046
+ 0x4C380000, // 0041 LDNIL R14
+ 0x1C381A0E, // 0042 EQ R14 R13 R14
+ 0x783A0001, // 0043 JMPF R14 #0046
+ 0x50380000, // 0044 LDBOOL R14 0 0
+ 0x80041C00, // 0045 RET 1 R14
+ 0x4C380000, // 0046 LDNIL R14
+ 0x20381A0E, // 0047 NE R14 R13 R14
+ 0x783A0005, // 0048 JMPF R14 #004F
+ 0x4C380000, // 0049 LDNIL R14
+ 0x1C38180E, // 004A EQ R14 R12 R14
+ 0x743A0001, // 004B JMPT R14 #004E
+ 0x28381A0C, // 004C GE R14 R13 R12
+ 0x783A0000, // 004D JMPF R14 #004F
+ 0x502C0200, // 004E LDBOOL R11 1 0
+ 0x78260005, // 004F JMPF R9 #0056
+ 0x00340F05, // 0050 ADD R13 R7 K5
+ 0x90021E0D, // 0051 SETMBR R0 K15 R13
+ 0x5C340400, // 0052 MOVE R13 R2
+ 0x8838010F, // 0053 GETMBR R14 R0 K15
+ 0x7C340200, // 0054 CALL R13 1
+ 0x70020000, // 0055 JMP #0057
+ 0x90021F10, // 0056 SETMBR R0 K15 K16
+ 0x6034000D, // 0057 GETGBL R13 G13
+ 0x5C380200, // 0058 MOVE R14 R1
+ 0x583C0011, // 0059 LDCONST R15 K17
+ 0x7C340400, // 005A CALL R13 2
+ 0x5C381600, // 005B MOVE R14 R11
+ 0x743A0013, // 005C JMPT R14 #0071
+ 0x5C381200, // 005D MOVE R14 R9
+ 0x743A0011, // 005E JMPT R14 #0071
+ 0xA8020005, // 005F EXBLK 0 #0066
+ 0x8C380112, // 0060 GETMET R14 R0 K18
+ 0x0040030E, // 0061 ADD R16 R1 K14
+ 0x5C441A00, // 0062 MOVE R17 R13
+ 0x7C380600, // 0063 CALL R14 3
+ 0xA8040001, // 0064 EXBLK 1 1
+ 0x7002000A, // 0065 JMP #0071
+ 0xAC380001, // 0066 CATCH R14 0 1
+ 0x70020007, // 0067 JMP #0070
+ 0x603C0001, // 0068 GETGBL R15 G1
+ 0x8C400913, // 0069 GETMET R16 R4 K19
+ 0x58480014, // 006A LDCONST R18 K20
+ 0x004C030E, // 006B ADD R19 R1 K14
+ 0x5C501C00, // 006C MOVE R20 R14
+ 0x7C400800, // 006D CALL R16 4
+ 0x7C3C0200, // 006E CALL R15 1
+ 0x70020000, // 006F JMP #0071
+ 0xB0080000, // 0070 RAISE 2 R0 R0
+ 0x5C381A00, // 0071 MOVE R14 R13
+ 0x7C380000, // 0072 CALL R14 0
+ 0x78260002, // 0073 JMPF R9 #0077
+ 0x5C380600, // 0074 MOVE R14 R3
+ 0x003C0F05, // 0075 ADD R15 R7 K5
+ 0x7C380200, // 0076 CALL R14 1
+ 0x50380200, // 0077 LDBOOL R14 1 0
+ 0x80041C00, // 0078 RET 1 R14
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: chars_in_string
+********************************************************************/
+be_local_closure(Tasmota_chars_in_string, /* name */
+ be_nested_proto(
+ 10, /* nstack */
+ 4, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 2]) { /* constants */
+ /* K0 */ be_const_int(0),
+ /* K1 */ be_const_int(1),
+ }),
+ &be_const_str_chars_in_string,
+ &be_const_str_solidified,
+ ( &(const binstruction[31]) { /* code */
+ 0x780E0001, // 0000 JMPF R3 #0003
+ 0x50100200, // 0001 LDBOOL R4 1 0
+ 0x70020000, // 0002 JMP #0004
+ 0x50100000, // 0003 LDBOOL R4 0 0
+ 0x58140000, // 0004 LDCONST R5 K0
+ 0x6018000C, // 0005 GETGBL R6 G12
+ 0x5C1C0200, // 0006 MOVE R7 R1
+ 0x7C180200, // 0007 CALL R6 1
+ 0x14180A06, // 0008 LT R6 R5 R6
+ 0x781A0012, // 0009 JMPF R6 #001D
+ 0x50180000, // 000A LDBOOL R6 0 0
+ 0x581C0000, // 000B LDCONST R7 K0
+ 0x6020000C, // 000C GETGBL R8 G12
+ 0x5C240400, // 000D MOVE R9 R2
+ 0x7C200200, // 000E CALL R8 1
+ 0x14200E08, // 000F LT R8 R7 R8
+ 0x78220006, // 0010 JMPF R8 #0018
+ 0x94200205, // 0011 GETIDX R8 R1 R5
+ 0x94240407, // 0012 GETIDX R9 R2 R7
+ 0x1C201009, // 0013 EQ R8 R8 R9
+ 0x78220000, // 0014 JMPF R8 #0016
+ 0x50180200, // 0015 LDBOOL R6 1 0
+ 0x001C0F01, // 0016 ADD R7 R7 K1
+ 0x7001FFF3, // 0017 JMP #000C
+ 0x20200806, // 0018 NE R8 R4 R6
+ 0x78220000, // 0019 JMPF R8 #001B
+ 0x80040A00, // 001A RET 1 R5
+ 0x00140B01, // 001B ADD R5 R5 K1
+ 0x7001FFE7, // 001C JMP #0005
+ 0x5419FFFE, // 001D LDINT R6 -1
+ 0x80040C00, // 001E RET 1 R6
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: cmd
+********************************************************************/
+be_local_closure(Tasmota_cmd, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
@@ -1881,19 +1401,26 @@ be_local_closure(remove_cmd, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
- /* K0 */ be_nested_string("_ccmd", -2131545883, 5),
- /* K1 */ be_nested_string("remove", -611183107, 6),
+ /* K0 */ be_nested_str(cmd_res),
+ /* K1 */ be_nested_str(_cmd),
}),
- (be_nested_const_str("remove_cmd", -462651594, 10)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[ 7]) { /* code */
- 0x88080100, // 0000 GETMBR R2 R0 K0
- 0x780A0003, // 0001 JMPF R2 #0006
- 0x88080100, // 0002 GETMBR R2 R0 K0
- 0x8C080501, // 0003 GETMET R2 R2 K1
- 0x5C100200, // 0004 MOVE R4 R1
- 0x7C080400, // 0005 CALL R2 2
- 0x80000000, // 0006 RET 0
+ &be_const_str_cmd,
+ &be_const_str_solidified,
+ ( &(const binstruction[14]) { /* code */
+ 0x50080200, // 0000 LDBOOL R2 1 0
+ 0x90020002, // 0001 SETMBR R0 K0 R2
+ 0x8C080101, // 0002 GETMET R2 R0 K1
+ 0x5C100200, // 0003 MOVE R4 R1
+ 0x7C080400, // 0004 CALL R2 2
+ 0x4C080000, // 0005 LDNIL R2
+ 0x880C0100, // 0006 GETMBR R3 R0 K0
+ 0x50100200, // 0007 LDBOOL R4 1 0
+ 0x200C0604, // 0008 NE R3 R3 R4
+ 0x780E0000, // 0009 JMPF R3 #000B
+ 0x88080100, // 000A GETMBR R2 R0 K0
+ 0x4C0C0000, // 000B LDNIL R3
+ 0x90020003, // 000C SETMBR R0 K0 R3
+ 0x80040400, // 000D RET 1 R2
})
)
);
@@ -1901,64 +1428,233 @@ be_local_closure(remove_cmd, /* name */
/********************************************************************
-** Solidified function: exec_cmd
+** Solidified function: add_cmd
********************************************************************/
-be_local_closure(exec_cmd, /* name */
+be_local_closure(Tasmota_add_cmd, /* name */
be_nested_proto(
- 12, /* nstack */
- 4, /* argc */
+ 5, /* nstack */
+ 3, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
- ( &(const bvalue[ 5]) { /* constants */
- /* K0 */ be_nested_string("_ccmd", -2131545883, 5),
- /* K1 */ be_nested_string("json", 916562499, 4),
- /* K2 */ be_nested_string("load", -435725847, 4),
- /* K3 */ be_nested_string("find_key_i", 850136726, 10),
- /* K4 */ be_nested_string("resolvecmnd", 993361485, 11),
+ ( &(const bvalue[ 4]) { /* constants */
+ /* K0 */ be_nested_str(_ccmd),
+ /* K1 */ be_nested_str(function),
+ /* K2 */ be_nested_str(value_error),
+ /* K3 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function),
}),
- (be_nested_const_str("exec_cmd", 493567399, 8)),
- ((bstring*) &be_const_str_input),
- ( &(const binstruction[27]) { /* code */
- 0x88100100, // 0000 GETMBR R4 R0 K0
- 0x78120016, // 0001 JMPF R4 #0019
- 0xA4120200, // 0002 IMPORT R4 K1
- 0x8C140902, // 0003 GETMET R5 R4 K2
- 0x5C1C0600, // 0004 MOVE R7 R3
- 0x7C140400, // 0005 CALL R5 2
- 0x8C180103, // 0006 GETMET R6 R0 K3
- 0x88200100, // 0007 GETMBR R8 R0 K0
- 0x5C240200, // 0008 MOVE R9 R1
- 0x7C180600, // 0009 CALL R6 3
- 0x4C1C0000, // 000A LDNIL R7
- 0x201C0C07, // 000B NE R7 R6 R7
- 0x781E000B, // 000C JMPF R7 #0019
- 0x8C1C0104, // 000D GETMET R7 R0 K4
- 0x5C240C00, // 000E MOVE R9 R6
- 0x7C1C0400, // 000F CALL R7 2
- 0x881C0100, // 0010 GETMBR R7 R0 K0
- 0x941C0E06, // 0011 GETIDX R7 R7 R6
- 0x5C200C00, // 0012 MOVE R8 R6
- 0x5C240400, // 0013 MOVE R9 R2
- 0x5C280600, // 0014 MOVE R10 R3
- 0x5C2C0A00, // 0015 MOVE R11 R5
- 0x7C1C0800, // 0016 CALL R7 4
- 0x501C0200, // 0017 LDBOOL R7 1 0
- 0x80040E00, // 0018 RET 1 R7
- 0x50100000, // 0019 LDBOOL R4 0 0
- 0x80040800, // 001A RET 1 R4
+ &be_const_str_add_cmd,
+ &be_const_str_solidified,
+ ( &(const binstruction[15]) { /* code */
+ 0x880C0100, // 0000 GETMBR R3 R0 K0
+ 0x740E0002, // 0001 JMPT R3 #0005
+ 0x600C0013, // 0002 GETGBL R3 G19
+ 0x7C0C0000, // 0003 CALL R3 0
+ 0x90020003, // 0004 SETMBR R0 K0 R3
+ 0x600C0004, // 0005 GETGBL R3 G4
+ 0x5C100400, // 0006 MOVE R4 R2
+ 0x7C0C0200, // 0007 CALL R3 1
+ 0x1C0C0701, // 0008 EQ R3 R3 K1
+ 0x780E0002, // 0009 JMPF R3 #000D
+ 0x880C0100, // 000A GETMBR R3 R0 K0
+ 0x980C0202, // 000B SETIDX R3 R1 R2
+ 0x70020000, // 000C JMP #000E
+ 0xB0060503, // 000D RAISE 1 K2 K3
+ 0x80000000, // 000E RET 0
})
)
);
/*******************************************************************/
+
+/********************************************************************
+** Solidified function: add_rule
+********************************************************************/
+be_local_closure(Tasmota_add_rule, /* name */
+ be_nested_proto(
+ 9, /* nstack */
+ 3, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 6]) { /* constants */
+ /* K0 */ be_nested_str(_rules),
+ /* K1 */ be_nested_str(function),
+ /* K2 */ be_nested_str(push),
+ /* K3 */ be_nested_str(kv),
+ /* K4 */ be_nested_str(value_error),
+ /* K5 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function),
+ }),
+ &be_const_str_add_rule,
+ &be_const_str_solidified,
+ ( &(const binstruction[20]) { /* code */
+ 0x880C0100, // 0000 GETMBR R3 R0 K0
+ 0x740E0002, // 0001 JMPT R3 #0005
+ 0x600C0012, // 0002 GETGBL R3 G18
+ 0x7C0C0000, // 0003 CALL R3 0
+ 0x90020003, // 0004 SETMBR R0 K0 R3
+ 0x600C0004, // 0005 GETGBL R3 G4
+ 0x5C100400, // 0006 MOVE R4 R2
+ 0x7C0C0200, // 0007 CALL R3 1
+ 0x1C0C0701, // 0008 EQ R3 R3 K1
+ 0x780E0007, // 0009 JMPF R3 #0012
+ 0x880C0100, // 000A GETMBR R3 R0 K0
+ 0x8C0C0702, // 000B GETMET R3 R3 K2
+ 0x8C140103, // 000C GETMET R5 R0 K3
+ 0x5C1C0200, // 000D MOVE R7 R1
+ 0x5C200400, // 000E MOVE R8 R2
+ 0x7C140600, // 000F CALL R5 3
+ 0x7C0C0400, // 0010 CALL R3 2
+ 0x70020000, // 0011 JMP #0013
+ 0xB0060905, // 0012 RAISE 1 K4 K5
+ 0x80000000, // 0013 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: exec_rules
+********************************************************************/
+be_local_closure(Tasmota_exec_rules, /* name */
+ be_nested_proto(
+ 12, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[12]) { /* constants */
+ /* K0 */ be_nested_str(_rules),
+ /* K1 */ be_nested_str(cmd_res),
+ /* K2 */ be_nested_str(json),
+ /* K3 */ be_nested_str(load),
+ /* K4 */ be_nested_str(log),
+ /* K5 */ be_nested_str(BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20),
+ /* K6 */ be_const_int(3),
+ /* K7 */ be_const_int(0),
+ /* K8 */ be_nested_str(try_rule),
+ /* K9 */ be_nested_str(k),
+ /* K10 */ be_nested_str(v),
+ /* K11 */ be_const_int(1),
+ }),
+ &be_const_str_exec_rules,
+ &be_const_str_solidified,
+ ( &(const binstruction[48]) { /* code */
+ 0x88080100, // 0000 GETMBR R2 R0 K0
+ 0x740A0003, // 0001 JMPT R2 #0006
+ 0x88080101, // 0002 GETMBR R2 R0 K1
+ 0x4C0C0000, // 0003 LDNIL R3
+ 0x20080403, // 0004 NE R2 R2 R3
+ 0x780A0027, // 0005 JMPF R2 #002E
+ 0xA40A0400, // 0006 IMPORT R2 K2
+ 0x8C0C0503, // 0007 GETMET R3 R2 K3
+ 0x5C140200, // 0008 MOVE R5 R1
+ 0x7C0C0400, // 0009 CALL R3 2
+ 0x50100000, // 000A LDBOOL R4 0 0
+ 0x4C140000, // 000B LDNIL R5
+ 0x1C140605, // 000C EQ R5 R3 R5
+ 0x78160004, // 000D JMPF R5 #0013
+ 0x8C140104, // 000E GETMET R5 R0 K4
+ 0x001E0A01, // 000F ADD R7 K5 R1
+ 0x58200006, // 0010 LDCONST R8 K6
+ 0x7C140600, // 0011 CALL R5 3
+ 0x5C0C0200, // 0012 MOVE R3 R1
+ 0x88140101, // 0013 GETMBR R5 R0 K1
+ 0x4C180000, // 0014 LDNIL R6
+ 0x20140A06, // 0015 NE R5 R5 R6
+ 0x78160000, // 0016 JMPF R5 #0018
+ 0x90020203, // 0017 SETMBR R0 K1 R3
+ 0x88140100, // 0018 GETMBR R5 R0 K0
+ 0x78160012, // 0019 JMPF R5 #002D
+ 0x58140007, // 001A LDCONST R5 K7
+ 0x6018000C, // 001B GETGBL R6 G12
+ 0x881C0100, // 001C GETMBR R7 R0 K0
+ 0x7C180200, // 001D CALL R6 1
+ 0x14180A06, // 001E LT R6 R5 R6
+ 0x781A000C, // 001F JMPF R6 #002D
+ 0x88180100, // 0020 GETMBR R6 R0 K0
+ 0x94180C05, // 0021 GETIDX R6 R6 R5
+ 0x8C1C0108, // 0022 GETMET R7 R0 K8
+ 0x5C240600, // 0023 MOVE R9 R3
+ 0x88280D09, // 0024 GETMBR R10 R6 K9
+ 0x882C0D0A, // 0025 GETMBR R11 R6 K10
+ 0x7C1C0800, // 0026 CALL R7 4
+ 0x741E0001, // 0027 JMPT R7 #002A
+ 0x74120000, // 0028 JMPT R4 #002A
+ 0x50100001, // 0029 LDBOOL R4 0 1
+ 0x50100200, // 002A LDBOOL R4 1 0
+ 0x00140B0B, // 002B ADD R5 R5 K11
+ 0x7001FFED, // 002C JMP #001B
+ 0x80040800, // 002D RET 1 R4
+ 0x50080000, // 002E LDBOOL R2 0 0
+ 0x80040400, // 002F RET 1 R2
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: cb_dispatch
+********************************************************************/
+be_local_closure(Tasmota_cb_dispatch, /* name */
+ be_nested_proto(
+ 12, /* nstack */
+ 6, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 3]) { /* constants */
+ /* K0 */ be_nested_str(_cb),
+ /* K1 */ be_const_int(0),
+ /* K2 */ be_nested_str(find),
+ }),
+ &be_const_str_cb_dispatch,
+ &be_const_str_solidified,
+ ( &(const binstruction[20]) { /* code */
+ 0x88180100, // 0000 GETMBR R6 R0 K0
+ 0x4C1C0000, // 0001 LDNIL R7
+ 0x1C180C07, // 0002 EQ R6 R6 R7
+ 0x781A0000, // 0003 JMPF R6 #0005
+ 0x80060200, // 0004 RET 1 K1
+ 0x88180100, // 0005 GETMBR R6 R0 K0
+ 0x8C180D02, // 0006 GETMET R6 R6 K2
+ 0x5C200200, // 0007 MOVE R8 R1
+ 0x7C180400, // 0008 CALL R6 2
+ 0x4C1C0000, // 0009 LDNIL R7
+ 0x201C0C07, // 000A NE R7 R6 R7
+ 0x781E0006, // 000B JMPF R7 #0013
+ 0x5C1C0C00, // 000C MOVE R7 R6
+ 0x5C200400, // 000D MOVE R8 R2
+ 0x5C240600, // 000E MOVE R9 R3
+ 0x5C280800, // 000F MOVE R10 R4
+ 0x5C2C0A00, // 0010 MOVE R11 R5
+ 0x7C1C0800, // 0011 CALL R7 4
+ 0x80040E00, // 0012 RET 1 R7
+ 0x80060200, // 0013 RET 1 K1
+ })
+ )
+);
+/*******************************************************************/
+
+
/********************************************************************
** Solidified function: hs2rgb
********************************************************************/
-be_local_closure(hs2rgb, /* name */
+be_local_closure(Tasmota_hs2rgb, /* name */
be_nested_proto(
17, /* nstack */
3, /* argc */
@@ -1970,14 +1666,14 @@ be_local_closure(hs2rgb, /* name */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_const_int(0),
- /* K1 */ be_nested_string("tasmota", 424643812, 7),
- /* K2 */ be_nested_string("scale_uint", -1204156202, 10),
+ /* K1 */ be_nested_str(tasmota),
+ /* K2 */ be_nested_str(scale_uint),
/* K3 */ be_const_int(1),
/* K4 */ be_const_int(2),
/* K5 */ be_const_int(3),
}),
- (be_nested_const_str("hs2rgb", 1040816349, 6)),
- ((bstring*) &be_const_str_input),
+ &be_const_str_hs2rgb,
+ &be_const_str_solidified,
( &(const binstruction[68]) { /* code */
0x4C0C0000, // 0000 LDNIL R3
0x1C0C0403, // 0001 EQ R3 R2 R3
@@ -2052,6 +1748,312 @@ be_local_closure(hs2rgb, /* name */
);
/*******************************************************************/
+
+/********************************************************************
+** Solidified function: init
+********************************************************************/
+be_local_closure(KV_init, /* name */
+ be_nested_proto(
+ 3, /* nstack */
+ 3, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 2]) { /* constants */
+ /* K0 */ be_nested_str(k),
+ /* K1 */ be_nested_str(v),
+ }),
+ &be_const_str_init,
+ &be_const_str_solidified,
+ ( &(const binstruction[ 3]) { /* code */
+ 0x90020001, // 0000 SETMBR R0 K0 R1
+ 0x90020202, // 0001 SETMBR R0 K1 R2
+ 0x80000000, // 0002 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified class: KV
+********************************************************************/
+be_local_class(KV,
+ 2,
+ NULL,
+ be_nested_map(3,
+ ( (struct bmapnode*) &(const bmapnode[]) {
+ { be_const_key(k, 2), be_const_var(0) },
+ { be_const_key(v, -1), be_const_var(1) },
+ { be_const_key(init, -1), be_const_closure(KV_init_closure) },
+ })),
+ be_str_literal("KV")
+);
+
+/********************************************************************
+** Solidified function: kv
+********************************************************************/
+be_local_closure(Tasmota_kv, /* name */
+ be_nested_proto(
+ 7, /* nstack */
+ 3, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 1]) { /* constants */
+ /* K0 */ be_const_class(be_class_KV),
+ }),
+ &be_const_str_kv,
+ &be_const_str_solidified,
+ ( &(const binstruction[ 7]) { /* code */
+ 0x580C0000, // 0000 LDCONST R3 K0
+ 0xB4000000, // 0001 CLASS K0
+ 0x5C100600, // 0002 MOVE R4 R3
+ 0x5C140200, // 0003 MOVE R5 R1
+ 0x5C180400, // 0004 MOVE R6 R2
+ 0x7C100400, // 0005 CALL R4 2
+ 0x80040800, // 0006 RET 1 R4
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: remove_cmd
+********************************************************************/
+be_local_closure(Tasmota_remove_cmd, /* name */
+ be_nested_proto(
+ 5, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 2]) { /* constants */
+ /* K0 */ be_nested_str(_ccmd),
+ /* K1 */ be_nested_str(remove),
+ }),
+ &be_const_str_remove_cmd,
+ &be_const_str_solidified,
+ ( &(const binstruction[ 7]) { /* code */
+ 0x88080100, // 0000 GETMBR R2 R0 K0
+ 0x780A0003, // 0001 JMPF R2 #0006
+ 0x88080100, // 0002 GETMBR R2 R0 K0
+ 0x8C080501, // 0003 GETMET R2 R2 K1
+ 0x5C100200, // 0004 MOVE R4 R1
+ 0x7C080400, // 0005 CALL R2 2
+ 0x80000000, // 0006 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: set_timer
+********************************************************************/
+be_local_closure(Tasmota_set_timer, /* name */
+ be_nested_proto(
+ 10, /* nstack */
+ 4, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 4]) { /* constants */
+ /* K0 */ be_nested_str(_timers),
+ /* K1 */ be_nested_str(push),
+ /* K2 */ be_nested_str(Timer),
+ /* K3 */ be_nested_str(millis),
+ }),
+ &be_const_str_set_timer,
+ &be_const_str_solidified,
+ ( &(const binstruction[16]) { /* code */
+ 0x88100100, // 0000 GETMBR R4 R0 K0
+ 0x74120002, // 0001 JMPT R4 #0005
+ 0x60100012, // 0002 GETGBL R4 G18
+ 0x7C100000, // 0003 CALL R4 0
+ 0x90020004, // 0004 SETMBR R0 K0 R4
+ 0x88100100, // 0005 GETMBR R4 R0 K0
+ 0x8C100901, // 0006 GETMET R4 R4 K1
+ 0xB81A0400, // 0007 GETNGBL R6 K2
+ 0x8C1C0103, // 0008 GETMET R7 R0 K3
+ 0x5C240200, // 0009 MOVE R9 R1
+ 0x7C1C0400, // 000A CALL R7 2
+ 0x5C200400, // 000B MOVE R8 R2
+ 0x5C240600, // 000C MOVE R9 R3
+ 0x7C180600, // 000D CALL R6 3
+ 0x7C100400, // 000E CALL R4 2
+ 0x80000000, // 000F RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: remove_timer
+********************************************************************/
+be_local_closure(Tasmota_remove_timer, /* name */
+ be_nested_proto(
+ 6, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 7]) { /* constants */
+ /* K0 */ be_nested_str(tasmota),
+ /* K1 */ be_nested_str(_timers),
+ /* K2 */ be_const_int(0),
+ /* K3 */ be_nested_str(size),
+ /* K4 */ be_nested_str(id),
+ /* K5 */ be_nested_str(remove),
+ /* K6 */ be_const_int(1),
+ }),
+ &be_const_str_remove_timer,
+ &be_const_str_solidified,
+ ( &(const binstruction[23]) { /* code */
+ 0xB80A0000, // 0000 GETNGBL R2 K0
+ 0x88080501, // 0001 GETMBR R2 R2 K1
+ 0x780A0012, // 0002 JMPF R2 #0016
+ 0x58080002, // 0003 LDCONST R2 K2
+ 0xB80E0000, // 0004 GETNGBL R3 K0
+ 0x880C0701, // 0005 GETMBR R3 R3 K1
+ 0x8C0C0703, // 0006 GETMET R3 R3 K3
+ 0x7C0C0200, // 0007 CALL R3 1
+ 0x140C0403, // 0008 LT R3 R2 R3
+ 0x780E000B, // 0009 JMPF R3 #0016
+ 0x880C0101, // 000A GETMBR R3 R0 K1
+ 0x940C0602, // 000B GETIDX R3 R3 R2
+ 0x880C0704, // 000C GETMBR R3 R3 K4
+ 0x1C0C0601, // 000D EQ R3 R3 R1
+ 0x780E0004, // 000E JMPF R3 #0014
+ 0x880C0101, // 000F GETMBR R3 R0 K1
+ 0x8C0C0705, // 0010 GETMET R3 R3 K5
+ 0x5C140400, // 0011 MOVE R5 R2
+ 0x7C0C0400, // 0012 CALL R3 2
+ 0x70020000, // 0013 JMP #0015
+ 0x00080506, // 0014 ADD R2 R2 K6
+ 0x7001FFED, // 0015 JMP #0004
+ 0x80000000, // 0016 RET 0
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: exec_cmd
+********************************************************************/
+be_local_closure(Tasmota_exec_cmd, /* name */
+ be_nested_proto(
+ 12, /* nstack */
+ 4, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 5]) { /* constants */
+ /* K0 */ be_nested_str(_ccmd),
+ /* K1 */ be_nested_str(json),
+ /* K2 */ be_nested_str(load),
+ /* K3 */ be_nested_str(find_key_i),
+ /* K4 */ be_nested_str(resolvecmnd),
+ }),
+ &be_const_str_exec_cmd,
+ &be_const_str_solidified,
+ ( &(const binstruction[27]) { /* code */
+ 0x88100100, // 0000 GETMBR R4 R0 K0
+ 0x78120016, // 0001 JMPF R4 #0019
+ 0xA4120200, // 0002 IMPORT R4 K1
+ 0x8C140902, // 0003 GETMET R5 R4 K2
+ 0x5C1C0600, // 0004 MOVE R7 R3
+ 0x7C140400, // 0005 CALL R5 2
+ 0x8C180103, // 0006 GETMET R6 R0 K3
+ 0x88200100, // 0007 GETMBR R8 R0 K0
+ 0x5C240200, // 0008 MOVE R9 R1
+ 0x7C180600, // 0009 CALL R6 3
+ 0x4C1C0000, // 000A LDNIL R7
+ 0x201C0C07, // 000B NE R7 R6 R7
+ 0x781E000B, // 000C JMPF R7 #0019
+ 0x8C1C0104, // 000D GETMET R7 R0 K4
+ 0x5C240C00, // 000E MOVE R9 R6
+ 0x7C1C0400, // 000F CALL R7 2
+ 0x881C0100, // 0010 GETMBR R7 R0 K0
+ 0x941C0E06, // 0011 GETIDX R7 R7 R6
+ 0x5C200C00, // 0012 MOVE R8 R6
+ 0x5C240400, // 0013 MOVE R9 R2
+ 0x5C280600, // 0014 MOVE R10 R3
+ 0x5C2C0A00, // 0015 MOVE R11 R5
+ 0x7C1C0800, // 0016 CALL R7 4
+ 0x501C0200, // 0017 LDBOOL R7 1 0
+ 0x80040E00, // 0018 RET 1 R7
+ 0x50100000, // 0019 LDBOOL R4 0 0
+ 0x80040800, // 001A RET 1 R4
+ })
+ )
+);
+/*******************************************************************/
+
+
+/********************************************************************
+** Solidified function: get_light
+********************************************************************/
+be_local_closure(Tasmota_get_light, /* name */
+ be_nested_proto(
+ 6, /* nstack */
+ 2, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 3]) { /* constants */
+ /* K0 */ be_nested_str(tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29),
+ /* K1 */ be_nested_str(light),
+ /* K2 */ be_nested_str(get),
+ }),
+ &be_const_str_get_light,
+ &be_const_str_solidified,
+ ( &(const binstruction[16]) { /* code */
+ 0x60080001, // 0000 GETGBL R2 G1
+ 0x580C0000, // 0001 LDCONST R3 K0
+ 0x7C080200, // 0002 CALL R2 1
+ 0xA40A0200, // 0003 IMPORT R2 K1
+ 0x4C0C0000, // 0004 LDNIL R3
+ 0x200C0203, // 0005 NE R3 R1 R3
+ 0x780E0004, // 0006 JMPF R3 #000C
+ 0x8C0C0502, // 0007 GETMET R3 R2 K2
+ 0x5C140200, // 0008 MOVE R5 R1
+ 0x7C0C0400, // 0009 CALL R3 2
+ 0x80040600, // 000A RET 1 R3
+ 0x70020002, // 000B JMP #000F
+ 0x8C0C0502, // 000C GETMET R3 R2 K2
+ 0x7C0C0200, // 000D CALL R3 1
+ 0x80040600, // 000E RET 1 R3
+ 0x80000000, // 000F RET 0
+ })
+ )
+);
+/*******************************************************************/
+
#include "../generate/be_fixed_be_class_tasmota.h"
@@ -2083,8 +2085,8 @@ class be_class_tasmota (scope: global, name: Tasmota) {
_global_addr, comptr(&TasmotaGlobal)
_settings_ptr, comptr(&Settings)
- init, closure(init_closure)
- kv, closure(kv_closure)
+ init, closure(Tasmota_init_closure)
+ kv, closure(Tasmota_kv_closure)
get_free_heap, func(l_getFreeHeap)
arch, func(l_arch)
@@ -2126,35 +2128,35 @@ class be_class_tasmota (scope: global, name: Tasmota) {
i2c_enabled, func(l_i2cenabled)
- cmd, closure(cmd_closure)
- chars_in_string, closure(chars_in_string_closure)
- find_key_i, closure(find_key_i_closure)
- find_op, closure(find_op_closure)
- add_rule, closure(add_rule_closure)
- remove_rule, closure(remove_rule_closure)
- try_rule, closure(try_rule_closure)
- exec_rules, closure(exec_rules_closure)
- exec_tele, closure(exec_tele_closure)
- set_timer, closure(set_timer_closure)
- run_deferred, closure(run_deferred_closure)
- remove_timer, closure(remove_timer_closure)
- add_cmd, closure(add_cmd_closure)
- remove_cmd, closure(remove_cmd_closure)
- exec_cmd, closure(exec_cmd_closure)
- gc, closure(gc_closure)
- event, closure(event_closure)
- add_driver, closure(add_driver_closure)
- remove_driver, closure(remove_driver_closure)
- load, closure(load_closure)
- wire_scan, closure(wire_scan_closure)
- time_str, closure(time_str_closure)
+ cmd, closure(Tasmota_cmd_closure)
+ chars_in_string, closure(Tasmota_chars_in_string_closure)
+ find_key_i, closure(Tasmota_find_key_i_closure)
+ find_op, closure(Tasmota_find_op_closure)
+ add_rule, closure(Tasmota_add_rule_closure)
+ remove_rule, closure(Tasmota_remove_rule_closure)
+ try_rule, closure(Tasmota_try_rule_closure)
+ exec_rules, closure(Tasmota_exec_rules_closure)
+ exec_tele, closure(Tasmota_exec_tele_closure)
+ set_timer, closure(Tasmota_set_timer_closure)
+ run_deferred, closure(Tasmota_run_deferred_closure)
+ remove_timer, closure(Tasmota_remove_timer_closure)
+ add_cmd, closure(Tasmota_add_cmd_closure)
+ remove_cmd, closure(Tasmota_remove_cmd_closure)
+ exec_cmd, closure(Tasmota_exec_cmd_closure)
+ gc, closure(Tasmota_gc_closure)
+ event, closure(Tasmota_event_closure)
+ add_driver, closure(Tasmota_add_driver_closure)
+ remove_driver, closure(Tasmota_remove_driver_closure)
+ load, closure(Tasmota_load_closure)
+ wire_scan, closure(Tasmota_wire_scan_closure)
+ time_str, closure(Tasmota_time_str_closure)
- hs2rgb, closure(hs2rgb_closure)
+ hs2rgb, closure(Tasmota_hs2rgb_closure)
- cb_dispatch, closure(cb_dispatch_closure)
- gen_cb, closure(gen_cb_closure)
+ cb_dispatch, closure(Tasmota_cb_dispatch_closure)
+ gen_cb, closure(Tasmota_gen_cb_closure)
- get_light, closure(get_light_closure)
- set_light, closure(set_light_closure)
+ get_light, closure(Tasmota_get_light_closure)
+ set_light, closure(Tasmota_set_light_closure)
}
@const_object_info_end */
diff --git a/lib/libesp32/Berry/default/be_timer_class.c b/lib/libesp32/Berry/default/be_timer_class.c
index 2646fd6b2..6664e408e 100644
--- a/lib/libesp32/Berry/default/be_timer_class.c
+++ b/lib/libesp32/Berry/default/be_timer_class.c
@@ -8,7 +8,7 @@
/********************************************************************
** Solidified function: tostring
********************************************************************/
-be_local_closure(tostring, /* name */
+be_local_closure(Timer_tostring, /* name */
be_nested_proto(
10, /* nstack */
1, /* argc */
@@ -19,35 +19,35 @@ be_local_closure(tostring, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
- /* K0 */ be_nested_string("string", 398550328, 6),
- /* K1 */ be_nested_string("format", -1180859054, 6),
- /* K2 */ be_nested_string("", 3546571739u, 0, 11, &be_const_str_autorun);
+be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, &be_const_str_id);
+be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, NULL);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str__get_cb);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_erase);
+be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 2052843416u, 0, 25, &be_const_str_cb_dispatch);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 452285201u, 0, 120, NULL);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "", 3546571739u, 0, 11, &be_const_str_autorun);
-be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, &be_const_str_id);
-be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, NULL);
-be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str__get_cb);
-be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_erase);
-be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 2052843416u, 0, 25, &be_const_str_area);
be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 452285201u, 0, 120, NULL);
-be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "", 3546571739u, 0, 11, &be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback);
+be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, &be_const_str_rule);
+be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_set_chg_current);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_find_op);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, NULL);
+be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 842307168u, 0, 77, &be_const_str_get_current_module_path);
+be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str_delay);
+be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20);
+be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, "", 4212500780u, 0, 82, &be_const_str_CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29);
+be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, "", 1926223891u, 0, 80, &be_const_str_CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29);
+be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_write);
+be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, &be_const_str_None);
+be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "Exception:
'%s'
%s
", 4252565082u, 0, 59, &be_const_str_classof);
+be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 2052843416u, 0, 25, &be_const_str_button_pressed);
be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 452285201u, 0, 120, NULL);
-be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "", 3546571739u, 0, 11, &be_const_str_atan);
+be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, NULL);
+be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_HTTP_POST);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_Wire);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_color);
+be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 842307168u, 0, 77, &be_const_str_set_power);
+be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str_bus);
+be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str_point);
+be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, "", 4212500780u, 0, 82, &be_const_str_get_warning_level);
+be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, "", 1926223891u, 0, 80, &be_const_str_get_vbus_current);
+be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_cb_event_closure);
+be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, NULL);
+be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "Exception:
'%s'
%s
", 4252565082u, 0, 59, &be_const_str_arg);
+be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 2052843416u, 0, 25, &be_const_str_area);
be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 452285201u, 0, 120, NULL);
-be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, " (This feature requires an internet connection)", 2719266486u, 0, 74, NULL);
-be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "Current configuration:
%s
", 4115655761u, 0, 46, &be_const_str_exec_tele);
-be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "", 1863865923u, 0, 16, NULL);
+be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_HTTP_POST);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_Wire);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_color);
+be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 842307168u, 0, 77, &be_const_str_set_power);
+be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str_bus);
+be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str_point);
+be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, "", 4212500780u, 0, 82, &be_const_str_get_warning_level);
+be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, "", 1926223891u, 0, 80, &be_const_str_get_vbus_current);
+be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_cb_event_closure);
+be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, NULL);
+be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "Exception:
'%s'
%s
", 4252565082u, 0, 59, &be_const_str_arg);
+be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 2052843416u, 0, 25, &be_const_str_area);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 452285201u, 0, 120, NULL);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, " (This feature requires an internet connection)", 2719266486u, 0, 74, &be_const_str_register_obj);
+be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "Current configuration:
%s
", 4115655761u, 0, 46, &be_const_str_get_cb_list);
+be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "", 4247924536u, 0, 19, &be_const_str_find_key_i);
+be_define_const_str(_X3D, "=", 940354920u, 0, 1, &be_const_str_listdir);
+be_define_const_str(_X3D_X3C_X3E_X21, "=<>!", 2664470277u, 0, 4, &be_const_str_shared_key);
+be_define_const_str(_X3D_X3D, "==", 2431966415u, 0, 2, &be_const_str_json_append);
+be_define_const_str(_X3E, ">", 990687777u, 0, 1, &be_const_str_battery_present);
+be_define_const_str(_X3E_X3D, ">=", 284975636u, 0, 2, &be_const_str_get_style_pad_right);
+be_define_const_str(_X3F, "?", 973910158u, 0, 1, &be_const_str_redirect);
+be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, &be_const_str_clear_to);
+be_define_const_str(AXP192, "AXP192", 757230128u, 0, 6, &be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29);
+be_define_const_str(Animate_X20pc_X20is_X20out_X20of_X20range, "Animate pc is out of range", 1854929421u, 0, 26, &be_const_str_detected_X20on_X20bus);
+be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_a);
+be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str_ip);
+be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, NULL);
+be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_remove_cmd);
+be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_SERIAL_7E1);
+be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_wire);
+be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, NULL);
+be_define_const_str(Auto_X2Dconfiguration, "Auto-configuration", 1665006109u, 0, 18, &be_const_str_Tasmota);
+be_define_const_str(BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, "BRY: ERROR, bad json: ", 2715135809u, 0, 22, &be_const_str_I2C_X3A);
+be_define_const_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "BRY: Exception> '%s' - %s", 2246990964u, 0, 25, NULL);
+be_define_const_str(BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29, "BRY: could not save compiled file %s (%s)", 736659787u, 0, 41, &be_const_str_bri);
+be_define_const_str(BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson, "BRY: failed to load _persist.json", 2991913445u, 0, 33, &be_const_str_target);
+be_define_const_str(BUTTON_CONFIGURATION, "BUTTON_CONFIGURATION", 70820856u, 0, 20, &be_const_str_SERIAL_5O1);
+be_define_const_str(CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting, "CFG: 'init.bat' done, restarting", 1569670677u, 0, 32, &be_const_str_delay);
+be_define_const_str(CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s, "CFG: Exception> '%s' - %s", 1228874553u, 0, 25, &be_const_str__p);
+be_define_const_str(CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29, "CFG: could not run %s (%s - %s)", 1428829580u, 0, 31, &be_const_str_arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj);
+be_define_const_str(CFG_X3A_X20downloading_X20_X27_X25s_X27, "CFG: downloading '%s'", 589480701u, 0, 21, &be_const_str_add_header);
+be_define_const_str(CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27, "CFG: exception '%s' - '%s'", 4095407913u, 0, 26, &be_const_str_Tele);
+be_define_const_str(CFG_X3A_X20loaded_X20_X20, "CFG: loaded ", 3710273538u, 0, 13, NULL);
+be_define_const_str(CFG_X3A_X20loaded_X20_X27_X25s_X27, "CFG: loaded '%s'", 1699028828u, 0, 16, &be_const_str_fromb64);
+be_define_const_str(CFG_X3A_X20loading_X20, "CFG: loading ", 4010361503u, 0, 13, &be_const_str_floor);
+be_define_const_str(CFG_X3A_X20loading_X20_X27_X25s_X27, "CFG: loading '%s'", 2285306097u, 0, 17, &be_const_str_Timer);
+be_define_const_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29, "CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371u, 0, 58, &be_const_str_content_stop);
+be_define_const_str(CFG_X3A_X20no_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found, "CFG: no '*.autoconf' file found", 127493957u, 0, 31, &be_const_str_byte);
+be_define_const_str(CFG_X3A_X20ran_X20_X20, "CFG: ran ", 3579570472u, 0, 10, &be_const_str_draw_line_dsc_init);
+be_define_const_str(CFG_X3A_X20removed_X20file_X20_X27_X25s_X27, "CFG: removed file '%s'", 2048602473u, 0, 22, &be_const_str_pixel_size);
+be_define_const_str(CFG_X3A_X20removing_X20autoconf_X20files, "CFG: removing autoconf files", 4014704970u, 0, 28, &be_const_str_issubclass);
+be_define_const_str(CFG_X3A_X20removing_X20first_X20time_X20marker, "CFG: removing first time marker", 2125556683u, 0, 31, NULL);
+be_define_const_str(CFG_X3A_X20return_code_X3D_X25i, "CFG: return_code=%i", 2059897320u, 0, 19, &be_const_str_get_option);
+be_define_const_str(CFG_X3A_X20running_X20, "CFG: running ", 2478334534u, 0, 13, &be_const_str_get_vbus_voltage);
+be_define_const_str(CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem, "CFG: skipping 'display.ini' because already present in file-system", 3965549264u, 0, 66, &be_const_str_create_custom_widget);
+be_define_const_str(COLOR_BLACK, "COLOR_BLACK", 264427940u, 0, 11, &be_const_str_SERIAL_6N2);
+be_define_const_str(COLOR_WHITE, "COLOR_WHITE", 2536871270u, 0, 11, &be_const_str_wd);
+be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str__filename);
+be_define_const_str(EVENT_DRAW_MAIN, "EVENT_DRAW_MAIN", 1955620614u, 0, 15, &be_const_str_from_to);
+be_define_const_str(EVENT_DRAW_PART_BEGIN, "EVENT_DRAW_PART_BEGIN", 3391865024u, 0, 21, NULL);
+be_define_const_str(EVENT_DRAW_PART_END, "EVENT_DRAW_PART_END", 3301625292u, 0, 19, &be_const_str_set_pixel_color);
+be_define_const_str(False, "False", 2541049336u, 0, 5, &be_const_str_get_style_line_color);
+be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str_SERIAL_5N1);
+be_define_const_str(HTTP_GET, "HTTP_GET", 1722467738u, 0, 8, &be_const_str_dac_voltage);
+be_define_const_str(HTTP_POST, "HTTP_POST", 1999554144u, 0, 9, &be_const_str_widget_event_impl);
+be_define_const_str(I2C_X3A, "I2C:", 813483371u, 0, 4, &be_const_str_WS2812);
+be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_SERIAL_5O2);
+be_define_const_str(LVG_X3A_X20call_X20to_X20unsupported_X20callback, "LVG: call to unsupported callback", 504176819u, 0, 33, &be_const_str__end_transmission);
+be_define_const_str(Leds, "Leds", 2709245275u, 0, 4, &be_const_str_display_X2Eini);
+be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, NULL);
+be_define_const_str(None, "None", 810547195u, 0, 4, &be_const_str_day);
+be_define_const_str(OPTION_A, "OPTION_A", 1133299440u, 0, 8, &be_const_str_isnan);
+be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_is_first_time);
+be_define_const_str(PART_MAIN, "PART_MAIN", 2473491508u, 0, 9, &be_const_str__ccmd);
+be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_getbits);
+be_define_const_str(Parameter_X20error, "Parameter error", 3840042038u, 0, 15, NULL);
+be_define_const_str(RES_OK, "RES_OK", 1233817284u, 0, 6, &be_const_str_k);
+be_define_const_str(Restart_X201, "Restart 1", 3504455855u, 0, 9, &be_const_str_year);
+be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_SERIAL_8N1);
+be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_SERIAL_8N2);
+be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, NULL);
+be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str_read_sensors);
+be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_return);
+be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str__t);
+be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, NULL);
+be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_digital_write);
+be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str__X5D);
+be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str__settings_def);
+be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_couldn_X27t_X20not_X20initialize_X20noepixelbus);
+be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_deregister_obj);
+be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_call);
+be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_global);
+be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_encrypt);
+be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_alternate);
+be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, NULL);
+be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str_arch);
+be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str__available);
+be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, NULL);
+be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_imin);
+be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_gen_cb);
+be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_return_X20code_X3D_X25i);
+be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_tag);
+be_define_const_str(SK6812_GRBW, "SK6812_GRBW", 81157857u, 0, 11, &be_const_str_item);
+be_define_const_str(STATE_DEFAULT, "STATE_DEFAULT", 712406428u, 0, 13, &be_const_str_pop);
+be_define_const_str(TAP_X3A_X20found_X20Tasmota_X20App_X20_X27_X25s_X27, "TAP: found Tasmota App '%s'", 2643152398u, 0, 27, &be_const_str_closure);
+be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, &be_const_str_dump);
+be_define_const_str(Tele, "Tele", 1329980653u, 0, 4, &be_const_str_f);
+be_define_const_str(Timer, "Timer", 3948127682u, 0, 5, &be_const_str_check_privileged_access);
+be_define_const_str(True, "True", 3453902341u, 0, 4, &be_const_str_hs2rgb);
+be_define_const_str(Unknown_X20command, "Unknown command", 1830905432u, 0, 15, &be_const_str_map);
+be_define_const_str(WS2812, "WS2812", 3539741218u, 0, 6, NULL);
+be_define_const_str(WS2812_GRB, "WS2812_GRB", 1736405692u, 0, 10, NULL);
+be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, NULL);
+be_define_const_str(_X5B, "[", 3725336506u, 0, 1, &be_const_str_get_object_from_ptr);
+be_define_const_str(_X5D, "]", 3624670792u, 0, 1, &be_const_str_x1);
+be_define_const_str(_, "_", 3658226030u, 0, 1, &be_const_str_widget_struct_by_class);
+be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_asin);
+be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_public_key);
+be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_class_init_obj);
+be_define_const_str(_anonymous_, "_anonymous_", 1957281476u, 0, 11, &be_const_str_matrix);
+be_define_const_str(_archive, "_archive", 4004559404u, 0, 8, &be_const_str_isrunning);
+be_define_const_str(_available, "_available", 1306196581u, 0, 10, &be_const_str_setitem);
+be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, NULL);
+be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, &be_const_str_seti);
+be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_enabled);
+be_define_const_str(_class, "_class", 2732146350u, 0, 6, &be_const_str__dirty);
+be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_nan);
+be_define_const_str(_debug_present, "_debug_present", 4063411725u, 0, 14, NULL);
+be_define_const_str(_def, "_def", 1985022181u, 0, 4, NULL);
+be_define_const_str(_dirty, "_dirty", 283846766u, 0, 6, &be_const_str_content_start);
+be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str_del);
+be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, &be_const_str_math);
+be_define_const_str(_energy, "_energy", 535372070u, 0, 7, &be_const_str_reduce);
+be_define_const_str(_error, "_error", 1132109656u, 0, 6, NULL);
+be_define_const_str(_filename, "_filename", 1430813195u, 0, 9, NULL);
+be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_add_rule);
+be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_destructor_cb);
+be_define_const_str(_lvgl, "_lvgl", 2689219483u, 0, 5, NULL);
+be_define_const_str(_p, "_p", 1594591802u, 0, 2, &be_const_str_scan);
+be_define_const_str(_persist_X2Ejson, "_persist.json", 2008425138u, 0, 13, NULL);
+be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, NULL);
+be_define_const_str(_read, "_read", 346717030u, 0, 5, &be_const_str_calldepth);
+be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_set_x);
+be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, NULL);
+be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_offseta);
+be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_event_send);
+be_define_const_str(_t, "_t", 1527481326u, 0, 2, &be_const_str_resolvecmnd);
+be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_add);
+be_define_const_str(_write, "_write", 2215462825u, 0, 6, &be_const_str_read12);
+be_define_const_str(a, "a", 3826002220u, 0, 1, &be_const_str_get_string);
+be_define_const_str(abs, "abs", 709362235u, 0, 3, NULL);
+be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_def);
+be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_zero);
+be_define_const_str(add_anim, "add_anim", 3980662668u, 0, 8, &be_const_str_content_flush);
+be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, NULL);
+be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, &be_const_str_atan2);
+be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_set_percentage);
+be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_call_native);
+be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_create_matrix);
+be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_toptr);
+be_define_const_str(alternate, "alternate", 1140253277u, 0, 9, NULL);
+be_define_const_str(animate, "animate", 3885786800u, 0, 7, &be_const_str_function);
+be_define_const_str(animators, "animators", 279858213u, 0, 9, &be_const_str_traceback);
+be_define_const_str(arch, "arch", 2952804297u, 0, 4, NULL);
+be_define_const_str(area, "area", 2601460036u, 0, 4, &be_const_str_find);
+be_define_const_str(arg, "arg", 1047474471u, 0, 3, NULL);
+be_define_const_str(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj, "arg must be a subclass of lv_obj", 1641882079u, 0, 32, &be_const_str_as);
+be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_widget_height_def);
+be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, NULL);
+be_define_const_str(as, "as", 1579491469u, 67, 2, NULL);
+be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_get_current_module_name);
+be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_display);
+be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_get_temp);
+be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_publish);
+be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_json_fdump_list);
+be_define_const_str(atleast1, "atleast1", 1956331672u, 0, 8, &be_const_str_exp);
+be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_cb_do_nothing);
+be_define_const_str(autoexec, "autoexec", 3676861891u, 0, 8, &be_const_str_cmd_res);
+be_define_const_str(autorun, "autorun", 1447527407u, 0, 7, &be_const_str_log);
+be_define_const_str(available, "available", 1727918744u, 0, 9, NULL);
+be_define_const_str(b, "b", 3876335077u, 0, 1, &be_const_str_get_bri);
+be_define_const_str(back_forth, "back_forth", 2665042062u, 0, 10, &be_const_str_debug);
+be_define_const_str(base_class, "base_class", 1107737279u, 0, 10, &be_const_str_is_running);
+be_define_const_str(battery_present, "battery_present", 3588397058u, 0, 15, NULL);
+be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_char);
+be_define_const_str(bool, "bool", 3365180733u, 0, 4, &be_const_str_log10);
+be_define_const_str(break, "break", 3378807160u, 58, 5, NULL);
+be_define_const_str(bri, "bri", 2112284244u, 0, 3, &be_const_str_set_style_pad_right);
+be_define_const_str(bus, "bus", 1607822841u, 0, 3, &be_const_str_minute);
+be_define_const_str(button_pressed, "button_pressed", 1694209616u, 0, 14, &be_const_str_editable);
+be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_set_timeouts);
+be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_read);
+be_define_const_str(c, "c", 3859557458u, 0, 1, &be_const_str_state);
+be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_get_coords);
+be_define_const_str(call_native, "call_native", 1389147405u, 0, 11, &be_const_str_read8);
+be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str__X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D);
+be_define_const_str(can_show, "can_show", 960091187u, 0, 8, &be_const_str_month);
+be_define_const_str(cb, "cb", 1428787088u, 0, 2, &be_const_str_get_bat_voltage);
+be_define_const_str(cb_do_nothing, "cb_do_nothing", 1488730702u, 0, 13, &be_const_str_contains);
+be_define_const_str(cb_event_closure, "cb_event_closure", 3828267325u, 0, 16, &be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E);
+be_define_const_str(cb_obj, "cb_obj", 1195696482u, 0, 6, NULL);
+be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, NULL);
+be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_every_50ms);
+be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_draw_line_dsc);
+be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, &be_const_str_solidified);
+be_define_const_str(class, "class", 2872970239u, 57, 5, NULL);
+be_define_const_str(class_init_obj, "class_init_obj", 178410604u, 0, 14, NULL);
+be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL);
+be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_gamma);
+be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL);
+be_define_const_str(clear_first_time, "clear_first_time", 632769909u, 0, 16, &be_const_str_get_power);
+be_define_const_str(clear_to, "clear_to", 3528002130u, 0, 8, &be_const_str_tanh);
+be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_write_bit);
+be_define_const_str(closure, "closure", 1548407746u, 0, 7, &be_const_str_cmd);
+be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_get_switch);
+be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, NULL);
+be_define_const_str(code, "code", 4180765940u, 0, 4, &be_const_str_group_def);
+be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_members);
+be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_file);
+be_define_const_str(color, "color", 1031692888u, 0, 5, &be_const_str_get_width);
+be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_ctypes_bytes);
+be_define_const_str(compress, "compress", 2818084237u, 0, 8, &be_const_str_find_op);
+be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_widget_dtor_impl);
+be_define_const_str(connect, "connect", 2866859257u, 0, 7, &be_const_str_stop);
+be_define_const_str(connected, "connected", 1424938192u, 0, 9, &be_const_str_obj_event_base);
+be_define_const_str(connection_error, "connection_error", 1358926260u, 0, 16, &be_const_str_wifi);
+be_define_const_str(constructor_cb, "constructor_cb", 2489105297u, 0, 14, &be_const_str_round_start);
+be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_deinit);
+be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, &be_const_str_write);
+be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, NULL);
+be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, NULL);
+be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_is_dirty);
+be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, NULL);
+be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, &be_const_str_line_dsc);
+be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL);
+be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_rad);
+be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_start);
+be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_h);
+be_define_const_str(couldn_X27t_X20not_X20initialize_X20noepixelbus, "couldn't not initialize noepixelbus", 2536490812u, 0, 35, NULL);
+be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_web_add_console_button);
+be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_save);
+be_define_const_str(create_custom_widget, "create_custom_widget", 1140594778u, 0, 20, &be_const_str_quality);
+be_define_const_str(create_matrix, "create_matrix", 3528185923u, 0, 13, &be_const_str_y1);
+be_define_const_str(create_segment, "create_segment", 3863522719u, 0, 14, &be_const_str_open);
+be_define_const_str(ctor, "ctor", 375399343u, 0, 4, &be_const_str_push);
+be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, NULL);
+be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_reapply);
+be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_time_reached);
+be_define_const_str(day, "day", 3830391293u, 0, 3, &be_const_str_every_100ms);
+be_define_const_str(debug, "debug", 1483009432u, 0, 5, &be_const_str_exec_rules);
+be_define_const_str(decompress, "decompress", 2887031650u, 0, 10, NULL);
+be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, NULL);
+be_define_const_str(def, "def", 3310976652u, 55, 3, NULL);
+be_define_const_str(deg, "deg", 3327754271u, 0, 3, NULL);
+be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, NULL);
+be_define_const_str(del, "del", 3478752842u, 0, 3, NULL);
+be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_run_deferred);
+be_define_const_str(delete_all_configs, "delete_all_configs", 2382067578u, 0, 18, &be_const_str_wire1);
+be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_get_bat_charge_current);
+be_define_const_str(deregister_obj, "deregister_obj", 3909966993u, 0, 14, &be_const_str_get_alternate);
+be_define_const_str(destructor_cb, "destructor_cb", 1930283190u, 0, 13, &be_const_str_p2);
+be_define_const_str(detect, "detect", 8884370u, 0, 6, NULL);
+be_define_const_str(detected_X20on_X20bus, "detected on bus", 1432002650u, 0, 15, &be_const_str_run);
+be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, NULL);
+be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, &be_const_str_gamma8);
+be_define_const_str(dirty, "dirty", 2667581083u, 0, 5, &be_const_str_pop_path);
+be_define_const_str(display, "display", 1164572437u, 0, 7, &be_const_str_finish);
+be_define_const_str(display_X2Eini, "display.ini", 2646174001u, 0, 11, NULL);
+be_define_const_str(do, "do", 1646057492u, 65, 2, NULL);
+be_define_const_str(draw_arc, "draw_arc", 1828251676u, 0, 8, &be_const_str_hour);
+be_define_const_str(draw_line, "draw_line", 1634465686u, 0, 9, NULL);
+be_define_const_str(draw_line_dsc, "draw_line_dsc", 4220676203u, 0, 13, &be_const_str_widget_instance_size);
+be_define_const_str(draw_line_dsc_init, "draw_line_dsc_init", 3866693646u, 0, 18, NULL);
+be_define_const_str(due, "due", 3895530293u, 0, 3, NULL);
+be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL);
+be_define_const_str(duration, "duration", 799079693u, 0, 8, &be_const_str_rotate);
+be_define_const_str(editable, "editable", 60532369u, 0, 8, &be_const_str_kv);
+be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL);
+be_define_const_str(else, "else", 3183434736u, 52, 4, NULL);
+be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_write_file);
+be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, &be_const_str_static);
+be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_try);
+be_define_const_str(energy_struct, "energy_struct", 1655792843u, 0, 13, NULL);
+be_define_const_str(engine, "engine", 3993360443u, 0, 6, &be_const_str_widget_destructor);
+be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_tolower);
+be_define_const_str(escape, "escape", 2652972038u, 0, 6, &be_const_str_hex);
+be_define_const_str(eth, "eth", 2191266556u, 0, 3, NULL);
+be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_set_width);
+be_define_const_str(event_cb, "event_cb", 3128698017u, 0, 8, &be_const_str_height_def);
+be_define_const_str(event_send, "event_send", 598925582u, 0, 10, &be_const_str_gamma10);
+be_define_const_str(every_100ms, "every_100ms", 1546407804u, 0, 11, NULL);
+be_define_const_str(every_50ms, "every_50ms", 2383884008u, 0, 10, &be_const_str_page_autoconf_mgr);
+be_define_const_str(every_second, "every_second", 2075451465u, 0, 12, &be_const_str_list);
+be_define_const_str(except, "except", 950914032u, 69, 6, NULL);
+be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str_light);
+be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_reverse);
+be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, &be_const_str_has);
+be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_setbits);
+be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_tasmota);
+be_define_const_str(f, "f", 3809224601u, 0, 1, &be_const_str_input);
+be_define_const_str(false, "false", 184981848u, 62, 5, NULL);
+be_define_const_str(file, "file", 2867484483u, 0, 4, NULL);
+be_define_const_str(file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27, "file extension is not '.be' or '.bec'", 3095719639u, 0, 37, NULL);
+be_define_const_str(files, "files", 1055342736u, 0, 5, &be_const_str_param);
+be_define_const_str(find, "find", 3186656602u, 0, 4, NULL);
+be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, &be_const_str_pin);
+be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL);
+be_define_const_str(finish, "finish", 1494643858u, 0, 6, NULL);
+be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_local);
+be_define_const_str(flush, "flush", 3002334877u, 0, 5, NULL);
+be_define_const_str(for, "for", 2901640080u, 54, 3, NULL);
+be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_memory);
+be_define_const_str(from_to, "from_to", 21625507u, 0, 7, &be_const_str_load);
+be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, NULL);
+be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, NULL);
+be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_get_input_power_status);
+be_define_const_str(function, "function", 2664841801u, 0, 8, &be_const_str_tostring);
+be_define_const_str(gamma, "gamma", 3492353034u, 0, 5, &be_const_str_widget_struct_default);
+be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, &be_const_str_get_free_heap);
+be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_resp_cmnd);
+be_define_const_str(gc, "gc", 1042313471u, 0, 2, NULL);
+be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, NULL);
+be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str__X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_XB0C_X7Be_X7D);
+be_define_const_str(get_alternate, "get_alternate", 1450148894u, 0, 13, NULL);
+be_define_const_str(get_aps_voltage, "get_aps_voltage", 2293036435u, 0, 15, NULL);
+be_define_const_str(get_bat_charge_current, "get_bat_charge_current", 1385293050u, 0, 22, &be_const_str_pi);
+be_define_const_str(get_bat_current, "get_bat_current", 1912106073u, 0, 15, NULL);
+be_define_const_str(get_bat_power, "get_bat_power", 3067374853u, 0, 13, &be_const_str_ins_time);
+be_define_const_str(get_bat_voltage, "get_bat_voltage", 706676538u, 0, 15, NULL);
+be_define_const_str(get_battery_chargin_status, "get_battery_chargin_status", 2233241571u, 0, 26, NULL);
+be_define_const_str(get_bri, "get_bri", 2041809895u, 0, 7, &be_const_str_page_autoconf_ctl);
+be_define_const_str(get_cb_list, "get_cb_list", 1605319182u, 0, 11, &be_const_str_offset);
+be_define_const_str(get_coords, "get_coords", 1044089006u, 0, 10, &be_const_str_upper);
+be_define_const_str(get_current_module_name, "get_current_module_name", 2379270740u, 0, 23, NULL);
+be_define_const_str(get_current_module_path, "get_current_module_path", 3206673408u, 0, 23, NULL);
+be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, &be_const_str_no_X20GPIO_X20specified_X20for_X20neopixelbus);
+be_define_const_str(get_height, "get_height", 3571755523u, 0, 10, &be_const_str_obj_class_create_obj);
+be_define_const_str(get_input_power_status, "get_input_power_status", 4102829177u, 0, 22, &be_const_str_get_style_bg_color);
+be_define_const_str(get_light, "get_light", 381930476u, 0, 9, &be_const_str_unknown_X20instruction);
+be_define_const_str(get_object_from_ptr, "get_object_from_ptr", 2345019201u, 0, 19, NULL);
+be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, NULL);
+be_define_const_str(get_percentage, "get_percentage", 2880483992u, 0, 14, NULL);
+be_define_const_str(get_pixel_color, "get_pixel_color", 337490048u, 0, 15, NULL);
+be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, NULL);
+be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, &be_const_str_tomap);
+be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_remove_driver);
+be_define_const_str(get_style_bg_color, "get_style_bg_color", 964794381u, 0, 18, &be_const_str_number);
+be_define_const_str(get_style_line_color, "get_style_line_color", 805371932u, 0, 20, &be_const_str_ins_ramp);
+be_define_const_str(get_style_pad_right, "get_style_pad_right", 3150287466u, 0, 19, NULL);
+be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, &be_const_str_set_y);
+be_define_const_str(get_tasmota, "get_tasmota", 334356779u, 0, 11, &be_const_str_imax);
+be_define_const_str(get_temp, "get_temp", 3370919486u, 0, 8, NULL);
+be_define_const_str(get_vbus_current, "get_vbus_current", 1205347942u, 0, 16, &be_const_str_tele);
+be_define_const_str(get_vbus_voltage, "get_vbus_voltage", 2398210401u, 0, 16, &be_const_str_toupper);
+be_define_const_str(get_warning_level, "get_warning_level", 1737834441u, 0, 17, NULL);
+be_define_const_str(get_width, "get_width", 3293417300u, 0, 9, &be_const_str_readbytes);
+be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_has_arg);
+be_define_const_str(geti, "geti", 2381006490u, 0, 4, NULL);
+be_define_const_str(global, "global", 503252654u, 0, 6, NULL);
+be_define_const_str(gpio, "gpio", 2638155258u, 0, 4, &be_const_str_strptime);
+be_define_const_str(group_def, "group_def", 1524213328u, 0, 9, NULL);
+be_define_const_str(h, "h", 3977000791u, 0, 1, &be_const_str_init);
+be_define_const_str(has, "has", 3988721635u, 0, 3, &be_const_str_pow);
+be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, &be_const_str__X7D);
+be_define_const_str(height_def, "height_def", 2348238838u, 0, 10, &be_const_str_set_height);
+be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson);
+be_define_const_str(hour, "hour", 3053661199u, 0, 4, &be_const_str_pixel_count);
+be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, &be_const_str_path);
+be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", 2743526309u, 0, 70, &be_const_str_pc_abs);
+be_define_const_str(https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson, "https://raw.githubusercontent.com/tasmota/autoconf/main/%s_manifest.json", 3657552045u, 0, 72, &be_const_str_int);
+be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, NULL);
+be_define_const_str(id, "id", 926444256u, 0, 2, &be_const_str_x);
+be_define_const_str(if, "if", 959999494u, 50, 2, NULL);
+be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_resize);
+be_define_const_str(imin, "imin", 2714127864u, 0, 4, NULL);
+be_define_const_str(import, "import", 288002260u, 66, 6, NULL);
+be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_pc_rel);
+be_define_const_str(init_draw_line_dsc, "init_draw_line_dsc", 2507936040u, 0, 18, NULL);
+be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_reset);
+be_define_const_str(ins_goto, "ins_goto", 1342843963u, 0, 8, NULL);
+be_define_const_str(ins_ramp, "ins_ramp", 1068049360u, 0, 8, &be_const_str_stop_iteration);
+be_define_const_str(ins_time, "ins_time", 2980245553u, 0, 8, NULL);
+be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_lvgl_event_dispatch);
+be_define_const_str(instance, "instance", 193386898u, 0, 8, &be_const_str_set_matrix_pixel_color);
+be_define_const_str(instance_size, "instance_size", 4280269518u, 0, 13, NULL);
+be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_set_style_text_font);
+be_define_const_str(internal_error, "internal_error", 2519158169u, 0, 14, &be_const_str_width_def);
+be_define_const_str(introspect, "introspect", 164638290u, 0, 10, &be_const_str_preinit);
+be_define_const_str(invalidate, "invalidate", 2649734928u, 0, 10, NULL);
+be_define_const_str(io_error, "io_error", 1970281036u, 0, 8, NULL);
+be_define_const_str(ip, "ip", 1261996636u, 0, 2, NULL);
+be_define_const_str(is_dirty, "is_dirty", 418034110u, 0, 8, &be_const_str_on);
+be_define_const_str(is_first_time, "is_first_time", 275242384u, 0, 13, &be_const_str_persist);
+be_define_const_str(is_running, "is_running", 2226847261u, 0, 10, &be_const_str__X7B_X7D);
+be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_last_modified);
+be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_iter);
+be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, NULL);
+be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_setmember);
+be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_json_fdump_any);
+be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_name);
+be_define_const_str(json, "json", 916562499u, 0, 4, NULL);
+be_define_const_str(json_append, "json_append", 3002019284u, 0, 11, &be_const_str_import);
+be_define_const_str(json_fdump, "json_fdump", 1694216580u, 0, 10, NULL);
+be_define_const_str(json_fdump_any, "json_fdump_any", 3348629385u, 0, 14, NULL);
+be_define_const_str(json_fdump_list, "json_fdump_list", 3903879853u, 0, 15, &be_const_str_millis);
+be_define_const_str(json_fdump_map, "json_fdump_map", 4091954653u, 0, 14, &be_const_str_save_before_restart);
+be_define_const_str(k, "k", 3993778410u, 0, 1, &be_const_str_keys);
+be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_min);
+be_define_const_str(kv, "kv", 1497177492u, 0, 2, NULL);
+be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, NULL);
+be_define_const_str(leds, "leds", 558858555u, 0, 4, &be_const_str_elif);
+be_define_const_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032, "length in bits must be between 0 and 32", 2584509128u, 0, 39, &be_const_str_false);
+be_define_const_str(light, "light", 3801947695u, 0, 5, NULL);
+be_define_const_str(line_dsc, "line_dsc", 4094490978u, 0, 8, &be_const_str_print);
+be_define_const_str(list, "list", 217798785u, 0, 4, NULL);
+be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, NULL);
+be_define_const_str(load, "load", 3859241449u, 0, 4, NULL);
+be_define_const_str(load_templates, "load_templates", 3513870133u, 0, 14, &be_const_str_set_bri);
+be_define_const_str(local, "local", 2621662984u, 0, 5, NULL);
+be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function);
+be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_web_add_handler);
+be_define_const_str(loop, "loop", 3723446379u, 0, 4, &be_const_str_continue);
+be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_push_path);
+be_define_const_str(lv, "lv", 1529997255u, 0, 2, NULL);
+be_define_const_str(lv_event, "lv_event", 2434089968u, 0, 8, &be_const_str_set_timer);
+be_define_const_str(lv_event_cb, "lv_event_cb", 2480731016u, 0, 11, &be_const_str_try_rule);
+be_define_const_str(lv_obj, "lv_obj", 4257833149u, 0, 6, NULL);
+be_define_const_str(lv_obj_class, "lv_obj_class", 4039656294u, 0, 12, NULL);
+be_define_const_str(lvgl_event_dispatch, "lvgl_event_dispatch", 2104396622u, 0, 19, &be_const_str_rule);
+be_define_const_str(map, "map", 3751997361u, 0, 3, NULL);
+be_define_const_str(math, "math", 4001929615u, 0, 4, &be_const_str_widget_event_cb);
+be_define_const_str(matrix, "matrix", 365099244u, 0, 6, &be_const_str_pixels_buffer);
+be_define_const_str(member, "member", 719708611u, 0, 6, &be_const_str_web_add_management_button);
+be_define_const_str(members, "members", 937576464u, 0, 7, &be_const_str_remove_rule);
+be_define_const_str(memory, "memory", 2229924270u, 0, 6, NULL);
+be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_module);
+be_define_const_str(min, "min", 3381609815u, 0, 3, NULL);
+be_define_const_str(minute, "minute", 954666857u, 0, 6, NULL);
+be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_setrange);
+be_define_const_str(month, "month", 3598321157u, 0, 5, &be_const_str_web_send);
+be_define_const_str(name, "name", 2369371622u, 0, 4, NULL);
+be_define_const_str(nan, "nan", 797905850u, 0, 3, &be_const_str_size);
+be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL);
+be_define_const_str(no_X20GPIO_X20specified_X20for_X20neopixelbus, "no GPIO specified for neopixelbus", 42078528u, 0, 33, NULL);
+be_define_const_str(null_cb, "null_cb", 2333536460u, 0, 7, NULL);
+be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_range);
+be_define_const_str(obj_class_create_obj, "obj_class_create_obj", 3304390632u, 0, 20, NULL);
+be_define_const_str(obj_event_base, "obj_event_base", 1624064363u, 0, 14, NULL);
+be_define_const_str(offset, "offset", 348705738u, 0, 6, &be_const_str_web_add_button);
+be_define_const_str(offseta, "offseta", 1663383089u, 0, 7, NULL);
+be_define_const_str(on, "on", 1630810064u, 0, 2, &be_const_str_webclient);
+be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will cause a restart.\");'>", 232646018u, 0, 57, &be_const_str_wire2);
+be_define_const_str(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E, "onsubmit='return confirm(\"This will change the current configuration and cause a restart.\");'>", 3792412559u, 0, 94, &be_const_str_srand);
+be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_search);
+be_define_const_str(out_X20of_X20range, "out of range", 2236631477u, 0, 12, NULL);
+be_define_const_str(p1, "p1", 2689521274u, 0, 2, NULL);
+be_define_const_str(p2, "p2", 2672743655u, 0, 2, &be_const_str_set_alternate);
+be_define_const_str(page_autoconf_ctl, "page_autoconf_ctl", 2453381496u, 0, 17, NULL);
+be_define_const_str(page_autoconf_mgr, "page_autoconf_mgr", 3643937031u, 0, 17, &be_const_str_write8);
+be_define_const_str(param, "param", 1309554226u, 0, 5, &be_const_str_resp_cmnd_error);
+be_define_const_str(path, "path", 2223459638u, 0, 4, &be_const_str_real);
+be_define_const_str(pc, "pc", 1313756516u, 0, 2, &be_const_str_nil);
+be_define_const_str(pc_abs, "pc_abs", 920256495u, 0, 6, &be_const_str_set);
+be_define_const_str(pc_rel, "pc_rel", 991921176u, 0, 6, &be_const_str_web_add_config_button);
+be_define_const_str(percentage, "percentage", 2538831285u, 0, 10, &be_const_str_tcpclient);
+be_define_const_str(persist, "persist", 3917083779u, 0, 7, NULL);
+be_define_const_str(persist_X2E_p_X20is_X20not_X20a_X20map, "persist._p is not a map", 1176528732u, 0, 23, NULL);
+be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL);
+be_define_const_str(pin, "pin", 1866532500u, 0, 3, NULL);
+be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, &be_const_str_set_ldo_voltage);
+be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_set_auth);
+be_define_const_str(pixel_count, "pixel_count", 2439130743u, 0, 11, NULL);
+be_define_const_str(pixel_size, "pixel_size", 2209135785u, 0, 10, NULL);
+be_define_const_str(pixels_buffer, "pixels_buffer", 1229555807u, 0, 13, NULL);
+be_define_const_str(point, "point", 414084241u, 0, 5, NULL);
+be_define_const_str(pop, "pop", 1362321360u, 0, 3, &be_const_str_resp_cmnd_failed);
+be_define_const_str(pop_path, "pop_path", 2403243998u, 0, 8, NULL);
+be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_seg7_font);
+be_define_const_str(preinit, "preinit", 2722007100u, 0, 7, &be_const_str_widget_ctor_cb);
+be_define_const_str(print, "print", 372738696u, 0, 5, NULL);
+be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_read32);
+be_define_const_str(publish, "publish", 264247304u, 0, 7, NULL);
+be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_skip);
+be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_width);
+be_define_const_str(push_path, "push_path", 1155254157u, 0, 9, NULL);
+be_define_const_str(quality, "quality", 2597670950u, 0, 7, &be_const_str_else);
+be_define_const_str(r, "r", 4144776981u, 0, 1, &be_const_str_set_light);
+be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_set_ldo_enable);
+be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL);
+be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL);
+be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_reverse_gamma10);
+be_define_const_str(read, "read", 3470762949u, 0, 4, NULL);
+be_define_const_str(read12, "read12", 4291076970u, 0, 6, NULL);
+be_define_const_str(read13, "read13", 12887293u, 0, 6, NULL);
+be_define_const_str(read24, "read24", 1808533811u, 0, 6, NULL);
+be_define_const_str(read32, "read32", 1741276240u, 0, 6, NULL);
+be_define_const_str(read8, "read8", 2802788167u, 0, 5, NULL);
+be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, NULL);
+be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, &be_const_str_round_end);
+be_define_const_str(readbytes, "readbytes", 2716426756u, 0, 9, NULL);
+be_define_const_str(readline, "readline", 1212709927u, 0, 8, NULL);
+be_define_const_str(real, "real", 3604983901u, 0, 4, NULL);
+be_define_const_str(reapply, "reapply", 3778939332u, 0, 7, NULL);
+be_define_const_str(redirect, "redirect", 389758641u, 0, 8, &be_const_str_rtc);
+be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, &be_const_str_sec);
+be_define_const_str(refr_size, "refr_size", 1958144468u, 0, 9, &be_const_str_target_search);
+be_define_const_str(register_obj, "register_obj", 3982614770u, 0, 12, &be_const_str_sys);
+be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL);
+be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL);
+be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, &be_const_str_tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29);
+be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, &be_const_str_except);
+be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, NULL);
+be_define_const_str(reset, "reset", 1695364032u, 0, 5, NULL);
+be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, NULL);
+be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL);
+be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, NULL);
+be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, &be_const_str_widget_editable);
+be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL);
+be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL);
+be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, &be_const_str_set_chg_current);
+be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, NULL);
+be_define_const_str(response_append, "response_append", 450346371u, 0, 15, &be_const_str_set_first_time);
+be_define_const_str(return, "return", 2246981567u, 60, 6, NULL);
+be_define_const_str(return_X20code_X3D_X25i, "return code=%i", 2127454401u, 0, 14, NULL);
+be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL);
+be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL);
+be_define_const_str(rotate, "rotate", 2784296202u, 0, 6, NULL);
+be_define_const_str(round_end, "round_end", 985288225u, 0, 9, &be_const_str_strftime);
+be_define_const_str(round_start, "round_start", 2949484384u, 0, 11, &be_const_str_sqrt);
+be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, NULL);
+be_define_const_str(rule, "rule", 4230889683u, 0, 4, &be_const_str_settings);
+be_define_const_str(run, "run", 718098122u, 0, 3, &be_const_str_set_style_line_color);
+be_define_const_str(run_bat, "run_bat", 2536903298u, 0, 7, &be_const_str_valuer_error);
+be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, NULL);
+be_define_const_str(running, "running", 343848780u, 0, 7, &be_const_str_string);
+be_define_const_str(save, "save", 3439296072u, 0, 4, NULL);
+be_define_const_str(save_before_restart, "save_before_restart", 1253239338u, 0, 19, NULL);
+be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, &be_const_str_widget_group_def);
+be_define_const_str(scan, "scan", 3974641896u, 0, 4, NULL);
+be_define_const_str(search, "search", 2150836393u, 0, 6, NULL);
+be_define_const_str(sec, "sec", 3139892658u, 0, 3, NULL);
+be_define_const_str(seg7_font, "seg7_font", 4099690689u, 0, 9, &be_const_str_set_useragent);
+be_define_const_str(select, "select", 297952813u, 0, 6, NULL);
+be_define_const_str(serial, "serial", 3687697785u, 0, 6, NULL);
+be_define_const_str(set, "set", 3324446467u, 0, 3, NULL);
+be_define_const_str(set_alternate, "set_alternate", 1709680562u, 0, 13, &be_const_str_widget_event);
+be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, &be_const_str_update);
+be_define_const_str(set_bri, "set_bri", 2789118779u, 0, 7, &be_const_str_str);
+be_define_const_str(set_chg_current, "set_chg_current", 336304386u, 0, 15, NULL);
+be_define_const_str(set_dc_voltage, "set_dc_voltage", 2181981936u, 0, 14, NULL);
+be_define_const_str(set_dcdc_enable, "set_dcdc_enable", 1594690786u, 0, 15, &be_const_str_class);
+be_define_const_str(set_first_time, "set_first_time", 3111247550u, 0, 14, &be_const_str_tan);
+be_define_const_str(set_height, "set_height", 1080207399u, 0, 10, NULL);
+be_define_const_str(set_ldo_enable, "set_ldo_enable", 2916502041u, 0, 14, NULL);
+be_define_const_str(set_ldo_voltage, "set_ldo_voltage", 4090501160u, 0, 15, NULL);
+be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, NULL);
+be_define_const_str(set_matrix_pixel_color, "set_matrix_pixel_color", 1197149462u, 0, 22, NULL);
+be_define_const_str(set_percentage, "set_percentage", 2952022724u, 0, 14, &be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D);
+be_define_const_str(set_pixel_color, "set_pixel_color", 1275248356u, 0, 15, NULL);
+be_define_const_str(set_power, "set_power", 549820893u, 0, 9, &be_const_str_v);
+be_define_const_str(set_style_bg_color, "set_style_bg_color", 1689513089u, 0, 18, NULL);
+be_define_const_str(set_style_line_color, "set_style_line_color", 3665238976u, 0, 20, NULL);
+be_define_const_str(set_style_pad_right, "set_style_pad_right", 3314069054u, 0, 19, NULL);
+be_define_const_str(set_style_text_font, "set_style_text_font", 1028590019u, 0, 19, &be_const_str_widget_ctor_impl);
+be_define_const_str(set_text, "set_text", 1849641155u, 0, 8, NULL);
+be_define_const_str(set_time, "set_time", 900236405u, 0, 8, &be_const_str_if);
+be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, NULL);
+be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, &be_const_str_for);
+be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, NULL);
+be_define_const_str(set_width, "set_width", 484671920u, 0, 9, NULL);
+be_define_const_str(set_x, "set_x", 1849400772u, 0, 5, &be_const_str_var);
+be_define_const_str(set_y, "set_y", 1866178391u, 0, 5, &be_const_str_raise);
+be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_super);
+be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL);
+be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL);
+be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, NULL);
+be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL);
+be_define_const_str(settings, "settings", 1745255176u, 0, 8, NULL);
+be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, NULL);
+be_define_const_str(show, "show", 2840060476u, 0, 4, NULL);
+be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_widget_constructor);
+be_define_const_str(sinh, "sinh", 282220607u, 0, 4, NULL);
+be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_top);
+be_define_const_str(skip, "skip", 1097563074u, 0, 4, &be_const_str_tr);
+be_define_const_str(solidified, "solidified", 3257553487u, 0, 10, NULL);
+be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str__X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D);
+be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, &be_const_str_widget_cb);
+be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL);
+be_define_const_str(start, "start", 1697318111u, 0, 5, NULL);
+be_define_const_str(state, "state", 2016490230u, 0, 5, NULL);
+be_define_const_str(static, "static", 3532702267u, 71, 6, NULL);
+be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL);
+be_define_const_str(stop_iteration, "stop_iteration", 4173793901u, 0, 14, NULL);
+be_define_const_str(str, "str", 3259748752u, 0, 3, NULL);
+be_define_const_str(strftime, "strftime", 187738851u, 0, 8, NULL);
+be_define_const_str(string, "string", 398550328u, 0, 6, NULL);
+be_define_const_str(strip, "strip", 4246411473u, 0, 5, NULL);
+be_define_const_str(strptime, "strptime", 1277910361u, 0, 8, &be_const_str_wire_scan);
+be_define_const_str(super, "super", 4152230356u, 0, 5, NULL);
+be_define_const_str(sys, "sys", 3277365014u, 0, 3, NULL);
+be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL);
+be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL);
+be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str__X7B);
+be_define_const_str(target, "target", 845187144u, 0, 6, &be_const_str_widget_width_def);
+be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, &be_const_str_url_encode);
+be_define_const_str(tasmota, "tasmota", 424643812u, 0, 7, &be_const_str_value_error);
+be_define_const_str(tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29, "tasmota.get_light() is deprecated, use light.get()", 3525753647u, 0, 50, &be_const_str_while);
+be_define_const_str(tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29, "tasmota.set_light() is deprecated, use light.set()", 2124937871u, 0, 50, NULL);
+be_define_const_str(tcpclient, "tcpclient", 3828797983u, 0, 9, NULL);
+be_define_const_str(tele, "tele", 3474458061u, 0, 4, &be_const_str_time_dump);
+be_define_const_str(the_X20second_X20argument_X20is_X20not_X20a_X20function, "the second argument is not a function", 3954574469u, 0, 37, NULL);
+be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL);
+be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, &be_const_str__X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D);
+be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, NULL);
+be_define_const_str(to_gamma, "to_gamma", 1597139862u, 0, 8, &be_const_str_value);
+be_define_const_str(tob64, "tob64", 373777640u, 0, 5, NULL);
+be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL);
+be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL);
+be_define_const_str(top, "top", 2802900028u, 0, 3, NULL);
+be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, NULL);
+be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL);
+be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str_webserver);
+be_define_const_str(tr, "tr", 1195724803u, 0, 2, NULL);
+be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, NULL);
+be_define_const_str(true, "true", 1303515621u, 61, 4, NULL);
+be_define_const_str(try, "try", 2887626766u, 68, 3, NULL);
+be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL);
+be_define_const_str(type, "type", 1361572173u, 0, 4, NULL);
+be_define_const_str(unknown_X20instruction, "unknown instruction", 1093911841u, 0, 19, NULL);
+be_define_const_str(update, "update", 672109684u, 0, 6, NULL);
+be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL);
+be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL);
+be_define_const_str(v, "v", 4077666505u, 0, 1, NULL);
+be_define_const_str(value, "value", 1113510858u, 0, 5, NULL);
+be_define_const_str(value_error, "value_error", 773297791u, 0, 11, NULL);
+be_define_const_str(valuer_error, "valuer_error", 2567947105u, 0, 12, NULL);
+be_define_const_str(var, "var", 2317739966u, 64, 3, NULL);
+be_define_const_str(w, "w", 4060888886u, 0, 1, NULL);
+be_define_const_str(wd, "wd", 1531424278u, 0, 2, NULL);
+be_define_const_str(web_add_button, "web_add_button", 3537875058u, 0, 14, NULL);
+be_define_const_str(web_add_config_button, "web_add_config_button", 639674325u, 0, 21, NULL);
+be_define_const_str(web_add_console_button, "web_add_console_button", 3481436192u, 0, 22, NULL);
+be_define_const_str(web_add_handler, "web_add_handler", 3990174962u, 0, 15, NULL);
+be_define_const_str(web_add_main_button, "web_add_main_button", 3960367664u, 0, 19, NULL);
+be_define_const_str(web_add_management_button, "web_add_management_button", 2738877186u, 0, 25, &be_const_str_do);
+be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL);
+be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, NULL);
+be_define_const_str(web_sensor, "web_sensor", 2900096972u, 0, 10, &be_const_str_write_gpio);
+be_define_const_str(webclient, "webclient", 4076389146u, 0, 9, NULL);
+be_define_const_str(webserver, "webserver", 1572454038u, 0, 9, NULL);
+be_define_const_str(while, "while", 231090382u, 53, 5, NULL);
+be_define_const_str(widget_cb, "widget_cb", 2763583055u, 0, 9, NULL);
+be_define_const_str(widget_constructor, "widget_constructor", 2543785934u, 0, 18, NULL);
+be_define_const_str(widget_ctor_cb, "widget_ctor_cb", 876007560u, 0, 14, NULL);
+be_define_const_str(widget_ctor_impl, "widget_ctor_impl", 194252479u, 0, 16, NULL);
+be_define_const_str(widget_destructor, "widget_destructor", 4207388345u, 0, 17, NULL);
+be_define_const_str(widget_dtor_cb, "widget_dtor_cb", 3151545845u, 0, 14, NULL);
+be_define_const_str(widget_dtor_impl, "widget_dtor_impl", 520430610u, 0, 16, NULL);
+be_define_const_str(widget_editable, "widget_editable", 3821793286u, 0, 15, NULL);
+be_define_const_str(widget_event, "widget_event", 1951408186u, 0, 12, NULL);
+be_define_const_str(widget_event_cb, "widget_event_cb", 1508466754u, 0, 15, NULL);
+be_define_const_str(widget_event_impl, "widget_event_impl", 2178430561u, 0, 17, NULL);
+be_define_const_str(widget_group_def, "widget_group_def", 1246968785u, 0, 16, NULL);
+be_define_const_str(widget_height_def, "widget_height_def", 3131667813u, 0, 17, NULL);
+be_define_const_str(widget_instance_size, "widget_instance_size", 2055354779u, 0, 20, NULL);
+be_define_const_str(widget_struct_by_class, "widget_struct_by_class", 3806373842u, 0, 22, NULL);
+be_define_const_str(widget_struct_default, "widget_struct_default", 781673633u, 0, 21, NULL);
+be_define_const_str(widget_width_def, "widget_width_def", 3986078862u, 0, 16, NULL);
+be_define_const_str(width, "width", 2508680735u, 0, 5, NULL);
+be_define_const_str(width_def, "width_def", 1143717879u, 0, 9, NULL);
+be_define_const_str(wifi, "wifi", 120087624u, 0, 4, NULL);
+be_define_const_str(wire, "wire", 4082753944u, 0, 4, NULL);
+be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, &be_const_str_true);
+be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL);
+be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL);
+be_define_const_str(write, "write", 3190202204u, 0, 5, NULL);
+be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL);
+be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL);
+be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL);
+be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL);
+be_define_const_str(write_gpio, "write_gpio", 2267940334u, 0, 10, NULL);
+be_define_const_str(x, "x", 4245442695u, 0, 1, NULL);
+be_define_const_str(x1, "x1", 274927234u, 0, 2, NULL);
+be_define_const_str(y, "y", 4228665076u, 0, 1, NULL);
+be_define_const_str(y1, "y1", 2355101727u, 0, 2, NULL);
+be_define_const_str(year, "year", 2927578396u, 0, 4, NULL);
+be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL);
+be_define_const_str(zero, "zero", 2339366755u, 0, 4, NULL);
+be_define_const_str(zip, "zip", 2877453236u, 0, 3, NULL);
+be_define_const_str(_X7B, "{", 4262220314u, 0, 1, NULL);
+be_define_const_str(_X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, "{s}Batt Current{m}%.1f mA{e}", 866537156u, 0, 28, NULL);
+be_define_const_str(_X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D, "{s}Batt Voltage{m}%.3f V{e}", 3184308199u, 0, 27, NULL);
+be_define_const_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_XB0C_X7Be_X7D, "{s}Temp AXP{m}%.1f \u00b0C{e}", 2304457292u, 0, 24, NULL);
+be_define_const_str(_X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D, "{s}VBus Current{m}%.1f mA{e}", 1032721155u, 0, 28, NULL);
+be_define_const_str(_X7Bs_X7DVBus_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D, "{s}VBus Voltage{m}%.3f V{e}", 165651270u, 0, 27, NULL);
+be_define_const_str(_X7B_X7D, "{}", 1415952421u, 0, 2, NULL);
+be_define_const_str(_X7D, "}", 4161554600u, 0, 1, NULL);
+
+static const bstring* const m_string_table[] = {
+ (const bstring *)&be_const_str__X3E_X3D,
+ (const bstring *)&be_const_str_run_bat,
+ NULL,
+ NULL,
+ (const bstring *)&be_const_str_io_error,
+ (const bstring *)&be_const_str_depower,
+ (const bstring *)&be_const_str_SERIAL_6O1,
+ (const bstring *)&be_const_str_STATE_DEFAULT,
+ (const bstring *)&be_const_str_SERIAL_6N1,
+ (const bstring *)&be_const_str_Auto_X2Dconfiguration,
+ (const bstring *)&be_const_str_decrypt,
+ (const bstring *)&be_const_str_insert,
+ NULL,
+ (const bstring *)&be_const_str__X3D,
+ (const bstring *)&be_const_str_write_bytes,
+ NULL,
+ (const bstring *)&be_const_str_running,
+ (const bstring *)&be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E,
+ (const bstring *)&be_const_str_read_bytes,
+ (const bstring *)&be_const_str_draw_arc,
+ (const bstring *)&be_const_str__X20,
+ (const bstring *)&be_const_str_event,
+ (const bstring *)&be_const_str_SERIAL_5E2,
+ (const bstring *)&be_const_str_SERIAL_6E1,
+ (const bstring *)&be_const_str_leds,
+ (const bstring *)&be_const_str__lvgl,
+ (const bstring *)&be_const_str_zip,
+ (const bstring *)&be_const_str_EC_C25519,
+ (const bstring *)&be_const_str_COLOR_BLACK,
+ (const bstring *)&be_const_str_readline,
+ (const bstring *)&be_const_str__X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E,
+ NULL,
+ (const bstring *)&be_const_str_load_templates,
+ (const bstring *)&be_const_str_get,
+ (const bstring *)&be_const_str_POST,
+ (const bstring *)&be_const_str___iterator__,
+ (const bstring *)&be_const_str_AudioGeneratorMP3,
+ (const bstring *)&be_const_str__energy,
+ (const bstring *)&be_const_str__rules,
+ (const bstring *)&be_const_str_break,
+ (const bstring *)&be_const_str__X2F_X2Eautoconf,
+ (const bstring *)&be_const_str_content_button,
+ (const bstring *)&be_const_str_copy,
+ (const bstring *)&be_const_str_get_aps_voltage,
+ (const bstring *)&be_const_str_AXP192,
+ (const bstring *)&be_const_str_select,
+ (const bstring *)&be_const_str_autoexec,
+ (const bstring *)&be_const_str__X0A,
+ (const bstring *)&be_const_str_available,
+ NULL,
+ (const bstring *)&be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B,
+ (const bstring *)&be_const_str_gc,
+ (const bstring *)&be_const_str_CFG_X3A_X20loading_X20_X27_X25s_X27,
+ (const bstring *)&be_const_str__X21_X3D_X3D,
+ (const bstring *)&be_const_str_split,
+ (const bstring *)&be_const_str_lower,
+ (const bstring *)&be_const_str__X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E,
+ (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E,
+ (const bstring *)&be_const_str_base_class,
+ (const bstring *)&be_const_str_connected,
+ (const bstring *)&be_const_str_instance,
+ NULL,
+ (const bstring *)&be_const_str__X2Etapp,
+ (const bstring *)&be_const_str__X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E,
+ (const bstring *)&be_const_str_attrdump,
+ (const bstring *)&be_const_str_EVENT_DRAW_MAIN,
+ (const bstring *)&be_const_str__request_from,
+ (const bstring *)&be_const_str__X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E,
+ (const bstring *)&be_const_str_acos,
+ (const bstring *)&be_const_str_get_light,
+ (const bstring *)&be_const_str_resp_cmnd_str,
+ NULL,
+ (const bstring *)&be_const_str_CFG_X3A_X20removing_X20autoconf_X20files,
+ NULL,
+ (const bstring *)&be_const_str_w,
+ (const bstring *)&be_const_str_draw_line,
+ NULL,
+ (const bstring *)&be_const_str_strip,
+ (const bstring *)&be_const_str_format,
+ (const bstring *)&be_const_str_Leds,
+ (const bstring *)&be_const_str_exec_tele,
+ (const bstring *)&be_const_str_chars_in_string,
+ (const bstring *)&be_const_str_CFG_X3A_X20skipping_X20_X27display_X2Eini_X27_X20because_X20already_X20present_X20in_X20file_X2Dsystem,
+ NULL,
+ (const bstring *)&be_const_str_widget_dtor_cb,
+ (const bstring *)&be_const_str_invalidate,
+ (const bstring *)&be_const_str__X3A,
+ NULL,
+ (const bstring *)&be_const_str_out_X20of_X20range,
+ NULL,
+ (const bstring *)&be_const_str_lv_event_cb,
+ (const bstring *)&be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback,
+ (const bstring *)&be_const_str_escape,
+ (const bstring *)&be_const_str_event_cb,
+ (const bstring *)&be_const_str_init_draw_line_dsc,
+ NULL,
+ (const bstring *)&be_const_str_isinstance,
+ (const bstring *)&be_const_str_exists,
+ (const bstring *)&be_const_str_HTTP_GET,
+ (const bstring *)&be_const_str_clear_first_time,
+ (const bstring *)&be_const_str__X2Eautoconf,
+ (const bstring *)&be_const_str_clear,
+ (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E,
+ (const bstring *)&be_const_str_SERIAL_7N1,
+ (const bstring *)&be_const_str_get_percentage,
+ (const bstring *)&be_const_str_SERIAL_7O1,
+ (const bstring *)&be_const_str_remove,
+ (const bstring *)&be_const_str_set_time,
+ (const bstring *)&be_const_str_get_size,
+ (const bstring *)&be_const_str_remove_timer,
+ (const bstring *)&be_const_str__X23autoexec_X2Ebat,
+ (const bstring *)&be_const_str__X2D_X2D_X3A_X2D_X2D,
+ (const bstring *)&be_const_str_due,
+ (const bstring *)&be_const_str__X2C,
+ (const bstring *)&be_const_str_instance_size,
+ (const bstring *)&be_const_str_Animate_X20pc_X20is_X20out_X20of_X20range,
+ (const bstring *)&be_const_str_cb,
+ (const bstring *)&be_const_str_resp_cmnd_done,
+ NULL,
+ (const bstring *)&be_const_str_energy_struct,
+ NULL,
+ (const bstring *)&be_const_str__drivers,
+ (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dzip_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20,
+ (const bstring *)&be_const_str_tob64,
+ (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E,
+ (const bstring *)&be_const_str_CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29,
+ (const bstring *)&be_const_str__X3C,
+ (const bstring *)&be_const_str_y,
+ (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E_X26_X23129668_X3B_X20Auto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E,
+ (const bstring *)&be_const_str_files,
+ (const bstring *)&be_const_str__X2Ew,
+ (const bstring *)&be_const_str_assert,
+ (const bstring *)&be_const_str_bytes,
+ (const bstring *)&be_const_str__X23,
+ (const bstring *)&be_const_str_abs,
+ (const bstring *)&be_const_str__X2E_X2E,
+ (const bstring *)&be_const_str__global_addr,
+ (const bstring *)&be_const_str_connect,
+ (const bstring *)&be_const_str__settings_ptr,
+ NULL,
+ (const bstring *)&be_const_str_CFG_X3A_X20ran_X20_X20,
+ (const bstring *)&be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20,
+ NULL,
+ (const bstring *)&be_const_str__X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d,
+ (const bstring *)&be_const_str_i2c_enabled,
+ (const bstring *)&be_const_str_ctypes_bytes_dyn,
+ (const bstring *)&be_const_str_CFG_X3A_X20loading_X20,
+ NULL,
+ NULL,
+ (const bstring *)&be_const_str_refr_size,
+ (const bstring *)&be_const_str_content_send_style,
+ NULL,
+ NULL,
+ (const bstring *)&be_const_str_begin,
+ (const bstring *)&be_const_str_c,
+ (const bstring *)&be_const_str_ins_goto,
+ (const bstring *)&be_const_str__buffer,
+ (const bstring *)&be_const_str_concat,
+ (const bstring *)&be_const_str_percentage,
+ NULL,
+ (const bstring *)&be_const_str_SERIAL_5N2,
+ NULL,
+ NULL,
+ (const bstring *)&be_const_str_SK6812_GRBW,
+ (const bstring *)&be_const_str__X3Cp_X3E_X3Csmall_X3E_X26nbsp_X3B_X28This_X20feature_X20requires_X20an_X20internet_X20connection_X29_X3C_X2Fsmall_X3E_X3C_X2Fp_X3E,
+ (const bstring *)&be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E,
+ NULL,
+ NULL,
+ (const bstring *)&be_const_str_lv_obj,
+ (const bstring *)&be_const_str___upper__,
+ (const bstring *)&be_const_str_Restart_X201,
+ NULL,
+ (const bstring *)&be_const_str_introspect,
+ (const bstring *)&be_const_str__X23autoexec_X2Ebe,
+ (const bstring *)&be_const_str_CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27,
+ (const bstring *)&be_const_str_bool,
+ (const bstring *)&be_const_str_PART_MAIN,
+ (const bstring *)&be_const_str_back_forth,
+ (const bstring *)&be_const_str_lv_obj_class,
+ (const bstring *)&be_const_str_TAP_X3A_X20found_X20Tasmota_X20App_X20_X27_X25s_X27,
+ (const bstring *)&be_const_str_GET,
+ (const bstring *)&be_const_str_deg,
+ (const bstring *)&be_const_str__X28_X29,
+ NULL,
+ (const bstring *)&be_const_str__X23preinit_X2Ebe,
+ (const bstring *)&be_const_str__class,
+ NULL,
+ (const bstring *)&be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E,
+ (const bstring *)&be_const_str_CFG_X3A_X20downloading_X20_X27_X25s_X27,
+ (const bstring *)&be_const_str__X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E,
+ (const bstring *)&be_const_str_fromstring,
+ (const bstring *)&be_const_str_SERIAL_8E2,
+ NULL,
+ (const bstring *)&be_const_str__anonymous_,
+ (const bstring *)&be_const_str__X2502d_X25s_X2502d,
+ (const bstring *)&be_const_str_CFG_X3A_X20return_code_X3D_X25i,
+ (const bstring *)&be_const_str_web_sensor,
+ (const bstring *)&be_const_str_detect,
+ (const bstring *)&be_const_str_exec_cmd,
+ (const bstring *)&be_const_str_to_gamma,
+ (const bstring *)&be_const_str__ptr,
+ (const bstring *)&be_const_str_null_cb,
+ (const bstring *)&be_const_str_eth,
+ (const bstring *)&be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_X2F_X25s_X2Eautoconf,
+ (const bstring *)&be_const_str_erase,
+ (const bstring *)&be_const_str__archive,
+ (const bstring *)&be_const_str_CFG_X3A_X20removed_X20file_X20_X27_X25s_X27,
+ (const bstring *)&be_const_str_code,
+ (const bstring *)&be_const_str_BUTTON_CONFIGURATION,
+ (const bstring *)&be_const_str_web_send_decimal,
+ (const bstring *)&be_const_str_fromptr,
+ (const bstring *)&be_const_str_SERIAL_8E1,
+ NULL,
+ (const bstring *)&be_const_str_set_style_bg_color,
+ (const bstring *)&be_const_str_end,
+ (const bstring *)&be_const_str__read,
+ (const bstring *)&be_const_str_cos,
+ (const bstring *)&be_const_str_codedump,
+ (const bstring *)&be_const_str__X23init_X2Ebat,
+ (const bstring *)&be_const_str_get_battery_chargin_status,
+ (const bstring *)&be_const_str__X2Ebec,
+ (const bstring *)&be_const_str_set_dcdc_enable,
+ NULL,
+ (const bstring *)&be_const_str_ctor,
+ (const bstring *)&be_const_str_digital_read,
+ (const bstring *)&be_const_str_close,
+ (const bstring *)&be_const_str__X2F,
+ (const bstring *)&be_const_str_cosh,
+ (const bstring *)&be_const_str_I2C_Driver,
+ (const bstring *)&be_const_str_read24,
+ (const bstring *)&be_const_str__write,
+ (const bstring *)&be_const_str__X23display_X2Eini,
+ (const bstring *)&be_const_str_get_bat_power,
+ (const bstring *)&be_const_str_pin_mode,
+ (const bstring *)&be_const_str__,
+ (const bstring *)&be_const_str_scale_uint,
+ (const bstring *)&be_const_str_WS2812_GRB,
+ (const bstring *)&be_const_str_AudioOutput,
+ (const bstring *)&be_const_str_animate,
+ (const bstring *)&be_const_str__X3F,
+ (const bstring *)&be_const_str_id,
+ (const bstring *)&be_const_str_arg_name,
+ (const bstring *)&be_const_str_internal_error,
+ (const bstring *)&be_const_str_serial,
+ NULL,
+ NULL,
+ (const bstring *)&be_const_str_CFG_X3A_X20could_X20not_X20run_X20_X25s_X20_X28_X25s_X20_X2D_X20_X25s_X29,
+ (const bstring *)&be_const_str__begin_transmission,
+ (const bstring *)&be_const_str__X2Ep1,
+ (const bstring *)&be_const_str_engine,
+ (const bstring *)&be_const_str__def,
+ (const bstring *)&be_const_str_get_pixel_color,
+ (const bstring *)&be_const_str__X3C_X3D,
+ (const bstring *)&be_const_str_CFG_X3A_X20removing_X20first_X20time_X20marker,
+ (const bstring *)&be_const_str__X3D_X3D,
+ (const bstring *)&be_const_str_can_show,
+ (const bstring *)&be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20,
+ (const bstring *)&be_const_str_response_append,
+ (const bstring *)&be_const_str_CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting,
+ (const bstring *)&be_const_str_content_send,
+ (const bstring *)&be_const_str_create_segment,
+ (const bstring *)&be_const_str_duration,
+ (const bstring *)&be_const_str_get_height,
+ (const bstring *)&be_const_str_delete_all_configs,
+ (const bstring *)&be_const_str_reset_search,
+ (const bstring *)&be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson,
+ (const bstring *)&be_const_str_,
+ (const bstring *)&be_const_str_b,
+ (const bstring *)&be_const_str_SERIAL_5E1,
+ (const bstring *)&be_const_str_SERIAL_6E2,
+ (const bstring *)&be_const_str_read13,
+ (const bstring *)&be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s,
+ (const bstring *)&be_const_str_publish_result,
+ (const bstring *)&be_const_str_get_bat_current,
+ NULL,
+ (const bstring *)&be_const_str_ceil,
+ (const bstring *)&be_const_str_autorun,
+ (const bstring *)&be_const_str_length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032,
+ (const bstring *)&be_const_str_set_text,
+ (const bstring *)&be_const_str__X3D_X3C_X3E_X21,
+ (const bstring *)&be_const_str_r,
+ (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X20,
+ (const bstring *)&be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E,
+ (const bstring *)&be_const_str__X2Ep,
+ (const bstring *)&be_const_str__error,
+ (const bstring *)&be_const_str_lv,
+ (const bstring *)&be_const_str_flush,
+ (const bstring *)&be_const_str_AudioFileSource,
+ (const bstring *)&be_const_str_web_add_main_button,
+ (const bstring *)&be_const_str__X2Elen,
+ (const bstring *)&be_const_str_persist_X2E_p_X20is_X20not_X20a_X20map,
+ (const bstring *)&be_const_str_compile,
+ (const bstring *)&be_const_str_CFG_X3A_X20running_X20,
+ (const bstring *)&be_const_str_compress,
+ NULL,
+ (const bstring *)&be_const_str_pin_used,
+ (const bstring *)&be_const_str__X2Ebe,
+ (const bstring *)&be_const_str_SERIAL_8O1,
+ (const bstring *)&be_const_str_CFG_X3A_X20loaded_X20_X27_X25s_X27,
+ (const bstring *)&be_const_str_EVENT_DRAW_PART_END,
+ NULL,
+ NULL,
+ (const bstring *)&be_const_str_button_pressed,
+ (const bstring *)&be_const_str_atleast1,
+ (const bstring *)&be_const_str_add_anim,
+ (const bstring *)&be_const_str_count,
+ (const bstring *)&be_const_str__X25s_X2Eautoconf,
+ (const bstring *)&be_const_str_False,
+ (const bstring *)&be_const_str_time_str,
+ (const bstring *)&be_const_str__X26lt_X3BNone_X26gt_X3B,
+ (const bstring *)&be_const_str_allocated,
+ NULL,
+ (const bstring *)&be_const_str_cb_obj,
+ (const bstring *)&be_const_str__X21_X3D,
+ (const bstring *)&be_const_str__X3Cselect_X20name_X3D_X27zip_X27_X3E,
+ (const bstring *)&be_const_str_OneWire,
+ (const bstring *)&be_const_str_classof,
+ (const bstring *)&be_const_str_json,
+ (const bstring *)&be_const_str_True,
+ (const bstring *)&be_const_str__X2B,
+ (const bstring *)&be_const_str_decompress,
+ (const bstring *)&be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s,
+ (const bstring *)&be_const_str_lv_event,
+ (const bstring *)&be_const_str_counters,
+ (const bstring *)&be_const_str_pc,
+ (const bstring *)&be_const_str__X2Esize,
+ NULL,
+ (const bstring *)&be_const_str__X5B,
+ (const bstring *)&be_const_str__X3C_X2Fform_X3E_X3C_X2Fp_X3E,
+ (const bstring *)&be_const_str_connection_error,
+ (const bstring *)&be_const_str_classname,
+ (const bstring *)&be_const_str_AudioGeneratorWAV,
+ (const bstring *)&be_const_str_AudioGenerator,
+ (const bstring *)&be_const_str_Parameter_X20error,
+ (const bstring *)&be_const_str_get_tasmota,
+ (const bstring *)&be_const_str_loop,
+ (const bstring *)&be_const_str__timers,
+ (const bstring *)&be_const_str_constructor_cb,
+ (const bstring *)&be_const_str_addr,
+ (const bstring *)&be_const_str__X2E,
+ (const bstring *)&be_const_str_RES_OK,
+ NULL,
+ (const bstring *)&be_const_str_OPTION_A,
+ NULL,
+ (const bstring *)&be_const_str_collect,
+ (const bstring *)&be_const_str_SERIAL_6O2,
+ (const bstring *)&be_const_str_AudioFileSourceFS,
+ (const bstring *)&be_const_str_show,
+ (const bstring *)&be_const_str__cmd,
+ (const bstring *)&be_const_str_SERIAL_7N2,
+ (const bstring *)&be_const_str_dirty,
+ (const bstring *)&be_const_str_SERIAL_7E2,
+ (const bstring *)&be_const_str__X3E,
+ (const bstring *)&be_const_str__X2F_X3Frst_X3D,
+ (const bstring *)&be_const_str__X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E,
+ (const bstring *)&be_const_str_EVENT_DRAW_PART_BEGIN,
+ (const bstring *)&be_const_str__persist_X2Ejson,
+ (const bstring *)&be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29,
+ (const bstring *)&be_const_str__X3Clambda_X3E
+};
+
+static const struct bconststrtab m_const_string_table = {
+ .size = 359,
+ .count = 741,
+ .table = m_string_table
+};
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_aes_gcm.h b/lib/libesp32/berry/generate/be_fixed_be_class_aes_gcm.h
new file mode 100644
index 000000000..7c4096f34
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_aes_gcm.h
@@ -0,0 +1,22 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_aes_gcm_map) {
+ { be_const_key(encrypt, 4), be_const_func(m_aes_gcm_encryt) },
+ { be_const_key(_X2Ep2, -1), be_const_var(0) },
+ { be_const_key(decrypt, -1), be_const_func(m_aes_gcm_decryt) },
+ { be_const_key(init, -1), be_const_func(m_aes_gcm_init) },
+ { be_const_key(_X2Ep1, -1), be_const_var(1) },
+ { be_const_key(tag, -1), be_const_func(m_aes_gcm_tag) },
+};
+
+static be_define_const_map(
+ be_class_aes_gcm_map,
+ 6
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_aes_gcm,
+ 2,
+ NULL,
+ AES_GCM
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source.h
new file mode 100644
index 000000000..f3d59effc
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source.h
@@ -0,0 +1,17 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_audio_file_source_map) {
+ { be_const_key(_X2Ep, -1), be_const_var(0) },
+};
+
+static be_define_const_map(
+ be_class_audio_file_source_map,
+ 1
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_audio_file_source,
+ 1,
+ NULL,
+ AudioFileSource
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source_fs.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source_fs.h
new file mode 100644
index 000000000..6605ba27e
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_file_source_fs.h
@@ -0,0 +1,18 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_audio_file_source_fs_map) {
+ { be_const_key(deinit, -1), be_const_func(i2s_file_source_fs_deinit) },
+ { be_const_key(init, -1), be_const_func(i2s_file_source_fs_init) },
+};
+
+static be_define_const_map(
+ be_class_audio_file_source_fs_map,
+ 2
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_audio_file_source_fs,
+ 0,
+ (bclass *)&be_class_audio_file_source,
+ AudioFileSourceFS
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator.h
new file mode 100644
index 000000000..41b50f180
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator.h
@@ -0,0 +1,17 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_audio_generator_map) {
+ { be_const_key(_X2Ep, -1), be_const_var(0) },
+};
+
+static be_define_const_map(
+ be_class_audio_generator_map,
+ 1
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_audio_generator,
+ 1,
+ NULL,
+ AudioGenerator
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_mp3.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_mp3.h
new file mode 100644
index 000000000..dbe5f0d4f
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_mp3.h
@@ -0,0 +1,22 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_audio_generator_mp3_map) {
+ { be_const_key(begin, -1), be_const_func(i2s_generator_mp3_begin) },
+ { be_const_key(loop, -1), be_const_func(i2s_generator_mp3_loop) },
+ { be_const_key(isrunning, -1), be_const_func(i2s_generator_mp3_isrunning) },
+ { be_const_key(init, 1), be_const_func(i2s_generator_mp3_init) },
+ { be_const_key(deinit, -1), be_const_func(i2s_generator_mp3_deinit) },
+ { be_const_key(stop, -1), be_const_func(i2s_generator_mp3_stop) },
+};
+
+static be_define_const_map(
+ be_class_audio_generator_mp3_map,
+ 6
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_audio_generator_mp3,
+ 0,
+ (bclass *)&be_class_audio_generator,
+ AudioGeneratorMP3
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_wav.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_wav.h
new file mode 100644
index 000000000..f08522407
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_generator_wav.h
@@ -0,0 +1,22 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_audio_generator_wav_map) {
+ { be_const_key(begin, -1), be_const_func(i2s_generator_wav_begin) },
+ { be_const_key(loop, -1), be_const_func(i2s_generator_wav_loop) },
+ { be_const_key(isrunning, -1), be_const_func(i2s_generator_wav_isrunning) },
+ { be_const_key(init, 1), be_const_func(i2s_generator_wav_init) },
+ { be_const_key(deinit, -1), be_const_func(i2s_generator_wav_deinit) },
+ { be_const_key(stop, -1), be_const_func(i2s_generator_wav_stop) },
+};
+
+static be_define_const_map(
+ be_class_audio_generator_wav_map,
+ 6
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_audio_generator_wav,
+ 0,
+ (bclass *)&be_class_audio_generator,
+ AudioGeneratorWAV
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_output.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_output.h
new file mode 100644
index 000000000..192ee0677
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_output.h
@@ -0,0 +1,17 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_audio_output_map) {
+ { be_const_key(_X2Ep, -1), be_const_var(0) },
+};
+
+static be_define_const_map(
+ be_class_audio_output_map,
+ 1
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_audio_output,
+ 1,
+ NULL,
+ AudioOutput
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_audio_output_i2s.h b/lib/libesp32/berry/generate/be_fixed_be_class_audio_output_i2s.h
new file mode 100644
index 000000000..4e6b84e0d
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_audio_output_i2s.h
@@ -0,0 +1,19 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_audio_output_i2s_map) {
+ { be_const_key(init, -1), be_const_func(i2s_output_i2s_init) },
+ { be_const_key(deinit, -1), be_const_func(i2s_output_i2s_deinit) },
+ { be_const_key(stop, -1), be_const_func(i2s_output_i2s_stop) },
+};
+
+static be_define_const_map(
+ be_class_audio_output_i2s_map,
+ 3
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_audio_output_i2s,
+ 0,
+ (bclass *)&be_class_audio_output,
+ AudioOutputI2S
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h b/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h
new file mode 100644
index 000000000..cd9ea1f54
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_bytes.h
@@ -0,0 +1,44 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_bytes_map) {
+ { be_const_key(setitem, -1), be_const_func(m_setitem) },
+ { be_const_key(_X2E_X2E, -1), be_const_func(m_connect) },
+ { be_const_key(geti, -1), be_const_func(m_geti) },
+ { be_const_key(deinit, -1), be_const_func(m_deinit) },
+ { be_const_key(add, 18), be_const_func(m_add) },
+ { be_const_key(get, -1), be_const_func(m_getu) },
+ { be_const_key(asstring, 9), be_const_func(m_asstring) },
+ { be_const_key(_X2Ep, -1), be_const_var(0) },
+ { be_const_key(copy, 25), be_const_func(m_copy) },
+ { be_const_key(size, -1), be_const_func(m_size) },
+ { be_const_key(getbits, -1), be_const_closure(getbits_closure) },
+ { be_const_key(_X3D_X3D, -1), be_const_func(m_equal) },
+ { be_const_key(tob64, 3), be_const_func(m_tob64) },
+ { be_const_key(init, -1), be_const_func(m_init) },
+ { be_const_key(_X2B, -1), be_const_func(m_merge) },
+ { be_const_key(setbits, -1), be_const_closure(setbits_closure) },
+ { be_const_key(_buffer, -1), be_const_func(m_buffer) },
+ { be_const_key(tostring, -1), be_const_func(m_tostring) },
+ { be_const_key(_X2Elen, -1), be_const_var(1) },
+ { be_const_key(fromb64, 13), be_const_func(m_fromb64) },
+ { be_const_key(_X2Esize, 6), be_const_var(2) },
+ { be_const_key(resize, -1), be_const_func(m_resize) },
+ { be_const_key(seti, -1), be_const_func(m_set) },
+ { be_const_key(_X21_X3D, 5), be_const_func(m_nequal) },
+ { be_const_key(item, -1), be_const_func(m_item) },
+ { be_const_key(fromstring, -1), be_const_func(m_fromstring) },
+ { be_const_key(clear, 24), be_const_func(m_clear) },
+ { be_const_key(set, 10), be_const_func(m_set) },
+};
+
+static be_define_const_map(
+ be_class_bytes_map,
+ 28
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_bytes,
+ 3,
+ NULL,
+ bytes
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_ctypes.h b/lib/libesp32/berry/generate/be_fixed_be_class_ctypes.h
new file mode 100644
index 000000000..cf75e6d9a
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_ctypes.h
@@ -0,0 +1,22 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_ctypes_map) {
+ { be_const_key(_def, 5), be_const_nil() },
+ { be_const_key(setmember, 0), be_const_func(be_ctypes_setmember) },
+ { be_const_key(copy, -1), be_const_func(be_ctypes_copy) },
+ { be_const_key(init, -1), be_const_func(be_ctypes_init) },
+ { be_const_key(tomap, -1), be_const_func(be_ctypes_tomap) },
+ { be_const_key(member, -1), be_const_func(be_ctypes_member) },
+};
+
+static be_define_const_map(
+ be_class_ctypes_map,
+ 6
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_ctypes,
+ 0,
+ (bclass *)&be_class_bytes,
+ ctypes_bytes
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_ctypes_dyn.h b/lib/libesp32/berry/generate/be_fixed_be_class_ctypes_dyn.h
new file mode 100644
index 000000000..101f9d66a
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_ctypes_dyn.h
@@ -0,0 +1,18 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_ctypes_dyn_map) {
+ { be_const_key(_def, -1), be_const_var(0) },
+ { be_const_key(init, 0), be_const_func(be_ctypes_dyn_init) },
+};
+
+static be_define_const_map(
+ be_class_ctypes_dyn_map,
+ 2
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_ctypes_dyn,
+ 1,
+ (bclass *)&be_class_ctypes,
+ ctypes_bytes_dyn
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_ec_c25519.h b/lib/libesp32/berry/generate/be_fixed_be_class_ec_c25519.h
new file mode 100644
index 000000000..87182a254
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_ec_c25519.h
@@ -0,0 +1,18 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_ec_c25519_map) {
+ { be_const_key(public_key, 1), be_const_func(m_ec_c25519_pubkey) },
+ { be_const_key(shared_key, -1), be_const_func(m_ec_c25519_sharedkey) },
+};
+
+static be_define_const_map(
+ be_class_ec_c25519_map,
+ 2
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_ec_c25519,
+ 0,
+ NULL,
+ EC_C25519
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_list.h b/lib/libesp32/berry/generate/be_fixed_be_class_list.h
new file mode 100644
index 000000000..f05a19dc5
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_list.h
@@ -0,0 +1,38 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_list_map) {
+ { be_const_key(_X2B, -1), be_const_func(m_merge) },
+ { be_const_key(init, -1), be_const_func(m_init) },
+ { be_const_key(_X2E_X2E, 11), be_const_func(m_connect) },
+ { be_const_key(tostring, 2), be_const_func(m_tostring) },
+ { be_const_key(pop, 6), be_const_func(m_pop) },
+ { be_const_key(insert, -1), be_const_func(m_insert) },
+ { be_const_key(size, -1), be_const_func(m_size) },
+ { be_const_key(remove, 12), be_const_func(m_remove) },
+ { be_const_key(find, -1), be_const_func(m_find) },
+ { be_const_key(push, 1), be_const_func(m_push) },
+ { be_const_key(item, 5), be_const_func(m_item) },
+ { be_const_key(concat, -1), be_const_func(m_concat) },
+ { be_const_key(_X2Ep, -1), be_const_var(0) },
+ { be_const_key(iter, -1), be_const_func(m_iter) },
+ { be_const_key(copy, -1), be_const_func(m_copy) },
+ { be_const_key(reverse, 13), be_const_func(m_reverse) },
+ { be_const_key(keys, -1), be_const_func(m_keys) },
+ { be_const_key(resize, 16), be_const_func(m_resize) },
+ { be_const_key(setitem, -1), be_const_func(m_setitem) },
+ { be_const_key(_X21_X3D, 7), be_const_func(m_nequal) },
+ { be_const_key(clear, -1), be_const_func(m_clear) },
+ { be_const_key(_X3D_X3D, -1), be_const_func(m_equal) },
+};
+
+static be_define_const_map(
+ be_class_list_map,
+ 22
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_list,
+ 1,
+ NULL,
+ list
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_map.h b/lib/libesp32/berry/generate/be_fixed_be_class_map.h
new file mode 100644
index 000000000..f884630e3
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_map.h
@@ -0,0 +1,30 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_map_map) {
+ { be_const_key(setitem, -1), be_const_func(m_setitem) },
+ { be_const_key(remove, 8), be_const_func(m_remove) },
+ { be_const_key(insert, -1), be_const_func(m_insert) },
+ { be_const_key(tostring, 4), be_const_func(m_tostring) },
+ { be_const_key(has, -1), be_const_func(m_contains) },
+ { be_const_key(init, -1), be_const_func(m_init) },
+ { be_const_key(contains, 9), be_const_func(m_contains) },
+ { be_const_key(_X2Ep, 13), be_const_var(0) },
+ { be_const_key(reduce, -1), be_const_func(m_reduce) },
+ { be_const_key(size, -1), be_const_func(m_size) },
+ { be_const_key(find, -1), be_const_func(m_find) },
+ { be_const_key(keys, -1), be_const_func(m_keys) },
+ { be_const_key(item, -1), be_const_func(m_item) },
+ { be_const_key(iter, -1), be_const_func(m_iter) },
+};
+
+static be_define_const_map(
+ be_class_map_map,
+ 14
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_map,
+ 1,
+ NULL,
+ map
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_md5.h b/lib/libesp32/berry/generate/be_fixed_be_class_md5.h
new file mode 100644
index 000000000..b3fff0a5c
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_md5.h
@@ -0,0 +1,20 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_md5_map) {
+ { be_const_key(update, -1), be_const_func(m_md5_update) },
+ { be_const_key(_X2Ep, -1), be_const_var(0) },
+ { be_const_key(finish, -1), be_const_func(m_md5_finish) },
+ { be_const_key(init, 1), be_const_func(m_md5_init) },
+};
+
+static be_define_const_map(
+ be_class_md5_map,
+ 4
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_md5,
+ 1,
+ NULL,
+ MD5
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_range.h b/lib/libesp32/berry/generate/be_fixed_be_class_range.h
new file mode 100644
index 000000000..371840af1
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_range.h
@@ -0,0 +1,24 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_range_map) {
+ { be_const_key(setrange, -1), be_const_func(m_setrange) },
+ { be_const_key(iter, -1), be_const_func(m_iter) },
+ { be_const_key(lower, -1), be_const_func(m_lower) },
+ { be_const_key(init, 4), be_const_func(m_init) },
+ { be_const_key(__upper__, -1), be_const_var(0) },
+ { be_const_key(tostring, -1), be_const_func(m_tostring) },
+ { be_const_key(__lower__, -1), be_const_var(1) },
+ { be_const_key(upper, 1), be_const_func(m_upper) },
+};
+
+static be_define_const_map(
+ be_class_range_map,
+ 8
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_range,
+ 2,
+ NULL,
+ range
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_tasmota.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota.h
new file mode 100644
index 000000000..05c140fe0
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota.h
@@ -0,0 +1,93 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_tasmota_map) {
+ { be_const_key(run_deferred, -1), be_const_closure(Tasmota_run_deferred_closure) },
+ { be_const_key(publish, -1), be_const_func(l_publish) },
+ { be_const_key(try_rule, 5), be_const_closure(Tasmota_try_rule_closure) },
+ { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) },
+ { be_const_key(get_free_heap, 47), be_const_func(l_getFreeHeap) },
+ { be_const_key(eth, 56), be_const_func(l_eth) },
+ { be_const_key(set_power, -1), be_const_func(l_setpower) },
+ { be_const_key(exec_rules, -1), be_const_closure(Tasmota_exec_rules_closure) },
+ { be_const_key(i2c_enabled, -1), be_const_func(l_i2cenabled) },
+ { be_const_key(chars_in_string, 55), be_const_closure(Tasmota_chars_in_string_closure) },
+ { be_const_key(hs2rgb, -1), be_const_closure(Tasmota_hs2rgb_closure) },
+ { be_const_key(time_str, 0), be_const_closure(Tasmota_time_str_closure) },
+ { be_const_key(set_light, -1), be_const_closure(Tasmota_set_light_closure) },
+ { be_const_key(response_append, 1), be_const_func(l_respAppend) },
+ { be_const_key(gen_cb, -1), be_const_closure(Tasmota_gen_cb_closure) },
+ { be_const_key(remove_driver, 50), be_const_closure(Tasmota_remove_driver_closure) },
+ { be_const_key(event, -1), be_const_closure(Tasmota_event_closure) },
+ { be_const_key(exec_cmd, 2), be_const_closure(Tasmota_exec_cmd_closure) },
+ { be_const_key(rtc, 12), be_const_func(l_rtc) },
+ { be_const_key(read_sensors, -1), be_const_func(l_read_sensors) },
+ { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) },
+ { be_const_key(set_timer, -1), be_const_closure(Tasmota_set_timer_closure) },
+ { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) },
+ { be_const_key(exec_tele, -1), be_const_closure(Tasmota_exec_tele_closure) },
+ { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) },
+ { be_const_key(cmd_res, -1), be_const_var(0) },
+ { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) },
+ { be_const_key(add_driver, 14), be_const_closure(Tasmota_add_driver_closure) },
+ { be_const_key(_timers, -1), be_const_var(1) },
+ { be_const_key(add_rule, -1), be_const_closure(Tasmota_add_rule_closure) },
+ { be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) },
+ { be_const_key(remove_rule, 9), be_const_closure(Tasmota_remove_rule_closure) },
+ { be_const_key(web_send, 16), be_const_func(l_webSend) },
+ { be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) },
+ { be_const_key(remove_timer, 10), be_const_closure(Tasmota_remove_timer_closure) },
+ { be_const_key(memory, 52), be_const_func(l_memory) },
+ { be_const_key(global, 71), be_const_var(2) },
+ { be_const_key(find_op, -1), be_const_closure(Tasmota_find_op_closure) },
+ { be_const_key(yield, 60), be_const_func(l_yield) },
+ { be_const_key(resolvecmnd, -1), be_const_func(l_resolveCmnd) },
+ { be_const_key(get_option, -1), be_const_func(l_getoption) },
+ { be_const_key(kv, 43), be_const_closure(Tasmota_kv_closure) },
+ { be_const_key(wire_scan, -1), be_const_closure(Tasmota_wire_scan_closure) },
+ { be_const_key(wifi, 37), be_const_func(l_wifi) },
+ { be_const_key(_cmd, -1), be_const_func(l_cmd) },
+ { be_const_key(gc, -1), be_const_closure(Tasmota_gc_closure) },
+ { be_const_key(get_power, -1), be_const_func(l_getpower) },
+ { be_const_key(get_light, -1), be_const_closure(Tasmota_get_light_closure) },
+ { be_const_key(time_dump, -1), be_const_func(l_time_dump) },
+ { be_const_key(settings, -1), be_const_var(3) },
+ { be_const_key(cmd, 62), be_const_closure(Tasmota_cmd_closure) },
+ { be_const_key(load, -1), be_const_closure(Tasmota_load_closure) },
+ { be_const_key(strptime, -1), be_const_func(l_strptime) },
+ { be_const_key(_ccmd, -1), be_const_var(4) },
+ { be_const_key(find_key_i, 25), be_const_closure(Tasmota_find_key_i_closure) },
+ { be_const_key(delay, -1), be_const_func(l_delay) },
+ { be_const_key(time_reached, -1), be_const_func(l_timereached) },
+ { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) },
+ { be_const_key(save, 36), be_const_func(l_save) },
+ { be_const_key(millis, -1), be_const_func(l_millis) },
+ { be_const_key(wire2, -1), be_const_var(5) },
+ { be_const_key(wire1, 72), be_const_var(6) },
+ { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) },
+ { be_const_key(scale_uint, 51), be_const_func(l_scaleuint) },
+ { be_const_key(get_switch, -1), be_const_func(l_getswitch) },
+ { be_const_key(_debug_present, -1), be_const_var(7) },
+ { be_const_key(publish_result, -1), be_const_func(l_publish_result) },
+ { be_const_key(_drivers, -1), be_const_var(8) },
+ { be_const_key(add_cmd, -1), be_const_closure(Tasmota_add_cmd_closure) },
+ { be_const_key(strftime, -1), be_const_func(l_strftime) },
+ { be_const_key(log, -1), be_const_func(l_logInfo) },
+ { be_const_key(arch, -1), be_const_func(l_arch) },
+ { be_const_key(resp_cmnd_done, 74), be_const_func(l_respCmndDone) },
+ { be_const_key(_rules, 38), be_const_var(9) },
+ { be_const_key(remove_cmd, -1), be_const_closure(Tasmota_remove_cmd_closure) },
+ { be_const_key(init, -1), be_const_closure(Tasmota_init_closure) },
+ { be_const_key(wd, 53), be_const_var(10) },
+};
+
+static be_define_const_map(
+ be_class_tasmota_map,
+ 77
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_tasmota,
+ 11,
+ NULL,
+ Tasmota
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_onewire.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_onewire.h
new file mode 100644
index 000000000..a2619941b
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_onewire.h
@@ -0,0 +1,28 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_tasmota_onewire_map) {
+ { be_const_key(reset, -1), be_const_func(b_onewire_reset) },
+ { be_const_key(search, 10), be_const_func(b_onewire_search) },
+ { be_const_key(depower, -1), be_const_func(b_onewire_depower) },
+ { be_const_key(init, 2), be_const_func(b_onewire_init) },
+ { be_const_key(deinit, -1), be_const_func(b_onewire_deinit) },
+ { be_const_key(reset_search, -1), be_const_func(b_onewire_reset_search) },
+ { be_const_key(skip, -1), be_const_func(b_onewire_skip) },
+ { be_const_key(_X2Ep, -1), be_const_var(0) },
+ { be_const_key(write, -1), be_const_func(b_onewire_write) },
+ { be_const_key(read, -1), be_const_func(b_onewire_read) },
+ { be_const_key(select, 11), be_const_func(b_onewire_select) },
+ { be_const_key(target_search, -1), be_const_func(b_onewire_target_search) },
+};
+
+static be_define_const_map(
+ be_class_tasmota_onewire_map,
+ 12
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_tasmota_onewire,
+ 1,
+ NULL,
+ OneWire
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_serial.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_serial.h
new file mode 100644
index 000000000..fab58e1f6
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_serial.h
@@ -0,0 +1,47 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_tasmota_serial_map) {
+ { be_const_key(SERIAL_5E2, 3), be_const_int(SERIAL_5E2) },
+ { be_const_key(SERIAL_8E1, -1), be_const_int(SERIAL_8E1) },
+ { be_const_key(SERIAL_8O1, 22), be_const_int(SERIAL_8O1) },
+ { be_const_key(SERIAL_5O1, -1), be_const_int(SERIAL_5O1) },
+ { be_const_key(read, 0), be_const_func(b_serial_read) },
+ { be_const_key(flush, -1), be_const_func(b_serial_flush) },
+ { be_const_key(SERIAL_7E2, -1), be_const_int(SERIAL_7E2) },
+ { be_const_key(SERIAL_5N2, -1), be_const_int(SERIAL_5N2) },
+ { be_const_key(SERIAL_6N2, -1), be_const_int(SERIAL_6N2) },
+ { be_const_key(SERIAL_6E2, -1), be_const_int(SERIAL_6E2) },
+ { be_const_key(available, -1), be_const_func(b_serial_available) },
+ { be_const_key(SERIAL_6N1, 12), be_const_int(SERIAL_6N1) },
+ { be_const_key(SERIAL_7O1, -1), be_const_int(SERIAL_7O1) },
+ { be_const_key(SERIAL_7N1, 14), be_const_int(SERIAL_7N1) },
+ { be_const_key(SERIAL_6O1, -1), be_const_int(SERIAL_6O1) },
+ { be_const_key(SERIAL_6E1, -1), be_const_int(SERIAL_6E1) },
+ { be_const_key(write, -1), be_const_func(b_serial_write) },
+ { be_const_key(SERIAL_8O2, -1), be_const_int(SERIAL_8O2) },
+ { be_const_key(SERIAL_5O2, 24), be_const_int(SERIAL_5O2) },
+ { be_const_key(SERIAL_5E1, 26), be_const_int(SERIAL_5E1) },
+ { be_const_key(deinit, -1), be_const_func(b_serial_deinit) },
+ { be_const_key(SERIAL_5N1, -1), be_const_int(SERIAL_5N1) },
+ { be_const_key(SERIAL_8N1, 1), be_const_int(SERIAL_8N1) },
+ { be_const_key(SERIAL_7E1, -1), be_const_int(SERIAL_7E1) },
+ { be_const_key(SERIAL_8N2, -1), be_const_int(SERIAL_8N2) },
+ { be_const_key(_X2Ep, 8), be_const_var(0) },
+ { be_const_key(SERIAL_8E2, -1), be_const_int(SERIAL_8E2) },
+ { be_const_key(SERIAL_7O2, -1), be_const_int(SERIAL_7O2) },
+ { be_const_key(SERIAL_7N2, -1), be_const_int(SERIAL_7N2) },
+ { be_const_key(init, -1), be_const_func(b_serial_init) },
+ { be_const_key(SERIAL_6O2, 9), be_const_int(SERIAL_6O2) },
+};
+
+static be_define_const_map(
+ be_class_tasmota_serial_map,
+ 31
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_tasmota_serial,
+ 1,
+ NULL,
+ serial
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_wire.h b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_wire.h
new file mode 100644
index 000000000..be34d40b0
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_tasmota_wire.h
@@ -0,0 +1,31 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_tasmota_wire_map) {
+ { be_const_key(init, -1), be_const_func(b_wire_init) },
+ { be_const_key(_available, -1), be_const_func(b_wire_available) },
+ { be_const_key(bus, -1), be_const_var(0) },
+ { be_const_key(read_bytes, -1), be_const_closure(read_bytes_closure) },
+ { be_const_key(_request_from, -1), be_const_func(b_wire_requestfrom) },
+ { be_const_key(detect, -1), be_const_func(b_wire_detect) },
+ { be_const_key(scan, 2), be_const_func(b_wire_scan) },
+ { be_const_key(enabled, -1), be_const_func(b_wire_enabled) },
+ { be_const_key(_write, 13), be_const_func(b_wire_write) },
+ { be_const_key(read, -1), be_const_func(b_wire_validread) },
+ { be_const_key(_end_transmission, 8), be_const_func(b_wire_endtransmission) },
+ { be_const_key(_begin_transmission, -1), be_const_func(b_wire_begintransmission) },
+ { be_const_key(write_bytes, 7), be_const_closure(write_bytes_closure) },
+ { be_const_key(_read, -1), be_const_func(b_wire_read) },
+ { be_const_key(write, -1), be_const_func(b_wire_validwrite) },
+};
+
+static be_define_const_map(
+ be_class_tasmota_wire_map,
+ 15
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_tasmota_wire,
+ 1,
+ NULL,
+ Wire
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_tcpclient.h b/lib/libesp32/berry/generate/be_fixed_be_class_tcpclient.h
new file mode 100644
index 000000000..72bdbffb4
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_tcpclient.h
@@ -0,0 +1,26 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_tcpclient_map) {
+ { be_const_key(write, 8), be_const_func(wc_tcp_write) },
+ { be_const_key(close, -1), be_const_func(wc_tcp_close) },
+ { be_const_key(connected, 3), be_const_func(wc_tcp_connected) },
+ { be_const_key(deinit, -1), be_const_func(wc_tcp_deinit) },
+ { be_const_key(_X2Ew, 0), be_const_var(0) },
+ { be_const_key(init, -1), be_const_func(wc_tcp_init) },
+ { be_const_key(readbytes, -1), be_const_func(wc_tcp_readbytes) },
+ { be_const_key(connect, -1), be_const_func(wc_tcp_connect) },
+ { be_const_key(available, -1), be_const_func(wc_tcp_available) },
+ { be_const_key(read, -1), be_const_func(wc_tcp_read) },
+};
+
+static be_define_const_map(
+ be_class_tcpclient_map,
+ 10
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_tcpclient,
+ 1,
+ NULL,
+ tcpclient
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_webclient.h b/lib/libesp32/berry/generate/be_fixed_be_class_webclient.h
new file mode 100644
index 000000000..75c369e7d
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_be_class_webclient.h
@@ -0,0 +1,32 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(be_class_webclient_map) {
+ { be_const_key(close, -1), be_const_func(wc_close) },
+ { be_const_key(get_string, 5), be_const_func(wc_getstring) },
+ { be_const_key(_X2Ew, 11), be_const_var(0) },
+ { be_const_key(_X2Ep, 13), be_const_var(1) },
+ { be_const_key(add_header, 10), be_const_func(wc_addheader) },
+ { be_const_key(url_encode, -1), be_const_func(wc_urlencode) },
+ { be_const_key(POST, -1), be_const_func(wc_POST) },
+ { be_const_key(GET, 6), be_const_func(wc_GET) },
+ { be_const_key(deinit, -1), be_const_func(wc_deinit) },
+ { be_const_key(get_size, -1), be_const_func(wc_getsize) },
+ { be_const_key(set_timeouts, -1), be_const_func(wc_set_timeouts) },
+ { be_const_key(set_auth, -1), be_const_func(wc_set_auth) },
+ { be_const_key(set_useragent, -1), be_const_func(wc_set_useragent) },
+ { be_const_key(init, 0), be_const_func(wc_init) },
+ { be_const_key(begin, -1), be_const_func(wc_begin) },
+ { be_const_key(write_file, -1), be_const_func(wc_writefile) },
+};
+
+static be_define_const_map(
+ be_class_webclient_map,
+ 16
+);
+
+BE_EXPORT_VARIABLE be_define_const_class(
+ be_class_webclient,
+ 2,
+ NULL,
+ webclient
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_cb.h b/lib/libesp32/berry/generate/be_fixed_cb.h
new file mode 100644
index 000000000..ef458f363
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_cb.h
@@ -0,0 +1,18 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libcb_map) {
+ { be_const_key(get_cb_list, -1), be_const_func(be_cb_get_cb_list) },
+ { be_const_key(gen_cb, -1), be_const_func(be_cb_gen_cb) },
+};
+
+static be_define_const_map(
+ m_libcb_map,
+ 2
+);
+
+static be_define_const_module(
+ m_libcb,
+ "cb"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(cb);
diff --git a/lib/libesp32/berry/generate/be_fixed_debug.h b/lib/libesp32/berry/generate/be_fixed_debug.h
new file mode 100644
index 000000000..b7b396a35
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_debug.h
@@ -0,0 +1,22 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libdebug_map) {
+ { be_const_key(counters, 3), be_const_func(m_counters) },
+ { be_const_key(traceback, -1), be_const_func(m_traceback) },
+ { be_const_key(attrdump, 0), be_const_func(m_attrdump) },
+ { be_const_key(calldepth, 5), be_const_func(m_calldepth) },
+ { be_const_key(top, -1), be_const_func(m_top) },
+ { be_const_key(codedump, -1), be_const_func(m_codedump) },
+};
+
+static be_define_const_map(
+ m_libdebug_map,
+ 6
+);
+
+static be_define_const_module(
+ m_libdebug,
+ "debug"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(debug);
diff --git a/lib/libesp32/berry/generate/be_fixed_flash.h b/lib/libesp32/berry/generate/be_fixed_flash.h
new file mode 100644
index 000000000..4909e0fe6
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_flash.h
@@ -0,0 +1,19 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libflash_map) {
+ { be_const_key(read, -1), be_const_func(p_flash_read) },
+ { be_const_key(erase, -1), be_const_func(p_flash_erase) },
+ { be_const_key(write, -1), be_const_func(p_flash_write) },
+};
+
+static be_define_const_map(
+ m_libflash_map,
+ 3
+);
+
+static be_define_const_module(
+ m_libflash,
+ "flash"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(flash);
diff --git a/lib/libesp32/berry/generate/be_fixed_gc.h b/lib/libesp32/berry/generate/be_fixed_gc.h
new file mode 100644
index 000000000..401c77b53
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_gc.h
@@ -0,0 +1,18 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libgc_map) {
+ { be_const_key(allocated, -1), be_const_func(m_allocated) },
+ { be_const_key(collect, -1), be_const_func(m_collect) },
+};
+
+static be_define_const_map(
+ m_libgc_map,
+ 2
+);
+
+static be_define_const_module(
+ m_libgc,
+ "gc"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(gc);
diff --git a/lib/libesp32/berry/generate/be_fixed_global.h b/lib/libesp32/berry/generate/be_fixed_global.h
new file mode 100644
index 000000000..31e615b88
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_global.h
@@ -0,0 +1,19 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libglobal_map) {
+ { be_const_key(member, -1), be_const_func(m_findglobal) },
+ { be_const_key(setmember, 0), be_const_func(m_setglobal) },
+ { be_const_key(_X28_X29, -1), be_const_func(m_globals) },
+};
+
+static be_define_const_map(
+ m_libglobal_map,
+ 3
+);
+
+static be_define_const_module(
+ m_libglobal,
+ "global"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(global);
diff --git a/lib/libesp32/berry/generate/be_fixed_gpio.h b/lib/libesp32/berry/generate/be_fixed_gpio.h
new file mode 100644
index 000000000..d87b01643
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_gpio.h
@@ -0,0 +1,23 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libgpio_map) {
+ { be_const_key(pin, -1), be_const_func(gp_pin) },
+ { be_const_key(member, -1), be_const_func(gp_member) },
+ { be_const_key(digital_write, -1), be_const_func(gp_digital_write) },
+ { be_const_key(pin_mode, 1), be_const_func(gp_pin_mode) },
+ { be_const_key(pin_used, -1), be_const_func(gp_pin_used) },
+ { be_const_key(dac_voltage, -1), be_const_func(gp_dac_voltage) },
+ { be_const_key(digital_read, 3), be_const_func(gp_digital_read) },
+};
+
+static be_define_const_map(
+ m_libgpio_map,
+ 7
+);
+
+static be_define_const_module(
+ m_libgpio,
+ "gpio"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(gpio);
diff --git a/lib/libesp32/berry/generate/be_fixed_introspect.h b/lib/libesp32/berry/generate/be_fixed_introspect.h
new file mode 100644
index 000000000..e6d5624f5
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_introspect.h
@@ -0,0 +1,21 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libintrospect_map) {
+ { be_const_key(get, -1), be_const_func(m_findmember) },
+ { be_const_key(toptr, 3), be_const_func(m_toptr) },
+ { be_const_key(set, -1), be_const_func(m_setmember) },
+ { be_const_key(fromptr, -1), be_const_func(m_fromptr) },
+ { be_const_key(members, 1), be_const_func(m_attrlist) },
+};
+
+static be_define_const_map(
+ m_libintrospect_map,
+ 5
+);
+
+static be_define_const_module(
+ m_libintrospect,
+ "introspect"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(introspect);
diff --git a/lib/libesp32/berry/generate/be_fixed_json.h b/lib/libesp32/berry/generate/be_fixed_json.h
new file mode 100644
index 000000000..c0149e316
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_json.h
@@ -0,0 +1,18 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libjson_map) {
+ { be_const_key(dump, -1), be_const_func(m_json_dump) },
+ { be_const_key(load, 0), be_const_func(m_json_load) },
+};
+
+static be_define_const_map(
+ m_libjson_map,
+ 2
+);
+
+static be_define_const_module(
+ m_libjson,
+ "json"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(json);
diff --git a/lib/libesp32/berry/generate/be_fixed_light.h b/lib/libesp32/berry/generate/be_fixed_light.h
new file mode 100644
index 000000000..9540ca804
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_light.h
@@ -0,0 +1,21 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_liblight_map) {
+ { be_const_key(gamma8, 1), be_const_func(l_gamma8) },
+ { be_const_key(get, -1), be_const_func(l_getlight) },
+ { be_const_key(set, 4), be_const_func(l_setlight) },
+ { be_const_key(gamma10, -1), be_const_func(l_gamma10) },
+ { be_const_key(reverse_gamma10, -1), be_const_func(l_rev_gamma10) },
+};
+
+static be_define_const_map(
+ m_liblight_map,
+ 5
+);
+
+static be_define_const_module(
+ m_liblight,
+ "light"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(light);
diff --git a/lib/libesp32/berry/generate/be_fixed_m_builtin.h b/lib/libesp32/berry/generate/be_fixed_m_builtin.h
new file mode 100644
index 000000000..1a803b21b
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_m_builtin.h
@@ -0,0 +1,66 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_builtin_map) {
+ { be_const_key(number, 23), be_const_int(7) },
+ { be_const_key(call, -1), be_const_int(22) },
+ { be_const_key(range, -1), be_const_int(20) },
+ { be_const_key(input, -1), be_const_int(2) },
+ { be_const_key(bytes, 11), be_const_int(21) },
+ { be_const_key(issubclass, -1), be_const_int(14) },
+ { be_const_key(compile, -1), be_const_int(13) },
+ { be_const_key(open, 22), be_const_int(17) },
+ { be_const_key(module, 17), be_const_int(11) },
+ { be_const_key(list, 7), be_const_int(18) },
+ { be_const_key(isinstance, -1), be_const_int(15) },
+ { be_const_key(classname, 20), be_const_int(5) },
+ { be_const_key(size, -1), be_const_int(12) },
+ { be_const_key(real, -1), be_const_int(10) },
+ { be_const_key(int, -1), be_const_int(9) },
+ { be_const_key(__iterator__, 5), be_const_int(16) },
+ { be_const_key(str, -1), be_const_int(8) },
+ { be_const_key(bool, -1), be_const_int(23) },
+ { be_const_key(classof, -1), be_const_int(6) },
+ { be_const_key(assert, -1), be_const_int(0) },
+ { be_const_key(super, -1), be_const_int(3) },
+ { be_const_key(type, 8), be_const_int(4) },
+ { be_const_key(map, -1), be_const_int(19) },
+ { be_const_key(print, -1), be_const_int(1) },
+};
+
+static be_define_const_map(
+ m_builtin_map,
+ 24
+);
+
+static const bvalue __vlist_array[] = {
+ be_const_func(l_assert),
+ be_const_func(l_print),
+ be_const_func(l_input),
+ be_const_func(l_super),
+ be_const_func(l_type),
+ be_const_func(l_classname),
+ be_const_func(l_classof),
+ be_const_func(l_number),
+ be_const_func(l_str),
+ be_const_func(l_int),
+ be_const_func(l_real),
+ be_const_func(l_module),
+ be_const_func(l_size),
+ be_const_func(l_compile),
+ be_const_func(l_issubclass),
+ be_const_func(l_isinstance),
+ be_const_func(l_iterator),
+ be_const_func(be_nfunc_open),
+ be_const_class(be_class_list),
+ be_const_class(be_class_map),
+ be_const_class(be_class_range),
+ be_const_class(be_class_bytes),
+ be_const_func(l_call),
+ be_const_func(l_bool),
+};
+
+static be_define_const_vector(
+ m_builtin_vector,
+ __vlist_array,
+ 24
+);
diff --git a/lib/libesp32/berry/generate/be_fixed_math.h b/lib/libesp32/berry/generate/be_fixed_math.h
new file mode 100644
index 000000000..f36928843
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_math.h
@@ -0,0 +1,43 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libmath_map) {
+ { be_const_key(asin, 7), be_const_func(m_asin) },
+ { be_const_key(isnan, -1), be_const_func(m_isnan) },
+ { be_const_key(sinh, 22), be_const_func(m_sinh) },
+ { be_const_key(cos, -1), be_const_func(m_cos) },
+ { be_const_key(rand, -1), be_const_func(m_rand) },
+ { be_const_key(deg, -1), be_const_func(m_deg) },
+ { be_const_key(log10, 16), be_const_func(m_log10) },
+ { be_const_key(acos, -1), be_const_func(m_acos) },
+ { be_const_key(cosh, -1), be_const_func(m_cosh) },
+ { be_const_key(tanh, 21), be_const_func(m_tanh) },
+ { be_const_key(rad, 11), be_const_func(m_rad) },
+ { be_const_key(abs, -1), be_const_func(m_abs) },
+ { be_const_key(atan2, -1), be_const_func(m_atan2) },
+ { be_const_key(tan, 19), be_const_func(m_tan) },
+ { be_const_key(ceil, 15), be_const_func(m_ceil) },
+ { be_const_key(nan, -1), be_const_real(NAN) },
+ { be_const_key(imin, -1), be_const_int(M_IMIN) },
+ { be_const_key(pow, -1), be_const_func(m_pow) },
+ { be_const_key(atan, -1), be_const_func(m_atan) },
+ { be_const_key(imax, 25), be_const_int(M_IMAX) },
+ { be_const_key(exp, 17), be_const_func(m_exp) },
+ { be_const_key(log, 1), be_const_func(m_log) },
+ { be_const_key(sqrt, -1), be_const_func(m_sqrt) },
+ { be_const_key(srand, -1), be_const_func(m_srand) },
+ { be_const_key(floor, -1), be_const_func(m_floor) },
+ { be_const_key(sin, -1), be_const_func(m_sin) },
+ { be_const_key(pi, 8), be_const_real(M_PI) },
+};
+
+static be_define_const_map(
+ m_libmath_map,
+ 27
+);
+
+static be_define_const_module(
+ m_libmath,
+ "math"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(math);
diff --git a/lib/libesp32/berry/generate/be_fixed_os.h b/lib/libesp32/berry/generate/be_fixed_os.h
new file mode 100644
index 000000000..12eff88ab
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_os.h
@@ -0,0 +1,2 @@
+#include "be_constobj.h"
+
diff --git a/lib/libesp32/berry/generate/be_fixed_path.h b/lib/libesp32/berry/generate/be_fixed_path.h
new file mode 100644
index 000000000..12eff88ab
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_path.h
@@ -0,0 +1,2 @@
+#include "be_constobj.h"
+
diff --git a/lib/libesp32/berry/generate/be_fixed_solidify.h b/lib/libesp32/berry/generate/be_fixed_solidify.h
new file mode 100644
index 000000000..82e81d27b
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_solidify.h
@@ -0,0 +1,17 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libsolidify_map) {
+ { be_const_key(dump, -1), be_const_func(m_dump) },
+};
+
+static be_define_const_map(
+ m_libsolidify_map,
+ 1
+);
+
+static be_define_const_module(
+ m_libsolidify,
+ "solidify"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(solidify);
diff --git a/lib/libesp32/berry/generate/be_fixed_strict.h b/lib/libesp32/berry/generate/be_fixed_strict.h
new file mode 100644
index 000000000..b26e3f566
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_strict.h
@@ -0,0 +1,17 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libstrict_map) {
+ { be_const_key(init, -1), be_const_func(m_init) },
+};
+
+static be_define_const_map(
+ m_libstrict_map,
+ 1
+);
+
+static be_define_const_module(
+ m_libstrict,
+ "strict"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(strict);
diff --git a/lib/libesp32/berry/generate/be_fixed_string.h b/lib/libesp32/berry/generate/be_fixed_string.h
new file mode 100644
index 000000000..9710edd7f
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_string.h
@@ -0,0 +1,27 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libstring_map) {
+ { be_const_key(char, -1), be_const_func(str_char) },
+ { be_const_key(tr, -1), be_const_func(str_tr) },
+ { be_const_key(count, 4), be_const_func(str_count) },
+ { be_const_key(format, 7), be_const_func(str_format) },
+ { be_const_key(escape, -1), be_const_func(str_escape) },
+ { be_const_key(byte, -1), be_const_func(str_byte) },
+ { be_const_key(toupper, -1), be_const_func(str_toupper) },
+ { be_const_key(hex, -1), be_const_func(str_i2hex) },
+ { be_const_key(find, -1), be_const_func(str_find) },
+ { be_const_key(split, 1), be_const_func(str_split) },
+ { be_const_key(tolower, -1), be_const_func(str_tolower) },
+};
+
+static be_define_const_map(
+ m_libstring_map,
+ 11
+);
+
+static be_define_const_module(
+ m_libstring,
+ "string"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(string);
diff --git a/lib/libesp32/berry/generate/be_fixed_sys.h b/lib/libesp32/berry/generate/be_fixed_sys.h
new file mode 100644
index 000000000..91403719c
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_sys.h
@@ -0,0 +1,17 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libsys_map) {
+ { be_const_key(path, -1), be_const_func(m_path) },
+};
+
+static be_define_const_map(
+ m_libsys_map,
+ 1
+);
+
+static be_define_const_module(
+ m_libsys,
+ "sys"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(sys);
diff --git a/lib/libesp32/berry/generate/be_fixed_tasmota_path.h b/lib/libesp32/berry/generate/be_fixed_tasmota_path.h
new file mode 100644
index 000000000..90ae43054
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_tasmota_path.h
@@ -0,0 +1,20 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libpath_map) {
+ { be_const_key(listdir, -1), be_const_func(m_path_listdir) },
+ { be_const_key(last_modified, 2), be_const_func(m_path_last_modified) },
+ { be_const_key(exists, 3), be_const_func(m_path_exists) },
+ { be_const_key(remove, -1), be_const_func(m_path_remove) },
+};
+
+static be_define_const_map(
+ m_libpath_map,
+ 4
+);
+
+static be_define_const_module(
+ m_libpath,
+ "path"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(path);
diff --git a/lib/libesp32/berry/generate/be_fixed_time.h b/lib/libesp32/berry/generate/be_fixed_time.h
new file mode 100644
index 000000000..12eff88ab
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_time.h
@@ -0,0 +1,2 @@
+#include "be_constobj.h"
+
diff --git a/lib/libesp32/berry/generate/be_fixed_webserver.h b/lib/libesp32/berry/generate/be_fixed_webserver.h
new file mode 100644
index 000000000..27f475997
--- /dev/null
+++ b/lib/libesp32/berry/generate/be_fixed_webserver.h
@@ -0,0 +1,31 @@
+#include "be_constobj.h"
+
+static be_define_const_map_slots(m_libwebserver_map) {
+ { be_const_key(state, 5), be_const_func(w_webserver_state) },
+ { be_const_key(member, 9), be_const_func(w_webserver_member) },
+ { be_const_key(content_button, -1), be_const_func(w_webserver_content_button) },
+ { be_const_key(content_start, -1), be_const_func(w_webserver_content_start) },
+ { be_const_key(content_send, -1), be_const_func(w_webserver_content_send) },
+ { be_const_key(content_flush, -1), be_const_func(w_webserver_content_flush) },
+ { be_const_key(redirect, 8), be_const_func(w_webserver_redirect) },
+ { be_const_key(content_send_style, -1), be_const_func(w_webserver_content_send_style) },
+ { be_const_key(arg, -1), be_const_func(w_webserver_arg) },
+ { be_const_key(content_stop, -1), be_const_func(w_webserver_content_stop) },
+ { be_const_key(arg_name, -1), be_const_func(w_webserver_arg_name) },
+ { be_const_key(has_arg, -1), be_const_func(w_webserver_has_arg) },
+ { be_const_key(arg_size, -1), be_const_func(w_webserver_argsize) },
+ { be_const_key(check_privileged_access, 11), be_const_func(w_webserver_check_privileged_access) },
+ { be_const_key(on, 3), be_const_func(w_webserver_on) },
+};
+
+static be_define_const_map(
+ m_libwebserver_map,
+ 15
+);
+
+static be_define_const_module(
+ m_libwebserver,
+ "webserver"
+);
+
+BE_EXPORT_VARIABLE be_define_const_native_module(webserver);
diff --git a/lib/libesp32/berry/include/be_ctypes.h b/lib/libesp32/berry/include/be_ctypes.h
new file mode 100644
index 000000000..d0be5dd9d
--- /dev/null
+++ b/lib/libesp32/berry/include/be_ctypes.h
@@ -0,0 +1,89 @@
+/********************************************************************
+ * Tasmota ctypes mapping headers
+ *******************************************************************/
+#ifndef __BE_CONSTOBJ_H__
+#define __BE_CONSTOBJ_H__
+
+#include "be_constobj.h"
+
+enum {
+ ctypes_i32 = 14,
+ ctypes_i16 = 12,
+ ctypes_i8 = 11,
+ ctypes_u32 = 4,
+ ctypes_u16 = 2,
+ ctypes_u8 = 1,
+
+ // big endian
+ ctypes_be_i32 = -14,
+ ctypes_be_i16 = -12,
+ ctypes_be_i8 = -11,
+ ctypes_be_u32 = -4,
+ ctypes_be_u16 = -2,
+ ctypes_be_u8 = -1,
+
+ // floating point
+ ctypes_float = 5,
+ ctypes_double = 10,
+
+ // pointer
+ ctypes_ptr32 = 9,
+ ctypes_ptr64 = -9,
+
+ ctypes_bf = 0, //bif-field
+};
+
+typedef struct be_ctypes_structure_item_t {
+ const char * name;
+ uint16_t offset_bytes;
+ uint8_t offset_bits : 3;
+ uint8_t len_bits : 5;
+ int8_t type : 5;
+ uint8_t mapping : 3;
+} be_ctypes_structure_item_t;
+
+typedef struct be_ctypes_structure_t {
+ uint16_t size_bytes; /* size in bytes */
+ uint16_t size_elt; /* number of elements */
+ const char **instance_mapping; /* array of instance class names for automatic instanciation of class */
+ const be_ctypes_structure_item_t * items;
+} be_ctypes_structure_t;
+
+typedef struct be_ctypes_class_t {
+ const char * name;
+ const be_ctypes_structure_t * definitions;
+} be_ctypes_class_t;
+
+typedef struct be_ctypes_classes_t {
+ uint16_t size;
+ const char **instance_mapping; /* array of instance class names for automatic instanciation of class */
+ const be_ctypes_class_t * classes;
+} be_ctypes_classes_t;
+
+BE_EXPORT_VARIABLE const bclass be_class_ctypes;
+
+static void ctypes_register_class(bvm *vm, const bclass * ctypes_class, const be_ctypes_structure_t * definitions) {
+ be_pushntvclass(vm, ctypes_class);
+ be_setglobal(vm, str(ctypes_class->name));
+ be_pop(vm, 1);
+}
+
+// Define a sub-class of ctypes with only one member which points to the ctypes defintion
+#define be_define_ctypes_class(_c_name, _def, _super, _name) \
+ be_local_class(_c_name, \
+ 0, \
+ _super, \
+ be_nested_map(1, \
+ ( (struct bmapnode*) &(const bmapnode[]) { \
+ { be_nested_key("_def", 1985022181, 4, -1), be_const_comptr(_def) },\
+ })), \
+ (be_nested_const_str(_name, 0, sizeof(_name)-1)) \
+ )
+
+// list of simple classes, sorted
+typedef struct be_ctypes_class_by_name_t {
+ const char * name;
+ const bclass * cl;
+} be_ctypes_class_by_name_t;
+
+#endif // __BE_CONSTOBJ_H__
diff --git a/lib/libesp32/berry/include/be_lvgl.h b/lib/libesp32/berry/include/be_lvgl.h
new file mode 100644
index 000000000..52b5edc2d
--- /dev/null
+++ b/lib/libesp32/berry/include/be_lvgl.h
@@ -0,0 +1,40 @@
+/********************************************************************
+ * Tasmota LVGL Headers
+ *******************************************************************/
+#ifndef __BE_LVGL_H__
+#define __BE_LVGL_H__
+
+#include "be_constobj.h"
+
+#ifdef USE_LVGL
+
+#include "lvgl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ // table of functions per class
+ typedef struct lvbe_call_c_t {
+ const char * name;
+ void * func;
+ const char * return_type;
+ const char * arg_type;
+ } lvbe_call_c_t;
+
+ // list of classes and function tables
+ typedef struct lvbe_call_c_classes_t {
+ const char * name;
+ const bclass * cl;
+ const lvbe_call_c_t * func_table;
+ size_t size;
+ } lvbe_call_c_classes_t;
+ extern const lvbe_call_c_classes_t lv_classes[];
+ extern const size_t lv_classes_size;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // USE_LVGL
+
+#endif // __BE_LVGL_H__
\ No newline at end of file
diff --git a/lib/libesp32/berry/library.json b/lib/libesp32/berry/library.json
new file mode 100644
index 000000000..705592bd5
--- /dev/null
+++ b/lib/libesp32/berry/library.json
@@ -0,0 +1,30 @@
+{
+ "name":"Berry",
+ "description":"Berry scripting language for Tasmota32",
+ "keywords":"berry, script",
+ "authors":
+ {
+ "name": "Guan Wenliang , ",
+ "maintainer": true
+ },
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/Skiars/berry"
+ },
+ "version": "7.0",
+ "license": "MIT License",
+ "frameworks": "*",
+ "platforms": "*",
+ "build": {
+ "srcFilter": [
+ "+<*.c>",
+ "+<../default/*.c>",
+ "+<../default/*.cpp>",
+ "+<../default/*.hpp>",
+ "+<*.cpp>",
+ "+<*.h>"
+ ],
+ "flags": [ "-I$PROJECT_DIR/tasmota", "-DCOMPILE_BERRY_LIB" ]
+ }
+}
\ No newline at end of file
diff --git a/lib/libesp32/berry/src/be_api.c b/lib/libesp32/berry/src/be_api.c
new file mode 100644
index 000000000..79d5c48ff
--- /dev/null
+++ b/lib/libesp32/berry/src/be_api.c
@@ -0,0 +1,1173 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_vm.h"
+#include "be_func.h"
+#include "be_class.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_var.h"
+#include "be_list.h"
+#include "be_map.h"
+#include "be_parser.h"
+#include "be_debug.h"
+#include "be_exec.h"
+#include "be_strlib.h"
+#include "be_module.h"
+#include "be_gc.h"
+#include
+
+#define retreg(vm) ((vm)->cf->func)
+
+struct solidfuncinfo {
+ const char *name;
+ bclosure *function;
+};
+
+static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib)
+{
+ if (lib) {
+ while (lib->name) {
+ bstring *s = be_newstr(vm, lib->name);
+ if (lib->function) { /* method */
+ be_prim_method_bind(vm, c, s, lib->function);
+ } else {
+ be_member_bind(vm, c, s, btrue); /* member */
+ }
+ ++lib;
+ }
+ if (lib->function == (bntvfunc) BE_CLOSURE) {
+ /* next section is closures */
+ struct solidfuncinfo *slib = (struct solidfuncinfo*)++lib;
+ while (slib->name) {
+ if (slib->function) { /* method */
+ bstring *s = be_newstr(vm, slib->name);
+ be_closure_method_bind(vm, c, s, slib->function);
+ }
+ ++slib;
+ }
+ }
+ be_map_compact(vm, c->members); /* clear space */
+ }
+}
+
+static bclass* class_auto_make(bvm *vm, bstring *name, const bnfuncinfo *lib)
+{
+ bvalue key, *res;
+ var_setobj(&key, BE_COMPTR, (void*)lib);
+ if (vm->ntvclass == NULL) {
+ vm->ntvclass = be_map_new(vm);
+ }
+ res = be_map_find(vm, vm->ntvclass, &key);
+ if (res == NULL || !var_isclass(res)) {
+ bclass *c;
+ /* insert class to native class table */
+ res = be_map_insert(vm, vm->ntvclass, &key, NULL);
+ var_setnil(res); /* must be initialized to ensure correct GC */
+ c = be_newclass(vm, name, NULL);
+ var_setclass(res, c);
+ class_init(vm, c, lib); /* bind members */
+ return c;
+ }
+ return var_toobj(res);
+}
+
+BERRY_API void be_regfunc(bvm *vm, const char *name, bntvfunc f)
+{
+ bvalue *var;
+ bstring *s = be_newstr(vm, name);
+#if !BE_USE_PRECOMPILED_OBJECT
+ int idx = be_builtin_find(vm, s);
+ be_assert(idx == -1);
+ if (idx == -1) { /* new function */
+ idx = be_builtin_new(vm, s);
+#else
+ int idx = be_global_find(vm, s);
+ be_assert(idx < be_builtin_count(vm));
+ if (idx < be_builtin_count(vm)) { /* new function */
+ idx = be_global_new(vm, s);
+#endif
+ var = be_global_var(vm, idx);
+ var_setntvfunc(var, f);
+ } /* error case, do nothing */
+}
+
+BERRY_API void be_regclass(bvm *vm, const char *name, const bnfuncinfo *lib)
+{
+ bvalue *var;
+ bstring *s = be_newstr(vm, name);
+#if !BE_USE_PRECOMPILED_OBJECT
+ int idx = be_builtin_find(vm, s);
+ be_assert(idx == -1);
+ if (idx == -1) { /* new function */
+ idx = be_builtin_new(vm, s);
+#else
+ int idx = be_global_find(vm, s);
+ be_assert(idx < be_builtin_count(vm));
+ if (idx < be_builtin_count(vm)) { /* new function */
+ idx = be_global_new(vm, s);
+#endif
+ var = be_global_var(vm, idx);
+ var_setclass(var, class_auto_make(vm, s, lib));
+ } /* error case, do nothing */
+}
+
+BERRY_API int be_top(bvm *vm)
+{
+ return cast_int(vm->top - vm->reg);
+}
+
+BERRY_API void be_pop(bvm *vm, int n)
+{
+ be_assert(n <= vm->top - vm->reg);
+ be_stackpop(vm, n);
+}
+
+BERRY_API int be_absindex(bvm *vm, int index)
+{
+ if (index > 0) {
+ return index;
+ }
+ be_assert(vm->reg <= vm->top + index);
+ return cast_int(vm->top + index - vm->reg + 1);
+}
+
+BERRY_API bbool be_isnil(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isnil(v);
+}
+
+BERRY_API bbool be_isbool(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isbool(v);
+}
+
+BERRY_API bbool be_isint(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isint(v);
+}
+
+BERRY_API bbool be_isreal(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isreal(v);
+}
+
+BERRY_API bbool be_isnumber(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isnumber(v);
+}
+
+BERRY_API bbool be_isstring(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isstr(v);
+}
+
+BERRY_API bbool be_isclosure(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isclosure(v);
+}
+
+BERRY_API bbool be_isntvclos(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isntvclos(v);
+}
+
+BERRY_API bbool be_isfunction(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isfunction(v);
+}
+
+BERRY_API bbool be_isproto(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isproto(v);
+}
+
+BERRY_API bbool be_isclass(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isclass(v);
+}
+
+BERRY_API bbool be_isinstance(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_isinstance(v);
+}
+
+BERRY_API bbool be_ismodule(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_ismodule(v);
+}
+
+BERRY_API bbool be_islist(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_islist(v);
+}
+
+BERRY_API bbool be_ismap(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_ismap(v);
+}
+
+BERRY_API bbool be_iscomptr(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_istype(v, BE_COMPTR);
+}
+
+BERRY_API bbool be_iscomobj(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_istype(v, BE_COMOBJ);
+}
+
+BERRY_API bint be_toint(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_toint(v);
+}
+
+BERRY_API breal be_toreal(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_isreal(v)) {
+ return var_toreal(v);
+ }
+ if (var_isint(v)) {
+ return cast(breal, var_toint(v));
+ }
+ return cast(breal, 0.0);
+}
+
+BERRY_API int be_toindex(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return var_toidx(v);
+}
+
+BERRY_API bbool be_tobool(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return be_value2bool(vm, v);
+}
+
+BERRY_API const char* be_tostring(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (!var_isstr(v)) {
+ be_val2str(vm, index);
+ v = be_indexof(vm, index);
+ }
+ return str(var_tostr(v));
+}
+
+BERRY_API void* be_tocomptr(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_istype(v, BE_COMPTR)) {
+ return var_toobj(v);
+ }
+ if (var_istype(v, BE_COMOBJ)) {
+ bcommomobj *obj = var_toobj(v);
+ return obj->data;
+ }
+ return NULL;
+}
+
+BERRY_API void be_moveto(bvm *vm, int from, int to)
+{
+ bvalue *src = be_indexof(vm, from);
+ bvalue *dst = be_indexof(vm, to);
+ var_setval(dst, src);
+}
+
+BERRY_API void be_pushnil(bvm *vm)
+{
+ bvalue *reg = be_incrtop(vm);
+ var_setnil(reg);
+}
+
+BERRY_API void be_pushbool(bvm *vm, int b)
+{
+ bvalue *reg = be_incrtop(vm);
+ var_setbool(reg, b != bfalse);
+}
+
+BERRY_API void be_pushint(bvm *vm, bint i)
+{
+ bvalue *reg = be_incrtop(vm);
+ var_setint(reg, i);
+}
+
+BERRY_API void be_pushreal(bvm *vm, breal r)
+{
+ bvalue *reg = be_incrtop(vm);
+ var_setreal(reg, r);
+}
+
+BERRY_API void be_pushstring(bvm *vm, const char *str)
+{
+ /* to create a string and then push the top registor,
+ * otherwise the GC may crash due to uninitialized values.
+ **/
+ bstring *s = be_newstr(vm, str);
+ bvalue *reg = be_incrtop(vm);
+ be_assert(reg < vm->stacktop);
+ var_setstr(reg, s);
+}
+
+BERRY_API void be_pushnstring(bvm *vm, const char *str, size_t n)
+{
+ /* to create a string and then push the top registor,
+ * otherwise the GC may crash due to uninitialized values.
+ **/
+ bstring *s = be_newstrn(vm, str, n);
+ bvalue *reg = be_incrtop(vm);
+ var_setstr(reg, s);
+}
+
+BERRY_API const char* be_pushfstring(bvm *vm, const char *format, ...)
+{
+ const char* s;
+ va_list arg_ptr;
+ va_start(arg_ptr, format);
+ s = be_pushvfstr(vm, format, arg_ptr);
+ va_end(arg_ptr);
+ return s;
+}
+
+BERRY_API void* be_pushbuffer(bvm *vm, size_t size)
+{
+ bstring *s = be_newlongstr(vm, NULL, size);
+ bvalue *reg = be_incrtop(vm);
+ var_setstr(reg, s);
+ return (void*)str(s);
+}
+
+BERRY_API void be_pushvalue(bvm *vm, int index)
+{
+ bvalue *reg = vm->top;
+ var_setval(reg, be_indexof(vm, index));
+ be_incrtop(vm);
+}
+
+BERRY_API void be_pushclosure(bvm *vm, void *cl)
+{
+ bvalue *reg = be_incrtop(vm);
+ bclosure * closure = (bclosure*) cl;
+ var_setclosure(reg, closure);
+}
+
+BERRY_API void be_pushntvclosure(bvm *vm, bntvfunc f, int nupvals)
+{
+ /* to create a native closure and then push the top registor,
+ * otherwise the GC may crash due to uninitialized values.
+ **/
+ bntvclos *cl = be_newntvclosure(vm, f, nupvals);
+ bvalue *top = be_incrtop(vm);
+ var_setntvclos(top, cl);
+}
+
+BERRY_API void be_pushntvfunction(bvm *vm, bntvfunc f)
+{
+ bvalue *top = be_incrtop(vm);
+ var_setntvfunc(top, f);
+}
+
+BERRY_API void be_pushclass(bvm *vm, const char *name, const bnfuncinfo *lib)
+{
+ bclass *c;
+ bstring *s = be_newstr(vm, name);
+ bvalue *dst = be_incrtop(vm);
+ var_setstr(dst, s);
+ c = class_auto_make(vm, s, lib);
+ var_setclass(vm->top - 1, c);
+}
+
+BERRY_API void be_pushntvclass(bvm *vm, const struct bclass * c)
+{
+ bvalue *top = be_incrtop(vm);
+ var_setclass(top, (bclass *) c);
+}
+
+BERRY_API void be_pushcomptr(bvm *vm, void *ptr)
+{
+ bvalue *top = be_incrtop(vm);
+ var_setobj(top, BE_COMPTR, ptr);
+}
+
+BERRY_API void be_remove(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ bvalue *top = --vm->top;
+ while (v < top) {
+ *v = v[1];
+ ++v;
+ }
+}
+
+BERRY_API void be_strconcat(bvm *vm, int index)
+{
+ bstring *s;
+ bvalue *dst = be_indexof(vm, index);
+ bvalue *src = be_indexof(vm, -1);
+ be_assert(var_isstr(src) && var_isstr(dst));
+ s = be_strcat(vm, var_tostr(dst), var_tostr(src));
+ var_setstr(dst, s);
+}
+
+BERRY_API bbool be_setsuper(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ bvalue *top = be_indexof(vm, -1);
+ if (var_isclass(v) && var_isclass(top)) {
+ bclass *c = var_toobj(v);
+ if (!gc_isconst(c)) {
+ bclass *super = var_toobj(top);
+ be_class_setsuper(c, super);
+ return btrue;
+ }
+ }
+ return bfalse;
+}
+
+BERRY_API void be_getsuper(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ bvalue *top = be_incrtop(vm);
+ if (var_isclass(v)) {
+ bclass *c = var_toobj(v);
+ c = be_class_super(c);
+ if (c) {
+ var_setclass(top, c);
+ return;
+ }
+ } else if (var_isinstance(v)) {
+ binstance *o = var_toobj(v);
+ o = be_instance_super(o);
+ if (o) {
+ var_setinstance(top, o);
+ return;
+ }
+ }
+ var_setnil(top);
+}
+
+static bclass* _getclass(bvalue *v)
+{
+ if (var_isinstance(v)) {
+ binstance *ins = var_toobj(v);
+ return be_instance_class(ins);
+ }
+ return var_isclass(v) ? var_toobj(v) : NULL;
+}
+
+BERRY_API bbool be_isderived(bvm *vm, int index)
+{
+ bclass *sup = _getclass(be_indexof(vm, -1));
+ if (sup) {
+ bclass *c = _getclass(be_indexof(vm, index));
+ while (c && c != sup)
+ c = be_class_super(c);
+ return c != NULL;
+ }
+ return bfalse;
+}
+
+BERRY_API const char *be_typename(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ return be_vtype2str(v);
+}
+
+BERRY_API const char *be_classname(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_isclass(v)) {
+ bclass *c = var_toobj(v);
+ return str(be_class_name(c));
+ }
+ if (var_isinstance(v)) {
+ binstance *i = var_toobj(v);
+ return str(be_instance_name(i));
+ }
+ return NULL;
+}
+
+BERRY_API bbool be_classof(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_isinstance(v)) {
+ bvalue *top = be_incrtop(vm);
+ binstance *ins = var_toobj(v);
+ var_setclass(top, be_instance_class(ins));
+ return btrue;
+ }
+ return bfalse;
+}
+
+BERRY_API int be_strlen(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_isstr(v)) {
+ return str_len(var_tostr(v));
+ }
+ return 0;
+}
+
+BERRY_API void be_newlist(bvm *vm)
+{
+ blist *list = be_list_new(vm);
+ bvalue *top = be_incrtop(vm);
+ var_setlist(top, list);
+}
+
+BERRY_API void be_newmap(bvm *vm)
+{
+ bmap *map = be_map_new(vm);
+ bvalue *top = be_incrtop(vm);
+ var_setobj(top, BE_MAP, map);
+}
+
+BERRY_API void be_newmodule(bvm *vm)
+{
+ bmodule *mod = be_module_new(vm);
+ bvalue *top = be_incrtop(vm);
+ var_setobj(top, BE_MODULE, mod);
+}
+
+BERRY_API void be_newobject(bvm *vm, const char *name)
+{
+ be_getbuiltin(vm, name);
+ be_call(vm, 0);
+ be_getmember(vm, -1, ".p");
+}
+
+BERRY_API bbool be_setname(bvm *vm, int index, const char *name)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_ismodule(v)) {
+ bmodule *module = var_toobj(v);
+ return be_module_setname(module, be_newstr(vm, name));
+ }
+ return bfalse;
+}
+
+BERRY_API bbool be_getglobal(bvm *vm, const char *name)
+{
+ int idx = be_global_find(vm, be_newstr(vm, name));
+ bvalue *top = be_incrtop(vm);
+ if (idx > -1) {
+ *top = *be_global_var(vm, idx);
+ return btrue;
+ }
+ var_setnil(top);
+ return bfalse;
+}
+
+BERRY_API void be_setglobal(bvm *vm, const char *name)
+{
+ int idx;
+ bstring *s = be_newstr(vm, name);
+ bvalue *v = be_incrtop(vm);
+ var_setstr(v, s);
+ idx = be_global_new(vm, s);
+ v = be_global_var(vm, idx);
+ *v = *be_indexof(vm, -2);
+ be_stackpop(vm, 1);
+}
+
+BERRY_API bbool be_getbuiltin(bvm *vm, const char *name)
+{
+ int idx = be_builtin_find(vm, be_newstr(vm, name));
+ bvalue *top = be_incrtop(vm);
+ if (idx > -1) {
+ *top = *be_global_var(vm, idx);
+ return btrue;
+ }
+ var_setnil(top);
+ return bfalse;
+}
+
+BERRY_API bbool be_setmember(bvm *vm, int index, const char *k)
+{
+ bvalue *o = be_indexof(vm, index);
+ bvalue *v = be_indexof(vm, -1);
+ if (var_isinstance(o)) {
+ bstring *key = be_newstr(vm, k);
+ binstance *obj = var_toobj(o);
+ return be_instance_setmember(vm, obj, key, v);
+ } else if (var_ismodule(o)) {
+ bstring *key = be_newstr(vm, k);
+ bmodule *mod = var_toobj(o);
+ return be_module_setmember(vm, mod, key, v);
+ }
+ return bfalse;
+}
+
+BERRY_API bbool be_copy(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ bvalue *top = be_incrtop(vm);
+ if (var_type(v) == BE_LIST) {
+ blist *list = be_list_copy(vm, var_toobj(v));
+ var_setlist(top, list)
+ return btrue;
+ }
+ var_setnil(top);
+ return bfalse;
+}
+
+/* `onlyins` limits the search to instance, and discards module. Makes sure getmethod does not return anything for module. */
+static int ins_member(bvm *vm, int index, const char *k, bbool onlyins)
+{
+ int type = BE_NIL;
+ bvalue *o = be_indexof(vm, index);
+ bvalue *top = be_incrtop(vm);
+ var_setnil(top);
+ if (var_isinstance(o)) {
+ binstance *obj = var_toobj(o);
+ type = be_instance_member(vm, obj, be_newstr(vm, k), top);
+ } else if (var_isclass(o) && !onlyins) {
+ bclass *cl = var_toobj(o);
+ type = be_class_member(vm, cl, be_newstr(vm, k), top);
+ } else if (var_ismodule(o) && !onlyins) {
+ bmodule *module = var_toobj(o);
+ type = be_module_attr(vm, module, be_newstr(vm, k), top);
+ }
+ if (type == BE_NONE) {
+ type = BE_NIL;
+ }
+ return type;
+}
+
+BERRY_API bbool be_getmember(bvm *vm, int index, const char *k)
+{
+ return ins_member(vm, index, k, bfalse) != BE_NIL;
+}
+
+BERRY_API bbool be_getmethod(bvm *vm, int index, const char *k)
+{
+ return basetype(ins_member(vm, index, k, btrue)) == BE_FUNCTION;
+}
+
+BERRY_API bbool be_getindex(bvm *vm, int index)
+{
+ bvalue *o = be_indexof(vm, index);
+ bvalue *k = be_indexof(vm, -1);
+ bvalue *dst = be_incrtop(vm);
+ switch (var_type(o)) {
+ case BE_LIST:
+ if (var_isint(k)) {
+ blist *list = cast(blist*, var_toobj(o));
+ int idx = var_toidx(k);
+ bvalue *src = be_list_index(list, idx);
+ if (src) {
+ var_setval(dst, src);
+ return btrue;
+ }
+ }
+ break;
+ case BE_MAP:
+ if (!var_isnil(k)) {
+ bmap *map = cast(bmap*, var_toobj(o));
+ bvalue *src = be_map_find(vm, map, k);
+ if (src) {
+ var_setval(dst, src);
+ return btrue;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ var_setnil(dst);
+ return bfalse;
+}
+
+static bvalue* list_setindex(blist *list, bvalue *key)
+{
+ int idx = var_toidx(key);
+ if (idx < be_list_count(list)) {
+ return be_list_at(list, idx);
+ }
+ return NULL;
+}
+
+BERRY_API bbool be_setindex(bvm *vm, int index)
+{
+ bvalue *dst = NULL;
+ bvalue *o = be_indexof(vm, index);
+ bvalue *k = be_indexof(vm, -2);
+ bvalue *v = be_indexof(vm, -1);
+ switch (var_type(o)) {
+ case BE_LIST:
+ if (var_isint(k)) {
+ blist *list = var_toobj(o);
+ dst = list_setindex(list, k);
+ }
+ break;
+ case BE_MAP:
+ if (!var_isnil(k)) {
+ bmap *map = var_toobj(o);
+ dst = be_map_insert(vm, map, k, NULL);
+ }
+ break;
+ default:
+ break;
+ }
+ if (dst) {
+ var_setval(dst, v);
+ return btrue;
+ }
+ return bfalse;
+}
+
+BERRY_API void be_getupval(bvm *vm, int index, int pos)
+{
+ bvalue *f = index ? be_indexof(vm, index) : vm->cf->func;
+ bvalue *uv, *top = be_incrtop(vm);
+ be_assert(var_istype(f, BE_NTVCLOS));
+ if (var_istype(f, BE_NTVCLOS)) {
+ bntvclos *nf = var_toobj(f);
+ be_assert(pos >= 0 && pos < nf->nupvals);
+ uv = be_ntvclos_upval(nf, pos)->value;
+ var_setval(top, uv);
+ } else {
+ var_setnil(top);
+ }
+}
+
+BERRY_API bbool be_setupval(bvm *vm, int index, int pos)
+{
+ bvalue *f = index ? be_indexof(vm, index) : vm->cf->func;
+ bvalue *uv, *v = be_indexof(vm, -1);
+ be_assert(var_istype(f, BE_NTVCLOS));
+ if (var_istype(f, BE_NTVCLOS)) {
+ bntvclos *nf = var_toobj(f);
+ be_assert(pos >= 0 && pos < nf->nupvals);
+ uv = be_ntvclos_upval(nf, pos)->value;
+ var_setval(uv, v);
+ return btrue;
+ }
+ return bfalse;
+}
+
+BERRY_API int be_data_size(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_islist(v)) {
+ blist *list = var_toobj(v);
+ return be_list_count(list);
+ } else if (var_ismap(v)) {
+ bmap *map = cast(bmap*, var_toobj(v));
+ return be_map_count(map);
+ }
+ return -1;
+}
+
+BERRY_API void be_data_push(bvm *vm, int index)
+{
+ bvalue *o = be_indexof(vm, index);
+ bvalue *v = be_indexof(vm, -1);
+ if (var_islist(o)) {
+ blist *list = var_toobj(o);
+ be_list_push(vm, list, v);
+ }
+}
+
+BERRY_API bbool be_data_insert(bvm *vm, int index)
+{
+ bvalue *o = be_indexof(vm, index);
+ bvalue *k = be_indexof(vm, -2);
+ bvalue *v = be_indexof(vm, -1);
+ switch (var_type(o)) {
+ case BE_MAP:
+ if (!var_isnil(k)) {
+ bmap *map = cast(bmap*, var_toobj(o));
+ bvalue *dst = be_map_find(vm, map, k);
+ if (dst == NULL) {
+ return be_map_insert(vm, map, k, v) != NULL;
+ }
+ }
+ break;
+ case BE_LIST:
+ if (var_isint(k)) {
+ blist *list = cast(blist*, var_toobj(o));
+ return be_list_insert(vm, list, var_toidx(k), v) != NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ return bfalse;
+}
+
+BERRY_API bbool be_data_remove(bvm *vm, int index)
+{
+ bvalue *o = be_indexof(vm, index);
+ bvalue *k = be_indexof(vm, -1);
+ switch (var_type(o)) {
+ case BE_MAP:
+ if (!var_isnil(k)) {
+ bmap *map = cast(bmap*, var_toobj(o));
+ return be_map_remove(vm, map, k);
+ }
+ break;
+ case BE_LIST:
+ if (var_isint(k)) {
+ blist *list = cast(blist*, var_toobj(o));
+ return be_list_remove(vm, list, var_toidx(k));
+ }
+ break;
+ default:
+ break;
+ }
+ return bfalse;
+}
+
+BERRY_API bbool be_data_merge(bvm *vm, int index)
+{
+ bvalue *a = be_indexof(vm, index);
+ bvalue *b = be_indexof(vm, -1);
+ if (var_islist(a) && var_islist(b)) {
+ blist *dst = var_toobj(a), *src = var_toobj(b);
+ be_list_merge(vm, dst, src);
+ return btrue;
+ }
+ return bfalse;
+}
+
+BERRY_API void be_data_resize(bvm *vm, int index)
+{
+ bvalue *o = be_indexof(vm, index);
+ bvalue *v = be_indexof(vm, -1);
+ if (var_islist(o)) {
+ blist *list = var_toobj(o);
+ if (var_isint(v)) {
+ be_list_resize(vm, list, var_toidx(v));
+ }
+ }
+}
+
+BERRY_API void be_data_reverse(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_type(v) == BE_LIST) {
+ be_list_reverse(var_toobj(v));
+ }
+}
+
+BERRY_API bbool be_pushiter(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ if (var_ismap(v)) {
+ bvalue *iter = be_incrtop(vm);
+ var_setobj(iter, BE_COMPTR, NULL);
+ return btrue;
+ } else if (var_islist(v)) {
+ blist *list = var_toobj(v);
+ bvalue *iter = be_incrtop(vm);
+ var_setobj(iter, BE_COMPTR, be_list_data(list) - 1);
+ return btrue;
+ }
+ return bfalse;
+}
+
+static int list_next(bvm *vm)
+{
+ bvalue *iter = be_indexof(vm, -1);
+ bvalue *next, *dst = be_incrtop(vm);
+ next = cast(bvalue*, var_toobj(iter)) + 1;
+ var_setobj(iter, BE_COMPTR, next);
+ var_setval(dst, next);
+ return 1;
+}
+
+static bbool list_hasnext(bvm *vm, bvalue *v)
+{
+ bvalue *next;
+ bvalue *iter = be_indexof(vm, -1);
+ blist *obj = var_toobj(v);
+ next = cast(bvalue*, var_toobj(iter)) + 1;
+ return next >= be_list_data(obj) && next < be_list_end(obj);
+}
+
+static int map_next(bvm *vm, bvalue *v)
+{
+ bmapiter iter;
+ bmapnode *entry;
+ bvalue *dst = vm->top;
+ bvalue *itvar = be_indexof(vm, -1);
+ iter = var_toobj(itvar);
+ entry = be_map_next(var_toobj(v), &iter);
+ var_setobj(itvar, BE_COMPTR, iter);
+ if (entry) {
+ be_map_key2value(dst, entry);
+ var_setval(dst + 1, &entry->value);
+ vm->top += 2;
+ return 2;
+ }
+ return 0;
+}
+
+static bbool map_hasnext(bvm *vm, bvalue *v)
+{
+ bvalue *node = be_indexof(vm, -1);
+ bmapiter iter = var_toobj(node);
+ return be_map_next(var_toobj(v), &iter) != NULL;
+}
+
+BERRY_API int be_iter_next(bvm *vm, int index)
+{
+ bvalue *o = be_indexof(vm, index);
+ if (var_islist(o)) {
+ return list_next(vm);
+ } else if (var_ismap(o)) {
+ return map_next(vm, o);
+ }
+ return 0;
+}
+
+BERRY_API bbool be_iter_hasnext(bvm *vm, int index)
+{
+ bvalue *o = be_indexof(vm, index);
+ if (var_islist(o)) {
+ return list_hasnext(vm, o);
+ } else if (var_ismap(o)) {
+ return map_hasnext(vm, o);
+ }
+ return bfalse;
+}
+
+BERRY_API bbool be_refcontains(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ binstance **ref = be_stack_base(&vm->refstack);
+ binstance **top = be_stack_top(&vm->refstack);
+ binstance *ins = var_toobj(v);
+ be_assert(var_isinstance(v));
+ if (ref) {
+ while (ref <= top && *ref != ins) {
+ ++ref;
+ }
+ return ref <= top;
+ }
+ return bfalse;
+}
+
+BERRY_API void be_refpush(bvm *vm, int index)
+{
+ bvalue *v = be_indexof(vm, index);
+ binstance *ins = var_toobj(v);
+ be_assert(var_isinstance(v));
+ be_stack_push(vm, &vm->refstack, &ins);
+}
+
+BERRY_API void be_refpop(bvm *vm)
+{
+ be_stack_pop(&vm->refstack);
+ if (be_stack_isempty(&vm->refstack)) {
+ be_vector_release(vm, &vm->refstack);
+ }
+}
+
+BERRY_API int be_returnvalue(bvm *vm)
+{
+ bvalue *src = vm->top - 1;
+ bvalue *ret = retreg(vm);
+ var_setval(ret, src);
+ return 0;
+}
+
+BERRY_API int be_returnnilvalue(bvm *vm)
+{
+ bvalue *ret = retreg(vm);
+ var_setnil(ret);
+ return 0;
+}
+
+BERRY_API void be_call(bvm *vm, int argc)
+{
+ bvalue *fval = vm->top - argc - 1;
+ be_dofunc(vm, fval, argc);
+}
+
+BERRY_API int be_pcall(bvm *vm, int argc)
+{
+ bvalue *f = vm->top - argc - 1;
+ return be_protectedcall(vm, f, argc);
+}
+
+__attribute__((noreturn))
+BERRY_API void be_raise(bvm *vm, const char *except, const char *msg)
+{
+ be_pushstring(vm, except);
+ if (msg) {
+ be_pushstring(vm, msg);
+ } else {
+ be_pushnil(vm);
+ }
+ be_pop(vm, 2);
+ be_save_stacktrace(vm);
+ be_throw(vm, BE_EXCEPTION);
+#ifdef __GNUC__
+ __builtin_unreachable();
+#endif
+}
+
+BERRY_API void be_stop_iteration(bvm *vm)
+{
+ be_raise(vm, "stop_iteration", NULL);
+}
+
+BERRY_API int be_getexcept(bvm *vm, int code)
+{
+ if (code == BE_EXCEPTION) {
+ if (be_isstring(vm, -2)) {
+ const char *except = be_tostring(vm, -2);
+ if (!strcmp(except, "syntax_error")) {
+ return BE_SYNTAX_ERROR;
+ }
+ if (!strcmp(except, "io_error")) {
+ return BE_IO_ERROR;
+ }
+ }
+ return BE_EXEC_ERROR;
+ }
+ return code;
+}
+
+static int _dvfunc(bvm *vm, bbool esc)
+{
+ const char* s = esc ?
+ be_toescape(vm, 1, 'x') : be_tostring(vm, 1);
+ be_writestring(s);
+ be_return_nil(vm);
+}
+
+static int _dumpesc(bvm *vm)
+{
+ return _dvfunc(vm, btrue);
+}
+
+static int _dumpdir(bvm *vm)
+{
+ return _dvfunc(vm, bfalse);
+}
+
+static int dump_value(bvm *vm, int index, bbool esc)
+{
+ int res, top = be_top(vm) + 1;
+ index = be_absindex(vm, index);
+ be_pushntvfunction(vm, esc ? _dumpesc : _dumpdir);
+ be_pushvalue(vm, index);
+ res = be_pcall(vm, 1); /* using index to store result */
+ be_remove(vm, top); /* remove '_dumpvalue' function */
+ be_remove(vm, top); /* remove the value */
+ if (res == BE_EXCEPTION) {
+ be_dumpexcept(vm);
+ }
+ return res;
+}
+
+BERRY_API void be_dumpvalue(bvm *vm, int index)
+{
+ if (dump_value(vm, index, btrue) == BE_OK) {
+ be_writenewline();
+ }
+}
+
+BERRY_API void be_dumpexcept(bvm *vm)
+{
+ do {
+ /* print exception value */
+ if (dump_value(vm, -2, bfalse)) break;
+ be_writestring(": ");
+ /* print exception argument */
+ if (dump_value(vm, -1, bfalse)) break;
+ be_writenewline();
+ /* print stack traceback */
+ be_tracestack(vm);
+ } while (0);
+ be_pop(vm, 2); /* pop the exception value & argument */
+}
+
+BERRY_API bbool be_iseq(bvm *vm)
+{
+ be_assert(vm->reg + 2 <= vm->top);
+ return be_vm_iseq(vm, vm->top - 2, vm->top - 1);
+}
+
+BERRY_API bbool be_isneq(bvm *vm)
+{
+ be_assert(vm->reg + 2 <= vm->top);
+ return be_vm_isneq(vm, vm->top - 2, vm->top - 1);
+}
+
+BERRY_API bbool be_islt(bvm *vm)
+{
+ be_assert(vm->reg + 2 <= vm->top);
+ return be_vm_islt(vm, vm->top - 2, vm->top - 1);
+}
+
+BERRY_API bbool be_isle(bvm *vm)
+{
+ be_assert(vm->reg + 2 <= vm->top);
+ return be_vm_isle(vm, vm->top - 2, vm->top - 1);
+}
+
+BERRY_API bbool be_isgt(bvm *vm)
+{
+ be_assert(vm->reg + 2 <= vm->top);
+ return be_vm_isgt(vm, vm->top - 2, vm->top - 1);
+}
+
+BERRY_API bbool be_isge(bvm *vm)
+{
+ be_assert(vm->reg + 2 <= vm->top);
+ return be_vm_isge(vm, vm->top - 2, vm->top - 1);
+}
+
+BERRY_API int be_register(bvm *vm, int index)
+{
+ bvalue *v;
+ if (!vm->registry) {
+ vm->registry = be_list_new(vm);
+ be_list_pool_init(vm, vm->registry);
+ }
+ be_assert(vm->registry != NULL);
+ v = be_indexof(vm, index);
+ return be_list_pool_alloc(vm, vm->registry, v);
+}
+
+BERRY_API void be_unregister(bvm *vm, int id)
+{
+ be_assert(vm->registry != NULL);
+ be_list_pool_free(vm->registry, id);
+}
+
+BERRY_API void be_getregister(bvm *vm, int id)
+{
+ blist *reg = vm->registry;
+ be_assert(reg && id > 0 && id < be_list_count(reg));
+ var_setval(vm->top, be_list_at(reg, id));
+ be_incrtop(vm);
+}
diff --git a/lib/libesp32/berry/src/be_baselib.c b/lib/libesp32/berry/src/be_baselib.c
new file mode 100644
index 000000000..98f96b48e
--- /dev/null
+++ b/lib/libesp32/berry/src/be_baselib.c
@@ -0,0 +1,520 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_vm.h"
+#include "be_exec.h"
+#include "be_mem.h"
+#include "be_gc.h"
+#include "be_class.h"
+#include "be_vector.h"
+#include "be_string.h"
+#include "be_map.h"
+#include
+
+#define READLINE_STEP 100
+
+static int l_assert(bvm *vm)
+{
+ int argc = be_top(vm);
+ /* assertion fails when there is no argument
+ * or the first argument is nil or false. */
+ if (!argc || !be_tobool(vm, 1)) {
+ const char *msg = "assert failed!";
+ if (argc >= 2 && be_isstring(vm, 2)) {
+ msg = be_tostring(vm, 2);
+ }
+ be_raise(vm, "assert_failed", msg);
+ }
+ be_return_nil(vm);
+}
+
+static int l_print(bvm *vm)
+{
+ int i, argc = be_top(vm);
+ for (i = 1; i <= argc; ++i) {
+ const char *str = be_tostring(vm, i);
+ size_t len = be_strlen(vm, i);
+ be_writebuffer(str, len);
+ if (i < argc) {
+ be_writebuffer(" ", 1);
+ }
+ }
+ be_writenewline();
+ be_return_nil(vm);
+}
+
+static int m_readline(bvm *vm)
+{
+ size_t pos = 0, size = READLINE_STEP;
+ char *buffer = be_malloc(vm, size);
+ char *res = be_readstring(buffer, (int)size);
+ while (res) {
+ pos += strlen(buffer + pos) - 1;
+ if (!pos || buffer[pos] == '\n') {
+ buffer[pos] = '\0'; /* trim \n */
+ break;
+ }
+ buffer = be_realloc(vm, buffer, size, size + READLINE_STEP);
+ res = be_readstring(buffer + pos + 1, READLINE_STEP);
+ size += READLINE_STEP;
+ }
+ be_pushstring(vm, buffer);
+ be_free(vm, buffer, size);
+ be_return(vm);
+}
+
+static int l_input(bvm *vm)
+{
+ if (be_top(vm) && be_isstring(vm, 1)) { /* echo prompt */
+ be_writestring(be_tostring(vm, 1));
+ }
+ return m_readline(vm);
+}
+
+/* Look in the current class and all super classes for a method corresponding to a specific closure pointer */
+static bclass *find_class_closure(bclass *cl, bclosure *needle)
+{
+ while (cl) {
+ bmapnode *node; /* iterate on members of the class */
+ bmap *members = be_class_members(cl);
+ if (members) { /* only iterate if there are members */
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(members, &iter)) != NULL) {
+ if (var_type(&node->value) == BE_CLOSURE) { /* only native functions are considered */
+ bclosure *clos_iter = var_toobj(&node->value); /* retrieve the method's closure */
+ if (clos_iter == needle) {
+ /* we found the closure, we now know its class */
+ return cl;
+ }
+ }
+ }
+ }
+ cl = be_class_super(cl); /* move to super class */
+ }
+ return NULL; /* not found */
+}
+
+static int l_super(bvm *vm)
+{
+ int argc = be_top(vm);
+
+ /* if no argument, or arg 1 is nil, return nil */
+ if (argc == 0 || be_isnil(vm, 1)) {
+ be_return_nil(vm);
+ }
+
+ /* if arg 1 is a class, simply return super */
+ if (be_isclass(vm, 1)) {
+ be_getsuper(vm, 1);
+ be_return(vm);
+ }
+
+ /* arg 1 is an instance */
+ if (be_isinstance(vm, 1)) {
+ binstance *o = var_toobj(be_indexof(vm, 1));
+ bclass *target_class = NULL; /* the minimal class expected, or any super class */
+ bclass *base_class = NULL; /* current class of the caller, if any */
+
+ /* if arg 2 is present, it must be a class */
+ if (argc >= 2) {
+ if (be_isclass(vm, 2)) {
+ target_class = var_toobj(be_indexof(vm, 2));
+ } else if (be_isnil(vm, 2)) {
+ // ignore, revert to standard super() behavior if second arg is explicit nil
+ } else {
+ be_raise(vm, "type_error", "leveled super() requires 'instance' and 'class' arguments");
+ }
+ }
+
+ /* now the more complex part, if arg 1 is an instance */
+ /* if instance is the sole argument, try to find if it comes from a method of a class and set 'base_class' accordinly */
+ /* later it will be equivalent to passing this class as second argument */
+ if (argc == 1) {
+ /* we look in the callstack for the caller's closure */
+ int size = be_stack_count(&vm->callstack);
+ if (size >= 2) { /* need at least 2 stackframes: current (for super() native) and caller (the one we are interested in) */
+ bcallframe *caller = be_vector_at(&vm->callstack, size - 2); /* get the callframe of caller */
+ bvalue *func = caller->func; /* function object of caller */
+ if (var_type(func) == BE_CLOSURE) { /* only useful if the caller is a Berry closure (i.e. not native) */
+ bclosure *clos_ctx = var_toobj(func); /* this is the closure we look for in the class chain */
+ base_class = find_class_closure(o->_class, clos_ctx); /* iterate on current and super classes to find where the closure belongs */
+ }
+ }
+ }
+
+ if (base_class || target_class) {
+ if (base_class) {
+ target_class = base_class->super;
+ if (!target_class) be_return_nil(vm); /* fast exit if top class */
+ }
+ /* leveled super, i.e. fix the parenthood class level */
+ if (o) {
+ o = be_instance_super(o); /* always skip the current class and move to super */
+ }
+ while (o) {
+ bclass *c = be_instance_class(o);
+ if (c == target_class) break; /* found */
+ o = be_instance_super(o);
+ }
+ bvalue *top = be_incrtop(vm);
+ if (o) {
+ var_setinstance(top, o); /* return the instance with the specified parent class */
+ } else {
+ var_setnil(top); /* not found, return nil */
+ }
+ be_return(vm);
+ } else {
+ be_getsuper(vm, 1);
+ be_return(vm);
+ }
+ }
+
+ /* fall through, return nil if we don't know what to do */
+ be_return_nil(vm);
+}
+
+static int l_type(bvm *vm)
+{
+ if (be_top(vm)) {
+ be_pushstring(vm, be_typename(vm, 1));
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int l_classname(bvm *vm)
+{
+ if (be_top(vm)) {
+ const char *t = be_classname(vm, 1);
+ if (t) {
+ be_pushstring(vm, t);
+ be_return(vm);
+ }
+ }
+ be_return_nil(vm);
+}
+
+static int l_classof(bvm *vm)
+{
+ if (be_top(vm) && be_classof(vm, 1)) {
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int l_number(bvm *vm)
+{
+ if (be_top(vm)) {
+ if (be_isstring(vm, 1)) {
+ be_str2num(vm, be_tostring(vm, 1));
+ be_return(vm);
+ } else if (be_isnumber(vm, 1)) {
+ be_pushvalue(vm, 1);
+ be_return(vm);
+ }
+ }
+ be_return_nil(vm);
+}
+
+static int l_int(bvm *vm)
+{
+ if (be_top(vm)) {
+ if (be_isstring(vm, 1)) {
+ const char *s = be_tostring(vm, 1);
+ be_pushint(vm, be_str2int(s, NULL));
+ } else if (be_isreal(vm, 1)) {
+ be_pushint(vm, (bint)be_toreal(vm, 1));
+ } else if (be_isint(vm, 1)) {
+ be_pushvalue(vm, 1);
+ } else if (be_isbool(vm, 1)) {
+ be_pushint(vm, be_tobool(vm, 1) ? 1 : 0);
+ } else {
+ be_return_nil(vm);
+ }
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int l_real(bvm *vm)
+{
+ if (be_top(vm)) {
+ if (be_isstring(vm, 1)) {
+ const char *s = be_tostring(vm, 1);
+ be_pushreal(vm, be_str2real(s, NULL));
+ } else if (be_isint(vm, 1)) {
+ be_pushreal(vm, (breal)be_toint(vm, 1));
+ } else if (be_isreal(vm, 1)) {
+ be_pushvalue(vm, 1);
+ } else {
+ be_return_nil(vm);
+ }
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int check_method(bvm *vm, const char *attr)
+{
+ return be_top(vm) &&
+ be_isinstance(vm, 1) && be_getmethod(vm, 1, attr);
+}
+
+static int l_iterator(bvm *vm)
+{
+ if (be_top(vm) && be_isfunction(vm, 1)) {
+ be_return(vm); /* return the argument[0]::function */
+ }
+ if (check_method(vm, "iter")) {
+ be_pushvalue(vm, 1);
+ be_call(vm, 1);
+ be_pop(vm, 1);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+/* call a function with variable number of arguments */
+/* first argument is a callable object (function, closure, native function, native closure) */
+/* then all subsequent arguments are pushed except the last one */
+/* If the last argument is a 'list', then all elements are pushed as arguments */
+/* otherwise the last argument is pushed as well */
+static int l_call(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 1 && be_isfunction(vm, 1)) {
+ size_t arg_count = top - 1; /* we have at least 'top - 1' arguments */
+ /* test if last argument is a list */
+
+ if (top > 1 && be_isinstance(vm, top) && be_getmember(vm, top, ".p") && be_islist(vm, top + 1)) {
+ int32_t list_size = be_data_size(vm, top + 1);
+
+ if (list_size > 0) {
+ be_stack_require(vm, list_size + 3); /* make sure we don't overflow the stack */
+ for (int i = 0; i < list_size; i++) {
+ be_pushnil(vm);
+ }
+ be_moveto(vm, top + 1, top + 1 + list_size);
+ be_moveto(vm, top, top + list_size);
+
+ be_refpush(vm, -2);
+ be_pushiter(vm, -1);
+ while (be_iter_hasnext(vm, -2)) {
+ be_iter_next(vm, -2);
+ be_moveto(vm, -1, top);
+ top++;
+ be_pop(vm, 1);
+ }
+ be_pop(vm, 1); /* remove iterator */
+ be_refpop(vm);
+ }
+ be_pop(vm, 2);
+ arg_count = arg_count - 1 + list_size;
+ }
+ /* actual call */
+ be_call(vm, arg_count);
+ /* remove args */
+ be_pop(vm, arg_count);
+ /* return value */
+
+ be_return(vm);
+ }
+ be_raise(vm, "value_error", "first argument must be a function");
+ be_return_nil(vm);
+}
+
+static int l_str(bvm *vm)
+{
+ if (be_top(vm)) {
+ be_tostring(vm, 1);
+ } else {
+ be_pushstring(vm, "");
+ }
+ be_return(vm);
+}
+
+static int l_bool(bvm *vm)
+{
+ if (be_top(vm)) {
+ be_pushbool(vm, be_tobool(vm, 1));
+ } else {
+ be_pushbool(vm, bfalse);
+ }
+ be_return(vm);
+}
+
+
+static int l_size(bvm *vm)
+{
+ if (be_top(vm) && be_isstring(vm, 1)) {
+ be_pushint(vm, be_strlen(vm, 1));
+ be_return(vm);
+ }
+ if (check_method(vm, "size")) {
+ be_pushvalue(vm, 1);
+ be_call(vm, 1);
+ be_pop(vm, 1);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int l_module(bvm *vm)
+{
+ int argc = be_top(vm);
+ be_newmodule(vm);
+ if (argc > 0 && be_isstring(vm, 1)) {
+ be_setname(vm, -1, be_tostring(vm, 1));
+ }
+ be_return(vm);
+}
+
+#if BE_USE_SCRIPT_COMPILER
+static int raise_compile_error(bvm *vm)
+{
+ be_pop(vm, 2); /* pop the exception value and message */
+ be_throw(vm, BE_EXCEPTION);
+ return 0;
+}
+
+static int m_compile_str(bvm *vm)
+{
+ int len = be_strlen(vm, 1);
+ const char *src = be_tostring(vm, 1);
+ int res = be_loadbuffer(vm, "string", src, len);
+ if (res == BE_OK) {
+ be_return(vm);
+ }
+ return raise_compile_error(vm);
+}
+
+static int m_compile_file(bvm *vm)
+{
+ const char *fname = be_tostring(vm, 1);
+ int res = be_loadfile(vm, fname);
+ if (res == BE_OK) {
+ be_return(vm);
+ } else if (res == BE_IO_ERROR) {
+ be_pushstring(vm, "io_error");
+ be_pushvalue(vm, -2);
+ }
+ return raise_compile_error(vm);
+}
+#endif
+
+static int l_compile(bvm *vm)
+{
+#if BE_USE_SCRIPT_COMPILER
+ if (be_top(vm) && be_isstring(vm, 1)) {
+ if (be_top(vm) >= 2 && be_isstring(vm, 2)) {
+ const char *s = be_tostring(vm, 2);
+ if (!strcmp(s, "string")) {
+ return m_compile_str(vm);
+ }
+ if (!strcmp(s, "file")) {
+ return m_compile_file(vm);
+ }
+ } else {
+ return m_compile_str(vm);
+ }
+ }
+#endif
+ be_return_nil(vm);
+}
+
+static int _issubv(bvm *vm, bbool (*filter)(bvm*, int))
+{
+ bbool status = bfalse;
+ if (be_top(vm) >= 2 && filter(vm, 1)) {
+ be_pushvalue(vm, 2);
+ status = be_isderived(vm, 1);
+ }
+ be_pushbool(vm, status);
+ be_return(vm);
+}
+
+static int l_issubclass(bvm *vm)
+{
+ return _issubv(vm, be_isclass);
+}
+
+static int l_isinstance(bvm *vm)
+{
+ return _issubv(vm, be_isinstance);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+void be_load_baselib(bvm *vm)
+{
+ be_regfunc(vm, "assert", l_assert);
+ be_regfunc(vm, "print", l_print);
+ be_regfunc(vm, "input", l_input);
+ be_regfunc(vm, "super", l_super);
+ be_regfunc(vm, "type", l_type);
+ be_regfunc(vm, "classname", l_classname);
+ be_regfunc(vm, "classof", l_classof);
+ be_regfunc(vm, "number", l_number);
+ be_regfunc(vm, "str", l_str);
+ be_regfunc(vm, "int", l_int);
+ be_regfunc(vm, "real", l_real);
+ be_regfunc(vm, "module", l_module);
+ be_regfunc(vm, "size", l_size);
+ be_regfunc(vm, "compile", l_compile);
+ be_regfunc(vm, "issubclass", l_issubclass);
+ be_regfunc(vm, "isinstance", l_isinstance);
+ be_regfunc(vm, "__iterator__", l_iterator);
+}
+
+/* call must be added later to respect order of builtins */
+void be_load_baselib_next(bvm *vm)
+{
+ be_regfunc(vm, "call", l_call);
+ be_regfunc(vm, "bool", l_bool);
+}
+#else
+extern const bclass be_class_list;
+extern const bclass be_class_map;
+extern const bclass be_class_range;
+extern const bclass be_class_bytes;
+extern int be_nfunc_open(bvm *vm);
+/* @const_object_info_begin
+vartab m_builtin (scope: local) {
+ assert, func(l_assert)
+ print, func(l_print)
+ input, func(l_input)
+ super, func(l_super)
+ type, func(l_type)
+ classname, func(l_classname)
+ classof, func(l_classof)
+ number, func(l_number)
+ str, func(l_str)
+ int, func(l_int)
+ real, func(l_real)
+ module, func(l_module)
+ size, func(l_size)
+ compile, func(l_compile)
+ issubclass, func(l_issubclass)
+ isinstance, func(l_isinstance)
+ __iterator__, func(l_iterator)
+ open, func(be_nfunc_open)
+ list, class(be_class_list)
+ map, class(be_class_map)
+ range, class(be_class_range)
+ bytes, class(be_class_bytes)
+ call, func(l_call)
+ bool, func(l_bool)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_m_builtin.h"
+#include "be_var.h"
+
+void be_load_baselib(bvm *vm)
+{
+ be_const_builtin_set(vm, &m_builtin_map, &m_builtin_vector);
+}
+#endif
diff --git a/lib/libesp32/berry/src/be_bytecode.c b/lib/libesp32/berry/src/be_bytecode.c
new file mode 100644
index 000000000..9f9283fbe
--- /dev/null
+++ b/lib/libesp32/berry/src/be_bytecode.c
@@ -0,0 +1,590 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_bytecode.h"
+#include "be_decoder.h"
+#include "be_vector.h"
+#include "be_string.h"
+#include "be_class.h"
+#include "be_func.h"
+#include "be_exec.h"
+#include "be_list.h"
+#include "be_map.h"
+#include "be_mem.h"
+#include "be_sys.h"
+#include "be_var.h"
+#include "be_vm.h"
+#include
+
+#define MAGIC_NUMBER1 0xBE
+#define MAGIC_NUMBER2 0xCD
+#define MAGIC_NUMBER3 0xFE
+#define BYTECODE_VERSION 3
+
+#define USE_64BIT_INT (BE_INTGER_TYPE == 2 \
+ || BE_INTGER_TYPE == 1 && LONG_MAX == 9223372036854775807L)
+
+#if !BE_USE_SCRIPT_COMPILER && BE_USE_BYTECODE_SAVER
+#error bytecode generation dependent compiler (require BE_USE_SCRIPT_COMPILER != 0)
+#endif
+
+#if BE_USE_BYTECODE_SAVER || BE_USE_BYTECODE_LOADER
+static void bytecode_error(bvm *vm, const char *msg)
+{
+ be_raise(vm, "io_error", msg);
+}
+
+static uint8_t vm_sizeinfo(void)
+{
+ uint8_t res = sizeof(bint) == 8;
+ res |= (sizeof(breal) == 8) << 1;
+ return res;
+}
+#endif
+
+#if BE_USE_BYTECODE_SAVER
+static void save_proto(bvm *vm, void *fp, bproto *proto);
+
+static void save_byte(void *fp, uint8_t value)
+{
+ be_fwrite(fp, &value, 1);
+}
+
+static void save_word(void *fp, uint16_t value)
+{
+ uint8_t buffer[2];
+ buffer[0] = value & 0xff;
+ buffer[1] = value >> 8;
+ be_fwrite(fp, buffer, sizeof(buffer));
+}
+
+static void save_long(void *fp, uint32_t value)
+{
+ uint8_t buffer[4];
+ buffer[0] = value & 0xff;
+ buffer[1] = (value >> 8) & 0xff;
+ buffer[2] = (value >> 16) & 0xff;
+ buffer[3] = (value >> 24) & 0xff;
+ be_fwrite(fp, buffer, sizeof(buffer));
+}
+
+static void save_header(void *fp)
+{
+ uint8_t buffer[8] = { 0 };
+ buffer[0] = MAGIC_NUMBER1;
+ buffer[1] = MAGIC_NUMBER2;
+ buffer[2] = MAGIC_NUMBER3;
+ buffer[3] = BYTECODE_VERSION;
+ buffer[4] = vm_sizeinfo();
+ be_fwrite(fp, buffer, sizeof(buffer));
+}
+
+static void save_int(void *fp, bint i)
+{
+#if USE_64BIT_INT
+ save_long(fp, i & 0xffffffff);
+ save_long(fp, (i >> 32) & 0xffffffff);
+#else
+ save_long(fp, (uint32_t)i);
+#endif
+}
+
+static void save_real(void *fp, breal r)
+{
+#if BE_USE_SINGLE_FLOAT
+ union { breal r; uint32_t i; } u;
+ u.r = r;
+ save_long(fp, u.i);
+#else
+ union { breal r; uint64_t i; } u;
+ u.r = r;
+ save_long(fp, u.i & 0xffffffff);
+ save_long(fp, (u.i >> 32) & 0xffffffff);
+#endif
+}
+
+static void save_string(void *fp, bstring *s)
+{
+ if (s) {
+ uint16_t length = (uint16_t)str_len(s);
+ const char *data = str(s);
+ save_word(fp, length);
+ be_fwrite(fp, data, length);
+ }
+}
+
+static bstring** save_members(bvm *vm, void *fp, bclass *c, int nvar)
+{
+ bmapnode *node;
+ bstring **vars = NULL;
+ bmap *members = c->members;
+ bmapiter iter = be_map_iter();
+ if (nvar) {
+ /* allocate the member-variable name cache */
+ vars = be_malloc(vm, sizeof(bstring *) * nvar);
+ }
+ while ((node = be_map_next(members, &iter)) != NULL) {
+ be_assert(var_isstr(&node->key));
+ if (var_isindex(&node->value)) { /* cache member name */
+ if (vars == NULL) {
+ return NULL; /* should never be executed */
+ }
+ vars[var_toidx(&node->value)] = var_tostr(&node->key);
+ } else { /* save method's name and function */
+ bproto *proto;
+ bvalue *value = &node->value;
+ be_assert(var_isclosure(value) || var_isproto(value) || var_isnil(value));
+ save_string(fp, var_tostr(&node->key)); /* save method name */
+ if (var_isproto(value)) { /* the method is a prototype */
+ proto = var_toobj(value);
+ save_proto(vm, fp, proto); /* only save prototype */
+ } else if (var_isclosure(value)) { /* the method is a closure */
+ proto = cast(bclosure *, var_toobj(value))->proto;
+ save_proto(vm, fp, proto); /* only save prototype */
+ } else if (var_isnil(value)) {
+ /* this is a static member (nil default) */
+ save_word(fp, 0); /* store a zero byte that will be seen as a zero length method name which is invalid */
+ } else {
+ be_raise(vm, "internal_error", "unsupported member in class");
+ return NULL; /* should never be executed */
+ }
+ }
+ }
+ return vars;
+}
+
+static void save_class(bvm *vm, void *fp, bclass *c)
+{
+ bstring **vars;
+ int i, count = be_map_count(c->members);
+ int nvar = c->nvar - be_class_closure_count(c);
+ save_string(fp, c->name);
+ save_long(fp, nvar); /* member variables count */
+ save_long(fp, count - nvar); /* method count */
+ vars = save_members(vm, fp, c, nvar);
+ if (vars != NULL) {
+ for (i = 0; i < nvar; ++i) {
+ save_string(fp, vars[i]);
+ }
+ be_free(vm, vars, sizeof(bstring *) * nvar);
+ }
+}
+
+static void save_value(bvm *vm, void *fp, bvalue *v)
+{
+ save_byte(fp, (uint8_t)var_type(v)); /* type */
+ switch (var_type(v)) {
+ case BE_INT: save_int(fp, var_toint(v)); break;
+ case BE_REAL: save_real(fp, var_toreal(v)); break;
+ case BE_STRING: save_string(fp, var_tostr(v)); break;
+ case BE_CLASS: save_class(vm, fp, var_toobj(v)); break;
+ default: break;
+ }
+}
+
+static void save_bytecode(bvm *vm, void *fp, bproto *proto)
+{
+ int forbid_gbl = comp_is_named_gbl(vm);
+ binstruction *code = proto->code, *end;
+ save_long(fp, (uint32_t)proto->codesize);
+ for (end = code + proto->codesize; code < end; ++code) {
+ save_long(fp, (uint32_t)*code);
+ if (forbid_gbl) { /* we are saving only named globals, so make sure we don't save OP_GETGBL or OP_SETGBL */
+ if ((uint32_t)*code == OP_GETGBL || (uint32_t)*code == OP_SETGBL) {
+ be_raise(vm, "internal_error", "GETGBL/SETGBL found when saving with named globals");
+ }
+ }
+ }
+}
+
+static void save_constants(bvm *vm, void *fp, bproto *proto)
+{
+ bvalue *v = proto->ktab, *end;
+ save_long(fp, proto->nconst); /* constants count */
+ for (end = v + proto->nconst; v < end; ++v) {
+ save_value(vm, fp, v);
+ }
+}
+
+static void save_proto_table(bvm *vm, void *fp, bproto *proto)
+{
+ bproto **p = proto->ptab, **end;
+ save_long(fp, proto->nproto); /* proto count */
+ for (end = p + proto->nproto; p < end; ++p) {
+ save_proto(vm, fp, *p);
+ }
+}
+
+static void save_upvals(void *fp, bproto *proto)
+{
+ bupvaldesc *uv = proto->upvals, *end;
+ save_byte(fp, proto->nupvals); /* upvals count */
+ for (end = uv + proto->nupvals; uv < end; ++uv) {
+ save_byte(fp, uv->instack);
+ save_byte(fp, uv->idx);
+ }
+}
+
+static void save_proto(bvm *vm, void *fp, bproto *proto)
+{
+ if (proto) {
+ save_string(fp, proto->name); /* name */
+ save_string(fp, proto->source); /* source */
+ save_byte(fp, proto->argc); /* argc */
+ save_byte(fp, proto->nstack); /* nstack */
+ save_byte(fp, proto->varg); /* varg */
+ save_byte(fp, 0x00); /* reserved */
+ save_bytecode(vm, fp, proto); /* bytecode */
+ save_constants(vm, fp, proto); /* constant */
+ save_proto_table(vm, fp, proto); /* proto table */
+ save_upvals(fp, proto); /* upvals description table */
+ }
+}
+
+static void save_globals(bvm *vm, void *fp)
+{
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ bmap *map = vm->gbldesc.global.vtab;
+ int i, count = be_global_count(vm);
+ bstring **list = be_malloc(vm, sizeof(bstring*) * count);
+ while ((node = be_map_next(map, &iter)) != NULL) {
+ if (var_isstr(&node->key)) {
+ int idx = var_toidx(&node->value);
+ be_assert(idx < count);
+ list[idx] = var_tostr(&node->key);
+ }
+ }
+ for (i = 0; i < count; ++i) {
+ save_string(fp, list[i]);
+ }
+ be_free(vm, list, sizeof(bstring*) * count);
+}
+
+static void save_global_info(bvm *vm, void *fp)
+{
+ save_long(fp, be_builtin_count(vm));
+ if (comp_is_named_gbl(vm)) {
+ /* named globals only so no need to save current globals */
+ save_long(fp, 0);
+ } else {
+ save_long(fp, be_global_count(vm));
+ save_globals(vm, fp);
+ }
+}
+
+void be_bytecode_save(bvm *vm, const char *filename, bproto *proto)
+{
+ void *fp = be_fopen(filename, "wb");
+ if (fp == NULL) {
+ bytecode_error(vm, be_pushfstring(vm,
+ "can not open file '%s'.", filename));
+ } else {
+ save_header(fp);
+ save_global_info(vm, fp);
+ save_proto(vm, fp, proto);
+ be_fclose(fp);
+ }
+}
+#endif /* BE_USE_BYTECODE_SAVER */
+
+#if BE_USE_BYTECODE_LOADER
+static bbool load_proto(bvm *vm, void *fp, bproto **proto, int info, int version);
+
+static uint8_t load_byte(void *fp)
+{
+ uint8_t buffer[1];
+ if (be_fread(fp, buffer, sizeof(buffer)) == sizeof(buffer)) {
+ return buffer[0];
+ }
+ return 0;
+}
+
+static uint16_t load_word(void *fp)
+{
+ uint8_t buffer[2];
+ if (be_fread(fp, buffer, sizeof(buffer)) == sizeof(buffer)) {
+ return ((uint16_t)buffer[1] << 8) | buffer[0];
+ }
+ return 0;
+}
+
+static uint32_t load_long(void *fp)
+{
+ uint8_t buffer[4];
+ if (be_fread(fp, buffer, sizeof(buffer)) == sizeof(buffer)) {
+ return ((uint32_t)buffer[3] << 24)
+ | ((uint32_t)buffer[2] << 16)
+ | ((uint32_t)buffer[1] << 8)
+ | buffer[0];
+ }
+ return 0;
+}
+
+static int load_head(void *fp)
+{
+ int res;
+ uint8_t buffer[8] = { 0 };
+ be_fread(fp, buffer, sizeof(buffer));
+ res = buffer[0] == MAGIC_NUMBER1 &&
+ buffer[1] == MAGIC_NUMBER2 &&
+ buffer[2] == MAGIC_NUMBER3 &&
+ buffer[3] <= BYTECODE_VERSION &&
+ buffer[4] == vm_sizeinfo();
+ if (res) {
+ return buffer[3];
+ } else {
+ return 0;
+ }
+}
+
+bbool be_bytecode_check(const char *path)
+{
+ void *fp = be_fopen(path, "r");
+ if (fp) {
+ uint8_t buffer[3], rb;
+ rb = (uint8_t)be_fread(fp, buffer, 3);
+ be_fclose(fp);
+ /* check magic number */
+ return rb == 3 &&
+ buffer[0] == MAGIC_NUMBER1 &&
+ buffer[1] == MAGIC_NUMBER2 &&
+ buffer[2] == MAGIC_NUMBER3;
+ }
+ return bfalse;
+}
+
+static bint load_int(void *fp)
+{
+#if USE_64BIT_INT
+ bint i;
+ i = load_long(fp);
+ i |= (bint)load_long(fp) << 32;
+ return i;
+#else
+ return load_long(fp);
+#endif
+}
+
+static breal load_real(void *fp)
+{
+#if BE_USE_SINGLE_FLOAT
+ union { breal r; uint32_t i; } u;
+ u.i = load_long(fp);
+ return u.r;
+#else
+ union {
+ breal r;
+ uint64_t i;
+ } u;
+ u.i = load_long(fp);
+ u.i |= (uint64_t)load_long(fp) << 32;
+ return u.r;
+#endif
+}
+
+static bstring* load_string(bvm *vm, void *fp)
+{
+ uint16_t len = load_word(fp);
+ if (len > 0) {
+ bstring *str;
+ char *buf = be_malloc(vm, len);
+ be_fread(fp, buf, len);
+ str = be_newstrn(vm, buf, len);
+ be_free(vm, buf, len);
+ return str;
+ }
+ return str_literal(vm, "");
+}
+
+static bstring* cache_string(bvm *vm, void *fp)
+{
+ bstring *str = load_string(vm, fp);
+ var_setstr(vm->top, str);
+ be_incrtop(vm);
+ return str;
+}
+
+static void load_class(bvm *vm, void *fp, bvalue *v, int version)
+{
+ int nvar, count;
+ bclass *c = be_newclass(vm, NULL, NULL);
+ var_setclass(v, c);
+ c->name = load_string(vm, fp);
+ nvar = load_long(fp);
+ count = load_long(fp);
+ while (count--) { /* load method table */
+ bvalue *value;
+ bstring *name = cache_string(vm, fp);
+ value = vm->top;
+ var_setproto(value, NULL);
+ be_incrtop(vm);
+ if (load_proto(vm, fp, (bproto**)&var_toobj(value), -3, version)) {
+ /* actual method */
+ be_method_bind(vm, c, name, var_toobj(value), bfalse);
+ } else {
+ /* no proto, static member set to nil */
+ be_member_bind(vm, c, name, bfalse);
+ }
+ be_stackpop(vm, 2); /* pop the cached string and proto */
+ }
+ for (count = 0; count < nvar; ++count) { /* load member-variable table */
+ bstring *name = cache_string(vm, fp);
+ be_member_bind(vm, c, name, btrue);
+ be_stackpop(vm, 1); /* pop the cached string */
+ }
+}
+
+static void load_value(bvm *vm, void *fp, bvalue *v, int version)
+{
+ switch (load_byte(fp)) {
+ case BE_INT: var_setint(v, load_int(fp)); break;
+ case BE_REAL: var_setreal(v, load_real(fp)); break;
+ case BE_STRING: var_setstr(v, load_string(vm, fp)); break;
+ case BE_CLASS: load_class(vm, fp, v, version); break;
+ default: break;
+ }
+}
+
+static void load_bytecode(bvm *vm, void *fp, bproto *proto, int info)
+{
+ int size = (int)load_long(fp);
+ if (size) {
+ binstruction *code, *end;
+ int bcnt = be_builtin_count(vm);
+ blist *list = var_toobj(be_indexof(vm, info));
+ be_assert(be_islist(vm, info));
+ proto->code = be_malloc(vm, sizeof(binstruction) * size);
+ proto->codesize = size;
+ code = proto->code;
+ for (end = code + size; code < end; ++code) {
+ binstruction ins = (binstruction)load_long(fp);
+ binstruction op = IGET_OP(ins);
+ /* fix global variable index */
+ if (op == OP_GETGBL || op == OP_SETGBL) {
+ int idx = IGET_Bx(ins);
+ if (idx >= bcnt) { /* does not fix builtin index */
+ bvalue *name = be_list_at(list, idx - bcnt);
+ idx = be_global_find(vm, var_tostr(name));
+ ins = (ins & ~IBx_MASK) | ISET_Bx(idx);
+ }
+ }
+ *code = ins;
+ }
+ }
+}
+
+static void load_constant(bvm *vm, void *fp, bproto *proto, int version)
+{
+ int size = (int)load_long(fp); /* nconst */
+ if (size) {
+ bvalue *end, *v = be_malloc(vm, sizeof(bvalue) * size);
+ memset(v, 0, sizeof(bvalue) * size);
+ proto->ktab = v;
+ proto->nconst = size;
+ for (end = v + size; v < end; ++v) {
+ load_value(vm, fp, v, version);
+ }
+ }
+}
+
+static void load_proto_table(bvm *vm, void *fp, bproto *proto, int version)
+{
+ int size = (int)load_long(fp); /* proto count */
+ if (size) {
+ bproto **p = be_malloc(vm, sizeof(bproto *) * size);
+ memset(p, 0, sizeof(bproto *) * size);
+ proto->ptab = p;
+ proto->nproto = size;
+ while (size--) {
+ load_proto(vm, fp, p++, -1, version);
+ }
+ }
+}
+
+static void load_upvals(bvm *vm, void *fp, bproto *proto)
+{
+ int size = (int)load_byte(fp);
+ if (size) {
+ bupvaldesc *uv, *end;
+ proto->upvals = be_malloc(vm, sizeof(bupvaldesc) * size);
+ proto->nupvals = (bbyte)size;
+ uv = proto->upvals;
+ for (end = uv + size; uv < end; ++uv) {
+ uv->instack = load_byte(fp);
+ uv->idx = load_byte(fp);
+ }
+ }
+}
+
+static bbool load_proto(bvm *vm, void *fp, bproto **proto, int info, int version)
+{
+ /* first load the name */
+ /* if empty, it's a static member so don't allocate an actual proto */
+ bstring *name = load_string(vm, fp);
+ if (str_len(name)) {
+ *proto = be_newproto(vm);
+ (*proto)->name = name;
+ (*proto)->source = load_string(vm, fp);
+ (*proto)->argc = load_byte(fp);
+ (*proto)->nstack = load_byte(fp);
+ if (version > 1) {
+ (*proto)->varg = load_byte(fp);
+ load_byte(fp); /* discard reserved byte */
+ }
+ load_bytecode(vm, fp, *proto, info);
+ load_constant(vm, fp, *proto, version);
+ load_proto_table(vm, fp, *proto, version);
+ load_upvals(vm, fp, *proto);
+ return btrue;
+ }
+ return bfalse; /* no proto read */
+}
+
+void load_global_info(bvm *vm, void *fp)
+{
+ int i;
+ int bcnt = (int)load_long(fp); /* builtin count */
+ int gcnt = (int)load_long(fp); /* global count */
+ if (bcnt > be_builtin_count(vm)) {
+ bytecode_error(vm, be_pushfstring(vm,
+ "inconsistent number of builtin objects."));
+ }
+ be_newlist(vm);
+ for (i = 0; i < gcnt; ++i) {
+ bstring *name = cache_string(vm, fp);
+ be_global_new(vm, name);
+ be_data_push(vm, -2); /* push the variable name to list */
+ be_stackpop(vm, 1); /* pop the cached string */
+ }
+ be_global_release_space(vm);
+}
+
+bclosure* be_bytecode_load(bvm *vm, const char *filename)
+{
+ void *fp = be_fopen(filename, "rb");
+ if (fp == NULL) {
+ bytecode_error(vm, be_pushfstring(vm,
+ "can not open file '%s'.", filename));
+ } else {
+ int version = load_head(fp);
+ if (version) {
+ bclosure *cl = be_newclosure(vm, 0);
+ var_setclosure(vm->top, cl);
+ be_stackpush(vm);
+ load_global_info(vm, fp);
+ load_proto(vm, fp, &cl->proto, -1, version);
+ be_stackpop(vm, 2); /* pop the closure and list */
+ be_fclose(fp);
+ return cl;
+ }
+ }
+ bytecode_error(vm, be_pushfstring(vm,
+ "invalid bytecode file '%s'.", filename));
+ return NULL;
+}
+#endif /* BE_USE_BYTECODE_LOADER */
diff --git a/lib/libesp32/berry/src/be_bytecode.h b/lib/libesp32/berry/src/be_bytecode.h
new file mode 100644
index 000000000..08affe1de
--- /dev/null
+++ b/lib/libesp32/berry/src/be_bytecode.h
@@ -0,0 +1,17 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef __BE_BYTECODE_H
+#define __BE_BYTECODE_H
+
+#include "be_object.h"
+
+void be_bytecode_save(bvm *vm, const char *filename, bproto *proto);
+bclosure* be_bytecode_load(bvm *vm, const char *filename);
+bbool be_bytecode_check(const char *path);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_byteslib.c b/lib/libesp32/berry/src/be_byteslib.c
new file mode 100644
index 000000000..82f4ab2be
--- /dev/null
+++ b/lib/libesp32/berry/src/be_byteslib.c
@@ -0,0 +1,1447 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang - Stephan Hadinger
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_string.h"
+#include "be_strlib.h"
+#include "be_list.h"
+#include "be_func.h"
+#include "be_exec.h"
+#include "be_vm.h"
+#include "be_mem.h"
+#include "be_constobj.h"
+#include
+#include
+
+#define BYTES_DEFAULT_SIZE 28 // default pre-reserved size for buffer (keep 4 bytes for len/size)
+#define BYTES_MAX_SIZE (32*1024) // max 32Kb
+#define BYTES_OVERHEAD 4 // bytes overhead to be added when allocating (used to store len and size)
+#define BYTES_HEADROOM 8 // keep a natural headroom of 8 bytes when resizing
+
+#define BYTES_SIZE_FIXED -1 // if size is -1, then the bytes object cannot be reized
+#define BYTES_SIZE_MAPPED -2 // if size is -2, then the bytes object is mapped to a fixed memory region, i.e. cannot be resized
+
+#define BYTES_RESIZE_ERROR "attribute_error"
+#define BYTES_RESIZE_MESSAGE "bytes object size if fixed and cannot be resized"
+/* be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); */
+
+typedef struct buf_impl {
+ int32_t size; // size in bytes of the buffer
+ int32_t len; // current size of the data in buffer. Invariant: len <= size
+ uint8_t *bufptr; // the actual data
+ int32_t prev_size; // previous value read from the instance
+ int32_t prev_len; // previous value read from the instance
+ uint8_t *prev_bufptr;
+ bbool fixed; // is size fixed? (actually encoded as negative size)
+ bbool mapped;
+} buf_impl;
+
+/********************************************************************
+** Base64 lib from https://github.com/Densaugeo/base64_arduino
+**
+********************************************************************/
+
+/* binary_to_base64:
+ * Description:
+ * Converts a single byte from a binary value to the corresponding base64 character
+ * Parameters:
+ * v - Byte to convert
+ * Returns:
+ * ascii code of base64 character. If byte is >= 64, then there is not corresponding base64 character
+ * and 255 is returned
+ */
+static unsigned char binary_to_base64(unsigned char v);
+
+/* base64_to_binary:
+ * Description:
+ * Converts a single byte from a base64 character to the corresponding binary value
+ * Parameters:
+ * c - Base64 character (as ascii code)
+ * Returns:
+ * 6-bit binary value
+ */
+static unsigned char base64_to_binary(unsigned char c);
+
+/* encode_base64_length:
+ * Description:
+ * Calculates length of base64 string needed for a given number of binary bytes
+ * Parameters:
+ * input_length - Amount of binary data in bytes
+ * Returns:
+ * Number of base64 characters needed to encode input_length bytes of binary data
+ */
+static unsigned int encode_base64_length(unsigned int input_length);
+
+/* decode_base64_length:
+ * Description:
+ * Calculates number of bytes of binary data in a base64 string
+ * Parameters:
+ * input - Base64-encoded null-terminated string
+ * Returns:
+ * Number of bytes of binary data in input
+ */
+static unsigned int decode_base64_length(unsigned char input[]);
+
+/* encode_base64:
+ * Description:
+ * Converts an array of bytes to a base64 null-terminated string
+ * Parameters:
+ * input - Pointer to input data
+ * input_length - Number of bytes to read from input pointer
+ * output - Pointer to output string. Null terminator will be added automatically
+ * Returns:
+ * Length of encoded string in bytes (not including null terminator)
+ */
+static unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]);
+
+/* decode_base64:
+ * Description:
+ * Converts a base64 null-terminated string to an array of bytes
+ * Parameters:
+ * input - Pointer to input string
+ * output - Pointer to output array
+ * Returns:
+ * Number of bytes in the decoded binary
+ */
+static unsigned int decode_base64(unsigned char input[], unsigned char output[]);
+
+static unsigned char binary_to_base64(unsigned char v) {
+ // Capital letters - 'A' is ascii 65 and base64 0
+ if(v < 26) return v + 'A';
+
+ // Lowercase letters - 'a' is ascii 97 and base64 26
+ if(v < 52) return v + 71;
+
+ // Digits - '0' is ascii 48 and base64 52
+ if(v < 62) return v - 4;
+
+ // '+' is ascii 43 and base64 62
+ if(v == 62) return '+';
+
+ // '/' is ascii 47 and base64 63
+ if(v == 63) return '/';
+
+ return 64;
+}
+
+static unsigned char base64_to_binary(unsigned char c) {
+ // Capital letters - 'A' is ascii 65 and base64 0
+ if('A' <= c && c <= 'Z') return c - 'A';
+
+ // Lowercase letters - 'a' is ascii 97 and base64 26
+ if('a' <= c && c <= 'z') return c - 71;
+
+ // Digits - '0' is ascii 48 and base64 52
+ if('0' <= c && c <= '9') return c + 4;
+
+ // '+' is ascii 43 and base64 62
+ if(c == '+') return 62;
+
+ // '/' is ascii 47 and base64 63
+ if(c == '/') return 63;
+
+ return 255;
+}
+
+static unsigned int encode_base64_length(unsigned int input_length) {
+ return (input_length + 2)/3*4;
+}
+
+static unsigned int decode_base64_length(unsigned char input[]) {
+ unsigned char *start = input;
+
+ while(base64_to_binary(input[0]) < 64) {
+ ++input;
+ }
+
+ unsigned int input_length = input - start;
+
+ unsigned int output_length = input_length/4*3;
+
+ switch(input_length % 4) {
+ default: return output_length;
+ case 2: return output_length + 1;
+ case 3: return output_length + 2;
+ }
+}
+
+static unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]) {
+ unsigned int full_sets = input_length/3;
+
+ // While there are still full sets of 24 bits...
+ for(unsigned int i = 0; i < full_sets; ++i) {
+ output[0] = binary_to_base64( input[0] >> 2);
+ output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
+ output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
+ output[3] = binary_to_base64( input[2] & 0x3F);
+
+ input += 3;
+ output += 4;
+ }
+
+ switch(input_length % 3) {
+ case 0:
+ output[0] = '\0';
+ break;
+ case 1:
+ output[0] = binary_to_base64( input[0] >> 2);
+ output[1] = binary_to_base64((input[0] & 0x03) << 4);
+ output[2] = '=';
+ output[3] = '=';
+ output[4] = '\0';
+ break;
+ case 2:
+ output[0] = binary_to_base64( input[0] >> 2);
+ output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
+ output[2] = binary_to_base64((input[1] & 0x0F) << 2);
+ output[3] = '=';
+ output[4] = '\0';
+ break;
+ }
+
+ return encode_base64_length(input_length);
+}
+
+static unsigned int decode_base64(unsigned char input[], unsigned char output[]) {
+ unsigned int output_length = decode_base64_length(input);
+
+ // While there are still full sets of 24 bits...
+ for(unsigned int i = 2; i < output_length; i += 3) {
+ output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
+ output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
+ output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
+
+ input += 4;
+ output += 3;
+ }
+
+ switch(output_length % 3) {
+ case 1:
+ output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
+ break;
+ case 2:
+ output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
+ output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
+ break;
+ }
+
+ return output_length;
+}
+
+/********************************************************************
+** Buffer low-level implementation
+**
+** Extracted from Tasmota SBuffer lib
+********************************************************************/
+// static inline uint8_t* buf_get_buf(buf_impl* attr)
+// {
+// return &attr->bufptr[0];
+// }
+
+// shrink or increase. If increase, fill with zeores. Cannot go beyond `size`
+static void buf_set_len(buf_impl* attr, const size_t len)
+{
+ uint16_t old_len = attr->len;
+ attr->len = ((int32_t)len <= attr->size) ? (int32_t)len : attr->size;
+ if (old_len < attr->len) {
+ memset((void*) &attr->bufptr[old_len], 0, attr->len - old_len);
+ }
+}
+
+static size_t buf_add1(buf_impl* attr, const uint8_t data) // append 8 bits value
+{
+ if (attr->len < attr->size) { // do we have room for 1 byte
+ attr->bufptr[attr->len++] = data;
+ }
+ return attr->len;
+}
+
+static size_t buf_add2_le(buf_impl* attr, const uint16_t data) // append 16 bits value
+{
+ if (attr->len < attr->size - 1) { // do we have room for 2 bytes
+ attr->bufptr[attr->len++] = data;
+ attr->bufptr[attr->len++] = data >> 8;
+ }
+ return attr->len;
+}
+
+static size_t buf_add2_be(buf_impl* attr, const uint16_t data) // append 16 bits value
+{
+ if (attr->len < attr->size - 1) { // do we have room for 2 bytes
+ attr->bufptr[attr->len++] = data >> 8;
+ attr->bufptr[attr->len++] = data;
+ }
+ return attr->len;
+}
+
+static size_t buf_add4_le(buf_impl* attr, const uint32_t data) // append 32 bits value
+{
+ if (attr->len < attr->size - 3) { // do we have room for 4 bytes
+ attr->bufptr[attr->len++] = data;
+ attr->bufptr[attr->len++] = data >> 8;
+ attr->bufptr[attr->len++] = data >> 16;
+ attr->bufptr[attr->len++] = data >> 24;
+ }
+ return attr->len;
+}
+
+size_t buf_add4_be(buf_impl* attr, const uint32_t data) // append 32 bits value
+{
+ if (attr->len < attr->size - 3) { // do we have room for 4 bytes
+ attr->bufptr[attr->len++] = data >> 24;
+ attr->bufptr[attr->len++] = data >> 16;
+ attr->bufptr[attr->len++] = data >> 8;
+ attr->bufptr[attr->len++] = data;
+ }
+ return attr->len;
+}
+
+static size_t buf_add_buf(buf_impl* attr, buf_impl* attr2)
+{
+ if (attr->len + attr2->len <= attr->size) {
+ for (int32_t i = 0; i < attr2->len; i++) {
+ attr->bufptr[attr->len++] = attr2->bufptr[i];
+ }
+ }
+ return attr->len;
+}
+
+static uint8_t buf_get1(buf_impl* attr, int offset)
+{
+ if ((offset >= 0) && (offset < attr->len)) {
+ return attr->bufptr[offset];
+ }
+ return 0;
+}
+
+static void buf_set1(buf_impl* attr, size_t offset, uint8_t data)
+{
+ if ((int32_t)offset < attr->len) {
+ attr->bufptr[offset] = data;
+ }
+}
+
+static void buf_set2_le(buf_impl* attr, size_t offset, uint16_t data)
+{
+ if ((int32_t)offset + 1 < attr->len) {
+ attr->bufptr[offset] = data & 0xFF;
+ attr->bufptr[offset+1] = data >> 8;
+ }
+}
+
+static void buf_set2_be(buf_impl* attr, size_t offset, uint16_t data)
+{
+ if ((int32_t)offset + 1 < attr->len) {
+ attr->bufptr[offset+1] = data & 0xFF;
+ attr->bufptr[offset] = data >> 8;
+ }
+}
+
+static uint16_t buf_get2_le(buf_impl* attr, size_t offset)
+{
+ if ((int32_t)offset + 1 < attr->len) {
+ return attr->bufptr[offset] | (attr->bufptr[offset+1] << 8);
+ }
+ return 0;
+}
+
+static uint16_t buf_get2_be(buf_impl* attr, size_t offset)
+{
+ if ((int32_t)offset + 1 < attr->len) {
+ return attr->bufptr[offset+1] | (attr->bufptr[offset] << 8);
+ }
+ return 0;
+}
+
+static void buf_set4_le(buf_impl* attr, size_t offset, uint32_t data)
+{
+ if ((int32_t)offset + 3 < attr->len) {
+ attr->bufptr[offset] = data & 0xFF;
+ attr->bufptr[offset+1] = (data >> 8) & 0xFF;
+ attr->bufptr[offset+2] = (data >> 16) & 0xFF;
+ attr->bufptr[offset+3] = data >> 24;
+ }
+}
+
+static void buf_set4_be(buf_impl* attr, size_t offset, uint32_t data)
+{
+ if ((int32_t)offset + 3 < attr->len) {
+ attr->bufptr[offset+3] = data & 0xFF;
+ attr->bufptr[offset+2] = (data >> 8) & 0xFF;
+ attr->bufptr[offset+1] = (data >> 16) & 0xFF;
+ attr->bufptr[offset] = data >> 24;
+ }
+}
+
+static uint32_t buf_get4_le(buf_impl* attr, size_t offset)
+{
+ if ((int32_t)offset + 3 < attr->len) {
+ return attr->bufptr[offset] | (attr->bufptr[offset+1] << 8) |
+ (attr->bufptr[offset+2] << 16) | (attr->bufptr[offset+3] << 24);
+ }
+ return 0;
+}
+
+static uint32_t buf_get4_be(buf_impl* attr, size_t offset)
+{
+ if ((int32_t)offset + 3 < attr->len) {
+ return attr->bufptr[offset+3] | (attr->bufptr[offset+2] << 8) |
+ (attr->bufptr[offset+1] << 16) | (attr->bufptr[offset] << 24);
+ }
+ return 0;
+}
+
+// nullptr accepted
+static bbool buf_equals(buf_impl* buf1, buf_impl* buf2)
+{
+ if (buf1 == buf2) { return btrue; }
+ if (!buf1 || !buf2) { return bfalse; } // at least one attr is not empty
+ // we know that both buf1 and buf2 are non-null
+ if (buf1->len != buf2->len) { return bfalse; }
+ size_t len = buf1->len;
+ for (uint32_t i=0; i= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; }
+ else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; }
+ return rVal;
+}
+
+// does not check if there is enough room before hand, truncated if buffer too small
+static void buf_add_hex(buf_impl* attr, const char *hex, size_t len)
+{
+ uint8_t val;
+ for (; len > 1; len -= 2) {
+ val = asc2byte(*hex++) << 4;
+ val |= asc2byte(*hex++);
+ buf_add1(attr, val);
+ }
+}
+
+/********************************************************************
+** Wrapping into lib
+********************************************************************/
+
+/* load instance attribute into a single structure, and store 'previous' values in order to later update only the changed ones */
+/* stack item 1 must contain the instance */
+buf_impl m_read_attributes(bvm *vm, int idx)
+{
+ buf_impl attr;
+ be_getmember(vm, idx, ".p");
+ attr.bufptr = attr.prev_bufptr = be_tocomptr(vm, -1);
+ be_pop(vm, 1);
+
+ be_getmember(vm, idx, ".len");
+ attr.len = attr.prev_len = be_toint(vm, -1);
+ be_pop(vm, 1);
+
+ be_getmember(vm, idx, ".size");
+ int32_t signed_size = be_toint(vm, -1);
+ attr.fixed = bfalse;
+ attr.mapped = bfalse;
+ if (signed_size < 0) {
+ if (signed_size == BYTES_SIZE_MAPPED) {
+ attr.mapped = btrue;
+ }
+ signed_size = attr.len;
+ attr.fixed = btrue;
+ }
+ attr.size = attr.prev_size = signed_size;
+ be_pop(vm, 1);
+ return attr;
+}
+
+/* Write back attributes to the bytes instance, only if values changed after loading */
+/* stack item 1 must contain the instance */
+void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr)
+{
+ int idx = be_absindex(vm, rel_idx);
+ if (attr->bufptr != attr->prev_bufptr) {
+ be_pushcomptr(vm, attr->bufptr);
+ be_setmember(vm, idx, ".p");
+ be_pop(vm, 1);
+ }
+
+ if (attr->len != attr->prev_len) {
+ be_pushint(vm, attr->len);
+ be_setmember(vm, idx, ".len");
+ be_pop(vm, 1);
+ }
+
+ int32_t new_size = attr->size;
+ if (attr->mapped) {
+ new_size = BYTES_SIZE_MAPPED;
+ } else if (attr->fixed) {
+ new_size = BYTES_SIZE_FIXED;
+ }
+ if (new_size != attr->prev_size) {
+ be_pushint(vm, new_size);
+ be_setmember(vm, idx, ".size");
+ be_pop(vm, 1);
+ }
+}
+
+// buf_impl * bytes_realloc(bvm *vm, buf_impl *oldbuf, int32_t size)
+void bytes_realloc(bvm *vm, buf_impl * attr, int32_t size)
+{
+ if (!attr->fixed && size < 4) { size = 4; }
+ if (size > BYTES_MAX_SIZE) { size = BYTES_MAX_SIZE; }
+ size_t oldsize = attr->bufptr ? attr->size : 0;
+ attr->bufptr = (uint8_t*) be_realloc(vm, attr->bufptr, oldsize, size); /* malloc */
+ attr->size = size;
+ if (!attr->bufptr) {
+ attr->len = 0; /* allocate a new buffer */
+ }
+}
+
+/* allocate a new `bytes` object with pre-allocated size */
+static void bytes_new_object(bvm *vm, size_t size)
+{
+ be_getbuiltin(vm, "bytes");
+ be_pushint(vm, size);
+ be_call(vm, 1);
+ be_pop(vm, 1);
+}
+
+/*
+ * constructor for bytes()
+ * Arg0 is always self
+ *
+ * Option 1: main use
+ * Arg1: string - a string representing the bytes in HEX
+ *
+ * Option 2:
+ * Arg1: string - a string representing the bytes in HEX
+ * Arg2: int - pre-reserved buffer size. If negative, size is fixed and cannot be later changed
+ *
+ * Option 3: used by subclasses like ctypes
+ * Arg1: int - pre-reserved buffer size. If negative, size is fixed and cannot be later changed
+ *
+ * Option 4: mapped buffer
+ * Arg1: comptr - buffer address of the mapped buffer
+ * Arg2: int - buffer size. Always fixed (negative or positive)
+ *
+ * */
+static int m_init(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = { 0, 0, NULL, 0, -1, NULL, bfalse, bfalse }; /* initialize prev_values to invalid to force a write at the end */
+ /* size cannot be 0, len cannot be negative */
+ const char * hex_in = NULL;
+
+ int32_t size_arg = 0;
+ if (argc > 1 && be_isint(vm, 2)) {
+ size_arg = be_toint(vm, 2); /* raw size arg, can be positive or negative */
+ } else if (argc > 2 && be_isint(vm, 3)) {
+ size_arg = be_toint(vm, 3); /* raw size arg, can be positive or negative */
+ }
+
+ if (argc > 1 && be_iscomptr(vm, 2)) {
+ if (size_arg) {
+ attr.len = (size_arg < 0) ? -size_arg : size_arg;
+ attr.bufptr = be_tocomptr(vm, 2);
+ attr.fixed = btrue;
+ attr.mapped = btrue;
+ m_write_attributes(vm, 1, &attr); /* write attributes back to instance */
+ be_return_nil(vm);
+ } else {
+ be_raise(vm, "value_error", "size is required");
+ }
+ }
+ if (size_arg == 0) { size_arg = BYTES_DEFAULT_SIZE; } /* if not specified, use default size */
+
+ /* compute actual size to be reserved */
+ if (size_arg >= 0) {
+ size_arg += BYTES_HEADROOM; /* add automatic headroom to slightly overallocate */
+ if (size_arg > attr.size) {
+ attr.size = size_arg;
+ }
+ } else {
+ attr.size = -size_arg; /* set the size to a fixed negative value */
+ attr.fixed = btrue;
+ }
+ size_arg = attr.size;
+
+ /* if arg1 is string, we convert hex */
+ if (argc > 1 && be_isstring(vm, 2)) {
+ hex_in = be_tostring(vm, 2);
+ if (hex_in) {
+ size_arg = strlen(hex_in) / 2; /* allocate headroom */
+ }
+ /* check if fixed size that we have the right size */
+ if (size_arg > attr.size) {
+ if (attr.fixed) {
+ be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
+ } else {
+ attr.size = size_arg;
+ }
+ }
+ }
+
+ /* allocate */
+ bytes_realloc(vm, &attr, attr.size); /* allocate new buffer */
+ if (!attr.bufptr) {
+ be_throw(vm, BE_MALLOC_FAIL);
+ }
+
+ if (hex_in) {
+ buf_add_hex(&attr, hex_in, strlen(hex_in));
+ }
+
+ /* if fixed size, set len to size */
+ if (attr.fixed) {
+ buf_set_len(&attr, attr.size);
+ }
+
+ m_write_attributes(vm, 1, &attr); /* write attributes back to instance */
+ be_return_nil(vm);
+}
+
+/* deallocate buffer */
+static int m_deinit(bvm *vm)
+{
+ buf_impl attr = m_read_attributes(vm, 1);
+ if (attr.bufptr != NULL && !attr.mapped) {
+ be_realloc(vm, attr.bufptr, attr.size, 0);
+ }
+ attr.size = 0;
+ attr.len = 0;
+ attr.bufptr = NULL;
+ m_write_attributes(vm, 1, &attr);
+ be_return_nil(vm);
+}
+
+/* grow or shrink to the exact value */
+/* stack item 1 must contain the instance */
+void _bytes_resize(bvm *vm, buf_impl * attr, size_t new_size) {
+ bytes_realloc(vm, attr, new_size);
+ if (!attr->bufptr) {
+ be_throw(vm, BE_MALLOC_FAIL);
+ }
+}
+
+/* grow if needed but don't shrink */
+/* if grow, then add some headroom */
+/* stack item 1 must contain the instance */
+void bytes_resize(bvm *vm, buf_impl * attr, size_t new_size) {
+ if (attr->mapped) { return; } /* if mapped, don't bother with allocation */
+ /* when resized to smaller, we introduce a new heurstic */
+ /* If the buffer is 64 bytes or smaller, don't shrink */
+ /* Shrink buffer only if target size is smaller than half the original size */
+ if (attr->size >= (int32_t)new_size) { /* enough room, consider if need to shrink */
+ if (attr->size <= 64) { return; } /* don't shrink if below 64 bytes */
+ if (attr->size < (int32_t)new_size * 2) { return; }
+ }
+ _bytes_resize(vm, attr, new_size);
+}
+
+buf_impl bytes_check_data(bvm *vm, size_t add_size) {
+ buf_impl attr = m_read_attributes(vm, 1);
+ /* check if the `size` is big enough */
+ if (attr.len + (int32_t)add_size > attr.size) {
+ /* it does not fit so we need to realocate the buffer */
+ bytes_resize(vm, &attr, attr.len + add_size);
+ }
+ return attr;
+}
+
+static size_t tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) {
+ static const char * hex = "0123456789ABCDEF";
+ const uint8_t * pin = in;
+ char * pout = out;
+ for (; pin < in + insz; pout += 2, pin++) {
+ pout[0] = hex[((*pin)>>4) & 0xF];
+ pout[1] = hex[ (*pin) & 0xF];
+ if (pout + 3 > out + outsz) { break; } /* check overflow */
+ }
+ pout[0] = 0; /* terminating Nul char */
+ return pout - out;
+}
+
+static int m_tostring(bvm *vm)
+{
+ int argc = be_top(vm);
+ int32_t max_len = 32; /* limit to 32 bytes by default */
+ int truncated = 0;
+ if (argc > 1 && be_isint(vm, 2)) {
+ max_len = be_toint(vm, 2); /* you can specify the len as second argument, or 0 for unlimited */
+ }
+ buf_impl attr = m_read_attributes(vm, 1);
+ int32_t len = attr.len;
+ if (max_len > 0 && len > max_len) {
+ len = max_len; /* limit output size */
+ truncated = 1;
+ }
+ size_t hex_len = len * 2 + 5 + 2 + 2 + 1 + truncated * 3; /* reserve size for `bytes("")\0` - 9 chars */
+
+ char * hex_out = be_pushbuffer(vm, hex_len);
+ size_t l = be_strlcpy(hex_out, "bytes('", hex_len);
+ l += tohex(&hex_out[l], hex_len - l, attr.bufptr, len);
+ if (truncated) {
+ l += be_strlcpy(&hex_out[l], "...", hex_len - l);
+ }
+ l += be_strlcpy(&hex_out[l], "')", hex_len - l);
+
+ be_pushnstring(vm, hex_out, l); /* make escape string from buffer */
+ be_remove(vm, -2); /* remove buffer */
+ be_return(vm);
+}
+
+/*
+ * Copy the buffer into a string without any changes
+ */
+static int m_asstring(bvm *vm)
+{
+ buf_impl attr = bytes_check_data(vm, 0);
+ be_pushnstring(vm, (const char*) attr.bufptr, attr.len);
+ be_return(vm);
+}
+
+static int m_fromstring(bvm *vm)
+{
+ int argc = be_top(vm);
+ if (argc >= 2 && be_isstring(vm, 2)) {
+ const char *s = be_tostring(vm, 2);
+ int32_t len = be_strlen(vm, 2); /* calling be_strlen to support null chars in string */
+ buf_impl attr = bytes_check_data(vm, 0);
+ if (attr.fixed && attr.len != len) {
+ be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
+ }
+ bytes_resize(vm, &attr, len); /* resize if needed */
+ if (len > attr.size) { len = attr.size; } /* avoid overflow */
+ memmove(attr.bufptr, s, len);
+ attr.len = len;
+ be_pop(vm, 1); /* remove arg to leave instance */
+ m_write_attributes(vm, 1, &attr); /* update attributes */
+ be_return(vm);
+ }
+ be_raise(vm, "type_error", "operand must be a string");
+ be_return_nil(vm);
+}
+
+/*
+ * Add an int made of 1, 2 or 4 bytes, in little or big endian
+ * `add(value:int[, size:int = 1]) -> instance`
+ *
+ * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian)
+ * obvisouly -1 is idntical to 1
+ * size==0 does nothing
+ */
+static int m_add(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
+ if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
+ if (argc >= 2 && be_isint(vm, 2)) {
+ int32_t v = be_toint(vm, 2);
+ int vsize = 1;
+ if (argc >= 3 && be_isint(vm, 3)) {
+ vsize = be_toint(vm, 3);
+ }
+ switch (vsize) {
+ case 0: break;
+ case -1: /* fallback below */
+ case 1: buf_add1(&attr, v); break;
+ case 2: buf_add2_le(&attr, v); break;
+ case 4: buf_add4_le(&attr, v); break;
+ case -2: buf_add2_be(&attr, v); break;
+ case -4: buf_add4_be(&attr, v); break;
+ default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4.");
+ }
+ be_pop(vm, argc - 1);
+ m_write_attributes(vm, 1, &attr); /* update attributes */
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+/*
+ * Get an int made of 1, 2 or 4 bytes, in little or big endian
+ * `get(index:int[, size:int = 1]) -> int`
+ *
+ * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian)
+ * obvisouly -1 is identical to 1
+ * 0 returns nil
+ */
+static int m_get(bvm *vm, bbool sign)
+{
+ int argc = be_top(vm);
+ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
+ if (argc >=2 && be_isint(vm, 2)) {
+ int32_t idx = be_toint(vm, 2);
+ int vsize = 1;
+ if (argc >= 3 && be_isint(vm, 3)) {
+ vsize = be_toint(vm, 3);
+ }
+ int ret = 0;
+ switch (vsize) {
+ case 0: break;
+ case -1: /* fallback below */
+ case 1: ret = buf_get1(&attr, idx);
+ if (sign) { ret = (int8_t)(uint8_t) ret; }
+ break;
+ case 2: ret = buf_get2_le(&attr, idx);
+ if (sign) { ret = (int16_t)(uint16_t) ret; }
+ break;
+ case 4: ret = buf_get4_le(&attr, idx); break;
+ case -2: ret = buf_get2_be(&attr, idx);
+ if (sign) { ret = (int16_t)(uint16_t) ret; }
+ break;
+ case -4: ret = buf_get4_be(&attr, idx); break;
+ default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4.");
+ }
+ be_pop(vm, argc - 1);
+ if (vsize != 0) {
+ be_pushint(vm, ret);
+ } else {
+ be_pushnil(vm);
+ }
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+/* signed int */
+static int m_geti(bvm *vm)
+{
+ return m_get(vm, 1);
+}
+
+/* unsigned int */
+static int m_getu(bvm *vm)
+{
+ return m_get(vm, 0);
+}
+
+/*
+ * Set an int made of 1, 2 or 4 bytes, in little or big endian
+ * `set(index:int, value:int[, size:int = 1]) -> nil`
+ *
+ * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian)
+ * obvisouly -1 is identical to 1
+ * 0 returns nil
+ */
+static int m_set(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
+ if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
+ int32_t idx = be_toint(vm, 2);
+ int32_t value = be_toint(vm, 3);
+ int vsize = 1;
+ if (argc >= 4 && be_isint(vm, 4)) {
+ vsize = be_toint(vm, 4);
+ }
+ switch (vsize) {
+ case 0: break;
+ case -1: /* fallback below */
+ case 1: buf_set1(&attr, idx, value); break;
+ case 2: buf_set2_le(&attr, idx, value); break;
+ case 4: buf_set4_le(&attr, idx, value); break;
+ case -2: buf_set2_be(&attr, idx, value); break;
+ case -4: buf_set4_be(&attr, idx, value); break;
+ default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4.");
+ }
+ be_pop(vm, argc - 1);
+ m_write_attributes(vm, 1, &attr); /* update attributes */
+ be_return_nil(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int m_setitem(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
+ if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
+ int index = be_toint(vm, 2);
+ int val = be_toint(vm, 3);
+ if (index >= 0 && index < attr.len) {
+ buf_set1(&attr, index, val);
+ m_write_attributes(vm, 1, &attr); /* update attributes */
+ be_return_nil(vm);
+ }
+ }
+ be_raise(vm, "index_error", "bytes index out of range or value non int");
+ be_return_nil(vm);
+}
+
+static int m_item(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
+ if (argc >=2 && be_isint(vm, 2)) { /* single byte */
+ int index = be_toint(vm,2);
+ if (index < 0) {
+ index += attr.len;
+ }
+ if (index >= 0 && index < attr.len) {
+ be_pushint(vm, buf_get1(&attr, index));
+ be_return(vm);
+ }
+ }
+ if (argc >= 2 && be_isinstance(vm, 2)) {
+ const char *cname = be_classname(vm, 2);
+ if (!strcmp(cname, "range")) {
+ bint lower, upper;
+ bint size = attr.len;
+ /* get index range */
+ be_getmember(vm, 2, "__lower__");
+ lower = be_toint(vm, -1);
+ be_pop(vm, 1);
+ be_getmember(vm, 2, "__upper__");
+ upper = be_toint(vm, -1);
+ be_pop(vm, 1);
+ /* handle negative limits */
+ if (upper < 0) { upper += attr.len; }
+ if (lower < 0) { lower += attr.len; }
+ /* protection scope */
+ upper = upper < size ? upper : size - 1;
+ lower = lower < 0 ? 0 : lower;
+ /* construction result list instance */
+ bytes_new_object(vm, upper > lower ? upper-lower : 0);
+ buf_impl attr2 = m_read_attributes(vm, -1);
+
+ for (; lower <= upper; ++lower) {
+ buf_add1(&attr2, attr.bufptr[lower]);
+ }
+ m_write_attributes(vm, -1, &attr2); /* update instance */
+ be_return(vm);
+ }
+ }
+ be_raise(vm, "index_error", "bytes index out of range");
+ be_return_nil(vm);
+}
+
+static int m_size(bvm *vm)
+{
+ buf_impl attr = m_read_attributes(vm, 1);
+ be_pushint(vm, attr.len);
+ be_return(vm);
+}
+
+static int m_resize(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = m_read_attributes(vm, 1);
+
+ if (argc <= 1 || !be_isint(vm, 2)) {
+ be_raise(vm, "type_error", "size must be of type 'int'");
+ }
+ int new_len = be_toint(vm, 2);
+ if (new_len < 0) {
+ new_len = 0;
+ }
+ if (attr.fixed && attr.len != new_len) {
+ be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
+ }
+
+ bytes_resize(vm, &attr, new_len);
+ buf_set_len(&attr, new_len);
+ be_pop(vm, 1);
+ m_write_attributes(vm, 1, &attr); /* update instance */
+ be_return(vm);
+}
+
+static int m_clear(bvm *vm)
+{
+ buf_impl attr = m_read_attributes(vm, 1);
+ if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
+ attr.len = 0;
+ m_write_attributes(vm, 1, &attr); /* update instance */
+ be_return_nil(vm);
+}
+
+static int m_merge(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = m_read_attributes(vm, 1); /* no resize yet */
+ if (argc >= 2 && be_isbytes(vm, 2)) {
+ buf_impl attr2 = m_read_attributes(vm, 2);
+
+ /* allocate new object */
+ bytes_new_object(vm, attr.len + attr2.len);
+ buf_impl attr3 = m_read_attributes(vm, -1);
+
+ buf_add_buf(&attr3, &attr);
+ buf_add_buf(&attr3, &attr2);
+
+ m_write_attributes(vm, -1, &attr3); /* update instance */
+ be_return(vm); /* return self */
+ }
+ be_raise(vm, "type_error", "operand must be bytes");
+ be_return_nil(vm); /* return self */
+}
+
+static int m_copy(bvm *vm)
+{
+ buf_impl attr = m_read_attributes(vm, 1);
+ bytes_new_object(vm, attr.len);
+ buf_impl attr2 = m_read_attributes(vm, -1);
+ buf_add_buf(&attr2, &attr);
+ m_write_attributes(vm, -1, &attr2); /* update instance */
+ be_return(vm); /* return self */
+}
+
+/* accept bytes or int as operand */
+static int m_connect(bvm *vm)
+{
+ int argc = be_top(vm);
+ buf_impl attr = m_read_attributes(vm, 1);
+ if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
+ if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2))) {
+ if (be_isint(vm, 2)) {
+ bytes_resize(vm, &attr, attr.len + 1); /* resize */
+ buf_add1(&attr, be_toint(vm, 2));
+ m_write_attributes(vm, 1, &attr); /* update instance */
+ be_pushvalue(vm, 1);
+ be_return(vm); /* return self */
+ } else {
+ buf_impl attr2 = m_read_attributes(vm, 2);
+ bytes_resize(vm, &attr, attr.len + attr2.len); /* resize buf1 for total size */
+ buf_add_buf(&attr, &attr2);
+ m_write_attributes(vm, 1, &attr); /* update instance */
+ be_pushvalue(vm, 1);
+ be_return(vm); /* return self */
+ }
+ }
+ be_raise(vm, "type_error", "operand must be bytes or int");
+ be_return_nil(vm); /* return self */
+}
+
+static int bytes_equal(bvm *vm, bbool iseq)
+{
+ bbool ret;
+ buf_impl attr1 = m_read_attributes(vm, 1);
+ if (!be_isbytes(vm, 2)) {
+ ret = !iseq;
+ } else {
+ buf_impl attr2 = m_read_attributes(vm, 2);
+
+ if (buf_equals(&attr1, &attr2)) {
+ ret = iseq;
+ } else {
+ ret = !iseq;
+ }
+ }
+ be_pushbool(vm, ret);
+ be_return(vm);
+}
+
+static int m_equal(bvm *vm)
+{
+ return bytes_equal(vm, btrue);
+}
+
+static int m_nequal(bvm *vm)
+{
+ return bytes_equal(vm, bfalse);
+}
+
+/*
+ * Converts bytes() to a base64 string
+ *
+ * Note: there are no line breaks inserted
+ *
+ * `b.tob64() -> string`
+ */
+static int m_tob64(bvm *vm)
+{
+ buf_impl attr = m_read_attributes(vm, 1);
+ int32_t len = attr.len;
+ int32_t b64_len = encode_base64_length(len) + 1; /* size of base64 encoded string for this binary length, add NULL terminator */
+
+ char * b64_out = be_pushbuffer(vm, b64_len);
+ size_t converted = encode_base64(attr.bufptr, len, (unsigned char*)b64_out);
+
+ be_pushnstring(vm, b64_out, converted); /* make string from buffer */
+ be_remove(vm, -2); /* remove buffer */
+ be_return(vm);
+}
+
+/*
+ * Converts base63 to bytes()
+ *
+ * `bytes().fromb64() -> bytes()`
+ */
+static int m_fromb64(bvm *vm)
+{
+ int argc = be_top(vm);
+ if (argc >= 2 && be_isstring(vm, 2)) {
+ const char *s = be_tostring(vm, 2);
+ int32_t bin_len = decode_base64_length((unsigned char*)s); /* do a first pass to calculate the buffer size */
+
+ buf_impl attr = m_read_attributes(vm, 1);
+ if (attr.fixed && attr.len != bin_len) {
+ be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
+ }
+ bytes_resize(vm, &attr, bin_len); /* resize if needed */
+ if (bin_len > attr.size) { /* avoid overflow */
+ be_raise(vm, "memory_error", "cannot allocate buffer");
+ }
+
+ int32_t bin_len_final = decode_base64((unsigned char*)s, attr.bufptr); /* decode */
+ attr.len = bin_len_final;
+ be_pop(vm, 1); /* remove arg to leave instance */
+ m_write_attributes(vm, 1, &attr); /* update instance */
+ be_return(vm);
+ }
+ be_raise(vm, "type_error", "operand must be a string");
+ be_return_nil(vm);
+}
+
+
+/*
+ * Advanced API
+ */
+
+/*
+ * Retrieve the memory address of the raw buffer
+ * to be used in C functions.
+ *
+ * Note: the address is guaranteed not to move unless you
+ * resize the buffer
+ *
+ * `_buffer() -> comptr`
+ */
+static int m_buffer(bvm *vm)
+{
+ buf_impl attr = m_read_attributes(vm, 1);
+ be_pushcomptr(vm, attr.bufptr);
+ be_return(vm);
+}
+
+/*
+ * External API
+ */
+BERRY_API void * be_pushbytes(bvm *vm, const void * bytes, size_t len)
+{
+ bytes_new_object(vm, len);
+ buf_impl attr = m_read_attributes(vm, -1);
+ if ((int32_t)len > attr.size) { len = attr.size; } /* double check if the buffer allocated was smaller */
+ if (bytes) { /* if bytes is null, buffer is filled with zeros */
+ memmove((void*)attr.bufptr, bytes, len);
+ } else {
+ memset((void*)attr.bufptr, 0, len);
+ }
+ attr.len = len;
+ m_write_attributes(vm, -1, &attr); /* update instance */
+ /* bytes instance is on top of stack */
+ return (void*)attr.bufptr;
+}
+
+BERRY_API const void *be_tobytes(bvm *vm, int rel_index, size_t *len)
+{
+ int index = be_absindex(vm, rel_index);
+ if (be_isbytes(vm, index)) {
+ buf_impl attr = m_read_attributes(vm, index);
+ if (len) { *len = attr.len; }
+ return (void*) attr.bufptr;
+ }
+ if (len) { *len = 0; }
+ return NULL;
+}
+
+BERRY_API bbool be_isbytes(bvm *vm, int rel_index)
+{
+ bbool ret = bfalse;
+ int index = be_absindex(vm, rel_index);
+ if (be_isinstance(vm, index)) {
+ be_getbuiltin(vm, "bytes");
+ if (be_isderived(vm, index)) {
+ ret = btrue;
+ }
+ be_pop(vm, 1);
+ }
+ return ret;
+}
+
+/* Helper code to compile bytecode
+
+
+class Bytes : bytes
+#-------------------------------------------------------------
+#- 'getbits' function
+#-
+#- Reads a bit-field in a `bytes()` object
+#-
+#- Input:
+#- offset_bits (int): bit number to start reading from (0 = LSB)
+#- len_bits (int): how many bits to read
+#- Output:
+#- valuer (int)
+#-------------------------------------------------------------#
+ def getbits(offset_bits, len_bits)
+ if len_bits <= 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end
+ var ret = 0
+
+ var offset_bytes = offset_bits >> 3
+ offset_bits = offset_bits % 8
+
+ var bit_shift = 0 #- bit number to write to -#
+
+ while (len_bits > 0)
+ var block_bits = 8 - offset_bits # how many bits to read in the current block (block = byte) -#
+ if block_bits > len_bits block_bits = len_bits end
+
+ var mask = ( (1<> offset_bits) << bit_shift)
+
+ #- move the input window -#
+ bit_shift += block_bits
+ len_bits -= block_bits
+ offset_bits = 0 #- start at full next byte -#
+ offset_bytes += 1
+ end
+
+ return ret
+ end
+
+ #-------------------------------------------------------------
+ #- 'setbits' function
+ #-
+ #- Writes a bit-field in a `bytes()` object
+ #-
+ #- Input:
+ #- offset_bits (int): bit number to start writing to (0 = LSB)
+ #- len_bits (int): how many bits to write
+ #- val (int): value to set
+ #-------------------------------------------------------------#
+ def setbits(offset_bits, len_bits, val)
+ if len_bits < 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end
+
+ val = int(val) #- convert bool or others to int -#
+ var offset_bytes = offset_bits >> 3
+ offset_bits = offset_bits % 8
+
+ while (len_bits > 0)
+ var block_bits = 8 - offset_bits #- how many bits to write in the current block (block = byte) -#
+ if block_bits > len_bits block_bits = len_bits end
+
+ var mask_val = (1<>= block_bits
+ len_bits -= block_bits
+ offset_bits = 0 #- start at full next byte -#
+ offset_bytes += 1
+ end
+ return self
+ end
+end
+
+*/
+
+/********************************************************************
+** Solidified function: getbits
+********************************************************************/
+be_local_closure(getbits, /* name */
+ be_nested_proto(
+ 9, /* nstack */
+ 3, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 5]) { /* constants */
+ /* K0 */ be_const_int(0),
+ /* K1 */ be_nested_str(value_error),
+ /* K2 */ be_nested_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032),
+ /* K3 */ be_const_int(3),
+ /* K4 */ be_const_int(1),
+ }),
+ &be_const_str_getbits,
+ &be_const_str_solidified,
+ ( &(const binstruction[32]) { /* code */
+ 0x180C0500, // 0000 LE R3 R2 K0
+ 0x740E0002, // 0001 JMPT R3 #0005
+ 0x540E001F, // 0002 LDINT R3 32
+ 0x240C0403, // 0003 GT R3 R2 R3
+ 0x780E0000, // 0004 JMPF R3 #0006
+ 0xB0060302, // 0005 RAISE 1 K1 K2
+ 0x580C0000, // 0006 LDCONST R3 K0
+ 0x3C100303, // 0007 SHR R4 R1 K3
+ 0x54160007, // 0008 LDINT R5 8
+ 0x10040205, // 0009 MOD R1 R1 R5
+ 0x58140000, // 000A LDCONST R5 K0
+ 0x24180500, // 000B GT R6 R2 K0
+ 0x781A0011, // 000C JMPF R6 #001F
+ 0x541A0007, // 000D LDINT R6 8
+ 0x04180C01, // 000E SUB R6 R6 R1
+ 0x241C0C02, // 000F GT R7 R6 R2
+ 0x781E0000, // 0010 JMPF R7 #0012
+ 0x5C180400, // 0011 MOVE R6 R2
+ 0x381E0806, // 0012 SHL R7 K4 R6
+ 0x041C0F04, // 0013 SUB R7 R7 K4
+ 0x381C0E01, // 0014 SHL R7 R7 R1
+ 0x94200004, // 0015 GETIDX R8 R0 R4
+ 0x2C201007, // 0016 AND R8 R8 R7
+ 0x3C201001, // 0017 SHR R8 R8 R1
+ 0x38201005, // 0018 SHL R8 R8 R5
+ 0x300C0608, // 0019 OR R3 R3 R8
+ 0x00140A06, // 001A ADD R5 R5 R6
+ 0x04080406, // 001B SUB R2 R2 R6
+ 0x58040000, // 001C LDCONST R1 K0
+ 0x00100904, // 001D ADD R4 R4 K4
+ 0x7001FFEB, // 001E JMP #000B
+ 0x80040600, // 001F RET 1 R3
+ })
+ )
+);
+/*******************************************************************/
+
+/********************************************************************
+** Solidified function: setbits
+********************************************************************/
+be_local_closure(setbits, /* name */
+ be_nested_proto(
+ 10, /* nstack */
+ 4, /* argc */
+ 0, /* varg */
+ 0, /* has upvals */
+ NULL, /* no upvals */
+ 0, /* has sup protos */
+ NULL, /* no sub protos */
+ 1, /* has constants */
+ ( &(const bvalue[ 5]) { /* constants */
+ /* K0 */ be_const_int(0),
+ /* K1 */ be_nested_str(value_error),
+ /* K2 */ be_nested_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032),
+ /* K3 */ be_const_int(3),
+ /* K4 */ be_const_int(1),
+ }),
+ &be_const_str_setbits,
+ &be_const_str_solidified,
+ ( &(const binstruction[37]) { /* code */
+ 0x14100500, // 0000 LT R4 R2 K0
+ 0x74120002, // 0001 JMPT R4 #0005
+ 0x5412001F, // 0002 LDINT R4 32
+ 0x24100404, // 0003 GT R4 R2 R4
+ 0x78120000, // 0004 JMPF R4 #0006
+ 0xB0060302, // 0005 RAISE 1 K1 K2
+ 0x60100009, // 0006 GETGBL R4 G9
+ 0x5C140600, // 0007 MOVE R5 R3
+ 0x7C100200, // 0008 CALL R4 1
+ 0x5C0C0800, // 0009 MOVE R3 R4
+ 0x3C100303, // 000A SHR R4 R1 K3
+ 0x54160007, // 000B LDINT R5 8
+ 0x10040205, // 000C MOD R1 R1 R5
+ 0x24140500, // 000D GT R5 R2 K0
+ 0x78160014, // 000E JMPF R5 #0024
+ 0x54160007, // 000F LDINT R5 8
+ 0x04140A01, // 0010 SUB R5 R5 R1
+ 0x24180A02, // 0011 GT R6 R5 R2
+ 0x781A0000, // 0012 JMPF R6 #0014
+ 0x5C140400, // 0013 MOVE R5 R2
+ 0x381A0805, // 0014 SHL R6 K4 R5
+ 0x04180D04, // 0015 SUB R6 R6 K4
+ 0x541E00FE, // 0016 LDINT R7 255
+ 0x38200C01, // 0017 SHL R8 R6 R1
+ 0x041C0E08, // 0018 SUB R7 R7 R8
+ 0x94200004, // 0019 GETIDX R8 R0 R4
+ 0x2C201007, // 001A AND R8 R8 R7
+ 0x2C240606, // 001B AND R9 R3 R6
+ 0x38241201, // 001C SHL R9 R9 R1
+ 0x30201009, // 001D OR R8 R8 R9
+ 0x98000808, // 001E SETIDX R0 R4 R8
+ 0x3C0C0605, // 001F SHR R3 R3 R5
+ 0x04080405, // 0020 SUB R2 R2 R5
+ 0x58040000, // 0021 LDCONST R1 K0
+ 0x00100904, // 0022 ADD R4 R4 K4
+ 0x7001FFE8, // 0023 JMP #000D
+ 0x80040000, // 0024 RET 1 R0
+ })
+ )
+);
+/*******************************************************************/
+
+#if !BE_USE_PRECOMPILED_OBJECT
+void be_load_byteslib(bvm *vm)
+{
+ static const bnfuncinfo members[] = {
+ { ".p", NULL },
+ { ".size", NULL },
+ { ".len", NULL },
+ { "_buffer", m_buffer },
+ { "init", m_init },
+ { "deinit", m_deinit },
+ { "tostring", m_tostring },
+ { "asstring", m_asstring },
+ { "fromstring", m_fromstring },
+ { "tob64", m_tob64 },
+ { "fromb64", m_fromb64 },
+ { "add", m_add },
+ { "get", m_getu },
+ { "geti", m_geti },
+ { "set", m_set },
+ { "seti", m_set }, // setters for signed and unsigned are identical
+ { "item", m_item },
+ { "setitem", m_setitem },
+ { "size", m_size },
+ { "resize", m_resize },
+ { "clear", m_clear },
+ { "copy", m_copy },
+ { "+", m_merge },
+ { "..", m_connect },
+ { "==", m_equal },
+ { "!=", m_nequal },
+
+ { NULL, (bntvfunc) BE_CLOSURE }, /* mark section for berry closures */
+ { "getbits", (bntvfunc) &getbits_closure },
+ { "setbits", (bntvfunc) &setbits_closure },
+
+ { NULL, NULL }
+ };
+ be_regclass(vm, "bytes", members);
+}
+#else
+/* @const_object_info_begin
+class be_class_bytes (scope: global, name: bytes) {
+ .p, var
+ .size, var
+ .len, var
+ _buffer, func(m_buffer)
+ init, func(m_init)
+ deinit, func(m_deinit)
+ tostring, func(m_tostring)
+ asstring, func(m_asstring)
+ fromstring, func(m_fromstring)
+ tob64, func(m_tob64)
+ fromb64, func(m_fromb64)
+ add, func(m_add)
+ get, func(m_getu)
+ geti, func(m_geti)
+ set, func(m_set)
+ seti, func(m_set)
+ item, func(m_item)
+ setitem, func(m_setitem)
+ size, func(m_size)
+ resize, func(m_resize)
+ clear, func(m_clear)
+ copy, func(m_copy)
+ +, func(m_merge)
+ .., func(m_connect)
+ ==, func(m_equal)
+ !=, func(m_nequal)
+
+ getbits, closure(getbits_closure)
+ setbits, closure(setbits_closure)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_be_class_bytes.h"
+#endif
diff --git a/lib/libesp32/berry/src/be_class.c b/lib/libesp32/berry/src/be_class.c
new file mode 100644
index 000000000..0f4efb3d5
--- /dev/null
+++ b/lib/libesp32/berry/src/be_class.c
@@ -0,0 +1,360 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_class.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_map.h"
+#include "be_exec.h"
+#include "be_gc.h"
+#include "be_vm.h"
+#include "be_func.h"
+#include "be_var.h"
+#include
+
+#define check_members(vm, c) \
+ if (!(c)->members) { \
+ (c)->members = be_map_new(vm); \
+ }
+
+bclass* be_newclass(bvm *vm, bstring *name, bclass *super)
+{
+ bgcobject *gco = be_gcnew(vm, BE_CLASS, bclass);
+ bclass *obj = cast_class(gco);
+ bvalue *buf = be_incrtop(vm); /* protect new objects from GC */
+ var_setclass(buf, obj);
+ if (obj) {
+ obj->super = super;
+ obj->members = NULL; /* gc protection */
+ obj->nvar = 0;
+ obj->name = name;
+ }
+ be_stackpop(vm, 1);
+ return obj;
+}
+
+void be_class_compress(bvm *vm, bclass *c)
+{
+ if (!gc_isconst(c) && c->members) {
+ be_map_compact(vm, c->members); /* clear space */
+ }
+}
+
+int be_class_attribute(bvm *vm, bclass *c, bstring *attr)
+{
+ for (; c; c = c->super) {
+ if (c->members) {
+ bvalue *v = be_map_findstr(vm, c->members, attr);
+ if (v) {
+ return var_type(v);
+ }
+ }
+ }
+ return BE_NONE;
+}
+
+void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var)
+{
+ bvalue *attr;
+ set_fixed(name);
+ check_members(vm, c);
+ attr = be_map_insertstr(vm, c->members, name, NULL);
+ restore_fixed(name);
+ if (var) {
+ /* this is an instance variable so we set it as MT_VARIABLE */
+ attr->v.i = c->nvar++;
+ attr->type = MT_VARIABLE;
+ } else {
+ /* this is a static class constant, leave it as BE_NIL */
+ attr->v.i = 0;
+ attr->type = BE_NIL;
+ }
+}
+
+void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static)
+{
+ bclosure *cl;
+ bvalue *attr;
+ set_fixed(name);
+ check_members(vm, c);
+ attr = be_map_insertstr(vm, c->members, name, NULL);
+ restore_fixed(name);
+ var_setnil(attr);
+ cl = be_newclosure(vm, p->nupvals);
+ cl->proto = p;
+ var_setclosure(attr, cl);
+ if (is_static) {
+ func_setstatic(attr);
+ }
+}
+
+void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
+{
+ bvalue *attr;
+ set_fixed(name);
+ check_members(vm, c);
+ attr = be_map_insertstr(vm, c->members, name, NULL);
+ restore_fixed(name);
+ attr->v.nf = f;
+ attr->type = MT_PRIMMETHOD;
+}
+
+void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl)
+{
+ bvalue *attr;
+ check_members(vm, c);
+ attr = be_map_insertstr(vm, c->members, name, NULL);
+ attr->v.gc = (bgcobject*) cl;
+ attr->type = MT_METHOD;
+}
+
+/* get the closure method count that need upvalues */
+int be_class_closure_count(bclass *c)
+{
+ int count = 0;
+ if (c->members) {
+ bmapnode *node;
+ bmap *members = c->members;
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(members, &iter)) != NULL) {
+ if (var_isproto(&node->value)) {
+ ++count;
+ }
+ }
+ }
+ return count;
+}
+
+static binstance* instance_member(bvm *vm,
+ binstance *obj, bstring *name, bvalue *dst)
+{
+ for (; obj; obj = obj->super) {
+ bmap *members = obj->_class->members;
+ if (members) {
+ bvalue *v = be_map_findstr(vm, members, name);
+ if (v) {
+ *dst = *v;
+ return obj;
+ }
+ }
+ }
+ var_setnil(dst);
+ return NULL;
+}
+
+static bclass* class_member(bvm *vm,
+ bclass *obj, bstring *name, bvalue *dst)
+{
+ for (; obj; obj = obj->super) {
+ bmap *members = obj->members;
+ if (members) {
+ bvalue *v = be_map_findstr(vm, members, name);
+ if (v) {
+ *dst = *v;
+ return obj;
+ }
+ }
+ }
+ var_setnil(dst);
+ return NULL;
+}
+
+void be_class_upvalue_init(bvm *vm, bclass *c)
+{
+ bmap *mbr = c->members;
+ if (mbr != NULL) {
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(mbr, &iter)) != NULL) {
+ if (var_isclosure(&node->value)) {
+ bclosure *cl = var_toobj(&node->value);
+ if (cl->proto->nupvals) {
+ /* initialize the closure's upvalues */
+ be_release_upvalues(vm, cl);
+ be_initupvals(vm, cl);
+ }
+ }
+ }
+ }
+}
+
+/* (internal) Instanciate an instance for a single class and initialize variables to nil */
+static binstance* newobjself(bvm *vm, bclass *c)
+{
+ size_t size = sizeof(binstance) + sizeof(bvalue) * (c->nvar - 1);
+ bgcobject *gco = be_newgcobj(vm, BE_INSTANCE, size);
+ binstance *obj = cast_instance(gco);
+ be_assert(obj != NULL);
+ if (obj) { /* initialize members */
+ bvalue *v = obj->members, *end = v + c->nvar; /* instance variables is a simple array of pointers at obj->members of size c->nvar */
+ while (v < end) { var_setnil(v); ++v; } /* Initialize all instance variables to `nil` */
+ obj->_class = c; /* set its class object */
+ obj->super = NULL; /* no super class instance for now */
+ obj->sub = NULL; /* no subclass instance for now */
+ }
+ return obj;
+}
+
+/* (internal) Instanciate the whole chain of instances when there is a class hierarchy */
+/* All variables set to nil, constructors are not called here */
+static binstance* newobject(bvm *vm, bclass *c)
+{
+ binstance *obj, *prev;
+ be_assert(c != NULL);
+ obj = prev = newobjself(vm, c);
+ var_setinstance(vm->top, obj);
+ be_incrtop(vm); /* protect new objects from GC */
+ for (c = c->super; c; c = c->super) { /* initialize one instance object per class and per superclass */
+ prev->super = newobjself(vm, c);
+ prev->super->sub = prev; /* link the super/sub classes instances */
+ prev = prev->super;
+ }
+ be_stackpop(vm, 1);
+ return obj;
+}
+
+/* Instanciate new instance from stack with argc parameters */
+/* Pushes the constructor on the stack to be executed if a construtor is found */
+/* Returns true if a constructor is found */
+bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode)
+{
+ bvalue init;
+ binstance *obj = newobject(vm, c); /* create empty object hierarchy from class hierarchy */
+ // reg = vm->reg + pos - mode; /* the stack may have changed, mode=1 when class is instanciated from module #104 */
+ var_setinstance(vm->reg + pos, obj);
+ var_setinstance(vm->reg + pos - mode, obj); /* copy to reg and reg+1 if mode==1 */
+ /* find constructor */
+ obj = instance_member(vm, obj, str_literal(vm, "init"), &init);
+ if (obj && var_type(&init) != MT_VARIABLE) {
+ /* copy argv */
+ bvalue * reg;
+ for (reg = vm->reg + pos + 1; argc > 0; --argc) {
+ reg[argc] = reg[argc - 2];
+ }
+ *reg = init; /* set constructor */
+ return btrue;
+ }
+ return bfalse;
+}
+
+/* Default empty constructor */
+static int default_init_native_method(bvm *vm) {
+ be_return_nil(vm);
+}
+
+/* Find instance member by name and copy value to `dst` */
+/* Do not look into virtual members */
+int be_instance_member_simple(bvm *vm, binstance *instance, bstring *name, bvalue *dst)
+{
+ int type;
+ be_assert(name != NULL);
+ binstance * obj = instance_member(vm, instance, name, dst);
+ type = var_type(dst);
+ if (obj && type == MT_VARIABLE) {
+ *dst = obj->members[dst->v.i];
+ }
+ return type;
+}
+
+/* Find instance member by name and copy value to `dst` */
+/* Input: none of `obj`, `name` and `dst` may not be NULL */
+/* Returns the type of the member or BE_NONE if member not found */
+/* TODO need to support synthetic members */
+int be_instance_member(bvm *vm, binstance *instance, bstring *name, bvalue *dst)
+{
+ int type;
+ be_assert(name != NULL);
+ binstance * obj = instance_member(vm, instance, name, dst);
+ type = var_type(dst);
+ if (obj && type == MT_VARIABLE) {
+ *dst = obj->members[dst->v.i];
+ }
+ if (obj) {
+ return type;
+ } else { /* if no method found, try virtual */
+ /* if 'init' does not exist, create a virtual empty constructor */
+ if (strcmp(str(name), "init") == 0) {
+ var_setntvfunc(dst, default_init_native_method);
+ return var_type(dst);
+ } else {
+ /* get method 'member' */
+ obj = instance_member(vm, instance, str_literal(vm, "member"), vm->top);
+ if (obj && basetype(var_type(vm->top)) == BE_FUNCTION) {
+ bvalue *top = vm->top;
+ var_setinstance(&top[1], instance);
+ var_setstr(&top[2], name);
+ vm->top += 3; /* prevent gc collection results */
+ be_dofunc(vm, top, 2); /* call method 'member' */
+ vm->top -= 3;
+ *dst = *vm->top; /* copy result to R(A) */
+ if (obj && var_type(dst) == MT_VARIABLE) {
+ *dst = obj->members[dst->v.i];
+ }
+ type = var_type(dst);
+ if (type != BE_NIL) {
+ return type;
+ }
+ }
+ }
+ }
+ return BE_NONE;
+}
+
+int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst)
+{
+ int type;
+ be_assert(name != NULL);
+ obj = class_member(vm, obj, name, dst);
+ type = var_type(dst);
+ if (obj) {
+ return type;
+ } else {
+ return BE_NONE;
+ }
+}
+
+bbool be_instance_setmember(bvm *vm, binstance *o, bstring *name, bvalue *src)
+{
+ bvalue v;
+ be_assert(name != NULL);
+ binstance * obj = instance_member(vm, o, name, &v);
+ if (obj && var_istype(&v, MT_VARIABLE)) {
+ obj->members[var_toint(&v)] = *src;
+ return btrue;
+ } else {
+ obj = instance_member(vm, o, str_literal(vm, "setmember"), &v);
+ if (obj && var_type(&v) == MT_VARIABLE) {
+ v = obj->members[v.v.i];
+ }
+ if (var_basetype(&v) == BE_FUNCTION) {
+ bvalue *top = vm->top;
+ var_setval(top, &v);
+ var_setinstance(top + 1, o); /* move instance to argv[0] */
+ var_setstr(top + 2, name); /* move method name to argv[1] */
+ var_setval(top + 3, src); /* move method name to argv[1] */
+ vm->top += 4; /* prevent collection results */
+ be_dofunc(vm, top, 3); /* call method 'member' */
+ vm->top -= 4;
+ return btrue;
+ }
+ }
+ return bfalse;
+}
+
+bbool be_class_setmember(bvm *vm, bclass *o, bstring *name, bvalue *src)
+{
+ bvalue v;
+ be_assert(name != NULL);
+ if (!gc_isconst(o)) {
+ bclass * obj = class_member(vm, o, name, &v);
+ if (obj && !var_istype(&v, MT_VARIABLE)) {
+ be_map_insertstr(vm, obj->members, name, src);
+ return btrue;
+ }
+ }
+ return bfalse;
+}
diff --git a/lib/libesp32/berry/src/be_class.h b/lib/libesp32/berry/src/be_class.h
new file mode 100644
index 000000000..405ea6d38
--- /dev/null
+++ b/lib/libesp32/berry/src/be_class.h
@@ -0,0 +1,68 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_CLASS_H
+#define BE_CLASS_H
+
+#include "be_object.h"
+
+#define MT_VARIABLE BE_INDEX
+#define MT_METHOD BE_CLOSURE
+#define MT_PRIMMETHOD BE_NTVFUNC
+
+#define be_class_name(cl) ((cl)->name)
+#define be_class_members(cl) ((cl)->members)
+#define be_class_super(cl) ((cl)->super)
+#define be_class_setsuper(self, sup) ((self)->super = (sup))
+#define be_class_setsub(self, sub) ((self)->sub = (sub))
+#define be_instance_name(obj) ((obj)->_class->name)
+#define be_instance_class(obj) ((obj)->_class)
+#define be_instance_members(obj) ((obj)->members)
+#define be_instance_member_count(obj) ((obj)->_class->nvar)
+#define be_instance_super(obj) ((obj)->super)
+#define be_instance_sub(obj) ((obj)->sub)
+
+struct bclass {
+ bcommon_header;
+ uint16_t nvar; /* members variable data field count */
+ struct bclass *super;
+ bmap *members;
+ bstring *name;
+ bgcobject *gray; /* for gc gray list */
+#ifdef __cplusplus
+ BE_CONSTEXPR bclass(uint16_t nv, bclass *sup, bmap *mem, bstring *s) :
+ next(0), type(BE_CLASS), marked(GC_CONST), nvar(nv),
+ super(sup), members(mem), name(s), gray(0) {}
+#endif
+};
+
+struct binstance {
+ bcommon_header;
+ struct binstance *super;
+ struct binstance *sub;
+ bclass *_class;
+ bgcobject *gray; /* for gc gray list */
+ bvalue members[1]; /* members variable data field */
+};
+
+bclass* be_newclass(bvm *vm, bstring *name, bclass *super);
+void be_class_compress(bvm *vm, bclass *c);
+int be_class_attribute(bvm *vm, bclass *c, bstring *attr);
+void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var);
+void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static);
+void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f);
+void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl);
+int be_class_closure_count(bclass *c);
+void be_class_upvalue_init(bvm *vm, bclass *c);
+bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode);
+int be_instance_member_simple(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
+int be_instance_member(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
+int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst);
+bbool be_instance_setmember(bvm *vm, binstance *obj, bstring *name, bvalue *src);
+bbool be_class_setmember(bvm *vm, bclass *obj, bstring *name, bvalue *src);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_code.c b/lib/libesp32/berry/src/be_code.c
new file mode 100644
index 000000000..40e067265
--- /dev/null
+++ b/lib/libesp32/berry/src/be_code.c
@@ -0,0 +1,930 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_code.h"
+#include "be_decoder.h"
+#include "be_parser.h"
+#include "be_lexer.h"
+#include "be_vector.h"
+#include "be_list.h"
+#include "be_var.h"
+#include "be_exec.h"
+#include "be_vm.h"
+
+#define NOT_MASK (1 << 0)
+#define NOT_EXPR (1 << 1)
+#define FUNC_RET_FLAG (1 << 0)
+
+#define isset(v, mask) (((v) & (mask)) != 0)
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define notexpr(e) isset((e)->not, NOT_EXPR)
+#define notmask(e) isset((e)->not, NOT_MASK)
+#define exp2anyreg(f, e) exp2reg(f, e, -1) /* -1 means allocate a new register if needed */
+#define var2anyreg(f, e) var2reg(f, e, -1) /* -1 means allocate a new register if needed */
+#define hasjump(e) ((e)->t != (e)->f || notexpr(e))
+#define code_bool(f, r, b, j) codeABC(f, OP_LDBOOL, r, b, j)
+#define code_call(f, a, b) codeABC(f, OP_CALL, a, b, 0)
+#define code_getmbr(f, a, b, c) codeABC(f, OP_GETMBR, a, b, c)
+#define jumpboolop(e, b) ((b) != notmask(e) ? OP_JMPT : OP_JMPF)
+
+#if BE_USE_SCRIPT_COMPILER
+
+static int var2reg(bfuncinfo *finfo, bexpdesc *e, int dst);
+
+#if BE_DEBUG_RUNTIME_INFO
+static void codelineinfo(bfuncinfo *finfo)
+{
+ bvector *vec = &finfo->linevec;
+ int line = finfo->lexer->lastline;
+ blineinfo *li = be_vector_end(vec);
+ if (be_vector_isempty(vec) || li->linenumber != line) {
+ be_vector_push(finfo->lexer->vm, vec, NULL);
+ li = be_vector_end(vec);
+ li->endpc = finfo->pc;
+ li->linenumber = line;
+ finfo->proto->lineinfo = be_vector_data(vec);
+ finfo->proto->nlineinfo = be_vector_capacity(vec);
+ } else {
+ li->endpc = finfo->pc;
+ }
+}
+#else
+ #define codelineinfo(finfo)
+#endif
+
+/* Add new instruction in the code vector */
+static int codeinst(bfuncinfo *finfo, binstruction ins)
+{
+ /* put new instruction in code array */
+ be_vector_push_c(finfo->lexer->vm, &finfo->code, &ins);
+ finfo->proto->code = be_vector_data(&finfo->code);
+ finfo->proto->codesize = be_vector_capacity(&finfo->code);
+ codelineinfo(finfo);
+ return finfo->pc++;
+}
+
+static int codeABC(bfuncinfo *finfo, bopcode op, int a, int b, int c)
+{
+ return codeinst(finfo, ISET_OP(op)
+ | ISET_RA(a) | ISET_RKB(b) | ISET_RKC(c));
+}
+
+static int codeABx(bfuncinfo *finfo, bopcode op, int a, int bx)
+{
+ return codeinst(finfo, ISET_OP(op) | ISET_RA(a) | ISET_Bx(bx));
+}
+
+/* Move value from register b to register a */
+/* Check the previous instruction to compact both instruction as one if possible */
+/* If b is a constant, add LDCONST or add MOVE otherwise */
+static void code_move(bfuncinfo *finfo, int a, int b)
+{
+ if (finfo->pc) { /* If not the first instruction of the function */
+ binstruction *i = be_vector_end(&finfo->code); /* get the last instruction */
+ bopcode op = IGET_OP(*i);
+ if (op <= OP_LDNIL) { /* binop or unop */
+ /* remove redundant MOVE instruction */
+ int x = IGET_RA(*i), y = IGET_RKB(*i), z = IGET_RKC(*i);
+ if (b == x && (a == y || (op < OP_NEG && a == z))) {
+ *i = (*i & ~IRA_MASK) | ISET_RA(a);
+ return;
+ }
+ }
+ }
+ if (isK(b)) {
+ codeABx(finfo, OP_LDCONST, a, b & 0xFF);
+ } else {
+ codeABC(finfo, OP_MOVE, a, b, 0);
+ }
+}
+
+/* Free register at top (checks that it´s a register) */
+/* Warning: the register must be at top of stack */
+static void free_expreg(bfuncinfo *finfo, bexpdesc *e)
+{
+ /* release temporary register */
+ if (e && e->type == ETREG) {
+ be_code_freeregs(finfo, 1);
+ }
+}
+
+/* Privat. Allocate `count` new registers on the stack and uptade proto´s max nstack accordingly */
+/* Note: deallocate is simpler and handled by a macro */
+static void allocstack(bfuncinfo *finfo, int count)
+{
+ int nstack = finfo->freereg + count;
+ if (nstack > finfo->proto->nstack) {
+ if (nstack >= 255) {
+ be_lexerror(finfo->lexer, "register overflow (more than 255)");
+ }
+ finfo->proto->nstack = (bbyte)nstack;
+ }
+}
+
+/* Allocate `count` registers at top of stack, update stack accordingly */
+int be_code_allocregs(bfuncinfo *finfo, int count)
+{
+ int base = finfo->freereg;
+ allocstack(finfo, count);
+ finfo->freereg += (char)count;
+ return base;
+}
+
+static void setjump(bfuncinfo *finfo, int pc, int dst)
+{
+ binstruction *p = be_vector_at(&finfo->code, pc);
+ int offset = dst - (pc + 1);
+ /* instruction edit jump destination */
+ *p = (*p & ~IBx_MASK) | ISET_sBx(offset);
+}
+
+static int isjumpbool(bfuncinfo *finfo, int pc)
+{
+ binstruction *p = be_vector_at(&finfo->code, pc);
+ bopcode op = IGET_OP(*p);
+
+ if (op == OP_JMPT || op == OP_JMPF) {
+ return 1;
+ }
+ return 0;
+}
+
+static int get_jump(bfuncinfo *finfo, int pc)
+{
+ binstruction *i = be_vector_at(&finfo->code, pc);
+ int offset = IGET_sBx(*i);
+ return offset == NO_JUMP ? NO_JUMP : pc + 1 + offset;
+}
+
+static void patchlistaux(bfuncinfo *finfo, int list, int vtarget, int dtarget)
+{
+ while (list != NO_JUMP) {
+ int next = get_jump(finfo, list);
+ if (isjumpbool(finfo, list)) {
+ setjump(finfo, list, dtarget); /* jump to default target */
+ } else {
+ setjump(finfo, list, vtarget);
+ }
+ list = next;
+ }
+}
+
+static int appendjump(bfuncinfo *finfo, bopcode op, bexpdesc *e)
+{
+ int reg = e ? var2anyreg(finfo, e) : 0;
+ if (isK(reg)) {
+ reg = be_code_allocregs(finfo, 1);
+ code_move(finfo, reg, e->v.idx);
+ e->v.idx = reg;
+ e->type = ETREG;
+ }
+ return codeABx(finfo, op, reg, NO_JUMP + IsBx_MAX);
+}
+
+int be_code_jump(bfuncinfo *finfo)
+{
+ return appendjump(finfo, OP_JMP, NULL);
+}
+
+void be_code_jumpto(bfuncinfo *finfo, int dst)
+{
+ be_code_patchlist(finfo, be_code_jump(finfo), dst);
+}
+
+void be_code_jumpbool(bfuncinfo *finfo, bexpdesc *e, int jture)
+{
+ int pc = appendjump(finfo, jumpboolop(e, jture), e);
+ be_code_conjump(finfo, jture ? &e->t : &e->f, pc);
+ be_code_patchjump(finfo, jture ? e->f : e->t);
+ free_expreg(finfo, e);
+ jture ? (e->f = NO_JUMP) : (e->t = NO_JUMP);
+ e->not = 0;
+}
+
+/* connect jump */
+void be_code_conjump(bfuncinfo *finfo, int *list, int jmp)
+{
+ if (jmp == NO_JUMP) {
+ return;
+ }
+ if (*list == NO_JUMP) {
+ *list = jmp;
+ } else {
+ int next, l = *list;
+ while ((next = (get_jump(finfo, l))) != NO_JUMP) {
+ l = next;
+ }
+ setjump(finfo, l, jmp);
+ }
+}
+
+void be_code_patchlist(bfuncinfo *finfo, int list, int dst)
+{
+ if (dst == finfo->pc) {
+ be_code_patchjump(finfo, list);
+ } else {
+ patchlistaux(finfo, list, dst, dst);
+ }
+}
+
+void be_code_patchjump(bfuncinfo *finfo, int jmp)
+{
+ patchlistaux(finfo, jmp, finfo->pc, finfo->pc);
+}
+
+/* Allocate new constant for value k */
+/* If k is NULL then push `nil` value */
+static int newconst(bfuncinfo *finfo, bvalue *k)
+{
+ int idx = be_vector_count(&finfo->kvec);
+ be_vector_push_c(finfo->lexer->vm, &finfo->kvec, k);
+ finfo->proto->ktab = be_vector_data(&finfo->kvec);
+ finfo->proto->nconst = be_vector_capacity(&finfo->kvec);
+ if (k == NULL) {
+ var_setnil(&finfo->proto->ktab[idx]);
+ }
+ return idx;
+}
+
+/* Find constant by value and return constant number, or -1 if constant does not exist */
+/* The search is linear and limited to BE_CONST_SEARCH_SIZE elements for performance reasons */
+static int findconst(bfuncinfo *finfo, bexpdesc *e)
+{
+ int i, count = be_vector_count(&finfo->kvec);
+ /* if the constant table is too large, the lookup
+ * operation will become very time consuming.
+ * so only search the constant table for the
+ * previous value.
+ **/
+ count = count < BE_CONST_SEARCH_SIZE ? count : BE_CONST_SEARCH_SIZE;
+ for (i = 0; i < count; ++i) {
+ bvalue *k = be_vector_at(&finfo->kvec, i);
+ switch (e->type) {
+ case ETINT:
+ if (var_isint(k) && k->v.i == e->v.i) {
+ return i;
+ }
+ break;
+ case ETREAL:
+ if (var_isreal(k) && k->v.r == e->v.r) {
+ return i;
+ }
+ break;
+ case ETSTRING:
+ if (var_isstr(k) && be_eqstr(k->v.p, e->v.s)) {
+ return i;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return -1;
+}
+
+/* convert expdesc to constant and return kreg index (either constant kindex or register number) */
+static int exp2const(bfuncinfo *finfo, bexpdesc *e)
+{
+ int idx = findconst(finfo, e); /* does the constant already exist? */
+ if (idx == -1) { /* if not add it */
+ bvalue k;
+ switch (e->type) {
+ case ETINT:
+ k.type = BE_INT;
+ k.v.i = e->v.i;
+ break;
+ case ETREAL:
+ k.type = BE_REAL;
+ k.v.r = e->v.r;
+ break;
+ case ETSTRING:
+ k.type = BE_STRING;
+ k.v.s = e->v.s;
+ break;
+ default: /* all other values are filled later */
+ break;
+ }
+ idx = newconst(finfo, &k); /* create new constant */
+ }
+ if (idx < 256) { /* if constant number fits in KB or KC */
+ e->type = ETCONST; /* new type is constant by index */
+ e->v.idx = setK(idx);
+ } else { /* index value is too large */
+ e->type = ETREG; /* does not fit in compact mode, allocate an explicit register and emit LDCONTS */
+ e->v.idx = be_code_allocregs(finfo, 1);
+ codeABx(finfo, OP_LDCONST, e->v.idx, idx);
+ }
+ return e->v.idx;
+}
+
+static void free_suffix(bfuncinfo *finfo, bexpdesc *e)
+{
+ int idx = e->v.ss.idx;
+ int nlocal = be_list_count(finfo->local);
+ /* release suffix register */
+ if (!isK(idx) && idx >= nlocal) {
+ be_code_freeregs(finfo, 1);
+ }
+ /* release object register */
+ if (e->v.ss.tt == ETREG && (int)e->v.ss.obj >= nlocal && (e->v.ss.obj + 1 >= finfo->freereg)) {
+ be_code_freeregs(finfo, 1);
+ }
+}
+
+static int suffix_destreg(bfuncinfo *finfo, bexpdesc *e1, int dst, bbool no_reg_reuse)
+{
+ int cand_dst = dst; /* candidate for new dst */
+ int nlocal = be_list_count(finfo->local);
+ int reg1 = (e1->v.ss.tt == ETREG) ? e1->v.ss.obj : -1; /* check if obj is ETREG or -1 */
+ int reg2 = (!isK(e1->v.ss.idx) && e1->v.ss.idx >= nlocal) ? e1->v.ss.idx : -1; /* check if idx is ETREG or -1 */
+ if (no_reg_reuse) { /* if no_reg_reuse flag, then don't reuse any register, this is useful for compound assignments */
+ reg1 = reg2 = -1;
+ }
+
+ if (reg1 >= 0 && reg2 >= 0) {
+ /* both are ETREG, we keep the lowest and discard the other */
+ if (reg1 != reg2) {
+ cand_dst = min(reg1, reg2);
+ be_code_freeregs(finfo, 1); /* and free the other one */
+ } else {
+ cand_dst = reg1; /* both ETREG are equal, we return its value */
+ }
+ } else if (reg1 >= 0) {
+ cand_dst = reg1;
+ } else if (reg2 >= 0) {
+ cand_dst = reg2;
+ } else {
+ // dst unchanged
+ }
+
+ if (dst >= finfo->freereg) {
+ dst = cand_dst; /* if dst was allocating a new register, use the more precise candidate */
+ }
+ return dst;
+}
+
+static int code_suffix(bfuncinfo *finfo, bopcode op, bexpdesc *e, int dst, bbool no_reg_reuse)
+{
+ dst = suffix_destreg(finfo, e, dst, no_reg_reuse);
+ if (dst > finfo->freereg) {
+ dst = finfo->freereg;
+ }
+ codeABC(finfo, op, dst, e->v.ss.obj, e->v.ss.idx);
+ return dst;
+}
+
+/* idx: the proto index in proto_table
+ * dst: the destination register
+ **/
+static void code_closure(bfuncinfo *finfo, int idx, int dst)
+{
+ codeABx(finfo, OP_CLOSURE, dst, idx); /* load closure to register */
+}
+
+/* Given an integer, check if we should create a constant */
+/* True for values 0..3 and if there is room for kindex */
+/* This optimization makes code more compact for commonly used ints */
+static bbool constint(bfuncinfo *finfo, bint i)
+{
+ /* cache common numbers */
+ if ((i < IsBx_MIN || i > IsBx_MAX) ||
+ (i >= 0 && i <= 3 && be_vector_count(&finfo->kvec) < 256)) {
+ return btrue;
+ }
+ return bfalse;
+}
+
+/* Compute variable from an expdesc */
+/* Return constant index, or existing register or fallback to dst */
+/* At exit, If dst is `freereg`, the register is allocated */
+static int var2reg(bfuncinfo *finfo, bexpdesc *e, int dst)
+{
+ bbool no_reg_reuse = (dst >= 0); /* if dst reg is explicitly specified, do not optimize register allocation */
+ if (dst < 0) { /* if unspecified, allocate a new register if needed */
+ dst = finfo->freereg;
+ }
+ be_assert(e != NULL);
+ switch (e->type) {
+ case ETINT:
+ if (constint(finfo, e->v.i)) {
+ return exp2const(finfo, e);
+ } else {
+ codeABx(finfo, OP_LDINT, dst, var_toidx(e) + IsBx_MAX);
+ }
+ break;
+ case ETBOOL:
+ code_bool(finfo, dst, e->v.i != 0, 0);
+ break;
+ case ETNIL:
+ codeABx(finfo, OP_LDNIL, dst, 0);
+ break;
+ case ETREAL:
+ case ETSTRING:
+ return exp2const(finfo, e);
+ case ETPROTO:
+ code_closure(finfo, e->v.idx, dst);
+ break;
+ case ETGLOBAL:
+ codeABx(finfo, OP_GETGBL, dst, e->v.idx);
+ break;
+ case ETNGLOBAL:
+ codeABC(finfo, OP_GETNGBL, dst, e->v.ss.idx, 0);
+ break;
+ case ETUPVAL:
+ codeABx(finfo, OP_GETUPV, dst, e->v.idx);
+ break;
+ case ETMEMBER:
+ dst = code_suffix(finfo, OP_GETMBR, e, dst, no_reg_reuse);
+ break;
+ case ETINDEX:
+ dst = code_suffix(finfo, OP_GETIDX, e, dst, no_reg_reuse);
+ break;
+ case ETLOCAL: case ETREG: case ETCONST:
+ return e->v.idx;
+ default:
+ return dst; /* error */
+ }
+ if (dst == finfo->freereg) { /* use a new register */
+ be_code_allocregs(finfo, 1);
+ }
+ e->type = ETREG;
+ e->v.idx = dst;
+ return dst;
+}
+
+static int exp2reg(bfuncinfo *finfo, bexpdesc *e, int dst)
+{
+ int reg = var2reg(finfo, e, dst);
+ if (hasjump(e)) { /* if conditional expression */
+ int pcf = NO_JUMP; /* position of an eventual LOAD false */
+ int pct = NO_JUMP; /* position of an eventual LOAD true */
+ int jpt = appendjump(finfo, jumpboolop(e, 1), e);
+ reg = e->v.idx;
+ be_code_conjump(finfo, &e->t, jpt);
+ pcf = code_bool(finfo, reg, 0, 1);
+ pct = code_bool(finfo, reg, 1, 0);
+ patchlistaux(finfo, e->f, finfo->pc, pcf);
+ patchlistaux(finfo, e->t, finfo->pc, pct);
+ e->t = NO_JUMP;
+ e->f = NO_JUMP;
+ e->not = 0;
+ }
+ return reg;
+}
+
+/* Select dest registers from both expressions */
+/* If one of them is already a register, keep it */
+/* If e1 or e2 are registers, we keep the lowest and free the highest (that must be at top) */
+/* If none is a register, allocate a new one */
+/* Returns the destination register, guaranteed to be ETREG */
+static int codedestreg(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, int dst)
+{
+ if (dst < 0) { dst = finfo->freereg; }
+ int cand_dst = dst;
+ int con1 = e1->type == ETREG, con2 = e2->type == ETREG;
+
+ if (con1 && con2) {
+ cand_dst = min(e1->v.idx, e2->v.idx);
+ be_code_freeregs(finfo, 1);
+ } else if (con1) {
+ cand_dst = e1->v.idx;
+ } else if (con2) {
+ cand_dst = e2->v.idx;
+ } else {
+ if (dst >= finfo->freereg) {
+ cand_dst = be_code_allocregs(finfo, 1);
+ return cand_dst;
+ }
+ }
+ if (dst >= finfo->freereg) {
+ return cand_dst;
+ } else {
+ return dst;
+ }
+}
+
+/* compute binary expression and update e1 as result */
+/* On exit, e1 is guaranteed to be ETREG, which may have been allocated */
+static void binaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e1, bexpdesc *e2, int dst)
+{
+ int src1 = exp2reg(finfo, e1, dst); /* potentially force the target for src1 reg */
+ int src2 = exp2anyreg(finfo, e2);
+ dst = codedestreg(finfo, e1, e2, dst);
+ codeABC(finfo, op, dst, src1, src2);
+ e1->type = ETREG;
+ e1->v.idx = dst; /* update register as output */
+}
+
+void be_code_prebinop(bfuncinfo *finfo, int op, bexpdesc *e)
+{
+ switch (op) {
+ case OptAnd:
+ be_code_jumpbool(finfo, e, bfalse);
+ break;
+ case OptOr:
+ be_code_jumpbool(finfo, e, btrue);
+ break;
+ default:
+ exp2anyreg(finfo, e);
+ break;
+ }
+}
+
+/* Apply binary operator `op` to e1 and e2, result in e1 */
+void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2, int dst)
+{
+ switch (op) {
+ case OptAnd:
+ var2anyreg(finfo, e2);
+ be_code_conjump(finfo, &e2->f, e1->f);
+ *e1 = *e2;
+ break;
+ case OptOr:
+ var2anyreg(finfo, e2);
+ be_code_conjump(finfo, &e2->t, e1->t);
+ *e1 = *e2;
+ break;
+ case OptAdd: case OptSub: case OptMul: case OptDiv:
+ case OptMod: case OptLT: case OptLE: case OptEQ:
+ case OptNE: case OptGT: case OptGE: case OptConnect:
+ case OptBitAnd: case OptBitOr: case OptBitXor:
+ case OptShiftL: case OptShiftR:
+ binaryexp(finfo, (bopcode)(op - OptAdd), e1, e2, dst);
+ break;
+ default: break;
+ }
+}
+
+/* Apply unary operator and return register number */
+/* If input is register, change in place or allocate new register */
+static void unaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e)
+{
+ int src = exp2anyreg(finfo, e);
+ int dst = e->type == ETREG ? src : be_code_allocregs(finfo, 1);
+ if (!(op == OP_MOVE && src == dst)) {
+ /* skip if MOVE from same src / dst */
+ codeABC(finfo, op, dst, src, 0);
+ }
+ e->type = ETREG;
+ e->v.idx = dst;
+}
+
+/* Apply not to conditional expression */
+/* If literal compute the value */
+/* Or invert t/f subexpressions */
+static void code_not(bfuncinfo *finfo, bexpdesc *e)
+{
+ switch (e->type) {
+ case ETINT: e->v.i = e->v.i == 0; break;
+ case ETREAL: e->v.i = e->v.r == cast(breal, 0); break;
+ case ETNIL: e->v.i = 1; break;
+ case ETBOOL: e->v.i = !e->v.i; break;
+ case ETSTRING: e->v.i = 0; break;
+ default: {
+ unaryexp(finfo, OP_MOVE, e);
+ int temp = e->t;
+ e->t = e->f;
+ e->f = temp;
+ e->not = NOT_EXPR | (e->not ^ NOT_MASK);
+ return;
+ }
+ }
+ e->type = ETBOOL;
+}
+
+/* Negative value of literal or emit NEG opcode */
+static int code_neg(bfuncinfo *finfo, bexpdesc *e)
+{
+ switch (e->type) {
+ case ETINT: e->v.i = -e->v.i; break;
+ case ETREAL: e->v.r = -e->v.r; break;
+ case ETNIL: case ETBOOL: case ETSTRING:
+ return 1; /* error */
+ default:
+ unaryexp(finfo, OP_NEG, e);
+ }
+ return 0;
+}
+
+/* Bit flip of literal or emit FLIP opcode */
+static int code_flip(bfuncinfo *finfo, bexpdesc *e)
+{
+ switch (e->type) {
+ case ETINT: e->v.i = ~e->v.i; break;
+ case ETREAL: case ETNIL: case ETBOOL: case ETSTRING:
+ return 2; /* error */
+ default:
+ unaryexp(finfo, OP_FLIP, e);
+ }
+ return 0;
+}
+
+/* Apply unary operator: not, neg or bitflip */
+int be_code_unop(bfuncinfo *finfo, int op, bexpdesc *e)
+{
+ switch (op) {
+ case OptNot:
+ code_not(finfo, e); break;
+ case OptFlip: /* do nothing */
+ return code_flip(finfo, e);
+ case OptSub:
+ return code_neg(finfo, e);
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void setbgblvar(bfuncinfo *finfo, bopcode op, bexpdesc *e1, int src)
+{
+ if (isK(src)) { /* move const to register */
+ code_move(finfo, finfo->freereg, src);
+ src = finfo->freereg;
+ }
+ codeABC(finfo, op, src, e1->v.idx, 0);
+}
+
+static void setsupvar(bfuncinfo *finfo, bopcode op, bexpdesc *e1, int src)
+{
+ if (isK(src)) { /* move const to register */
+ code_move(finfo, finfo->freereg, src);
+ src = finfo->freereg;
+ }
+ codeABx(finfo, op, src, e1->v.idx);
+}
+
+static void setsfxvar(bfuncinfo *finfo, bopcode op, bexpdesc *e1, int src)
+{
+ int obj = e1->v.ss.obj;
+ free_suffix(finfo, e1);
+ if (isK(obj)) { /* move const to register */
+ code_move(finfo, finfo->freereg, obj);
+ obj = finfo->freereg;
+ }
+ codeABC(finfo, op, obj, e1->v.ss.idx, src);
+}
+
+/* Assign expr e2 to e1 */
+/* e1 must be in a register and have a valid idx */
+/* return 1 if assignment was possible, 0 if type is not compatible */
+int be_code_setvar(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2)
+{
+ int src = exp2reg(finfo, e2,
+ e1->type == ETLOCAL ? e1->v.idx : -1); /* Convert e2 to kreg */
+ /* If e1 is a local variable, use the register */
+
+ if (e1->type != ETLOCAL || e1->v.idx != src) {
+ free_expreg(finfo, e2); /* free source (checks only ETREG) */ /* TODO e2 is at top */
+ }
+ switch (e1->type) {
+ case ETLOCAL: /* It can't be ETREG. */
+ if (e1->v.idx != src) {
+ code_move(finfo, e1->v.idx, src); /* do explicit move only if needed */
+ }
+ break;
+ case ETGLOBAL: /* store to grobal R(A) -> G(Bx) by global index */
+ setsupvar(finfo, OP_SETGBL, e1, src);
+ break;
+ case ETNGLOBAL: /* store to global R(A) -> G(Bx) by name */
+ setbgblvar(finfo, OP_SETNGBL, e1, src);
+ break;
+ case ETUPVAL:
+ setsupvar(finfo, OP_SETUPV, e1, src);
+ break;
+ case ETMEMBER: /* store to member R(A).RK(B) <- RK(C) */
+ setsfxvar(finfo, OP_SETMBR, e1, src);
+ break;
+ case ETINDEX: /* store to member R(A)[RK(B)] <- RK(C) */
+ setsfxvar(finfo, OP_SETIDX, e1, src);
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+/* Get the expdesc as a register */
+/* if already in a register, use the existing register */
+/* if local or const, allocate a new register and copy value */
+int be_code_nextreg(bfuncinfo *finfo, bexpdesc *e)
+{
+ int dst = finfo->freereg;
+ int src = exp2anyreg(finfo, e); /* get variable register index */
+ if (e->type != ETREG) { /* move local and const to new register */
+ code_move(finfo, dst, src);
+ be_code_allocregs(finfo, 1);
+ } else {
+ dst = src;
+ }
+ return dst;
+}
+
+int be_code_getmethod(bfuncinfo *finfo, bexpdesc *e)
+{
+ int dst = finfo->freereg;
+ be_assert(e->type == ETMEMBER);
+ dst = code_suffix(finfo, OP_GETMET, e, dst, bfalse);
+ /* method [object] args */
+ be_code_allocregs(finfo, dst == finfo->freereg ? 2 : 1);
+ return dst;
+}
+
+/* Generate a CALL instruction at base register with argc consecutive values */
+/* i.e. arg1 is base+1... */
+/* Important: argc registers are freed upon call, which are supposed to be registers above base */
+void be_code_call(bfuncinfo *finfo, int base, int argc)
+{
+ codeABC(finfo, OP_CALL, base, argc, 0);
+ be_code_freeregs(finfo, argc);
+}
+
+int be_code_proto(bfuncinfo *finfo, bproto *proto)
+{
+ int idx = be_vector_count(&finfo->pvec);
+ /* append proto to current function proto table */
+ be_vector_push_c(finfo->lexer->vm, &finfo->pvec, &proto);
+ finfo->proto->ptab = be_vector_data(&finfo->pvec);
+ finfo->proto->nproto = be_vector_capacity(&finfo->pvec);
+ return idx;
+}
+
+void be_code_closure(bfuncinfo *finfo, bexpdesc *e, int idx)
+{
+ int reg = (e->type == ETGLOBAL || e->type == ETNGLOBAL) ? finfo->freereg: e->v.idx;
+ code_closure(finfo, idx, reg);
+ if (e->type == ETGLOBAL) { /* store to global R(A) -> G(Bx) */
+ codeABx(finfo, OP_SETGBL, reg, e->v.idx);
+ } else if (e->type == ETNGLOBAL) { /* store R(A) -> GLOBAL[RK(B)] */
+ codeABC(finfo, OP_SETNGBL, reg, e->v.idx, 0);
+ }
+}
+
+void be_code_close(bfuncinfo *finfo, int isret)
+{
+ bblockinfo *binfo = finfo->binfo;
+ if (isret) { /* in 'return' */
+ while (binfo && !binfo->hasupval) {
+ binfo = binfo->prev;
+ }
+ if (binfo) {
+ codeABC(finfo, OP_CLOSE, 0, 0, 0);
+ }
+ } else if (binfo->prev) { /* leave block */
+ if (binfo->hasupval) {
+ codeABC(finfo, OP_CLOSE, binfo->nactlocals, 0, 0);
+ }
+ }
+}
+
+static void leave_function(bfuncinfo *finfo)
+{
+ int try_depth = 0; /* count of exception catch blocks */
+ bblockinfo *binfo = finfo->binfo;
+ for (; binfo; binfo = binfo->prev) {
+ if (binfo->type & BLOCK_EXCEPT) {
+ ++try_depth; /* leave the exception catch block */
+ }
+ }
+ if (try_depth) { /* exception catch blocks that needs to leave */
+ be_code_exblk(finfo, try_depth);
+ }
+}
+
+void be_code_ret(bfuncinfo *finfo, bexpdesc *e)
+{
+ if (finfo->binfo->prev == NULL) {
+ if (finfo->flags & FUNC_RET_FLAG) {
+ return;
+ }
+ finfo->flags |= FUNC_RET_FLAG;
+ }
+ if (e) {
+ int reg = exp2anyreg(finfo, e);
+ be_code_close(finfo, 1);
+ leave_function(finfo);
+ codeABC(finfo, OP_RET, e->type != ETVOID, reg, 0);
+ free_expreg(finfo, e);
+ } else {
+ be_code_close(finfo, 1);
+ codeABC(finfo, OP_RET, 0, 0, 0);
+ }
+}
+
+/* Package a suffix object from `c` with key `k` */
+/* Both expdesc are materialized in kregs */
+static void package_suffix(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k)
+{
+ int key = exp2anyreg(finfo, k);
+ c->v.ss.obj = exp2anyreg(finfo, c);
+ c->v.ss.tt = c->type;
+ c->v.ss.idx = key;
+}
+
+int be_code_nglobal(bfuncinfo *finfo, bexpdesc *k)
+{
+ return exp2anyreg(finfo, k);
+}
+
+/* Package a MEMBER suffix object from `c` with key `k` */
+void be_code_member(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k)
+{
+ package_suffix(finfo, c, k);
+ c->type = ETMEMBER;
+}
+
+/* Package a INDEX suffix object from `c` with key `k` */
+void be_code_index(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k)
+{
+ package_suffix(finfo, c, k);
+ c->type = ETINDEX;
+}
+
+void be_code_class(bfuncinfo *finfo, bexpdesc *dst, bclass *c)
+{
+ int src;
+ bvalue var;
+ var_setclass(&var, c); /* new var of CLASS type */
+ src = newconst(finfo, &var); /* allocate a new constant and return kreg */
+ if (dst->type == ETLOCAL) { /* if target is a local variable, just assign */
+ codeABx(finfo, OP_LDCONST, dst->v.idx, src);
+ } else if (dst->type == ETGLOBAL) { /* otherwise set as global with same name as class name */
+ codeABx(finfo, OP_LDCONST, finfo->freereg, src);
+ codeABx(finfo, OP_SETGBL, finfo->freereg, dst->v.idx);
+ } else if (dst->type == ETNGLOBAL) {
+ codeABx(finfo, OP_LDCONST, finfo->freereg, src);
+ codeABC(finfo, OP_SETNGBL, finfo->freereg, dst->v.idx, 0);
+ }
+ codeABx(finfo, OP_CLASS, 0, src); /* emit CLASS opcode to register class */
+}
+
+void be_code_setsuper(bfuncinfo *finfo, bexpdesc *c, bexpdesc *s)
+{
+ int self = exp2anyreg(finfo, c);
+ int super = exp2anyreg(finfo, s);
+ codeABC(finfo, OP_SETSUPER, self, super, 0);
+ free_expreg(finfo, c);
+ free_expreg(finfo, s);
+}
+
+/* Emit IMPORT opcode for import module */
+/* `m` is module name, is copied to register if not already */
+/* `v` is destination where the imported module is stored */
+/* If destination is a local variable, it is the destination of the IMPORT opcode */
+/* otherwise the value is copied to a temporary register and stored to the destination */
+/* TODO is this optilization useful, isn´t it done anyways by be_code_move optim? */
+void be_code_import(bfuncinfo *finfo, bexpdesc *m, bexpdesc *v)
+{
+ int dst, src = exp2anyreg(finfo, m);
+ if (v->type == ETLOCAL) {
+ dst = v->v.idx;
+ codeABC(finfo, OP_IMPORT, dst, src, 0);
+ } else {
+ dst = be_code_allocregs(finfo, 1);
+ codeABC(finfo, OP_IMPORT, dst, src, 0);
+ m->type = ETREG;
+ m->v.idx = dst;
+ be_code_setvar(finfo, v, m);
+ }
+}
+
+int be_code_exblk(bfuncinfo *finfo, int depth)
+{
+ if (depth == 0) {
+ return appendjump(finfo, OP_EXBLK, NULL);
+ }
+ codeABx(finfo, OP_EXBLK, 1, depth);
+ return 0;
+}
+
+void be_code_catch(bfuncinfo *finfo, int base, int ecnt, int vcnt, int *jmp)
+{
+ codeABC(finfo, OP_CATCH, base, ecnt, vcnt);
+ if (jmp) {
+ *jmp = NO_JUMP; /* reset jump point */
+ be_code_conjump(finfo, jmp, be_code_jump(finfo));
+ }
+}
+
+/* Emit RAISE opcode */
+/* e1 is the exception code */
+/* e2 is the exception description */
+/* both are materialized to a temp register (if not null) */
+void be_code_raise(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2)
+{
+ if (e1) {
+ int src1 = exp2anyreg(finfo, e1);
+ int src2 = e2 ? exp2anyreg(finfo, e2) : 0;
+ codeABC(finfo, OP_RAISE, e2 != NULL, src1, src2);
+ } else {
+ codeABC(finfo, OP_RAISE, 2, 0, 0); /* rethrow the current exception with parameters already on top of stack */
+ }
+ /* release the register occupied by the expression */
+ free_expreg(finfo, e1);
+ free_expreg(finfo, e2);
+}
+
+#endif
diff --git a/lib/libesp32/berry/src/be_code.h b/lib/libesp32/berry/src/be_code.h
new file mode 100644
index 000000000..54d0c317c
--- /dev/null
+++ b/lib/libesp32/berry/src/be_code.h
@@ -0,0 +1,43 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_CODE_H
+#define BE_CODE_H
+
+#include "be_parser.h"
+
+#define be_code_freeregs(f, n) ((f)->freereg -= (bbyte)(n))
+
+int be_code_allocregs(bfuncinfo *finfo, int count);
+void be_code_prebinop(bfuncinfo *finfo, int op, bexpdesc *e);
+void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2, int dst);
+int be_code_unop(bfuncinfo *finfo, int op, bexpdesc *e);
+int be_code_setvar(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2);
+int be_code_nextreg(bfuncinfo *finfo, bexpdesc *e);
+int be_code_jump(bfuncinfo *finfo);
+void be_code_jumpto(bfuncinfo *finfo, int dst);
+void be_code_jumpbool(bfuncinfo *finfo, bexpdesc *e, int jumptrue);
+void be_code_conjump(bfuncinfo *finfo, int *list, int jmp);
+void be_code_patchlist(bfuncinfo *finfo, int list, int dst);
+void be_code_patchjump(bfuncinfo *finfo, int jmp);
+int be_code_getmethod(bfuncinfo *finfo, bexpdesc *e);
+void be_code_call(bfuncinfo *finfo, int base, int argc);
+int be_code_proto(bfuncinfo *finfo, bproto *proto);
+void be_code_closure(bfuncinfo *finfo, bexpdesc *e, int idx);
+void be_code_close(bfuncinfo *finfo, int isret);
+void be_code_class(bfuncinfo *finfo, bexpdesc *dst, bclass *c);
+void be_code_ret(bfuncinfo *finfo, bexpdesc *e);
+int be_code_nglobal(bfuncinfo *finfo, bexpdesc *k);
+void be_code_member(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2);
+void be_code_index(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k);
+void be_code_setsuper(bfuncinfo *finfo, bexpdesc *c, bexpdesc *s);
+void be_code_import(bfuncinfo *finfo, bexpdesc *m, bexpdesc *v);
+int be_code_exblk(bfuncinfo *finfo, int depth);
+void be_code_catch(bfuncinfo *finfo, int base, int ecnt, int vcnt, int *jmp);
+void be_code_raise(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_constobj.h b/lib/libesp32/berry/src/be_constobj.h
new file mode 100644
index 000000000..8716d7fe2
--- /dev/null
+++ b/lib/libesp32/berry/src/be_constobj.h
@@ -0,0 +1,384 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_CONSTOBJ_H
+#define BE_CONSTOBJ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "be_object.h"
+#include "be_gc.h"
+#include "be_map.h"
+#include "be_list.h"
+#include "be_class.h"
+#include "be_string.h"
+#include "be_module.h"
+
+#ifndef __cplusplus
+
+#define be_const_header(_t) \
+ .next = NULL, \
+ .type = (_t), \
+ .marked = GC_CONST
+
+#define be_const_key(_str, _next) { \
+ .v.c = &be_const_str_##_str, \
+ .type = BE_STRING, \
+ .next = (uint32_t)(_next) & 0xFFFFFF \
+}
+
+#define be_const_func(_func) { \
+ .v.nf = (_func), \
+ .type = BE_FUNCTION \
+}
+
+#define be_const_static_func(_func) { \
+ .v.nf = (_func), \
+ .type = BE_FUNCTION | BE_FUNC_STATIC \
+}
+
+#define be_const_nil() { \
+ .v.i = 0, \
+ .type = BE_NIL \
+}
+
+#define be_const_int(_val) { \
+ .v.i = (bint)(_val), \
+ .type = BE_INT \
+}
+
+#define be_const_var(_val) { \
+ .v.i = (bint)(_val), \
+ .type = BE_INDEX \
+}
+
+#define be_const_real(_val) { \
+ .v.r = (breal)(_val), \
+ .type = BE_REAL \
+}
+
+#define be_const_real_hex(_val) { \
+ .v.p = (void*)(_val), \
+ .type = BE_REAL \
+}
+
+#define be_const_bool(_val) { \
+ .v.b = (bbool)(_val), \
+ .type = BE_BOOL \
+}
+
+#define be_const_str(_str) { \
+ .v.s = (bstring*)(_str), \
+ .type = BE_STRING \
+}
+
+#define be_const_comptr(_val) { \
+ .v.c = (const void*)(_val), \
+ .type = BE_COMPTR \
+}
+
+#define be_const_class(_class) { \
+ .v.c = &(_class), \
+ .type = BE_CLASS \
+}
+
+#define be_const_closure(_closure) { \
+ .v.c = &(_closure), \
+ .type = BE_CLOSURE \
+}
+
+#define be_const_static_closure(_closure) { \
+ .v.c = &(_closure), \
+ .type = BE_CLOSURE | BE_FUNC_STATIC \
+}
+
+#define be_const_module(_module) { \
+ .v.c = &(_module), \
+ .type = BE_MODULE \
+}
+
+#define be_const_simple_instance(_instance) { \
+ .v.c = (_instance), \
+ .type = BE_INSTANCE \
+}
+
+#define be_const_map(_map) { \
+ .v.c = &(_map), \
+ .type = BE_MAP \
+}
+
+#define be_const_list(_list) { \
+ .v.c = &(_list), \
+ .type = BE_LIST \
+}
+
+#define be_define_const_map_slots(_name) \
+const bmapnode _name##_slots[] =
+
+#define be_define_const_map(_name, _size) \
+const bmap _name = { \
+ be_const_header(BE_MAP), \
+ .slots = (bmapnode*)_name##_slots, \
+ .lastfree = NULL, \
+ .size = _size, \
+ .count = _size \
+}
+
+#define be_define_const_class(_name, _nvar, _super, _name_) \
+const bclass _name = { \
+ be_const_header(BE_CLASS), \
+ .nvar = _nvar, \
+ .super = _super, \
+ .members = (bmap*)&_name##_map, \
+ .name = (bstring*)&be_const_str_##_name_ \
+}
+
+#define be_define_const_empty_class(_name, _super, _name_) \
+const bclass _name = { \
+ be_const_header(BE_CLASS), \
+ .nvar = 0, \
+ .super = (bclass*)_super, \
+ .members = NULL, \
+ .name = (bstring*)&be_const_str_##_name_ \
+}
+
+#define be_define_const_module(_name, _name_) \
+const bmodule _name = { \
+ be_const_header(BE_MODULE), \
+ .table = (bmap*)&_name##_map, \
+ .info.name = _name_, \
+}
+
+#define be_define_const_vector(_name, _data, _size) \
+const bvector _name = { \
+ .capacity = _size, \
+ .size = sizeof(bvalue), \
+ .count = _size, \
+ .data = (void*)_data, \
+ .end = (void*)(_data + (_size) - 1) \
+}
+
+#define be_define_const_native_module(_module) \
+const bntvmodule be_native_module(_module) = { \
+ .name = #_module, \
+ .attrs = NULL, \
+ .size = 0, \
+ .module = (bmodule*)&(m_lib##_module) \
+}
+
+/* defines needed for solidified classes */
+#define be_local_class(_name, _nvar, _super, _map, _cname) \
+ const bclass be_class_##_name = { \
+ be_const_header(BE_CLASS), \
+ .nvar = _nvar, \
+ .super = (bclass*)_super, \
+ .members = (bmap*)_map, \
+ .name = _cname \
+}
+
+/* defines needed for solidified modules */
+#define be_local_module(_c_name, _module_name, _map) \
+ static const bmodule m_lib##_c_name = { \
+ be_const_header(BE_MODULE), \
+ .table = (bmap*)_map, \
+ .info.name = _module_name \
+}
+
+/* only instances with no super and no sub instance are supported */
+/* primarily for `list` and `map`*/
+#define be_nested_simple_instance(_class_ptr, _members) \
+ & (const binstance) { \
+ be_const_header(BE_INSTANCE), \
+ .super = NULL, \
+ .sub = NULL, \
+ ._class = (bclass*) _class_ptr, \
+ .members = _members \
+ }
+
+// #define be_local_instance(_name, _class_ptr, _members) \
+// static const binstance i_##_name = { \
+// be_const_header(BE_INSTANCE), \
+// .super = NULL, \
+// .sub = NULL, \
+// ._class = (bclass*) _class_ptr, \
+// .members = _members \
+// }
+
+#define be_nested_map(_size, _slots) \
+ & (const bmap) { \
+ be_const_header(BE_MAP), \
+ .slots = _slots, \
+ .lastfree = NULL, \
+ .size = _size, \
+ .count = _size \
+ }
+
+#define be_nested_list(_size, _items) \
+ & (const blist) { \
+ be_const_header(BE_LIST), \
+ .count = _size, \
+ .capacity = _size, \
+ .data = _items \
+ }
+
+#define be_nested_str(_name_) \
+ { \
+ { .s=((bstring*)&be_const_str_##_name_) }, \
+ BE_STRING \
+ }
+
+#define be_nested_str_literal(_str) \
+ { \
+ { .s=(be_nested_const_str(_str, 0, sizeof(_str)-1 )) \
+ }, \
+ BE_STRING \
+ }
+
+#define be_str_literal(_str) \
+ be_nested_const_str(_str, 0, sizeof(_str)-1 )
+
+#define be_nested_string(_str, _hash, _len) \
+ { \
+ { .s=(be_nested_const_str(_str, _hash, _len )) \
+ }, \
+ BE_STRING \
+ }
+
+#define be_nested_key(_str, _hash, _len, _next) \
+ { \
+ { .s=(be_nested_const_str(_str, _hash, _len )) }, \
+ BE_STRING, \
+ (uint32_t)(_next) & 0xFFFFFF \
+ }
+
+#else
+
+#define be_const_key(_str, _next) { \
+ bvaldata(&be_const_str_##_str), \
+ BE_STRING, \
+ uint32_t((_next)&0xFFFFFF) \
+}
+
+#define be_const_func(_func) { \
+ bvaldata(_func), \
+ BE_FUNCTION \
+}
+
+#define be_const_static_func(_func) { \
+ bvaldata(_func), \
+ BE_FUNCTION | BE_FUNC_STATIC \
+}
+
+#define be_const_nil() { \
+ bvaldata(0), \
+ BE_NIL \
+}
+
+#define be_const_int(_val) { \
+ bvaldata(bint(_val)), \
+ BE_INT \
+}
+
+#define be_const_bool(_val) { \
+ bvaldata(bbool(_val)), \
+ BE_BOOL \
+}
+
+#define be_const_var(_val) { \
+ bvaldata(bint(_val)), \
+ BE_INDEX \
+}
+
+#define be_const_real(_val) { \
+ bvaldata(breal(_val)), \
+ BE_REAL \
+}
+
+#define be_const_real_hex(_val) { \
+ bvaldata((void*)(_val)), \
+ BE_REAL \
+}
+
+#define be_const_comptr(_val) { \
+ bvaldata((void*)(_val)), \
+ BE_COMPTR \
+}
+
+#define be_const_str(_string) { \
+ bvaldata(bstring(_string)), \
+ BE_STRING \
+}
+
+#define be_const_class(_class) { \
+ bvaldata(&(_class)), \
+ BE_CLASS \
+}
+
+#define be_const_closure(_closure) { \
+ bvaldata(&(_closure)), \
+ BE_CLOSURE \
+}
+
+#define be_const_static_closure(_closure) { \
+ bvaldata(&(_closure)), \
+ BE_CLOSURE | BE_FUNC_STATIC \
+}
+
+#define be_const_module(_module) { \
+ bvaldata(&(_module)), \
+ BE_MODULE \
+}
+
+#define be_define_const_map_slots(_name) \
+const bmapnode _name##_slots[] =
+
+#define be_define_const_map(_name, _size) \
+const bmap _name( \
+ (bmapnode*)_name##_slots, _size \
+)
+
+#define be_define_const_class(_name, _nvar, _super, _name_) \
+const bclass _name( \
+ _nvar, (bclass*)_super, (bmap*)&_name##_map, \
+ (bstring*)&be_const_str_##_name_ \
+)
+
+#define be_define_const_empty_class(_name, _super, _name_) \
+const bclass _name( \
+ 0, (bclass*)_super, NULL, \
+ (bstring*)&be_const_str_##_name_ \
+)
+
+#define be_define_const_module(_name, _name_) \
+const bmodule _name((bmap*)&_name##_map, _name_)
+
+#define be_define_const_vector(_name, _data, _size) \
+const bvector _name = { \
+ _size, sizeof(bvalue), _size, \
+ (void*)_data, (void*)(_data + (_size) - 1) \
+}
+
+#define be_define_const_native_module(_module) \
+const bntvmodule be_native_module(_module) = { \
+ #_module, \
+ 0, 0, \
+ (bmodule*)&(m_lib##_module) \
+}
+
+#endif
+
+/* provide pointers to map and list classes for solidified code */
+extern const bclass be_class_list;
+extern const bclass be_class_map;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesp32/berry/src/be_debug.c b/lib/libesp32/berry/src/be_debug.c
new file mode 100644
index 000000000..6184a32ef
--- /dev/null
+++ b/lib/libesp32/berry/src/be_debug.c
@@ -0,0 +1,402 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_debug.h"
+#include "be_func.h"
+#include "be_decoder.h"
+#include "be_string.h"
+#include "be_class.h"
+#include "be_vm.h"
+#include "be_vector.h"
+#include "be_strlib.h"
+#include "be_exec.h"
+#include "be_mem.h"
+#include
+#include
+
+#if BE_USE_DEBUG_HOOK && !BE_DEBUG_RUNTIME_INFO
+ #error This macro BE_USE_DEBUG_HOOK requires BE_DEBUG_RUNTIME_INFO != 0
+#endif
+
+#ifndef INST_BUF_SIZE
+#define INST_BUF_SIZE 96
+#endif
+
+#define logbuf(...) snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__)
+
+#define logfmt(...) \
+ do { \
+ char __lbuf[INST_BUF_SIZE]; \
+ logbuf(__VA_ARGS__); \
+ be_writestring(__lbuf); \
+ } while (0)
+
+#if BE_USE_DEBUG_MODULE
+static const char* opc2str(bopcode op)
+{
+ static const char* const opc_tab[] = {
+ #define OPCODE(opc) #opc
+ #include "be_opcodes.h"
+ #undef OPCODE
+ };
+ return op < array_count(opc_tab) ? opc_tab[op] : "ERROP";
+}
+
+void be_print_inst(binstruction ins, int pc)
+{
+ char __lbuf[INST_BUF_SIZE];
+ bopcode op = IGET_OP(ins);
+
+ logbuf(" %.4X ", pc);
+ be_writestring(__lbuf);
+ switch (op) {
+ case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
+ case OP_MOD: case OP_LT: case OP_LE: case OP_EQ:
+ case OP_NE: case OP_GT: case OP_GE: case OP_CONNECT:
+ case OP_GETMBR: case OP_SETMBR: case OP_GETMET:
+ case OP_GETIDX: case OP_SETIDX: case OP_AND:
+ case OP_OR: case OP_XOR: case OP_SHL: case OP_SHR:
+ logbuf("%s\tR%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins),
+ isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK,
+ isKC(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK);
+ break;
+ case OP_GETNGBL: case OP_SETNGBL:
+ logbuf("%s\tR%d\t%c%d", opc2str(op), IGET_RA(ins),
+ isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK);
+ break;
+ case OP_GETGBL: case OP_SETGBL:
+ logbuf("%s\tR%d\tG%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins));
+ break;
+ case OP_MOVE: case OP_SETSUPER: case OP_NEG: case OP_FLIP: case OP_IMPORT:
+ logbuf("%s\tR%d\t%c%d", opc2str(op), IGET_RA(ins),
+ isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK);
+ break;
+ case OP_JMP:
+ logbuf("%s\t\t#%.4X", opc2str(op), IGET_sBx(ins) + pc + 1);
+ break;
+ case OP_JMPT: case OP_JMPF:
+ logbuf("%s\tR%d\t#%.4X", opc2str(op), IGET_RA(ins), IGET_sBx(ins) + pc + 1);
+ break;
+ case OP_LDINT:
+ logbuf("%s\tR%d\t%d", opc2str(op), IGET_RA(ins), IGET_sBx(ins));
+ break;
+ case OP_LDBOOL:
+ logbuf("%s\tR%d\t%d\t%d", opc2str(op), IGET_RA(ins), IGET_RKB(ins), IGET_RKC(ins));
+ break;
+ case OP_RET:
+ if (IGET_RA(ins)) {
+ logbuf("%s\t%d\t%c%d", opc2str(op), IGET_RA(ins),
+ isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK);
+ } else {
+ logbuf("%s\t%d", opc2str(op), IGET_RA(ins)); /* RET 0 does not take an additional parameter */
+ }
+ break;
+ case OP_GETUPV: case OP_SETUPV:
+ logbuf("%s\tR%d\tU%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins));
+ break;
+ case OP_LDCONST:
+ logbuf("%s\tR%d\tK%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins));
+ break;
+ case OP_CALL:
+ logbuf("%s\tR%d\t%d", opc2str(op), IGET_RA(ins), IGET_RKB(ins));
+ break;
+ case OP_CLOSURE:
+ logbuf("%s\tR%d\tP%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins));
+ break;
+ case OP_CLASS:
+ logbuf("%s\tK%d", opc2str(op), IGET_Bx(ins));
+ break;
+ case OP_CLOSE: case OP_LDNIL:
+ logbuf("%s\tR%d", opc2str(op), IGET_RA(ins));
+ break;
+ case OP_RAISE:
+ logbuf("%s\t%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins),
+ isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK,
+ isKC(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK);
+ break;
+ case OP_EXBLK:
+ if (IGET_RA(ins)) {
+ logbuf("%s\t%d\t%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins));
+ } else {
+ logbuf("%s\t%d\t#%.4X", opc2str(op), IGET_RA(ins), IGET_sBx(ins) + pc + 1);
+ }
+ break;
+ case OP_CATCH:
+ logbuf("%s\tR%d\t%d\t%d", opc2str(op), IGET_RA(ins), IGET_RKB(ins), IGET_RKC(ins));
+ break;
+ default:
+ logbuf("%s", opc2str(op));
+ break;
+ }
+ be_writestring(__lbuf);
+ be_writenewline();
+}
+#endif
+
+#if BE_USE_DEBUG_MODULE
+void be_dumpclosure(bclosure *cl)
+{
+ int pc;
+ bproto *proto = cl->proto;
+ binstruction *code = proto->code;
+#if BE_DEBUG_RUNTIME_INFO
+ blineinfo *lineinfo = proto->lineinfo;
+#endif
+ logfmt("source '%s', ", str(proto->source));
+ logfmt("function '%s':\n", str(proto->name));
+#if BE_DEBUG_RUNTIME_INFO
+ if (lineinfo) { /* first line */
+ logfmt("; line %d\n", lineinfo->linenumber);
+ }
+#endif
+ for (pc = 0; pc < proto->codesize; pc++) {
+#if BE_DEBUG_RUNTIME_INFO
+ if (lineinfo && pc > lineinfo->endpc) {
+ logfmt("; line %d\n", (++lineinfo)->linenumber);
+ }
+#endif
+ be_print_inst(*code++, pc);
+ }
+}
+#endif
+
+static void sourceinfo(bproto *proto, binstruction *ip)
+{
+#if BE_DEBUG_RUNTIME_INFO
+ char buf[24];
+ be_assert(proto != NULL);
+ if (proto->lineinfo && proto->nlineinfo) {
+ blineinfo *it = proto->lineinfo;
+ blineinfo *end = it + proto->nlineinfo;
+ int pc = cast_int(ip - proto->code - 1); /* now vm->ip has been increased */
+ for (; it < end && pc > it->endpc; ++it);
+ sprintf(buf, ":%d:", it->linenumber);
+ be_writestring(str(proto->source));
+ be_writestring(buf);
+ } else {
+ be_writestring(":");
+ }
+#else
+ (void)proto; (void)ip;
+ be_writestring(":");
+#endif
+}
+
+static void tracestack(bvm *vm)
+{
+ bcallsnapshot *cf;
+ bcallsnapshot *base = be_stack_base(&vm->tracestack);
+ bcallsnapshot *top = be_stack_top(&vm->tracestack);
+ be_writestring("stack traceback:\n");
+ for (cf = top; cf >= base; --cf) {
+ if (cf <= top - 10 && cf >= base + 10) {
+ if (cf == top - 10)
+ be_writestring("\t...\n");
+ continue;
+ }
+ if (var_isclosure(&cf->func)) {
+ bclosure *cl = var_toobj(&cf->func);
+ be_writestring("\t");
+ sourceinfo(cl->proto, cf->ip);
+ be_writestring(" in function `");
+ be_writestring(str(cl->proto->name));
+ be_writestring("`\n");
+ } else {
+ be_writestring("\t: in native function\n");
+ }
+ }
+}
+
+static void repair_stack(bvm *vm)
+{
+ bcallsnapshot *cf;
+ bcallsnapshot *base = be_stack_base(&vm->tracestack);
+ bcallsnapshot *top = be_stack_top(&vm->tracestack);
+ /* Because the native function does not push `ip` to the
+ * stack, the ip on the native function frame corresponds
+ * to the previous Berry closure. */
+ for (cf = top; cf >= base; --cf) {
+ if (!var_isclosure(&cf->func)) {
+ /* the last native function stack frame has the `ip` of
+ * the previous Berry frame */
+ binstruction *ip = cf->ip;
+ /* skip native function stack frames */
+ for (; cf >= base && !var_isclosure(&cf->func); --cf);
+ /* fixed `ip` of Berry closure frame near native function frame */
+ if (cf >= base) cf->ip = ip;
+ }
+ }
+}
+
+void be_tracestack(bvm *vm)
+{
+ if (be_stack_count(&vm->tracestack)) {
+ repair_stack(vm);
+ tracestack(vm);
+ }
+}
+
+#if BE_USE_DEBUG_HOOK
+
+static void hook_callnative(bvm *vm, int mask)
+{
+ bhookinfo info;
+ int top = be_top(vm);
+ bcallframe *cf = vm->cf;
+ bclosure *cl = var_toobj(cf->func);
+ struct bhookblock *hb = var_toobj(&vm->hook);
+ be_stack_require(vm, BE_STACK_FREE_MIN + 2);
+ info.type = mask;
+ info.line = cf->lineinfo->linenumber;
+ info.source = str(cl->proto->source);
+ info.func_name = str(cl->proto->name);
+ info.data = hb->data;
+ hb->hook(vm, &info);
+ vm->top += 2;
+ be_pop(vm, be_top(vm) - top);
+}
+
+static int hook_pushargs(bvm *vm, int mask)
+{
+ bcallframe *cf = vm->cf;
+ if (mask == BE_HOOK_LINE) {
+ be_pushstring(vm, "line");
+ be_pushint(vm, cf->lineinfo->linenumber);
+ return 2;
+ }
+ if (mask == BE_HOOK_CALL) {
+ bclosure *cl = var_toobj(cf->func);
+ be_pushstring(vm, "call");
+ var_setstr(vm->top, cl->proto->name);
+ vm->top++;
+ return 2;
+ }
+ if (mask == BE_HOOK_RET) {
+ be_pushstring(vm, "return");
+ return 1;
+ }
+ return 0;
+}
+
+static void hook_call(bvm *vm, int mask)
+{
+ int argc;
+ vm->top[2] = vm->hook;
+ be_stack_require(vm, 5);
+ vm->top += 3;
+ argc = hook_pushargs(vm, mask);
+ be_call(vm, argc);
+ be_pop(vm, 3 + argc);
+}
+
+void be_callhook(bvm *vm, int mask)
+{
+ if (vm->hookmask & mask) {
+ int hookmask = vm->hookmask;
+ vm->hookmask = 0;
+ if (var_istype(&vm->hook, BE_COMPTR)) {
+ hook_callnative(vm, mask);
+ } else {
+ hook_call(vm, mask);
+ }
+ vm->hookmask = (bbyte)hookmask;
+ }
+}
+
+static bbyte parse_hookmask(const char *mask)
+{
+ int c, res = 0;
+ if (mask) {
+ while ((c = *mask++) != '\0') {
+ switch (c) {
+ case 'l': res |= BE_HOOK_LINE; break;
+ case 'c': res |= BE_HOOK_CALL; break;
+ case 'r': res |= BE_HOOK_RET; break;
+ default: break;
+ }
+ }
+ }
+ return (bbyte)res;
+}
+
+BERRY_API void be_sethook(bvm *vm, const char *mask)
+{
+ vm->hookmask = parse_hookmask(mask);
+ if (vm->hookmask && var_istype(&vm->hook, BE_COMPTR)) /* free native hook */
+ be_free(vm, var_toobj(&vm->hook), sizeof(struct bhookblock));
+ if (vm->hookmask) {
+ vm->hook = *be_indexof(vm, -1);
+ } else if (!var_istype(&vm->hook, BE_COMPTR)) {
+ var_setnil(&vm->hook);
+ }
+}
+
+BERRY_API void be_setntvhook(bvm *vm, bntvhook hook, void *data, int mask)
+{
+ struct bhookblock *hb;
+ if (mask) {
+ if (!var_istype(&vm->hook, BE_COMPTR)) {
+ var_setobj(&vm->hook, BE_COMPTR,
+ be_malloc(vm, sizeof(struct bhookblock)));
+ }
+ hb = var_toobj(&vm->hook);
+ be_assert(hb != NULL);
+ hb->hook = hook;
+ hb->data = data;
+ } else if (!var_istype(&vm->hook, BE_COMPTR)) {
+ var_setnil(&vm->hook);
+ }
+ vm->hookmask = (bbyte)mask;
+}
+
+#endif
+
+#if BE_DEBUG_VAR_INFO
+static binstruction* callstack_fixip(bvm *vm, int level)
+{
+ bcallframe *top = (bcallframe*)be_stack_top(&vm->callstack);
+ bcallframe *cf = top - level + 2;
+ for (; cf <= top && cf->status & PRIM_FUNC; ++cf);
+ return cf <= top ? cf->ip : vm->ip;
+}
+
+bbool be_debug_varname(bvm *vm, int level, int index)
+{
+ int depth = be_stack_count(&vm->callstack);
+ if (level > 0 && level <= depth) {
+ bcallframe *cf = be_vector_at(&vm->callstack, depth - level);
+ if ((cf->status & PRIM_FUNC) == 0) {
+ bproto *proto = cast(bclosure*, var_toobj(cf->func))->proto;
+ int pc = (int)(callstack_fixip(vm, level) - proto->code);
+ bstring *name = be_func_varname(proto, index, pc);
+ if (name) {
+ bvalue *reg = be_incrtop(vm);
+ var_setstr(reg, name);
+ return btrue;
+ }
+ }
+ }
+ return bfalse;
+}
+
+bbool be_debug_upvname(bvm *vm, int level, int index)
+{
+ int depth = be_stack_count(&vm->callstack);
+ if (level > 0 && level <= depth) {
+ bcallframe *cf = be_vector_at(&vm->callstack, depth - level);
+ if ((cf->status & PRIM_FUNC) == 0) {
+ bproto *proto = cast(bclosure*, var_toobj(cf->func))->proto;
+ if (index >= 0 && index < proto->nupvals) {
+ bvalue *reg = be_incrtop(vm);
+ var_setstr(reg, proto->upvals[index].name);
+ return btrue;
+ }
+ }
+ }
+ return bfalse;
+}
+#endif
diff --git a/lib/libesp32/berry/src/be_debug.h b/lib/libesp32/berry/src/be_debug.h
new file mode 100644
index 000000000..0956e8f8e
--- /dev/null
+++ b/lib/libesp32/berry/src/be_debug.h
@@ -0,0 +1,28 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_DEBUG_H
+#define BE_DEBUG_H
+
+#include "be_object.h"
+
+struct bhookblock {
+ void *data;
+ bntvhook hook;
+};
+
+void be_dumpclosure(bclosure *cl);
+void be_tracestack(bvm *vm);
+void be_callhook(bvm *vm, int mask);
+bbool be_debug_varname(bvm *vm, int level, int index);
+bbool be_debug_upvname(bvm *vm, int level, int index);
+
+#if BE_USE_DEBUG_MODULE
+void be_print_inst(binstruction ins, int pc);
+#endif
+
+#endif
diff --git a/lib/libesp32/berry/src/be_debuglib.c b/lib/libesp32/berry/src/be_debuglib.c
new file mode 100644
index 000000000..153af55fb
--- /dev/null
+++ b/lib/libesp32/berry/src/be_debuglib.c
@@ -0,0 +1,215 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_module.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_class.h"
+#include "be_debug.h"
+#include "be_map.h"
+#include "be_vm.h"
+#include
+
+#if BE_USE_DEBUG_MODULE
+
+static void dump_map(bmap *map)
+{
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(map, &iter)) != NULL) {
+ if (var_isstr(&node->key)) {
+ bstring *s = var_tostr(&node->key);
+ be_writestring("\t");
+ be_writebuffer(str(s), str_len(s));
+ be_writestring(": <");
+ be_writestring(be_vtype2str(&node->value));
+ be_writestring(">\n");
+ }
+ }
+}
+
+static void dump_module(bmodule *module)
+{
+ dump_map(module->table);
+}
+
+static void dump_class(bclass *class)
+{
+ if (class->members) {
+ dump_map(class->members);
+ }
+}
+
+static void dump_instanse(binstance *ins)
+{
+ dump_class(ins->_class);
+}
+
+static void dump_value(bvalue *value)
+{
+ be_writestring("value type <");
+ be_writestring(be_vtype2str(value));
+ be_writestring(">, attributes:\n");
+}
+
+static int m_attrdump(bvm *vm)
+{
+ if (be_top(vm) >= 1) {
+ bvalue *v = be_indexof(vm, 1);
+ void *obj = var_toobj(v);
+ dump_value(v);
+ switch (var_type(v)) {
+ case BE_MODULE: dump_module(obj); break;
+ case BE_CLASS: dump_class(obj); break;
+ case BE_INSTANCE: dump_instanse(obj); break;
+ default: break;
+ }
+ }
+ be_return_nil(vm);
+}
+
+static int m_codedump(bvm *vm)
+{
+ if (be_top(vm) >= 1) {
+ bvalue *v = be_indexof(vm, 1);
+ if (var_isclosure(v)) {
+ be_dumpclosure(var_toobj(v));
+ }
+ }
+ be_return_nil(vm);
+}
+
+static int m_traceback(bvm *vm)
+{
+ be_tracestack(vm);
+ be_return_nil(vm);
+}
+
+#if BE_USE_DEBUG_HOOK
+static int m_sethook(bvm *vm)
+{
+ if (be_top(vm) >= 2) {
+ be_pushvalue(vm, 1);
+ be_sethook(vm, be_tostring(vm, 2));
+ } else {
+ be_sethook(vm, NULL);
+ }
+ be_return_nil(vm);
+}
+#endif
+
+static int m_top(bvm *vm)
+{
+ bint top = vm->top - vm->stack + 1;
+ be_pushint(vm, top);
+ be_return(vm);
+}
+
+static int m_calldepth(bvm *vm)
+{
+ bint depth = be_stack_count(&vm->callstack);
+ be_pushint(vm, depth);
+ be_return(vm);
+}
+
+#if BE_DEBUG_VAR_INFO
+static int v_getname(bvm *vm, bbool(*getter)(bvm *vm, int, int))
+{
+ int index, level = 1;
+ if (be_top(vm) < 1)
+ be_raise(vm, "value_error", "too few arguments");
+ if (!be_isint(vm, 1) || (be_top(vm) >= 2 && !be_isint(vm, 2)))
+ be_raise(vm, "value_error", "invalid argument(s) value");
+ if (be_top(vm) >= 2)
+ level = be_toindex(vm, 2);
+ index = be_toindex(vm, 1);
+ if (index < 0)
+ be_raise(vm, "value_error", "variable index cannot be less than 0");
+ if (level < 1 || level >= be_stack_count(&vm->callstack))
+ be_raise(vm, "value_error", "invalid call depth level");
+ if (getter(vm, level + 1, index)) {
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int m_varname(bvm *vm)
+{
+ return v_getname(vm, be_debug_varname);
+}
+
+static int m_upvname(bvm *vm)
+{
+ return v_getname(vm, be_debug_upvname);
+}
+#endif
+
+
+#if BE_USE_PERF_COUNTERS
+static void map_insert(bvm *vm, const char *key, int value)
+{
+ be_pushstring(vm, key);
+ be_pushint(vm, value);
+ be_data_insert(vm, -3);
+ be_pop(vm, 2);
+}
+
+static int m_counters(bvm *vm)
+{
+ be_newobject(vm, "map");
+ map_insert(vm, "instruction", vm->counter_ins);
+ map_insert(vm, "vmenter", vm->counter_enter);
+ map_insert(vm, "call", vm->counter_call);
+ map_insert(vm, "get", vm->counter_get);
+ map_insert(vm, "set", vm->counter_set);
+ map_insert(vm, "try", vm->counter_try);
+ map_insert(vm, "raise", vm->counter_exc);
+ map_insert(vm, "objects", vm->counter_gc_kept);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+#endif
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(debug) {
+ be_native_module_function("attrdump", m_attrdump),
+ be_native_module_function("codedump", m_codedump),
+ be_native_module_function("traceback", m_traceback),
+#if BE_USE_DEBUG_HOOK
+ be_native_module_function("sethook", m_sethook),
+#endif
+#if BE_USE_PERF_COUNTERS
+ be_native_module_function("counters", m_counters),
+#endif
+ be_native_module_function("calldepth", m_calldepth),
+ be_native_module_function("top", m_top),
+#if BE_DEBUG_VAR_INFO
+ be_native_module_function("varname", m_varname),
+ be_native_module_function("upvname", m_upvname)
+#endif
+};
+
+be_define_native_module(debug, NULL);
+#else
+/* @const_object_info_begin
+module debug (scope: global, depend: BE_USE_DEBUG_MODULE) {
+ attrdump, func(m_attrdump)
+ codedump, func(m_codedump)
+ traceback, func(m_traceback)
+ sethook, func(m_sethook), BE_USE_DEBUG_HOOK
+ counters, func(m_counters), BE_USE_PERF_COUNTERS
+ calldepth, func(m_calldepth)
+ top, func(m_top)
+ varname, func(m_varname), BE_DEBUG_VAR_INFO
+ upvname, func(m_upvname), BE_DEBUG_VAR_INFO
+}
+@const_object_info_end */
+#include "../generate/be_fixed_debug.h"
+#endif
+
+#endif /* BE_USE_DEBUG_MODULE */
diff --git a/lib/libesp32/berry/src/be_decoder.h b/lib/libesp32/berry/src/be_decoder.h
new file mode 100644
index 000000000..c6cfd7ade
--- /dev/null
+++ b/lib/libesp32/berry/src/be_decoder.h
@@ -0,0 +1,74 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_OPCODE_H
+#define BE_OPCODE_H
+
+#define NO_JUMP -1
+
+/* define field's bit-width */
+#define IOP_BITS 6u
+#define IRA_BITS 8u
+#define IRKB_BITS 9u
+#define IRKC_BITS 9u
+
+/* define field's bit-width and positions */
+#define IRKC_POS 0u
+#define IRKB_POS (IRKC_POS + IRKC_BITS)
+#define IRA_POS (IRKB_POS + IRKB_BITS)
+#define IOP_POS (IRA_POS + IRA_BITS)
+#define IAx_BITS (IRA_BITS + IRKB_BITS + IRKC_BITS)
+#define IBx_BITS (IRKC_BITS + IRKB_BITS)
+
+/* basic field operation */
+#define INS_MASK(pos, bits) ((binstruction)((1 << (bits)) - 1) << (pos))
+#define INS_GETx(i, mask, pos) cast_int(((binstruction)(i) & (mask)) >> (pos))
+#define INS_SETx(v, mask, pos) (((binstruction)(v) << (pos)) & (mask))
+
+/* instruction operation */
+#define isK(v) (((v) & (1 << (IRKB_BITS - 1))) != 0)
+#define setK(v) ((v) | (1 << (IRKB_BITS - 1)))
+#define KR2idx(v) ((v) & 0xFF)
+#define isKB(v) (((v) & (1 << (IRA_POS - 1))) != 0)
+#define isKC(v) (((v) & (1 << (IRKB_POS - 1))) != 0)
+
+/* define masks and limit values */
+#define IOP_MASK INS_MASK(IOP_POS, IOP_BITS)
+#define IRA_MASK INS_MASK(IRA_POS, IRA_BITS)
+#define IRKB_MASK INS_MASK(IRKB_POS, IRKB_BITS)
+#define IRKC_MASK INS_MASK(IRKC_POS, IRKC_BITS)
+#define IAx_MASK INS_MASK(0, IAx_BITS)
+#define IBx_MASK INS_MASK(0, IBx_BITS)
+#define IsBx_MAX cast_int(IBx_MASK >> 1)
+#define IsBx_MIN cast_int(-IsBx_MAX - 1)
+
+/* mask for K/R values */
+#define KR_MASK ((1 << (IRKB_BITS-1)) - 1)
+
+/* get field */
+#define IGET_OP(i) cast(bopcode, INS_GETx(i, IOP_MASK, IOP_POS))
+#define IGET_RA(i) INS_GETx(i, IRA_MASK, IRA_POS)
+#define IGET_RKB(i) INS_GETx(i, IRKB_MASK, IRKB_POS)
+#define IGET_RKC(i) INS_GETx(i, IRKC_MASK, IRKC_POS)
+#define IGET_Bx(i) INS_GETx(i, IBx_MASK, 0)
+#define IGET_sBx(i) (IGET_Bx(i) - IsBx_MAX)
+
+/* set field */
+#define ISET_OP(i) INS_SETx(i, IOP_MASK, IOP_POS)
+#define ISET_RA(i) INS_SETx(i, IRA_MASK, IRA_POS)
+#define ISET_RKB(i) INS_SETx(i, IRKB_MASK, IRKB_POS)
+#define ISET_RKC(i) INS_SETx(i, IRKC_MASK, IRKC_POS)
+#define ISET_Bx(i) INS_SETx(i, IBx_MASK, 0)
+#define ISET_sBx(i) (ISET_Bx(cast_int(i) + IsBx_MAX))
+
+typedef enum {
+ #define OPCODE(opc) OP_##opc
+ #include "be_opcodes.h"
+ #undef OPCODE
+} bopcode;
+
+#endif
diff --git a/lib/libesp32/berry/src/be_exec.c b/lib/libesp32/berry/src/be_exec.c
new file mode 100644
index 000000000..14dbe903c
--- /dev/null
+++ b/lib/libesp32/berry/src/be_exec.c
@@ -0,0 +1,497 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_exec.h"
+#include "be_parser.h"
+#include "be_vm.h"
+#include "be_vector.h"
+#include "be_mem.h"
+#include "be_sys.h"
+#include "be_debug.h"
+#include "be_bytecode.h"
+#include "be_decoder.h"
+#include
+
+#if !BE_USE_SCRIPT_COMPILER && !BE_USE_BYTECODE_LOADER
+ #error no compiler or bytecode loader enabled.
+#endif
+
+#define FILE_BUFFER_SIZE 256
+
+#define __STR(s) #s
+#define STR(s) __STR(s)
+
+#define STACK_OVER_MSG(n) \
+ "stack overflow (maximum stack size is " STR(n) ")"
+
+#ifdef BE_EXPLICIT_ABORT
+ #define _os_abort BE_EXPLICIT_ABORT
+#else
+ #define _os_abort abort
+#endif
+
+#ifdef BE_EXPLICIT_EXIT
+ #define _os_exit BE_EXPLICIT_EXIT
+#else
+ #define _os_exit exit
+#endif
+
+#define exec_try(j) if (be_setjmp((j)->b) == 0)
+#define exec_throw(j) be_longjmp((j)->b, 1)
+
+#define fixup_ptr(ptr, offset) ((ptr) = (void*)((bbyte*)(ptr) + (offset)))
+#define ptr_offset(ptr1, ptr2) ((bbyte*)(ptr1) - (bbyte*)(ptr2))
+
+struct pparser {
+ const char *fname;
+ breader reader;
+ void *data;
+ bbyte islocal;
+};
+
+struct pcall {
+ bvalue *v;
+ int argc;
+};
+
+struct vmstate {
+ int top, reg, depth;
+};
+
+struct strbuf {
+ size_t len;
+ const char *s;
+};
+
+struct filebuf {
+ void *fp;
+ char buf[FILE_BUFFER_SIZE];
+};
+
+void be_throw(bvm *vm, int errorcode)
+{
+#if BE_USE_PERF_COUNTERS
+ vm->counter_exc++;
+#endif
+ if (vm->errjmp) {
+ vm->errjmp->status = errorcode;
+ exec_throw(vm->errjmp);
+ } else {
+ _os_abort();
+ }
+}
+
+/* Fatal error Exit */
+/* Raise a BE_EXIT exception if within a try/catch block, or exit VM */
+BERRY_API void be_exit(bvm *vm, int status)
+{
+ if (vm->errjmp) {
+ be_pushint(vm, status);
+ be_pop(vm, 1);
+ be_throw(vm, BE_EXIT);
+ } else {
+ _os_exit(status);
+ }
+}
+
+void be_throw_message(bvm *vm, int errorcode, const char *msg)
+{
+ be_pushstring(vm, msg);
+ be_throw(vm, errorcode);
+}
+
+/* Exec protected: exec function and capture any exception and contain it within call */
+/* Exceptions or fatal errors are not propagated */
+int be_execprotected(bvm *vm, bpfunc f, void *data)
+{
+ struct blongjmp jmp;
+ jmp.status = 0;
+ jmp.prev = vm->errjmp; /* save long jump position */
+ vm->errjmp = &jmp;
+ exec_try(vm->errjmp) {
+ f(vm, data);
+ }
+ vm->errjmp = jmp.prev; /* restore long jump position */
+ return jmp.status;
+}
+
+static void vm_state_save(bvm *vm, struct vmstate *state)
+{
+ state->depth = be_stack_count(&vm->callstack);
+ state->top = cast_int(vm->top - vm->stack);
+ state->reg = cast_int(vm->reg - vm->stack);
+}
+
+static void copy_exception(bvm *vm, int res, int dstindex)
+{
+ bvalue *dst = vm->stack + dstindex;
+ if (res == BE_EXCEPTION || res == BE_EXIT) {
+ bvalue *src = vm->top;
+ *dst++ = *src++;
+ if (res == BE_EXCEPTION) {
+ *dst++ = *src++;
+ }
+ }
+ vm->top = dst;
+}
+
+static void vm_state_restore(bvm *vm, const struct vmstate *state, int res)
+{
+ vm->reg = vm->stack + state->reg;
+ /* copy exception information to top */
+ copy_exception(vm, res, state->top);
+ be_assert(be_stack_count(&vm->callstack) >= state->depth);
+ if (be_stack_count(&vm->callstack) > state->depth) {
+ be_vector_resize(vm, &vm->callstack, state->depth);
+ vm->cf = be_stack_top(&vm->callstack);
+ }
+}
+
+#if BE_USE_SCRIPT_COMPILER
+static void m_parser(bvm *vm, void *data)
+{
+ struct pparser *p = cast(struct pparser*, data);
+ bclosure *cl = be_parser_source(vm,
+ p->fname, p->reader, p->data, p->islocal);
+ var_setclosure(vm->top, cl);
+ be_incrtop(vm);
+}
+
+int be_protectedparser(bvm *vm,
+ const char *fname, breader reader, void *data, bbool islocal)
+{
+ int res;
+ struct pparser s;
+ struct vmstate state;
+ s.fname = fname;
+ s.reader = reader;
+ s.data = data;
+ s.islocal = (bbyte)(islocal != 0);
+ vm_state_save(vm, &state);
+ res = be_execprotected(vm, m_parser, &s);
+ if (res) { /* restore call stack */
+ vm_state_restore(vm, &state, res);
+ }
+ return res;
+}
+
+static const char* _sgets(void *data, size_t *size)
+{
+ struct strbuf *sb = data;
+ *size = sb->len;
+ if (sb->len) {
+ sb->len = 0;
+ return sb->s;
+ }
+ return NULL;
+}
+
+static const char* _fgets(void *data, size_t *size)
+{
+ struct filebuf *fb = data;
+ *size = be_fread(fb->fp, fb->buf, sizeof(fb->buf));
+ if (*size) {
+ return fb->buf;
+ }
+ return NULL;
+}
+
+BERRY_API int be_loadbuffer(bvm *vm,
+ const char *name, const char *buffer, size_t length)
+{
+ struct strbuf sbuf;
+ sbuf.s = buffer;
+ sbuf.len = length;
+ return be_protectedparser(vm, name, _sgets, &sbuf, bfalse);
+}
+
+static int fileparser(bvm *vm, const char *name, bbool islocal)
+{
+ int res = BE_IO_ERROR;
+ struct filebuf *fbuf = be_malloc(vm, sizeof(struct filebuf));
+ fbuf->fp = be_fopen(name, "r");
+ if (fbuf->fp) {
+ res = be_protectedparser(vm, name, _fgets, fbuf, islocal);
+ be_fclose(fbuf->fp);
+ }
+ be_free(vm, fbuf, sizeof(struct filebuf));
+ return res;
+}
+#endif /* BE_USE_SCRIPT_COMPILER */
+
+#if BE_USE_BYTECODE_LOADER
+static void bytecode_loader(bvm *vm, void *data)
+{
+ bclosure *cl = be_bytecode_load(vm, (const char *)data);
+ if (cl != NULL) {
+ var_setclosure(vm->top, cl);
+ } else {
+ var_setnil(vm->top);
+ }
+ be_incrtop(vm);
+}
+
+/* load bytecode file */
+static int load_bytecode(bvm *vm, const char *name)
+{
+ int res = BE_SYNTAX_ERROR;
+ if (be_bytecode_check(name)) {
+ struct vmstate state;
+ vm_state_save(vm, &state);
+ res = be_execprotected(vm, bytecode_loader, (void*)name);
+ if (res) { /* restore call stack */
+ vm_state_restore(vm, &state, res);
+ }
+ }
+ return res;
+}
+
+#else
+#define load_bytecode(vm, name) BE_SYNTAX_ERROR
+#endif /* BE_USE_BYTECODE_LOADER */
+
+BERRY_API int be_loadmode(bvm *vm, const char *name, bbool islocal)
+{
+ int res = load_bytecode(vm, name);
+#if BE_USE_SCRIPT_COMPILER
+ if (res && res != BE_IO_ERROR) {
+ res = fileparser(vm, name, islocal);
+ }
+#else
+ (void)islocal;
+#endif
+ if (res == BE_IO_ERROR) {
+ be_pushfstring(vm, "cannot open file '%s'.", name);
+ }
+ return res;
+}
+
+#if BE_USE_BYTECODE_SAVER
+static void _bytecode_save(bvm *vm, void *data)
+{
+ if (be_top(vm) > 0 && var_isclosure(vm->top - 1)) {
+ bclosure *cl = var_toobj(vm->top - 1);
+ be_bytecode_save(vm, (const char *)data, cl->proto);
+ }
+}
+
+/* save bytecode file */
+BERRY_API int be_savecode(bvm *vm, const char *name)
+{
+ int res;
+ struct vmstate state;
+ vm_state_save(vm, &state);
+ res = be_execprotected(vm, _bytecode_save, (void *)name);
+ if (res) { /* restore call stack */
+ vm_state_restore(vm, &state, res);
+ }
+ return res;
+}
+#endif
+
+static void m_pcall(bvm *vm, void *data)
+{
+ struct pcall *p = cast(struct pcall*, data);
+ be_dofunc(vm, p->v, p->argc);
+}
+
+/* Protected call: contain any exception of fatal error and restore context if something went wrong */
+int be_protectedcall(bvm *vm, bvalue *v, int argc)
+{
+ int res;
+ struct pcall s;
+ struct vmstate state;
+ s.v = v;
+ s.argc = argc;
+ vm_state_save(vm, &state);
+ res = be_execprotected(vm, m_pcall, &s);
+ if (res) { /* restore call stack */
+ vm_state_restore(vm, &state, res);
+ }
+ return res;
+}
+
+#if BE_DEBUG && defined(be_assert)
+/* increase top register and return new top */
+/* Does not expand the stack if there is not enough room, but may corrupt memory */
+bvalue* be_incrtop(bvm *vm)
+{
+ bvalue *top = vm->top++;
+ be_assert(top < vm->stacktop);
+ return top;
+}
+#endif
+
+/* TODO what is the difference with be_stack_push? */
+void be_stackpush(bvm *vm)
+{
+ /* make sure there is enough stack space */
+ be_stack_require(vm, 1 + BE_STACK_FREE_MIN);
+ be_incrtop(vm);
+}
+
+/* check that the stack is able to store `count` items, and increase stack if needed */
+void be_stack_require(bvm *vm, int count)
+{
+ if (vm->top + count >= vm->stacktop) {
+ be_stack_expansion(vm, count);
+ }
+}
+
+/* Scan the entire callstack and adjust all pointer by `offset` */
+static void update_callstack(bvm *vm, intptr_t offset)
+{
+ bcallframe *cf = be_stack_top(&vm->callstack);
+ bcallframe *base = be_stack_base(&vm->callstack);
+ for (; cf >= base; --cf) {
+ fixup_ptr(cf->func, offset);
+ fixup_ptr(cf->top, offset);
+ fixup_ptr(cf->reg, offset);
+ }
+ fixup_ptr(vm->top, offset);
+ fixup_ptr(vm->reg, offset);
+}
+
+static void update_upvalues(bvm *vm, intptr_t offset)
+{
+ bupval *node = vm->upvalist;
+ /* update the value referenced by open upvalues */
+ for (; node != NULL; node = node->u.next) {
+ fixup_ptr(node->value, offset);
+ }
+}
+
+/* Resize the stack to new `size` as number of elements */
+/* Then update all pointers in callstack and upvalues with the new stack address */
+static void stack_resize(bvm *vm, size_t size)
+{
+ intptr_t offset;
+ bvalue *old = vm->stack; /* save original pointer of stack before resize */
+ size_t os = (vm->stacktop - old) * sizeof(bvalue); /* size of current stack allocated in bytes */
+ vm->stack = be_realloc(vm, old, os, sizeof(bvalue) * size); /* reallocate with the new size */
+ vm->stacktop = vm->stack + size; /* compute new stacktop */
+ offset = ptr_offset(vm->stack, old); /* compute the address difference between old and ne stack addresses */
+ /* update callframes */
+ update_callstack(vm, offset);
+ /* update open upvalues */
+ update_upvalues(vm, offset);
+}
+
+/* Stack resize internal API */
+/* Increases the stack by `n` elements, reallocate stack if needed and update all callstacks and upvals */
+/* Check if we are above the max allowed stack */
+void be_stack_expansion(bvm *vm, int n)
+{
+ size_t size = vm->stacktop - vm->stack;
+ /* check new stack size */
+ if (size + n > BE_STACK_TOTAL_MAX) {
+ /* ensure the stack is enough when generating error messages. */
+ stack_resize(vm, size + 1);
+ be_raise(vm, "runtime_error", STACK_OVER_MSG(BE_STACK_TOTAL_MAX));
+ }
+ if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_STACK_RESIZE_START, size * sizeof(bvalue), (size + n) * sizeof(bvalue));
+ stack_resize(vm, size + n);
+}
+
+static void fixup_exceptstack(bvm* vm, struct bexecptframe* lbase)
+{
+ struct bexecptframe *base = be_stack_base(&vm->exceptstack);
+ if (lbase != base) { /* the address has changed when the stack is expanded */
+ struct bexecptframe *top = be_stack_top(&vm->exceptstack);
+ bbyte *begin = (bbyte*)&lbase->errjmp;
+ bbyte *end = (bbyte*)&(lbase + (top - base))->errjmp;
+ intptr_t offset = ptr_offset(base, lbase);
+ struct blongjmp *errjmp = vm->errjmp;
+ while (errjmp) {
+ bbyte *prev = (bbyte*)errjmp->prev;
+ if (prev >= begin && prev < end) {
+ fixup_ptr(prev, offset); /* fixup the prev pointer */
+ errjmp->prev = (struct blongjmp*)prev;
+ }
+ errjmp = (struct blongjmp*)prev;
+ }
+ }
+}
+
+/* set an exception handling recovery point. To do this, we have to
+ * push some VM states into the exception stack. */
+void be_except_block_setup(bvm *vm)
+{
+ struct bexecptframe *frame;
+ struct bexecptframe *lbase = be_stack_base(&vm->exceptstack);
+ be_stack_push(vm, &vm->exceptstack, NULL);
+ frame = be_stack_top(&vm->exceptstack);
+ frame->depth = be_stack_count(&vm->callstack); /* the call stack depth */
+ frame->ip = vm->ip; /* OP_EXBLK's next instruction pointer */
+ /* set longjmp() jump point */
+ frame->errjmp.status = 0;
+ frame->errjmp.prev = vm->errjmp; /* save long jump list */
+ vm->errjmp = &frame->errjmp;
+ fixup_exceptstack(vm, lbase);
+}
+
+/* resumes to the state of the previous frame when an exception occurs. */
+void be_except_block_resume(bvm *vm)
+{
+ int errorcode = vm->errjmp->status;
+ struct bexecptframe *frame = be_stack_top(&vm->exceptstack);
+ if (errorcode == BE_EXCEPTION) {
+ vm->errjmp = vm->errjmp->prev;
+ /* jump to except instruction */
+ vm->ip = frame->ip + IGET_sBx(frame->ip[-1]);
+ if (be_stack_count(&vm->callstack) > frame->depth) {
+ bvalue *top = vm->top;
+ bcallframe *cf = be_vector_at(&vm->callstack, frame->depth);
+ vm->top = cf->top;
+ vm->reg = cf->reg;
+ vm->cf = frame->depth ? cf - 1 : NULL;
+ be_vector_resize(vm, &vm->callstack, frame->depth);
+ /* copy the exception value and argument to the top of
+ * the current function */
+ vm->top[0] = top[0]; /* exception value */
+ vm->top[1] = top[1]; /* exception argument */
+ }
+ be_stack_pop(&vm->exceptstack);
+ } else { /* other errors cannot be catch by the except block */
+ /* find the next error handling location */
+ while (vm->errjmp == &frame->errjmp) {
+ vm->errjmp = vm->errjmp->prev;
+ be_stack_pop(&vm->exceptstack);
+ frame = be_stack_top(&vm->exceptstack);
+ }
+ be_throw(vm, errorcode); /* rethrow this exception */
+ }
+}
+
+/* only close the except block, no other operations */
+void be_except_block_close(bvm *vm, int count)
+{
+ struct bexecptframe *frame;
+ int size = be_stack_count(&vm->exceptstack);
+ be_assert(count > 0 && count <= size);
+ frame = be_vector_at(&vm->exceptstack, size - count);
+ vm->errjmp = frame->errjmp.prev;
+ be_vector_resize(vm, &vm->exceptstack, size - count);
+}
+
+void be_save_stacktrace(bvm *vm)
+{
+ bstack *stack = &vm->tracestack;
+ be_stack_clear(stack);
+ if (be_stack_count(&vm->callstack)) {
+ bcallframe *cf;
+ bcallframe *base = be_stack_base(&vm->callstack);
+ bcallframe *top = be_stack_top(&vm->callstack);
+ for (cf = base; cf <= top; ++cf) {
+ bcallsnapshot *st;
+ be_stack_push(vm, stack, NULL);
+ st = be_stack_top(stack);
+ st->func = *cf->func;
+ st->ip = cf == top ? vm->ip : cf[1].ip;
+ }
+ }
+}
diff --git a/lib/libesp32/berry/src/be_exec.h b/lib/libesp32/berry/src/be_exec.h
new file mode 100644
index 000000000..ffb85fa87
--- /dev/null
+++ b/lib/libesp32/berry/src/be_exec.h
@@ -0,0 +1,62 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_EXEC_H
+#define BE_EXEC_H
+
+#include "be_object.h"
+#include
+
+/* protected-call function */
+typedef void (*bpfunc)(bvm *vm, void *data);
+
+#if BE_DEBUG
+bvalue* be_incrtop(bvm *vm);
+#else
+/* increase top register */
+#define be_incrtop(vm) ((vm)->top++)
+#endif
+
+#define be_stackpop(vm, n) ((vm)->top -= (n))
+
+/* in MinGW-w64, setjmp / longjmp may be broken,
+ * so here is replaced by __builtin version. */
+#if defined(__GNUC__) && defined(__MINGW32__)
+ #define be_setjmp(env) __builtin_setjmp(env)
+ #define be_longjmp(env, v) __builtin_longjmp(env, v)
+#else
+ #define be_setjmp(env) setjmp(env)
+ #define be_longjmp(env, v) longjmp(env, v)
+#endif
+
+typedef jmp_buf bjmpbuf;
+
+struct blongjmp {
+ bjmpbuf b;
+ struct blongjmp *prev;
+ volatile int status; /* error code */
+};
+
+struct bexecptframe {
+ struct blongjmp errjmp; /* long jump information */
+ int depth; /* function call stack depth */
+ binstruction *ip; /* instruction pointer */
+};
+
+void be_throw(bvm *vm, int errorcode);
+int be_execprotected(bvm *vm, bpfunc f, void *data);
+int be_protectedparser(bvm *vm, const char *fname,
+ breader reader, void *data, bbool islocal);
+int be_protectedcall(bvm *vm, bvalue *v, int argc);
+void be_stackpush(bvm *vm);
+void be_stack_expansion(bvm *vm, int n);
+void be_except_block_setup(bvm *vm);
+void be_except_block_resume(bvm *vm);
+void be_except_block_close(bvm *vm, int count);
+void be_save_stacktrace(bvm *vm);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_filelib.c b/lib/libesp32/berry/src/be_filelib.c
new file mode 100644
index 000000000..87691809b
--- /dev/null
+++ b/lib/libesp32/berry/src/be_filelib.c
@@ -0,0 +1,224 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_mem.h"
+#include "be_sys.h"
+#include "be_gc.h"
+#include
+
+#define READLINE_STEP 100
+
+static int i_write(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ if(be_iscomptr(vm, -1) && (be_isstring(vm, 2) || be_isbytes(vm, 2))) {
+ void *fh = be_tocomptr(vm, -1);
+ size_t size = 0;
+ const char *data = NULL;
+ if (be_isstring(vm, 2)) {
+ data = be_tostring(vm, 2);
+ size = be_strlen(vm, 2);
+ } else {
+ data = be_tobytes(vm, 2, &size);
+ }
+ be_fwrite(fh, data, size);
+ }
+ be_return_nil(vm);
+}
+
+static size_t readsize(bvm *vm, int argc, void *fh)
+{
+ if (argc >=2 && be_isint(vm, 2)) {
+ return be_toindex(vm, 2);
+ }
+ return be_fsize(fh) - be_ftell(fh);
+}
+
+static int i_read(bvm *vm)
+{
+ int argc = be_top(vm);
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1)) {
+ void *fh = be_tocomptr(vm, -1);
+ size_t size = readsize(vm, argc, fh);
+ if (size) {
+ char *buffer = be_malloc(vm, size);
+ size = be_fread(fh, buffer, size);
+ be_pushnstring(vm, buffer, size);
+ be_free(vm, buffer, size);
+ } else {
+ be_pushstring(vm, "");
+ }
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int i_readbytes(bvm *vm)
+{
+ int argc = be_top(vm);
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1)) {
+ void *fh = be_tocomptr(vm, -1);
+ size_t size = readsize(vm, argc, fh);
+ if (size) {
+ /* avoid double allocation, using directly the internal buffer of bytes() */
+ be_getbuiltin(vm, "bytes");
+ be_pushint(vm, size);
+ be_call(vm, 1); /* call bytes() constructor with pre-sized buffer */
+ be_pop(vm, 1); /* bytes() instance is at top */
+
+ be_getmember(vm, -1, "resize");
+ be_pushvalue(vm, -2);
+ be_pushint(vm, size);
+ be_call(vm, 2); /* call b.resize(size) */
+ be_pop(vm, 3); /* bytes() instance is at top */
+
+ char *buffer = (char*) be_tobytes(vm, -1, NULL); /* we get the address of the internam buffer of size 'size' */
+ size = be_fread(fh, buffer, size);
+
+ /* resize if something went wrong */
+ be_getmember(vm, -1, "resize");
+ be_pushvalue(vm, -2);
+ be_pushint(vm, size);
+ be_call(vm, 2); /* call b.resize(size) */
+ be_pop(vm, 3); /* bytes() instance is at top */
+ } else {
+ be_pushbytes(vm, NULL, 0);
+ }
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int i_readline(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1)) {
+ void *fh = be_tocomptr(vm, -1);
+ size_t pos = 0, size = READLINE_STEP;
+ char *buffer = be_malloc(vm, size);
+ char *res = be_fgets(fh, buffer, (int)size);
+ while (res) {
+ pos += strlen(buffer + pos);
+ if (!pos || buffer[pos - 1] == '\n') {
+ break;
+ }
+ buffer = be_realloc(vm, buffer, size, size + READLINE_STEP);
+ res = be_fgets(fh, buffer + pos, READLINE_STEP);
+ size += READLINE_STEP;
+ }
+ be_pushnstring(vm, buffer, pos);
+ be_free(vm, buffer, size);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int i_seek(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1) && be_isint(vm, 2)) {
+ void *fh = be_tocomptr(vm, -1);
+ be_fseek(fh, be_toindex(vm, 2));
+ }
+ be_return_nil(vm);
+}
+
+static int i_tell(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1)) {
+ void *fh = be_tocomptr(vm, -1);
+ size_t pos = be_ftell(fh);
+ be_pushint(vm, cast(bint, pos));
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int i_size(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1)) {
+ void *fh = be_tocomptr(vm, -1);
+ size_t pos = be_fsize(fh);
+ be_pushint(vm, cast(bint, pos));
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int i_flush(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1)) {
+ void *fh = be_tocomptr(vm, -1);
+ be_fflush(fh);
+ }
+ be_return_nil(vm);
+}
+
+static int i_close(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ if (be_iscomptr(vm, -1)) {
+ void *fh = be_tocomptr(vm, -1);
+ be_fclose(fh);
+ be_pushnil(vm);
+ be_setmember(vm, 1, ".p");
+ }
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+static int m_open(bvm *vm)
+#else
+int be_nfunc_open(bvm *vm)
+#endif
+{
+ int argc = be_top(vm);
+ const char *fname, *mode;
+ static const bnfuncinfo members[] = {
+ { ".p", NULL },
+ { "write", i_write },
+ { "read", i_read },
+ { "readbytes", i_readbytes },
+ { "readline", i_readline },
+ { "seek", i_seek },
+ { "tell", i_tell },
+ { "size", i_size },
+ { "flush", i_flush },
+ { "close", i_close },
+ { "deinit", i_close },
+ { NULL, NULL }
+ };
+ fname = argc >= 1 && be_isstring(vm, 1) ? be_tostring(vm, 1) : NULL;
+ mode = argc >= 2 && be_isstring(vm, 2) ? be_tostring(vm, 2) : "r";
+ if (fname) {
+ void *fh = be_fopen(fname, mode);
+ if (fh == NULL) {
+ be_raise(vm, "io_error",
+ be_pushfstring(vm, "cannot open file '%s'", fname));
+ }
+ be_pushclass(vm, "file", members);
+ be_call(vm, 0);
+ be_pushcomptr(vm, fh);
+ be_setmember(vm, -2, ".p");
+ be_pop(vm, 1);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+void be_load_filelib(bvm *vm)
+{
+ be_regfunc(vm, "open", m_open);
+}
+#endif
diff --git a/lib/libesp32/berry/src/be_func.c b/lib/libesp32/berry/src/be_func.c
new file mode 100644
index 000000000..d49229954
--- /dev/null
+++ b/lib/libesp32/berry/src/be_func.c
@@ -0,0 +1,181 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_func.h"
+#include "be_gc.h"
+#include "be_mem.h"
+#include "be_vm.h"
+#include "be_exec.h"
+#include
+
+#define clousersize(n) \
+ (sizeof(bclosure) + sizeof(bupval*) * ((size_t)(n) - 1))
+
+static bupval* findupval(bvm *vm, bvalue *level)
+{
+ bupval *node = vm->upvalist;
+ while (node != NULL && node->value > level) {
+ node = node->u.next;
+ }
+ if (!node || node->value != level) {
+ /* not found */
+ node = be_malloc(vm, sizeof(bupval));
+ node->value = level;
+ node->refcnt = 0;
+ /* insert to list head */
+ node->u.next = vm->upvalist;
+ vm->upvalist = node;
+ }
+ return node;
+}
+
+void be_initupvals(bvm *vm, bclosure *cl)
+{
+ int count = cl->proto->nupvals;
+ bupvaldesc *desc = cl->proto->upvals;
+ bvalue *stack = vm->reg;
+ bupval **uv = cl->upvals;
+ bupval **superuv = cast(bclosure*, var_toobj(vm->cf->func))->upvals;
+ for (; count--; desc++, uv++) {
+ if (desc->instack) {
+ bvalue *ref = stack + desc->idx;
+ *uv = findupval(vm, ref);
+ } else {
+ *uv = superuv[desc->idx];
+ }
+ (*uv)->refcnt++;
+ }
+}
+
+void be_upvals_close(bvm *vm, bvalue *level)
+{
+ bupval *node = vm->upvalist, *next;
+ bupval **prev = &vm->upvalist;
+ while (node) {
+ next = node->u.next;
+ if (node->value >= level) {
+ if (!node->refcnt) {
+ be_free(vm, node, sizeof(bupval));
+ } else {
+ node->u.value = *node->value; /* move value to upvalue slot */
+ node->value = &node->u.value;
+ }
+ *prev = next; /* remove from linked list */
+ } else {
+ prev = &node->u.next;
+ }
+ node = next;
+ }
+}
+
+void be_release_upvalues(bvm *vm, bclosure *cl)
+{
+ int i, count = cl->nupvals;
+ for (i = 0; i < count; ++i) {
+ bupval *uv = cl->upvals[i];
+ if (uv) {
+ if (uv->refcnt) {
+ --uv->refcnt;
+ }
+ /* delete non-referenced closed upvalue */
+ if (uv->value == &uv->u.value && !uv->refcnt) {
+ be_free(vm, uv, sizeof(bupval));
+ }
+ }
+ }
+}
+
+bproto* be_newproto(bvm *vm)
+{
+ bgcobject *gco = be_gcnew(vm, BE_PROTO, bproto);
+ bproto *p = cast_proto(gco);
+ if (p) {
+ p->upvals = NULL;
+ p->ktab = NULL;
+ p->ptab = NULL;
+ p->code = NULL;
+ p->name = NULL;
+ p->gray = NULL;
+ p->codesize = 0;
+ p->nupvals = 0;
+ p->nproto = 0;
+ p->nconst = 0;
+ p->nstack = 0;
+ p->codesize = 0;
+ p->argc = 0;
+ p->varg = 0;
+ p->source = NULL;
+#if BE_DEBUG_RUNTIME_INFO
+ p->lineinfo = NULL;
+ p->nlineinfo = 0;
+#endif
+#if BE_DEBUG_VAR_INFO
+ p->varinfo = NULL;
+ p->nvarinfo = 0;
+#endif
+ }
+ return p;
+}
+
+bclosure* be_newclosure(bvm *vm, int nupval)
+{
+ bgcobject *gco = be_newgcobj(vm, BE_CLOSURE, clousersize(nupval));
+ bclosure *cl = cast_closure(gco);
+ if (cl) {
+ cl->proto = NULL;
+ cl->nupvals = (bbyte)nupval;
+ while (nupval--) {
+ cl->upvals[nupval] = NULL;
+ }
+ }
+ return cl;
+}
+
+static void init_upvals(bvm *vm, bntvclos *f)
+{
+ int count = f->nupvals;
+ bupval **upvals = &be_ntvclos_upval(f, 0);
+ while (count--) {
+ bupval *uv = be_malloc(vm, sizeof(bupval)); /* was closed */
+ uv->value = &uv->u.value;
+ uv->refcnt = 1;
+ var_setnil(uv->value);
+ *upvals++ = uv;
+ }
+}
+
+bntvclos* be_newntvclosure(bvm *vm, bntvfunc cf, int nupvals)
+{
+ size_t size = sizeof(bntvclos) + sizeof(bupval*) * nupvals;
+ bgcobject *gco = be_newgcobj(vm, BE_NTVCLOS, size);
+ bntvclos *f = cast_ntvclos(gco);
+ if (f) {
+ f->f = cf;
+ f->nupvals = (bbyte)nupvals;
+ if (nupvals) {
+ var_setntvclos(vm->top, f);
+ be_incrtop(vm);
+ init_upvals(vm, f); /* may be GC */
+ be_stackpop(vm, 1);
+ }
+ }
+ return f;
+}
+
+#if BE_DEBUG_VAR_INFO
+bstring* be_func_varname(bproto *proto, int index, int pc)
+{
+ int i, nvarinfo = proto->nvarinfo;
+ bvarinfo *varinfo = proto->varinfo;
+ for (i = 0; i < nvarinfo && varinfo[i].beginpc <= pc; ++i) {
+ if (pc <= varinfo[i].endpc && index-- == 0) {
+ return varinfo[i].name;
+ }
+ }
+ return NULL;
+}
+#endif
diff --git a/lib/libesp32/berry/src/be_func.h b/lib/libesp32/berry/src/be_func.h
new file mode 100644
index 000000000..a9cdaa127
--- /dev/null
+++ b/lib/libesp32/berry/src/be_func.h
@@ -0,0 +1,27 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_FUNC_H
+#define BE_FUNC_H
+
+#include "be_object.h"
+
+#define be_newntvclos(vm, cf) \
+ be_newntvclosure(vm, cf, 0)
+
+#define be_ntvclos_upval(cc, n) \
+ (((bupval**)((size_t)cc + sizeof(bntvclos)))[n])
+
+void be_initupvals(bvm *vm, bclosure *cl);
+void be_upvals_close(bvm *vm, bvalue *level);
+void be_release_upvalues(bvm *vm, bclosure *cl);
+bproto* be_newproto(bvm *vm);
+bclosure* be_newclosure(bvm *vm, int nupval);
+bntvclos* be_newntvclosure(bvm *vm, bntvfunc cf, int nupvals);
+bstring* be_func_varname(bproto *proto, int index, int pc);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_gc.c b/lib/libesp32/berry/src/be_gc.c
new file mode 100644
index 000000000..8d19affb1
--- /dev/null
+++ b/lib/libesp32/berry/src/be_gc.c
@@ -0,0 +1,565 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_gc.h"
+#include "be_vm.h"
+#include "be_mem.h"
+#include "be_var.h"
+#include "be_vector.h"
+#include "be_string.h"
+#include "be_class.h"
+#include "be_list.h"
+#include "be_func.h"
+#include "be_map.h"
+#include "be_module.h"
+#include "be_exec.h"
+#include "be_debug.h"
+
+#define GC_PAUSE (1 << 0) /* GC will not be executed automatically */
+#define GC_HALT (1 << 1) /* GC completely stopped */
+#define GC_ALLOC (1 << 2) /* GC in alloc */
+
+#define gc_try(expr) be_assert(expr); if (expr)
+#define gc_setdark_safe(o) if (o) gc_setdark(o)
+
+#define next_threshold(gc) ((gc).usage * ((size_t)(gc).steprate + 100) / 100)
+
+#define link_gray(vm, obj) { \
+ (obj)->gray = (vm)->gc.gray; \
+ (vm)->gc.gray = gc_object(obj); \
+}
+
+static void destruct_object(bvm *vm, bgcobject *obj);
+static void free_object(bvm *vm, bgcobject *obj);
+
+void be_gc_init(bvm *vm)
+{
+ vm->gc.usage = sizeof(bvm);
+ be_gc_setsteprate(vm, 200);
+}
+
+void be_gc_deleteall(bvm *vm)
+{
+ bupval *uv, *uvnext;
+ bgcobject *node, *next;
+ /* halt GC and delete all objects */
+ vm->gc.status |= GC_HALT;
+ /* first: call destructor */
+ for (node = vm->gc.list; node; node = node->next) {
+ destruct_object(vm, node);
+ }
+ /* second: free objects */
+ for (node = vm->gc.list; node; node = next) {
+ next = node->next;
+ free_object(vm, node);
+ }
+ /* delete open upvalue list */
+ for (uv = vm->upvalist; uv; uv = uvnext) {
+ uvnext = uv->u.next;
+ be_free(vm, uv, sizeof(bupval));
+ }
+}
+
+void be_gc_setsteprate(bvm *vm, int rate)
+{
+ be_assert(rate >= 100 && rate <= 355);
+ vm->gc.steprate = (bbyte)(rate - 100);
+ vm->gc.threshold = next_threshold(vm->gc);
+}
+
+void be_gc_setpause(bvm *vm, int pause)
+{
+ if (pause) {
+ vm->gc.status |= GC_PAUSE;
+ } else {
+ vm->gc.status &= ~GC_PAUSE;
+ }
+}
+
+bgcobject* be_newgcobj(bvm *vm, int type, size_t size)
+{
+ bgcobject *obj = be_malloc(vm, size);
+ be_gc_auto(vm);
+ var_settype(obj, (bbyte)type); /* mark the object type */
+ obj->marked = GC_WHITE; /* default gc object type is white */
+ obj->next = vm->gc.list; /* link to the next field */
+ vm->gc.list = obj; /* insert to head */
+ return obj;
+}
+
+bgcobject* be_gc_newstr(bvm *vm, size_t size, int islong)
+{
+ bgcobject *obj;
+ if (islong) { /* creating long strings is similar to ordinary GC objects */
+ return be_newgcobj(vm, BE_STRING, size);
+ }
+ obj = be_malloc(vm, size);
+ be_gc_auto(vm);
+ var_settype(obj, BE_STRING); /* mark the object type to BE_STRING */
+ obj->marked = GC_WHITE; /* default string type is white */
+ return obj;
+}
+
+void be_gc_fix(bvm *vm, bgcobject *obj)
+{
+ (void)vm;
+ if (!gc_isconst(obj)) {
+ gc_setfixed(obj);
+ }
+}
+
+void be_gc_unfix(bvm *vm, bgcobject *obj)
+{
+ (void)vm;
+ if (!gc_isconst(obj)) {
+ gc_clearfixed(obj);
+ }
+}
+
+bbool be_gc_fix_set(bvm *vm, bgcobject *obj, bbool fix)
+{
+ (void)vm;
+ bbool was_fixed = gc_isfixed(obj);
+ if (!gc_isconst(obj)) {
+ if (fix) {
+ gc_setfixed(obj);
+ } else {
+ gc_clearfixed(obj);
+ }
+ }
+ return was_fixed;
+}
+
+static void mark_gray(bvm *vm, bgcobject *obj)
+{
+ if (obj && gc_iswhite(obj) && !gc_isconst(obj)) {
+ gc_setgray(obj);
+ switch (var_type(obj)) {
+ case BE_STRING: gc_setdark(obj); break; /* just set dark */
+ case BE_CLASS: link_gray(vm, cast_class(obj)); break;
+ case BE_PROTO: link_gray(vm, cast_proto(obj)); break;
+ case BE_INSTANCE: link_gray(vm, cast_instance(obj)); break;
+ case BE_MAP: link_gray(vm, cast_map(obj)); break;
+ case BE_LIST: link_gray(vm, cast_list(obj)); break;
+ case BE_CLOSURE: link_gray(vm, cast_closure(obj)); break;
+ case BE_NTVCLOS: link_gray(vm, cast_ntvclos(obj)); break;
+ case BE_MODULE: link_gray(vm, cast_module(obj)); break;
+ case BE_COMOBJ: gc_setdark(obj); break; /* just set dark */
+ default: break;
+ }
+ }
+}
+
+static void mark_gray_var(bvm *vm, bvalue *value)
+{
+ if (be_isgcobj(value)) {
+ mark_gray(vm, var_togc(value));
+ }
+}
+
+static void mark_map(bvm *vm, bgcobject *obj)
+{
+ bmap *map = cast_map(obj);
+ gc_try (map != NULL) {
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ vm->gc.gray = map->gray; /* remove object from gray list */
+ while ((node = be_map_next(map, &iter)) != NULL) {
+ bmapkey *key = &node->key;
+ bvalue *val = &node->value;
+ if (be_isgctype((signed char)key->type)) {
+ mark_gray(vm, var_togc(key));
+ }
+ mark_gray_var(vm, val);
+ }
+ }
+}
+
+static void mark_list(bvm *vm, bgcobject *obj)
+{
+ blist *list = cast_list(obj);
+ gc_try (list != NULL) {
+ bvalue *val = be_list_data(list);
+ bvalue *end = be_list_end(list);
+ vm->gc.gray = list->gray; /* remove object from gray list */
+ for (; val < end; val++) {
+ mark_gray_var(vm, val);
+ }
+ }
+}
+
+static void mark_proto(bvm *vm, bgcobject *obj)
+{
+ bproto *p = cast_proto(obj);
+ gc_try (p != NULL) {
+ int count;
+ bvalue *k = p->ktab;
+ bproto **ptab = p->ptab;
+ vm->gc.gray = p->gray; /* remove object from gray list */
+ for (count = p->nconst; count--; ++k) {
+ mark_gray_var(vm, k);
+ }
+ for (count = p->nproto; count--; ++ptab) {
+ mark_gray(vm, gc_object(*ptab));
+ }
+ gc_setdark_safe(p->name);
+ gc_setdark_safe(p->source);
+#if BE_DEBUG_VAR_INFO
+ if (p->nvarinfo) {
+ bvarinfo *vinfo = p->varinfo;
+ be_assert(vinfo != NULL);
+ for (count = p->nvarinfo; count--; ++vinfo) {
+ gc_setdark_safe(vinfo->name);
+ }
+ }
+#endif
+ }
+}
+
+static void mark_closure(bvm *vm, bgcobject *obj)
+{
+ bclosure *cl = cast_closure(obj);
+ gc_try (cl != NULL) {
+ int count = cl->nupvals;
+ bupval **uv = cl->upvals;
+ vm->gc.gray = cl->gray; /* remove object from gray list */
+ for (; count--; ++uv) {
+ if (*uv && (*uv)->refcnt) {
+ mark_gray_var(vm, (*uv)->value);
+ }
+ }
+ mark_gray(vm, gc_object(cl->proto));
+ }
+}
+
+static void mark_ntvclos(bvm *vm, bgcobject *obj)
+{
+ bntvclos *f = cast_ntvclos(obj);
+ gc_try (f != NULL) {
+ int count = f->nupvals;
+ bupval **uv = &be_ntvclos_upval(f, 0);
+ vm->gc.gray = f->gray; /* remove object from gray list */
+ for (; count--; ++uv) {
+ if (*uv && (*uv)->refcnt) {
+ mark_gray_var(vm, (*uv)->value);
+ }
+ }
+ }
+}
+
+static void mark_class(bvm *vm, bgcobject *obj)
+{
+ bclass *c = cast_class(obj);
+ gc_try (c != NULL) {
+ vm->gc.gray = c->gray; /* remove object from gray list */
+ mark_gray(vm, gc_object(be_class_name(c)));
+ mark_gray(vm, gc_object(be_class_members(c)));
+ mark_gray(vm, gc_object(be_class_super(c)));
+ }
+}
+
+static void mark_instance(bvm *vm, bgcobject *obj)
+{
+ binstance *o = cast_instance(obj);
+ gc_try (o != NULL) {
+ bvalue *var = be_instance_members(o);
+ int nvar = be_instance_member_count(o);
+ vm->gc.gray = o->gray; /* remove object from gray list */
+ mark_gray(vm, gc_object(be_instance_class(o)));
+ mark_gray(vm, gc_object(be_instance_super(o)));
+ for (; nvar--; var++) { /* mark variables */
+ mark_gray_var(vm, var);
+ }
+ }
+}
+
+static void mark_module(bvm *vm, bgcobject *obj)
+{
+ bmodule *o = cast_module(obj);
+ gc_try (o != NULL) {
+ vm->gc.gray = o->gray; /* remove object from gray list */
+ mark_gray(vm, gc_object(o->table));
+ if (!gc_isconst(o) && gc_exmark(o) & BE_MODULE_NAME) {
+ mark_gray(vm, gc_object(o->info.sname));
+ }
+ }
+}
+
+static void free_proto(bvm *vm, bgcobject *obj)
+{
+ bproto *proto = cast_proto(obj);
+ gc_try (proto != NULL) {
+ be_free(vm, proto->upvals, proto->nupvals * sizeof(bupvaldesc));
+ be_free(vm, proto->ktab, proto->nconst * sizeof(bvalue));
+ be_free(vm, proto->ptab, proto->nproto * sizeof(bproto*));
+ be_free(vm, proto->code, proto->codesize * sizeof(binstruction));
+#if BE_DEBUG_RUNTIME_INFO
+ be_free(vm, proto->lineinfo, proto->nlineinfo * sizeof(blineinfo));
+#endif
+#if BE_DEBUG_VAR_INFO
+ be_free(vm, proto->varinfo, proto->nvarinfo * sizeof(bvarinfo));
+#endif
+ be_free(vm, proto, sizeof(bproto));
+ }
+}
+
+static void free_closure(bvm *vm, bgcobject *obj)
+{
+ bclosure *cl = cast_closure(obj);
+ gc_try (cl != NULL) {
+ int count = cl->nupvals;
+ be_release_upvalues(vm, cl);
+ be_free(vm, cl, sizeof(bclosure)
+ + sizeof(bupval*) * ((size_t)count - 1));
+ }
+}
+
+static void free_ntvclos(bvm *vm, bgcobject *obj)
+{
+ bntvclos *f = cast_ntvclos(obj);
+ gc_try (f != NULL) {
+ int count = f->nupvals;
+ bupval **uv = &be_ntvclos_upval(f, 0);
+ while (count--) {
+ be_free(vm, *uv++, sizeof(bupval));
+ }
+ be_free(vm, f, sizeof(bntvclos) + sizeof(bupval*) * f->nupvals);
+ }
+}
+
+static void free_lstring(bvm *vm, bgcobject *obj)
+{
+ blstring *ls = gc_cast(obj, BE_STRING, blstring);
+ gc_try (ls != NULL) {
+ be_free(vm, ls, sizeof(blstring) + ls->llen + 1);
+ }
+}
+
+static void free_instance(bvm *vm, bgcobject *obj)
+{
+ binstance *o = cast_instance(obj);
+ int nvar = be_instance_member_count(o);
+ be_free(vm, obj, sizeof(binstance) + sizeof(bvalue) * (nvar - 1));
+}
+
+static void free_object(bvm *vm, bgcobject *obj)
+{
+ switch (var_type(obj)) {
+ case BE_STRING: free_lstring(vm, obj); break; /* long string */
+ case BE_CLASS: be_free(vm, obj, sizeof(bclass)); break;
+ case BE_INSTANCE: free_instance(vm, obj); break;
+ case BE_MAP: be_map_delete(vm, cast_map(obj)); break;
+ case BE_LIST: be_list_delete(vm, cast_list(obj)); break;
+ case BE_CLOSURE: free_closure(vm, obj); break;
+ case BE_NTVCLOS: free_ntvclos(vm, obj); break;
+ case BE_PROTO: free_proto(vm, obj); break;
+ case BE_MODULE: be_module_delete(vm, cast_module(obj)); break;
+ case BE_COMOBJ: be_commonobj_delete(vm, obj); break;
+ default: break; /* case BE_STRING: break; */
+ }
+}
+
+static void premark_internal(bvm *vm)
+{
+ mark_gray(vm, gc_object(vm->module.loaded));
+ mark_gray(vm, gc_object(vm->module.path));
+ mark_gray(vm, gc_object(vm->ntvclass));
+ mark_gray(vm, gc_object(vm->registry));
+#if BE_USE_DEBUG_HOOK
+ if (be_isgcobj(&vm->hook)) {
+ mark_gray(vm, gc_object(var_toobj(&vm->hook)));
+ }
+#endif
+}
+
+static void premark_global(bvm *vm)
+{
+ bvalue *v = vm->gbldesc.global.vlist.data;
+ bvalue *end = v + be_global_count(vm);
+ while (v < end) {
+ if (be_isgcobj(v)) {
+ mark_gray(vm, var_togc(v));
+ }
+ ++v;
+ }
+ v = vm->gbldesc.builtin.vlist.data;
+ end = v + be_builtin_count(vm);
+ while (v < end) {
+ mark_gray_var(vm, v++);
+ }
+}
+
+static void premark_stack(bvm *vm)
+{
+ bvalue *v = vm->stack, *end = vm->top;
+ /* mark live objects */
+ for (; v < end; ++v) {
+ mark_gray_var(vm, v);
+ }
+ /* set other values to nil */
+ end = vm->stacktop;
+ for (; v < end; ++v) {
+ var_setnil(v);
+ }
+}
+
+static void premark_tracestack(bvm *vm)
+{
+ bcallsnapshot *cf = be_vector_data(&vm->tracestack);
+ bcallsnapshot *end = be_vector_end(&vm->tracestack);
+ for (; cf <= end; ++cf) {
+ mark_gray_var(vm, &cf->func);
+ }
+}
+
+static void premark_fixed(bvm *vm)
+{
+ bgcobject *node = vm->gc.list;
+ for (; node; node = node->next) {
+ if (gc_isfixed(node) && gc_iswhite(node)) {
+ mark_gray(vm, node);
+ }
+ }
+}
+
+static void mark_unscanned(bvm *vm)
+{
+ while (vm->gc.gray) {
+ bgcobject *obj = vm->gc.gray;
+ if (obj && !gc_isdark(obj) && !gc_isconst(obj)) {
+ gc_setdark(obj);
+ switch (var_type(obj)) {
+ case BE_CLASS: mark_class(vm, obj); break;
+ case BE_PROTO: mark_proto(vm, obj); break;
+ case BE_INSTANCE: mark_instance(vm, obj); break;
+ case BE_MAP: mark_map(vm, obj); break;
+ case BE_LIST: mark_list(vm, obj); break;
+ case BE_CLOSURE: mark_closure(vm, obj); break;
+ case BE_NTVCLOS: mark_ntvclos(vm, obj); break;
+ case BE_MODULE: mark_module(vm, obj); break;
+ default:
+ be_assert(0); /* error */
+ break;
+ }
+ }
+ }
+}
+
+static void destruct_object(bvm *vm, bgcobject *obj)
+{
+ if (vm->gc.status & GC_ALLOC) {
+ return; /* no destructor is called during the allocation. */
+ }
+ if (obj->type == BE_INSTANCE) {
+ int type;
+ binstance *ins = cast_instance(obj);
+ /* does not GC when creating the string "deinit". */
+ type = be_instance_member_simple(vm, ins, str_literal(vm, "deinit"), vm->top);
+ be_incrtop(vm);
+ if (basetype(type) == BE_FUNCTION) {
+ var_setinstance(vm->top, ins); /* push instance on stack as arg 1 */
+ be_incrtop(vm);
+ be_dofunc(vm, vm->top - 2, 1); /* warning, there shoudln't be any exception raised here, or the gc stops */
+ be_stackpop(vm, 1);
+ }
+ be_stackpop(vm, 1);
+ }
+}
+
+static void destruct_white(bvm *vm)
+{
+ bgcobject *node = vm->gc.list;
+ /* since the destructor may allocate objects, we must first suspend the GC */
+ vm->gc.status |= GC_HALT; /* mark GC is halt */
+ while (node) {
+ if (gc_iswhite(node)) {
+ destruct_object(vm, node);
+ }
+ node = node->next;
+ }
+ vm->gc.status &= ~GC_HALT; /* reset GC halt flag */
+}
+
+static void delete_white(bvm *vm)
+{
+ bgcobject *node, *prev, *next;
+ for (node = vm->gc.list, prev = node; node; node = next) {
+ next = node->next;
+ if (gc_iswhite(node)) {
+ if (node == vm->gc.list) { /* first node */
+ vm->gc.list = node->next;
+ prev = node->next;
+ } else { /* not first node */
+ prev->next = next;
+ }
+ free_object(vm, node);
+#if BE_USE_PERF_COUNTERS
+ vm->counter_gc_freed++;
+#endif
+ } else {
+ gc_setwhite(node);
+ prev = node;
+ }
+ }
+}
+
+static void reset_fixedlist(bvm *vm)
+{
+ bgcobject *node;
+ for (node = vm->gc.fixed; node; node = node->next) {
+ if (gc_isdark(node)) {
+ gc_setwhite(node);
+ }
+ }
+}
+
+void be_gc_auto(bvm *vm)
+{
+#if BE_USE_DEBUG_GC
+ if (vm->gc.status & GC_PAUSE) { /* force gc each time it's possible */
+ be_gc_collect(vm);
+ }
+#else
+ if (vm->gc.status & GC_PAUSE && vm->gc.usage > vm->gc.threshold) {
+ be_gc_collect(vm);
+ }
+#endif
+}
+
+size_t be_gc_memcount(bvm *vm)
+{
+ return vm->gc.usage;
+}
+
+void be_gc_collect(bvm *vm)
+{
+ if (vm->gc.status & GC_HALT) {
+ return; /* the GC cannot run for some reason */
+ }
+#if BE_USE_PERF_COUNTERS
+ vm->counter_gc_kept = 0;
+ vm->counter_gc_freed = 0;
+#endif
+ if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_START, vm->gc.usage);
+ /* step 1: set root-set reference objects to unscanned */
+ premark_internal(vm); /* object internal the VM */
+ premark_global(vm); /* global objects */
+ premark_stack(vm); /* stack objects */
+ premark_tracestack(vm); /* trace stack objects */
+ premark_fixed(vm); /* fixed objects */
+ /* step 2: set unscanned objects to black */
+ mark_unscanned(vm);
+ /* step 3: destruct and delete unreachable objects */
+ destruct_white(vm);
+ delete_white(vm);
+ be_gcstrtab(vm);
+ /* step 4: reset the fixed objects */
+ reset_fixedlist(vm);
+ /* step 5: calculate the next GC threshold */
+ vm->gc.threshold = next_threshold(vm->gc);
+ if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_kept, vm->counter_gc_freed);
+}
diff --git a/lib/libesp32/berry/src/be_gc.h b/lib/libesp32/berry/src/be_gc.h
new file mode 100644
index 000000000..0e0ce9e82
--- /dev/null
+++ b/lib/libesp32/berry/src/be_gc.h
@@ -0,0 +1,80 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_GC_H
+#define BE_GC_H
+
+#include "be_object.h"
+
+#define gc_object(o) cast(bgcobject*, o)
+#define gc_cast(o, t, T) ((o) && (o)->type == (t) ? (T*)(o) : NULL)
+#define cast_proto(o) gc_cast(o, BE_PROTO, bproto)
+#define cast_closure(o) gc_cast(o, BE_CLOSURE, bclosure)
+#define cast_ntvclos(o) gc_cast(o, BE_NTVCLOS, bntvclos)
+#define cast_str(o) gc_cast(o, BE_STRING, bstring)
+#define cast_class(o) gc_cast(o, BE_CLASS, bclass)
+#define cast_instance(o) gc_cast(o, BE_INSTANCE, binstance)
+#define cast_map(o) gc_cast(o, BE_MAP, bmap)
+#define cast_list(o) gc_cast(o, BE_LIST, blist)
+#define cast_module(o) gc_cast(o, BE_MODULE, bmodule)
+
+#define gc_ismark(o, m) (((o)->marked & 0x03) == m)
+#define gc_iswhite(o) gc_ismark((o), GC_WHITE)
+#define gc_isgray(o) gc_ismark((o), GC_GRAY)
+#define gc_isdark(o) gc_ismark((o), GC_DARK)
+
+#define gc_setmark(o, m) \
+if (!gc_isconst(o)) { \
+ (o)->marked &= ~0x03; \
+ (o)->marked |= (m) & 0x03; \
+}
+
+#define gc_setwhite(o) gc_setmark((o), GC_WHITE)
+#define gc_setgray(o) gc_setmark((o), GC_GRAY)
+#if BE_USE_PERF_COUNTERS
+ #define gc_setdark(o) { vm->counter_gc_kept++; gc_setmark((o), GC_DARK); }
+#else
+ #define gc_setdark(o) gc_setmark((o), GC_DARK)
+#endif
+#define gc_isfixed(o) (((o)->marked & GC_FIXED) != 0)
+#define gc_setfixed(o) ((o)->marked |= GC_FIXED)
+#define gc_clearfixed(o) ((o)->marked &= ~GC_FIXED)
+#define gc_isconst(o) (((o)->marked & GC_CONST) != 0)
+#define gc_exmark(o) (((o)->marked >> 4) & 0x0F)
+#define gc_setexmark(o, k) ((o)->marked |= (k) << 4)
+
+#define be_isgctype(t) ((t) >= BE_GCOBJECT)
+#define be_isgcobj(o) be_isgctype(var_type(o))
+#define be_gcnew(v, t, s) be_newgcobj((v), (t), sizeof(s))
+
+#define set_fixed(s) bbool _was_fixed = be_gc_fix_set(vm, cast(bgcobject*, (s)), 1)
+#define restore_fixed(s) be_gc_fix_set(vm, cast(bgcobject*, (s)), _was_fixed);
+
+/* the GC mark uses bit4:0 of the `object->marked` field,
+ * so other bits can be used for special flags (ex-mark). */
+typedef enum {
+ GC_WHITE = 0x00, /* unreachable object */
+ GC_GRAY = 0x01, /* unscanned object */
+ GC_DARK = 0x02, /* scanned object */
+ GC_FIXED = 0x04, /* disable collection mark */
+ GC_CONST = 0x08 /* constant object mark */
+} bgcmark;
+
+void be_gc_init(bvm *vm);
+void be_gc_deleteall(bvm *vm);
+void be_gc_setsteprate(bvm *vm, int rate);
+void be_gc_setpause(bvm *vm, int pause);
+size_t be_gc_memcount(bvm *vm);
+bgcobject *be_newgcobj(bvm *vm, int type, size_t size);
+bgcobject* be_gc_newstr(bvm *vm, size_t size, int islong);
+void be_gc_fix(bvm *vm, bgcobject *obj);
+void be_gc_unfix(bvm *vm, bgcobject *obj);
+bbool be_gc_fix_set(bvm *vm, bgcobject *obj, bbool fix);
+void be_gc_collect(bvm *vm);
+void be_gc_auto(bvm *vm);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_gclib.c b/lib/libesp32/berry/src/be_gclib.c
new file mode 100644
index 000000000..9ca9eab50
--- /dev/null
+++ b/lib/libesp32/berry/src/be_gclib.c
@@ -0,0 +1,47 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_gc.h"
+
+#if BE_USE_GC_MODULE
+
+static int m_allocated(bvm *vm)
+{
+ size_t count = be_gc_memcount(vm);
+ if (count < 0x80000000) {
+ be_pushint(vm, (bint)count);
+ } else {
+ be_pushreal(vm, (breal)count);
+ }
+ be_return(vm);
+}
+
+static int m_collect(bvm *vm)
+{
+ be_gc_collect(vm);
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(gc){
+ be_native_module_function("allocated", m_allocated),
+ be_native_module_function("collect", m_collect)
+};
+
+be_define_native_module(gc, NULL);
+#else
+/* @const_object_info_begin
+module gc (scope: global, depend: BE_USE_GC_MODULE) {
+ allocated, func(m_allocated)
+ collect, func(m_collect)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_gc.h"
+#endif
+
+#endif /* BE_USE_SYS_MODULE */
diff --git a/lib/libesp32/berry/src/be_globallib.c b/lib/libesp32/berry/src/be_globallib.c
new file mode 100644
index 000000000..1d8267b95
--- /dev/null
+++ b/lib/libesp32/berry/src/be_globallib.c
@@ -0,0 +1,86 @@
+/********************************************************************
+** Copyright (c) 2018-2021 Guan Wenliang & Stephan Hadinger
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_module.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_class.h"
+#include "be_debug.h"
+#include "be_map.h"
+#include "be_vm.h"
+#include
+
+#if BE_USE_GLOBAL_MODULE
+
+#define global(vm) ((vm)->gbldesc.global)
+
+static void dump_map_keys(bvm *vm, bmap *map)
+{
+ if (!map) { return; } /* protect agains potential null pointer */
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(map, &iter)) != NULL) {
+ if (var_isstr(&node->key)) {
+ bstring *s = var_tostr(&node->key);
+ be_pushstring(vm, str(s));
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ }
+ }
+}
+
+static int m_globals(bvm *vm)
+{
+ be_newobject(vm, "list");
+ dump_map_keys(vm, global(vm).vtab);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+static int m_findglobal(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 1 && be_isstring(vm, 1)) {
+ const char * name = be_tostring(vm, 1);
+ be_getglobal(vm, name);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int m_setglobal(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 2 && be_isstring(vm, 1)) {
+ const char * name = be_tostring(vm, 1);
+ be_setglobal(vm, name);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(global) {
+ be_native_module_function("()", m_globals),
+ be_native_module_function("member", m_findglobal),
+ be_native_module_function("setmember", m_setglobal),
+};
+
+be_define_native_module(global, NULL);
+#else
+/* @const_object_info_begin
+module global (scope: global, depend: BE_USE_GLOBAL_MODULE) {
+ (), func(m_globals)
+ member, func(m_findglobal)
+ setmember, func(m_setglobal)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_global.h"
+#endif
+
+#endif /* BE_USE_GLOBAL_MODULE */
diff --git a/lib/libesp32/berry/src/be_introspectlib.c b/lib/libesp32/berry/src/be_introspectlib.c
new file mode 100644
index 000000000..61f614daf
--- /dev/null
+++ b/lib/libesp32/berry/src/be_introspectlib.c
@@ -0,0 +1,157 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_module.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_class.h"
+#include "be_debug.h"
+#include "be_map.h"
+#include "be_vm.h"
+#include "be_exec.h"
+#include "be_gc.h"
+#include
+
+#if BE_USE_INTROSPECT_MODULE
+
+#define global(vm) ((vm)->gbldesc.global)
+#define builtin(vm) ((vm)->gbldesc.builtin)
+
+static void dump_map_keys(bvm *vm, bmap *map)
+{
+ if (!map) { return; } /* protect agains potential null pointer */
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(map, &iter)) != NULL) {
+ if (var_isstr(&node->key)) {
+ bstring *s = var_tostr(&node->key);
+ be_pushstring(vm, str(s));
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ }
+ }
+}
+
+static int m_attrlist(bvm *vm)
+{
+ int top = be_top(vm);
+ be_newobject(vm, "list");
+ if (top >= 1) {
+ bvalue *v = be_indexof(vm, 1);
+ void *obj = var_toobj(v);
+ switch (var_type(v)) {
+ case BE_NIL: dump_map_keys(vm, global(vm).vtab); break;
+ case BE_MODULE: dump_map_keys(vm, ((bmodule*)obj)->table); break;
+ case BE_CLASS: dump_map_keys(vm, ((bclass*)obj)->members); break;
+ case BE_INSTANCE: dump_map_keys(vm, ((binstance*)obj)->_class->members); break;
+ default: break;
+ }
+ } else { /* if no parameter, then dump globals */
+ dump_map_keys(vm, global(vm).vtab);
+ }
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+static void m_findmember_protected(bvm *vm, void* data)
+{
+ be_getmember(vm, 1, (const char*) data);
+}
+
+static int m_findmember(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 2 && (be_isinstance(vm, 1) || be_ismodule(vm, 1) || be_isclass(vm, 1)) && be_isstring(vm, 2)) {
+ int ret = be_execprotected(vm, &m_findmember_protected, (void*) be_tostring(vm, 2));
+ if (ret == BE_OK) {
+ be_return(vm);
+ }
+ }
+ be_return_nil(vm);
+}
+
+static int m_setmember(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 3 && (be_isinstance(vm, 1) || be_ismodule(vm, 1)) && be_isstring(vm, 2)) {
+ be_setmember(vm, 1, be_tostring(vm, 2));
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int m_toptr(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 1) {
+ bvalue *v = be_indexof(vm, 1);
+ if (var_basetype(v) >= BE_FUNCTION || var_type(v) == BE_COMPTR) {
+ be_pushcomptr(vm, var_toobj(v));
+ be_return(vm);
+ } else if (var_type(v) == BE_INT) {
+ be_pushcomptr(vm, (void*) var_toint(v));
+ be_return(vm);
+ } else {
+ be_raise(vm, "value_error", "unsupported for this type");
+ }
+ }
+ be_return_nil(vm);
+}
+
+static int m_fromptr(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 1) {
+ void* v;
+ if (be_iscomptr(vm, 1)) {
+ v = be_tocomptr(vm, 1);
+ } else {
+ v = (void*) be_toint(vm, 1);
+ }
+ if (v) {
+ bgcobject * ptr = (bgcobject*) v;
+ if (var_basetype(ptr) >= BE_GCOBJECT) {
+ bvalue *top = be_incrtop(vm);
+ var_setobj(top, ptr->type, ptr);
+ } else {
+ be_raise(vm, "value_error", "unsupported for this type");
+ }
+ be_return(vm);
+ }
+ }
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(introspect) {
+ be_native_module_function("members", m_attrlist),
+
+ be_native_module_function("get", m_findmember),
+ be_native_module_function("set", m_setmember),
+
+ be_native_module_function("toptr", m_toptr),
+ be_native_module_function("fromptr", m_fromptr),
+};
+
+be_define_native_module(introspect, NULL);
+#else
+/* @const_object_info_begin
+module introspect (scope: global, depend: BE_USE_INTROSPECT_MODULE) {
+ members, func(m_attrlist)
+
+ get, func(m_findmember)
+ set, func(m_setmember)
+
+ toptr, func(m_toptr)
+ fromptr, func(m_fromptr)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_introspect.h"
+#endif
+
+#endif /* BE_USE_INTROSPECT_MODULE */
diff --git a/lib/libesp32/berry/src/be_jsonlib.c b/lib/libesp32/berry/src/be_jsonlib.c
new file mode 100644
index 000000000..1d7049ea1
--- /dev/null
+++ b/lib/libesp32/berry/src/be_jsonlib.c
@@ -0,0 +1,448 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_mem.h"
+#include
+
+#if BE_USE_JSON_MODULE
+
+#define MAX_INDENT 24
+#define INDENT_WIDTH 2
+#define INDENT_CHAR ' '
+
+static const char* parser_value(bvm *vm, const char *json);
+static void value_dump(bvm *vm, int *indent, int idx, int fmt);
+
+static const char* skip_space(const char *s)
+{
+ int c;
+ while (((c = *s) != '\0') && ((c == ' ')
+ || (c == '\t') || (c == '\r') || (c == '\n'))) {
+ ++s;
+ }
+ return s;
+}
+
+static int is_digit(int c)
+{
+ return c >= '0' && c <= '9';
+}
+
+static const char* match_char(const char *json, int ch)
+{
+ json = skip_space(json);
+ if (*json == ch) {
+ return skip_space(json + 1);
+ }
+ return NULL;
+}
+
+static int is_object(bvm *vm, const char *class, int idx)
+{
+ if (be_isinstance(vm, idx)) {
+ be_pushvalue(vm, idx);
+ while (1) {
+ be_getsuper(vm, -1);
+ if (be_isnil(vm, -1)) {
+ be_pop(vm, 1);
+ break;
+ }
+ be_remove(vm, -2);
+ }
+ const char *name = be_classname(vm, -1);
+ bbool ret = !strcmp(name, class);
+ be_pop(vm, 1);
+ return ret;
+ }
+ return 0;
+}
+
+static int json_strlen(const char *json)
+{
+ int ch;
+ const char *s = json + 1; /* skip '"' */
+ /* get string length "(\\.|[^"])*" */
+ while ((ch = *s) != '\0' && ch != '"') {
+ ++s;
+ if (ch == '\\') {
+ ch = *s++;
+ if (ch == '\0') {
+ return -1;
+ }
+ }
+ }
+ return ch ? cast_int(s - json - 1) : -1;
+}
+
+static void json2berry(bvm *vm, const char *class)
+{
+ be_getbuiltin(vm, class);
+ be_pushvalue(vm, -2);
+ be_call(vm, 1);
+ be_moveto(vm, -2, -3);
+ be_pop(vm, 2);
+}
+
+static const char* parser_true(bvm *vm, const char *json)
+{
+ if (!strncmp(json, "true", 4)) {
+ be_pushbool(vm, btrue);
+ return json + 4;
+ }
+ return NULL;
+}
+
+static const char* parser_false(bvm *vm, const char *json)
+{
+ if (!strncmp(json, "false", 5)) {
+ be_pushbool(vm, bfalse);
+ return json + 5;
+ }
+ return NULL;
+}
+
+static const char* parser_null(bvm *vm, const char *json)
+{
+ if (!strncmp(json, "null", 4)) {
+ be_pushnil(vm);
+ return json + 4;
+ }
+ return NULL;
+}
+
+static char* load_unicode(char *dst, const char *json)
+{
+ int ucode = 0, i = 4;
+ while (i--) {
+ int ch = *json++;
+ if (ch >= '0' && ch <= '9') {
+ ucode = (ucode << 4) | (ch - '0');
+ } else if (ch >= 'A' && ch <= 'F') {
+ ucode = (ucode << 4) | (ch - 'A' + 0x0A);
+ } else if (ch >= 'a' && ch <= 'f') {
+ ucode = (ucode << 4) | (ch - 'a' + 0x0A);
+ } else {
+ return NULL;
+ }
+ }
+ /* convert unicode to utf8 */
+ if (ucode < 0x007F) {
+ /* unicode: 0000 - 007F -> utf8: 0xxxxxxx */
+ *dst++ = (char)(ucode & 0x7F);
+ } else if (ucode < 0x7FF) {
+ /* unicode: 0080 - 07FF -> utf8: 110xxxxx 10xxxxxx */
+ *dst++ = (char)(((ucode >> 6) & 0x1F) | 0xC0);
+ *dst++ = (char)((ucode & 0x3F) | 0x80);
+ } else {
+ /* unicode: 0800 - FFFF -> utf8: 1110xxxx 10xxxxxx 10xxxxxx */
+ *dst++ = (char)(((ucode >> 12) & 0x0F) | 0xE0);
+ *dst++ = (char)(((ucode >> 6) & 0x03F) | 0x80);
+ *dst++ = (char)((ucode & 0x3F) | 0x80);
+ }
+ return dst;
+}
+
+static const char* parser_string(bvm *vm, const char *json)
+{
+ if (*json == '"') {
+ int len = json_strlen(json++);
+ if (len > -1) {
+ int ch;
+ char *buf, *dst = buf = be_malloc(vm, len);
+ while ((ch = *json) != '\0' && ch != '"') {
+ ++json;
+ if (ch == '\\') {
+ ch = *json++; /* skip '\' */
+ switch (ch) {
+ case '"': *dst++ = '"'; break;
+ case '\\': *dst++ = '\\'; break;
+ case '/': *dst++ = '/'; break;
+ case 'b': *dst++ = '\b'; break;
+ case 'f': *dst++ = '\f'; break;
+ case 'n': *dst++ = '\n'; break;
+ case 'r': *dst++ = '\r'; break;
+ case 't': *dst++ = '\t'; break;
+ case 'u': { /* load unicode */
+ dst = load_unicode(dst, json);
+ if (dst == NULL) {
+ be_free(vm, buf, len);
+ return NULL;
+ }
+ json += 4;
+ break;
+ }
+ default: be_free(vm, buf, len); return NULL; /* error */
+ }
+ } else {
+ *dst++ = (char)ch;
+ }
+ }
+ be_assert(ch == '"');
+ be_pushnstring(vm, buf, cast_int(dst - buf));
+ be_free(vm, buf, len);
+ return json + 1; /* skip '"' */
+ }
+ }
+ return NULL;
+}
+
+static const char* parser_field(bvm *vm, const char *json)
+{
+ if (json && *json == '"') {
+ json = parser_string(vm, json);
+ if (json) {
+ json = match_char(json, ':');
+ if (json) {
+ json = parser_value(vm, json);
+ if (json) {
+ be_data_insert(vm, -3);
+ be_pop(vm, 2); /* pop key and value */
+ return json;
+ }
+ }
+ be_pop(vm, 1); /* pop key */
+ }
+ }
+ return NULL;
+}
+
+static const char* parser_object(bvm *vm, const char *json)
+{
+ json = match_char(json, '{');
+ be_newmap(vm);
+ if (*json != '}') {
+ const char *s;
+ json = parser_field(vm, json);
+ if (json == NULL) {
+ be_pop(vm, 1); /* pop map */
+ return NULL;
+ }
+ while ((s = match_char(json, ',')) != NULL) {
+ json = parser_field(vm, s);
+ if (json == NULL) {
+ be_pop(vm, 1); /* pop map */
+ return NULL;
+ }
+ }
+ }
+ if ((json = match_char(json, '}')) == NULL) {
+ be_pop(vm, 1); /* pop map */
+ return NULL;
+ }
+ json2berry(vm, "map");
+ return json;
+}
+
+static const char* parser_array(bvm *vm, const char *json)
+{
+ json = match_char(json, '[');
+ be_newlist(vm);
+ if (*json != ']') {
+ const char *s;
+ json = parser_value(vm, json);
+ if (json == NULL) {
+ be_pop(vm, 1); /* pop map */
+ return NULL;
+ }
+ be_data_push(vm, -2);
+ be_pop(vm, 1); /* pop value */
+ while ((s = match_char(json, ',')) != NULL) {
+ json = parser_value(vm, s);
+ if (json == NULL) {
+ be_pop(vm, 1); /* pop map */
+ return NULL;
+ }
+ be_data_push(vm, -2);
+ be_pop(vm, 1); /* pop value */
+ }
+ }
+ if ((json = match_char(json, ']')) == NULL) {
+ be_pop(vm, 1); /* pop map */
+ return NULL;
+ }
+ json2berry(vm, "list");
+ return json;
+}
+
+/* parser json value */
+static const char* parser_value(bvm *vm, const char *json)
+{
+ json = skip_space(json);
+ switch (*json) {
+ case '{': /* object */
+ return parser_object(vm, json);
+ case '[': /* array */
+ return parser_array(vm, json);
+ case '"': /* string */
+ return parser_string(vm, json);
+ case 't': /* true */
+ return parser_true(vm, json);
+ case 'f': /* false */
+ return parser_false(vm, json);
+ case 'n': /* null */
+ return parser_null(vm, json);
+ default: /* number */
+ if (*json == '-' || is_digit(*json)) {
+ /* check invalid JSON syntax: 0\d+ */
+ if (json[0] == '0' && is_digit(json[1])) {
+ return NULL;
+ }
+ return be_str2num(vm, json);
+ }
+ }
+ return NULL;
+}
+
+static int m_json_load(bvm *vm)
+{
+ if (be_isstring(vm, 1)) {
+ const char *json = be_tostring(vm, 1);
+ json = parser_value(vm, json);
+ if (json != NULL && *json == '\0') {
+ be_return(vm);
+ }
+ }
+ be_return_nil(vm);
+}
+
+static void make_indent(bvm *vm, int stridx, int indent)
+{
+ if (indent) {
+ char buf[MAX_INDENT * INDENT_WIDTH + 1];
+ indent = (indent < MAX_INDENT ? indent : MAX_INDENT) * INDENT_WIDTH;
+ memset(buf, INDENT_CHAR, indent);
+ buf[indent] = '\0';
+ stridx = be_absindex(vm, stridx);
+ be_pushstring(vm, buf);
+ be_strconcat(vm, stridx);
+ be_pop(vm, 1);
+ }
+}
+
+void string_dump(bvm *vm, int index)
+{
+ be_tostring(vm, index); /* convert value to string */
+ be_toescape(vm, index, 'u');
+ be_pushvalue(vm, index);
+}
+
+static void object_dump(bvm *vm, int *indent, int idx, int fmt)
+{
+ be_getmember(vm, idx, ".p");
+ be_pushstring(vm, fmt ? "{\n" : "{");
+ be_pushiter(vm, -2); /* map iterator use 1 register */
+ *indent += fmt;
+ while (be_iter_hasnext(vm, -3)) {
+ make_indent(vm, -2, fmt ? *indent : 0);
+ be_iter_next(vm, -3);
+ /* key.tostring() */
+ string_dump(vm, -2);
+ be_strconcat(vm, -5);
+ be_pop(vm, 1);
+ be_pushstring(vm, fmt ? ": " : ":"); /* add ': ' */
+ be_strconcat(vm, -5);
+ be_pop(vm, 1);
+ /* value.tostring() */
+ value_dump(vm, indent, -1, fmt);
+ be_strconcat(vm, -5);
+ be_pop(vm, 3);
+ if (be_iter_hasnext(vm, -3)) {
+ be_pushstring(vm, fmt ? ",\n" : ",");
+ be_strconcat(vm, -3);
+ be_pop(vm, 1);
+ } else if (fmt) {
+ be_pushstring(vm, "\n");
+ be_strconcat(vm, -3);
+ be_pop(vm, 1);
+ }
+ }
+ *indent -= fmt;
+ be_pop(vm, 1); /* pop iterator */
+ make_indent(vm, -1, fmt ? *indent : 0);
+ be_pushstring(vm, "}");
+ be_strconcat(vm, -2);
+ be_moveto(vm, -2, -3);
+ be_pop(vm, 2);
+}
+
+static void array_dump(bvm *vm, int *indent, int idx, int fmt)
+{
+ be_getmember(vm, idx, ".p");
+ be_pushstring(vm, fmt ? "[\n" : "[");
+ be_pushiter(vm, -2);
+ *indent += fmt;
+ while (be_iter_hasnext(vm, -3)) {
+ make_indent(vm, -2, fmt ? *indent : 0);
+ be_iter_next(vm, -3);
+ value_dump(vm, indent, -1, fmt);
+ be_strconcat(vm, -4);
+ be_pop(vm, 2);
+ if (be_iter_hasnext(vm, -3)) {
+ be_pushstring(vm, fmt ? ",\n" : ",");
+ be_strconcat(vm, -3);
+ be_pop(vm, 1);
+ } else if (fmt) {
+ be_pushstring(vm, "\n");
+ be_strconcat(vm, -3);
+ be_pop(vm, 1);
+ }
+ }
+ *indent -= fmt;
+ be_pop(vm, 1); /* pop iterator */
+ make_indent(vm, -1, fmt ? *indent : 0);
+ be_pushstring(vm, "]");
+ be_strconcat(vm, -2);
+ be_moveto(vm, -2, -3);
+ be_pop(vm, 2);
+}
+
+static void value_dump(bvm *vm, int *indent, int idx, int fmt)
+{
+ if (is_object(vm, "map", idx)) { /* convert to json object */
+ object_dump(vm, indent, idx, fmt);
+ } else if (is_object(vm, "list", idx)) { /* convert to json array */
+ array_dump(vm, indent, idx, fmt);
+ } else if (be_isnil(vm, idx)) { /* convert to json null */
+ be_pushstring(vm, "null");
+ } else if (be_isnumber(vm, idx) || be_isbool(vm, idx)) { /* convert to json number and boolean */
+ be_tostring(vm, idx);
+ be_pushvalue(vm, idx); /* push to top */
+ } else { /* convert to string */
+ string_dump(vm, idx);
+ }
+}
+
+static int m_json_dump(bvm *vm)
+{
+ int indent = 0, argc = be_top(vm);
+ int fmt = 0;
+ if (argc > 1) {
+ fmt = !strcmp(be_tostring(vm, 2), "format");
+ }
+ value_dump(vm, &indent, 1, fmt);
+ be_return(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(json) {
+ be_native_module_function("load", m_json_load),
+ be_native_module_function("dump", m_json_dump)
+};
+
+be_define_native_module(json, NULL);
+#else
+/* @const_object_info_begin
+module json (scope: global, depend: BE_USE_JSON_MODULE) {
+ load, func(m_json_load)
+ dump, func(m_json_dump)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_json.h"
+#endif
+
+#endif /* BE_USE_JSON_MODULE */
diff --git a/lib/libesp32/berry/src/be_lexer.c b/lib/libesp32/berry/src/be_lexer.c
new file mode 100644
index 000000000..c4c736508
--- /dev/null
+++ b/lib/libesp32/berry/src/be_lexer.c
@@ -0,0 +1,621 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_lexer.h"
+#include "be_string.h"
+#include "be_mem.h"
+#include "be_gc.h"
+#include "be_exec.h"
+#include "be_map.h"
+#include "be_vm.h"
+
+#define SHORT_STR_LEN 32
+#define EOS '\0' /* end of source */
+
+#define type_count() (int)array_count(kwords_tab)
+#define lexbuf(lex) ((lex)->buf.s)
+#define isvalid(lex) ((lex)->cursor < (lex)->endbuf)
+#define lgetc(lex) ((lex)->cursor)
+#define setstr(lex, v) ((lex)->token.u.s = (v))
+#define setint(lex, v) ((lex)->token.u.i = (v))
+#define setreal(lex, v) ((lex)->token.u.r = (v))
+#define match(lex, pattern) while (pattern(lgetc(lex))) { save(lex); }
+
+#if BE_USE_SCRIPT_COMPILER
+
+/* IMPORTANT: This must follow the enum found in be_lexer.h !!! */
+static const char* const kwords_tab[] = {
+ "NONE", "EOS", "ID", "INT", "REAL", "STR",
+ "=", "+=","-=", "*=", "/=", "%=", "&=", "|=",
+ "^=", "<<=", ">>=", "+", "-", "*", "/", "%",
+ "<", "<=", "==", "!=", ">", ">=", "&", "|",
+ "^", "<<", ">>", "..", "&&", "||", "!", "~",
+ "(", ")", "[", "]", "{", "}", ".", ",", ";",
+ ":", "?", "->", "if", "elif", "else", "while",
+ "for", "def", "end", "class", "break", "continue",
+ "return", "true", "false", "nil", "var", "do",
+ "import", "as", "try", "except", "raise", "static"
+};
+
+void be_lexerror(blexer *lexer, const char *msg)
+{
+ bvm *vm = lexer->vm;
+ const char *error = be_pushfstring(vm,
+ "%s:%d: %s", lexer->fname, lexer->linenumber, msg);
+ be_lexer_deinit(lexer);
+ be_raise(vm, "syntax_error", error);
+}
+
+static void keyword_registe(bvm *vm)
+{
+ int i;
+ for (i = KeyIf; i < type_count(); ++i) {
+ bstring *s = be_newstr(vm, kwords_tab[i]);
+ be_gc_fix(vm, gc_object(s));
+ be_str_setextra(s, i);
+ }
+}
+
+static void keyword_unregiste(bvm *vm)
+{
+ int i;
+ for (i = KeyIf; i < type_count(); ++i) {
+ bstring *s = be_newstr(vm, kwords_tab[i]);
+ be_gc_unfix(vm, gc_object(s));
+ }
+}
+
+static bstring* cache_string(blexer *lexer, bstring *s)
+{
+ bvalue *res;
+ bvm *vm = lexer->vm;
+ var_setstr(vm->top, s);
+ be_stackpush(vm); /* cache string to stack */
+ res = be_map_findstr(lexer->vm, lexer->strtab, s);
+ if (res) {
+ s = var_tostr(&be_map_val2node(res)->key);
+ } else {
+ res = be_map_insertstr(vm, lexer->strtab, s, NULL);
+ var_setnil(res);
+ }
+ be_stackpop(vm, 1); /* pop string frome stack */
+ return s;
+}
+
+static bstring* lexer_newstrn(blexer *lexer, const char *str, size_t len)
+{
+ return cache_string(lexer, be_newstrn(lexer->vm, str, len));
+}
+
+bstring* be_lexer_newstr(blexer *lexer, const char *str)
+{
+ return cache_string(lexer, be_newstr(lexer->vm, str));
+}
+
+static int next(blexer *lexer)
+{
+ struct blexerreader *lr = &lexer->reader;
+ if (!(lr->len--)) {
+ static const char eos = EOS;
+ const char *s = lr->readf(lr->data, &lr->len);
+ lr->s = s ? s : &eos;
+ --lr->len;
+ }
+ lexer->cursor = *lr->s++;
+ return lexer->cursor;
+}
+
+static void clear_buf(blexer *lexer)
+{
+ lexer->buf.len = 0;
+}
+
+/* save and next */
+static int save(blexer *lexer)
+{
+ int ch = lgetc(lexer);
+ struct blexerbuf *buf = &lexer->buf;
+ if (buf->len >= buf->size) {
+ size_t size = buf->size << 1;
+ buf->s = be_realloc(lexer->vm, buf->s, buf->size, size);
+ buf->size = size;
+ }
+ buf->s[buf->len++] = (char)ch;
+ return next(lexer);
+}
+
+static bstring* buf_tostr(blexer *lexer)
+{
+ struct blexerbuf *buf = &lexer->buf;
+ return lexer_newstrn(lexer, buf->s, buf->len);
+}
+
+static int is_newline(int c)
+{
+ return c == '\n' || c == '\r';
+}
+
+static int is_digit(int c)
+{
+ return c >= '0' && c <= '9';
+}
+
+static int is_octal(int c)
+{
+ return c >= '0' && c <= '7';
+}
+
+static int is_letter(int c)
+{
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
+}
+
+static int is_word(int c)
+{
+ return is_letter(c) || is_digit(c);
+}
+
+static int check_next(blexer *lexer, int c)
+{
+ if (lgetc(lexer) == c) {
+ next(lexer);
+ return 1;
+ }
+ return 0;
+}
+
+static int char2hex(int c)
+{
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ return c - 'a' + 0x0A;
+ } else if (c >= 'A' && c <= 'F') {
+ return c - 'A' + 0x0A;
+ }
+ return -1;
+}
+
+static int check2hex(blexer *lexer, int c)
+{
+ c = char2hex(c);
+ if (c < 0) {
+ be_lexerror(lexer, "invalid hexadecimal number");
+ }
+ return c;
+}
+
+static int read_hex(blexer *lexer, const char *src)
+{
+ int c = check2hex(lexer, *src++);
+ return ((unsigned)c << 4) + check2hex(lexer, *src);
+}
+
+static int read_oct(blexer *lexer, const char *src)
+{
+ int c = 0;
+ const char *end = src + 3;
+ while (src < end && is_octal(*src)) {
+ c = 8 * c + *src++ - '0';
+ }
+ if (src < end) {
+ be_lexerror(lexer, "invalid octal number");
+ }
+ return c;
+}
+
+static void tr_string(blexer *lexer)
+{
+ char *dst, *src, *end;
+ dst = src = lexbuf(lexer);
+ end = lexbuf(lexer) + lexer->buf.len;
+ while (src < end) {
+ int c = *src++;
+ switch (c) {
+ case '\n': case '\r':
+ be_lexerror(lexer, "unfinished string");
+ break;
+ case '\\':
+ switch (*src) {
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\\': c = '\\'; break;
+ case '\'': c = '\''; break;
+ case '"': c = '"'; break;
+ case '?': c = '?'; break;
+ case 'x': c = read_hex(lexer, ++src); ++src; break;
+ default:
+ c = read_oct(lexer, src);
+ if (c != EOS) {
+ src += 2;
+ }
+ break;
+ }
+ ++src;
+ break;
+ default:
+ break;
+ }
+ *dst++ = (char)c;
+ }
+ lexer->buf.len = dst - lexbuf(lexer);
+}
+
+static int skip_newline(blexer *lexer)
+{
+ int lc = lgetc(lexer);
+ next(lexer);
+ if (is_newline(lgetc(lexer)) && lgetc(lexer) != lc) {
+ next(lexer); /* skip "\n\r" or "\r\n" */
+ }
+ lexer->linenumber++;
+ return lexer->cursor;
+}
+
+static void skip_comment(blexer *lexer)
+{
+ next(lexer); /* skip '#' */
+ if (lgetc(lexer) == '-') { /* mult-line comment */
+ int mark, c = 'x'; /* skip first '-' (#- ... -#) */
+ do {
+ mark = c == '-';
+ if (is_newline(c)) {
+ c = skip_newline(lexer);
+ continue;
+ }
+ c = next(lexer);
+ } while (!(mark && c == '#') && c != EOS);
+ next(lexer); /* skip '#' */
+ } else { /* line comment */
+ while (!is_newline(lgetc(lexer)) && lgetc(lexer)) {
+ next(lexer);
+ }
+ }
+}
+
+static bbool scan_realexp(blexer *lexer)
+{
+ int c = lgetc(lexer);
+ if (c == 'e' || c == 'E') {
+ c = save(lexer);
+ if (c == '+' || c == '-') {
+ c = save(lexer);
+ }
+ if (!is_digit(c)) {
+ be_lexerror(lexer, "malformed number");
+ }
+ match(lexer, is_digit);
+ return btrue;
+ }
+ return bfalse;
+}
+
+static btokentype scan_dot_real(blexer *lexer)
+{
+ if (save(lexer) == '.') { /* is '..' */
+ next(lexer);
+ return OptConnect;
+ }
+ if (is_digit(lgetc(lexer))) {
+ match(lexer, is_digit);
+ scan_realexp(lexer);
+ setreal(lexer, be_str2real(lexbuf(lexer), NULL));
+ return TokenReal;
+ }
+ return OptDot;
+}
+
+/* check the dots is a decimal dot or '..' operator */
+static bbool decimal_dots(blexer *lexer)
+{
+ if (lgetc(lexer) == '.') { /* '..' or real */
+ if (save(lexer) != '.') { /* read numberic => \.\b* */
+ match(lexer, is_digit); /* match and skip numberic */
+ return btrue;
+ }
+ /* token '..' */
+ next(lexer); /* skip the second '.' */
+ lexer->cacheType = OptConnect;
+ }
+ return bfalse; /* operator '..' */
+}
+
+static bint scan_hexadecimal(blexer *lexer)
+{
+ bint res = 0;
+ int dig, num = 0;
+ while ((dig = char2hex(lgetc(lexer))) >= 0) {
+ res = ((bint)res << 4) + dig;
+ next(lexer);
+ ++num;
+ }
+ if (num == 0) {
+ be_lexerror(lexer, "invalid hexadecimal number");
+ }
+ return res;
+}
+
+static btokentype scan_decimal(blexer *lexer)
+{
+ btokentype type = TokenInteger;
+ match(lexer, is_digit);
+ if (decimal_dots(lexer) | scan_realexp(lexer)) {
+ type = TokenReal;
+ }
+ lexer->buf.s[lexer->buf.len] = '\0';
+ if (type == TokenReal) {
+ setreal(lexer, be_str2real(lexbuf(lexer), NULL));
+ } else {
+ setint(lexer, be_str2int(lexbuf(lexer), NULL));
+ }
+ return type;
+}
+
+static btokentype scan_numeral(blexer *lexer)
+{
+ btokentype type = TokenInteger;
+ int c0 = lgetc(lexer), c1 = save(lexer);
+ /* hex: 0[xX][0-9a-fA-F]+ */
+ if (c0 == '0' && (c1 == 'x' || c1 == 'X')) {
+ next(lexer);
+ setint(lexer, scan_hexadecimal(lexer));
+ } else {
+ type = scan_decimal(lexer);
+ }
+ /* can't follow decimal or letter after numeral */
+ if (lexer->cacheType == TokenNone) {
+ if (is_letter(lgetc(lexer)) || decimal_dots(lexer)) {
+ be_lexerror(lexer, "malformed number");
+ }
+ }
+ return type;
+}
+
+static btokentype scan_identifier(blexer *lexer)
+{
+ int type;
+ bstring *s;
+ save(lexer);
+ match(lexer, is_word);
+ s = buf_tostr(lexer);
+ type = str_extra(s);
+ if (type >= KeyIf && type < type_count()) {
+ lexer->token.type = (btokentype)type;
+ return lexer->token.type;
+ }
+ setstr(lexer, s); /* set identifier name */
+ return TokenId;
+}
+
+static btokentype scan_string(blexer *lexer)
+{
+ int c, end = lgetc(lexer);
+ next(lexer); /* skip '"' or '\'' */
+ while ((c = lgetc(lexer)) != EOS && (c != end)) {
+ save(lexer);
+ if (c == '\\') {
+ save(lexer); /* skip '\\.' */
+ }
+ }
+ tr_string(lexer);
+ setstr(lexer, buf_tostr(lexer));
+ next(lexer); /* skip '"' or '\'' */
+ return TokenString;
+}
+
+static btokentype scan_assign(blexer *lexer, btokentype is, btokentype not)
+{
+ next(lexer);
+ return check_next(lexer, '=') ? is : not;
+}
+
+static btokentype scan_sub(blexer *lexer)
+{
+ btokentype op;
+ switch (next(lexer)) {
+ case '>': op = OptArrow; break;
+ case '=': op = OptSubAssign; break;
+ default: return OptSub;
+ }
+ next(lexer);
+ return op;
+}
+
+static btokentype scan_and(blexer *lexer)
+{
+ btokentype op;
+ switch (next(lexer)) {
+ case '&': op = OptAnd; break;
+ case '=': op = OptAndAssign; break;
+ default: return OptBitAnd;
+ }
+ next(lexer);
+ return op;
+}
+
+static btokentype scan_or(blexer *lexer)
+{
+ btokentype op;
+ switch (next(lexer)) {
+ case '|': op = OptOr; break;
+ case '=': op = OptOrAssign; break;
+ default: return OptBitOr;
+ }
+ next(lexer);
+ return op;
+}
+
+static btokentype scan_le(blexer *lexer)
+{
+ switch (next(lexer)) {
+ case '=':
+ next(lexer);
+ return OptLE;
+ case '<':
+ next(lexer);
+ return check_next(lexer, '=') ? OptLsfAssign : OptShiftL;
+ default:
+ return OptLT;
+ }
+}
+
+static btokentype scan_ge(blexer *lexer)
+{
+ switch (next(lexer)) {
+ case '=':
+ next(lexer);
+ return OptGE;
+ case '>':
+ next(lexer);
+ return check_next(lexer, '=') ? OptRsfAssign : OptShiftR;
+ default:
+ return OptGT;
+ }
+}
+
+static btokentype lexer_next(blexer *lexer)
+{
+ for (;;) {
+ switch (lgetc(lexer)) {
+ case '\r': case '\n': /* newline */
+ skip_newline(lexer);
+ break;
+ case ' ': case '\t': case '\f': case '\v': /* spaces */
+ next(lexer);
+ break;
+ case '#': /* comment */
+ skip_comment(lexer);
+ break;
+ case EOS: return TokenEOS; /* end of source stream */
+ /* operator */
+ case '+': return scan_assign(lexer, OptAddAssign, OptAdd);
+ case '-': return scan_sub(lexer);
+ case '*': return scan_assign(lexer, OptMulAssign, OptMul);
+ case '/': return scan_assign(lexer, OptDivAssign, OptDiv);
+ case '%': return scan_assign(lexer, OptModAssign, OptMod);
+ case '(': next(lexer); return OptLBK;
+ case ')': next(lexer); return OptRBK;
+ case '[': next(lexer); return OptLSB;
+ case ']': next(lexer); return OptRSB;
+ case '{': next(lexer); return OptLBR;
+ case '}': next(lexer); return OptRBR;
+ case ',': next(lexer); return OptComma;
+ case ';': next(lexer); return OptSemic;
+ case ':': next(lexer); return OptColon;
+ case '?': next(lexer); return OptQuestion;
+ case '^': return scan_assign(lexer, OptXorAssign, OptBitXor);
+ case '~': next(lexer); return OptFlip;
+ case '&': return scan_and(lexer);
+ case '|': return scan_or(lexer);
+ case '<': return scan_le(lexer);
+ case '>': return scan_ge(lexer);
+ case '=':
+ next(lexer);
+ return check_next(lexer, '=') ? OptEQ : OptAssign;
+ case '!':
+ next(lexer);
+ return check_next(lexer, '=') ? OptNE : OptNot;
+ case '\'': case '"':
+ return scan_string(lexer);
+ case '.':
+ return scan_dot_real(lexer);
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return scan_numeral(lexer);
+ default:
+ if (is_letter(lgetc(lexer))) {
+ return scan_identifier(lexer);
+ }
+ be_lexerror(lexer, be_pushfstring(lexer->vm,
+ "stray '\\%d' in program", (unsigned char)lgetc(lexer)));
+ return TokenNone; /* error */
+ }
+ }
+}
+
+static void lexerbuf_init(blexer *lexer)
+{
+ lexer->buf.size = SHORT_STR_LEN;
+ lexer->buf.s = be_malloc(lexer->vm, SHORT_STR_LEN);
+ lexer->buf.len = 0;
+}
+
+void be_lexer_init(blexer *lexer, bvm *vm,
+ const char *fname, breader reader, void *data)
+{
+ lexer->vm = vm;
+ lexer->cacheType = TokenNone;
+ lexer->fname = fname;
+ lexer->linenumber = 1;
+ lexer->lastline = 1;
+ lexer->reader.readf = reader;
+ lexer->reader.data = data;
+ lexer->reader.len = 0;
+ lexerbuf_init(lexer);
+ keyword_registe(vm);
+ lexer->strtab = be_map_new(vm);
+ var_setmap(vm->top, lexer->strtab);
+ be_stackpush(vm); /* save string to cache */
+ next(lexer); /* read the first character */
+}
+
+void be_lexer_deinit(blexer *lexer)
+{
+ be_free(lexer->vm, lexer->buf.s, lexer->buf.size);
+ keyword_unregiste(lexer->vm);
+}
+
+int be_lexer_scan_next(blexer *lexer)
+{
+ btokentype type;
+ if (lexer->cacheType != TokenNone) {
+ lexer->token.type = lexer->cacheType;
+ lexer->cacheType = TokenNone;
+ return 1;
+ }
+ if (lgetc(lexer) == EOS) { /* clear lexer */
+ lexer->token.type = TokenEOS;
+ return 0;
+ }
+ lexer->lastline = lexer->linenumber;
+ type = lexer_next(lexer);
+ clear_buf(lexer);
+ if (type != TokenNone) {
+ lexer->token.type = type;
+ } else {
+ lexer->token.type = TokenEOS;
+ return 0;
+ }
+ return 1;
+}
+
+const char* be_token2str(bvm *vm, btoken *token)
+{
+ switch (token->type) {
+ case TokenString:
+ case TokenId:
+ return str(token->u.s);
+ case TokenInteger:
+ return be_pushfstring(vm, "%d", token->u.i);
+ case TokenReal:
+ return be_pushfstring(vm, "%g", token->u.r);
+ default:
+ return kwords_tab[token->type];
+ }
+}
+
+const char* be_tokentype2str(btokentype type)
+{
+ return kwords_tab[type];
+}
+
+#endif
diff --git a/lib/libesp32/berry/src/be_lexer.h b/lib/libesp32/berry/src/be_lexer.h
new file mode 100644
index 000000000..467070946
--- /dev/null
+++ b/lib/libesp32/berry/src/be_lexer.h
@@ -0,0 +1,138 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_LEXER_H
+#define BE_LEXER_H
+
+#include "be_object.h"
+
+typedef enum {
+ TokenNone = 0,
+ TokenEOS, /* end of source */
+ TokenId, /* identifier */
+ TokenInteger,
+ TokenReal,
+ TokenString,
+ /* operator, don't change order */
+ /* assign operator */
+ OptAssign, /* operator, = */
+ OptAddAssign, /* operator, += */
+ OptSubAssign, /* operator, -= */
+ OptMulAssign, /* operator, *= */
+ OptDivAssign, /* operator, /= */
+ OptModAssign, /* operator, %= */
+ OptAndAssign, /* operator, &= */
+ OptOrAssign, /* operator, |= */
+ OptXorAssign, /* operator, ^= */
+ OptLsfAssign, /* operator, <<= */
+ OptRsfAssign, /* operator, >>= */
+ /* binary operator */
+ OptAdd, /* operator, + */
+ OptSub, /* operator, - */
+ OptMul, /* operator, * */
+ OptDiv, /* operator, / */
+ OptMod, /* operator, % */
+ OptLT, /* operator, < */
+ OptLE, /* operator, <= */
+ OptEQ, /* operator, == */
+ OptNE, /* operator, != */
+ OptGT, /* operator, > */
+ OptGE, /* operator, >= */
+ OptBitAnd, /* operatoe, & */
+ OptBitOr, /* operatoe, | */
+ OptBitXor, /* operatoe, ^ */
+ OptShiftL, /* operatoe, << */
+ OptShiftR, /* operatoe, >> */
+ OptConnect, /* operator, .. */
+ OptAnd, /* operator, && */
+ OptOr, /* operator, || */
+ /* unary operator */
+ OptNot, /* operator, ! */
+ OptFlip, /* operator, ~ */
+ /* postfix operator or bracket */
+ OptLBK, /* operator, ( bracket */
+ OptRBK, /* operator, ) bracket */
+ OptLSB, /* operator, [ square bracket */
+ OptRSB, /* operator, ] square bracket */
+ OptLBR, /* operator, { brace */
+ OptRBR, /* operator, } brace */
+ OptDot, /* operator, . dot */
+ /* other symbol */
+ OptComma, /* operator, , */
+ OptSemic, /* operator, ; */
+ OptColon, /* operator, : */
+ OptQuestion, /* operator, ? */
+ OptArrow, /* operator, -> */
+ /* keyword */
+ KeyIf, /* keyword if */
+ KeyElif, /* keyword elif */
+ KeyElse, /* keyword else */
+ KeyWhile, /* keyword while */
+ KeyFor, /* keyword for */
+ KeyDef, /* keyword def */
+ KeyEnd, /* keyword end */
+ KeyClass, /* keyword class */
+ KeyBreak, /* keyword break */
+ KeyContinue, /* keyword continue */
+ KeyReturn, /* keyword return */
+ KeyTrue, /* keyword true */
+ KeyFalse, /* keyword false */
+ KeyNil, /* keyword nil */
+ KeyVar, /* keyword var */
+ KeyDo, /* keyword do */
+ KeyImport, /* keyword import */
+ KeyAs, /* keyword as */
+ KeyTry, /* keyword try */
+ KeyExcept, /* keyword except */
+ KeyRaise, /* keyword raise */
+ KeyStatic /* keyword static */
+} btokentype;
+
+struct blexerreader {
+ const char *s;
+ size_t len;
+ void *data;
+ breader readf;
+};
+
+struct blexerbuf {
+ char *s;
+ size_t len, size;
+};
+
+typedef struct btoken {
+ btokentype type;
+ union {
+ bstring *s;
+ bint i;
+ breal r;
+ } u;
+} btoken;
+
+typedef struct blexer {
+ const char *fname;
+ btoken token;
+ int linenumber;
+ int lastline;
+ btokentype cacheType;
+ struct blexerbuf buf;
+ struct blexerreader reader;
+ bmap *strtab;
+ bvm *vm;
+ int cursor;
+} blexer;
+
+void be_lexer_init(blexer *lexer, bvm *vm,
+ const char *fname, breader reader, void *data);
+void be_lexer_deinit(blexer *lexer);
+void be_lexerror(blexer *lexer, const char *msg);
+int be_lexer_scan_next(blexer *lexer);
+bstring* be_lexer_newstr(blexer *lexer, const char *str);
+const char *be_token2str(bvm *vm, btoken *token);
+const char* be_tokentype2str(btokentype type);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_libs.c b/lib/libesp32/berry/src/be_libs.c
new file mode 100644
index 000000000..a9a2f0e39
--- /dev/null
+++ b/lib/libesp32/berry/src/be_libs.c
@@ -0,0 +1,29 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_libs.h"
+
+extern void be_load_baselib(bvm *vm);
+extern void be_load_baselib_next(bvm *vm);
+extern void be_load_listlib(bvm *vm);
+extern void be_load_maplib(bvm *vm);
+extern void be_load_rangelib(bvm *vm);
+extern void be_load_filelib(bvm *vm);
+extern void be_load_byteslib(bvm *vm);
+
+void be_loadlibs(bvm *vm)
+{
+ be_load_baselib(vm);
+#if !BE_USE_PRECOMPILED_OBJECT
+ be_load_listlib(vm);
+ be_load_maplib(vm);
+ be_load_rangelib(vm);
+ be_load_filelib(vm);
+ be_load_byteslib(vm);
+ be_load_baselib_next(vm);
+#endif
+}
diff --git a/lib/libesp32/berry/src/be_libs.h b/lib/libesp32/berry/src/be_libs.h
new file mode 100644
index 000000000..a8014790b
--- /dev/null
+++ b/lib/libesp32/berry/src/be_libs.h
@@ -0,0 +1,15 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_LIBS_H
+#define BE_LIBS_H
+
+#include "berry.h"
+
+void be_loadlibs(bvm *vm);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_list.c b/lib/libesp32/berry/src/be_list.c
new file mode 100644
index 000000000..7d696d736
--- /dev/null
+++ b/lib/libesp32/berry/src/be_list.c
@@ -0,0 +1,207 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_list.h"
+#include "be_mem.h"
+#include "be_gc.h"
+#include "be_vm.h"
+#include "be_vector.h"
+#include "be_exec.h"
+#include
+
+#define datasize(size) ((size) * sizeof(bvalue))
+
+blist* be_list_new(bvm *vm)
+{
+ bgcobject *gco = be_gcnew(vm, BE_LIST, blist);
+ blist *list = cast_list(gco);
+ if (list) {
+ list->count = 0;
+ list->capacity = 2;
+ var_setlist(vm->top, list);
+ be_incrtop(vm);
+ list->data = be_malloc(vm, datasize(list->capacity));
+ be_stackpop(vm, 1);
+ }
+ return list;
+}
+
+void be_list_delete(bvm *vm, blist *list)
+{
+ be_free(vm, list->data, datasize(list->capacity));
+ be_free(vm, list, sizeof(blist));
+}
+
+blist* be_list_copy(bvm *vm, blist *original)
+{
+ bgcobject *gco = be_gcnew(vm, BE_LIST, blist);
+ blist *list = cast_list(gco);
+ if (list) {
+ size_t size = datasize(original->capacity);
+ list->count = original->count;
+ list->capacity = original->capacity;
+ var_setlist(vm->top, list);
+ be_incrtop(vm);
+ list->data = be_malloc(vm, size);
+ be_stackpop(vm, 1);
+ memcpy(list->data, original->data, size);
+ }
+ return list;
+}
+
+bvalue* be_list_index(blist *list, int index)
+{
+ if (index < 0) {
+ index = list->count + index;
+ }
+ if (index < 0 || index >= list->count) {
+ return NULL;
+ }
+ return be_list_at(list, index);
+}
+
+bvalue* be_list_push(bvm *vm, blist *list, bvalue *value)
+{
+ bvalue *slot;
+ if (list->count >= list->capacity) {
+ int newcap = be_nextsize(list->capacity);
+ list->data = be_realloc(vm, list->data,
+ datasize(list->capacity), datasize(newcap));
+ list->capacity = newcap;
+ }
+ slot = list->data + list->count++;
+ if (value != NULL) {
+ *slot = *value;
+ }
+ return slot;
+}
+
+bvalue* be_list_insert(bvm *vm, blist *list, int index, bvalue *value)
+{
+ int i;
+ bvalue *data;
+ if (index < 0) {
+ index = list->count + index;
+ }
+ if (index < 0 || index > list->count) {
+ return NULL;
+ }
+ if (list->count >= list->capacity) {
+ int newcap = be_nextsize(list->capacity);
+ list->data = be_realloc(vm, list->data,
+ datasize(list->capacity), datasize(newcap));
+ list->capacity = newcap;
+ }
+ data = list->data;
+ for (i = list->count++; i > index; --i) {
+ data[i] = data[i - 1];
+ }
+ data = list->data + index;
+ if (value != NULL) {
+ *data = *value;
+ }
+ return data;
+}
+
+int be_list_remove(bvm *vm, blist *list, int index)
+{
+ int i;
+ bvalue *data;
+ (void)vm;
+ if (index < 0) {
+ index = list->count + index;
+ }
+ if (index < 0 || index >= list->count) {
+ return bfalse;
+ }
+ data = list->data;
+ list->count--;
+ for (i = index; i < list->count; ++i) {
+ data[i] = data[i + 1];
+ }
+ return btrue;
+}
+
+void be_list_resize(bvm *vm, blist *list, int count)
+{
+ if (count != list->count) {
+ int newcap = be_nextsize(count);
+ if (newcap > list->capacity) {
+ bvalue *v, *end;
+ list->data = be_realloc(vm, list->data,
+ datasize(list->capacity), datasize(newcap));
+ list->capacity = newcap;
+ v = list->data + list->count;
+ end = list->data + count;
+ while (v < end) {
+ var_setnil(v++);
+ }
+ }
+ list->count = count;
+ }
+}
+
+void be_list_merge(bvm *vm, blist *list, const blist *other)
+{
+ int dst_len = list->count;
+ int src_len = other->count;
+ int length = src_len + dst_len;
+ if (length != 0) {
+ int newcap = be_nextsize(length);
+ if (newcap > list->capacity) {
+ list->data = be_realloc(vm, list->data,
+ datasize(list->capacity), datasize(newcap));
+ list->capacity = newcap;
+ }
+ memcpy(list->data + dst_len, other->data, src_len * sizeof(bvalue));
+ list->count = length;
+ }
+}
+
+void be_list_reverse(blist *list)
+{
+ bvalue *left = list->data;
+ bvalue *right = left + list->count - 1;
+ for (; left < right; ++left, --right) {
+ bvalue temp = *left;
+ *left = *right;
+ *right = temp;
+ }
+}
+
+void be_list_pool_init(bvm *vm, blist *list)
+{
+ bvalue *head;
+ be_list_resize(vm, list, 0);
+ head = be_list_push(vm, list, NULL);
+ var_setint(head, 0);
+}
+
+int be_list_pool_alloc(bvm *vm, blist *list, bvalue *src)
+{
+ bvalue *head = be_list_data(list), *node;
+ int id = var_toidx(head); /* get the first free node */
+ if (id) {
+ node = head + id;
+ head->v.i = var_toint(node); /* link the next free node to head */
+ } else {
+ id = be_list_count(list);
+ node = be_list_push(vm, list, NULL);
+ }
+ *node = *src;
+ return id;
+}
+
+void be_list_pool_free(blist *list, int id)
+{
+ bvalue *head = be_list_data(list);
+ bvalue *node = head + id;
+ be_assert(id > 0 && id < list->count);
+ /* insert a new free node to head */
+ *node = *head;
+ head->v.i = id;
+}
diff --git a/lib/libesp32/berry/src/be_list.h b/lib/libesp32/berry/src/be_list.h
new file mode 100644
index 000000000..9f5745725
--- /dev/null
+++ b/lib/libesp32/berry/src/be_list.h
@@ -0,0 +1,39 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_LIST_H
+#define BE_LIST_H
+
+#include "be_object.h"
+
+struct blist {
+ bcommon_header;
+ bgcobject *gray; /* for gc gray list */
+ int count, capacity;
+ bvalue *data;
+};
+
+#define be_list_data(list) ((list)->data)
+#define be_list_count(list) ((list)->count)
+#define be_list_at(list, index) ((list)->data + index)
+#define be_list_end(list) ((list)->data + (list)->count)
+
+blist* be_list_new(bvm *vm);
+void be_list_delete(bvm *vm, blist *list);
+blist* be_list_copy(bvm *vm, blist *original);
+bvalue* be_list_index(blist *list, int index);
+bvalue* be_list_push(bvm *vm, blist *list, bvalue *value);
+bvalue* be_list_insert(bvm *vm, blist *list, int index, bvalue *value);
+int be_list_remove(bvm *vm, blist *list, int index);
+void be_list_resize(bvm *vm, blist *list, int count);
+void be_list_merge(bvm *vm, blist *list, const blist *other);
+void be_list_reverse(blist *list);
+void be_list_pool_init(bvm *vm, blist *list);
+int be_list_pool_alloc(bvm *vm, blist *list, bvalue *src);
+void be_list_pool_free(blist *list, int id);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_listlib.c b/lib/libesp32/berry/src/be_listlib.c
new file mode 100644
index 000000000..a98b679df
--- /dev/null
+++ b/lib/libesp32/berry/src/be_listlib.c
@@ -0,0 +1,546 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_string.h"
+#include "be_strlib.h"
+#include "be_list.h"
+#include "be_func.h"
+#include "be_exec.h"
+#include "be_vm.h"
+#include
+
+#define list_check_data(vm, argc) \
+ if (!be_islist(vm, -1) || be_top(vm) - 1 < argc) { \
+ be_return_nil(vm); \
+ }
+
+#define list_check_ref(vm) \
+ if (be_refcontains(vm, 1)) { \
+ be_pushstring(vm, "[...]"); \
+ be_return(vm); \
+ }
+
+static void list_getindex(bvm *vm, int index)
+{
+ if (!be_getindex(vm, index)) {
+ be_raise(vm, "index_error", "list index out of range");
+ }
+}
+
+static int m_init(bvm *vm)
+{
+ int i, argc = be_top(vm);
+ if (argc > 1 && be_islist(vm, 2)) {
+ be_pushvalue(vm, 2);
+ be_setmember(vm, 1, ".p");
+ } else {
+ be_newlist(vm);
+ be_setmember(vm, 1, ".p");
+ for (i = 2; i <= argc; ++i) {
+ be_pushvalue(vm, i);
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ }
+ }
+ be_return_nil(vm);
+}
+
+static void push_element(bvm *vm)
+{
+ be_toescape(vm, -1, 'x'); /* escape string */
+ be_strconcat(vm, -3);
+ be_pop(vm, 1);
+}
+
+static int m_tostring(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ list_check_ref(vm);
+ be_refpush(vm, 1);
+ be_pushstring(vm, "[");
+ be_pushiter(vm, -2);
+ while (be_iter_hasnext(vm, -3)) {
+ be_iter_next(vm, -3);
+ push_element(vm);
+ if (be_iter_hasnext(vm, -3)) {
+ be_pushstring(vm, ", ");
+ be_strconcat(vm, -3);
+ be_pop(vm, 1);
+ }
+ }
+ be_pop(vm, 1); /* pop iterator */
+ be_pushstring(vm, "]");
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ be_refpop(vm);
+ be_return(vm);
+}
+
+static int m_push(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 2);
+ be_pushvalue(vm, 2);
+ be_data_push(vm, -2);
+ be_return_nil(vm);
+}
+
+static int m_pop(bvm *vm)
+{
+ int argc = be_top(vm);
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ if (argc >= 2) {
+ be_pushvalue(vm, 2);
+ } else {
+ be_pushint(vm, -1);
+ }
+ list_getindex(vm, -2);
+ be_pushvalue(vm, -2);
+ be_data_remove(vm, -4);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+static int m_insert(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 3);
+ be_pushvalue(vm, 2);
+ be_pushvalue(vm, 3);
+ be_data_insert(vm, -3);
+ be_return_nil(vm);
+}
+
+static int m_remove(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 2);
+ be_pushvalue(vm, 2);
+ be_data_remove(vm, -2);
+ be_return_nil(vm);
+}
+
+static int item_range(bvm *vm)
+{
+ bint lower, upper;
+ bint size = be_data_size(vm, -1); /* get source list size */
+ /* get index range */
+ be_getmember(vm, 2, "__lower__");
+ lower = be_toint(vm, -1);
+ if (lower < 0) {
+ lower = size + lower;
+ }
+ be_pop(vm, 1);
+ be_getmember(vm, 2, "__upper__");
+ upper = be_toint(vm, -1);
+ if (upper < 0) {
+ upper = size + upper;
+ }
+ be_pop(vm, 1);
+ /* protection scope */
+ upper = upper < size ? upper : size - 1;
+ lower = lower < 0 ? 0 : lower;
+ /* construction result list instance */
+ be_newobject(vm, "list"); /* result list */
+ be_getmember(vm, 1, ".p"); /* source list */
+ /* copy elements */
+ for (; lower <= upper; ++lower) {
+ be_pushint(vm, lower);
+ list_getindex(vm, -2);
+ be_data_push(vm, -4);
+ be_pop(vm, 2);
+ }
+ be_pop(vm, 2);
+ be_return(vm);
+}
+
+static int item_list(bvm *vm)
+{
+ int i, srcsize, idxsize;
+ be_getmember(vm, 2, ".p"); /* get index list */
+ srcsize = be_data_size(vm, -2); /* get source list size */
+ idxsize = be_data_size(vm, -1); /* get index list size */
+ /* construction result list instance */
+ be_newobject(vm, "list"); /* result list */
+ be_getmember(vm, 1, ".p"); /* source list */
+ /* copy elements */
+ for (i = 0; i < idxsize; ++i) {
+ be_pushint(vm, i);
+ be_getindex(vm, -5);
+ if (be_isint(vm, -1)) {
+ int idx = be_toindex(vm, -1);
+ if (idx >= 0 && idx < srcsize) {
+ be_getindex(vm, -3);
+ } else {
+ be_pushnil(vm);
+ }
+ } else {
+ be_pushnil(vm);
+ }
+ be_data_push(vm, -5);
+ be_pop(vm, 3);
+ }
+ be_pop(vm, 2);
+ be_return(vm);
+}
+
+static int m_item(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 2);
+ if (be_isint(vm, 2)) {
+ be_pushvalue(vm, 2);
+ list_getindex(vm, -2);
+ be_return(vm);
+ }
+ if (be_isinstance(vm, 2)) {
+ const char *cname = be_classname(vm, 2);
+ if (!strcmp(cname, "range")) {
+ return item_range(vm);
+ }
+ if (!strcmp(cname, "list")) {
+ return item_list(vm);
+ }
+ }
+ be_raise(vm, "index_error", "list index out of range");
+ be_return_nil(vm);
+}
+
+static int m_find(bvm *vm)
+{
+ bbool found = bfalse;
+ int idx;
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 2);
+ list_check_ref(vm);
+ be_refpush(vm, 1);
+ be_pushiter(vm, -1);
+ for (idx=0; be_iter_hasnext(vm, -2); idx++) {
+ be_iter_next(vm, -2);
+ be_pushvalue(vm, 2); /* push needle to compare */
+ if (be_iseq(vm)) {
+ found = btrue;
+ be_pop(vm, 2);
+ break;
+ }
+ be_pop(vm, 2);
+ }
+ be_pop(vm, 1); /* pop iterator */
+ be_refpop(vm);
+ if (found) {
+ be_pushint(vm, idx);
+ be_return(vm);
+ } else {
+ be_return_nil(vm);
+ }
+}
+
+static int m_setitem(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 3);
+ be_pushvalue(vm, 2);
+ be_pushvalue(vm, 3);
+ if (!be_setindex(vm, -3)) {
+ be_raise(vm, "index_error", "list assignment index out of range");
+ }
+ be_return_nil(vm);
+}
+
+static int m_size(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ be_pushint(vm, be_data_size(vm, -1));
+ be_return(vm);
+}
+
+static int m_resize(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 2);
+ be_pushvalue(vm, 2);
+ be_data_resize(vm, -2);
+ be_return_nil(vm);
+}
+
+static int m_clear(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ be_pushint(vm, 0);
+ be_data_resize(vm, -2);
+ be_return_nil(vm);
+}
+
+static int iter_closure(bvm *vm)
+{
+ /* for better performance, we operate the upvalues
+ * directly without using by the stack. */
+ bntvclos *func = var_toobj(vm->cf->func);
+ bvalue *uv0 = be_ntvclos_upval(func, 0)->value; /* list value */
+ bvalue *uv1 = be_ntvclos_upval(func, 1)->value; /* iter value */
+ bvalue *next = cast(bvalue*, var_toobj(uv1)) + 1;
+ blist *list = var_toobj(uv0);
+ if (next >= be_list_end(list)) {
+ be_stop_iteration(vm);
+ }
+ var_toobj(uv1) = next; /* set upvale[1] (iter value) */
+ /* push next value to top */
+ var_setval(vm->top, next);
+ be_incrtop(vm);
+ be_return(vm);
+}
+
+static int m_iter(bvm *vm)
+{
+ be_pushntvclosure(vm, iter_closure, 2);
+ be_getmember(vm, 1, ".p");
+ be_setupval(vm, -2, 0);
+ be_pushiter(vm, -1);
+ be_setupval(vm, -3, 1);
+ be_pop(vm, 2);
+ be_return(vm);
+}
+
+static int m_connect(bvm *vm)
+{
+ int argc = be_top(vm);
+ if (argc >= 2) {
+ be_getmember(vm, 1, ".p");
+ be_pushvalue(vm, 2);
+ be_data_push(vm, -2);
+ be_pop(vm, argc + 1);
+ }
+ be_return(vm); /* return self */
+}
+
+static int m_merge(bvm *vm)
+{
+ int argc = be_top(vm);
+ if (argc >= 2) {
+ be_newobject(vm, "list"); /* stack contains instance and .p */
+ be_getmember(vm, 1, ".p");
+ be_data_merge(vm, -2);
+ be_getmember(vm, 2, ".p");
+ if (!be_islist(vm, -1)) {
+ be_raise(vm, "type_error", "operand must be a list");
+ }
+ be_data_merge(vm, -3);
+ be_pop(vm, 3);
+ }
+ be_return(vm); /* return self */
+}
+
+static void connect(bvm *vm, bvalue *begin, bvalue *end, const char * delimiter, bbool first_element)
+{
+ size_t l0 = be_strlen(vm, -1), len = l0;
+ size_t d = delimiter ? strlen(delimiter) : 0; /* len of delimiter */
+ char *buf, *p;
+ bvalue *it;
+ for (it = begin; it < end; ++it) {
+ len += str_len(var_tostr(it)) + d;
+ }
+ if (first_element) {
+ len -= d; /* remove size for first delimiter non needed */
+ }
+ buf = be_pushbuffer(vm, len);
+ memcpy(buf, be_tostring(vm, -2), l0);
+ p = buf + l0;
+ for (it = begin; it < end; ++it) {
+ if ((it != begin || !first_element) && delimiter) {
+ /* add delimiter */
+ memcpy(p, delimiter, d);
+ p += d;
+ }
+ bstring *s = var_tostr(it);
+ size_t l = str_len(s);
+ memcpy(p, str(s), l);
+ p += l;
+ }
+ be_pushstring(vm, buf);
+ be_moveto(vm, -1, -3);
+ be_pop(vm, 2);
+}
+
+static void list_concat(bvm *vm, blist *list, const char * delimiter)
+{
+ bvalue *it, *begin = be_list_data(list);
+ bvalue *end = be_list_end(list);
+ be_pushstring(vm, ""); /* push a empty string */
+ bbool first_element = btrue;
+ for (it = begin; it < end;) {
+ for (; it < end && var_isstr(it); ++it);
+ if (begin < it) {
+ connect(vm, begin, it, delimiter, first_element); /* connect string list */
+ first_element = bfalse;
+ }
+ if (it < end) {
+ if (delimiter && !first_element) {
+ be_pushstring(vm, delimiter);
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ }
+ /* connect other value */
+ var_setval(vm->top, it);
+ be_incrtop(vm);
+ be_val2str(vm, -1);
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ begin = ++it;
+ first_element = bfalse;
+ }
+ }
+}
+
+static int m_concat(bvm *vm)
+{
+ bvalue *value;
+ int top = be_top(vm);
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ value = be_indexof(vm, -1);
+ const char * delimiter = NULL;
+ if (top >= 2) {
+ delimiter = be_tostring(vm, 2);
+ }
+ list_concat(vm, var_toobj(value), delimiter);
+ be_return(vm);
+}
+
+static int m_reverse(bvm *vm)
+{
+ int top = be_top(vm);
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ be_data_reverse(vm, -1);
+ be_pop(vm, top);
+ be_return(vm);
+}
+
+static int m_copy(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ be_getbuiltin(vm, "list");
+ be_copy(vm, -2);
+ be_call(vm, 1);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+static int list_equal(bvm *vm, bbool iseq)
+{
+ int i, j, res;
+ bbool (*eqfunc)(bvm*) = iseq ? be_iseq : be_isneq;
+ be_getmember(vm, 1, ".p");
+ be_getmember(vm, 2, ".p");
+ i = be_data_size(vm, -2);
+ j = be_data_size(vm, -1);
+ if (i == j) {
+ res = iseq;
+ for (i = 0; res == iseq && i < j; ++i) {
+ be_pushint(vm, i);
+ be_getindex(vm, -3);
+ be_pushint(vm, i);
+ be_getindex(vm, -4);
+ be_remove(vm, -2);
+ res = eqfunc(vm);
+ be_pop(vm, 3);
+ }
+ } else {
+ res = !iseq;
+ }
+ be_pushbool(vm, res);
+ be_return(vm);
+}
+
+static int m_keys(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ list_check_data(vm, 1);
+ int size = be_data_size(vm, -1);
+ be_getbuiltin(vm, "range");
+ be_pushint(vm, 0);
+ be_pushint(vm, size - 1);
+ be_call(vm, 2);
+ be_pop(vm, 2);
+ be_return(vm);
+}
+
+static int m_equal(bvm *vm)
+{
+ return list_equal(vm, btrue);
+}
+
+static int m_nequal(bvm *vm)
+{
+ return list_equal(vm, bfalse);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+void be_load_listlib(bvm *vm)
+{
+ static const bnfuncinfo members[] = {
+ { ".p", NULL },
+ { "init", m_init },
+ { "tostring", m_tostring },
+ { "push", m_push },
+ { "pop", m_pop },
+ { "insert", m_insert },
+ { "remove", m_remove },
+ { "item", m_item },
+ { "find", m_find },
+ { "setitem", m_setitem },
+ { "size", m_size },
+ { "resize", m_resize },
+ { "clear", m_clear },
+ { "iter", m_iter },
+ { "concat", m_concat },
+ { "reverse", m_reverse },
+ { "copy", m_copy },
+ { "keys", m_keys },
+ { "..", m_connect },
+ { "+", m_merge },
+ { "==", m_equal },
+ { "!=", m_nequal },
+ { NULL, NULL }
+ };
+ be_regclass(vm, "list", members);
+}
+#else
+/* @const_object_info_begin
+class be_class_list (scope: global, name: list) {
+ .p, var
+ init, func(m_init)
+ tostring, func(m_tostring)
+ push, func(m_push)
+ pop, func(m_pop)
+ insert, func(m_insert)
+ remove, func(m_remove)
+ item, func(m_item)
+ find, func(m_find)
+ setitem, func(m_setitem)
+ size, func(m_size)
+ resize, func(m_resize)
+ clear, func(m_clear)
+ iter, func(m_iter)
+ concat, func(m_concat)
+ reverse, func(m_reverse)
+ copy, func(m_copy)
+ keys, func(m_keys)
+ .., func(m_connect)
+ +, func(m_merge)
+ ==, func(m_equal)
+ !=, func(m_nequal)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_be_class_list.h"
+#endif
diff --git a/lib/libesp32/berry/src/be_map.c b/lib/libesp32/berry/src/be_map.c
new file mode 100644
index 000000000..37f9efc62
--- /dev/null
+++ b/lib/libesp32/berry/src/be_map.c
@@ -0,0 +1,352 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_map.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_class.h"
+#include "be_mem.h"
+#include "be_gc.h"
+#include "be_vm.h"
+#include "be_exec.h"
+#include
+
+#define key(node) (&(node)->key)
+#define value(node) (&(node)->value)
+#define isnil(node) var_isnil(key(node))
+#define setnil(node) var_setnil(key(node))
+#define hash2slot(m, h) ((m)->slots + (h) % (m)->size)
+#define hashcode(_v) _hashcode(vm, (_v)->type, (_v)->v)
+#define keytype(key) ((signed char)(key)->type)
+
+#define next(node) ((node)->key.next)
+#define pos2slot(map, n) ((n) != LASTNODE ? ((map)->slots + (n)) : NULL)
+#define pos(map, node) ((int)((node) - (map)->slots))
+#define setkey(node, _v) { (node)->key.type = (bbyte)(_v)->type; \
+ (node)->key.v = (_v)->v; }
+
+#define datasize(size) ((size) * sizeof(bmapnode))
+
+#define LASTNODE ((1 << 24) - 1)
+
+static int map_nextsize(int size)
+{
+ be_assert(size < LASTNODE);
+ if (size < LASTNODE) {
+ return be_nextsize(size);
+ }
+ return LASTNODE + 1;
+}
+
+static uint32_t hashptr(void *p)
+{
+ uintptr_t i = (uintptr_t)p;
+ return (uint32_t)((i ^ (i >> 16)) & 0xFFFFFFFF);
+}
+
+#if BE_USE_SINGLE_FLOAT
+#define hashreal(v) ((uint32_t)((v).i))
+#else
+static uint32_t hashreal(union bvaldata v)
+{
+ union { breal r; uint32_t i[2]; } u;
+ u.r = v.r;
+ return u.i[0] ^ u.i[1];
+}
+#endif
+
+#if BE_USE_OVERLOAD_HASH
+static uint32_t hashins(bvm *vm, binstance *obj)
+{
+ int type = be_instance_member(vm, obj, str_literal(vm, "hash"), vm->top);
+ if (basetype(type) == BE_FUNCTION) {
+ bvalue *top = vm->top;
+ var_setinstance(top + 1, obj);
+ vm->top += 2;
+ be_dofunc(vm, top, 1); /* call method 'item' */
+ vm->top -= 2;
+ if (!var_isint(vm->top)) { /* check the return value */
+ const char *name = str(be_instance_name(obj));
+ be_raise(vm, "runtime_error", be_pushfstring(vm,
+ "the value of `%s::hash()` is not a 'int'",
+ strlen(name) ? name : ""));
+ }
+ return (uint32_t)var_toint(vm->top);
+ }
+ return hashptr(obj);
+}
+#endif
+
+static uint32_t _hashcode(bvm *vm, int type, union bvaldata v)
+{
+ (void)vm;
+ switch (type) {
+ case BE_NIL: return 0;
+ case BE_BOOL: return (uint32_t)v.b;
+ case BE_INT: return (uint32_t)v.i;
+ case BE_REAL: return hashreal(v);
+ case BE_STRING: return be_strhash(v.s);
+#if BE_USE_OVERLOAD_HASH
+ case BE_INSTANCE: return hashins(vm, v.p);
+#endif
+ default: return hashptr(v.p);
+ }
+}
+
+static int eqnode(bvm *vm, bmapnode *node, bvalue *key, uint32_t hash)
+{
+ (void)vm;
+ if (!var_isnil(key)) {
+ bmapkey *k = key(node);
+#if BE_USE_OVERLOAD_HASH
+ if (var_isinstance(key)) {
+ bvalue kv;
+ kv.type = k->type;
+ kv.v = k->v;
+ return be_vm_iseq(vm, key, &kv);
+ }
+#endif
+ if(keytype(k) == key->type && hashcode(k) == hash) {
+ switch (key->type) {
+ case BE_INT: return var_toint(key) == var_toint(k);
+ case BE_REAL: return var_toreal(key) == var_toreal(k);
+ case BE_STRING: return be_eqstr(var_tostr(key), var_tostr(k));
+ default: return var_toobj(key) == var_toobj(k);
+ }
+ }
+ }
+ return 0;
+}
+
+static bmapnode* findprev(bmap *map, bmapnode *list, bmapnode *slot)
+{
+ int n, pos = pos(map, slot);
+ bmapnode *prev = list;
+ for (;;) {
+ n = next(prev);
+ if (n == pos || n == LASTNODE) {
+ break;
+ }
+ prev = map->slots + n;
+ }
+ return n == pos ? prev : NULL;
+}
+
+static bmapnode* nextfree(bmap *map)
+{
+ bmapnode *base = map->slots;
+ while (map->lastfree >= base) {
+ if (isnil(map->lastfree)) {
+ return map->lastfree;
+ }
+ --map->lastfree;
+ }
+ return NULL;
+}
+
+static bmapnode* insert(bvm *vm, bmap *map, bvalue *key, uint32_t hash)
+{
+ bmapnode *slot = hash2slot(map, hash);
+ if (isnil(slot)) { /* empty slot */
+ setkey(slot, key);
+ next(slot) = LASTNODE;
+ } else {
+ uint32_t h = hashcode(key(slot)); /* get the hashcode of the exist node */
+ bmapnode *mainslot = hash2slot(map, h); /* get the main-slot */
+ bmapnode *new = nextfree(map); /* get a free slot */
+ if (mainslot == slot) { /* old is main slot */
+ /* insert in first */
+ setkey(new, key);
+ next(new) = next(slot);
+ next(slot) = pos(map, new);
+ slot = new;
+ } else {
+ bmapnode *prev = findprev(map, mainslot, slot);
+ next(prev) = pos(map, new); /* link the previous node */
+ *new = *slot; /* copy to new slot */
+ setkey(slot, key);
+ next(slot) = LASTNODE;
+ }
+ }
+ return slot;
+}
+
+static bmapnode* find(bvm *vm, bmap *map, bvalue *key, uint32_t hash)
+{
+ bmapnode *slot = hash2slot(map, hash);
+ if (isnil(slot)) {
+ return NULL;
+ }
+ while (!eqnode(vm, slot, key, hash)) {
+ int n = next(slot);
+ if (n == LASTNODE) {
+ return NULL;
+ }
+ slot = map->slots + n;
+ }
+ return slot;
+}
+
+static void resize(bvm *vm, bmap *map, int size)
+{
+ int i, oldsize;
+ bmapnode *slots, *oldslots;
+ if (size < map->count) {
+ return;
+ }
+ oldsize = map->size;
+ oldslots = map->slots;
+ slots = be_malloc(vm, datasize(size));
+ for (i = 0; i < size; ++i) {
+ setnil(slots + i);
+ }
+ map->size = size;
+ map->slots = slots;
+ map->lastfree = slots + size - 1;
+ /* rehash */
+ for (i = 0; i < oldsize; ++i) {
+ bmapnode *node = oldslots + i;
+ if (!isnil(node)) {
+ bvalue v;
+ bmapnode *newslot;
+ v.type = node->key.type;
+ v.v = node->key.v;
+ newslot = insert(vm, map, &v, hashcode(&v));
+ newslot->value = node->value;
+ }
+ }
+ be_free(vm, oldslots, datasize(oldsize));
+}
+
+bmap* be_map_new(bvm *vm)
+{
+ bgcobject *gco = be_gcnew(vm, BE_MAP, bmap);
+ bmap *map = cast_map(gco);
+ if (map) {
+ map->size = 0;
+ map->count = 0;
+ map->slots = NULL;
+ var_setmap(vm->top, map);
+ be_incrtop(vm);
+ resize(vm, map, 2);
+ be_stackpop(vm, 1);
+ }
+ return map;
+}
+
+void be_map_delete(bvm *vm, bmap *map)
+{
+ be_free(vm, map->slots, datasize(map->size));
+ be_free(vm, map, sizeof(bmap));
+}
+
+bvalue* be_map_find(bvm *vm, bmap *map, bvalue *key)
+{
+ bmapnode *entry = find(vm, map, key, hashcode(key));
+ return entry ? value(entry) : NULL;
+}
+
+bvalue* be_map_insert(bvm *vm, bmap *map, bvalue *key, bvalue *value)
+{
+ uint32_t hash = hashcode(key);
+ bmapnode *entry = find(vm, map, key, hash);
+ if (!entry) { /* new entry */
+ if (map->count >= map->size) {
+ resize(vm, map, map_nextsize(map->size));
+ }
+ entry = insert(vm, map, key, hash);
+ ++map->count;
+ }
+ if (value) {
+ entry->value = *value;
+ }
+ return value(entry);
+}
+
+int be_map_remove(bvm *vm, bmap *map, bvalue *key)
+{
+ uint32_t hash = hashcode(key);
+ bmapnode *slot = hash2slot(map, hash); /* main slot */
+
+ if (eqnode(vm, slot, key, hash)) { /* first node */
+ bmapnode *next = pos2slot(map, next(slot));
+ if (next) { /* has next */
+ *slot = *next; /* first: copy the second node to the slot */
+ slot = next; /* second: set the second node to nil (empty) */
+ }
+ } else { /* the node will be remove is not first-node */
+ bmapnode *prev = slot;
+ for (;;) { /* find the previous node */
+ int n = next(prev);
+ slot = pos2slot(map, n);
+ if (slot == NULL) { /* node not found */
+ return bfalse;
+ }
+ if (eqnode(vm, slot, key, hash)) {
+ break;
+ }
+ prev = slot;
+ }
+ /* link the list */
+ next(prev) = next(slot);
+ }
+ /* set to nil */
+ setnil(slot);
+ /* add to lastfree */
+ if (map->lastfree < slot) {
+ map->lastfree = slot;
+ }
+ --map->count;
+ return btrue;
+}
+
+bvalue* be_map_findstr(bvm *vm, bmap *map, bstring *key)
+{
+ bvalue v;
+ var_setstr(&v, key);
+ return be_map_find(vm, map, &v);
+}
+
+bvalue* be_map_insertstr(bvm *vm, bmap *map, bstring *key, bvalue *value)
+{
+ bvalue v;
+ var_setstr(&v, key);
+ set_fixed(key);
+ bvalue * r = be_map_insert(vm, map, &v, value);
+ restore_fixed(key);
+ return r;
+}
+
+void be_map_removestr(bvm *vm, bmap *map, bstring *key)
+{
+ bvalue v;
+ var_setstr(&v, key);
+ be_map_remove(vm, map, &v);
+}
+
+bmapnode* be_map_next(bmap *map, bmapiter *iter)
+{
+ bmapnode *end = map->slots + map->size;
+ *iter = *iter ? *iter + 1 : map->slots;
+ while (*iter < end && isnil(*iter)) {
+ ++(*iter);
+ }
+ return *iter < end ? *iter : NULL;
+}
+
+bmapnode* be_map_val2node(bvalue *value)
+{
+ return (bmapnode *)((size_t)value - sizeof(bmapkey));
+}
+
+void be_map_compact(bvm *vm, bmap *map)
+{
+ (void)vm;
+ if (!gc_isconst(map)) {
+ resize(vm, map, map->count ? map->count : 1);
+ }
+}
diff --git a/lib/libesp32/berry/src/be_map.h b/lib/libesp32/berry/src/be_map.h
new file mode 100644
index 000000000..7ae76962c
--- /dev/null
+++ b/lib/libesp32/berry/src/be_map.h
@@ -0,0 +1,61 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_MAP_H
+#define BE_MAP_H
+
+#include "be_object.h"
+
+typedef struct bmapkey {
+ union bvaldata v;
+ uint32_t type:8;
+ uint32_t next:24;
+} bmapkey;
+
+typedef struct bmapnode {
+ bmapkey key;
+ bvalue value;
+} bmapnode;
+
+struct bmap {
+ bcommon_header;
+ bgcobject *gray; /* for gc gray list */
+ bmapnode *slots;
+ bmapnode *lastfree;
+ int size;
+ int count;
+#ifdef __cplusplus
+ BE_CONSTEXPR bmap(bmapnode *s, int n) :
+ next(0), type(BE_MAP), marked(GC_CONST), gray(0),
+ slots(s), lastfree(0), size(n), count(n) {}
+#endif
+};
+
+typedef bmapnode *bmapiter;
+
+#define be_map_iter() NULL
+#define be_map_count(map) ((map)->count)
+#define be_map_size(map) (map->size)
+
+#define be_map_key2value(dst, node) do { \
+ (dst)->type = (node)->key.type; \
+ (dst)->v = (node)->key.v; \
+} while (0);
+
+bmap* be_map_new(bvm *vm);
+void be_map_delete(bvm *vm, bmap *map);
+bvalue* be_map_find(bvm *vm, bmap *map, bvalue *key);
+bvalue* be_map_insert(bvm *vm, bmap *map, bvalue *key, bvalue *value);
+int be_map_remove(bvm *vm, bmap *map, bvalue *key);
+bvalue* be_map_findstr(bvm *vm, bmap *map, bstring *key);
+bvalue* be_map_insertstr(bvm *vm, bmap *map, bstring *key, bvalue *value);
+void be_map_removestr(bvm *vm, bmap *map, bstring *key);
+bmapnode* be_map_next(bmap *map, bmapiter *iter);
+bmapnode* be_map_val2node(bvalue *value);
+void be_map_compact(bvm *vm, bmap *map);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_maplib.c b/lib/libesp32/berry/src/be_maplib.c
new file mode 100644
index 000000000..a8fc7309e
--- /dev/null
+++ b/lib/libesp32/berry/src/be_maplib.c
@@ -0,0 +1,313 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_func.h"
+#include "be_exec.h"
+#include "be_map.h"
+#include "be_vm.h"
+
+#define map_check_data(vm, argc) \
+ if (!be_ismap(vm, -1) || be_top(vm) - 1 < argc) { \
+ be_return_nil(vm); \
+ }
+
+#define map_check_ref(vm) \
+ if (be_refcontains(vm, 1)) { \
+ be_pushstring(vm, "{...}"); \
+ be_return(vm); \
+ }
+
+static int m_init(bvm *vm)
+{
+ if (be_top(vm) > 1 && be_ismap(vm, 2)) {
+ be_pushvalue(vm, 2);
+ be_setmember(vm, 1, ".p");
+ } else {
+ be_newmap(vm);
+ be_setmember(vm, 1, ".p");
+ }
+ be_return_nil(vm);
+}
+
+static void push_key(bvm *vm)
+{
+ be_toescape(vm, -2, 'x'); /* escape string */
+ be_pushvalue(vm, -2); /* push to top */
+ be_strconcat(vm, -5);
+ be_pop(vm, 1);
+}
+
+static void push_value(bvm *vm)
+{
+ be_toescape(vm, -1, 'x'); /* escape string */
+ be_strconcat(vm, -4);
+ be_pop(vm, 2);
+ if (be_iter_hasnext(vm, -3)) {
+ be_pushstring(vm, ", ");
+ be_strconcat(vm, -3);
+ be_pop(vm, 1);
+ }
+}
+
+static int m_tostring(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 1);
+ map_check_ref(vm);
+ be_refpush(vm, 1);
+ be_pushstring(vm, "{");
+ be_pushiter(vm, -2); /* map iterator use 1 register */
+ while (be_iter_hasnext(vm, -3)) {
+ be_iter_next(vm, -3);
+ push_key(vm); /* key.tostring() */
+ be_pushstring(vm, ": "); /* add ': ' */
+ be_strconcat(vm, -5);
+ be_pop(vm, 1);
+ push_value(vm); /* value.tostring() */
+ }
+ be_pop(vm, 1); /* pop iterator */
+ be_pushstring(vm, "}");
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ be_refpop(vm);
+ be_return(vm);
+}
+
+static int m_remove(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 2);
+ be_pushvalue(vm, 2);
+ be_data_remove(vm, -2);
+ be_return_nil(vm);
+}
+
+static int m_item(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 2);
+ be_pushvalue(vm, 2);
+ if (!be_getindex(vm, -2)) {
+ be_raise(vm, "key_error", be_tostring(vm, 2));
+ }
+ be_return(vm);
+}
+
+static int m_setitem(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 3);
+ be_pushvalue(vm, 2);
+ be_pushvalue(vm, 3);
+ be_setindex(vm, -3);
+ be_return_nil(vm);
+}
+
+static int m_find(bvm *vm)
+{
+ int argc = be_top(vm);
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 2);
+ be_pushvalue(vm, 2);
+ /* not find and has default value */
+ if (!be_getindex(vm, -2) && argc >= 3) {
+ be_pushvalue(vm, 3);
+ }
+ be_return(vm);
+}
+
+static int m_contains(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 2);
+ be_pushvalue(vm, 2);
+ be_pushbool(vm, be_getindex(vm, -2));
+ be_return(vm);
+}
+
+static int m_insert(bvm *vm)
+{
+ bbool res;
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 3);
+ be_pushvalue(vm, 2);
+ be_pushvalue(vm, 3);
+ res = be_data_insert(vm, -3);
+ be_pushbool(vm, res);
+ be_return(vm);
+}
+
+static int m_size(bvm *vm)
+{
+ be_getmember(vm, 1, ".p");
+ map_check_data(vm, 1);
+ be_pushint(vm, be_data_size(vm, -1));
+ be_return(vm);
+}
+
+static int iter_closure(bvm *vm)
+{
+ /* for better performance, we operate the upvalues
+ * directly without using by the stack. */
+ bntvclos *func = var_toobj(vm->cf->func);
+ bvalue *uv0 = be_ntvclos_upval(func, 0)->value; /* list value */
+ bvalue *uv1 = be_ntvclos_upval(func, 1)->value; /* iter value */
+ bmapiter iter = var_toobj(uv1);
+ bmapnode *next = be_map_next(var_toobj(uv0), &iter);
+ if (next == NULL) {
+ be_stop_iteration(vm);
+ be_return_nil(vm); /* will not be executed */
+ }
+ var_setobj(uv1, BE_COMPTR, iter); /* set upvale[1] (iter value) */
+ /* push next value to top */
+ var_setval(vm->top, &next->value);
+ be_incrtop(vm);
+ be_return(vm);
+}
+
+static int m_iter(bvm *vm)
+{
+ be_pushntvclosure(vm, iter_closure, 2);
+ be_getmember(vm, 1, ".p");
+ be_setupval(vm, -2, 0);
+ be_pushiter(vm, -1);
+ be_setupval(vm, -3, 1);
+ be_pop(vm, 2);
+ be_return(vm);
+}
+
+static int keys_iter_closure(bvm *vm)
+{
+ /* for better performance, we operate the upvalues
+ * directly without using by the stack. */
+ bntvclos *func = var_toobj(vm->cf->func);
+ bvalue *uv0 = be_ntvclos_upval(func, 0)->value; /* list value */
+ bvalue *uv1 = be_ntvclos_upval(func, 1)->value; /* iter value */
+ bmapiter iter = var_toobj(uv1);
+ bmapnode *next = be_map_next(var_toobj(uv0), &iter);
+ if (next == NULL) {
+ be_stop_iteration(vm);
+ be_return_nil(vm); /* will not be executed */
+ }
+ var_setobj(uv1, BE_COMPTR, iter); /* set upvale[1] (iter value) */
+ /* push next value to top */
+ var_setobj(vm->top, next->key.type, next->key.v.p);
+ be_incrtop(vm);
+ be_return(vm);
+}
+
+static int m_keys(bvm *vm)
+{
+ be_pushntvclosure(vm, keys_iter_closure, 2);
+ be_getmember(vm, 1, ".p");
+ be_setupval(vm, -2, 0);
+ be_pushiter(vm, -1);
+ be_setupval(vm, -3, 1);
+ be_pop(vm, 2);
+ be_return(vm);
+}
+
+/* apply a function/closure to each element of a map */
+/* `map.reduce(f:function [, initializer:any]) -> any` */
+/* Calls for each element `f(key, value, acc) -> any` */
+/* `acc` is initialized with `initilizer` if present or `nil` */
+/* the return value of the function becomes the next value passed in arg `acc` */
+static int m_reduce(bvm *vm)
+{
+ int argc = be_top(vm);
+ if (argc > 1 && be_isfunction(vm, 2)) {
+ bbool has_initializer = (argc > 2);
+ /* get map internal object */
+ be_getmember(vm, 1, ".p");
+ bvalue *v = be_indexof(vm, -1);
+ bmap *map = cast(bmap*, var_toobj(v));
+ /* get the number of slots if any */
+ int slots_initial = be_map_size(map);
+ /* place-holder for on-going value and return value */
+ if (has_initializer) {
+ be_pushvalue(vm, 3);
+ } else {
+ be_pushnil(vm); /* if no initializer use `nil` */
+ }
+ for (int i = 0; i < slots_initial; i++) {
+ bmapnode * node = map->slots + i;
+ if (!var_isnil(&node->key)) { /* is the key present in this slot? */
+ be_pushvalue(vm, 2); /* push function */
+
+ bvalue kv; /* push key on stack */
+ kv.type = node->key.type;
+ kv.v = node->key.v;
+ bvalue *reg = vm->top;
+ var_setval(reg, &kv);
+ be_incrtop(vm);
+
+ reg = vm->top; /* push value on stack */
+ var_setval(reg, &node->value);
+ be_incrtop(vm);
+
+ be_pushvalue(vm, -4);
+
+ be_call(vm, 3);
+ be_pop(vm, 3); /* pop args, keep return value */
+ be_remove(vm, -2); /* remove previous accumulator, keep return value from function */
+ }
+ /* check if the map has been resized during the call */
+ if (be_map_size(map) != slots_initial) {
+ be_raise(vm, "stop_iteration", "map resized within apply");
+ break; /* abort */
+ }
+ }
+ be_return(vm);
+ }
+ be_raise(vm, "value_error", "needs function as first argument");
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+void be_load_maplib(bvm *vm)
+{
+ static const bnfuncinfo members[] = {
+ { ".p", NULL },
+ { "init", m_init },
+ { "tostring", m_tostring },
+ { "remove", m_remove },
+ { "item", m_item },
+ { "setitem", m_setitem },
+ { "find", m_find },
+ { "contains", m_contains },
+ { "has", m_contains }, /* deprecated */
+ { "size", m_size },
+ { "insert", m_insert },
+ { "iter", m_iter },
+ { "keys", m_keys },
+ { "reduce", m_reduce },
+ { NULL, NULL }
+ };
+ be_regclass(vm, "map", members);
+}
+#else
+/* @const_object_info_begin
+class be_class_map (scope: global, name: map) {
+ .p, var
+ init, func(m_init)
+ tostring, func(m_tostring)
+ remove, func(m_remove)
+ item, func(m_item)
+ setitem, func(m_setitem)
+ find, func(m_find)
+ contains, func(m_contains)
+ has, func(m_contains)
+ size, func(m_size)
+ insert, func(m_insert)
+ iter, func(m_iter)
+ keys, func(m_keys)
+ reduce, func(m_reduce)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_be_class_map.h"
+#endif
diff --git a/lib/libesp32/berry/src/be_mathlib.c b/lib/libesp32/berry/src/be_mathlib.c
new file mode 100644
index 000000000..b9598f525
--- /dev/null
+++ b/lib/libesp32/berry/src/be_mathlib.c
@@ -0,0 +1,351 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include
+#include
+#include
+
+#if BE_USE_MATH_MODULE
+
+#ifdef M_PI
+ #undef M_PI
+#endif
+#define M_PI 3.141592653589793238462643383279
+
+#if BE_INTGER_TYPE == 0 /* int */
+ #define M_IMAX INT_MAX
+ #define M_IMIN INT_MIN
+#elif BE_INTGER_TYPE == 1 /* long */
+ #define M_IMAX LONG_MAX
+ #define M_IMIN LONG_MIN
+#else /* int64_t (long long) */
+ #define M_IMAX LLONG_MAX
+ #define M_IMIN LLONG_MIN
+#endif
+
+#if BE_USE_SINGLE_FLOAT
+ #define mathfunc(func) func##f
+#else
+ #define mathfunc(func) func
+#endif
+
+static int m_isnan(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isreal(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushbool(vm, isnan(x));
+ } else {
+ be_pushbool(vm, bfalse);
+ }
+ be_return(vm);
+}
+
+static int m_abs(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(fabs)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_ceil(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(ceil)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_floor(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(floor)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_sin(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(sin)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_cos(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(cos)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_tan(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(tan)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_asin(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(asin)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_acos(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(acos)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_atan(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(atan)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_atan2(bvm *vm)
+{
+ if (be_top(vm) >= 2 && be_isnumber(vm, 1) && be_isnumber(vm, 2)) {
+ breal y = be_toreal(vm, 1);
+ breal x = be_toreal(vm, 2);
+ be_pushreal(vm, mathfunc(atan2)(y, x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_sinh(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(sinh)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_cosh(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(cosh)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_tanh(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(tanh)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_sqrt(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(sqrt)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_exp(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(exp)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_log(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(log)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_log10(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, mathfunc(log10)(x));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_deg(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, x * (breal)(180.0 / M_PI));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_rad(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
+ breal x = be_toreal(vm, 1);
+ be_pushreal(vm, x * (breal)(M_PI / 180.0));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_pow(bvm *vm)
+{
+ if (be_top(vm) >= 2 && be_isnumber(vm, 1) && be_isnumber(vm, 2)) {
+ breal x = be_toreal(vm, 1);
+ breal y = be_toreal(vm, 2);
+ be_pushreal(vm, mathfunc(pow)(x, y));
+ } else {
+ be_pushreal(vm, (breal)0.0);
+ }
+ be_return(vm);
+}
+
+static int m_srand(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isint(vm, 1)) {
+ srand((unsigned int)be_toint(vm, 1));
+ }
+ be_return_nil(vm);
+}
+
+static int m_rand(bvm *vm)
+{
+ be_pushint(vm, rand());
+ be_return(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(math) {
+ be_native_module_function("isnan", m_isnan),
+ be_native_module_function("abs", m_abs),
+ be_native_module_function("ceil", m_ceil),
+ be_native_module_function("floor", m_floor),
+ be_native_module_function("sin", m_sin),
+ be_native_module_function("cos", m_cos),
+ be_native_module_function("tan", m_tan),
+ be_native_module_function("asin", m_asin),
+ be_native_module_function("acos", m_acos),
+ be_native_module_function("atan", m_atan),
+ be_native_module_function("atan2", m_atan2),
+ be_native_module_function("sinh", m_sinh),
+ be_native_module_function("cosh", m_cosh),
+ be_native_module_function("tanh", m_tanh),
+ be_native_module_function("sqrt", m_sqrt),
+ be_native_module_function("exp", m_exp),
+ be_native_module_function("log", m_log),
+ be_native_module_function("log10", m_log10),
+ be_native_module_function("deg", m_deg),
+ be_native_module_function("rad", m_rad),
+ be_native_module_function("pow", m_pow),
+ be_native_module_function("srand", m_srand),
+ be_native_module_function("rand", m_rand),
+ be_native_module_real("pi", M_PI),
+ be_native_module_real("nan", NAN),
+ be_native_module_int("imax", M_IMAX),
+ be_native_module_int("imin", M_IMIN),
+};
+
+be_define_native_module(math, NULL);
+#else
+/* @const_object_info_begin
+module math (scope: global, depend: BE_USE_MATH_MODULE) {
+ isnan, func(m_isnan)
+ abs, func(m_abs)
+ ceil, func(m_ceil)
+ floor, func(m_floor)
+ sin, func(m_sin)
+ cos, func(m_cos)
+ tan, func(m_tan)
+ asin, func(m_asin)
+ acos, func(m_acos)
+ atan, func(m_atan)
+ atan2, func(m_atan2)
+ sinh, func(m_sinh)
+ cosh, func(m_cosh)
+ tanh, func(m_tanh)
+ sqrt, func(m_sqrt)
+ exp, func(m_exp)
+ log, func(m_log)
+ log10, func(m_log10)
+ deg, func(m_deg)
+ rad, func(m_rad)
+ pow, func(m_pow)
+ srand, func(m_srand)
+ rand, func(m_rand)
+ pi, real(M_PI)
+ nan, real(NAN)
+ imax, int(M_IMAX)
+ imin, int(M_IMIN)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_math.h"
+#endif
+
+#endif /* BE_USE_MATH_MODULE */
diff --git a/lib/libesp32/berry/src/be_mem.c b/lib/libesp32/berry/src/be_mem.c
new file mode 100644
index 000000000..9cfe364df
--- /dev/null
+++ b/lib/libesp32/berry/src/be_mem.c
@@ -0,0 +1,79 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_mem.h"
+#include "be_exec.h"
+#include "be_vm.h"
+#include "be_gc.h"
+#include
+#include
+
+#define GC_ALLOC (1 << 2) /* GC in alloc */
+
+#ifdef BE_EXPLICIT_MALLOC
+ #define malloc BE_EXPLICIT_MALLOC
+#endif
+
+#ifdef BE_EXPLICIT_FREE
+ #define free BE_EXPLICIT_FREE
+#endif
+
+#ifdef BE_EXPLICIT_REALLOC
+ #define realloc BE_EXPLICIT_REALLOC
+#endif
+
+BERRY_API void* be_os_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+BERRY_API void be_os_free(void *ptr)
+{
+ free(ptr);
+}
+
+BERRY_API void* be_os_realloc(void *ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+
+static void* _realloc(void *ptr, size_t old_size, size_t new_size)
+{
+ if (old_size == new_size) { /* the block unchanged */
+ return ptr;
+ }
+ if (ptr && new_size) { /* realloc block */
+ return realloc(ptr, new_size);
+ }
+ if (new_size) { /* alloc a new block */
+ be_assert(ptr == NULL && old_size == 0);
+ return malloc(new_size);
+ }
+ be_assert(new_size == 0);
+
+#if BE_USE_DEBUG_GC
+ memset(ptr, 0xFF, old_size); /* fill the structure with invalid pointers */
+#endif
+ free(ptr);
+ return NULL;
+}
+
+BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size)
+{
+ void *block = _realloc(ptr, old_size, new_size);
+ if (!block && new_size) { /* allocation failure */
+ vm->gc.status |= GC_ALLOC;
+ be_gc_collect(vm); /* try to allocate again after GC */
+ vm->gc.status &= ~GC_ALLOC;
+ block = _realloc(ptr, old_size, new_size);
+ if (!block) { /* lack of heap space */
+ be_throw(vm, BE_MALLOC_FAIL);
+ }
+ }
+ vm->gc.usage = vm->gc.usage + new_size - old_size; /* update allocated count */
+ return block;
+}
diff --git a/lib/libesp32/berry/src/be_mem.h b/lib/libesp32/berry/src/be_mem.h
new file mode 100644
index 000000000..88d305862
--- /dev/null
+++ b/lib/libesp32/berry/src/be_mem.h
@@ -0,0 +1,29 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_MEM_H
+#define BE_MEM_H
+
+#include "berry.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define be_malloc(vm, size) be_realloc((vm), NULL, 0, (size))
+#define be_free(vm, ptr, size) be_realloc((vm), (ptr), (size), 0)
+
+BERRY_API void* be_os_malloc(size_t size);
+BERRY_API void be_os_free(void *ptr);
+BERRY_API void* be_os_realloc(void *ptr, size_t size);
+BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesp32/berry/src/be_module.c b/lib/libesp32/berry/src/be_module.c
new file mode 100644
index 000000000..0256809af
--- /dev/null
+++ b/lib/libesp32/berry/src/be_module.c
@@ -0,0 +1,467 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_module.h"
+#include "be_string.h"
+#include "be_strlib.h"
+#include "be_list.h"
+#include "be_exec.h"
+#include "be_map.h"
+#include "be_gc.h"
+#include "be_mem.h"
+#include "be_vm.h"
+#include
+
+/* the maximum suffix length */
+#define SUFFIX_LEN 5 /* length of (.be .bec .so .dll) + 1 */
+
+/* check POSIX platforms */
+#if defined(__linux__) || \
+ defined(__APPLE__) || defined(__unix__) || defined(__CYGWIN__)
+ #define __POSIX_OS__
+#endif
+
+#if BE_USE_SHARED_LIB
+ #if defined(__POSIX_OS__)
+ #define DLL_SUFFIX ".so"
+ #elif defined(_WIN32)
+ #define DLL_SUFFIX ".dll"
+ #else
+ #define DLL_SUFFIX ""
+ #warning module: unsuppord OS
+ #endif
+#endif
+
+extern BERRY_LOCAL const bntvmodule* const be_module_table[];
+
+static bmodule* native_module(bvm *vm, const bntvmodule *nm, bvalue *dst);
+
+static const bntvmodule* find_native(bstring *path)
+{
+ const bntvmodule *module;
+ const bntvmodule* const *node = be_module_table;
+ for (; (module = *node) != NULL; ++node) {
+ if (!strcmp(module->name, str(path))) {
+ return module;
+ }
+ }
+ return NULL;
+}
+
+static void insert_attrs(bvm *vm, bmap *table, const bntvmodule *nm)
+{
+ size_t i;
+ for (i = 0; i < nm->size; ++i) {
+ const bntvmodobj *node = nm->attrs + i;
+ bstring *name = be_newstr(vm, node->name);
+ bvalue *v = be_map_insertstr(vm, table, name, NULL);
+ be_assert(node->type <= BE_CMODULE);
+ switch (node->type) {
+ case BE_CNIL:
+ var_setnil(v);
+ break;
+ case BE_CINT:
+ var_setint(v, node->u.i);
+ break;
+ case BE_CREAL:
+ var_setreal(v, node->u.r);
+ break;
+ case BE_CBOOL:
+ var_setbool(v, node->u.b);
+ break;
+ case BE_CFUNCTION:
+ var_setntvfunc(v, node->u.f);
+ break;
+ case BE_CSTRING:
+ var_setstr(v, be_newstr(vm, node->u.s));
+ break;
+ case BE_CMODULE:
+ native_module(vm, node->u.o, v);
+ break;
+ default: /* error */
+ break;
+ }
+ }
+}
+
+static bmodule* new_module(bvm *vm, const bntvmodule *nm)
+{
+ bgcobject *gco = be_gcnew(vm, BE_MODULE, bmodule);
+ bmodule *obj = cast_module(gco);
+ if (obj) {
+ var_setmodule(vm->top, obj);
+ be_incrtop(vm);
+ obj->info.native = nm;
+ obj->table = NULL; /* gc protection */
+ obj->table = be_map_new(vm);
+ insert_attrs(vm, obj->table, nm);
+ be_map_compact(vm, obj->table); /* clear space */
+ be_stackpop(vm, 1);
+ }
+ return obj;
+}
+
+static bmodule* native_module(bvm *vm, const bntvmodule *nm, bvalue *dst)
+{
+ if (nm) {
+ bmodule *obj;
+ if (nm->module) {
+ obj = (bmodule *)nm->module;
+ } else { /* new module */
+ obj = new_module(vm, nm);
+ }
+ if (obj && dst) {
+ var_setmodule(dst, obj);
+ }
+ return obj;
+ }
+ return NULL;
+}
+
+static char* fixpath(bvm *vm, bstring *path, size_t *size)
+{
+ char *buffer;
+ const char *split, *base;
+ bvalue *func = vm->cf->func;
+ bclosure *cl = var_toobj(func);
+ be_assert(var_isclosure(func));
+ base = str(cl->proto->source); /* get the source file path */
+ split = be_splitpath(base);
+ *size = split - base + (size_t)str_len(path) + SUFFIX_LEN;
+ buffer = be_malloc(vm, *size);
+ strncpy(buffer, base, split - base);
+ strcpy(buffer + (split - base), str(path));
+ return buffer;
+}
+
+static char* conpath(bvm *vm, bstring *path1, bstring *path2, size_t *size)
+{
+ char *buffer;
+ int len1 = str_len(path1);
+ *size = (size_t)len1 + (size_t)str_len(path2) + 1 + SUFFIX_LEN;
+ buffer = be_malloc(vm, *size);
+ strcpy(buffer, str(path1));
+ buffer[len1] = '/';
+ strcpy(buffer + len1 + 1, str(path2));
+ return buffer;
+}
+
+static int open_script(bvm *vm, char *path)
+{
+ int res = be_loadmodule(vm, path);
+ if (res == BE_OK)
+ be_call(vm, 0);
+ return res;
+}
+
+#if BE_USE_SHARED_LIB
+static int open_dllib(bvm *vm, char *path)
+{
+ int res = be_loadlib(vm, path);
+ if (res == BE_OK)
+ be_call(vm, 0);
+ return res;
+}
+#endif
+
+static int open_libfile(bvm *vm, char *path, size_t size)
+{
+ int res, idx = 0;
+ const char *sfxs[] = { "", ".bec", ".be" };
+ do {
+ strcpy(path + size - SUFFIX_LEN, sfxs[idx]);
+ res = open_script(vm, path);
+ } while (idx++ < 2 && res == BE_IO_ERROR);
+ if (res == BE_IO_ERROR) {
+#if BE_USE_SHARED_LIB
+ strcpy(path + size - SUFFIX_LEN, DLL_SUFFIX);
+ res = open_dllib(vm, path);
+#endif
+ }
+ be_free(vm, path, size);
+ return res;
+}
+
+static int load_path(bvm *vm, bstring *path, bstring *mod)
+{
+ size_t size;
+ char *fullpath = conpath(vm, path, mod, &size);
+ return open_libfile(vm, fullpath, size);
+}
+
+static int load_cwd(bvm *vm, bstring *path)
+{
+ size_t size;
+ char *fullpath = fixpath(vm, path, &size);
+ return open_libfile(vm, fullpath, size);
+}
+
+static int load_package(bvm *vm, bstring *path)
+{
+ int res = load_cwd(vm, path); /* load from current directory */
+ if (res == BE_IO_ERROR && vm->module.path) {
+ blist *list = vm->module.path;
+ bvalue *v = be_list_end(list) - 1;
+ bvalue *first = be_list_data(list);
+ for (; res == BE_IO_ERROR && v >= first; v--) {
+ if (var_isstr(v)) {
+ res = load_path(vm, var_tostr(v), path);
+ }
+ }
+ }
+ return res;
+}
+
+static int load_native(bvm *vm, bstring *path)
+{
+ const bntvmodule *nm = find_native(path);
+ bmodule *mod = native_module(vm, nm, NULL);
+ if (mod != NULL) {
+ /* the pointer vm->top may be changed */
+ var_setmodule(vm->top, mod);
+ be_incrtop(vm);
+ return BE_OK;
+ }
+ return BE_IO_ERROR;
+}
+
+static bvalue* load_cached(bvm *vm, bstring *path)
+{
+ bvalue *v = NULL;
+ if (vm->module.loaded) {
+ v = be_map_findstr(vm, vm->module.loaded, path);
+ if (v) {
+ *vm->top = *v;
+ be_incrtop(vm);
+ }
+ }
+ return v;
+}
+
+static void cache_module(bvm *vm, bstring *name)
+{
+ bvalue *v;
+ if (vm->module.loaded == NULL) {
+ vm->module.loaded = be_map_new(vm);
+ }
+ v = be_map_insertstr(vm, vm->module.loaded, name, NULL);
+ *v = vm->top[-1];
+}
+
+/* Try to run '()' function of module. Module is already loaded. */
+static void module_init(bvm *vm) {
+ if (be_ismodule(vm, -1)) {
+ if (be_getmember(vm, -1, "init")) {
+ /* found, call it with current module as parameter */
+ be_pushvalue(vm, -2);
+ be_call(vm, 1);
+ /* the result of init() is cached and returned */
+ be_pop(vm, 1);
+ be_remove(vm, -2); /* remove initial module */
+ } else {
+ be_pop(vm, 1);
+ }
+ }
+}
+
+/* load module to vm->top */
+int be_module_load(bvm *vm, bstring *path)
+{
+ int res = BE_OK;
+ if (!load_cached(vm, path)) {
+ res = load_native(vm, path);
+ if (res == BE_IO_ERROR)
+ res = load_package(vm, path);
+ if (res == BE_OK) {
+ /* on first load of the module, try running the '()' function */
+ module_init(vm);
+ cache_module(vm, path);
+ }
+ }
+ return res;
+}
+
+BERRY_API bbool be_getmodule(bvm *vm, const char *k)
+{
+ int res = be_module_load(vm, be_newstr(vm, k));
+ return res == BE_OK;
+}
+
+bmodule* be_module_new(bvm *vm)
+{
+ bgcobject *gco = be_gcnew(vm, BE_MODULE, bmodule);
+ bmodule *obj = cast_module(gco);
+ if (obj) {
+ var_setmodule(vm->top, obj);
+ be_incrtop(vm);
+ obj->info.native = NULL;
+ obj->table = NULL; /* gc protection */
+ obj->table = be_map_new(vm);
+ be_stackpop(vm, 1);
+ }
+ return obj;
+}
+
+void be_module_delete(bvm *vm, bmodule *module)
+{
+ be_free(vm, module, sizeof(bmodule));
+}
+
+int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst)
+{
+ bvalue *member = be_map_findstr(vm, module->table, attr);
+ if (!member) { /* try the 'member' function */
+ member = be_map_findstr(vm, module->table, str_literal(vm, "member"));
+ if (member && var_basetype(member) == BE_FUNCTION) {
+ bvalue *top = vm->top;
+ top[0] = *member;
+ var_setstr(&top[1], attr);
+ vm->top += 2; /* prevent collection results */
+ be_dofunc(vm, top, 1); /* call method 'method' */
+ vm->top -= 2;
+ *dst = *vm->top; /* copy result to R(A) */
+ if (var_basetype(dst) != BE_NIL) {
+ return var_type(dst);
+ }
+ }
+ return BE_NONE;
+ } else {
+ *dst = *member;
+ return var_type(dst);
+ }
+}
+
+bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src)
+{
+ assert(src);
+ bmap *attrs = module->table;
+ if (!gc_isconst(attrs)) {
+ bvalue *v = be_map_findstr(vm, attrs, attr);
+ if (v == NULL) {
+ v = be_map_insertstr(vm, attrs, attr, NULL);
+ }
+ if (v) {
+ *v = *src;
+ return btrue;
+ }
+ } else {
+ /* if not writable, try 'setmember' */
+ int type = be_module_attr(vm, module, str_literal(vm, "setmember"), vm->top);
+ if (basetype(type) == BE_FUNCTION) {
+ bvalue *top = vm->top;
+ // top[0] already has 'member'
+ var_setstr(&top[1], attr); /* attribute name */
+ top[2] = *src; /* new value */
+ vm->top += 3; /* prevent collection results */
+ be_dofunc(vm, top, 2); /* call method 'setmember' */
+ vm->top -= 3;
+ return btrue;
+ }
+ }
+ return bfalse;
+}
+
+const char* be_module_name(bmodule *module)
+{
+ if (gc_isconst(module)) {
+ return module->info.name;
+ }
+ if (gc_exmark(module) & BE_MODULE_NAME) {
+ return str(module->info.sname);
+ }
+ if (module->info.native) {
+ return module->info.native->name;
+ }
+ return NULL;
+}
+
+bbool be_module_setname(bmodule *module, bstring *name)
+{
+ if (!gc_isconst(module)) {
+ module->info.sname = name;
+ gc_setexmark(module, BE_MODULE_NAME);
+ return btrue;
+ }
+ return bfalse;
+}
+
+static blist* pathlist(bvm *vm)
+{
+ if (!vm->module.path) {
+ vm->module.path = be_list_new(vm);
+ }
+ return vm->module.path;
+}
+
+/* push the path list to the top */
+BERRY_API void be_module_path(bvm *vm)
+{
+ blist *list = pathlist(vm);
+ bvalue *reg = be_incrtop(vm);
+ var_setlist(reg, list);
+}
+
+BERRY_API void be_module_path_set(bvm *vm, const char *path)
+{
+ blist *list = pathlist(vm);
+ bvalue *value = be_list_push(vm, list, NULL);
+ var_setnil(value);
+ var_setstr(value, be_newstr(vm, path))
+}
+
+/* shared library support */
+#if BE_USE_SHARED_LIB
+
+#if defined(__POSIX_OS__)
+#include
+
+#if defined(__GNUC__)
+ #define cast_func(f) (__extension__(bntvfunc)(f))
+#else
+ #define cast_func(f) ((bntvfunc)(f))
+#endif
+
+/* load shared library */
+BERRY_API int be_loadlib(bvm *vm, const char *path)
+{
+ void *handle = dlopen(path, RTLD_LAZY);
+ bntvfunc func = cast_func(dlsym(handle, "berry_export"));
+ if (func == NULL) {
+ return BE_IO_ERROR;
+ }
+ be_pushntvfunction(vm, func);
+ return BE_OK;
+}
+#elif defined(_WIN32)
+#include
+#include
+
+BERRY_API int be_loadlib(bvm *vm, const char *path)
+{
+ HINSTANCE handle = LoadLibrary(path);
+ if (handle) {
+ union {
+ FARPROC proc;
+ bntvfunc func;
+ } u;
+ u.proc = GetProcAddress(handle, "berry_export");
+ if (u.func != NULL) {
+ be_pushntvfunction(vm, u.func);
+ return BE_OK;
+ }
+ }
+ return BE_IO_ERROR;
+}
+#else
+BERRY_API int be_loadlib(bvm *vm, const char *path)
+{
+ (void)vm, (void)path;
+ return BE_IO_ERROR;
+}
+#endif
+
+#endif /* BE_USE_SHARED_LIB */
diff --git a/lib/libesp32/berry/src/be_module.h b/lib/libesp32/berry/src/be_module.h
new file mode 100644
index 000000000..4f9b869de
--- /dev/null
+++ b/lib/libesp32/berry/src/be_module.h
@@ -0,0 +1,42 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_MODULE_H
+#define BE_MODULE_H
+
+#include "be_object.h"
+
+#define BE_MODULE_NAME 1
+
+typedef struct bmodule {
+ bcommon_header;
+ bmap *table;
+ union infodata {
+ const bntvmodule *native;
+ const char *name;
+ const bstring *sname;
+#ifdef __cplusplus
+ BE_CONSTEXPR infodata(const char *name) : name(name) {}
+#endif
+ } info;
+ bgcobject *gray; /* for gc gray list */
+#ifdef __cplusplus
+ BE_CONSTEXPR bmodule(bmap *tab, const char *name) :
+ next(0), type(BE_MODULE), marked(GC_CONST),
+ table(tab), info(infodata(name)), gray(0) {}
+#endif
+} bmodule;
+
+bmodule* be_module_new(bvm *vm);
+void be_module_delete(bvm *vm, bmodule *module);
+int be_module_load(bvm *vm, bstring *path);
+int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst);
+bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src);
+const char* be_module_name(bmodule *module);
+bbool be_module_setname(bmodule *module, bstring *name);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_object.c b/lib/libesp32/berry/src/be_object.c
new file mode 100644
index 000000000..6c246231c
--- /dev/null
+++ b/lib/libesp32/berry/src/be_object.c
@@ -0,0 +1,73 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_exec.h"
+#include "be_mem.h"
+#include "be_gc.h"
+#include "be_vm.h"
+
+#define cast_comobj(o) gc_cast(o, BE_COMOBJ, bcommomobj)
+
+const char* be_vtype2str(bvalue *v)
+{
+ switch(var_type(v)) {
+ case BE_NIL: return "nil";
+ case BE_INT: return "int";
+ case BE_REAL: return "real";
+ case BE_BOOL: return "bool";
+ case BE_CLOSURE: case BE_NTVCLOS:
+ case BE_NTVFUNC: return "function";
+ case BE_PROTO: return "proto";
+ case BE_CLASS: return "class";
+ case BE_STRING: return "string";
+ case BE_LIST: return "list";
+ case BE_MAP: return "map";
+ case BE_INSTANCE: return "instance";
+ case BE_MODULE: return "module";
+ case BE_INDEX: return "var";
+ case BE_COMPTR: return "ptr";
+ default: return "invalid type";
+ }
+}
+
+bvalue* be_indexof(bvm *vm, int idx)
+{
+ if (idx > 0) { /* absolute index */
+ be_assert(vm->reg + idx <= vm->top);
+ return vm->reg + idx - 1;
+ }
+ /* relative index */
+ be_assert(vm->top + idx >= vm->reg);
+ return vm->top + idx;
+}
+
+BERRY_API void be_newcomobj(bvm *vm, void *data, bntvfunc destory)
+{
+ bcommomobj *obj;
+ bgcobject *gco = be_gcnew(vm, BE_COMOBJ, bcommomobj);
+ if ((obj = cast_comobj(gco)) != NULL) {
+ bvalue* top = be_incrtop(vm);
+ obj->data = data;
+ obj->destory = destory;
+ var_setobj(top, BE_COMOBJ, obj);
+ }
+}
+
+void be_commonobj_delete(bvm *vm, bgcobject *obj)
+{
+ bcommomobj *co = cast_comobj(obj);
+ if (co) {
+ if (co->destory && co->data) {
+ be_pushntvfunction(vm, co->destory);
+ be_pushcomptr(vm, co->data);
+ be_call(vm, 1);
+ be_pop(vm, 2);
+ }
+ be_free(vm, co, sizeof(bcommomobj));
+ }
+}
diff --git a/lib/libesp32/berry/src/be_object.h b/lib/libesp32/berry/src/be_object.h
new file mode 100644
index 000000000..e19d766d6
--- /dev/null
+++ b/lib/libesp32/berry/src/be_object.h
@@ -0,0 +1,254 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_OBJECT_H
+#define BE_OBJECT_H
+
+#include "berry.h"
+
+/* basic types, do not change value */
+#define BE_NIL 0
+#define BE_INT 1
+#define BE_REAL 2
+#define BE_BOOL 3
+#define BE_NONE 4 /* unknown type */
+#define BE_COMPTR 5 /* common pointer */
+#define BE_INDEX 6 /* index for instance variable, previously BE_INT */
+#define BE_FUNCTION 7
+
+#define BE_GCOBJECT 16 /* from this type can be gced */
+
+#define BE_STRING 16
+#define BE_CLASS 17
+#define BE_INSTANCE 18
+#define BE_PROTO 19
+#define BE_LIST 20
+#define BE_MAP 21
+#define BE_MODULE 22
+#define BE_COMOBJ 23 /* common object */
+
+#define BE_NTVFUNC ((0 << 5) | BE_FUNCTION)
+#define BE_CLOSURE ((1 << 5) | BE_FUNCTION)
+#define BE_NTVCLOS ((2 << 5) | BE_FUNCTION)
+#define BE_FUNC_STATIC (1 << 7)
+
+#define func_isstatic(o) (((o)->type & BE_FUNC_STATIC) != 0)
+#define func_setstatic(o) ((o)->type |= BE_FUNC_STATIC)
+#define func_clearstatic(o) ((o)->type &= ~BE_FUNC_STATIC)
+
+#define array_count(a) (sizeof(a) / sizeof((a)[0]))
+
+#define bcommon_header \
+ struct bgcobject *next; \
+ bbyte type; \
+ bbyte marked
+
+#define bstring_header \
+ bcommon_header; \
+ bbyte extra; \
+ bbyte slen
+
+typedef struct bgcobject {
+ bcommon_header;
+} bgcobject;
+
+typedef struct bclosure bclosure;
+typedef struct bntvclos bntvclos;
+typedef struct bclass bclass;
+typedef struct binstance binstance;
+typedef struct blist blist;
+typedef struct bmap bmap;
+typedef struct bupval bupval;
+
+typedef uint32_t binstruction;
+
+typedef struct bstring {
+ bstring_header;
+} bstring;
+
+/* the definition of the vector and stack data structures.
+ * in fact, the stack is implemented by vector. */
+typedef struct bvector {
+ int capacity; /* the number of elements that the vector can store */
+ int size; /* the size of each element (bytes) */
+ int count; /* number of elements of the vector */
+ void *data; /* the data block pointer, if vector is empty,
+ it will point to the first element */
+ void *end; /* pointer to the last element, if the vector is empty,
+ the end pointer will be smaller than the data pointer */
+} bvector, bstack;
+
+/* berry value data union, a berry value is always described
+ * by the data structure contained in the bvaldata union. */
+union bvaldata {
+ bbool b; /* boolean */
+ breal r; /* real number */
+ bint i; /* integer number */
+ void *p; /* object pointer */
+ const void *c; /* const object pointer */
+ bstring *s; /* string pointer */
+ bgcobject *gc; /* GC object */
+ bntvfunc nf; /* native C function */
+#ifdef __cplusplus
+ BE_CONSTEXPR bvaldata(bbool v) : b(v) {}
+ BE_CONSTEXPR bvaldata(breal v) : r(v) {}
+ BE_CONSTEXPR bvaldata(bint v) : i(v) {}
+ BE_CONSTEXPR bvaldata(void *v) : p(v) {}
+ BE_CONSTEXPR bvaldata(const void *v) : c(v) {}
+ BE_CONSTEXPR bvaldata(bntvfunc v) : nf(v) {}
+#endif
+};
+
+/* berry value. for simple types, the value of the data is stored,
+ * while the complex type stores a reference to the data. */
+typedef struct bvalue {
+ union bvaldata v; /* the value data */
+ int type; /* the value type */
+} bvalue;
+
+typedef struct {
+#if BE_DEBUG_VAR_INFO
+ bstring *name;
+#endif
+ bbyte instack;
+ bbyte idx;
+} bupvaldesc;
+
+typedef struct {
+#if BE_DEBUG_RUNTIME_INFO > 1
+ uint16_t linenumber;
+ uint16_t endpc;
+#else
+ int linenumber;
+ int endpc;
+#endif
+} blineinfo;
+
+typedef struct {
+ bstring *name;
+#if BE_DEBUG_RUNTIME_INFO > 1
+ uint16_t beginpc;
+ uint16_t endpc;
+#else
+ int beginpc;
+ int endpc;
+#endif
+} bvarinfo;
+
+typedef struct bproto {
+ bcommon_header;
+ bbyte nstack; /* number of stack size by this function */
+ bbyte nupvals; /* upvalue count */
+ bbyte argc; /* argument count */
+ bbyte varg; /* variable argument position + 1 */
+ bgcobject *gray; /* for gc gray list */
+ bupvaldesc *upvals;
+ bvalue *ktab; /* constants table */
+ struct bproto **ptab; /* proto table */
+ binstruction *code; /* instructions sequence */
+ bstring *name; /* function name */
+ int codesize; /* code size */
+ int nconst; /* constants count */
+ int nproto; /* proto count */
+ bstring *source; /* source file name */
+#if BE_DEBUG_RUNTIME_INFO /* debug information */
+ blineinfo *lineinfo;
+ int nlineinfo;
+#endif
+#if BE_DEBUG_VAR_INFO
+ bvarinfo *varinfo;
+ int nvarinfo;
+#endif
+} bproto;
+
+/* berry closure */
+struct bclosure {
+ bcommon_header;
+ bbyte nupvals;
+ bgcobject *gray; /* for gc gray list */
+ bproto *proto;
+ bupval *upvals[1];
+};
+
+/* C native function or closure */
+struct bntvclos {
+ bcommon_header;
+ bbyte nupvals;
+ bgcobject *gray; /* for gc gray list */
+ bntvfunc f;
+};
+
+/* common object */
+typedef struct {
+ bcommon_header;
+ void *data;
+ bntvfunc destory;
+} bcommomobj;
+
+typedef const char* (*breader)(void*, size_t*);
+
+#define cast(_T, _v) ((_T)(_v))
+#define cast_int(_v) cast(int, _v)
+#define cast_bool(_v) cast(bbool, _v)
+#define basetype(_t) ((_t) & 0x1F)
+
+#define var_type(_v) ((_v)->type & 0x7F)
+#define var_basetype(_v) basetype((_v)->type)
+#define var_istype(_v, _t) (var_type(_v) == _t)
+#define var_settype(_v, _t) ((_v)->type = _t)
+#define var_setobj(_v, _t, _o) { (_v)->v.p = _o; var_settype(_v, _t); }
+
+#define var_isnil(_v) var_istype(_v, BE_NIL)
+#define var_isbool(_v) var_istype(_v, BE_BOOL)
+#define var_isint(_v) var_istype(_v, BE_INT)
+#define var_isreal(_v) var_istype(_v, BE_REAL)
+#define var_isstr(_v) var_istype(_v, BE_STRING)
+#define var_isclosure(_v) var_istype(_v, BE_CLOSURE)
+#define var_isntvclos(_v) var_istype(_v, BE_NTVCLOS)
+#define var_isntvfunc(_v) var_istype(_v, BE_NTVFUNC)
+#define var_isfunction(_v) (var_basetype(_v) == BE_FUNCTION)
+#define var_isproto(_v) var_istype(_v, BE_PROTO)
+#define var_isclass(_v) var_istype(_v, BE_CLASS)
+#define var_isinstance(_v) var_istype(_v, BE_INSTANCE)
+#define var_islist(_v) var_istype(_v, BE_LIST)
+#define var_ismap(_v) var_istype(_v, BE_MAP)
+#define var_ismodule(_v) var_istype(_v, BE_MODULE)
+#define var_isindex(_v) var_istype(_v, BE_INDEX)
+#define var_iscomptr(_v) var_istype(_v, BE_COMPTR)
+#define var_isnumber(_v) (var_isint(_v) || var_isreal(_v))
+
+#define var_setnil(_v) var_settype(_v, BE_NIL)
+#define var_setval(_v, _s) (*(_v) = *(_s))
+#define var_setbool(_v, _b) { var_settype(_v, BE_BOOL); (_v)->v.b = (bbool)(_b); }
+#define var_setint(_v, _i) { var_settype(_v, BE_INT); (_v)->v.i = (_i); }
+#define var_setreal(_v, _r) { var_settype(_v, BE_REAL); (_v)->v.r = (_r); }
+#define var_setstr(_v, _s) var_setobj(_v, BE_STRING, _s)
+#define var_setinstance(_v, _o) var_setobj(_v, BE_INSTANCE, _o)
+#define var_setclass(_v, _o) var_setobj(_v, BE_CLASS, _o)
+#define var_setclosure(_v, _o) var_setobj(_v, BE_CLOSURE, _o)
+#define var_setntvclos(_v, _o) var_setobj(_v, BE_NTVCLOS, _o)
+#define var_setntvfunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_NTVFUNC); }
+#define var_setlist(_v, _o) var_setobj(_v, BE_LIST, _o)
+#define var_setmap(_v, _o) var_setobj(_v, BE_MAP, _o)
+#define var_setmodule(_v, _o) var_setobj(_v, BE_MODULE, _o)
+#define var_setindex(_v, _i) { var_settype(_v, BE_INDEX); (_v)->v.i = (_i); }
+#define var_setproto(_v, _o) var_setobj(_v, BE_PROTO, _o)
+
+#define var_tobool(_v) ((_v)->v.b)
+#define var_toint(_v) ((_v)->v.i)
+#define var_toreal(_v) ((_v)->v.r)
+#define var_tostr(_v) ((_v)->v.s)
+#define var_togc(_v) ((_v)->v.gc)
+#define var_toobj(_v) ((_v)->v.p)
+#define var_tontvfunc(_v) ((_v)->v.nf)
+#define var_toidx(_v) cast_int(var_toint(_v))
+
+const char* be_vtype2str(bvalue *v);
+bvalue* be_indexof(bvm *vm, int idx);
+void be_commonobj_delete(bvm *vm, bgcobject *obj);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_opcodes.h b/lib/libesp32/berry/src/be_opcodes.h
new file mode 100644
index 000000000..12c3781e0
--- /dev/null
+++ b/lib/libesp32/berry/src/be_opcodes.h
@@ -0,0 +1,57 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+/* define opcode, don't change order */
+/* opcode parameters description */
+OPCODE(ADD), /* A, B, C | R(A) <- RK(B) + RK(C) */
+OPCODE(SUB), /* A, B, C | R(A) <- RK(B) - RK(C) */
+OPCODE(MUL), /* A, B, C | R(A) <- RK(B) * RK(C) */
+OPCODE(DIV), /* A, B, C | R(A) <- RK(B) / RK(C) */
+OPCODE(MOD), /* A, B, C | R(A) <- RK(B) % RK(C) */
+OPCODE(LT), /* A, B, C | R(A) <- RK(B) < RK(C) */
+OPCODE(LE), /* A, B, C | R(A) <- RK(B) <= RK(C) */
+OPCODE(EQ), /* A, B, C | R(A) <- RK(B) == RK(C) */
+OPCODE(NE), /* A, B, C | R(A) <- RK(B) != RK(C) */
+OPCODE(GT), /* A, B, C | R(A) <- RK(B) > RK(C) */
+OPCODE(GE), /* A, B, C | R(A) <- RK(B) >= RK(C) */
+OPCODE(AND), /* A, B, C | R(A) <- RK(B) & RK(C) */
+OPCODE(OR), /* A, B, C | R(A) <- RK(B) | RK(C) */
+OPCODE(XOR), /* A, B, C | R(A) <- RK(B) ^ RK(C) */
+OPCODE(SHL), /* A, B, C | R(A) <- RK(B) << RK(C) */
+OPCODE(SHR), /* A, B, C | R(A) <- RK(B) >> RK(C) */
+OPCODE(CONNECT), /* A, B, C | R(A) <- connect(RK(B), RK(C)) */
+OPCODE(NEG), /* A, B | R(A) <- -RK(B) */
+OPCODE(FLIP), /* A, B | R(A) <- ~RK(B) */
+OPCODE(LDNIL), /* A | R(A) <- nil */
+OPCODE(LDBOOL), /* A, B, C | R(A) <- cast_bool(B), if(C): pc++ */
+OPCODE(LDINT), /* A, sBx | R(A) <- sBx */
+OPCODE(LDCONST), /* A, Bx | R(A) <- K(Bx) */
+OPCODE(MOVE), /* A, B, C | R(A) <- RK(B) */
+OPCODE(GETGBL), /* A, Bx | R(A) <- GLOBAL(Bx) */
+OPCODE(SETGBL), /* A, Bx | R(A) -> GLOBAL(Bx) */
+OPCODE(GETUPV), /* A, Bx | R(A) <- UPVALUE(Bx)*/
+OPCODE(SETUPV), /* A, Bx | R(A) -> UPVALUE(Bx)*/
+OPCODE(JMP), /* sBx | pc <- pc + sBx */
+OPCODE(JMPT), /* A, sBx | if(R(A)): pc <- pc + sBx */
+OPCODE(JMPF), /* A, sBx | if(not R(A)): pc <- pc + sBx */
+OPCODE(CALL), /* A, B | CALL(R(A), B) */
+OPCODE(RET), /* A, B | if (R(A)) R(-1) <- RK(B) else R(-1) <- nil */
+OPCODE(CLOSURE), /* A, Bx | R(A) <- CLOSURE(proto_table[Bx])*/
+OPCODE(GETMBR), /* A, B, C | R(A) <- RK(B).RK(C) */
+OPCODE(GETMET), /* A, B, C | R(A) <- RK(B).RK(C), R(A+1) <- RK(B) */
+OPCODE(SETMBR), /* A, B, C | R(A).RK(B) <- RK(C) */
+OPCODE(GETIDX), /* A, B, C | R(A) <- RK(B)[RK(C)] */
+OPCODE(SETIDX), /* A, B, C | R(A)[RK(B)] <- RK(C) */
+OPCODE(SETSUPER), /* A, B | class:R(A) set super with class:RK(B) */
+OPCODE(CLOSE), /* A | close upvalues */
+OPCODE(IMPORT), /* A, B, C | IF (A == C) import module name as RK(B) to RK(A), ELSE from module RK(C) import name as RK(B) to RK(A) */
+OPCODE(EXBLK), /* A, Bx | ... */
+OPCODE(CATCH), /* A, B, C | ... */
+OPCODE(RAISE), /* A, B, C | RAISE(B,C) B is code, C is description. A==0 only B provided, A==1 B and C are provided, A==2 rethrow with both parameters already on stack */
+OPCODE(CLASS), /* Bx | init class in K[Bx] */
+OPCODE(GETNGBL), /* A, B | R(A) <- GLOBAL[RK(B)] by name */
+OPCODE(SETNGBL) /* A, B | R(A) -> GLOBAL[RK(B)] by name */
diff --git a/lib/libesp32/berry/src/be_oslib.c b/lib/libesp32/berry/src/be_oslib.c
new file mode 100644
index 000000000..1d4f029c2
--- /dev/null
+++ b/lib/libesp32/berry/src/be_oslib.c
@@ -0,0 +1,271 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_strlib.h"
+#include "be_mem.h"
+#include "be_sys.h"
+#include
+#include
+
+#define FNAME_BUF_SIZE 512
+
+#if BE_USE_OS_MODULE
+
+#if !BE_USE_FILE_SYSTEM
+ #error the dependent macro BE_USE_FILE_SYSTEM must be enabled
+#endif
+
+static int m_getcwd(bvm *vm)
+{
+ char *buf = be_malloc(vm, FNAME_BUF_SIZE);
+ if (be_getcwd(buf, FNAME_BUF_SIZE)) {
+ be_pushstring(vm, buf);
+ } else {
+ be_pushstring(vm, "");
+ }
+ be_free(vm, buf, FNAME_BUF_SIZE);
+ be_return(vm);
+}
+
+static int m_chdir(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ int res = be_chdir(be_tostring(vm, 1));
+ be_pushbool(vm, res == 0);
+ }
+ be_return(vm);
+}
+
+static int m_mkdir(bvm *vm)
+{
+ int res = 1;
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ res = be_mkdir(be_tostring(vm, 1));
+ }
+ be_pushbool(vm, res == 0);
+ be_return(vm);
+}
+
+static int m_remove(bvm *vm)
+{
+ int res = 1;
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ res = be_unlink(be_tostring(vm, 1));
+ }
+ be_pushbool(vm, res == 0);
+ be_return(vm);
+}
+
+static int m_listdir(bvm *vm)
+{
+ int res;
+ bdirinfo info;
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ res = be_dirfirst(&info, be_tostring(vm, 1));
+ } else {
+ res = be_dirfirst(&info, ".");
+ }
+ be_newobject(vm, "list");
+ while (res == 0) {
+ const char *fn = info.name;
+ if (strcmp(fn, ".") && strcmp(fn, "..")) {
+ be_pushstring(vm, fn);
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ }
+ res = be_dirnext(&info);
+ }
+ be_dirclose(&info);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+static int m_system(bvm *vm)
+{
+ int res = -1, i, argc = be_top(vm);
+ if (argc > 0) {
+ be_tostring(vm, 1);
+ be_pushstring(vm, " ");
+ for (i = 2; i <= argc; ++i) {
+ be_strconcat(vm, 1); /* add " " */
+ be_tostring(vm, i);
+ be_pushvalue(vm, i);
+ be_strconcat(vm, 1); /* concat arg */
+ be_pop(vm, 1);
+ }
+ be_pop(vm, argc);
+ res = system(be_tostring(vm, 1));
+ }
+ be_pushint(vm, res);
+ be_return(vm);
+}
+
+static int m_exit(bvm *vm)
+{
+ int status = 0;
+ if (be_top(vm)) {
+ if (be_isint(vm, 1)) {
+ status = be_toindex(vm, 1); /* get the exit code */
+ } else if (be_isbool(vm, 1)) {
+ status = be_tobool(vm, 1) - 1; /* true: 0, false: -1 */
+ } else {
+ status = -1;
+ }
+ }
+ be_exit(vm, status);
+ be_return_nil(vm);
+}
+
+static int m_path_isdir(bvm *vm)
+{
+ const char *path = NULL;
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ path = be_tostring(vm, 1);
+ }
+ be_pushbool(vm, be_isdir(path));
+ be_return(vm);
+}
+
+static int m_path_isfile(bvm *vm)
+{
+ const char *path = NULL;
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ path = be_tostring(vm, 1);
+ }
+ be_pushbool(vm, be_isfile(path));
+ be_return(vm);
+}
+
+static int m_path_split(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ const char *path = be_tostring(vm, 1);
+ const char *split = be_splitpath(path);
+ size_t len = split - path;
+ if (split > path + 1 && split[-1] == '/') {
+ const char *p = split - 1;
+ for (; p >= path && *p == '/'; --p);
+ if (p >= path) {
+ len = p - path + 1;
+ }
+ }
+ be_getbuiltin(vm, "list");
+ be_pushnstring(vm, path, len);
+ be_pushstring(vm, split);
+ be_call(vm, 2);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int m_path_splitext(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ const char *path = be_tostring(vm, 1);
+ const char *split = be_splitname(path);
+ be_getbuiltin(vm, "list");
+ be_pushnstring(vm, path, split - path);
+ be_pushstring(vm, split);
+ be_call(vm, 2);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int m_path_exists(bvm *vm)
+{
+ const char *path = NULL;
+ if (be_top(vm) >= 1 && be_isstring(vm, 1)) {
+ path = be_tostring(vm, 1);
+ }
+ be_pushbool(vm, be_isexist(path));
+ be_return(vm);
+}
+
+static int m_path_join(bvm *vm)
+{
+ char *buf, *p;
+ int i, len = 0, argc = be_top(vm);
+ for (i = 1; i <= argc; ++i) {
+ if (be_isstring(vm, i)) {
+ len += be_strlen(vm, i) + 1;
+ } else {
+ be_raise(vm, "type_error", "arguments must be string");
+ }
+ }
+ buf = p = be_malloc(vm, (size_t)len + 1);
+ for (i = 1; i <= argc; ++i) {
+ int l = be_strlen(vm, i);
+ const char *s = be_tostring(vm, i);
+ if (s[0] == '/') {
+ p = buf;
+ }
+ strcpy(p, s);
+ p += l;
+ if (l && s[l - 1] != '/' && i != argc) {
+ *p++ = '/';
+ }
+ }
+ be_pushnstring(vm, buf, p - buf);
+ be_free(vm, buf, (size_t)len + 1);
+ be_return(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(path) {
+ be_native_module_function("isdir", m_path_isdir),
+ be_native_module_function("isfile", m_path_isfile),
+ be_native_module_function("exists", m_path_exists),
+ be_native_module_function("split", m_path_split),
+ be_native_module_function("splitext", m_path_splitext),
+ be_native_module_function("join", m_path_join)
+};
+
+static be_define_native_module(path, NULL);
+
+be_native_module_attr_table(os) {
+ be_native_module_function("getcwd", m_getcwd),
+ be_native_module_function("chdir", m_chdir),
+ be_native_module_function("mkdir", m_mkdir),
+ be_native_module_function("remove", m_remove),
+ be_native_module_function("listdir", m_listdir),
+ be_native_module_function("system", m_system),
+ be_native_module_function("exit", m_exit),
+ be_native_module_module("path", be_native_module(path))
+};
+
+be_define_native_module(os, NULL);
+#else
+/* @const_object_info_begin
+module path (scope: local, file: os_path, depend: BE_USE_OS_MODULE) {
+ isdir, func(m_path_isdir)
+ isfile, func(m_path_isfile)
+ exists, func(m_path_exists)
+ split, func(m_path_split)
+ splitext, func(m_path_splitext)
+ join, func(m_path_join)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_os_path.h"
+
+/* @const_object_info_begin
+module os (scope: global, depend: BE_USE_OS_MODULE) {
+ getcwd, func(m_getcwd)
+ chdir, func(m_chdir)
+ mkdir, func(m_mkdir)
+ remove, func(m_remove)
+ listdir, func(m_listdir)
+ system, func(m_system)
+ exit, func(m_exit)
+ path, module(m_libpath)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_os.h"
+#endif
+
+#endif /* BE_USE_OS_MODULE */
diff --git a/lib/libesp32/berry/src/be_parser.c b/lib/libesp32/berry/src/be_parser.c
new file mode 100644
index 000000000..d2f2d7af5
--- /dev/null
+++ b/lib/libesp32/berry/src/be_parser.c
@@ -0,0 +1,1743 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_parser.h"
+#include "be_lexer.h"
+#include "be_vector.h"
+#include "be_mem.h"
+#include "be_vm.h"
+#include "be_map.h"
+#include "be_list.h"
+#include "be_var.h"
+#include "be_code.h"
+#include "be_string.h"
+#include "be_func.h"
+#include "be_class.h"
+#include "be_decoder.h"
+#include "be_debug.h"
+#include "be_exec.h"
+#include
+
+#define OP_NOT_BINARY TokenNone
+#define OP_NOT_UNARY TokenNone
+#define OP_NOT_ASSIGN TokenNone
+#define UNARY_OP_PRIO 3
+#define ASSIGN_OP_PRIO 16
+
+#define FUNC_METHOD 1
+#define FUNC_ANONYMOUS 2
+
+#if BE_INTGER_TYPE == 0 /* int */
+ #define M_IMAX INT_MAX
+ #define M_IMIN INT_MIN
+#elif BE_INTGER_TYPE == 1 /* long */
+ #define M_IMAX LONG_MAX
+ #define M_IMIN LONG_MIN
+#else /* int64_t (long long) */
+ #define M_IMAX LLONG_MAX
+ #define M_IMIN LLONG_MIN
+#endif
+
+/* get binary operator priority */
+#define binary_op_prio(op) (binary_op_prio_tab[cast_int(op) - OptAdd])
+
+#define scan_next_token(parser) (be_lexer_scan_next(&(parser)->lexer))
+#define next_token(parser) ((parser)->lexer.token)
+#define next_type(parser) (next_token(parser).type)
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define token2str(parser) be_token2str((parser)->vm, &next_token(parser))
+#define funcname(parser) ((parser)->islocal ? "loader" : "main")
+
+#define upval_index(v) ((v) & 0xFF)
+#define upval_target(v) ((bbyte)(((v) >> 8) & 0xFF))
+#define upval_instack(v) ((bbyte)(((v) >> 16) != 0))
+#define upval_desc(i, t, s) (((i) & 0xFF) | (((t) & 0xFF) << 8) \
+ | (((s) != 0) << 16))
+
+#define match_id(parser, s) ((s) = _match_id(parser))
+
+#define parser_newstr(p, str) be_lexer_newstr(&(p)->lexer, (str))
+
+#define parser_error(p, msg) be_lexerror(&(p)->lexer, msg)
+
+#define push_error(parser, ...) \
+ parser_error(parser, be_pushfstring(parser->vm, __VA_ARGS__))
+
+typedef struct {
+ blexer lexer;
+ bvm *vm;
+ bfuncinfo *finfo;
+ bclosure *cl;
+ bbyte islocal;
+} bparser;
+
+#if BE_USE_SCRIPT_COMPILER
+
+static void stmtlist(bparser *parser);
+static void block(bparser *parser, int type);
+static void expr(bparser *parser, bexpdesc *e);
+static void sub_expr(bparser *parser, bexpdesc *e, int prio);
+
+static const bbyte binary_op_prio_tab[] = {
+ 5, 5, 4, 4, 4, /* + - * / % */
+ 11, 11, 12, 12, 11, 11, /* < <= == != > >= */
+ 7, 9, 8, 6, 6, 10, 13, 14 /* & | ^ << >> .. && || */
+};
+
+static void match_token(bparser *parser, btokentype type)
+{
+ if (next_type(parser) != type) { /* error when token is no match */
+ btoken *token = &next_token(parser);
+ const char *s1 = be_tokentype2str(type);
+ const char *s2 = be_token2str(parser->vm, token);
+ push_error(parser, "expected '%s' before '%s'", s1, s2);
+ }
+ scan_next_token(parser); /* skip this token */
+}
+
+/* Check that the next token is not of type `type` */
+/* or raise an exception */
+static void match_notoken(bparser *parser, btokentype type)
+{
+ if (next_type(parser) == type) { /* error when token is match */
+ push_error(parser,
+ "expected statement before '%s'", token2str(parser));
+ }
+}
+
+/* check that if the expdesc is a symbol, it is a valid one or raise an exception */
+static void check_symbol(bparser *parser, bexpdesc *e)
+{
+ if (e->type == ETVOID && e->v.s == NULL) { /* error when token is not a symbol */
+ push_error(parser,
+ "unexpected symbol near '%s'", token2str(parser));
+ }
+}
+
+/* check that the value in `e` is valid for a variable, i.e. contains a value or a valid symbol */
+static void check_var(bparser *parser, bexpdesc *e)
+{
+ check_symbol(parser, e); /* check the token is a symbol */
+ if (e->type == ETVOID) { /* error when symbol is undefined */
+ int line = parser->lexer.linenumber;
+ parser->lexer.linenumber = parser->lexer.lastline;
+ push_error(parser,
+ "'%s' undeclared (first use in this function)", str(e->v.s));
+ parser->lexer.linenumber = line;
+ }
+}
+
+static int match_skip(bparser *parser, btokentype type)
+{
+ if (next_type(parser) == type) { /* match */
+ scan_next_token(parser); /* skip this token */
+ return btrue;
+ }
+ return bfalse;
+}
+
+static bstring* _match_id(bparser *parser)
+{
+ if (next_type(parser) == TokenId) {
+ bstring *str = next_token(parser).u.s;
+ scan_next_token(parser); /* skip ID */
+ return str;
+ }
+ return NULL;
+}
+
+#if BE_DEBUG_VAR_INFO
+
+void begin_varinfo(bparser *parser, bstring *name)
+{
+ bvarinfo *var;
+ bfuncinfo *finfo = parser->finfo;
+ be_vector_push_c(parser->vm, &finfo->varvec, NULL);
+ var = be_vector_end(&finfo->varvec);
+ var->name = name;
+ var->beginpc = finfo->pc;
+ var->endpc = 0; /* */
+ finfo->proto->varinfo = be_vector_data(&finfo->varvec);
+ finfo->proto->nvarinfo = be_vector_capacity(&finfo->varvec);
+}
+
+void end_varinfo(bparser *parser, int beginpc)
+{
+ bfuncinfo *finfo = parser->finfo;
+ bblockinfo *binfo = finfo->binfo;
+ bvarinfo *it = be_vector_data(&finfo->varvec);
+ bvarinfo *end = be_vector_end(&finfo->varvec);
+ if (beginpc == -1) /* use block->beginpc by default */
+ beginpc = binfo->beginpc;
+ /* skip the variable of the previous blocks */
+ for (; it->beginpc < beginpc; ++it);
+ for (; it <= end; ++it) {
+ if (!it->endpc) /* write to endpc only once */
+ it->endpc = finfo->pc;
+ }
+}
+
+#else
+
+#define begin_varinfo(parser, name)
+#define end_varinfo(parser, beginpc) (void)(beginpc)
+
+#endif
+
+/* Initialize bblockinfo structure */
+static void begin_block(bfuncinfo *finfo, bblockinfo *binfo, int type)
+{
+ binfo->prev = finfo->binfo; /* save previous block */
+ finfo->binfo = binfo; /* tell parser this is the current block */
+ binfo->type = (bbyte)type;
+ binfo->hasupval = 0;
+ binfo->beginpc = finfo->pc; /* set starting pc for this block */
+ binfo->nactlocals = (bbyte)be_list_count(finfo->local); /* count number of local variables in previous block */
+ if (type & BLOCK_LOOP) {
+ binfo->breaklist = NO_JUMP;
+ binfo->continuelist = NO_JUMP;
+ }
+}
+
+static void end_block_ex(bparser *parser, int beginpc)
+{
+ bfuncinfo *finfo = parser->finfo;
+ bblockinfo *binfo = finfo->binfo;
+ be_code_close(finfo, 0); /* close upvalues */
+ if (binfo->type & BLOCK_LOOP) {
+ be_code_jumpto(finfo, binfo->beginpc);
+ be_code_patchjump(finfo, binfo->breaklist);
+ be_code_patchlist(finfo, binfo->continuelist, binfo->beginpc);
+ }
+ end_varinfo(parser, beginpc);
+ be_list_resize(parser->vm, finfo->local, binfo->nactlocals); /* remove local variables from this block, they are now out of scope */
+ finfo->freereg = binfo->nactlocals; /* adjust first free register accordingly */
+ finfo->binfo = binfo->prev; /* restore previous block */
+}
+
+static void end_block(bparser *parser)
+{
+ end_block_ex(parser, -1);
+}
+
+/* Return the name of the source for this parser, could be `string`,
+ `stdin` or the name of the current function */
+static bstring* parser_source(bparser *parser)
+{
+ if (parser->finfo) {
+ return parser->finfo->proto->source;
+ }
+ return be_newstr(parser->vm, parser->lexer.fname);
+}
+
+/* Initialize a function block and create a new `bprotoˋ */
+static void begin_func(bparser *parser, bfuncinfo *finfo, bblockinfo *binfo)
+{
+ bvm *vm = parser->vm;
+ bproto *proto = be_newproto(vm);
+ var_setproto(vm->top, proto);
+ be_stackpush(vm);
+ be_vector_init(vm, &finfo->code, sizeof(binstruction)); /* vector for code, vectors are not gced */
+ proto->code = be_vector_data(&finfo->code);
+ proto->codesize = be_vector_capacity(&finfo->code);
+ be_vector_init(vm, &finfo->kvec, sizeof(bvalue)); /* vector for constants */
+ proto->ktab = be_vector_data(&finfo->kvec);
+ proto->nconst = be_vector_capacity(&finfo->kvec);
+ be_vector_init(vm, &finfo->pvec, sizeof(bproto*)); /* vector for subprotos */
+ proto->ptab = be_vector_data(&finfo->pvec);
+ proto->nproto = be_vector_capacity(&finfo->pvec);
+ proto->source = parser_source(parser); /* keep a copy of source for function */
+ finfo->local = be_list_new(vm); /* list for local variables */
+ var_setlist(vm->top, finfo->local); /* push list of local variables on the stack (avoid gc) */
+ be_stackpush(vm);
+ finfo->upval = be_map_new(vm); /* push a map for upvals on stack */
+ var_setmap(vm->top, finfo->upval);
+ be_stackpush(vm);
+ finfo->prev = parser->finfo; /* init finfo */
+ finfo->lexer = &parser->lexer;
+ finfo->proto = proto;
+ finfo->freereg = 0;
+ finfo->binfo = NULL;
+ finfo->pc = 0;
+ finfo->flags = 0;
+ parser->finfo = finfo;
+#if BE_DEBUG_RUNTIME_INFO
+ be_vector_init(vm, &finfo->linevec, sizeof(blineinfo));
+ proto->lineinfo = be_vector_data(&finfo->linevec);
+ proto->nlineinfo = be_vector_capacity(&finfo->linevec);
+#endif
+#if BE_DEBUG_VAR_INFO
+ be_vector_init(vm, &finfo->varvec, sizeof(bvarinfo));
+ proto->varinfo = be_vector_data(&finfo->varvec);
+ proto->nvarinfo = be_vector_capacity(&finfo->varvec);
+#endif
+ begin_block(finfo, binfo, 0);
+}
+
+/* compute the upval structure */
+static void setupvals(bfuncinfo *finfo)
+{
+ bproto *proto = finfo->proto;
+ int nupvals = be_map_count(finfo->upval);
+ if (nupvals) {
+ bmapnode *node;
+ bmap *map = finfo->upval;
+ bmapiter iter = be_map_iter();
+ bupvaldesc *upvals = be_malloc(
+ finfo->lexer->vm, sizeof(bupvaldesc) * nupvals);
+ while ((node = be_map_next(map, &iter)) != NULL) {
+ uint32_t v = (uint32_t)var_toint(&node->value);
+ bupvaldesc *uv = upvals + upval_index(v);
+ uv->idx = upval_target(v);
+ uv->instack = upval_instack(v);
+#if BE_DEBUG_VAR_INFO
+ uv->name = var_tostr(&node->key);
+#endif
+ }
+ proto->upvals = upvals;
+ proto->nupvals = (bbyte)nupvals;
+ }
+}
+
+/* Function is complete, finalize bproto */
+static void end_func(bparser *parser)
+{
+ bvm *vm = parser->vm;
+ bfuncinfo *finfo = parser->finfo;
+ bproto *proto = finfo->proto;
+
+ be_code_ret(finfo, NULL); /* append a return to last code */
+ end_block(parser); /* close block */
+ setupvals(finfo); /* close upvals */
+ proto->code = be_vector_release(vm, &finfo->code); /* compact all vectors and return NULL if empty */
+ proto->codesize = finfo->pc;
+ proto->ktab = be_vector_release(vm, &finfo->kvec);
+ proto->nconst = be_vector_count(&finfo->kvec);
+ proto->ptab = be_vector_release(vm, &finfo->pvec);
+ proto->nproto = be_vector_count(&finfo->pvec);
+#if BE_DEBUG_RUNTIME_INFO
+ proto->lineinfo = be_vector_release(vm, &finfo->linevec);
+ proto->nlineinfo = be_vector_count(&finfo->linevec);
+#endif
+#if BE_DEBUG_VAR_INFO
+ proto->varinfo = be_vector_release(vm, &finfo->varvec);
+ proto->nvarinfo = be_vector_count(&finfo->varvec);
+#endif
+ parser->finfo = parser->finfo->prev; /* restore previous `finfo` */
+ be_stackpop(vm, 2); /* pop upval and local */
+}
+
+/* is the next token a binary operator? If yes return the operator or `OP_NOT_BINARY` */
+static btokentype get_binop(bparser *parser)
+{
+ btokentype op = next_type(parser);
+ if (op >= OptAdd && op <= OptOr) {
+ return op;
+ }
+ return OP_NOT_BINARY;
+}
+
+/* is the next token a unary operator? If yes return the operator or `OP_NOT_BINARY` */
+/* operator 'negative' 'not' and 'flip' */
+static btokentype get_unary_op(bparser *parser)
+{
+ btokentype op = next_type(parser);
+ if (op == OptSub || op == OptNot || op == OptFlip) {
+ return op; /* operator 'negative' 'not' and 'flip' */
+ }
+ return OP_NOT_UNARY;
+}
+
+/* is the next token an assignment operator? If yes return the operator or `OP_NOT_BINARY` */
+/* `=`, `+=`, ... `>>=` */
+static btokentype get_assign_op(bparser *parser)
+{
+ btokentype op = next_type(parser);
+ if (op >= OptAssign && op <= OptRsfAssign) {
+ return op;
+ }
+ return OP_NOT_ASSIGN;
+}
+
+/* Initialize bexpdesc structure with specific type and value as int */
+static void init_exp(bexpdesc *e, exptype_t type, bint i)
+{
+ e->type = (bbyte)type;
+ e->t = NO_JUMP;
+ e->f = NO_JUMP;
+ e->not = 0;
+ e->v.s = NULL;
+ e->v.i = i;
+}
+
+/* find local variable by name, starting at index `begin` */
+/* linear search, returns -1 if not found */
+static int find_localvar(bfuncinfo *finfo, bstring *s, int begin)
+{
+ int i, count = be_list_count(finfo->local);
+ bvalue *var = be_list_data(finfo->local);
+ for (i = count - 1; i >= begin; --i) {
+ if (be_eqstr(var[i].v.s, s)) {
+ return i;
+ }
+ }
+ return -1; /* not found */
+}
+
+/* create a new local variable by name, or return the current register if already exists */
+/* returns the Reg number for the variable */
+/* If STRICT, we don't allow a var to hide a var from outer scope */
+/* We don't allow the same var to be defined twice in same scope */
+static int new_localvar(bparser *parser, bstring *name)
+{
+ bfuncinfo *finfo = parser->finfo;
+ int reg = find_localvar(finfo, name, finfo->binfo->nactlocals); /* look if already exists skipping the local variables from upper blocks */
+ /* 'strict': raise an exception if the local variable shadows another local variable */
+ if (reg == -1) {
+ bvalue *var;
+ if (comp_is_strict(parser->vm)) {
+ if (find_localvar(finfo, name, 0) >= 0 && str(name)[0] != '.') { /* we do accept nested redifinition of internal variables starting with ':' */
+ push_error(parser, "strict: redefinition of '%s' from outer scope", str(name));
+ }
+ }
+ reg = be_list_count(finfo->local); /* new local index */
+ var = be_list_push(parser->vm, finfo->local, NULL);
+ var_setstr(var, name);
+ if (reg >= finfo->freereg) {
+ be_code_allocregs(finfo, 1); /* use a register */
+ }
+ begin_varinfo(parser, name);
+ } else {
+ push_error(parser, "redefinition of '%s'", str(name));
+ }
+ return reg;
+}
+
+/* Find upval by name, if found return its index number, or -1 */
+static int find_upval(bfuncinfo *finfo, bstring *s)
+{
+ bvm *vm = finfo->lexer->vm;
+ bvalue *desc = be_map_findstr(vm, finfo->upval, s);
+ if (desc) {
+ return upval_index(desc->v.i);
+ }
+ return -1;
+}
+
+/* Recursively search for upper blocks that are referenced in upvals */
+/* and mark them with `hasupval` */
+static void mark_upval(bfuncinfo *finfo, int level)
+{
+ bblockinfo *binfo = finfo->prev->binfo;
+ while (binfo->nactlocals > level) {
+ binfo = binfo->prev;
+ }
+ binfo->hasupval = 1;
+}
+
+static int new_upval(bvm *vm, bfuncinfo *finfo, bstring *name, bexpdesc *var)
+{
+ int index;
+ bvalue *desc;
+ int target = var->v.idx;
+ int instack = var->type == ETLOCAL;
+ if (instack) { /* mark upvalue's block */
+ mark_upval(finfo, target);
+ }
+ index = be_map_count(finfo->upval);
+ if (index >= 255) {
+ be_lexerror(finfo->lexer, be_pushfstring(vm,
+ "too many upvalues (in '%s')", str(name)));
+ }
+ desc = be_map_insertstr(vm, finfo->upval, name, NULL);
+ var_setint(desc, upval_desc(index, target, instack));
+ return index;
+}
+
+/* create a new variable in currenr context as name, and create expdesc for it */
+/* If within a block, create as local, otherwise as global */
+static void new_var(bparser *parser, bstring *name, bexpdesc *var)
+{
+ bfuncinfo *finfo = parser->finfo;
+ if (finfo->prev || finfo->binfo->prev || parser->islocal) {
+ init_exp(var, ETLOCAL, 0);
+ var->v.idx = new_localvar(parser, name); /* if local, contains the index in current local var list */
+ } else {
+ init_exp(var, ETGLOBAL, 0);
+ var->v.idx = be_global_new(parser->vm, name);
+ if (var->v.idx > (int)IBx_MASK) {
+ push_error(parser,
+ "too many global variables (in '%s')", str(name));
+ }
+ if (comp_is_named_gbl(parser->vm)) {
+ /* change to ETNGLBAL */
+ bexpdesc key;
+ init_exp(&key, ETSTRING, 0);
+ key.v.s = name;
+ init_exp(var, ETNGLOBAL, 0);
+ var->v.idx = be_code_nglobal(parser->finfo, &key);
+ }
+ }
+}
+
+static int singlevaraux(bvm *vm, bfuncinfo *finfo, bstring *s, bexpdesc *var)
+{
+ if (finfo == NULL) {
+ return ETVOID;
+ } else {
+ int idx = find_localvar(finfo, s, 0);
+ if (idx >= 0) { /* local variable */
+ init_exp(var, ETLOCAL, 0);
+ var->v.idx = idx;
+ return ETLOCAL;
+ } else {
+ idx = find_upval(finfo, s);
+ if (idx < 0) {
+ /* find the previous scope */
+ int res = singlevaraux(vm, finfo->prev, s, var);
+ if (res == ETUPVAL || res == ETLOCAL) {
+ idx = new_upval(vm, finfo, s, var); /* new upvalue */
+ } else {
+ idx = be_global_find(vm, s);
+ if (idx >= 0) {
+ if (idx < be_builtin_count(vm)) {
+ return ETGLOBAL; /* global variable */
+ } else {
+ return comp_is_named_gbl(vm) ? ETNGLOBAL : ETGLOBAL; /* global variable */
+ }
+ } else {
+ return ETVOID; /* unknow (new variable or error) */
+ }
+ }
+ }
+ init_exp(var, ETUPVAL, idx);
+ return ETUPVAL;
+ }
+ }
+}
+
+/* get variable from next toden as name */
+/* and create an expdesc from it */
+/* can be new, global, named global, upval */
+static void singlevar(bparser *parser, bexpdesc *var)
+{
+ bexpdesc key;
+ bstring *varname = next_token(parser).u.s;
+ int type = singlevaraux(parser->vm, parser->finfo, varname, var);
+ switch (type) {
+ case ETVOID:
+ init_exp(var, ETVOID, 0);
+ var->v.s = varname;
+ break;
+ case ETGLOBAL:
+ init_exp(var, ETGLOBAL, 0);
+ var->v.idx = be_global_find(parser->vm, varname);
+ break;
+ case ETNGLOBAL:
+ init_exp(&key, ETSTRING, 0);
+ key.v.s = varname;
+ init_exp(var, ETNGLOBAL, 0);
+ var->v.idx = be_code_nglobal(parser->finfo, &key);
+ break;
+ default:
+ break;
+ }
+}
+
+/* parse a vararg argument in the form `def f(a, *b) end` */
+/* Munch the '*', read the token, create variable and declare the function as vararg */
+static void func_vararg(bparser *parser) {
+ bexpdesc v;
+ bstring *str;
+ match_token(parser, OptMul); /* skip '*' */
+ str = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ new_var(parser, str, &v); /* new variable */
+ parser->finfo->proto->varg = 1; /* set varg flag */
+}
+
+/* Parse function or method definition variable list */
+/* Create an implicit local variable for each argument starting at R0 */
+/* Update function proto argc to the expected number or arguments */
+/* Raise an exception if multiple arguments have the same name */
+/* New: vararg support */
+static void func_varlist(bparser *parser)
+{
+ bexpdesc v;
+ bstring *str;
+ /* '(' [ ID {',' ID}] ')' or */
+ /* '(' '*' ID ')' or */
+ /* '(' [ ID {',' ID}] ',' '*' ID ')' */
+ match_token(parser, OptLBK); /* skip '(' */
+ if (next_type(parser) == OptMul) {
+ func_vararg(parser);
+ } else if (match_id(parser, str) != NULL) {
+ new_var(parser, str, &v); /* new variable */
+ while (match_skip(parser, OptComma)) { /* ',' */
+ if (next_type(parser) == OptMul) {
+ func_vararg(parser);
+ break;
+ } else {
+ str = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ /* new local variable */
+ new_var(parser, str, &v);
+ }
+ }
+ }
+ match_token(parser, OptRBK); /* skip ')' */
+ parser->finfo->proto->argc = parser->finfo->freereg;
+}
+
+/* Parse a function includind arg list and body */
+/* Given name and type (function or method) */
+/* Returns `bproto` object */
+static bproto* funcbody(bparser *parser, bstring *name, int type)
+{
+ bfuncinfo finfo;
+ bblockinfo binfo;
+
+ /* '(' varlist ')' block 'end' */
+ begin_func(parser, &finfo, &binfo); /* init new function context */
+ finfo.proto->name = name;
+ if (type & FUNC_METHOD) { /* If method, add an implicit first argument `self` */
+ new_localvar(parser, parser_newstr(parser, "self"));
+ }
+ func_varlist(parser); /* parse arg list */
+ stmtlist(parser); /* parse statement without final `end` */
+ end_func(parser); /* close function context */
+ match_token(parser, KeyEnd); /* skip 'end' */
+ return finfo.proto; /* return fully constructed `bproto` */
+}
+
+/* anonymous function, build `bproto` object with name `_anonymous_` */
+/* and build a expdesc for the bproto */
+static void anon_func(bparser *parser, bexpdesc *e)
+{
+ bproto *proto;
+ bstring *name = parser_newstr(parser, "_anonymous_");
+ /* 'def' ID '(' varlist ')' block 'end' */
+ scan_next_token(parser); /* skip 'def' */
+ proto = funcbody(parser, name, FUNC_ANONYMOUS);
+ init_exp(e, ETPROTO, be_code_proto(parser->finfo, proto));
+ be_stackpop(parser->vm, 1);
+}
+
+static void lambda_varlist(bparser *parser)
+{
+ bexpdesc v;
+ bstring *str;
+ /* [ID {',' ID}] | {ID}] */
+ if (match_id(parser, str) != NULL) {
+ bbool comma;
+ new_var(parser, str, &v); /* new variable */
+ comma = next_type(parser) == OptComma;
+ while (next_type(parser) != OptArrow) {
+ if (comma) {
+ match_token(parser, OptComma); /* match and skip ',' */
+ }
+ str = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ /* new local variable */
+ new_var(parser, str, &v);
+ }
+ }
+ match_token(parser, OptArrow); /* skip '->' */
+ parser->finfo->proto->argc = parser->finfo->freereg;
+}
+
+/* lambda expression */
+static void lambda_expr(bparser *parser, bexpdesc *e)
+{
+ bexpdesc e1;
+ bfuncinfo finfo;
+ bblockinfo binfo;
+ bstring *name = parser_newstr(parser, "");
+ /* '/' ID {[',' ID]} '->' expr */
+ scan_next_token(parser); /* skip '/' */
+ begin_func(parser, &finfo, &binfo);
+ finfo.proto->name = name;
+ lambda_varlist(parser);
+ expr(parser, &e1);
+ check_var(parser, &e1);
+ be_code_ret(parser->finfo, &e1);
+ end_func(parser);
+ init_exp(e, ETPROTO, be_code_proto(parser->finfo, finfo.proto));
+ be_stackpop(parser->vm, 1);
+}
+
+/* Instanciate a builtin type by name */
+/* Allocates a new register for the value, and call empty constructor */
+/* Is allocated as LOCAL and must be changed to REG when completed */
+static void new_primtype(bparser *parser, const char *type, bexpdesc *e)
+{
+ int idx;
+ bvm *vm = parser->vm;
+ bfuncinfo *finfo = parser->finfo;
+
+ scan_next_token(parser);
+ idx = be_builtin_find(vm, parser_newstr(parser, type));
+ init_exp(e, ETGLOBAL, idx);
+ idx = be_code_nextreg(finfo, e);
+ be_code_call(finfo, idx, 0);
+ e->type = ETLOCAL; /* declare as local, will be changed to ETREG when completely initialized */
+}
+
+/* Parse next member within a list */
+/* `l` contains the current list. The expr is evaluated and added to the list */
+static void list_nextmember(bparser *parser, bexpdesc *l)
+{
+ bexpdesc e, v = *l;
+ bfuncinfo *finfo = parser->finfo;
+ expr(parser, &e); /* value */
+ check_var(parser, &e); /* check that we don´t have an unknown symbol */
+ be_code_binop(finfo, OptConnect, &v, &e, -1); /* add it to list with CONNECT */
+ be_code_freeregs(finfo, 1); /* since left arg is LOCAL, an ETREG was allocated. Free it */
+}
+
+static void map_nextmember(bparser *parser, bexpdesc *l)
+{
+ bexpdesc e, v = *l;
+ bfuncinfo *finfo = parser->finfo;
+ expr(parser, &e); /* key */
+ check_var(parser, &e); /* check if value is valid */
+ be_code_index(finfo, &v, &e); /* package as `v` as INDEX suffix for value `e` */
+ match_token(parser, OptColon); /* ':' */
+ expr(parser, &e); /* value in `e` */
+ check_var(parser, &e); /* check if value is correct */
+ be_code_setvar(finfo, &v, &e); /* set suffi INDEX value to e */
+}
+
+static void list_expr(bparser *parser, bexpdesc *e)
+{
+ /* '[' {expr ','} [expr] ']' */
+ new_primtype(parser, "list", e); /* new list, created as LOCAL first */
+ while (next_type(parser) != OptRSB) {
+ list_nextmember(parser, e);
+ if (!match_skip(parser, OptComma)) { /* ',' */
+ break;
+ }
+ }
+ e->type = ETREG; /* then turned to REG */
+ match_token(parser, OptRSB); /* skip ']' */
+}
+
+static void map_expr(bparser *parser, bexpdesc *e)
+{
+ /* '{' {expr ':' expr ','} [expr ':' expr] '}' */
+ new_primtype(parser, "map", e); /* new map */
+ while (next_type(parser) != OptRBR) {
+ map_nextmember(parser, e);
+ if (!match_skip(parser, OptComma)) { /* ',' */
+ break;
+ }
+ }
+ e->type = ETREG;
+ match_token(parser, OptRBR); /* skip '}' */
+}
+
+/* push each argument as new reg and return number of args */
+/* TODO `e` is ignored by caller */
+static int exprlist(bparser *parser, bexpdesc *e)
+{
+ bfuncinfo *finfo = parser->finfo;
+ int n = 1;
+ /* expr { ',' expr } */
+ expr(parser, e); /* parse expr */
+ check_var(parser, e); /* check if valid */
+ be_code_nextreg(finfo, e); /* move result to next reg */
+ while (match_skip(parser, OptComma)) { /* ',' */
+ expr(parser, e);
+ check_var(parser, e);
+ be_code_nextreg(finfo, e);
+ ++n;
+ }
+ return n;
+}
+
+/* parse call to method or function */
+/* `e` can be a member (method) or a register */
+/* On return, `e` is ETREG to the result of the call */
+static void call_expr(bparser *parser, bexpdesc *e)
+{
+ bexpdesc args;
+ bfuncinfo *finfo = parser->finfo;
+ int argc = 0, base;
+ int ismember = e->type == ETMEMBER;
+
+ /* func '(' [exprlist] ')' */
+ check_var(parser, e);
+ /* code function index to next register */
+ if (ismember) {
+ base = be_code_getmethod(finfo, e);
+ } else {
+ base = be_code_nextreg(finfo, e); /* allocate a new base reg if not at top already */
+ }
+ /* base is always taken at top of freereg and allocates 1 reg for function and 2 regs for method */
+ scan_next_token(parser); /* skip '(' */
+ if (next_type(parser) != OptRBK) { /* if arg list is not empty */
+ argc = exprlist(parser, &args); /* push each argument as new reg and return number of args */
+ }
+ match_token(parser, OptRBK); /* skip ')' */
+ argc += ismember; /* if method there is an additional implicit arg */
+ be_code_call(finfo, base, argc);
+ if (e->type != ETREG) {
+ e->type = ETREG;
+ e->v.idx = base;
+ }
+}
+
+/* Parse member expression */
+/* Generates an ETMEMBER object that is materialized later into GETMBR, GETMET or SETMBR */
+static void member_expr(bparser *parser, bexpdesc *e)
+{
+ bstring *str;
+ /* . ID */
+ check_var(parser, e);
+ scan_next_token(parser); /* skip '.' */
+ if (match_id(parser, str) != NULL) {
+ bexpdesc key;
+ init_exp(&key, ETSTRING, 0);
+ key.v.s = str;
+ be_code_member(parser->finfo, e, &key);
+ } else if (next_type(parser) == OptLBK) {
+ scan_next_token(parser); /* skip '(' */
+ bexpdesc key;
+ expr(parser, &key);
+ check_var(parser, &key);
+ match_token(parser, OptRBK); /* skip ')' */
+ be_code_member(parser->finfo, e, &key);
+ } else {
+ push_error(parser, "invalid syntax near '%s'",
+ be_token2str(parser->vm, &next_token(parser)));
+ }
+}
+
+static void index_expr(bparser *parser, bexpdesc *e)
+{
+ bexpdesc e1;
+ /* [expr] */
+ check_var(parser, e);
+ scan_next_token(parser); /* skip '[' */
+ expr(parser, &e1);
+ check_var(parser, &e1);
+ be_code_index(parser->finfo, e, &e1);
+ match_token(parser, OptRSB); /* skip ']' */
+}
+
+static void simple_expr(bparser *parser, bexpdesc *e)
+{
+ switch (next_type(parser)) {
+ case TokenInteger:
+ init_exp(e, ETINT, next_token(parser).u.i);
+ break;
+ case TokenReal:
+ init_exp(e, ETREAL, 0);
+ e->v.r = next_token(parser).u.r;
+ break;
+ case TokenString:
+ init_exp(e, ETSTRING, 0);
+ e->v.s = next_token(parser).u.s;
+ break;
+ case TokenId:
+ singlevar(parser, e);
+ break;
+ case KeyTrue:
+ init_exp(e, ETBOOL, 1);
+ break;
+ case KeyFalse:
+ init_exp(e, ETBOOL, 0);
+ break;
+ case KeyNil:
+ init_exp(e, ETNIL, 0);
+ break;
+ default: /* unknow expr */
+ return;
+ }
+ scan_next_token(parser);
+}
+
+static void primary_expr(bparser *parser, bexpdesc *e)
+{
+ switch (next_type(parser)) {
+ case OptLBK: /* '(' expr ')' */
+ scan_next_token(parser); /* skip '(' */
+ /* sub_expr() is more efficient because there is no need to initialize e. */
+ sub_expr(parser, e, ASSIGN_OP_PRIO);
+ check_var(parser, e);
+ match_token(parser, OptRBK); /* skip ')' */
+ break;
+ case OptLSB: /* list */
+ list_expr(parser, e);
+ break;
+ case OptLBR: /* map */
+ map_expr(parser, e);
+ break;
+ case KeyDef: /* anonymous function */
+ anon_func(parser, e);
+ break;
+ case OptDiv: /* lambda expression */
+ lambda_expr(parser, e);
+ break;
+ default: /* simple expr */
+ simple_expr(parser, e);
+ break;
+ }
+}
+
+/* parse a single string literal as parameter */
+static void call_single_string_expr(bparser *parser, bexpdesc *e)
+{
+ bexpdesc arg;
+ bfuncinfo *finfo = parser->finfo;
+ int base;
+
+ /* func 'string_literal' */
+ check_var(parser, e);
+ if (e->type == ETMEMBER) {
+ push_error(parser, "method not allowed for string prefix");
+ }
+
+ base = be_code_nextreg(finfo, e); /* allocate a new base reg if not at top already */
+ simple_expr(parser, &arg);
+ be_code_nextreg(finfo, &arg); /* move result to next reg */
+
+ be_code_call(finfo, base, 1); /* only one arg */
+ if (e->type != ETREG) {
+ e->type = ETREG;
+ e->v.idx = base;
+ }
+}
+
+static void suffix_expr(bparser *parser, bexpdesc *e)
+{
+ primary_expr(parser, e);
+ for (;;) {
+ switch (next_type(parser)) {
+ case OptLBK: /* '(' function call */
+ call_expr(parser, e);
+ break;
+ case OptDot: /* '.' member */
+ member_expr(parser, e);
+ break;
+ case OptLSB: /* '[' index */
+ index_expr(parser, e);
+ break;
+ case TokenString:
+ call_single_string_expr(parser, e); /* " string literal */
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+static void suffix_alloc_reg(bparser *parser, bexpdesc *l)
+{
+ bfuncinfo *finfo = parser->finfo;
+ bbool is_suffix = l->type == ETINDEX || l->type == ETMEMBER; /* is suffix */
+ bbool is_suffix_reg = l->v.ss.tt == ETREG || l->v.ss.tt == ETLOCAL || l->v.ss.tt == ETGLOBAL || l->v.ss.tt == ETNGLOBAL; /* if suffix, does it need a register */
+ bbool is_global = l->type == ETGLOBAL || l->type == ETNGLOBAL;
+ /* in the suffix expression, if the object is a temporary
+ * variable (l->v.ss.tt == ETREG), it needs to be cached. */
+ if (is_global || (is_suffix && is_suffix_reg)) {
+ be_code_allocregs(finfo, 1);
+ }
+}
+
+/* compound assignment */
+static void compound_assign(bparser *parser, int op, bexpdesc *l, bexpdesc *r)
+{
+ int dst = -1; /* destination register in case of compound assignment */
+ if (op != OptAssign) { /* check left variable */
+ check_var(parser, l);
+ /* cache the register of the object when continuously assigning */
+ dst = parser->finfo->freereg;
+ suffix_alloc_reg(parser, l);
+ }
+ expr(parser, r); /* right expression */
+ check_var(parser, r);
+ if (op != OptAssign) { /* compound assignment */
+ bexpdesc e = *l;
+ op = op < OptAndAssign ? op - OptAddAssign + OptAdd
+ : op - OptAndAssign + OptBitAnd;
+ be_code_binop(parser->finfo, op, &e, r, dst); /* coding operation */
+ *r = e;
+ }
+}
+
+/* check if we need to create a new local variable with this name to be assigned to */
+/* Returns true if it´s a new local variable */
+/* A new implicit local variable is created if no global has the same name (excluding builtins) */
+/* This means that you can override a builtin silently */
+/* This also means that a function cannot create a global, they must preexist or create with `global` module */
+/* TODO add warning in strict mode */
+static int check_newvar(bparser *parser, bexpdesc *e)
+{
+ if (e->type == ETGLOBAL) {
+ if (e->v.idx < be_builtin_count(parser->vm)) {
+ e->v.s = be_builtin_name(parser->vm, e->v.idx);
+ if (comp_is_strict(parser->vm)) {
+ push_error(parser, "strict: redefinition of builtin '%s'",
+ str(e->v.s));
+ }
+ return btrue;
+ }
+ return bfalse;
+ }
+ if (comp_is_strict(parser->vm)) {
+ bfuncinfo *finfo = parser->finfo;
+ if ((e->type == ETVOID) && (finfo->prev || finfo->binfo->prev || parser->islocal)) {
+ push_error(parser, "strict: no global '%s', did you mean 'var %s'?",
+ str(e->v.s), str(e->v.s));
+ }
+ }
+ return e->type == ETVOID;
+}
+
+static void assign_expr(bparser *parser)
+{
+ bexpdesc e;
+ btokentype op;
+ int line = parser->lexer.linenumber;
+ expr(parser, &e); /* left expression */
+ check_symbol(parser, &e);
+ op = get_assign_op(parser);
+ if (op != OP_NOT_ASSIGN) { /* assign operator */
+ bexpdesc e1;
+ scan_next_token(parser);
+ compound_assign(parser, op, &e, &e1);
+ if (check_newvar(parser, &e)) { /* new variable */
+ new_var(parser, e.v.s, &e);
+ }
+ if (be_code_setvar(parser->finfo, &e, &e1)) {
+ parser->lexer.linenumber = line;
+ parser_error(parser,
+ "try to assign constant expressions.");
+ }
+ } else if (e.type >= ETMEMBER) {
+ bfuncinfo *finfo = parser->finfo;
+ /* these expressions occupy a register and need to be freed */
+ finfo->freereg = (bbyte)be_list_count(finfo->local);
+ } else if (e.type == ETVOID) { /* not assign expression */
+ /* undeclared symbol */
+ parser->lexer.linenumber = line;
+ check_var(parser, &e);
+ }
+}
+
+/* conditional expression */
+static void cond_expr(bparser *parser, bexpdesc *e)
+{
+ /* expr '?' expr ':' expr */
+ if (next_type(parser) == OptQuestion) {
+ int jf, jl = NO_JUMP; /* jump list */
+ bfuncinfo *finfo = parser->finfo;
+ check_var(parser, e); /* check if valid */
+ scan_next_token(parser); /* skip '?' */
+ be_code_jumpbool(finfo, e, bfalse); /* go if true */
+ jf = e->f;
+ expr(parser, e);
+ check_var(parser, e);
+ be_code_nextreg(finfo, e);
+ be_code_freeregs(finfo, 1);
+ be_code_conjump(finfo, &jl, be_code_jump(finfo)); /* connect jump */
+ be_code_patchjump(finfo, jf);
+ match_token(parser, OptColon); /* match and skip ':' */
+ expr(parser, e);
+ check_var(parser, e);
+ e->v.idx = be_code_nextreg(finfo, e);
+ be_code_patchjump(finfo, jl);
+ e->type = ETREG;
+ }
+}
+
+/* binary operator: + - * / % && || < <= == != > >=
+ * unary operator: + - !
+ */
+static void sub_expr(bparser *parser, bexpdesc *e, int prio)
+{
+ bfuncinfo *finfo = parser->finfo;
+ btokentype op = get_unary_op(parser); /* check if first token in unary op */
+ if (op != OP_NOT_UNARY) { /* unary op found */
+ int line, res;
+ scan_next_token(parser); /* move to next token */
+ line = parser->lexer.linenumber; /* remember line number for error reporting */
+ sub_expr(parser, e, UNARY_OP_PRIO); /* parse subexpr with new prio */
+ check_var(parser, e); /* check that the value is ok */
+ res = be_code_unop(finfo, op, e); /* apply unary op with optimizations if the token is a value */
+ if (res) { /* encode unary op */
+ parser->lexer.linenumber = line;
+ push_error(parser, "wrong type argument to unary '%s'",
+ res == 1 ? "negative" : "bit-flip");
+ }
+ } else {
+ suffix_expr(parser, e); /* parse left part of binop */
+ }
+ op = get_binop(parser); /* check if binop */
+ while (op != OP_NOT_BINARY && prio > binary_op_prio(op)) { /* is binop applicable */
+ bexpdesc e2;
+ check_var(parser, e); /* check that left part is valid */
+ scan_next_token(parser); /* move to next token */
+ be_code_prebinop(finfo, op, e); /* and or */
+ init_exp(&e2, ETVOID, 0);
+ sub_expr(parser, &e2, binary_op_prio(op)); /* parse right side */
+ if ((e2.type == ETVOID) && (op == OptConnect)) {
+ init_exp(&e2, ETINT, M_IMAX);
+ } else {
+ check_var(parser, &e2); /* check if valid */
+ }
+ be_code_binop(finfo, op, e, &e2, -1); /* encode binary op */
+ op = get_binop(parser); /* is there a following binop? */
+ }
+ if (prio == ASSIGN_OP_PRIO) {
+ cond_expr(parser, e);
+ }
+}
+
+/* Parse new expression and return value in `e` (overwritten) */
+/* Initializes an empty expdes and parse subexpr */
+/* Always allocates a new temp register at top of freereg */
+static void expr(bparser *parser, bexpdesc *e)
+{
+ init_exp(e, ETVOID, 0);
+ sub_expr(parser, e, ASSIGN_OP_PRIO);
+}
+
+static void expr_stmt(bparser *parser)
+{
+ assign_expr(parser);
+}
+
+static int block_follow(bparser *parser)
+{
+ switch (next_type(parser)) {
+ case KeyElse: case KeyElif:
+ case KeyEnd: case KeyExcept:
+ case TokenEOS:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+static int cond_stmt(bparser *parser)
+{
+ bexpdesc e;
+ /* expr */
+ match_notoken(parser, OptRBK);
+ expr(parser, &e);
+ check_var(parser, &e);
+ be_code_jumpbool(parser->finfo, &e, bfalse); /* go if true */
+ return e.f;
+}
+
+static void condition_block(bparser *parser, int *jmp)
+{
+ bfuncinfo *finfo = parser->finfo;
+ int br = cond_stmt(parser);
+ block(parser, 0);
+ if (next_type(parser) == KeyElif
+ || next_type(parser) == KeyElse) {
+ be_code_conjump(finfo, jmp, be_code_jump(finfo)); /* connect jump */
+ }
+ be_code_patchjump(finfo, br);
+}
+
+static void if_stmt(bparser *parser)
+{
+ int jl = NO_JUMP; /* jump list */
+ /* IF expr block {ELSEIF expr block}, [ELSE block], end */
+ scan_next_token(parser); /* skip 'if' */
+ condition_block(parser, &jl);
+ while (match_skip(parser, KeyElif)) { /* 'elif' */
+ condition_block(parser, &jl);
+ }
+ if (match_skip(parser, KeyElse)) { /* 'else' */
+ block(parser, 0);
+ }
+ match_token(parser, KeyEnd); /* skip end */
+ be_code_patchjump(parser->finfo, jl);
+}
+
+static void do_stmt(bparser *parser)
+{
+ /* DO block END */
+ scan_next_token(parser); /* skip 'do' */
+ block(parser, 0);
+ match_token(parser, KeyEnd); /* skip 'end' */
+}
+
+static void while_stmt(bparser *parser)
+{
+ int brk;
+ bblockinfo binfo;
+ bfuncinfo *finfo = parser->finfo;
+ /* WHILE expr block END */
+ scan_next_token(parser); /* skip 'while' */
+ begin_block(parser->finfo, &binfo, BLOCK_LOOP);
+ brk = cond_stmt(parser);
+ stmtlist(parser);
+ end_block(parser);
+ be_code_patchjump(finfo, brk);
+ match_token(parser, KeyEnd); /* skip 'end' */
+}
+
+static bstring* for_itvar(bparser *parser)
+{
+ bstring *str;
+ if (match_id(parser, str) == NULL) {
+ push_error(parser,
+ "missing iteration variable before '%s'",
+ token2str(parser));
+ }
+ return str;
+}
+
+static void for_init(bparser *parser, bexpdesc *v)
+{
+ bexpdesc e;
+ bstring *s;
+ bfuncinfo *finfo = parser->finfo;
+ /* .it = __iterator__(expr) */
+ s = parser_newstr(parser, "__iterator__");
+ init_exp(&e, ETGLOBAL, be_builtin_find(parser->vm, s));
+ be_code_nextreg(finfo, &e); /* code function '__iterator__' */
+ expr(parser, v);
+ check_var(parser, v);
+ be_code_nextreg(finfo, v);
+ be_code_call(finfo, e.v.idx, 1); /* call __iterator__(expr) */
+ be_code_freeregs(finfo, 1); /* free register of __iterator__ */
+ s = parser_newstr(parser, ".it");
+ init_exp(v, ETLOCAL, new_localvar(parser, s));
+}
+
+static void for_iter(bparser *parser, bstring *var, bexpdesc *it)
+{
+ bexpdesc e;
+ bfuncinfo *finfo = parser->finfo;
+ /* reset the jump head PC of the for loop body */
+ finfo->binfo->beginpc = finfo->pc;
+ /* itvar = .it() */
+ init_exp(&e, ETLOCAL, new_localvar(parser, var)); /* new itvar */
+ be_code_setvar(finfo, &e, it); /* code function to variable '.it' */
+ be_code_call(finfo, e.v.idx, 0); /* itvar <- call .it() */
+ stmtlist(parser);
+}
+
+static void for_leave(bparser *parser, int jcatch, int beginpc)
+{
+ bexpdesc e;
+ bfuncinfo *finfo = parser->finfo;
+ int jbrk = finfo->binfo->breaklist;
+ init_exp(&e, ETSTRING, 0);
+ e.v.s = parser_newstr(parser, "stop_iteration");
+ end_block_ex(parser, beginpc); /* leave except & loop block */
+ if (jbrk != NO_JUMP) { /* has `break` statement in iteration block */
+ be_code_exblk(finfo, 1);
+ jbrk = be_code_jump(finfo);
+ }
+ be_code_conjump(finfo, &jcatch, finfo->pc);
+ be_code_catch(finfo, be_code_nextreg(finfo, &e), 1, 0, NULL);
+ be_code_raise(finfo, NULL, NULL);
+ be_code_conjump(finfo, &jbrk, finfo->pc);
+ be_code_freeregs(finfo, 1);
+}
+
+/* approximate equivalent script code:
+ * .it = __iter__(expr)
+ * try
+ * while (1)
+ * itvar = .it()
+ * stmtlist
+ * end
+ * except ('stop_iteration')
+ * end
+ * */
+static void for_stmt(bparser *parser)
+{
+ bstring *var;
+ bexpdesc iter;
+ bblockinfo binfo;
+ int jcatch, beginpc = parser->finfo->pc;
+ /* FOR ID : expr block END */
+ scan_next_token(parser); /* skip 'for' */
+ begin_block(parser->finfo, &binfo, BLOCK_EXCEPT | BLOCK_LOOP);
+ var = for_itvar(parser);
+ match_token(parser, OptColon); /* skip ':' */
+ for_init(parser, &iter);
+ jcatch = be_code_exblk(parser->finfo, 0);
+ for_iter(parser, var, &iter);
+ for_leave(parser, jcatch, beginpc);
+ match_token(parser, KeyEnd); /* skip 'end' */
+}
+
+static bblockinfo* break_block(bparser *parser)
+{
+ int try_depth = 0; /* count of exception catch blocks */
+ bblockinfo *binfo = parser->finfo->binfo;
+ /* BREAK | CONTINUE */
+ scan_next_token(parser); /* skip 'break' or 'continue' */
+ while (binfo && !(binfo->type & BLOCK_LOOP)) {
+ if (binfo->type & BLOCK_EXCEPT) {
+ ++try_depth; /* leave the exception catch block */
+ }
+ binfo = binfo->prev;
+ }
+ if (binfo && try_depth) { /* exception catch blocks that needs to leave */
+ be_code_exblk(parser->finfo, try_depth);
+ }
+ return binfo;
+}
+
+static void break_stmt(bparser *parser)
+{
+ bfuncinfo *f = parser->finfo;
+ bblockinfo *binfo = break_block(parser);
+ if (binfo != NULL) { /* connect jump */
+ be_code_conjump(f, &binfo->breaklist, be_code_jump(f));
+ } else {
+ parser_error(parser, "break not loop");
+ }
+}
+
+static void continue_stmt(bparser *parser)
+{
+ bfuncinfo *f = parser->finfo;
+ bblockinfo *b = break_block(parser);
+ if (b != NULL) { /* connect jump */
+ be_code_conjump(f, &b->continuelist, be_code_jump(f));
+ } else {
+ parser_error(parser, "continue not loop");
+ }
+}
+
+static bbool isoverloadable(btokentype type)
+{
+ return (type >= OptAdd && type <= OptConnect) /* overloaded binary operator */
+ || type == OptFlip || type == OptLBK; /* '~' and '()' operator */
+}
+
+static bstring* func_name(bparser* parser, bexpdesc* e, int ismethod)
+{
+ btokentype type = next_type(parser);
+ if (type == TokenId) {
+ bstring *name = next_token(parser).u.s;
+ if (!ismethod) {
+ new_var(parser, name, e); /* new variable */
+ }
+ scan_next_token(parser); /* skip name */
+ return name;
+ } else if (ismethod && isoverloadable(type)) {
+ scan_next_token(parser); /* skip token */
+ /* '-*' negative operator */
+ if (type == OptSub && next_type(parser) == OptMul) {
+ scan_next_token(parser); /* skip '*' */
+ return parser_newstr(parser, "-*");
+ }
+ /* '()' call operator */
+ if (type == OptLBK && next_type(parser) == OptRBK) {
+ scan_next_token(parser); /* skip ')' */
+ return parser_newstr(parser, "()");
+ }
+ return parser_newstr(parser, be_tokentype2str(type));
+ }
+ push_error(parser,
+ "the token '%s' is not a valid function name.",
+ token2str(parser));
+ return NULL;
+}
+
+static void def_stmt(bparser *parser)
+{
+ bexpdesc e;
+ bproto *proto;
+ bfuncinfo *finfo = parser->finfo;
+ /* 'def' ID '(' varlist ')' block 'end' */
+ scan_next_token(parser); /* skip 'def' */
+ proto = funcbody(parser, func_name(parser, &e, 0), 0);
+ be_code_closure(finfo, &e, be_code_proto(finfo, proto));
+ be_stackpop(parser->vm, 1);
+}
+
+static void return_stmt(bparser *parser)
+{
+ bexpdesc e;
+ /* 'return' expr */
+ scan_next_token(parser); /* skip 'return' */
+ expr(parser, &e);
+ if (e.v.s) { /* expression is not empty */
+ check_var(parser, &e);
+ }
+ be_code_ret(parser->finfo, &e);
+}
+
+static void check_class_attr(bparser *parser, bclass *c, bstring *attr)
+{
+ if (be_class_attribute(parser->vm, c, attr) != BE_NONE) {
+ push_error(parser,
+ "redefinition of the attribute '%s'", str(attr));
+ }
+}
+
+static void classvar_stmt(bparser *parser, bclass *c)
+{
+ bstring *name;
+ /* 'var' ID {',' ID} */
+ scan_next_token(parser); /* skip 'var' */
+ if (match_id(parser, name) != NULL) {
+ check_class_attr(parser, c, name);
+ be_member_bind(parser->vm, c, name, btrue);
+ while (match_skip(parser, OptComma)) { /* ',' */
+ if (match_id(parser, name) != NULL) {
+ check_class_attr(parser, c, name);
+ be_member_bind(parser->vm, c, name, btrue);
+ } else {
+ parser_error(parser, "class var error");
+ }
+ }
+ } else {
+ parser_error(parser, "class var error");
+ }
+}
+
+static void class_static_assignment_expr(bparser *parser, bexpdesc *e, bstring *name)
+{
+ if (match_skip(parser, OptAssign)) { /* '=' */
+ bexpdesc e1, e2;
+ /* parse the right expression */
+ expr(parser, &e2);
+
+ e1 = *e; /* copy the class description */
+ bexpdesc key; /* build the member key */
+ init_exp(&key, ETSTRING, 0);
+ key.v.s = name;
+
+ be_code_member(parser->finfo, &e1, &key); /* compute member accessor */
+ be_code_setvar(parser->finfo, &e1, &e2); /* set member */
+ }
+}
+
+static void classdef_stmt(bparser *parser, bclass *c, bbool is_static)
+{
+ bexpdesc e;
+ bstring *name;
+ bproto *proto;
+ /* 'def' ID '(' varlist ')' block 'end' */
+ scan_next_token(parser); /* skip 'def' */
+ name = func_name(parser, &e, 1);
+ check_class_attr(parser, c, name);
+ proto = funcbody(parser, name, is_static ? 0 : FUNC_METHOD);
+ be_method_bind(parser->vm, c, proto->name, proto, is_static);
+ be_stackpop(parser->vm, 1);
+}
+
+static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e)
+{
+ bstring *name;
+ /* 'static' ID ['=' expr] {',' ID ['=' expr] } */
+ scan_next_token(parser); /* skip 'static' */
+ if (next_type(parser) == KeyDef) { /* 'static' 'def' ... */
+ classdef_stmt(parser, c, btrue);
+ } else if (match_id(parser, name) != NULL) {
+ check_class_attr(parser, c, name);
+ be_member_bind(parser->vm, c, name, bfalse);
+ class_static_assignment_expr(parser, e, name);
+
+ while (match_skip(parser, OptComma)) { /* ',' */
+ if (match_id(parser, name) != NULL) {
+ check_class_attr(parser, c, name);
+ be_member_bind(parser->vm, c, name, bfalse);
+ class_static_assignment_expr(parser, e, name);
+ } else {
+ parser_error(parser, "class static error");
+ }
+ }
+ } else {
+ parser_error(parser, "class static error");
+ }
+}
+
+static void class_inherit(bparser *parser, bexpdesc *e)
+{
+ if (next_type(parser) == OptColon) { /* ':' */
+ bexpdesc ec = *e; /* work on a copy because we preserve original class */
+ bexpdesc e1;
+ scan_next_token(parser); /* skip ':' */
+ expr(parser, &e1);
+ check_var(parser, &e1);
+ be_code_setsuper(parser->finfo, &ec, &e1);
+ }
+}
+
+static void class_block(bparser *parser, bclass *c, bexpdesc *e)
+{
+ /* { [;] } */
+ while (block_follow(parser)) {
+ switch (next_type(parser)) {
+ case KeyVar: classvar_stmt(parser, c); break;
+ case KeyStatic: classstatic_stmt(parser, c, e); break;
+ case KeyDef: classdef_stmt(parser, c, bfalse); break;
+ case OptSemic: scan_next_token(parser); break;
+ default: push_error(parser,
+ "unexpected token '%s'", token2str(parser));
+ }
+ }
+}
+
+static void class_stmt(bparser *parser)
+{
+ bstring *name;
+ /* 'class' ID [':' ID] class_block 'end' */
+ scan_next_token(parser); /* skip 'class' */
+ if (match_id(parser, name) != NULL) {
+ bexpdesc e;
+ bclass *c = be_newclass(parser->vm, name, NULL);
+ new_var(parser, name, &e);
+ be_code_class(parser->finfo, &e, c);
+ class_inherit(parser, &e);
+ class_block(parser, c, &e);
+ be_class_compress(parser->vm, c); /* compress class size */
+ match_token(parser, KeyEnd); /* skip 'end' */
+ } else {
+ parser_error(parser, "class name error");
+ }
+}
+
+static void import_stmt(bparser *parser)
+{
+ bstring *name; /* variable name */
+ bexpdesc m, v;
+ /* 'import' (ID (['as' ID] | {',' ID}) | STRING 'as' ID ) */
+ scan_next_token(parser); /* skip 'import' */
+ init_exp(&m, ETSTRING, 0);
+ m.v.s = name = next_token(parser).u.s;
+ if (next_type(parser) == TokenString) { /* STRING 'as' ID */
+ scan_next_token(parser); /* skip the module path */
+ match_token(parser, KeyAs); /* match and skip 'as' */
+ name = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ } else { /* ID (['as' ID] | {',' ID}) */
+ match_token(parser, TokenId); /* match and skip ID */
+ if (match_skip(parser, KeyAs)) { /* 'as' */
+ name = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ } else { /* {',' ID} */
+ while (match_skip(parser, OptComma)) { /* ',' */
+ new_var(parser, name, &v);
+ be_code_import(parser->finfo, &m, &v); /* code import */
+ init_exp(&m, ETSTRING, 0); /* scanning for next node */
+ m.v.s = name = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ }
+ }
+ }
+ new_var(parser, name, &v);
+ be_code_import(parser->finfo, &m, &v);
+}
+
+static void var_field(bparser *parser)
+{
+ /* ID ['=' expr] */
+ bexpdesc e1, e2;
+ bstring *name;
+ name = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ if (match_skip(parser, OptAssign)) { /* '=' */
+ expr(parser, &e2);
+ check_var(parser, &e2);
+ } else {
+ init_exp(&e2, ETNIL, 0);
+ }
+ new_var(parser, name, &e1); /* new variable */
+ be_code_setvar(parser->finfo, &e1, &e2);
+}
+
+static void var_stmt(bparser *parser)
+{
+ /* 'var' ID ['=' expr] {',' ID ['=' expr]} */
+ scan_next_token(parser); /* skip 'var' */
+ var_field(parser);
+ while (match_skip(parser, OptComma)) { /* ',' */
+ var_field(parser);
+ }
+}
+
+static int except_case_list(bparser *parser, int *base)
+{
+ int idx;
+ bexpdesc e;
+ bfuncinfo *finfo = parser->finfo;
+ /* expr {',' expr} | '..' */
+ if (match_skip(parser, OptConnect)) { /* '..' */
+ *base = finfo->freereg;
+ return 0;
+ }
+ expr(parser, &e); /* first exception expression */
+ check_var(parser, &e);
+ *base = idx = be_code_nextreg(finfo, &e);
+ while (match_skip(parser, OptComma)) { /* ',' */
+ expr(parser, &e);
+ check_var(parser, &e);
+ idx = be_code_nextreg(finfo, &e);
+ }
+ idx = idx - *base + 1; /* count of exception expression */
+ be_code_freeregs(finfo, idx);
+ return idx;
+}
+
+static int except_var_list(bparser *parser, int base)
+{
+ bexpdesc v;
+ (void)base; /* unused variable (no debugging) */
+ /* [as ID [, ID]] */
+ if (match_skip(parser, KeyAs)) { /* 'as' */
+ bstring *name = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ new_var(parser, name, &v); /* new local variable */
+ be_assert(v.type == ETLOCAL && v.v.idx == base);
+ if (match_skip(parser, OptComma)) { /* match and skip ',' */
+ name = next_token(parser).u.s;
+ match_token(parser, TokenId); /* match and skip ID */
+ new_var(parser, name, &v); /* new local variable */
+ be_assert(v.type == ETLOCAL && v.v.idx == base + 1);
+ return 2;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static void except_block(bparser *parser, int *jmp, int *jbrk)
+{
+ int base = 0; /* the first register of the catch opcode */
+ int ecnt = 0; /* exception cases count */
+ int vcnt = 0; /* exception variable count */
+ bblockinfo binfo;
+ bfuncinfo *finfo = parser->finfo;
+ /* 'except' (expr {',' expr} | '..') ['as' ID [',' ID]] */
+ match_token(parser, KeyExcept); /* skip 'except' */
+ begin_block(finfo, &binfo, 0); /* begin catch block */
+ /* link from the previous except failure point */
+ be_code_conjump(finfo, jmp, finfo->pc);
+ /* (expr {',' expr} | '..') ['as' ID [',' ID]] */
+ ecnt = except_case_list(parser, &base);
+ vcnt = except_var_list(parser, base);
+ be_code_catch(finfo, base, ecnt, vcnt, jmp);
+ stmtlist(parser);
+ be_code_conjump(finfo, jbrk, be_code_jump(finfo));
+ end_block(parser); /* leave catch block */
+}
+
+static void try_stmt(bparser *parser)
+{
+ int jcatch, jbrk;
+ /* 'try' block 'except' except_stmt block 'end' */
+ scan_next_token(parser); /* skip 'try' */
+ jcatch = be_code_exblk(parser->finfo, 0);
+ block(parser, BLOCK_EXCEPT);
+ be_code_exblk(parser->finfo, 1);
+ jbrk = be_code_jump(parser->finfo);
+ except_block(parser, &jcatch, &jbrk);
+ while (next_type(parser) == KeyExcept) {
+ except_block(parser, &jcatch, &jbrk);
+ }
+ be_code_patchjump(parser->finfo, jcatch);
+ be_code_raise(parser->finfo, NULL, NULL);
+ be_code_patchjump(parser->finfo, jbrk);
+ match_token(parser, KeyEnd); /* skip 'end' */
+}
+
+static void throw_stmt(bparser *parser)
+{
+ bexpdesc e1, e2;
+ /* 'raise' expr */
+ scan_next_token(parser); /* skip 'raise' */
+ expr(parser, &e1);
+ check_var(parser, &e1);
+ if (match_skip(parser, OptComma)) {
+ expr(parser, &e2);
+ check_var(parser, &e2);
+ be_code_raise(parser->finfo, &e1, &e2);
+ } else {
+ be_code_raise(parser->finfo, &e1, NULL);
+ }
+}
+
+static void statement(bparser *parser)
+{
+ switch (next_type(parser)) {
+ case KeyIf: if_stmt(parser); break;
+ case KeyWhile: while_stmt(parser); break;
+ case KeyFor: for_stmt(parser); break;
+ case KeyDo: do_stmt(parser); break;
+ case KeyBreak: break_stmt(parser); break;
+ case KeyContinue: continue_stmt(parser); break;
+ case KeyDef: def_stmt(parser); break;
+ case KeyClass: class_stmt(parser); break;
+ case KeyReturn: return_stmt(parser); break;
+ case KeyImport: import_stmt(parser); break;
+ case KeyVar: var_stmt(parser); break;
+ case KeyTry: try_stmt(parser); break;
+ case KeyRaise: throw_stmt(parser); break;
+ case OptSemic: scan_next_token(parser); break; /* empty statement */
+ default: expr_stmt(parser); break;
+ }
+ be_assert(parser->finfo->freereg == be_list_count(parser->finfo->local));
+}
+
+static void stmtlist(bparser *parser)
+{
+ while (block_follow(parser)) {
+ statement(parser);
+ }
+}
+
+static void block(bparser *parser, int type)
+{
+ bblockinfo binfo;
+ begin_block(parser->finfo, &binfo, type);
+ stmtlist(parser);
+ end_block(parser);
+}
+
+static void mainfunc(bparser *parser, bclosure *cl)
+{
+ bblockinfo binfo;
+ bfuncinfo finfo;
+ begin_func(parser, &finfo, &binfo);
+ finfo.proto->argc = 0; /* args */
+ finfo.proto->name = be_newstr(parser->vm, funcname(parser));
+ cl->proto = finfo.proto;
+ be_remove(parser->vm, -3); /* pop proto from stack */
+ stmtlist(parser);
+ end_func(parser);
+ match_token(parser, TokenEOS); /* skip EOS */
+}
+
+bclosure* be_parser_source(bvm *vm,
+ const char *fname, breader reader, void *data, bbool islocal)
+{
+ bparser parser;
+ bclosure *cl = be_newclosure(vm, 0);
+ parser.vm = vm;
+ parser.finfo = NULL;
+ parser.cl = cl;
+ parser.islocal = (bbyte)islocal;
+ var_setclosure(vm->top, cl);
+ be_stackpush(vm);
+ be_lexer_init(&parser.lexer, vm, fname, reader, data);
+ scan_next_token(&parser); /* scan first token */
+ mainfunc(&parser, cl);
+ be_lexer_deinit(&parser.lexer);
+ be_global_release_space(vm); /* clear global space */
+ be_stackpop(vm, 2); /* pop strtab */
+ scan_next_token(&parser); /* clear lexer */
+ return cl;
+}
+
+#endif
diff --git a/lib/libesp32/berry/src/be_parser.h b/lib/libesp32/berry/src/be_parser.h
new file mode 100644
index 000000000..5b5510f2c
--- /dev/null
+++ b/lib/libesp32/berry/src/be_parser.h
@@ -0,0 +1,89 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_PARSER_H
+#define BE_PARSER_H
+
+#include "be_object.h"
+#include "be_string.h"
+
+typedef enum {
+ ETVOID, /* unknown (new variable or error) */
+ ETNIL,
+ ETBOOL,
+ ETREAL,
+ ETINT,
+ ETSTRING,
+ ETPROTO,
+ ETCONST,
+ ETLOCAL, /* local variable, allocated until end of scope */
+ ETGLOBAL, /* global by index number */
+ ETUPVAL,
+ ETMEMBER, /* member accessor (by name) */
+ ETINDEX, /* index accessor (ex array index) */
+ ETREG, /* temporary register, can be freed if top of stack */
+ ETNGLOBAL /* named global */
+} exptype_t;
+
+typedef struct {
+ union {
+ struct { /* for suffix */
+ unsigned int idx:9; /* suffix RK index */
+ unsigned int obj:9; /* object RK index */
+ unsigned int tt:5; /* object type */
+ } ss;
+ breal r; /* for ETREAL */
+ bint i; /* for ETINT */
+ bstring *s; /* for ETSTRING */
+ bproto *p; /* for ETPROTO */
+ int idx; /* variable index */
+ } v;
+ int t; /* patch list of 'exit when true' */
+ int f; /* patch list of 'exit when false' */
+ bbyte not; /* not mark */
+ bbyte type;
+} bexpdesc;
+
+typedef struct bblockinfo {
+ struct bblockinfo *prev;
+ bbyte nactlocals; /* number of active local variables */
+ bbyte type; /* block type mask */
+ bbyte hasupval; /* has upvalue mark */
+ int breaklist; /* break list */
+ int beginpc; /* begin pc */
+ int continuelist; /* continue list */
+} bblockinfo;
+
+typedef struct bfuncinfo {
+ struct bfuncinfo *prev; /* outer function */
+ bproto *proto; /* the function prototype */
+ bblockinfo *binfo; /* block information */
+ struct blexer *lexer; /* the lexer pointer */
+ blist *local; /* local variable */
+ bmap *upval; /* upvalue variable */
+ bvector code; /* code vector */
+ bvector kvec; /* constants table */
+ bvector pvec; /* proto table */
+#if BE_DEBUG_RUNTIME_INFO /* debug information */
+ bvector linevec;
+#endif
+#if BE_DEBUG_VAR_INFO
+ bvector varvec;
+#endif
+ int pc; /* program count */
+ bbyte freereg; /* first free register */
+ bbyte flags; /* some flages */
+} bfuncinfo;
+
+/* code block type definitions */
+#define BLOCK_LOOP 1
+#define BLOCK_EXCEPT 2
+
+bclosure *be_parser_source(bvm *vm,
+ const char *fname, breader reader, void *data, bbool islocal);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_rangelib.c b/lib/libesp32/berry/src/be_rangelib.c
new file mode 100644
index 000000000..3682ae3ce
--- /dev/null
+++ b/lib/libesp32/berry/src/be_rangelib.c
@@ -0,0 +1,123 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_func.h"
+#include "be_vm.h"
+
+static int m_init(bvm *vm)
+{
+ be_pushvalue(vm, 2);
+ be_setmember(vm, 1, "__lower__");
+ be_pop(vm, 1);
+ be_pushvalue(vm, 3);
+ be_setmember(vm, 1, "__upper__");
+ be_return_nil(vm);
+}
+
+static int m_tostring(bvm *vm)
+{
+ be_pushstring(vm, "(");
+ be_getmember(vm, 1, "__lower__");
+ be_tostring(vm, -1);
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ be_pushstring(vm, "..");
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ be_getmember(vm, 1, "__upper__");
+ be_tostring(vm, -1);
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ be_pushstring(vm, ")");
+ be_strconcat(vm, -2);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+static int m_upper(bvm *vm)
+{
+ be_getmember(vm, 1, "__upper__");
+ be_return(vm);
+}
+
+static int m_lower(bvm *vm)
+{
+ be_getmember(vm, 1, "__lower__");
+ be_return(vm);
+}
+
+static int m_setrange(bvm *vm)
+{
+ be_pushvalue(vm, 2);
+ be_setmember(vm, 1, "__lower__");
+ be_pop(vm, 1);
+ be_pushvalue(vm, 3);
+ be_setmember(vm, 1, "__upper__");
+ be_return_nil(vm);
+}
+
+static int iter_closure(bvm *vm)
+{
+ /* for better performance, we operate the upvalues
+ * directly without using by the stack. */
+ bntvclos *func = var_toobj(vm->cf->func);
+ bvalue *uv0 = be_ntvclos_upval(func, 0)->value;
+ bvalue *uv1 = be_ntvclos_upval(func, 1)->value;
+ bint lower = var_toint(uv0); /* upvalue[0] => lower */
+ bint upper = var_toint(uv1); /* upvalue[1] => upper */
+ if (lower > upper) {
+ be_stop_iteration(vm);
+ }
+ var_toint(uv0) = lower + 1; /* set upvale[0] */
+ be_pushint(vm, lower); /* push the return value */
+ be_return(vm);
+}
+
+static int m_iter(bvm *vm)
+{
+ be_pushntvclosure(vm, iter_closure, 2);
+ be_getmember(vm, 1, "__lower__");
+ be_setupval(vm, -2, 0);
+ be_pop(vm, 1);
+ be_getmember(vm, 1, "__upper__");
+ be_setupval(vm, -2, 1);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+void be_load_rangelib(bvm *vm)
+{
+ static const bnfuncinfo members[] = {
+ { "__lower__", NULL },
+ { "__upper__", NULL },
+ { "init", m_init },
+ { "tostring", m_tostring },
+ { "lower", m_lower },
+ { "upper", m_upper },
+ { "setrange", m_setrange },
+ { "iter", m_iter },
+ { NULL, NULL }
+ };
+ be_regclass(vm, "range", members);
+}
+#else
+/* @const_object_info_begin
+class be_class_range (scope: global, name: range) {
+ __lower__, var
+ __upper__, var
+ init, func(m_init)
+ tostring, func(m_tostring)
+ lower, func(m_lower)
+ upper, func(m_upper)
+ setrange, func(m_setrange)
+ iter, func(m_iter)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_be_class_range.h"
+#endif
diff --git a/lib/libesp32/berry/src/be_repl.c b/lib/libesp32/berry/src/be_repl.c
new file mode 100644
index 000000000..17b766df7
--- /dev/null
+++ b/lib/libesp32/berry/src/be_repl.c
@@ -0,0 +1,106 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "berry.h"
+#include "be_repl.h"
+#include
+
+#define safecall(func, ...) if (func) { func(__VA_ARGS__); }
+
+#if BE_USE_SCRIPT_COMPILER
+
+static int try_return(bvm *vm, const char *line)
+{
+ int res, idx;
+ line = be_pushfstring(vm, "return (%s)", line);
+ idx = be_absindex(vm, -1); /* get the source text absolute index */
+ res = be_loadbuffer(vm, "stdin", line, strlen(line)); /* compile line */
+ be_remove(vm, idx); /* remove source string */
+ return res;
+}
+
+static bbool is_multline(bvm *vm)
+{
+ const char *msg = be_tostring(vm, -1);
+ size_t len = strlen(msg);
+ if (len > 5) { /* multi-line text if the error message is 'EOS' at the end */
+ return !strcmp(msg + len - 5, "'EOS'");
+ }
+ return bfalse;
+}
+
+static int compile(bvm *vm, char *line, breadline getl, bfreeline freel)
+{
+ int res = try_return(vm, line);
+ if (be_getexcept(vm, res) == BE_SYNTAX_ERROR) {
+ be_pop(vm, 2); /* pop exception values */
+ be_pushstring(vm, line);
+ safecall(freel, line); /* free line buffer */
+ for (;;) {
+ const char *src = be_tostring(vm, -1); /* get source code */
+ int idx = be_absindex(vm, -1); /* get the source text absolute index */
+ /* compile source line */
+ res = be_loadbuffer(vm, "stdin", src, strlen(src));
+ if (!res || !is_multline(vm)) {
+ be_remove(vm, idx); /* remove source code */
+ return res;
+ }
+ be_pop(vm, 2); /* pop exception values */
+ line = getl(">> "); /* read a new input line */
+ be_pushfstring(vm, "\n%s", line);
+ safecall(freel, line); /* free line buffer */
+ be_strconcat(vm, -2);
+ be_pop(vm, 1); /* pop new line */
+ }
+ } else {
+ safecall(freel, line); /* free line buffer */
+ }
+ return res;
+}
+
+static int call_script(bvm *vm)
+{
+ int res = be_pcall(vm, 0); /* call the main function */
+ switch (res) {
+ case BE_OK: /* execution succeed */
+ if (!be_isnil(vm, -1)) { /* print return value when it's not nil */
+ be_dumpvalue(vm, -1);
+ }
+ be_pop(vm, 1); /* pop the result value */
+ break;
+ case BE_EXCEPTION: /* vm run error */
+ be_dumpexcept(vm);
+ be_pop(vm, 1); /* pop the function value */
+ break;
+ default: /* BE_EXIT or BE_MALLOC_FAIL */
+ return res;
+ }
+ return 0;
+}
+
+BERRY_API int be_repl(bvm *vm, breadline getline, bfreeline freeline)
+{
+ char *line;
+ be_assert(getline != NULL);
+ while ((line = getline("> ")) != NULL) {
+ int res = compile(vm, line, getline, freeline);
+ if (res == BE_MALLOC_FAIL)
+ return BE_MALLOC_FAIL;
+ if (res) {
+ be_dumpexcept(vm);
+ } else { /* compiled successfully */
+ res = call_script(vm);
+ if (res) {
+ return res == BE_EXIT ? be_toindex(vm, -1) : res;
+ }
+ }
+ }
+ be_writenewline();
+ return 0;
+}
+
+#endif
diff --git a/lib/libesp32/berry/src/be_repl.h b/lib/libesp32/berry/src/be_repl.h
new file mode 100644
index 000000000..7d27e7850
--- /dev/null
+++ b/lib/libesp32/berry/src/be_repl.h
@@ -0,0 +1,26 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_REPL_H
+#define BE_REPL_H
+
+#include "berry.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef char* (*breadline)(const char *prompt);
+typedef void (*bfreeline)(char *ptr);
+
+BERRY_API int be_repl(bvm *vm, breadline getline, bfreeline freeline);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesp32/berry/src/be_solidifylib.c b/lib/libesp32/berry/src/be_solidifylib.c
new file mode 100644
index 000000000..581131b75
--- /dev/null
+++ b/lib/libesp32/berry/src/be_solidifylib.c
@@ -0,0 +1,517 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_module.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_class.h"
+#include "be_list.h"
+#include "be_debug.h"
+#include "be_map.h"
+#include "be_vm.h"
+#include "be_decoder.h"
+#include
+#include
+#include
+
+extern const bclass be_class_list;
+extern const bclass be_class_map;
+
+#if BE_USE_SOLIDIFY_MODULE
+#include
+
+#ifndef INST_BUF_SIZE
+#define INST_BUF_SIZE 288
+#endif
+
+#define logbuf(...) snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__)
+
+#define logfmt(...) \
+ do { \
+ char __lbuf[INST_BUF_SIZE]; \
+ logbuf(__VA_ARGS__); \
+ be_writestring(__lbuf); \
+ } while (0)
+
+/********************************************************************
+ * Encode string to identifiers
+ *
+ * `_X` is used as an escape marker
+/********************************************************************/
+static unsigned toidentifier_length(const char *s)
+{
+ unsigned len = 1;
+ const char * p = s;
+ while (*p) {
+ if (p[0] == '_' && p[1] == 'X') {
+ len += 3;
+ p += 2;
+ } else if (isalnum(p[0]) || p[0] == '_') {
+ p++;
+ len++;
+ } else { // escape
+ p++;
+ len += 4;
+ }
+ }
+ return len;
+}
+
+inline static char hexdigit(int v)
+{
+ v = v & 0xF;
+ if (v >= 10) return v - 10 + 'A';
+ return v + '0';
+}
+
+static void toidentifier(char *to, const char *p)
+{
+ while (*p) {
+ if (p[0] == '_' && p[1] == 'X') {
+ to[0] = '_';
+ to[1] = 'X';
+ to[2] = '_';
+ p += 2;
+ to += 3;
+ } else if (isalnum(p[0]) || p[0] == '_') {
+ *to = *p;
+ to++;
+ p++;
+ } else { // escape
+ to[0] = '_';
+ to[1] = 'X';
+ to[2] = hexdigit((*p & 0xF0) >> 4);
+ to[3] = hexdigit(*p & 0x0F);
+ p++;
+ to += 4;
+ }
+ }
+ *to = 0; // final NULL
+}
+
+static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, const char *key);
+
+static void m_solidify_map(bvm *vm, bmap * map, const char *class_name)
+{
+ // compact first
+ be_map_compact(vm, map);
+
+ logfmt(" be_nested_map(%i,\n", map->count);
+
+ logfmt(" ( (struct bmapnode*) &(const bmapnode[]) {\n");
+ for (int i = 0; i < map->size; i++) {
+ bmapnode * node = &map->slots[i];
+ if (node->key.type == BE_NIL) {
+ continue; /* key not used */
+ }
+ if (node->key.type != BE_STRING) {
+ char error[64];
+ snprintf(error, sizeof(error), "Unsupported type in key: %i", node->key.type);
+ be_raise(vm, "internal_error", error);
+ }
+ int key_next = node->key.next;
+ size_t len = strlen(str(node->key.v.s));
+ if (0xFFFFFF == key_next) {
+ key_next = -1; /* more readable */
+ }
+ /* convert the string literal to identifier */
+ const char * key = str(node->key.v.s);
+ size_t id_len = toidentifier_length(key);
+ char id_buf[id_len];
+ toidentifier(id_buf, key);
+ logfmt(" { be_const_key(%s, %i), ", id_buf, key_next);
+ m_solidify_bvalue(vm, &node->value, class_name, str(node->key.v.s));
+
+ logfmt(" },\n");
+ }
+ logfmt(" }))"); // TODO need terminal comma?
+
+}
+
+static void m_solidify_list(bvm *vm, blist * list, const char *class_name)
+{
+ logfmt(" be_nested_list(%i,\n", list->count);
+
+ logfmt(" ( (struct bvalue*) &(const bvalue[]) {\n");
+ for (int i = 0; i < list->count; i++) {
+ logfmt(" ");
+ m_solidify_bvalue(vm, &list->data[i], class_name, "");
+ logfmt(",\n");
+ }
+ logfmt(" }))"); // TODO need terminal comma?
+}
+
+// pass key name in case of class, or NULL if none
+static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, const char *key)
+{
+ int type = var_type(value);
+ switch (type) {
+ case BE_NIL:
+ logfmt("be_const_nil()");
+ break;
+ case BE_BOOL:
+ logfmt("be_const_bool(%i)", var_tobool(value));
+ break;
+ case BE_INT:
+#if BE_INTGER_TYPE == 2
+ logfmt("be_const_int(%lli)", var_toint(value));
+#else
+ logfmt("be_const_int(%li)", var_toint(value));
+#endif
+ break;
+ case BE_INDEX:
+#if BE_INTGER_TYPE == 2
+ logfmt("be_const_var(%lli)", var_toint(value));
+#else
+ logfmt("be_const_var(%li)", var_toint(value));
+#endif
+ break;
+ case BE_REAL:
+#if BE_USE_SINGLE_FLOAT
+ logfmt("be_const_real_hex(0x%08X)", (uint32_t) var_toobj(value));
+#else
+ logfmt("be_const_real_hex(0x%016" PRIx64 ")", (uint64_t)var_toobj(value));
+#endif
+ break;
+ case BE_STRING:
+ {
+ const char * str = str(var_tostr(value));
+ size_t len = strlen(str);
+ if (len >= 255) {
+ be_raise(vm, "internal_error", "Strings greater than 255 chars not supported yet");
+ }
+ size_t id_len = toidentifier_length(str);
+ char id_buf[id_len];
+ toidentifier(id_buf, str);
+ logfmt("be_nested_str(%s)", id_buf);
+ }
+ break;
+ case BE_CLOSURE:
+ logfmt("be_const_%sclosure(%s%s%s_closure)",
+ func_isstatic(value) ? "static_" : "",
+ classname ? classname : "", classname ? "_" : "",
+ str(((bclosure*) var_toobj(value))->proto->name));
+ break;
+ case BE_CLASS:
+ logfmt("be_const_class(be_class_%s)", str(((bclass*) var_toobj(value))->name));
+ break;
+ case BE_COMPTR:
+ logfmt("be_const_comptr(&be_ntv_%s_%s)", classname ? classname : "unknown", key ? key : "unknown");
+ break;
+ case BE_NTVFUNC:
+ logfmt("be_const_%sfunc(be_ntv_%s_%s)",
+ func_isstatic(value) ? "static_" : "",
+ classname ? classname : "unknown", key ? key : "unknown");
+ break;
+ case BE_INSTANCE:
+ {
+ binstance * ins = (binstance *) var_toobj(value);
+ bclass * cl = ins->_class;
+ if (ins->super || ins->sub) {
+ be_raise(vm, "internal_error", "instance must not have a super/sub class");
+ } else if (cl->nvar != 1) {
+ be_raise(vm, "internal_error", "instance must have only one instance variable");
+ } else if ((cl != &be_class_map && cl != &be_class_list) || 1) { // TODO
+ const char * cl_ptr = "";
+ if (cl == &be_class_map) { cl_ptr = "map"; }
+ if (cl == &be_class_list) { cl_ptr = "list"; }
+ logfmt("be_const_simple_instance(be_nested_simple_instance(&be_class_%s, {\n", cl_ptr);
+ if (cl == &be_class_map) {
+ logfmt(" be_const_map( * ");
+ } else {
+ logfmt(" be_const_list( * ");
+ }
+ m_solidify_bvalue(vm, &ins->members[0], classname, key);
+ logfmt(" ) } ))");
+ }
+ }
+ break;
+ case BE_MAP:
+ m_solidify_map(vm, (bmap *) var_toobj(value), classname);
+ break;
+ case BE_LIST:
+ m_solidify_list(vm, (blist *) var_toobj(value), classname);
+ break;
+ default:
+ {
+ char error[64];
+ snprintf(error, sizeof(error), "Unsupported type in function constants: %i", type);
+ be_raise(vm, "internal_error", error);
+ }
+ }
+}
+
+static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins);
+
+/* solidify any inner class */
+static void m_solidify_proto_inner_class(bvm *vm, bproto *pr, int builtins)
+{
+ // parse any class in constants to output it first
+ if (pr->nconst > 0) {
+ for (int k = 0; k < pr->nconst; k++) {
+ if (var_type(&pr->ktab[k]) == BE_CLASS) {
+ // output the class
+ m_solidify_subclass(vm, (bclass*) var_toobj(&pr->ktab[k]), builtins);
+ }
+ }
+ }
+}
+
+
+static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int builtins, int indent)
+{
+ // const char * func_name = str(pr->name);
+ // const char * func_source = str(pr->source);
+
+ logfmt("%*sbe_nested_proto(\n", indent, "");
+ indent += 2;
+
+ logfmt("%*s%d, /* nstack */\n", indent, "", pr->nstack);
+ logfmt("%*s%d, /* argc */\n", indent, "", pr->argc);
+ logfmt("%*s%d, /* varg */\n", indent, "", pr->varg);
+ logfmt("%*s%d, /* has upvals */\n", indent, "", (pr->nupvals > 0) ? 1 : 0);
+
+ if (pr->nupvals > 0) {
+ logfmt("%*s( &(const bupvaldesc[%2d]) { /* upvals */\n", indent, "", pr->nupvals);
+ for (int32_t i = 0; i < pr->nupvals; i++) {
+ logfmt("%*s be_local_const_upval(%i, %i),\n", indent, "", pr->upvals[i].instack, pr->upvals[i].idx);
+ }
+ logfmt("%*s}),\n", indent, "");
+ } else {
+ logfmt("%*sNULL, /* no upvals */\n", indent, "");
+ }
+
+ logfmt("%*s%d, /* has sup protos */\n", indent, "", (pr->nproto > 0) ? 1 : 0);
+ if (pr->nproto > 0) {
+ logfmt("%*s( &(const struct bproto*[%2d]) {\n", indent, "", pr->nproto);
+ for (int32_t i = 0; i < pr->nproto; i++) {
+ size_t sub_len = strlen(func_name) + 10;
+ char sub_name[sub_len];
+ snprintf(sub_name, sizeof(sub_name), "%s_%d", func_name, i);
+ m_solidify_proto(vm, pr->ptab[i], sub_name, builtins, indent+2);
+ logfmt(",\n");
+ }
+ logfmt("%*s}),\n", indent, "");
+ } else {
+ logfmt("%*sNULL, /* no sub protos */\n", indent, "");
+ }
+
+ logfmt("%*s%d, /* has constants */\n", indent, "", (pr->nconst > 0) ? 1 : 0);
+ if (pr->nconst > 0) {
+ logfmt("%*s( &(const bvalue[%2d]) { /* constants */\n", indent, "", pr->nconst);
+ for (int k = 0; k < pr->nconst; k++) {
+ logfmt("%*s/* K%-3d */ ", indent, "", k);
+ m_solidify_bvalue(vm, &pr->ktab[k], NULL, NULL);
+ logfmt(",\n");
+ }
+ logfmt("%*s}),\n", indent, "");
+ } else {
+ logfmt("%*sNULL, /* no const */\n", indent, "");
+ }
+
+ /* convert the string literal to identifier */
+ {
+ const char * key = str(pr->name);
+ size_t id_len = toidentifier_length(key);
+ char id_buf[id_len];
+ toidentifier(id_buf, key);
+ logfmt("%*s&be_const_str_%s,\n", indent, "", id_buf);
+ }
+ // hard-code source as "solidified" for solidified
+ logfmt("%*s&be_const_str_solidified,\n", indent, "");
+
+ logfmt("%*s( &(const binstruction[%2d]) { /* code */\n", indent, "", pr->codesize);
+ for (int pc = 0; pc < pr->codesize; pc++) {
+ uint32_t ins = pr->code[pc];
+ logfmt("%*s 0x%08X, //", indent, "", ins);
+ be_print_inst(ins, pc);
+ bopcode op = IGET_OP(ins);
+ if (op == OP_GETGBL || op == OP_SETGBL) {
+ // check if the global is in built-ins
+ int glb = IGET_Bx(ins);
+ if (glb > builtins) {
+ // not supported
+ logfmt("\n===== unsupported global G%d\n", glb);
+ be_raise(vm, "internal_error", "Unsupported access to non-builtin global");
+ }
+ }
+ }
+ logfmt("%*s})\n", indent, "");
+ indent -= 2;
+ logfmt("%*s)", indent, "");
+
+}
+
+static void m_solidify_closure(bvm *vm, bclosure *cl, const char * classname, int builtins)
+{
+ bproto *pr = cl->proto;
+ const char * func_name = str(pr->name);
+
+ if (cl->nupvals > 0) {
+ be_raise(vm, "internal_error", "Unsupported upvals in closure");
+ }
+
+ int indent = 2;
+
+ m_solidify_proto_inner_class(vm, pr, builtins);
+
+ logfmt("\n");
+ logfmt("/********************************************************************\n");
+ logfmt("** Solidified function: %s\n", func_name);
+ logfmt("********************************************************************/\n");
+
+ logfmt("be_local_closure(%s%s%s, /* name */\n",
+ classname ? classname : "", classname ? "_" : "",
+ func_name);
+
+ m_solidify_proto(vm, pr, func_name, builtins, indent);
+ logfmt("\n");
+
+ // closure
+ logfmt(");\n");
+ logfmt("/*******************************************************************/\n\n");
+}
+
+static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins)
+{
+ const char * class_name = str(cl->name);
+
+ /* iterate on members to dump closures */
+ if (cl->members) {
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(cl->members, &iter)) != NULL) {
+ if (var_isstr(&node->key) && var_isclosure(&node->value)) {
+ bclosure *f = var_toobj(&node->value);
+ m_solidify_closure(vm, f, class_name, builtins);
+ }
+ }
+ }
+
+
+ logfmt("\n");
+ logfmt("/********************************************************************\n");
+ logfmt("** Solidified class: %s\n", class_name);
+ logfmt("********************************************************************/\n");
+
+ if (cl->super) {
+ logfmt("extern const bclass be_class_%s;\n", str(cl->super->name));
+ }
+
+ logfmt("be_local_class(%s,\n", class_name);
+ logfmt(" %i,\n", cl->nvar);
+ if (cl->super) {
+ logfmt(" &be_class_%s,\n", str(cl->super->name));
+ } else {
+ logfmt(" NULL,\n");
+ }
+
+ if (cl->members) {
+ m_solidify_map(vm, cl->members, class_name);
+ logfmt(",\n");
+ } else {
+ logfmt(" NULL,\n");
+ }
+
+ logfmt(" be_str_literal(\"%s\")\n", class_name);
+ logfmt(");\n");
+
+}
+
+
+static void m_solidify_class(bvm *vm, bclass *cl, int builtins)
+{
+ const char * class_name = str(cl->name);
+ m_solidify_subclass(vm, cl, builtins);
+ logfmt("/*******************************************************************/\n\n");
+
+ logfmt("void be_load_%s_class(bvm *vm) {\n", class_name);
+ logfmt(" be_pushntvclass(vm, &be_class_%s);\n", class_name);
+ logfmt(" be_setglobal(vm, \"%s\");\n", class_name);
+ logfmt(" be_pop(vm, 1);\n");
+ logfmt("}\n");
+}
+
+static void m_solidify_module(bvm *vm, bmodule *ml, int builtins)
+{
+ const char * module_name = be_module_name(ml);
+ if (!module_name) { module_name = ""; }
+
+ /* iterate on members to dump closures and classes */
+ if (ml->table) {
+ bmapnode *node;
+ bmapiter iter = be_map_iter();
+ while ((node = be_map_next(ml->table, &iter)) != NULL) {
+ if (var_isstr(&node->key) && var_isclosure(&node->value)) {
+ bclosure *f = var_toobj(&node->value);
+ m_solidify_closure(vm, f, module_name, builtins);
+ }
+ if (var_isstr(&node->key) && var_isclass(&node->value)) {
+ bclass *cl = var_toobj(&node->value);
+ m_solidify_subclass(vm, cl, builtins);
+ }
+ }
+ }
+
+
+ logfmt("\n");
+ logfmt("/********************************************************************\n");
+ logfmt("** Solidified module: %s\n", module_name);
+ logfmt("********************************************************************/\n");
+
+ logfmt("be_local_module(%s,\n", module_name);
+ logfmt(" \"%s\",\n", module_name);
+
+ if (ml->table) {
+ m_solidify_map(vm, ml->table, module_name);
+ logfmt("\n");
+ } else {
+ logfmt(" NULL,\n");
+ }
+ logfmt(");\n");
+ logfmt("BE_EXPORT_VARIABLE be_define_const_native_module(%s);\n", module_name);
+ logfmt("/********************************************************************/\n");
+
+}
+
+#define be_builtin_count(vm) \
+ be_vector_count(&(vm)->gbldesc.builtin.vlist)
+
+static int m_dump(bvm *vm)
+{
+ if (be_top(vm) >= 1) {
+ bvalue *v = be_indexof(vm, 1);
+ if (var_isclosure(v)) {
+ m_solidify_closure(vm, var_toobj(v), NULL, be_builtin_count(vm));
+ } else if (var_isclass(v)) {
+ m_solidify_class(vm, var_toobj(v), be_builtin_count(vm));
+ } else if (var_ismodule(v)) {
+ m_solidify_module(vm, var_toobj(v), be_builtin_count(vm));
+ } else {
+ be_raise(vm, "value_error", "unsupported type");
+ }
+ }
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(solidify) {
+ be_native_module_function("dump", m_dump),
+};
+
+be_define_native_module(solidify, NULL);
+#else
+/* @const_object_info_begin
+module solidify (scope: global, depend: BE_USE_SOLIDIFY_MODULE) {
+ dump, func(m_dump)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_solidify.h"
+#endif
+
+#endif /* BE_USE_SOLIFIDY_MODULE */
diff --git a/lib/libesp32/berry/src/be_strictlib.c b/lib/libesp32/berry/src/be_strictlib.c
new file mode 100644
index 000000000..b40329886
--- /dev/null
+++ b/lib/libesp32/berry/src/be_strictlib.c
@@ -0,0 +1,40 @@
+/********************************************************************
+** Copyright (c) 2018-2021 Guan Wenliang & Stephan Hadinger
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+#include "be_module.h"
+#include "be_string.h"
+#include "be_vector.h"
+#include "be_class.h"
+#include "be_debug.h"
+#include "be_map.h"
+#include "be_vm.h"
+
+#if BE_USE_STRICT_MODULE
+
+static int m_init(bvm *vm)
+{
+ comp_set_strict(vm); /* enable compiler strict mode */
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(strict) {
+ be_native_module_function("init", m_init),
+};
+
+be_define_native_module(strict, NULL);
+#else
+/* @const_object_info_begin
+module strict (scope: strict, depend: BE_USE_STRICT_MODULE) {
+ init, func(m_init)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_strict.h"
+#endif
+
+#endif /* BE_USE_STRICT_MODULE */
diff --git a/lib/libesp32/berry/src/be_string.c b/lib/libesp32/berry/src/be_string.c
new file mode 100644
index 000000000..798437420
--- /dev/null
+++ b/lib/libesp32/berry/src/be_string.c
@@ -0,0 +1,302 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_string.h"
+#include "be_vm.h"
+#include "be_mem.h"
+#include "be_constobj.h"
+#include
+
+#define next(_s) cast(void*, cast(bstring*, (_s)->next))
+#define sstr(_s) cast(char*, cast(bsstring*, _s) + 1)
+#define lstr(_s) cast(char*, cast(blstring*, _s) + 1)
+#define cstr(_s) (cast(bcstring*, _s)->s)
+
+#define be_define_const_str(_name, _s, _hash, _extra, _len, _next) \
+ BERRY_LOCAL const bcstring be_const_str_##_name = { \
+ .next = (bgcobject *)_next, \
+ .type = BE_STRING, \
+ .marked = GC_CONST, \
+ .extra = _extra, \
+ .slen = _len, \
+ .hash = _hash, \
+ .s = _s \
+ }
+
+/* const string table */
+struct bconststrtab {
+ const bstring* const *table;
+ int count; /* string count */
+ int size;
+};
+
+#if BE_USE_PRECOMPILED_OBJECT
+#include "../generate/be_const_strtab_def.h"
+#endif
+
+int be_eqstr(bstring *s1, bstring *s2)
+{
+ int slen;
+ if (s1 == s2) { /* short string or the same string */
+ return 1;
+ }
+ slen = s1->slen;
+ /* discard different lengths */
+ if (slen != s2->slen) {
+ return 0;
+ }
+ /* long string */
+ if (slen == 255) { /* s2->slen is also 255 */
+ blstring *ls1 = cast(blstring*, s1);
+ blstring *ls2 = cast(blstring*, s2);
+ return ls1->llen == ls2->llen && !strcmp(lstr(ls1), lstr(ls2));
+ }
+ /* const short strings */
+ if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */
+ uint32_t hash1 = cast(bcstring*, s1)->hash;
+ uint32_t hash2 = cast(bcstring*, s2)->hash;
+ if (hash1 && hash2 && hash1 != hash2) {
+ return 0; /* if hash differ, since we know both are non-null */
+ }
+ /* if hash are equals, there might be a chance that they are different */
+ /* This can happen with solidified code that a same string is present more than once */
+ /* so just considering that two strings with the same hash must be same pointer, this is no more true */
+ return !strcmp(str(s1), str(s2));
+ }
+
+ /* if both strings are in-memory, they can't be equal without having the same pointer */
+ return 0;
+}
+
+static void resize(bvm *vm, int size)
+{
+ int i;
+ struct bstringtable *tab = &vm->strtab;
+ if (size > tab->size) {
+ tab->table = be_realloc(vm, tab->table,
+ tab->size * sizeof(bstring*), size * sizeof(bstring*));
+ for (i = tab->size; i < size; ++i) {
+ tab->table[i] = NULL;
+ }
+ }
+ for (i = 0; i < tab->size; ++i) { /* rehash */
+ bstring *p = tab->table[i];
+ tab->table[i] = NULL;
+ while (p) { /* for each node in the list */
+ bstring *hnext = next(p);
+ uint32_t hash = be_strhash(p) & (size - 1);
+ p->next = cast(void*, tab->table[hash]);
+ tab->table[hash] = p;
+ p = hnext;
+ }
+ }
+ if (size < tab->size) {
+ for (i = size; i < tab->size; ++i) {
+ tab->table[i] = NULL;
+ }
+ tab->table = be_realloc(vm, tab->table,
+ tab->size * sizeof(bstring*), size * sizeof(bstring*));
+ }
+ tab->size = size;
+}
+
+static void free_sstring(bvm *vm, bstring *str)
+{
+ be_free(vm, str, sizeof(bsstring) + str->slen + 1);
+}
+
+/* FNV-1a Hash */
+static uint32_t str_hash(const char *str, size_t len)
+{
+ uint32_t hash = 2166136261u;
+ be_assert(str || len);
+ while (len--) {
+ hash = (hash ^ (unsigned char)*str++) * 16777619u;
+ }
+ return hash;
+}
+
+void be_string_init(bvm *vm)
+{
+ resize(vm, 8);
+#if !BE_USE_PRECOMPILED_OBJECT
+ /* the destructor name deinit needs to exist all the time, to ensure
+ * that it does not need to be created when the heap is exhausted. */
+ be_gc_fix(vm, cast(bgcobject*, str_literal(vm, "deinit")));
+#endif
+ /* be_const_str_deinit --> for precompiled */
+}
+
+void be_string_deleteall(bvm *vm)
+{
+ int i;
+ struct bstringtable *tab = &vm->strtab;
+ for (i = 0; i < tab->size; ++i) {
+ bstring *node = tab->table[i];
+ while (node) {
+ bstring *next = next(node);
+ free_sstring(vm, node);
+ node = next;
+ }
+ }
+ be_free(vm, tab->table, tab->size * sizeof(bstring*));
+}
+
+static bstring* createstrobj(bvm *vm, size_t len, int islong)
+{
+ size_t size = (islong ? sizeof(blstring)
+ : sizeof(bsstring)) + len + 1;
+ bgcobject *gco = be_gc_newstr(vm, size, islong);
+ bstring *s = cast_str(gco);
+ if (s) {
+ s->slen = islong ? 255 : (bbyte)len;
+ char *str = cast(char *, islong ? lstr(s) : sstr(s));
+ str[len] = '\0';
+ }
+ return s;
+}
+
+#if BE_USE_PRECOMPILED_OBJECT
+static bstring* find_conststr(const char *str, size_t len)
+{
+ const struct bconststrtab *tab = &m_const_string_table;
+ uint32_t hash = str_hash(str, len);
+ bcstring *s = (bcstring*)tab->table[hash % tab->size];
+ for (; s != NULL; s = next(s)) {
+ if (len == s->slen && !strncmp(str, s->s, len)) {
+ return (bstring*)s;
+ }
+ }
+ return NULL;
+}
+#endif
+
+static bstring* newshortstr(bvm *vm, const char *str, size_t len)
+{
+ bstring *s;
+ int size = vm->strtab.size;
+ uint32_t hash = str_hash(str, len);
+ bstring **list = vm->strtab.table + (hash & (size - 1));
+
+ for (s = *list; s != NULL; s = next(s)) {
+ if (len == s->slen && !strncmp(str, sstr(s), len)) {
+ return s;
+ }
+ }
+ s = createstrobj(vm, len, 0);
+ if (s) {
+ memcpy(cast(char *, sstr(s)), str, len);
+ s->extra = 0;
+ s->next = cast(void*, *list);
+#if BE_USE_STR_HASH_CACHE
+ cast(bsstring*, s)->hash = hash;
+#endif
+ *list = s;
+ vm->strtab.count++;
+ if (vm->strtab.count > size << 2) {
+ resize(vm, size << 1);
+ }
+ }
+ return s;
+}
+
+bstring* be_newlongstr(bvm *vm, const char *str, size_t len)
+{
+ bstring *s;
+ blstring *ls;
+ s = createstrobj(vm, len, 1);
+ ls = cast(blstring*, s);
+ s->extra = 0;
+ ls->llen = cast_int(len);
+ if (str) { /* if the argument 'str' is NULL, we just allocate space */
+ memcpy(cast(char *, lstr(s)), str, len);
+ }
+ return s;
+}
+
+bstring* be_newstr(bvm *vm, const char *str)
+{
+ return be_newstrn(vm, str, strlen(str));
+}
+
+bstring *be_newstrn(bvm *vm, const char *str, size_t len)
+{
+ if (len <= SHORT_STR_MAX_LEN) {
+#if BE_USE_PRECOMPILED_OBJECT
+ bstring *s = find_conststr(str, len);
+ return s ? s : newshortstr(vm, str, len);
+#else
+ return newshortstr(vm, str, len);
+#endif
+ }
+ return be_newlongstr(vm, str, len); /* long string */
+}
+
+void be_gcstrtab(bvm *vm)
+{
+ struct bstringtable *tab = &vm->strtab;
+ int size = tab->size, i;
+ for (i = 0; i < size; ++i) {
+ bstring **list = tab->table + i;
+ bstring *prev = NULL, *node, *next;
+ for (node = *list; node; node = next) {
+ next = next(node);
+ if (!gc_isfixed(node) && gc_iswhite(node)) {
+ free_sstring(vm, node);
+ tab->count--;
+ if (prev) { /* link list */
+ prev->next = cast(void*, next);
+ } else {
+ *list = next;
+ }
+ } else {
+ prev = node;
+ gc_setwhite(node);
+ }
+ }
+ }
+ if (tab->count < size >> 2 && size > 8) {
+ resize(vm, size >> 1);
+ }
+}
+
+uint32_t be_strhash(const bstring *s)
+{
+ if (gc_isconst(s)) {
+ bcstring* cs = cast(bcstring*, s);
+ if (cs->hash) { /* if hash is null we need to compute it */
+ return cs->hash;
+ } else {
+ return str_hash(cstr(s), str_len(s));
+ }
+ }
+#if BE_USE_STR_HASH_CACHE
+ if (s->slen != 255) {
+ return cast(bsstring*, s)->hash;
+ }
+#endif
+ return str_hash(str(s), str_len(s));
+}
+
+const char* be_str2cstr(const bstring *s)
+{
+ be_assert(cast_str(s) != NULL);
+ if (gc_isconst(s)) {
+ return cstr(s);
+ }
+ if (s->slen == 255) {
+ return lstr(s);
+ }
+ return sstr(s);
+}
+
+void be_str_setextra(bstring *s, int extra)
+{
+ if (!gc_isconst(s)) {
+ s->extra = cast(bbyte, extra);
+ }
+}
diff --git a/lib/libesp32/berry/src/be_string.h b/lib/libesp32/berry/src/be_string.h
new file mode 100644
index 000000000..51b3fd016
--- /dev/null
+++ b/lib/libesp32/berry/src/be_string.h
@@ -0,0 +1,57 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_STRING_H
+#define BE_STRING_H
+
+#include "be_object.h"
+
+#define SHORT_STR_MAX_LEN 64
+
+typedef struct {
+ bstring_header;
+#if BE_USE_STR_HASH_CACHE
+ uint32_t hash;
+#endif
+ /* char s[]; */
+} bsstring;
+
+typedef struct {
+ bstring str;
+ int llen;
+ /* char s[]; */
+} blstring;
+
+typedef struct {
+ bstring_header;
+ uint32_t hash;
+ const char *s;
+} bcstring;
+
+#define str_len(_s) \
+ ((_s)->slen == 255 ? cast(blstring*, _s)->llen : (_s)->slen)
+
+#define str(_s) be_str2cstr(_s)
+#define str_extra(_s) ((_s)->extra)
+#define str_literal(_vm, _s) be_newstrn((_vm), (_s), sizeof(_s) - 1)
+
+#if BE_USE_PRECOMPILED_OBJECT
+#include "../generate/be_const_strtab.h"
+#endif
+
+void be_string_init(bvm *vm);
+void be_string_deleteall(bvm *vm);
+int be_eqstr(bstring *s1, bstring *s2);
+bstring* be_newstr(bvm *vm, const char *str);
+bstring* be_newstrn(bvm *vm, const char *str, size_t len);
+bstring* be_newlongstr(bvm *vm, const char *str, size_t len);
+void be_gcstrtab(bvm *vm);
+uint32_t be_strhash(const bstring *s);
+const char* be_str2cstr(const bstring *s);
+void be_str_setextra(bstring *s, int extra);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_strlib.c b/lib/libesp32/berry/src/be_strlib.c
new file mode 100644
index 000000000..e0636c100
--- /dev/null
+++ b/lib/libesp32/berry/src/be_strlib.c
@@ -0,0 +1,876 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_strlib.h"
+#include "be_string.h"
+#include "be_vm.h"
+#include "be_class.h"
+#include "be_module.h"
+#include "be_exec.h"
+#include "be_mem.h"
+#include
+#include
+#include
+
+#define is_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+#define skip_space(s) while (is_space(*(s))) { ++(s); }
+
+typedef bint (*str_opfunc)(const char*, const char*, bint, bint);
+
+bstring* be_strcat(bvm *vm, bstring *s1, bstring *s2)
+{
+ size_t len = (size_t)str_len(s1) + str_len(s2);
+ if (len <= SHORT_STR_MAX_LEN) {
+ char buf[SHORT_STR_MAX_LEN + 1];
+ strcpy(buf, str(s1));
+ strncat(buf, str(s2), len);
+ return be_newstrn(vm, buf, len);
+ } else { /* long string */
+ bstring *s = be_newstrn(vm, NULL, len);
+ char *sbuf = (char*)str(s);
+ strcpy(sbuf, str(s1));
+ strcpy(sbuf + str_len(s1), str(s2));
+ return s;
+ }
+}
+
+int be_strcmp(bstring *s1, bstring *s2)
+{
+ if (be_eqstr(s1, s2)) {
+ return 0;
+ }
+ return strcmp(str(s1), str(s2));
+}
+
+bstring* be_num2str(bvm *vm, bvalue *v)
+{
+ char buf[25];
+ if (var_isint(v)) {
+ sprintf(buf, BE_INT_FORMAT, var_toint(v));
+ } else if (var_isreal(v)) {
+ sprintf(buf, "%g", var_toreal(v));
+ } else {
+ sprintf(buf, "(nan)");
+ }
+ return be_newstr(vm, buf);
+}
+
+static void module2str(char *buf, bvalue *v)
+{
+ const char *name = be_module_name(cast(bmodule*, var_toobj(v)));
+ if (name) {
+ sprintf(buf, "", name);
+ } else {
+ sprintf(buf, "", var_toobj(v));
+ }
+}
+
+static bstring* sim2str(bvm *vm, bvalue *v)
+{
+ char sbuf[64]; /* BUG: memory overflow */
+ switch (var_type(v)) {
+ case BE_NIL:
+ strcpy(sbuf, "nil");
+ break;
+ case BE_BOOL:
+ strcpy(sbuf, var_tobool(v) ? "true" : "false");
+ break;
+ case BE_INDEX:
+ case BE_INT:
+ sprintf(sbuf, BE_INT_FORMAT, var_toint(v));
+ break;
+ case BE_REAL:
+ sprintf(sbuf, "%g", var_toreal(v));
+ break;
+ case BE_CLOSURE: case BE_NTVCLOS: case BE_NTVFUNC:
+ sprintf(sbuf, "", var_toobj(v));
+ break;
+ case BE_CLASS:
+ sprintf(sbuf, "",
+ str(be_class_name(cast(bclass*, var_toobj(v)))));
+ break;
+ case BE_MODULE:
+ module2str(sbuf, v);
+ break;
+ case BE_COMPTR:
+ sprintf(sbuf, "", var_toobj(v));
+ break;
+ default:
+ strcpy(sbuf, "(unknown value)");
+ break;
+ }
+ return be_newstr(vm, sbuf);
+}
+
+static bstring* ins2str(bvm *vm, int idx)
+{
+ bstring *s = str_literal(vm, "tostring");
+ binstance *obj = var_toobj(vm->reg + idx);
+ /* get method 'tostring' */
+ int type = be_instance_member(vm, obj, s, vm->top);
+ be_incrtop(vm); /* push the obj::tostring to stack */
+ if (basetype(type) != BE_FUNCTION) {
+ bstring *name = be_class_name(be_instance_class(obj));
+ char *sbuf = be_malloc(vm, (size_t)str_len(name) + 16);
+ sprintf(sbuf, "", str(name));
+ be_stackpop(vm, 1); /* pop the obj::tostring */
+ s = be_newstr(vm, sbuf);
+ be_free(vm, sbuf, (size_t)str_len(name) + 16);
+ } else {
+ *vm->top = vm->reg[idx];
+ be_dofunc(vm, vm->top - 1, 1);
+ be_stackpop(vm, 1); /* pop the obj::tostring */
+ if (!var_isstr(vm->top)) { /* check the return value */
+ const char *name = str(be_instance_name(obj));
+ be_raise(vm, "runtime_error", be_pushfstring(vm,
+ "the value of `%s::tostring()` is not a 'string'",
+ strlen(name) ? name : ""));
+ }
+ s = var_tostr(vm->top);
+ }
+ return s;
+}
+
+void be_val2str(bvm *vm, int index)
+{
+ bstring *s;
+ int idx = be_absindex(vm, index) - 1;
+ bvalue *v = vm->reg + idx;
+ if (var_isstr(v)) return; /* do nothing */
+ s = var_isinstance(v) ? ins2str(vm, idx) : sim2str(vm, v);
+ v = vm->reg + idx; /* the stack may change */
+ var_setstr(v, s);
+}
+
+static void pushstr(bvm *vm, const char *s, size_t len)
+{
+ /* to create a string and then update the top pointer,
+ * otherwise the GC may crash due to uninitialized values.
+ **/
+ bstring *str = be_newstrn(vm, s, len);
+ bvalue *reg = be_incrtop(vm);
+ var_setstr(reg, str);
+}
+
+static const char* concat2(bvm *vm)
+{
+ bvalue *dst = vm->top - 2;
+ bstring *s1 = var_tostr(dst);
+ bstring *s2 = var_tostr(dst + 1);
+ bstring *s = be_strcat(vm, s1, s2);
+ be_assert(var_isstr(vm->top - 2) && var_isstr(vm->top - 1));
+ dst = vm->top - 2; /* the stack may change */
+ var_setstr(dst, s);
+ --vm->top;
+ return str(s);
+}
+
+const char* be_pushvfstr(bvm *vm, const char *format, va_list arg)
+{
+ pushstr(vm, "", 0);
+ for (;;) {
+ const char *p = strchr(format, '%');
+ if (p == NULL) {
+ break;
+ }
+ pushstr(vm, format, p - format);
+ concat2(vm);
+ switch (p[1]) {
+ case 's': {
+ const char *s = va_arg(arg, char*);
+ if (s == NULL) {
+ s = "(null)";
+ }
+ pushstr(vm, s, strlen(s));
+ break;
+ }
+ case 'd': {
+ bstring *s;
+ bvalue *v = be_incrtop(vm);
+ var_setint(v, va_arg(arg, int));
+ s = be_num2str(vm, v);
+ var_setstr(v, s);
+ break;
+ }
+ case 'f': case 'g': {
+ bstring *s;
+ bvalue *v = be_incrtop(vm);
+ var_setreal(v, cast(breal, va_arg(arg, double)));
+ s = be_num2str(vm, v);
+ var_setstr(v, s);
+ break;
+ }
+ case 'c': {
+ char c = cast(char, va_arg(arg, int));
+ pushstr(vm, &c, 1);
+ break;
+ }
+ case '%': {
+ pushstr(vm, "%", 1);
+ break;
+ }
+ case 'p': {
+ char buf[2 * sizeof(void*) + 4];
+ sprintf(buf, "%p", va_arg(arg, void*));
+ pushstr(vm, buf, strlen(buf));
+ break;
+ }
+ default:
+ pushstr(vm, "(unknown)", 8);
+ break;
+ }
+ concat2(vm);
+ format = p + 2;
+ }
+ pushstr(vm, format, strlen(format));
+ return concat2(vm);
+}
+
+/*******************************************************************
+ * the function be_str2int():
+ * >>-+------------+--+-----+----digits----><
+ * '-whitespace-' +- + -+
+ * '- - -'
+ *******************************************************************/
+BERRY_API bint be_str2int(const char *str, const char **endstr)
+{
+ int c, sign;
+ bint sum = 0;
+ skip_space(str);
+ sign = c = *str++;
+ if (c == '+' || c == '-') {
+ c = *str++;
+ }
+ while (is_digit(c)) {
+ sum = sum * 10 + c - '0';
+ c = *str++;
+ }
+ if (endstr) {
+ *endstr = str - 1;
+ }
+ return sign == '-' ? -sum : sum;
+}
+
+/*******************************************************************
+ * the function be_str2real():
+ * >>-+------------+--+-----+--+-digits--+---+--+--------+-+------->
+ * '-whitespace-' +- + -+ | '-.-' '-digits-' |
+ * '- - -' '-.--digits-----------------'
+ *
+ * >--+------------------------+----------------------------------><
+ * '-+-e-+--+-----+--digits-'
+ * '-E-' +- + -+
+ * '- - -'
+ *******************************************************************/
+BERRY_API breal be_str2real(const char *str, const char **endstr)
+{
+ int c, sign;
+ breal sum = 0, deci = 0, point = (breal)0.1;
+ skip_space(str);
+ sign = c = *str++;
+ if (c == '+' || c == '-') {
+ c = *str++;
+ }
+ while (is_digit(c)) {
+ sum = sum * 10 + c - '0';
+ c = *str++;
+ }
+ if (c == '.') {
+ c = *str++;
+ while (is_digit(c)) {
+ deci = deci + ((breal)c - '0') * point;
+ point *= (breal)0.1;
+ c = *str++;
+ }
+ }
+ sum = sum + deci;
+ if (c == 'e' || c == 'E') {
+ int e = 0;
+ breal ratio = (c = *str++) == '-' ? (breal)0.1 : 10;
+ if (c == '+' || c == '-') {
+ c = *str++;
+ }
+ while (is_digit(c)) {
+ e = e * 10 + c - '0';
+ c = *str++;
+ }
+ while (e--) {
+ sum *= ratio;
+ }
+ }
+ if (endstr) {
+ *endstr = str - 1;
+ }
+ return sign == '-' ? -sum : sum;
+}
+
+/* convert a string to a number (integer or real).
+ * 1. skip \s*[\+\-]?\d*
+ * 2. matched [.eE]? yes: real, no: integer.
+ **/
+BERRY_API const char *be_str2num(bvm *vm, const char *str)
+{
+ const char *sout;
+ bint c, vint = be_str2int(str, &sout);
+ c = *sout;
+ if (c == '.' || c == 'e' || c == 'E') {
+ be_pushreal(vm, be_str2real(str, &sout));
+ } else {
+ be_pushint(vm, vint);
+ }
+ return sout;
+}
+
+static bstring* string_range(bvm *vm, bstring *str, binstance *range)
+{
+ bint lower, upper;
+ bint size = str_len(str); /* size of source string */
+ /* get index range */
+ bvalue temp;
+ be_instance_member(vm, range, be_newstr(vm, "__lower__"), &temp);
+ lower = var_toint(&temp);
+ be_instance_member(vm, range, be_newstr(vm, "__upper__"), &temp);
+ upper = var_toint(&temp);
+ /* protection scope */
+ if (upper < 0) { upper = size + upper; }
+ if (lower < 0) { lower = size + lower; }
+ upper = upper < size ? upper : size - 1;
+ lower = lower < 0 ? 0 : lower;
+ if (lower > upper) {
+ return be_newstrn(vm, "", 0); /* empty string */
+ }
+ return be_newstrn(vm, str(str) + lower, upper - lower + 1);
+
+}
+
+/* string subscript operation */
+bstring* be_strindex(bvm *vm, bstring *str, bvalue *idx)
+{
+ if (var_isint(idx)) {
+ int pos = var_toidx(idx);
+ int size = str_len(str);
+ if (pos < 0) { pos = size + pos; }
+ if ((pos < size) && (pos >= 0)) {
+ return be_newstrn(vm, str(str) + pos, 1);
+ }
+ be_raise(vm, "index_error", "string index out of range");
+ } else if (var_isinstance(idx)) {
+ binstance * ins = var_toobj(idx);
+ const char *cname = str(be_instance_name(ins));
+ if (!strcmp(cname, "range")) {
+ return string_range(vm, str, ins);
+ }
+ // str(be_instance_name(i))
+ }
+ be_raise(vm, "index_error", "string indices must be integers");
+ return NULL;
+}
+
+size_t be_strlcpy(char *dst, const char *src, size_t maxlen)
+{
+ const size_t srclen = strlen(src);
+ if (srclen + 1 < maxlen) {
+ memcpy(dst, src, srclen + 1);
+ } else if (maxlen != 0) {
+ memcpy(dst, src, maxlen - 1);
+ dst[maxlen-1] = '\0';
+ }
+ return srclen;
+}
+
+const char* be_splitpath(const char *path)
+{
+ const char *p;
+ for (p = path - 1; *path != '\0'; ++path) {
+ if (*path == '/') {
+ p = path;
+ }
+ }
+ return p + 1; /* return the file name pointer */
+}
+
+const char* be_splitname(const char *path)
+{
+ const char *p, *q, *end = path + strlen(path);
+ for (p = end; *p != '.' && p > path; --p); /* skip [^\.] */
+ for (q = p; *q == '.' && q > path; --q); /* skip \. */
+ if ((q == path && *q == '.') || *q == '/') {
+ return end;
+ }
+ return p;
+}
+
+static unsigned escape_length(const char *s, int quote)
+{
+ unsigned c, len = 0, step = quote == '"' ? 5 : 3;
+ for (; (c = *s) != '\0'; ++s) {
+ switch (c) {
+ case '\\': case '\n': case '\r': case '\t':
+ len += 1;
+ break;
+ default:
+ if (c < 0x20)
+ len += step;
+ else if (c == (unsigned)quote)
+ len += 1;
+ break;
+ }
+ }
+ return len;
+}
+
+static unsigned eschex(unsigned num)
+{
+ return num <= 9 ? '0' + num : 'a' + num - 10;
+}
+
+/* escape as Berry or JSON */
+static char* escape(char *q, unsigned c, int quote)
+{
+ int json = quote == '"';
+ switch (c) {
+ case '\\': *q++ = '\\'; *q = '\\'; break;
+ case '\n': *q++ = '\\'; *q = 'n'; break;
+ case '\r': *q++ = '\\'; *q = 'r'; break;
+ case '\t': *q++ = '\\'; *q = 't'; break;
+ default:
+ if (c < 0x20) { /* other characters are escaped using '\uxxxx' */
+ *q++ = '\\';
+ if (json) {
+ *q++ = 'u'; *q++ = '0'; *q++ = '0';
+ *q++ = (char)eschex(c >> 4);
+ *q = (char)eschex(c & 0x0f);
+ } else {
+ *q++ = 'x';
+ *q++ = (char)eschex(c >> 4);
+ *q = (char)eschex(c & 0x0f);
+ }
+ } else { /* quotes and unescaped characters */
+ if (c == (unsigned)quote)
+ *q++ = '\\';
+ *q = (char)c;
+ }
+ break;
+ }
+ return q;
+}
+
+static void toescape(bvm *vm, int index, int quote)
+{
+ char *buf, *q;
+ const char *p, *s = be_tostring(vm, index);
+ size_t len = (size_t)be_strlen(vm, index);
+ len += escape_length(s, quote) + 2; /* escape length + quote mark */
+ buf = q = be_pushbuffer(vm, len);
+ *q++ = (char)quote; /* add first quote */
+ /* generate escape string */
+ for (p = s; *p != '\0'; ++p, ++q) {
+ q = escape(q, *p, quote);
+ }
+ *q = (char)quote; /* add last quote */
+ be_pushnstring(vm, buf, len); /* make escape string from buffer */
+ be_moveto(vm, -1, index);
+ be_pop(vm, 2); /* remove buffer & top string */
+}
+
+BERRY_API const char* be_toescape(bvm *vm, int index, int mode)
+{
+ if (be_isstring(vm, index)) {
+ index = be_absindex(vm, index);
+ toescape(vm, index, mode == 'u' ? '"' : '\'');
+ }
+ return be_tostring(vm, index);
+}
+
+#if BE_USE_STRING_MODULE
+
+#define MAX_FORMAT_MODE 32
+#define FLAGES "+- #0"
+
+static const char* skip2dig(const char *s)
+{
+ if (is_digit(*s)) {
+ ++s;
+ }
+ if (is_digit(*s)) {
+ ++s;
+ }
+ return s;
+}
+
+static const char* get_mode(const char *str, char *buf)
+{
+ const char *p = str;
+ while (*p && strchr(FLAGES, *p)) { /* skip flags */
+ ++p;
+ }
+ p = skip2dig(p); /* skip width (2 digits at most) */
+ if (*p == '.') {
+ p = skip2dig(++p); /* skip width (2 digits at most) */
+ }
+ *(buf++) = '%';
+ strncpy(buf, str, p - str + 1);
+ buf[p - str + 1] = '\0';
+ return p;
+}
+
+static void mode_fixlen(char *mode, const char *lenmode)
+{
+ size_t l = strlen(mode), lm = strlen(lenmode);
+ char spec = mode[l - 1];
+ strcpy(mode + l - 1, lenmode);
+ mode[l + lm - 1] = spec;
+ mode[l + lm] = '\0';
+}
+
+static int str_format(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top > 0 && be_isstring(vm, 1)) {
+ int index = 2;
+ const char *format = be_tostring(vm, 1);
+ pushstr(vm, "", 0);
+ for (;;) {
+ char mode[MAX_FORMAT_MODE];
+ char buf[128];
+ const char *p = strchr(format, '%');
+ if (p == NULL) {
+ break;
+ }
+ pushstr(vm, format, p - format);
+ concat2(vm);
+ p = get_mode(p + 1, mode);
+ buf[0] = '\0';
+ if (index > top && *p != '%') {
+ be_raise(vm, "runtime_error", be_pushfstring(vm,
+ "bad argument #%d to 'format': no value", index));
+ }
+ switch (*p) {
+ case '%':
+ be_pushstring(vm, "%");
+ --index; /* compensate the future ++index */
+ break;
+ case 'd': case 'i': case 'o':
+ case 'u': case 'x': case 'X':
+ if (be_isint(vm, index)) {
+ mode_fixlen(mode, BE_INT_FMTLEN);
+ sprintf(buf, mode, be_toint(vm, index));
+ }
+ be_pushstring(vm, buf);
+ break;
+ case 'e': case 'E':
+ case 'f': case 'g': case 'G':
+ if (be_isnumber(vm, index)) {
+ sprintf(buf, mode, be_toreal(vm, index));
+ }
+ be_pushstring(vm, buf);
+ break;
+ case 'c':
+ if (be_isint(vm, index)) {
+ sprintf(buf, "%c", (int)be_toint(vm, index));
+ }
+ be_pushstring(vm, buf);
+ break;
+ case 's': {
+ const char *s = be_tostring(vm, index);
+ int len = be_strlen(vm, 2);
+ if (len > 100 && strlen(mode) == 2) {
+ be_pushvalue(vm, index);
+ } else {
+ sprintf(buf, mode, s);
+ be_pushstring(vm, buf);
+ }
+ break;
+ }
+ default: /* error */
+ be_raise(vm, "runtime_error", be_pushfstring(vm,
+ "invalid option '%%%c' to 'format'", *p));
+ break;
+ }
+ concat2(vm);
+ format = p + 1;
+ ++index;
+ }
+ pushstr(vm, format, strlen(format));
+ concat2(vm);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+/* string.op(s1, s2, begin=0, end=length(s2)) */
+static bint str_operation(bvm *vm, str_opfunc func, bint error)
+{
+ int top = be_top(vm);
+ /* check the number and type of arguments */
+ if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
+ /* get the operation string and its length */
+ int len1 = be_strlen(vm, 1);
+ int len2 = be_strlen(vm, 2);
+ const char *s1 = be_tostring(vm, 1);
+ const char *s2 = be_tostring(vm, 2);
+ /* get begin and end indexes (may use default values) */
+ bint begin = top >= 3 && be_isint(vm, 3) ? be_toint(vm, 3) : 0;
+ bint end = top >= 4 && be_isint(vm, 4) ? be_toint(vm, 4) : len1;
+ /* basic range check:
+ * 1. begin position must be greater than 0 and
+ * less than the length of the source string.
+ * 2. the length of the pattern string cannot be
+ * less than the matching range (end - begin).
+ **/
+ if (begin >= 0 && begin <= len1 && end - begin >= len2) {
+ /* call the operation function */
+ return func(s1, s2, begin, end - len2);
+ }
+ }
+ return error; /* returns the default error value */
+}
+
+static bint _sfind(const char *s1, const char *s2, bint begin, bint end)
+{
+ const char *res = strstr(s1 + begin, s2);
+ if (res) {
+ bint pos = (bint)(res - s1);
+ return pos <= end ? pos : -1;
+ }
+ return -1;
+}
+
+static int str_find(bvm *vm)
+{
+ be_pushint(vm, str_operation(vm, _sfind, -1));
+ be_return(vm);
+}
+
+static bint _scount(const char *s1, const char *s2, bint begin, bint end)
+{
+ bint count = 0;
+ const char *res = s1 + begin, *send = s1 + end;
+ while ((res = strstr(res, s2)) != NULL && res <= send) {
+ count += 1;
+ res += 1;
+ }
+ return count;
+}
+
+static int str_count(bvm *vm)
+{
+ be_pushint(vm, str_operation(vm, _scount, 0));
+ be_return(vm);
+}
+
+static bbool _split_string(bvm *vm, int top)
+{
+ if (be_isstring(vm, 2)) {
+ const char *res;
+ int len1 = be_strlen(vm, 1);
+ int len2 = be_strlen(vm, 2);
+ const char *s1 = be_tostring(vm, 1);
+ const char *s2 = be_tostring(vm, 2);
+ bint count = len2 /* match when the pattern string is not empty */
+ ? top >= 3 && be_isint(vm, 3) ? be_toint(vm, 3) : len1
+ : 0; /* cannot match empty pattern string */
+ while (count-- && (res = strstr(s1, s2)) != NULL) {
+ be_pushnstring(vm, s1, res - s1);
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ s1 = res + len2;
+ }
+ be_pushstring(vm, s1);
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ return btrue;
+ }
+ return bfalse;
+}
+
+static bbool _split_index(bvm *vm)
+{
+ if (be_isint(vm, 2)) {
+ int len = be_strlen(vm, 1), idx = be_toindex(vm, 2);
+ const char *s = be_tostring(vm, 1);
+ idx = idx > len ? len : idx < -len ? -len : idx;
+ if (idx < 0) {
+ idx += len;
+ }
+ be_pushnstring(vm, s, idx);
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ be_pushnstring(vm, s + idx, (size_t)len - idx);
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ return btrue;
+ }
+ return bfalse;
+}
+
+static int str_split(bvm *vm)
+{
+ int top = be_top(vm);
+ be_newobject(vm, "list");
+ if (top >= 2 && be_isstring(vm, 1)) {
+ if (!_split_index(vm))
+ _split_string(vm, top);
+ }
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+static int str_i2hex(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top && be_isint(vm, 1)) {
+ bint value = be_toint(vm, 1);
+ char fmt[10] = { "%" BE_INT_FMTLEN "X" }, buf[18];
+ if (top >= 2 && be_isint(vm, 2)) {
+ bint num = be_toint(vm, 2);
+ if (num > 0 && num <= 16) {
+ sprintf(fmt, "%%.%d" BE_INT_FMTLEN "X", (int)num);
+ }
+ }
+ sprintf(buf, fmt, value);
+ be_pushstring(vm, buf);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int str_byte(bvm *vm)
+{
+ if (be_top(vm) && be_isstring(vm, 1)) {
+ const bbyte *s = (const bbyte *)be_tostring(vm, 1);
+ be_pushint(vm, *s);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int str_char(bvm *vm)
+{
+ if (be_top(vm) && be_isint(vm, 1)) {
+ char c = be_toint(vm, 1) & 0xFF;
+ be_pushnstring(vm, &c, 1);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+// boolean to select whether we call toupper() or tolower()
+static int str_touplower(bvm *vm, bbool up)
+{
+ if (be_top(vm) && be_isstring(vm, 1)) {
+ const char *p, *s = be_tostring(vm, 1);
+ size_t len = (size_t)be_strlen(vm, 1);
+ char *buf, *q;
+ buf = q = be_pushbuffer(vm, len);
+ /* convert to lower case */
+ for (p = s; *p != '\0'; ++p, ++q) {
+ *q = up ? toupper(*p) : tolower(*p);
+ }
+ be_pushnstring(vm, buf, len); /* make escape string from buffer */
+ be_remove(vm, 2); /* remove buffer */
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int str_tolower(bvm *vm) {
+ return str_touplower(vm, bfalse);
+}
+
+static int str_toupper(bvm *vm) {
+ return str_touplower(vm, btrue);
+}
+
+static int str_tr(bvm *vm)
+{
+ if (be_top(vm) == 3 && be_isstring(vm, 1) && be_isstring(vm, 2) && be_isstring(vm, 3)) {
+ const char *p, *s = be_tostring(vm, 1);
+ const char *t1 = be_tostring(vm, 2);
+ const char *t2 = be_tostring(vm, 3);
+ size_t len = (size_t)be_strlen(vm, 1);
+ char *buf, *q;
+ buf = be_pushbuffer(vm, len);
+ /* convert each char */
+ for (p = s, q = buf; *p != '\0'; ++p, ++q) {
+ const char *p1, *p2;
+ *q = *p; /* default to no change */
+ for (p1=t1, p2=t2; *p1 != '\0'; ++p1) {
+ if (*p == *p1) {
+ if (*p2) {
+ *q = *p2;
+ } else {
+ q--; /* remove this char */
+ len--;
+ }
+ break;
+ }
+ if (*p2) { p2++; }
+ }
+ }
+ be_pushnstring(vm, buf, len); /* make escape string from buffer */
+ be_remove(vm, 2); /* remove buffer */
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int str_escape(bvm *vm)
+{
+ int top = be_top(vm);
+ if (top >= 1 && be_isstring(vm, 1)) {
+ int quote = 'u';
+ if (top >= 2 && be_isbool(vm, 2)) {
+ if (be_tobool(vm, 1)) {
+ quote = 'x';
+ }
+ }
+ be_tostring(vm, 1);
+ be_toescape(vm, 1, quote);
+ be_pushvalue(vm, 1);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(string) {
+ be_native_module_function("format", str_format),
+ be_native_module_function("count", str_count),
+ be_native_module_function("split", str_split),
+ be_native_module_function("find", str_find),
+ be_native_module_function("hex", str_i2hex),
+ be_native_module_function("byte", str_byte),
+ be_native_module_function("char", str_char),
+ be_native_module_function("tolower", str_tolower),
+ be_native_module_function("toupper", str_toupper),
+ be_native_module_function("tr", str_tr),
+ be_native_module_function("escape", str_escape),
+};
+
+be_define_native_module(string, NULL);
+#else
+/* @const_object_info_begin
+module string (scope: global, depend: BE_USE_STRING_MODULE) {
+ format, func(str_format)
+ count, func(str_count)
+ split, func(str_split)
+ find, func(str_find)
+ hex, func(str_i2hex)
+ byte, func(str_byte)
+ char, func(str_char)
+ tolower, func(str_tolower)
+ toupper, func(str_toupper)
+ tr, func(str_tr)
+ escape, func(str_escape)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_string.h"
+#endif
+
+#endif /* BE_USE_STRING_MODULE */
diff --git a/lib/libesp32/berry/src/be_strlib.h b/lib/libesp32/berry/src/be_strlib.h
new file mode 100644
index 000000000..992257648
--- /dev/null
+++ b/lib/libesp32/berry/src/be_strlib.h
@@ -0,0 +1,32 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_STRLIB_H
+#define BE_STRLIB_H
+
+#include "be_object.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bstring* be_strcat(bvm *vm, bstring *s1, bstring *s2);
+int be_strcmp(bstring *s1, bstring *s2);
+bstring* be_num2str(bvm *vm, bvalue *v);
+void be_val2str(bvm *vm, int index);
+size_t be_strlcpy(char *dst, const char *src, size_t size);
+const char* be_splitpath(const char *path);
+const char* be_splitname(const char *path);
+const char* be_pushvfstr(bvm *vm, const char *format, va_list arg);
+bstring* be_strindex(bvm *vm, bstring *str, bvalue *idx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesp32/berry/src/be_sys.h b/lib/libesp32/berry/src/be_sys.h
new file mode 100644
index 000000000..79a8b3c69
--- /dev/null
+++ b/lib/libesp32/berry/src/be_sys.h
@@ -0,0 +1,48 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_SYS_H
+#define BE_SYS_H
+
+#include
+
+/* directory information for directory traversal */
+typedef struct {
+ void *dir;
+ void *file;
+ const char *name;
+} bdirinfo;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* be_fopen(const char *filename, const char *modes);
+int be_fclose(void *hfile);
+size_t be_fwrite(void *hfile, const void *buffer, size_t length);
+size_t be_fread(void *hfile, void *buffer, size_t length);
+char* be_fgets(void *hfile, void *buffer, int size);
+int be_fseek(void *hfile, long offset);
+long int be_ftell(void *hfile);
+long int be_fflush(void *hfile);
+size_t be_fsize(void *hfile);
+int be_isdir(const char *path);
+int be_isfile(const char *path);
+int be_isexist(const char *path);
+char* be_getcwd(char *buf, size_t size);
+int be_chdir(const char *path);
+int be_mkdir(const char *path);
+int be_unlink(const char *filename);
+int be_dirfirst(bdirinfo *info, const char *path);
+int be_dirnext(bdirinfo *info);
+int be_dirclose(bdirinfo *info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesp32/berry/src/be_syslib.c b/lib/libesp32/berry/src/be_syslib.c
new file mode 100644
index 000000000..650db845c
--- /dev/null
+++ b/lib/libesp32/berry/src/be_syslib.c
@@ -0,0 +1,36 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_object.h"
+
+#if BE_USE_SYS_MODULE
+
+static int m_path(bvm *vm)
+{
+ be_getbuiltin(vm, "list");
+ be_module_path(vm);
+ be_call(vm, 1);
+ be_pop(vm, 1);
+ be_return(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(sys){
+ be_native_module_function("path", m_path)
+};
+
+be_define_native_module(sys, NULL);
+#else
+/* @const_object_info_begin
+module sys (scope: global, depend: BE_USE_SYS_MODULE) {
+ path, func(m_path)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_sys.h"
+#endif
+
+#endif /* BE_USE_SYS_MODULE */
diff --git a/lib/libesp32/berry/src/be_timelib.c b/lib/libesp32/berry/src/be_timelib.c
new file mode 100644
index 000000000..7b779aa36
--- /dev/null
+++ b/lib/libesp32/berry/src/be_timelib.c
@@ -0,0 +1,71 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "berry.h"
+#include
+
+#if BE_USE_TIME_MODULE
+
+static int m_time(bvm *vm)
+{
+ be_pushint(vm, (bint)time(NULL));
+ be_return(vm);
+}
+
+static void time_insert(bvm *vm, const char *key, int value)
+{
+ be_pushstring(vm, key);
+ be_pushint(vm, value);
+ be_data_insert(vm, -3);
+ be_pop(vm, 2);
+}
+
+static int m_dump(bvm *vm)
+{
+ if (be_top(vm) >= 1 && be_isint(vm, 1)) {
+ time_t ts = be_toint(vm, 1);
+ struct tm *t = localtime(&ts);
+ be_newobject(vm, "map");
+ time_insert(vm, "year", t->tm_year + 1900);
+ time_insert(vm, "month", t->tm_mon + 1);
+ time_insert(vm, "day", t->tm_mday);
+ time_insert(vm, "hour", t->tm_hour);
+ time_insert(vm, "min", t->tm_min);
+ time_insert(vm, "sec", t->tm_sec);
+ time_insert(vm, "weekday", t->tm_wday);
+ be_pop(vm, 1);
+ be_return(vm);
+ }
+ be_return_nil(vm);
+}
+
+static int m_clock(bvm *vm)
+{
+ be_pushreal(vm, clock() / (breal)CLOCKS_PER_SEC);
+ be_return(vm);
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+be_native_module_attr_table(time) {
+ be_native_module_function("time", m_time),
+ be_native_module_function("dump", m_dump),
+ be_native_module_function("clock", m_clock)
+};
+
+be_define_native_module(time, NULL);
+#else
+/* @const_object_info_begin
+module time (scope: global, depend: BE_USE_TIME_MODULE) {
+ time, func(m_time)
+ dump, func(m_dump)
+ clock, func(m_clock)
+}
+@const_object_info_end */
+#include "../generate/be_fixed_time.h"
+#endif
+
+#endif /* BE_USE_TIME_MODULE */
diff --git a/lib/libesp32/berry/src/be_var.c b/lib/libesp32/berry/src/be_var.c
new file mode 100644
index 000000000..4fee144cd
--- /dev/null
+++ b/lib/libesp32/berry/src/be_var.c
@@ -0,0 +1,142 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_var.h"
+#include "be_vm.h"
+#include "be_vector.h"
+#include "be_string.h"
+#include "be_map.h"
+#include "be_gc.h"
+
+#define global(vm) ((vm)->gbldesc.global)
+#define builtin(vm) ((vm)->gbldesc.builtin)
+
+void be_globalvar_init(bvm *vm)
+{
+ global(vm).vtab = be_map_new(vm);
+ be_gc_fix(vm, gc_object(global(vm).vtab));
+ be_vector_init(vm, &global(vm).vlist, sizeof(bvalue));
+#if !BE_USE_PRECOMPILED_OBJECT
+ builtin(vm).vtab = be_map_new(vm);
+ be_vector_init(vm, &builtin(vm).vlist, sizeof(bvalue));
+ be_gc_fix(vm, gc_object(builtin(vm).vtab));
+#endif
+}
+
+void be_globalvar_deinit(bvm *vm)
+{
+ global(vm).vtab = NULL;
+ be_vector_delete(vm, &global(vm).vlist);
+#if !BE_USE_PRECOMPILED_OBJECT
+ builtin(vm).vtab = NULL;
+ be_vector_delete(vm, &builtin(vm).vlist);
+#endif
+}
+
+static int global_find(bvm *vm, bstring *name)
+{
+ bvalue *res = be_map_findstr(vm, global(vm).vtab, name);
+ if (res) {
+ return var_toidx(res) + be_builtin_count(vm);
+ }
+ return -1; /* not found */
+}
+
+int be_global_find(bvm *vm, bstring *name)
+{
+ int res = global_find(vm, name);
+ return res != -1 ? res : be_builtin_find(vm, name);
+}
+
+static int global_new_anonymous(bvm *vm)
+{
+ int idx = be_global_count(vm);
+ /* allocate space for new variables */
+ be_vector_resize(vm, &global(vm).vlist, idx + 1);
+ /* set the new variable to nil */
+ var_setnil((bvalue *)global(vm).vlist.end);
+ return idx;
+}
+
+int be_global_new(bvm *vm, bstring *name)
+{
+ int idx = global_find(vm, name);
+ if (idx == -1) {
+ bvalue *desc;
+ idx = global_new_anonymous(vm);
+ desc = be_map_insertstr(vm, global(vm).vtab, name, NULL);
+ var_setint(desc, idx);
+ idx += be_builtin_count(vm);
+ }
+ return idx;
+}
+
+bvalue* be_global_var(bvm *vm, int index)
+{
+ int bcnt = be_builtin_count(vm);
+ if (index < bcnt) {
+ return be_vector_at(&builtin(vm).vlist, index);
+ }
+ index -= bcnt;
+ return be_vector_at(&global(vm).vlist, index);
+}
+
+void be_global_release_space(bvm *vm)
+{
+ be_map_compact(vm, global(vm).vtab);
+ be_vector_release(vm, &global(vm).vlist);
+}
+
+int be_builtin_find(bvm *vm, bstring *name)
+{
+ bvalue *res = be_map_findstr(vm, builtin(vm).vtab, name);
+ if (res) {
+ return var_toidx(res);
+ }
+ return -1; /* not found */
+}
+
+bstring* be_builtin_name(bvm *vm, int index)
+{
+ bmap *map = builtin(vm).vtab;
+ bmapnode *end, *node = map->slots;
+ for (end = node + map->size; node < end; ++node) {
+ if (var_isstr(&node->key) && node->value.v.i == index) {
+ return node->key.v.s;
+ }
+ }
+ return NULL;
+}
+
+#if !BE_USE_PRECOMPILED_OBJECT
+int be_builtin_new(bvm *vm, bstring *name)
+{
+ int idx = be_builtin_find(vm, name);
+ if (idx == -1) {
+ bvalue *desc;
+ idx = be_map_count(builtin(vm).vtab);
+ desc = be_map_insertstr(vm, builtin(vm).vtab, name, NULL);
+ var_setint(desc, idx);
+ be_vector_resize(vm, &builtin(vm).vlist, idx + 1);
+ /* set the new variable to nil */
+ var_setnil((bvalue*)(builtin(vm).vlist.end));
+ }
+ return idx;
+}
+
+void be_bulitin_release_space(bvm *vm)
+{
+ be_map_compact(vm, builtin(vm).vtab);
+ be_vector_release(vm, &builtin(vm).vlist);
+}
+#else
+void be_const_builtin_set(bvm *vm, const bmap *map, const bvector *vec)
+{
+ builtin(vm).vtab = cast(bmap*, map);
+ builtin(vm).vlist = *vec;
+}
+#endif
diff --git a/lib/libesp32/berry/src/be_var.h b/lib/libesp32/berry/src/be_var.h
new file mode 100644
index 000000000..6b9908a6b
--- /dev/null
+++ b/lib/libesp32/berry/src/be_var.h
@@ -0,0 +1,31 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_VAR_H
+#define BE_VAR_H
+
+#include "be_object.h"
+
+#define be_global_count(vm) \
+ be_vector_count(&(vm)->gbldesc.global.vlist)
+
+#define be_builtin_count(vm) \
+ be_vector_count(&(vm)->gbldesc.builtin.vlist)
+
+void be_globalvar_init(bvm *vm);
+void be_globalvar_deinit(bvm *vm);
+int be_global_find(bvm *vm, bstring *name);
+int be_global_new(bvm *vm, bstring *name);
+bvalue* be_global_var(bvm *vm, int index);
+void be_global_release_space(bvm *vm);
+int be_builtin_find(bvm *vm, bstring *name);
+bstring* be_builtin_name(bvm *vm, int index);
+int be_builtin_new(bvm *vm, bstring *name);
+void be_bulitin_release_space(bvm *vm);
+void be_const_builtin_set(bvm *vm, const bmap *map, const bvector *vec);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_vector.c b/lib/libesp32/berry/src/be_vector.c
new file mode 100644
index 000000000..b73479601
--- /dev/null
+++ b/lib/libesp32/berry/src/be_vector.c
@@ -0,0 +1,153 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_vector.h"
+#include "be_mem.h"
+#include
+
+/* initialize a vector, the vector structure itself is usually allocated
+ * on the stack, and the data is allocated from the heap.
+ **/
+void be_vector_init(bvm *vm, bvector *vector, int size)
+{
+ vector->capacity = 2; /* the default capacity */
+ vector->size = size;
+ vector->count = 0;
+ vector->data = be_malloc(vm, (size_t)vector->capacity * size);
+ vector->end = (char*)vector->data - size;
+ memset(vector->data, 0, (size_t)vector->capacity * size);
+}
+
+void be_vector_delete(bvm *vm, bvector *vector)
+{
+ be_free(vm, vector->data, (size_t)vector->capacity * vector->size);
+}
+
+void* be_vector_at(bvector *vector, int index)
+{
+ return (char*)vector->data + (size_t)index * vector->size;
+}
+
+void be_vector_push(bvm *vm, bvector *vector, void *data)
+{
+ size_t size = vector->size;
+ size_t capacity = vector->capacity;
+ size_t count = vector->count++;
+ if (count >= capacity) {
+ int newcap = be_nextsize(vector->capacity);
+ vector->data = be_realloc(vm,
+ vector->data, vector->capacity * size, newcap * size);
+ vector->end = (char*)vector->data + count * size;
+ vector->capacity = newcap;
+ } else {
+ vector->end = (char*)vector->end + size;
+ }
+ if (data != NULL) {
+ memcpy(vector->end, data, size);
+ }
+}
+
+/* clear the expanded portion if the memory expands */
+void be_vector_push_c(bvm *vm, bvector *vector, void *data)
+{
+ int capacity = vector->capacity + 1;
+ be_vector_push(vm, vector, data);
+ if (vector->capacity > capacity) {
+ size_t size = ((size_t)vector->capacity - capacity) * vector->size;
+ memset(be_vector_at(vector, capacity), 0, size);
+ }
+}
+
+void be_vector_remove_end(bvector *vector)
+{
+ be_assert(vector->count > 0);
+ vector->count--;
+ vector->end = (char*)vector->end - vector->size;
+}
+
+void be_vector_resize(bvm *vm, bvector *vector, int count)
+{
+ size_t size = vector->size;
+ be_assert(count >= 0);
+ if (count != be_vector_count(vector)) {
+ int newcap = be_nextsize(count);
+ if (newcap > vector->capacity) { /* extended capacity */
+ vector->data = be_realloc(vm,
+ vector->data, vector->capacity * size, newcap * size);
+ vector->capacity = newcap;
+ }
+ vector->count = count;
+ vector->end = (char*)vector->data + size * ((size_t)count - 1);
+ }
+}
+
+void be_vector_clear(bvector *vector)
+{
+ vector->count = 0;
+ vector->end = (char*)vector->data - vector->size;
+}
+
+/* free not used */
+void* be_vector_release(bvm *vm, bvector *vector)
+{
+ size_t size = vector->size;
+ int count = be_vector_count(vector);
+ if (count == 0) {
+ be_free(vm, vector->data, vector->capacity * size);
+ vector->capacity = 0;
+ vector->data = NULL;
+ vector->end = NULL;
+ } else if (count < vector->capacity) {
+ vector->data = be_realloc(vm,
+ vector->data, vector->capacity * size, count * size);
+ vector->end = (char*)vector->data + ((size_t)count - 1) * size;
+ vector->capacity = count;
+ }
+ return vector->data;
+}
+
+/* use binary search to find the vector capacity between 0-1024 */
+static int binary_search(int value)
+{
+ static const uint16_t tab[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16,
+ 20, 24, 28, 32, 40, 48, 64, 96, 128,
+ 192, 256, 384, 512, 768, 1024
+ };
+ const uint16_t *low = tab;
+ const uint16_t *high = tab + array_count(tab) - 1;
+ while (low <= high) {
+ const uint16_t *mid = low + ((high - low) >> 1);
+ if (*mid == value) {
+ return mid[1];
+ }
+ if (*mid < value) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+ return *low;
+}
+
+static int nextpow(int value)
+{
+ value |= value >> 1;
+ value |= value >> 2;
+ value |= value >> 4;
+ value |= value >> 8;
+ value |= value >> 16;
+ return value + 1;
+}
+
+int be_nextsize(int size)
+{
+ if (size < 1024) {
+ return binary_search(size);
+ }
+ return nextpow(size);
+}
diff --git a/lib/libesp32/berry/src/be_vector.h b/lib/libesp32/berry/src/be_vector.h
new file mode 100644
index 000000000..15f399cc6
--- /dev/null
+++ b/lib/libesp32/berry/src/be_vector.h
@@ -0,0 +1,43 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_VECTOR_H
+#define BE_VECTOR_H
+
+#include "be_object.h"
+
+/* =============================== defines =============================== */
+#define be_vector_data(vector) ((vector)->data)
+#define be_vector_first(vector) ((vector)->data)
+#define be_vector_isend(vector, item) ((item) > (vector)->end)
+#define be_vector_isempty(vector) (!(vector)->count)
+#define be_vector_end(vector) ((vector)->end)
+#define be_vector_count(vector) ((vector)->count)
+#define be_vector_capacity(vector) ((vector)->capacity)
+#define be_stack_init(vm, stack, size) be_vector_init(vm, stack, size)
+#define be_stack_delete(vm, stack) be_vector_delete(vm, stack)
+#define be_stack_clear(stack) be_vector_clear(stack)
+#define be_stack_push(vm, stack, data) be_vector_push(vm, stack, data)
+#define be_stack_pop(stack) be_vector_remove_end(stack)
+#define be_stack_top(stack) be_vector_end(stack)
+#define be_stack_base(stack) be_vector_first(stack)
+#define be_stack_count(stack) be_vector_count(stack)
+#define be_stack_isempty(stack) be_vector_isempty(stack)
+
+/* ========================== function extern ========================== */
+void be_vector_init(bvm *vm, bvector *vector, int size);
+void be_vector_delete(bvm *vm, bvector *vector);
+void* be_vector_at(bvector *vector, int index);
+void be_vector_push(bvm *vm, bvector *vector, void *data);
+void be_vector_push_c(bvm *vm, bvector *vector, void *data);
+void be_vector_remove_end(bvector *vector);
+void be_vector_resize(bvm *vm, bvector *vector, int count);
+void be_vector_clear(bvector *vector);
+void* be_vector_release(bvm *vm, bvector *vector);
+int be_nextsize(int value);
+
+#endif
diff --git a/lib/libesp32/berry/src/be_vm.c b/lib/libesp32/berry/src/be_vm.c
new file mode 100644
index 000000000..e6cfd8856
--- /dev/null
+++ b/lib/libesp32/berry/src/be_vm.c
@@ -0,0 +1,1277 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "be_vm.h"
+#include "be_decoder.h"
+#include "be_string.h"
+#include "be_strlib.h"
+#include "be_class.h"
+#include "be_func.h"
+#include "be_vector.h"
+#include "be_list.h"
+#include "be_map.h"
+#include "be_module.h"
+#include "be_mem.h"
+#include "be_var.h"
+#include "be_gc.h"
+#include "be_exec.h"
+#include "be_debug.h"
+#include "be_libs.h"
+#include
+#include
+
+#define NOT_METHOD BE_NONE
+
+#define vm_error(vm, except, ...) \
+ be_raise(vm, except, be_pushfstring(vm, __VA_ARGS__))
+
+#define RA() (reg + IGET_RA(ins)) /* Get value of register A */
+#define RKB() ((isKB(ins) ? ktab : reg) + KR2idx(IGET_RKB(ins))) /* Get value of register or constant B */
+#define RKC() ((isKC(ins) ? ktab : reg) + KR2idx(IGET_RKC(ins))) /* Get value of register or constant C */
+
+#define var2cl(_v) cast(bclosure*, var_toobj(_v)) /* cast var to closure */
+#define var2real(_v) (var_isreal(_v) ? (_v)->v.r : (breal)(_v)->v.i) /* get var as real or convert to real if integer */
+#define val2bool(v) ((v) ? btrue : bfalse) /* get var as bool (trur if non zero) */
+#define ibinop(op, a, b) ((a)->v.i op (b)->v.i) /* apply binary operator to both arguments as integers */
+
+#if BE_USE_DEBUG_HOOK
+ #define DEBUG_HOOK() \
+ if (vm->hookmask & BE_HOOK_LINE) { \
+ do_linehook(vm); \
+ reg = vm->reg; \
+ }
+#else
+ #define DEBUG_HOOK()
+#endif
+
+#if BE_USE_PERF_COUNTERS
+ #define COUNTER_HOOK() \
+ vm->counter_ins++;
+#else
+ #define COUNTER_HOOK()
+#endif
+
+#if BE_USE_PERF_COUNTERS
+ #define VM_HEARTBEAT() \
+ if ((vm->counter_ins & ((1<<(BE_VM_OBSERVABILITY_SAMPLING - 1))-1) ) == 0) { /* call every 2^BE_VM_OBSERVABILITY_SAMPLING instructions */ \
+ if (vm->obshook != NULL) \
+ (*vm->obshook)(vm, BE_OBS_VM_HEARTBEAT, vm->counter_ins); \
+ }
+#else
+ #define VM_HEARTBEAT()
+#endif
+
+#define vm_exec_loop() \
+ loop: \
+ DEBUG_HOOK(); \
+ COUNTER_HOOK(); \
+ VM_HEARTBEAT(); \
+ switch (IGET_OP(ins = *vm->ip++))
+
+#if BE_USE_SINGLE_FLOAT
+ #define mathfunc(func) func##f
+#else
+ #define mathfunc(func) func
+#endif
+
+#define opcase(opcode) case OP_##opcode
+#define dispatch() goto loop
+
+#define equal_rule(op, iseq) \
+ bbool res; \
+ if (var_isint(a) && var_isint(b)) { \
+ res = ibinop(op, a, b); \
+ } else if (var_isnumber(a) && var_isnumber(b)) { \
+ res = var2real(a) op var2real(b); \
+ } else if (var_isinstance(a) && !var_isnil(b)) { \
+ res = object_eqop(vm, #op, iseq, a, b); \
+ } else if (var_type(a) == var_type(b)) { /* same types */ \
+ if (var_isnil(a)) { /* nil op nil */ \
+ res = 1 op 1; \
+ } else if (var_isbool(a)) { /* bool op bool */ \
+ res = var_tobool(a) op var_tobool(b); \
+ } else if (var_isstr(a)) { /* string op string */ \
+ res = 1 op be_eqstr(a->v.s, b->v.s); \
+ } else if (var_isclass(a) || var_isfunction(a) || var_iscomptr(a)) { \
+ res = var_toobj(a) op var_toobj(b); \
+ } else { \
+ binop_error(vm, #op, a, b); \
+ res = bfalse; /* will not be executed */ \
+ } \
+ } else { /* different types */ \
+ res = 1 op 0; \
+ } \
+ return res
+
+#define relop_rule(op) \
+ bbool res; \
+ if (var_isint(a) && var_isint(b)) { \
+ res = ibinop(op, a, b); \
+ } else if (var_isnumber(a) && var_isnumber(b)) { \
+ res = var2real(a) op var2real(b); \
+ } else if (var_isstr(a) && var_isstr(b)) { \
+ bstring *s1 = var_tostr(a), *s2 = var_tostr(b); \
+ res = be_strcmp(s1, s2) op 0; \
+ } else if (var_isinstance(a)) { \
+ binstance *obj = var_toobj(a); \
+ object_binop(vm, #op, *a, *b); \
+ check_bool(vm, obj, #op); \
+ res = var_tobool(vm->top); \
+ } else { \
+ binop_error(vm, #op, a, b); \
+ res = bfalse; /* will not be executed */ \
+ } \
+ return res
+
+#define bitwise_block(op) \
+ bvalue *dst = RA(), *a = RKB(), *b = RKC(); \
+ if (var_isint(a) && var_isint(b)) { \
+ var_setint(dst, ibinop(op, a, b)); \
+ } else if (var_isinstance(a)) { \
+ ins_binop(vm, #op, ins); \
+ } else { \
+ binop_error(vm, #op, a, b); \
+ }
+
+#define push_native(_vm, _f, _ns, _t) { \
+ precall(_vm, _f, _ns, _t); \
+ _vm->cf->status = PRIM_FUNC; \
+}
+
+static void prep_closure(bvm *vm, int pos, int argc, int mode);
+
+static void attribute_error(bvm *vm, const char *t, bvalue *b, bvalue *c)
+{
+ const char *attr = var_isstr(c) ? str(var_tostr(c)) : be_vtype2str(c);
+ vm_error(vm, "attribute_error",
+ "'%s' value has no %s '%s'", be_vtype2str(b), t, attr);
+}
+
+static void binop_error(bvm *vm, const char *op, bvalue *a, bvalue *b)
+{
+ vm_error(vm, "type_error",
+ "unsupported operand type(s) for %s: '%s' and '%s'",
+ op, be_vtype2str(a), be_vtype2str(b));
+}
+
+static void unop_error(bvm *vm, const char *op, bvalue *a)
+{
+ vm_error(vm, "type_error",
+ "unsupported operand type(s) for %s: '%s'",
+ op, be_vtype2str(a));
+}
+
+static void call_error(bvm *vm, bvalue *v)
+{
+ vm_error(vm, "type_error",
+ "'%s' value is not callable", be_vtype2str(v));
+}
+
+/* Check that the return value is bool or raise an exception */
+/* `obj` and `method` are only passed for error reporting */
+static void check_bool(bvm *vm, binstance *obj, const char *method)
+{
+ if (!var_isbool(vm->top)) {
+ const char *name = str(be_instance_name(obj));
+ vm_error(vm, "type_error",
+ "`%s::%s` return value error, the expected type is 'bool'",
+ strlen(name) ? name : "", method);
+ }
+}
+
+#if BE_USE_DEBUG_HOOK
+static void do_linehook(bvm *vm)
+{
+ bcallframe *cf = vm->cf;
+ bclosure *cl = var_toobj(cf->func);
+ int pc = cast_int(vm->ip - cl->proto->code);
+ if (!pc || pc > cf->lineinfo->endpc) {
+ while (pc > cf->lineinfo->endpc)
+ cf->lineinfo++;
+ be_callhook(vm, BE_HOOK_LINE);
+ } else {
+ blineinfo *linfo = cf->lineinfo;
+ blineinfo *base = cl->proto->lineinfo;
+ while (linfo > base && pc <= linfo[-1].endpc)
+ linfo--;
+ if (cf->lineinfo != linfo) {
+ cf->lineinfo = linfo;
+ be_callhook(vm, BE_HOOK_LINE);
+ }
+ }
+}
+#endif
+
+/* Prepare the stack for the function/method call */
+/* `func` is a pointer to the function/method on the stack, it contains the closure before call and the result after the call */
+/* `nstackˋ is the stack depth used by the function (determined by compiler), we add BE_STACK_FREE_MIN as a safety margin */
+static void precall(bvm *vm, bvalue *func, int nstack, int mode)
+{
+ bcallframe *cf;
+ int expan = nstack + BE_STACK_FREE_MIN; /* `expan` is the minimum required space on the stack */
+ if (vm->stacktop < func + expan) { /* do we have too little space left on the stack? */
+ size_t fpos = func - vm->stack; /* compute offset of `func` from base stack, in case stack is reallocated and base address changes */
+ be_stack_expansion(vm, expan); /* expand stack (vector object), warning stack address changes */
+ func = vm->stack + fpos; /* recompute `func` address with new stack address */
+ }
+ be_stack_push(vm, &vm->callstack, NULL); /* push a NULL value on callstack */
+ cf = be_stack_top(&vm->callstack); /* get address of new callframe at top of callstack */
+ cf->func = func - mode;
+ cf->top = vm->top; /* save previous stack top */
+ cf->reg = vm->reg; /* save previous stack base */
+ vm->reg = func + 1; /* new stack base is right after function */
+ vm->top = vm->reg + nstack; /* new stack top is above the registers used by the function, so we don´t mess with them */
+ vm->cf = cf; /* set new current callframe */
+}
+
+/* Prepare call of closure, setting the instruction pointer (ip) */
+static void push_closure(bvm *vm, bvalue *func, int nstack, int mode)
+{
+ bclosure *cl = var_toobj(func);
+ precall(vm, func, nstack, mode);
+ vm->cf->ip = vm->ip;
+ vm->cf->status = NONE_FLAG;
+ vm->ip = cl->proto->code;
+#if BE_USE_DEBUG_HOOK
+ vm->cf->lineinfo = cl->proto->lineinfo;
+ be_callhook(vm, BE_HOOK_CALL);
+#endif
+}
+
+static void ret_native(bvm *vm)
+{
+ bcallframe *_cf = vm->cf;
+ vm->reg = _cf->reg;
+ vm->top = _cf->top;
+ be_stack_pop(&vm->callstack);
+ vm->cf = be_stack_top(&vm->callstack);
+}
+
+static bbool obj2bool(bvm *vm, bvalue *var)
+{
+ binstance *obj = var_toobj(var);
+ bstring *tobool = str_literal(vm, "tobool");
+ /* get operator method */
+ int type = be_instance_member(vm, obj, tobool, vm->top);
+ if (type != BE_NONE && type != BE_NIL) {
+ vm->top[1] = *var; /* move self to argv[0] */
+ be_dofunc(vm, vm->top, 1); /* call method 'tobool' */
+ /* check the return value */
+ check_bool(vm, obj, "tobool");
+ return var_tobool(vm->top);
+ }
+ return btrue;
+}
+
+bbool be_value2bool(bvm *vm, bvalue *v)
+{
+ switch (var_basetype(v)) {
+ case BE_NIL:
+ return bfalse;
+ case BE_BOOL:
+ return var_tobool(v);
+ case BE_INT:
+ return val2bool(v->v.i);
+ case BE_REAL:
+ return val2bool(v->v.r);
+ case BE_INSTANCE:
+ return obj2bool(vm, v);
+ default:
+ return btrue;
+ }
+}
+
+static void obj_method(bvm *vm, bvalue *o, bstring *attr, bvalue *dst)
+{
+ binstance *obj = var_toobj(o);
+ int type = be_instance_member_simple(vm, obj, attr, dst);
+ if (basetype(type) != BE_FUNCTION) {
+ vm_error(vm, "attribute_error",
+ "the '%s' object has no method '%s'",
+ str(be_instance_name(obj)), str(attr));
+ }
+}
+
+static int obj_attribute(bvm *vm, bvalue *o, bstring *attr, bvalue *dst)
+{
+ binstance *obj = var_toobj(o);
+ int type = be_instance_member(vm, obj, attr, dst);
+ if (type == BE_NONE) {
+ vm_error(vm, "attribute_error",
+ "the '%s' object has no attribute '%s'",
+ str(be_instance_name(obj)), str(attr));
+ }
+ return type;
+}
+
+static int class_attribute(bvm *vm, bvalue *o, bvalue *c, bvalue *dst)
+{
+ bstring *attr = var_tostr(c);
+ bclass *obj = var_toobj(o);
+ int type = be_class_member(vm, obj, attr, dst);
+ if (type == BE_NONE || type == BE_INDEX) {
+ vm_error(vm, "attribute_error",
+ "the '%s' class has no static attribute '%s'",
+ str(obj->name), str(attr));
+ }
+ return type;
+}
+
+static int module_attribute(bvm *vm, bvalue *o, bvalue *c, bvalue *dst)
+{
+ bstring *attr = var_tostr(c);
+ bmodule *module = var_toobj(o);
+ int type = be_module_attr(vm, module, attr, dst);
+ if (type == BE_NONE) {
+ vm_error(vm, "attribute_error",
+ "module '%s' has no member '%s'",
+ be_module_name(module), str(attr));
+ }
+ return type;
+}
+
+static bbool object_eqop(bvm *vm,
+ const char *op, bbool iseq, bvalue *a, bvalue *b)
+{
+ binstance *o = var_toobj(a);
+ bvalue self = *a, other = *b;
+ bbool isself = var_isinstance(b) && o == var_toobj(b);
+ /* first, try to call the overloaded operator of the object */
+ int type = be_instance_member(vm, o, be_newstr(vm, op), vm->top);
+ if (basetype(type) == BE_FUNCTION) { /* call method */
+ bvalue *top = vm->top;
+ top[1] = self; /* move self to argv[0] */
+ top[2] = other; /* move other to argv[1] */
+ be_incrtop(vm); /* prevent collection results */
+ be_dofunc(vm, top, 2); /* call method 'item' */
+ be_stackpop(vm, 1);
+ check_bool(vm, o, op); /* check return value */
+ return var_tobool(vm->top); /* copy result to dst */
+ }
+ /* the default equal operation rule */
+ return iseq == isself; /* check object self */
+}
+
+static void object_binop(bvm *vm, const char *op, bvalue self, bvalue other)
+{
+ bvalue *top = vm->top;
+ /* get operator method (possible GC) */
+ obj_method(vm, &self, be_newstr(vm, op), vm->top);
+ top[1] = self; /* move self to argv[0] */
+ top[2] = other; /* move other to argv[1] */
+ be_incrtop(vm); /* prevent collection results */
+ be_dofunc(vm, top, 2); /* call method 'item' */
+ be_stackpop(vm, 1);
+}
+
+#define ins_binop(vm, op, ins) { \
+ object_binop(vm, op, *RKB(), *RKC()); \
+ reg = vm->reg; \
+ *RA() = *vm->top; /* copy result to dst */ \
+}
+
+static void ins_unop(bvm *vm, const char *op, bvalue self)
+{
+ bvalue *top = vm->top;
+ /* get operator method (possible GC) */
+ obj_method(vm, &self, be_newstr(vm, op), vm->top);
+ top[1] = self; /* move self to argv[0] */
+ be_dofunc(vm, top, 1); /* call method 'item' */
+}
+
+bbool be_vm_iseq(bvm *vm, bvalue *a, bvalue *b)
+{
+ equal_rule(==, btrue);
+}
+
+bbool be_vm_isneq(bvm *vm, bvalue *a, bvalue *b)
+{
+ equal_rule(!=, bfalse);
+}
+
+bbool be_vm_islt(bvm *vm, bvalue *a, bvalue *b)
+{
+ relop_rule(<);
+}
+
+bbool be_vm_isle(bvm *vm, bvalue *a, bvalue *b)
+{
+ relop_rule(<=);
+}
+
+bbool be_vm_isgt(bvm *vm, bvalue *a, bvalue *b)
+{
+ relop_rule(>);
+}
+
+bbool be_vm_isge(bvm *vm, bvalue *a, bvalue *b)
+{
+ relop_rule(>=);
+}
+
+static void make_range(bvm *vm, bvalue lower, bvalue upper)
+{
+ /* get method 'item' (possible GC) */
+ int idx = be_builtin_find(vm, str_literal(vm, "range"));
+ bvalue *top = vm->top;
+ top[0] = *be_global_var(vm, idx);
+ top[1] = lower; /* move lower to argv[0] */
+ top[2] = upper; /* move upper to argv[1] */
+ vm->top += 3; /* prevent collection results */
+ be_dofunc(vm, top, 2); /* call method 'item' */
+ vm->top -= 3;
+}
+
+static void connect_str(bvm *vm, bstring *a, bvalue *b)
+{
+ bstring *s;
+ if (var_isstr(b)) {
+ s = be_strcat(vm, a, var_tostr(b));
+ var_setstr(vm->top, s);
+ } else {
+ *vm->top++ = *b;
+ be_val2str(vm, -1);
+ b = vm->top - 1;
+ s = be_strcat(vm, a, var_tostr(b));
+ var_setstr(b, s);
+ vm->top -= 1;
+ }
+}
+
+BERRY_API bvm* be_vm_new(void)
+{
+ bvm *vm = be_os_malloc(sizeof(bvm));
+ be_assert(vm != NULL);
+ memset(vm, 0, sizeof(bvm)); /* clear all members */
+ be_gc_init(vm);
+ be_string_init(vm);
+ be_stack_init(vm, &vm->callstack, sizeof(bcallframe));
+ be_stack_init(vm, &vm->refstack, sizeof(binstance*));
+ be_stack_init(vm, &vm->exceptstack, sizeof(struct bexecptframe));
+ be_stack_init(vm, &vm->tracestack, sizeof(bcallsnapshot));
+ vm->stack = be_malloc(vm, sizeof(bvalue) * BE_STACK_START);
+ vm->stacktop = vm->stack + BE_STACK_START;
+ vm->reg = vm->stack;
+ vm->top = vm->reg;
+ be_globalvar_init(vm);
+ be_gc_setpause(vm, 1);
+ be_loadlibs(vm);
+ vm->compopt = 0;
+ vm->obshook = NULL;
+#if BE_USE_PERF_COUNTERS
+ vm->counter_ins = 0;
+ vm->counter_enter = 0;
+ vm->counter_call = 0;
+ vm->counter_get = 0;
+ vm->counter_set = 0;
+ vm->counter_try = 0;
+ vm->counter_exc = 0;
+ vm->counter_gc_kept = 0;
+ vm->counter_gc_freed = 0;
+#endif
+ return vm;
+}
+
+BERRY_API void be_vm_delete(bvm *vm)
+{
+ be_gc_deleteall(vm);
+ be_string_deleteall(vm);
+ be_stack_delete(vm, &vm->callstack);
+ be_stack_delete(vm, &vm->refstack);
+ be_stack_delete(vm, &vm->exceptstack);
+ be_stack_delete(vm, &vm->tracestack);
+ be_free(vm, vm->stack, (vm->stacktop - vm->stack) * sizeof(bvalue));
+ be_globalvar_deinit(vm);
+#if BE_USE_DEBUG_HOOK
+ /* free native hook */
+ if (var_istype(&vm->hook, BE_COMPTR))
+ be_free(vm, var_toobj(&vm->hook), sizeof(struct bhookblock));
+#endif
+ /* free VM structure */
+ be_os_free(vm);
+}
+
+static void vm_exec(bvm *vm)
+{
+ bclosure *clos;
+ bvalue *ktab, *reg;
+ binstruction ins;
+ vm->cf->status |= BASE_FRAME;
+newframe: /* a new call frame */
+ be_assert(var_isclosure(vm->cf->func));
+ clos = var_toobj(vm->cf->func); /* `clos` is the current function/closure */
+ ktab = clos->proto->ktab; /* `ktab` is the current constant table */
+ reg = vm->reg; /* `reg` is the current stack base for the callframe */
+#if BE_USE_PERF_COUNTERS
+ vm->counter_enter++;
+#endif
+ vm_exec_loop() {
+ opcase(LDNIL): {
+ var_setnil(RA());
+ dispatch();
+ }
+ opcase(LDBOOL): {
+ bvalue *v = RA();
+ var_setbool(v, IGET_RKB(ins));
+ if (IGET_RKC(ins)) { /* skip next instruction */
+ vm->ip += 1;
+ }
+ dispatch();
+ }
+ opcase(LDINT): {
+ bvalue *v = RA();
+ var_setint(v, IGET_sBx(ins));
+ dispatch();
+ }
+ opcase(LDCONST): {
+ bvalue *dst = RA();
+ *dst = ktab[IGET_Bx(ins)];
+ dispatch();
+ }
+ opcase(GETGBL): {
+ bvalue *v = RA();
+ int idx = IGET_Bx(ins);
+ *v = *be_global_var(vm, idx);
+ dispatch();
+ }
+ opcase(GETNGBL): { /* get Global by name */
+ bvalue *v = RA();
+ bvalue *b = RKB();
+ if (var_isstr(b)) {
+ bstring *name = var_tostr(b);
+ int idx = be_global_find(vm, name);
+ if (idx > -1) {
+ *v = *be_global_var(vm, idx);
+ } else {
+ vm_error(vm, "attribute_error", "'%s' undeclared", str(name));
+ }
+ } else {
+ vm_error(vm, "internal_error", "global name must be a string");
+ }
+ dispatch();
+ }
+ opcase(SETNGBL): { /* set Global by name */
+ bvalue *v = RA();
+ bvalue *b = RKB();
+ if (var_isstr(b)) {
+ bstring *name = var_tostr(b);
+ int idx = be_global_new(vm, name);
+ *be_global_var(vm, idx) = *v;
+ } else {
+ vm_error(vm, "internal_error", "global name must be a string");
+ }
+ dispatch();
+ }
+ opcase(SETGBL): {
+ bvalue *v = RA();
+ int idx = IGET_Bx(ins);
+ *be_global_var(vm, idx) = *v;
+ dispatch();
+ }
+ opcase(GETUPV): {
+ bvalue *v = RA();
+ int idx = IGET_Bx(ins);
+ be_assert(*clos->upvals != NULL);
+ *v = *clos->upvals[idx]->value;
+ dispatch();
+ }
+ opcase(SETUPV): {
+ bvalue *v = RA();
+ int idx = IGET_Bx(ins);
+ be_assert(*clos->upvals != NULL);
+ *clos->upvals[idx]->value = *v;
+ dispatch();
+ }
+ opcase(MOVE): {
+ bvalue *dst = RA();
+ *dst = *RKB();
+ dispatch();
+ }
+ opcase(ADD): {
+ bvalue *dst = RA(), *a = RKB(), *b = RKC();
+ if (var_isint(a) && var_isint(b)) {
+ var_setint(dst, ibinop(+, a, b));
+ } else if (var_isnumber(a) && var_isnumber(b)) {
+ breal x = var2real(a), y = var2real(b);
+ var_setreal(dst, x + y);
+ } else if (var_isstr(a) && var_isstr(b)) { /* strcat */
+ bstring *s = be_strcat(vm, var_tostr(a), var_tostr(b));
+ reg = vm->reg;
+ dst = RA();
+ var_setstr(dst, s);
+ } else if (var_isinstance(a)) {
+ ins_binop(vm, "+", ins);
+ } else {
+ binop_error(vm, "+", a, b);
+ }
+ dispatch();
+ }
+ opcase(SUB): {
+ bvalue *dst = RA(), *a = RKB(), *b = RKC();
+ if (var_isint(a) && var_isint(b)) {
+ var_setint(dst, ibinop(-, a, b));
+ } else if (var_isnumber(a) && var_isnumber(b)) {
+ breal x = var2real(a), y = var2real(b);
+ var_setreal(dst, x - y);
+ } else if (var_isinstance(a)) {
+ ins_binop(vm, "-", ins);
+ } else {
+ binop_error(vm, "-", a, b);
+ }
+ dispatch();
+ }
+ opcase(MUL): {
+ bvalue *dst = RA(), *a = RKB(), *b = RKC();
+ if (var_isint(a) && var_isint(b)) {
+ var_setint(dst, ibinop(*, a, b));
+ } else if (var_isnumber(a) && var_isnumber(b)) {
+ breal x = var2real(a), y = var2real(b);
+ var_setreal(dst, x * y);
+ } else if (var_isinstance(a)) {
+ ins_binop(vm, "*", ins);
+ } else {
+ binop_error(vm, "*", a, b);
+ }
+ dispatch();
+ }
+ opcase(DIV): {
+ bvalue *dst = RA(), *a = RKB(), *b = RKC();
+ if (var_isint(a) && var_isint(b)) {
+ bint x = var_toint(a), y = var_toint(b);
+ if (y == 0) {
+ vm_error(vm, "divzero_error", "division by zero");
+ } else {
+ var_setint(dst, x / y);
+ }
+ } else if (var_isnumber(a) && var_isnumber(b)) {
+ breal x = var2real(a), y = var2real(b);
+ if (y == cast(breal, 0)) {
+ vm_error(vm, "divzero_error", "division by zero");
+ }
+ var_setreal(dst, x / y);
+ } else if (var_isinstance(a)) {
+ ins_binop(vm, "/", ins);
+ } else {
+ binop_error(vm, "/", a, b);
+ }
+ dispatch();
+ }
+ opcase(MOD): {
+ bvalue *dst = RA(), *a = RKB(), *b = RKC();
+ if (var_isint(a) && var_isint(b)) {
+ var_setint(dst, ibinop(%, a, b));
+ } else if (var_isnumber(a) && var_isnumber(b)) {
+ var_setreal(dst, mathfunc(fmod)(var_toreal(a), var_toreal(b)));
+ } else if (var_isinstance(a)) {
+ ins_binop(vm, "%", ins);
+ } else {
+ binop_error(vm, "%", a, b);
+ }
+ dispatch();
+ }
+ opcase(LT): {
+ bbool res = be_vm_islt(vm, RKB(), RKC());
+ bvalue *dst;
+ reg = vm->reg;
+ dst = RA();
+ var_setbool(dst, res);
+ dispatch();
+ }
+ opcase(LE): {
+ bbool res = be_vm_isle(vm, RKB(), RKC());
+ bvalue *dst;
+ reg = vm->reg;
+ dst = RA();
+ var_setbool(dst, res);
+ dispatch();
+ }
+ opcase(EQ): {
+ bbool res = be_vm_iseq(vm, RKB(), RKC());
+ bvalue *dst;
+ reg = vm->reg;
+ dst = RA();
+ var_setbool(dst, res);
+ dispatch();
+ }
+ opcase(NE): {
+ bbool res = be_vm_isneq(vm, RKB(), RKC());
+ bvalue *dst;
+ reg = vm->reg;
+ dst = RA();
+ var_setbool(dst, res);
+ dispatch();
+ }
+ opcase(GT): {
+ bbool res = be_vm_isgt(vm, RKB(), RKC());
+ bvalue *dst;
+ reg = vm->reg;
+ dst = RA();
+ var_setbool(dst, res);
+ dispatch();
+ }
+ opcase(GE): {
+ bbool res = be_vm_isge(vm, RKB(), RKC());
+ bvalue *dst;
+ reg = vm->reg;
+ dst = RA();
+ var_setbool(dst, res);
+ dispatch();
+ }
+ opcase(CONNECT): {
+ bvalue *a = RKB(), *b = RKC();
+ if (var_isint(a) && var_isint(b)) {
+ make_range(vm, *RKB(), *RKC());
+ } else if (var_isstr(a)) {
+ connect_str(vm, var_tostr(a), b);
+ } else if (var_isinstance(a)) {
+ object_binop(vm, "..", *RKB(), *RKC());
+ } else {
+ binop_error(vm, "..", RKB(), RKC());
+ }
+ reg = vm->reg;
+ *RA() = *vm->top; /* copy result to R(A) */
+ dispatch();
+ }
+ opcase(AND): {
+ bitwise_block(&);
+ dispatch();
+ }
+ opcase(OR): {
+ bitwise_block(|);
+ dispatch();
+ }
+ opcase(XOR): {
+ bitwise_block(^);
+ dispatch();
+ }
+ opcase(SHL): {
+ bitwise_block(<<);
+ dispatch();
+ }
+ opcase(SHR): {
+ bitwise_block(>>);
+ dispatch();
+ }
+ opcase(NEG): {
+ bvalue *dst = RA(), *a = RKB();
+ if (var_isint(a)) {
+ var_setint(dst, -a->v.i);
+ } else if (var_isreal(a)) {
+ var_setreal(dst, -a->v.r);
+ } else if (var_isinstance(a)) {
+ ins_unop(vm, "-*", *RKB());
+ reg = vm->reg;
+ *RA() = *vm->top; /* copy result to dst */
+ } else {
+ unop_error(vm, "-", a);
+ }
+ dispatch();
+ }
+ opcase(FLIP): {
+ bvalue *dst = RA(), *a = RKB();
+ if (var_isint(a)) {
+ var_setint(dst, ~a->v.i);
+ } else if (var_isinstance(a)) {
+ ins_unop(vm, "~", *RKB());
+ reg = vm->reg;
+ *RA() = *vm->top; /* copy result to dst */
+ } else {
+ unop_error(vm, "~", a);
+ }
+ dispatch();
+ }
+ opcase(JMP): {
+ vm->ip += IGET_sBx(ins);
+ dispatch();
+ }
+ opcase(JMPT): {
+ if (be_value2bool(vm, RA())) {
+ vm->ip += IGET_sBx(ins);
+ }
+ dispatch();
+ }
+ opcase(JMPF): {
+ if (!be_value2bool(vm, RA())) {
+ vm->ip += IGET_sBx(ins);
+ }
+ dispatch();
+ }
+ opcase(CLOSURE): {
+ bvalue *dst;
+ bproto *p = clos->proto->ptab[IGET_Bx(ins)];
+ bclosure *cl = be_newclosure(vm, p->nupvals);
+ cl->proto = p;
+ reg = vm->reg;
+ dst = RA();
+ var_setclosure(dst, cl);
+ be_initupvals(vm, cl);
+ dispatch();
+ }
+ opcase(CLASS): {
+ bclass *c = var_toobj(ktab + IGET_Bx(ins));
+ be_class_upvalue_init(vm, c);
+ dispatch();
+ }
+ opcase(GETMBR): {
+#if BE_USE_PERF_COUNTERS
+ vm->counter_get++;
+#endif
+ bvalue a_temp; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
+ bvalue *b = RKB(), *c = RKC();
+ if (var_isinstance(b) && var_isstr(c)) {
+ obj_attribute(vm, b, var_tostr(c), &a_temp);
+ reg = vm->reg;
+ } else if (var_isclass(b) && var_isstr(c)) {
+ class_attribute(vm, b, c, &a_temp);
+ reg = vm->reg;
+ } else if (var_ismodule(b) && var_isstr(c)) {
+ module_attribute(vm, b, c, &a_temp);
+ reg = vm->reg;
+ } else {
+ attribute_error(vm, "attribute", b, c);
+ a_temp = *RA(); /* avoid gcc warning for uninitialized variable a_temp, this code is never reached */
+ }
+ bvalue *a = RA();
+ *a = a_temp; /* assign the resul to the specified register on the updated stack */
+ dispatch();
+ }
+ opcase(GETMET): {
+#if BE_USE_PERF_COUNTERS
+ vm->counter_get++;
+#endif
+ bvalue a_temp; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
+ bvalue *b = RKB(), *c = RKC();
+ if (var_isinstance(b) && var_isstr(c)) {
+ binstance *obj = var_toobj(b);
+ int type = obj_attribute(vm, b, var_tostr(c), &a_temp);
+ reg = vm->reg;
+ bvalue *a = RA();
+ *a = a_temp;
+ if (var_basetype(a) == BE_FUNCTION) {
+ if (func_isstatic(a) || (type == BE_INDEX)) { /* if instance variable then we consider it's non-method */
+ /* static method, don't bother with the instance */
+ a[1] = a_temp;
+ var_settype(a, NOT_METHOD);
+ } else {
+ /* this is a real method (i.e. non-static) */
+ /* check if the object is a superinstance, if so get the lowest possible subclass */
+ while (obj->sub) {
+ obj = obj->sub;
+ }
+ var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */
+ }
+ } else {
+ vm_error(vm, "attribute_error",
+ "class '%s' has no method '%s'",
+ str(be_instance_name(obj)), str(var_tostr(c)));
+ }
+ } else if (var_isclass(b) && var_isstr(c)) {
+ class_attribute(vm, b, c, &a_temp);
+ reg = vm->reg;
+ bvalue *a = RA();
+ a[1] = a_temp;
+ var_settype(a, NOT_METHOD);
+ } else if (var_ismodule(b) && var_isstr(c)) {
+ module_attribute(vm, b, c, &a_temp);
+ reg = vm->reg;
+ bvalue *a = RA();
+ a[1] = a_temp;
+ var_settype(a, NOT_METHOD);
+ } else {
+ attribute_error(vm, "method", b, c);
+ }
+ dispatch();
+ }
+ opcase(SETMBR): {
+#if BE_USE_PERF_COUNTERS
+ vm->counter_set++;
+#endif
+ bvalue *a = RA(), *b = RKB(), *c = RKC();
+ if (var_isinstance(a) && var_isstr(b)) {
+ binstance *obj = var_toobj(a);
+ bstring *attr = var_tostr(b);
+ if (!be_instance_setmember(vm, obj, attr, c)) {
+ reg = vm->reg;
+ vm_error(vm, "attribute_error",
+ "class '%s' cannot assign to attribute '%s'",
+ str(be_instance_name(obj)), str(attr));
+ }
+ reg = vm->reg;
+ dispatch();
+ }
+ if (var_isclass(a) && var_isstr(b)) {
+ /* if value is a function, we mark it as a static to distinguish from methods */
+ bclass *obj = var_toobj(a);
+ bstring *attr = var_tostr(b);
+ bvalue c_static = *c;
+ if (var_isfunction(&c_static)) {
+ c_static.type = func_setstatic(&c_static);
+ }
+ if (!be_class_setmember(vm, obj, attr, &c_static)) {
+ reg = vm->reg;
+ vm_error(vm, "attribute_error",
+ "class '%s' cannot assign to static attribute '%s'",
+ str(be_class_name(obj)), str(attr));
+ }
+ reg = vm->reg;
+ dispatch();
+ }
+ if (var_ismodule(a) && var_isstr(b)) {
+ bmodule *obj = var_toobj(a);
+ bstring *attr = var_tostr(b);
+ if (be_module_setmember(vm, obj, attr, c)) {
+ reg = vm->reg;
+ dispatch();
+ } else {
+ reg = vm->reg;
+ // fall through exception below
+ }
+ }
+ attribute_error(vm, "writable attribute", a, b);
+ dispatch();
+ }
+ opcase(GETIDX): {
+ bvalue *b = RKB(), *c = RKC();
+ if (var_isinstance(b)) {
+ bvalue *top = vm->top;
+ /* get method 'item' */
+ obj_method(vm, b, str_literal(vm, "item"), vm->top);
+ top[1] = *b; /* move object to argv[0] */
+ top[2] = *c; /* move key to argv[1] */
+ vm->top += 3; /* prevent collection results */
+ be_dofunc(vm, top, 2); /* call method 'item' */
+ vm->top -= 3;
+ reg = vm->reg;
+ *RA() = *vm->top; /* copy result to R(A) */
+ } else if (var_isstr(b)) {
+ bstring *s = be_strindex(vm, var_tostr(b), c);
+ reg = vm->reg;
+ var_setstr(RA(), s);
+ } else {
+ vm_error(vm, "type_error",
+ "value '%s' does not support subscriptable",
+ be_vtype2str(b));
+ }
+ dispatch();
+ }
+ opcase(SETIDX): {
+ bvalue *a = RA(), *b = RKB(), *c = RKC();
+ if (var_isinstance(a)) {
+ bvalue *top = vm->top;
+ /* get method 'setitem' */
+ obj_method(vm, a, str_literal(vm, "setitem"), vm->top);
+ top[1] = *a; /* move object to argv[0] */
+ top[2] = *b; /* move key to argv[1] */
+ top[3] = *c; /* move src to argv[2] */
+ vm->top += 4;
+ be_dofunc(vm, top, 3); /* call method 'setitem' */
+ vm->top -= 4;
+ reg = vm->reg;
+ } else {
+ vm_error(vm, "type_error",
+ "value '%s' does not support index assignment",
+ be_vtype2str(a));
+ }
+ dispatch();
+ }
+ opcase(SETSUPER): {
+ bvalue *a = RA(), *b = RKB();
+ if (var_isclass(a) && var_isclass(b)) {
+ bclass *obj = var_toobj(a);
+ if (!gc_isconst(obj)) {
+ be_class_setsuper(obj, var_toobj(b));
+ } else {
+ vm_error(vm, "internal_error",
+ "cannot change superclass of a read-only class");
+ }
+ } else {
+ vm_error(vm, "type_error",
+ "value '%s' does not support set super",
+ be_vtype2str(b));
+ }
+ dispatch();
+ }
+ opcase(CLOSE): {
+ be_upvals_close(vm, RA());
+ dispatch();
+ }
+ opcase(IMPORT): {
+ bvalue *b = RKB();
+ if (var_isstr(b)) {
+ bstring *name = var_tostr(b);
+ int res = be_module_load(vm, name);
+ reg = vm->reg;
+ switch (res) {
+ case BE_OK: /* find the module */
+ be_stackpop(vm, 1);
+ *RA() = *vm->top;
+ break;
+ case BE_EXCEPTION: /* pop the exception value and message */
+ be_pop(vm, 2);
+ be_throw(vm, BE_EXCEPTION);
+ break;
+ default:
+ vm_error(vm, "import_error", "module '%s' not found", str(name));
+ }
+ } else {
+ vm_error(vm, "type_error",
+ "import '%s' does not support import",
+ be_vtype2str(b));
+ }
+ dispatch();
+ }
+ opcase(CATCH): {
+ bvalue *base = RA(), *top = vm->top;
+ int i = 0, ecnt = IGET_RKB(ins), vcnt = IGET_RKC(ins);
+ while (i < ecnt && !be_vm_iseq(vm, top, base + i)) {
+ ++i;
+ }
+ if (!ecnt || i < ecnt) { /* exception catched */
+ base = RA(), top = vm->top;
+ for (i = 0; i < vcnt; ++i) {
+ *base++ = *top++;
+ }
+ vm->ip += 1; /* skip next instruction */
+ }
+ dispatch();
+ }
+ opcase(RAISE): {
+ if (IGET_RA(ins) < 2) { /* A==2 means no arguments are passed to RAISE, i.e. rethrow with current exception */
+ bvalue *top = vm->top;
+ top[0] = *RKB(); /* push the exception value to top */
+ if (IGET_RA(ins)) { /* has exception argument? */
+ top[1] = *RKC(); /* push the exception argument to top + 1 */
+ } else {
+ var_setnil(top + 1);
+ }
+ be_save_stacktrace(vm);
+ }
+ be_throw(vm, BE_EXCEPTION); /* throw / rethrow the exception */
+ dispatch();
+ }
+ opcase(EXBLK): {
+#if BE_USE_PERF_COUNTERS
+ vm->counter_try++;
+#endif
+ if (!IGET_RA(ins)) {
+ be_except_block_setup(vm);
+ if (be_setjmp(vm->errjmp->b)) {
+ bvalue *top = vm->top;
+ bvalue e1 = top[0];
+ bvalue e2 = top[1];
+ be_except_block_resume(vm);
+ top = vm->top;
+ top[0] = e1;
+ top[1] = e2;
+ goto newframe;
+ }
+ reg = vm->reg;
+ } else {
+ be_except_block_close(vm, IGET_Bx(ins));
+ }
+ dispatch();
+ }
+ opcase(CALL): {
+#if BE_USE_PERF_COUNTERS
+ vm->counter_call++;
+#endif
+ bvalue *var = RA(); /* `var` is the register for the call followed by arguments */
+ int mode = 0, argc = IGET_RKB(ins); /* B contains number of arguments pushed on stack */
+ recall: /* goto: instantiation class and call constructor */
+ switch (var_type(var)) {
+ case NOT_METHOD:
+ var[0] = var[1];
+ ++var, --argc, mode = 1;
+ goto recall;
+ case BE_CLASS:
+ if (be_class_newobj(vm, var_toobj(var), var - reg, ++argc, mode)) { /* instanciate object and find constructor */
+ reg = vm->reg + mode; /* constructor found */
+ mode = 0;
+ var = RA() + 1; /* to next register */
+ reg = vm->reg;
+ goto recall; /* call constructor */
+ }
+ break;
+ case BE_INSTANCE: {
+ bvalue *v = var + argc++, temp;
+ /* load the '()' method to `temp' */
+ obj_method(vm, var, str_literal(vm, "()"), &temp);
+ for (; v >= var; --v) v[1] = v[0];
+ *var = temp;
+ goto recall; /* call '()' method */
+ }
+ case BE_CLOSURE: {
+ // bvalue *v, *end;
+ // bproto *proto = var2cl(var)->proto; /* get proto for closure */
+ // push_closure(vm, var, proto->nstack, mode); /* prepare stack for closure */
+ // reg = vm->reg; /* `reg` has changed, now new base register */
+ // v = reg + argc; /* end of provided arguments */
+ // end = reg + proto->argc; /* end of expected arguments */
+ // for (; v < end; ++v) { /* set all not provided arguments to nil */
+ // var_setnil(v);
+ // }
+ // if (proto->varg) { /* there are vararg at the last argument, build the list */
+ // /* code below uses mostly low-level calls for performance */
+ // be_stack_require(vm, argc + 2); /* make sure we don't overflow the stack */
+ // bvalue *top_save = vm->top; /* save original stack, we need fresh slots to create the 'list' instance */
+ // vm->top = v; /* move top of stack right after last argument */
+ // be_newobject(vm, "list"); /* this creates 2 objects on stack: list instance, BE_LIST object */
+ // blist *list = var_toobj(vm->top-1); /* get low-level BE_LIST structure */
+ // v = reg + proto->argc - 1; /* last argument */
+ // for (; v < reg + argc; v++) {
+ // be_list_push(vm, list, v); /* push all varargs into list */
+ // }
+ // *(reg + proto->argc - 1) = *(vm->top-2); /* change the vararg argument to now contain the list instance */
+ // vm->top = top_save; /* restore top of stack pointer */
+ // }
+ prep_closure(vm, var - reg, argc, mode);
+ reg = vm->reg; /* `reg` has changed, now new base register */
+ goto newframe; /* continue execution of the closure */
+ }
+ case BE_NTVCLOS: {
+ bntvclos *f = var_toobj(var);
+ push_native(vm, var, argc, mode);
+ f->f(vm); /* call C primitive function */
+ ret_native(vm);
+ break;
+ }
+ case BE_NTVFUNC: {
+ bntvfunc f = var_tontvfunc(var);
+ push_native(vm, var, argc, mode);
+ f(vm); /* call C primitive function */
+ ret_native(vm);
+ break;
+ }
+ case BE_MODULE: {
+ bvalue attr;
+ var_setstr(&attr, str_literal(vm, "()"));
+ module_attribute(vm, var, &attr, var); /* exception if not found */
+ goto recall; /* call '()' method */
+ break;
+ }
+ default:
+ call_error(vm, var);
+ }
+ reg = vm->reg;
+ dispatch();
+ }
+ opcase(RET): {
+ bcallframe *cf;
+ bvalue *ret;
+#if BE_USE_DEBUG_HOOK
+ be_callhook(vm, BE_HOOK_RET);
+#endif
+ cf = vm->cf;
+ ret = vm->cf->func;
+ /* copy return value */
+ if (IGET_RA(ins)) {
+ *ret = *RKB();
+ } else {
+ var_setnil(ret);
+ }
+ vm->reg = cf->reg;
+ vm->top = cf->top;
+ vm->ip = cf->ip;
+ be_stack_pop(&vm->callstack); /* pop don't delete */
+ if (cf->status & BASE_FRAME) { /* entrance function */
+ bstack *cs = &vm->callstack;
+ if (!be_stack_isempty(cs)) {
+ vm->cf = be_stack_top(cs);
+ }
+ return;
+ }
+ vm->cf = be_stack_top(&vm->callstack);
+ goto newframe;
+ }
+ }
+}
+
+static void prep_closure(bvm *vm, int pos, int argc, int mode)
+{
+ bvalue *v, *end;
+ bproto *proto = var2cl(vm->reg + pos)->proto;
+ push_closure(vm, vm->reg + pos, proto->nstack, mode);
+ end = vm->reg + proto->argc;
+ for (v = vm->reg + argc; v <= end; ++v) {
+ var_setnil(v);
+ }
+ if (proto->varg) { /* there are vararg at the last argument, build the list */
+ /* code below uses mostly low-level calls for performance */
+ be_stack_require(vm, argc + 2); /* make sure we don't overflow the stack */
+ bvalue *top_save = vm->top; /* save original stack, we need fresh slots to create the 'list' instance */
+ vm->top = v; /* move top of stack right after last argument */
+ be_newobject(vm, "list"); /* this creates 2 objects on stack: list instance, BE_LIST object */
+ blist *list = var_toobj(vm->top-1); /* get low-level BE_LIST structure */
+ v = vm->reg + proto->argc - 1; /* last argument */
+ for (; v < vm->reg + argc; v++) {
+ be_list_push(vm, list, v); /* push all varargs into list */
+ }
+ *(vm->reg + proto->argc - 1) = *(vm->top-2); /* change the vararg argument to now contain the list instance */
+ vm->top = top_save; /* restore top of stack pointer */
+ }
+}
+
+static void do_closure(bvm *vm, int pos, int argc)
+{
+ // bvalue *v, *end;
+ // bproto *proto = var2cl(reg)->proto;
+ // push_closure(vm, reg, proto->nstack, 0);
+ // v = vm->reg + argc;
+ // end = vm->reg + proto->argc;
+ // for (; v <= end; ++v) {
+ // var_setnil(v);
+ // }
+ prep_closure(vm, pos, argc, 0);
+ vm_exec(vm);
+}
+
+static void do_ntvclos(bvm *vm, int pos, int argc)
+{
+ bntvclos *f = var_toobj(vm->reg + pos);
+ push_native(vm, vm->reg + pos, argc, 0);
+ f->f(vm); /* call C primitive function */
+ ret_native(vm);
+}
+
+static void do_ntvfunc(bvm *vm, int pos, int argc)
+{
+ bntvfunc f = var_tontvfunc(vm->reg + pos);
+ push_native(vm, vm->reg + pos, argc, 0);
+ f(vm); /* call C primitive function */
+ ret_native(vm);
+}
+
+static void do_class(bvm *vm, int pos, int argc)
+{
+ if (be_class_newobj(vm, var_toobj(vm->reg + pos), pos, ++argc, 0)) {
+ be_incrtop(vm);
+ be_dofunc(vm, vm->reg + pos + 1, argc);
+ be_stackpop(vm, 1);
+ }
+}
+
+void be_dofunc(bvm *vm, bvalue *v, int argc)
+{
+ be_assert(vm->reg <= v && v < vm->stacktop);
+ be_assert(vm->stack <= vm->reg && vm->reg < vm->stacktop);
+ int pos = v - vm->reg;
+ switch (var_type(v)) {
+ case BE_CLASS: do_class(vm, pos, argc); break;
+ case BE_CLOSURE: do_closure(vm, pos, argc); break;
+ case BE_NTVCLOS: do_ntvclos(vm, pos, argc); break;
+ case BE_NTVFUNC: do_ntvfunc(vm, pos, argc); break;
+ default: call_error(vm, v);
+ }
+}
+
+BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook)
+{
+ (void)vm; /* avoid comiler warning */
+ (void)hook; /* avoid comiler warning */
+
+ vm->obshook = hook;
+}
diff --git a/lib/libesp32/berry/src/be_vm.h b/lib/libesp32/berry/src/be_vm.h
new file mode 100644
index 000000000..19d745a7c
--- /dev/null
+++ b/lib/libesp32/berry/src/be_vm.h
@@ -0,0 +1,135 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef BE_VM_H
+#define BE_VM_H
+
+#include "be_object.h"
+
+#define comp_is_named_gbl(vm) ((vm)->compopt & (1<compopt |= (1<compopt &= ~(1<compopt & (1<compopt |= (1<compopt &= ~(1<
+#include
+
+#include "berry_conf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* do not modify the version number! */
+#define BERRY_VERSION "1.0.0"
+
+#if BE_STACK_TOTAL_MAX < BE_STACK_FREE_MIN * 2
+#error "The value of the macro BE_STACK_TOTAL_MAX is too small."
+#endif
+
+/* basic type definition */
+#if BE_INTGER_TYPE == 0
+ #define BE_INTEGER int
+ #define BE_INT_FMTLEN ""
+#elif BE_INTGER_TYPE == 1
+ #define BE_INTEGER long
+ #define BE_INT_FMTLEN "l"
+#elif BE_INTGER_TYPE == 2
+ #ifdef _WIN32
+ #define BE_INTEGER __int64
+ #define BE_INT_FMTLEN "I64"
+ #else
+ #define BE_INTEGER long long
+ #define BE_INT_FMTLEN "ll"
+ #endif
+#else
+ #error "Unsupported integer type for `bint`."
+#endif
+#define BE_INT_FORMAT "%" BE_INT_FMTLEN "d"
+
+typedef uint8_t bbyte;
+typedef BE_INTEGER bint;
+
+#if BE_USE_SINGLE_FLOAT != 0
+ typedef float breal;
+#else
+ typedef double breal;
+#endif
+
+/* boolean values definition */
+#ifndef __cplusplus
+ #define bbool _Bool
+ #define bfalse 0
+ #define btrue 1
+#else
+ #define bbool bool
+ #define bfalse false
+ #define btrue true
+#endif
+
+/* error code definition */
+enum berrorcode {
+ BE_OK = 0,
+ BE_EXIT,
+ BE_MALLOC_FAIL,
+ BE_EXCEPTION,
+ BE_SYNTAX_ERROR,
+ BE_EXEC_ERROR,
+ BE_IO_ERROR
+};
+
+/* native-module member type specifier */
+#define BE_CNIL 0
+#define BE_CINT 1
+#define BE_CREAL 2
+#define BE_CBOOL 3
+#define BE_CFUNCTION 4
+#define BE_CSTRING 5
+#define BE_CMODULE 6
+
+/* API function mark */
+#if defined(_WIN32) || defined(__CYGWIN__) /* in Windows */
+ #if defined(BERRY_MODULE) /* berry extension module */
+ #define BERRY_API __declspec(dllimport)
+ #else /* berry core */
+ #define BERRY_API __declspec(dllexport)
+ #endif
+#else /* other platforms */
+ #define BERRY_API extern
+#endif
+
+/* only linux */
+#if defined(_WIN32) || defined(__CYGWIN__) /* in Windows */
+ #define BERRY_LOCAL
+#elif defined(__GNUC__) /* in GCC */
+ #define BERRY_LOCAL __attribute__ ((visibility ("hidden")))
+#else /* other platforms */
+ #define BERRY_LOCAL
+#endif
+
+#ifdef __cplusplus
+#ifdef __cpp_constexpr
+ #define BE_CONSTEXPR constexpr
+#else
+ #define BE_CONSTEXPR
+#endif
+#endif
+
+#ifdef __cplusplus
+#define BE_EXPORT_VARIABLE extern "C"
+#else
+#define BE_EXPORT_VARIABLE
+#endif
+
+typedef struct bvm bvm; /* virtual machine structure */
+typedef int (*bntvfunc)(bvm*); /* native function pointer */
+struct bclass;
+
+/* native function information */
+typedef struct {
+ const char *name;
+ bntvfunc function;
+} bnfuncinfo;
+
+/* native module object node */
+typedef struct bntvmodobj {
+ const char *name;
+ int type;
+ union value {
+ bint i;
+ breal r;
+ bbool b;
+ bntvfunc f;
+ const char *s;
+ const void *o;
+#ifdef __cplusplus
+ BE_CONSTEXPR value(bint v) : i(v) {}
+ BE_CONSTEXPR value(breal v) : r(v) {}
+ BE_CONSTEXPR value(bbool v) : b(v) {}
+ BE_CONSTEXPR value(bntvfunc v) : f(v) {}
+ BE_CONSTEXPR value(const char *v) : s(v) {}
+ BE_CONSTEXPR value(const void *v) : o(v) {}
+#endif
+ } u;
+#ifdef __cplusplus
+ BE_CONSTEXPR bntvmodobj(const char *name) :
+ name(name), type(BE_CNIL), u(bint(0)) {}
+ BE_CONSTEXPR bntvmodobj(const char *name, bint v) :
+ name(name), type(BE_CINT), u(v) {}
+ BE_CONSTEXPR bntvmodobj(const char *name, breal v) :
+ name(name), type(BE_CREAL), u(v) {}
+ BE_CONSTEXPR bntvmodobj(const char *name, bbool v) :
+ name(name), type(BE_CBOOL), u(v) {}
+ BE_CONSTEXPR bntvmodobj(const char *name, bntvfunc v) :
+ name(name), type(BE_CFUNCTION), u(v) {}
+ BE_CONSTEXPR bntvmodobj(const char *name, const char *v) :
+ name(name), type(BE_CSTRING), u(v) {}
+ BE_CONSTEXPR bntvmodobj(const char *name, int _tpye, const void *v) :
+ name(name), type(_tpye), u(v) {}
+#endif
+} bntvmodobj;
+
+/* native module object */
+typedef struct bntvmodule {
+ const char *name; /* native module name */
+ const bntvmodobj *attrs; /* native module attributes */
+ size_t size; /* native module attribute count */
+ const struct bmodule *module; /* const module object */
+} bntvmodule;
+
+/* native module node definition macro */
+#ifndef __cplusplus
+#define be_native_module_nil(_name) \
+ { .name = (_name), .type = BE_CNIL, .u.i = 0 }
+
+#define be_native_module_int(_name, _v) \
+ { .name = (_name), .type = BE_CINT, .u.i = (bint)(_v) }
+
+#define be_native_module_real(_name, _v) \
+ { .name = (_name), .type = BE_CREAL, .u.r = (breal)(_v) }
+
+#define be_native_module_bool(_name, _b) \
+ { .name = (_name), .type = BE_CBOOL, .u.b = (bbool)(_b) }
+
+#define be_native_module_function(_name, _f) \
+ { .name = (_name), .type = BE_CFUNCTION, .u.f = (_f) }
+
+#define be_native_module_str(_name, _s) \
+ { .name = (_name), .type = BE_CSTRING, .u.s = (_s) }
+
+#define be_native_module_module(_name, _m) \
+ { .name = (_name), .type = BE_CMODULE, .u.o = &(_m) }
+#else
+#define be_native_module_nil(_name) \
+ bntvmodobj(_name)
+
+#define be_native_module_int(_name, _v) \
+ bntvmodobj(_name, bint(_v))
+
+#define be_native_module_real(_name, _v) \
+ bntvmodobj(_name, breal(_v))
+
+#define be_native_module_bool(_name, _b) \
+ bntvmodobj(_name, bbool(_b))
+
+#define be_native_module_function(_name, _f) \
+ bntvmodobj(_name, _f)
+
+#define be_native_module_str(_name, _s) \
+ bntvmodobj(_name, _s)
+
+#define be_native_module_module(_name, _m) \
+ bntvmodobj(_name, BE_CMODULE, &(_m))
+#endif
+
+#define be_native_module_attr_table(name) \
+ static const bntvmodobj name##_attrs[] =
+
+#define be_native_module(name) be_native_module_##name
+
+/* native module declaration macro */
+#define be_extern_native_module(name) \
+ extern const bntvmodule be_native_module(name)
+
+/* native module definition macro */
+#ifndef __cplusplus
+#define be_define_native_module(_name, _init) \
+ const bntvmodule be_native_module(_name) = { \
+ .name = #_name, \
+ .attrs = _name##_attrs, \
+ .size = sizeof(_name##_attrs) \
+ / sizeof(_name##_attrs[0]), \
+ .module = NULL, \
+ .init = _init \
+ }
+#else
+#define be_define_native_module(_name, _init) \
+ const bntvmodule be_native_module(_name) = { \
+ #_name, _name##_attrs, \
+ sizeof(_name##_attrs) \
+ / sizeof(_name##_attrs[0]), \
+ 0, _init \
+ }
+#endif
+
+/* support for solidified berry functions */
+/* native const strings outside of global string hash */
+#define be_define_local_const_str(_name, _s, _hash, _len) \
+ static const bcstring be_local_const_str_##_name = { \
+ .next = (bgcobject *)NULL, \
+ .type = BE_STRING, \
+ .marked = GC_CONST, \
+ .extra = 0, \
+ .slen = _len, \
+ .hash = 0, \
+ .s = _s \
+ }
+
+/* new version for more compact literals */
+#define be_nested_const_str(_s, _hash, _len) \
+ (bstring*) &(const bcstring) { \
+ .next = (bgcobject *)NULL, \
+ .type = BE_STRING, \
+ .marked = GC_CONST, \
+ .extra = 0, \
+ .slen = _len, \
+ .hash = 0, \
+ .s = _s \
+ }
+
+#define be_local_const_str(_name) (bstring*) &be_local_const_str_##_name
+
+/* conditional macro see https://stackoverflow.com/questions/11632219/c-preprocessor-macro-specialisation-based-on-an-argument */
+#define BE_IIF(cond) BE_IIF_ ## cond
+#define BE_IIF_0(t, f) f
+#define BE_IIF_1(t, f) t
+
+#if BE_DEBUG_VAR_INFO
+ #define be_local_const_upval(ins, idx) { "", ins, idx }
+#else
+ #define be_local_const_upval(ins, idx) { ins, idx }
+#endif
+
+/* conditional block in bproto depending on compilation options */
+#if BE_DEBUG_RUNTIME_INFO
+ #define PROTO_RUNTIME_BLOCK \
+ NULL, /* varinfo */ \
+ 0, /* nvarinfo */
+#else
+ #define PROTO_RUNTIME_BLOCK
+#endif
+#if BE_DEBUG_VAR_INFO
+ #define PROTO_VAR_INFO_BLOCK\
+ NULL, /* varinfo */ \
+ 0, /* nvarinfo */
+#else
+ #define PROTO_VAR_INFO_BLOCK
+#endif
+
+/* define bproto */
+#define be_define_local_proto(_name, _nstack, _argc, _is_const, _is_subproto, _is_upval) \
+ static const bproto _name##_proto = { \
+ NULL, /* bgcobject *next */ \
+ BE_PROTO, /* type BE_PROTO */ \
+ 0x08, /* marked outside of GC */ \
+ (_nstack), /* nstack */ \
+ BE_IIF(_is_upval)(sizeof(_name##_upvals)/sizeof(bupvaldesc),0),/* nupvals */ \
+ (_argc), /* argc */ \
+ 0, /* varg */ \
+ NULL, /* bgcobject *gray */ \
+ BE_IIF(_is_upval)((bupvaldesc*)&_name##_upvals,NULL), /* bupvaldesc *upvals */\
+ BE_IIF(_is_const)((bvalue*)&_name##_ktab,NULL), /* ktab */ \
+ BE_IIF(_is_subproto)((struct bproto**)&_name##_subproto,NULL),/* bproto **ptab */\
+ (binstruction*) &_name##_code, /* code */ \
+ be_local_const_str(_name##_str_name), /* name */ \
+ sizeof(_name##_code)/sizeof(uint32_t), /* codesize */ \
+ BE_IIF(_is_const)(sizeof(_name##_ktab)/sizeof(bvalue),0),/* nconst */ \
+ BE_IIF(_is_subproto)(sizeof(_name##_subproto)/sizeof(bproto*),0),/* proto */ \
+ be_local_const_str(_name##_str_source), /* source */ \
+ PROTO_RUNTIME_BLOCK \
+ PROTO_VAR_INFO_BLOCK \
+ }
+
+/* new version for more compact literals */
+#define be_nested_proto(_nstack, _argc, _varg, _has_upval, _upvals, _has_subproto, _protos, _has_const, _ktab, _fname, _source, _code) \
+ & (const bproto) { \
+ NULL, /* bgcobject *next */ \
+ BE_PROTO, /* type BE_PROTO */ \
+ 0x08, /* marked outside of GC */ \
+ (_nstack), /* nstack */ \
+ BE_IIF(_has_upval)(sizeof(*_upvals)/sizeof(bupvaldesc),0), /* nupvals */ \
+ (_argc), /* argc */ \
+ (_varg), /* varg */ \
+ NULL, /* bgcobject *gray */ \
+ (bupvaldesc*) _upvals, /* bupvaldesc *upvals */ \
+ (bvalue*) _ktab, /* ktab */ \
+ (struct bproto**) _protos, /* bproto **ptab */ \
+ (binstruction*) _code, /* code */ \
+ ((bstring*) _fname), /* name */ \
+ sizeof(*_code)/sizeof(binstruction), /* codesize */ \
+ BE_IIF(_has_const)(sizeof(*_ktab)/sizeof(bvalue),0), /* nconst */ \
+ BE_IIF(_has_subproto)(sizeof(*_protos)/sizeof(bproto*),0), /* proto */ \
+ ((bstring*) _source), /* source */ \
+ PROTO_RUNTIME_BLOCK \
+ PROTO_VAR_INFO_BLOCK \
+ }
+
+#define be_define_local_closure(_name) \
+ const bclosure _name##_closure = { \
+ NULL, /* bgcobject *next */ \
+ BE_CLOSURE, /* type BE_CLOSURE */ \
+ GC_CONST, /* marked GC_CONST */ \
+ 0, /* nupvals */ \
+ NULL, /* bgcobject *gray */ \
+ (bproto*) &_name##_proto, /* proto */ \
+ { NULL } /* upvals */ \
+ }
+
+/* new version for more compact literals */
+#define be_local_closure(_name, _proto) \
+ static const bclosure _name##_closure = { \
+ NULL, /* bgcobject *next */ \
+ BE_CLOSURE, /* type BE_CLOSURE */ \
+ GC_CONST, /* marked GC_CONST */ \
+ 0, /* nupvals */ \
+ NULL, /* bgcobject *gray */ \
+ (bproto*) _proto, /* proto */ \
+ { NULL } /* upvals */ \
+ }
+
+/* debug hook typedefs */
+#define BE_HOOK_LINE 1
+#define BE_HOOK_CALL 2
+#define BE_HOOK_RET 4
+#define BE_HOOK_EXCEPT 8
+
+typedef struct bhookinfo {
+ int type; /* current hook type */
+ int line; /* current linenumber */
+ const char *source; /* source path information */
+ const char *func_name; /* current function name */
+ void *data; /* user extended data */
+} bhookinfo;
+
+typedef void(*bntvhook)(bvm *vm, bhookinfo *info);
+
+/* the default assert definition */
+#if !BE_DEBUG
+ #if defined(be_assert)
+ #undef be_assert
+ #endif
+ #define be_assert(expr) ((void)0)
+#endif
+
+/* Observability hook */
+
+typedef void(*bobshook)(bvm *vm, int event, ...);
+enum beobshookevents {
+ BE_OBS_PCALL_ERROR, /* called when be_callp() returned an error, most likely an exception */
+ BE_OBS_GC_START, /* start of GC, arg = allocated size */
+ BE_OBS_GC_END, /* end of GC, arg = allocated size */
+ BE_OBS_VM_HEARTBEAT, /* VM heartbeat called every million instructions */
+ BE_OBS_STACK_RESIZE_START, /* Berry stack resized */
+};
+
+/* FFI functions */
+#define be_writestring(s) be_writebuffer((s), strlen(s))
+#define be_writenewline() be_writebuffer("\n", 1)
+
+#define be_return(vm) return be_returnvalue(vm)
+#define be_return_nil(vm) return be_returnnilvalue(vm)
+
+#define be_loadfile(vm, name) be_loadmode((vm), (name), 0)
+#define be_loadmodule(vm, name) be_loadmode((vm), (name), 1)
+
+#define be_loadstring(vm, str) \
+ be_loadbuffer((vm), "string", (str), strlen(str))
+
+#define be_dostring(vm, s) \
+ (be_loadstring((vm), (s)) || be_pcall((vm), 0))
+
+BERRY_API bint be_str2int(const char *str, const char **endstr);
+BERRY_API breal be_str2real(const char *str, const char **endstr);
+BERRY_API const char *be_str2num(bvm *vm, const char *str);
+
+BERRY_API int be_top(bvm *vm);
+BERRY_API const char *be_typename(bvm *vm, int index);
+BERRY_API const char *be_classname(bvm *vm, int index);
+BERRY_API bbool be_classof(bvm *vm, int index);
+BERRY_API int be_strlen(bvm *vm, int index);
+BERRY_API void be_strconcat(bvm *vm, int index);
+BERRY_API void be_pop(bvm *vm, int n);
+BERRY_API void be_remove(bvm *vm, int index);
+BERRY_API int be_absindex(bvm *vm, int index);
+
+BERRY_API bbool be_isnil(bvm *vm, int index);
+BERRY_API bbool be_isbool(bvm *vm, int index);
+BERRY_API bbool be_isint(bvm *vm, int index);
+BERRY_API bbool be_isreal(bvm *vm, int index);
+BERRY_API bbool be_isnumber(bvm *vm, int index);
+BERRY_API bbool be_isstring(bvm *vm, int index);
+BERRY_API bbool be_isclosure(bvm *vm, int index);
+BERRY_API bbool be_isntvclos(bvm *vm, int index);
+BERRY_API bbool be_isfunction(bvm *vm, int index);
+BERRY_API bbool be_isproto(bvm *vm, int index);
+BERRY_API bbool be_isclass(bvm *vm, int index);
+BERRY_API bbool be_isinstance(bvm *vm, int index);
+BERRY_API bbool be_ismodule(bvm *vm, int index);
+BERRY_API bbool be_islist(bvm *vm, int index);
+BERRY_API bbool be_ismap(bvm *vm, int index);
+BERRY_API bbool be_iscomptr(bvm *vm, int index);
+BERRY_API bbool be_iscomobj(bvm *vm, int index);
+BERRY_API bbool be_isderived(bvm *vm, int index);
+BERRY_API bbool be_isbytes(bvm *vm, int index);
+
+BERRY_API bint be_toint(bvm *vm, int index);
+BERRY_API breal be_toreal(bvm *vm, int index);
+BERRY_API int be_toindex(bvm *vm, int index);
+BERRY_API bbool be_tobool(bvm *vm, int index);
+BERRY_API const char* be_tostring(bvm *vm, int index);
+BERRY_API const char* be_toescape(bvm *vm, int index, int mode);
+BERRY_API void* be_tocomptr(bvm* vm, int index);
+BERRY_API void be_moveto(bvm *vm, int from, int to);
+BERRY_API void be_pushnil(bvm *vm);
+BERRY_API void be_pushbool(bvm *vm, int b);
+BERRY_API void be_pushint(bvm *vm, bint i);
+BERRY_API void be_pushreal(bvm *vm, breal r);
+BERRY_API void be_pushstring(bvm *vm, const char *str);
+BERRY_API void be_pushnstring(bvm *vm, const char *str, size_t n);
+BERRY_API const char* be_pushfstring(bvm *vm, const char *format, ...);
+BERRY_API void* be_pushbuffer(bvm *vm, size_t size);
+BERRY_API void be_pushvalue(bvm *vm, int index);
+BERRY_API void be_pushclosure(bvm *vm, void *cl);
+BERRY_API void be_pushntvclosure(bvm *vm, bntvfunc f, int nupvals);
+BERRY_API void be_pushntvfunction(bvm *vm, bntvfunc f);
+BERRY_API void be_pushclass(bvm *vm, const char *name, const bnfuncinfo *lib);
+BERRY_API void be_pushntvclass(bvm *vm, const struct bclass * c);
+BERRY_API void be_pushcomptr(bvm *vm, void *ptr);
+BERRY_API bbool be_pushiter(bvm *vm, int index);
+
+BERRY_API void be_newlist(bvm *vm);
+BERRY_API void be_newmap(bvm *vm);
+BERRY_API void be_newmodule(bvm *vm);
+BERRY_API void be_newcomobj(bvm *vm, void *data, bntvfunc destory);
+BERRY_API void be_newobject(bvm *vm, const char *name);
+BERRY_API bbool be_copy(bvm *vm, int index);
+BERRY_API bbool be_setname(bvm *vm, int index, const char *name);
+BERRY_API bbool be_getglobal(bvm *vm, const char *name);
+BERRY_API void be_setglobal(bvm *vm, const char *name);
+BERRY_API bbool be_getbuiltin(bvm *vm, const char *name);
+BERRY_API bbool be_setmember(bvm *vm, int index, const char *k);
+BERRY_API bbool be_getmember(bvm *vm, int index, const char *k);
+BERRY_API bbool be_getmethod(bvm *vm, int index, const char *k);
+BERRY_API bbool be_getindex(bvm *vm, int index);
+BERRY_API bbool be_setindex(bvm *vm, int index);
+BERRY_API void be_getupval(bvm *vm, int index, int pos);
+BERRY_API bbool be_setupval(bvm *vm, int index, int pos);
+BERRY_API bbool be_setsuper(bvm *vm, int index);
+BERRY_API void be_getsuper(bvm *vm, int index);
+BERRY_API int be_data_size(bvm *vm, int index);
+BERRY_API void be_data_push(bvm *vm, int index);
+BERRY_API bbool be_data_insert(bvm *vm, int index);
+BERRY_API bbool be_data_remove(bvm *vm, int index);
+BERRY_API bbool be_data_merge(bvm *vm, int index);
+BERRY_API void be_data_resize(bvm *vm, int index);
+BERRY_API void be_data_reverse(bvm *vm, int index);
+BERRY_API int be_iter_next(bvm *vm, int index);
+BERRY_API bbool be_iter_hasnext(bvm *vm, int index);
+BERRY_API bbool be_refcontains(bvm *vm, int index);
+BERRY_API void be_refpush(bvm *vm, int index);
+BERRY_API void be_refpop(bvm *vm);
+BERRY_API void be_stack_require(bvm *vm, int count);
+BERRY_API bbool be_getmodule(bvm *vm, const char *k);
+
+/* relop operation APIs */
+BERRY_API bbool be_iseq(bvm *vm);
+BERRY_API bbool be_isneq(bvm *vm);
+BERRY_API bbool be_islt(bvm *vm);
+BERRY_API bbool be_isle(bvm *vm);
+BERRY_API bbool be_isgt(bvm *vm);
+BERRY_API bbool be_isge(bvm *vm);
+
+/* Function call/return APIs */
+BERRY_API int be_returnvalue(bvm *vm);
+BERRY_API int be_returnnilvalue(bvm *vm);
+BERRY_API void be_call(bvm *vm, int argc);
+BERRY_API int be_pcall(bvm *vm, int argc);
+BERRY_API void be_exit(bvm *vm, int status);
+
+/* exception APIs */
+__attribute__((noreturn))
+BERRY_API void be_raise(bvm *vm, const char *except, const char *msg);
+BERRY_API int be_getexcept(bvm *vm, int code);
+BERRY_API void be_dumpvalue(bvm *vm, int index);
+BERRY_API void be_dumpexcept(bvm *vm);
+BERRY_API void be_stop_iteration(bvm *vm);
+
+BERRY_API void be_regfunc(bvm *vm, const char *name, bntvfunc f);
+BERRY_API void be_regclass(bvm *vm, const char *name, const bnfuncinfo *lib);
+
+/* VM management APIs */
+BERRY_API bvm* be_vm_new(void);
+BERRY_API void be_vm_delete(bvm *vm);
+
+/* Observability hook */
+BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook);
+
+/* code load APIs */
+BERRY_API int be_loadbuffer(bvm *vm,
+ const char *name, const char *buffer, size_t length);
+BERRY_API int be_loadmode(bvm *vm, const char *name, bbool islocal);
+BERRY_API int be_loadlib(bvm *vm, const char *path);
+BERRY_API int be_savecode(bvm *vm, const char *name);
+
+/* module path list APIs */
+BERRY_API void be_module_path(bvm *vm);
+BERRY_API void be_module_path_set(bvm *vm, const char *path);
+
+/* bytes operations */
+BERRY_API void* be_pushbytes(bvm *vm, const void *buf, size_t len);
+BERRY_API const void* be_tobytes(bvm *vm, int index, size_t *len);
+
+/* registry operation */
+BERRY_API int be_register(bvm *vm, int index);
+BERRY_API void be_unregister(bvm *vm, int id);
+BERRY_API void be_getregister(bvm *vm, int id);
+
+/* debug APIs */
+BERRY_API void be_sethook(bvm *vm, const char *mask);
+BERRY_API void be_setntvhook(bvm *vm, bntvhook hook, void *data, int mask);
+
+/* basic character IO APIs */
+BERRY_API void be_writebuffer(const char *buffer, size_t length);
+BERRY_API char* be_readstring(char *buffer, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesp32/berry/src/berry_conf.h b/lib/libesp32/berry/src/berry_conf.h
new file mode 100644
index 000000000..ff5a40419
--- /dev/null
+++ b/lib/libesp32/berry/src/berry_conf.h
@@ -0,0 +1 @@
+#include "../default/berry_conf.h"
diff --git a/lib/libesp32/berry/testall.be b/lib/libesp32/berry/testall.be
new file mode 100755
index 000000000..57414dbc5
--- /dev/null
+++ b/lib/libesp32/berry/testall.be
@@ -0,0 +1,44 @@
+#! ./berry
+import os
+
+os.system('lcov', '-q -c -i -d . -o init.info')
+
+var exec = './berry'
+var path = 'tests'
+var testcases = os.listdir(path)
+var total = 0, failed = 0
+
+for i : testcases
+ if os.path.splitext(i)[1] == '.be'
+ print('\033[0;36mrun testcase: ' + i + '\033[0m')
+ var ret = os.system(exec, os.path.join(path, i))
+ if ret != 0
+ print('\033[0;31mreturn code:', ret, '\033[0m')
+ failed += 1
+ end
+ total += 1
+ end
+end
+
+print('\033[0;32mtest results: ' +
+ str(total) + ' total, ' + str(failed) + ' failed' +
+ (failed ? '' : ' (all tests passed)') +
+ '.\033[0m')
+
+if failed != 0
+ os.exit(-1)
+end
+
+var cmds = [
+ 'lcov -q -c -d ./ -o cover.info',
+ 'lcov -q -a init.info -a cover.info -o total.info',
+ 'lcov --remove total.info */usr/include/* -o final.info',
+ 'genhtml -q -o test_report --legend --title "lcov" --prefix=./ final.info',
+ 'rm -f init.info cover.info total.info final.info'
+]
+
+for cmd : cmds
+ if os.system(cmd)
+ os.exit(-1)
+ end
+end
diff --git a/lib/libesp32/berry/tests/assignment.be b/lib/libesp32/berry/tests/assignment.be
new file mode 100644
index 000000000..71bb81ebf
--- /dev/null
+++ b/lib/libesp32/berry/tests/assignment.be
@@ -0,0 +1,34 @@
+class Test
+ var a
+end
+
+# continuous assignment of global suffix expressions
+o = Test()
+o.a = 100
+assert(o.a == 100)
+o.a += 10
+assert(o.a == 110)
+
+p = Test()
+p.a = Test()
+p.a.a = 50
+assert(p.a.a == 50)
+p.a.a += 10
+assert(p.a.a == 60)
+
+# continuous assignment of local suffix expressions
+def test_func()
+ var o = Test()
+ o.a = 100
+ assert(o.a == 100)
+ o.a += 10
+ assert(o.a == 110)
+
+ var p = Test()
+ p.a = Test()
+ p.a.a = 50
+ assert(p.a.a == 50)
+ p.a.a += 10
+ assert(p.a.a == 60)
+end
+test_func()
diff --git a/lib/libesp32/berry/tests/bool.be b/lib/libesp32/berry/tests/bool.be
new file mode 100644
index 000000000..807d36148
--- /dev/null
+++ b/lib/libesp32/berry/tests/bool.be
@@ -0,0 +1,39 @@
+# test cases for boolean expressions
+
+assert(1 != false && 1 != true)
+assert(0 != false && 0 != true)
+assert(!!1 == true)
+assert(!!0 == false)
+
+a = true
+b = false
+assert(!!list == true)
+assert(a && b == false)
+assert(!(a && b))
+def test(a, b)
+ while !(a && b)
+ assert(false)
+ end
+end
+test(true, true)
+
+# bug in unary
+def f(i)
+ var j = !i # bug if i is erroneously modified
+ return i
+end
+assert(f(1) == 1)
+
+#- addind bool() function -#
+assert(bool() == false)
+assert(bool(0) == false)
+assert(bool(0.0) == false)
+assert(bool(false) == false)
+assert(bool(nil) == false)
+
+assert(bool(-1) == true)
+assert(bool(3.5) == true)
+assert(bool('') == true)
+assert(bool('a') == true)
+assert(bool(list) == true)
+assert(bool(list()) == true)
diff --git a/lib/libesp32/berry/tests/bytes.be b/lib/libesp32/berry/tests/bytes.be
new file mode 100644
index 000000000..76b506c87
--- /dev/null
+++ b/lib/libesp32/berry/tests/bytes.be
@@ -0,0 +1,185 @@
+#- basic initialization -#
+b=bytes()
+assert(str(b) == "bytes('')")
+b=bytes("")
+assert(str(b) == "bytes('')")
+b=bytes(0)
+assert(str(b) == "bytes('')")
+b=bytes(1)
+assert(str(b) == "bytes('')")
+b=bytes(-1)
+assert(str(b) == "bytes(\'00\')")
+assert(b.size() == 1)
+
+b=bytes("a")
+assert(str(b) == "bytes('')")
+b=bytes(3.5)
+assert(str(b) == "bytes('')")
+b=bytes([])
+assert(str(b) == "bytes('')")
+
+b=bytes("1122AAaaBBbb")
+assert(str(b) == "bytes('1122AAAABBBB')")
+assert(b.size() == 6)
+b=bytes("112")
+assert(str(b) == "bytes('11')")
+b=bytes("++")
+assert(str(b) == "bytes('00')")
+
+#- add -#
+b=bytes()
+b.add(0x22)
+assert(str(b) == "bytes('22')")
+b.add(0x12345678, 0)
+assert(str(b) == "bytes('22')")
+b.add(0x12345678, 1)
+assert(str(b) == "bytes('2278')")
+b.add(0x12345678, 2)
+assert(str(b) == "bytes('22787856')")
+b.add(0x12345678, 4)
+assert(str(b) == "bytes('2278785678563412')")
+b.add(0x12345678, -1) #- big endian -#
+assert(str(b) == "bytes('227878567856341278')")
+b.add(0x12345678, -2)
+assert(str(b) == "bytes('2278785678563412785678')")
+b.add(0x12345678, -4)
+assert(str(b) == "bytes('227878567856341278567812345678')")
+
+#- get -#
+b=bytes("000102030405")
+assert(b.get(0) == 0)
+assert(b.get(-1) == 0) #- could consider nil as well -#
+assert(b.get(6) == 0) #- could consider nil as well -#
+assert(b.get(1) == 1)
+assert(b.get(5) == 5)
+
+assert(b.get(1,0) == nil)
+assert(b.get(1,1) == 0x01)
+assert(b.get(1,2) == 0x0201)
+assert(b.get(1,4) == 0x04030201)
+assert(b.get(1,-1) == 0x01)
+assert(b.get(1,-2) == 0x0102) #- big endian -#
+assert(b.get(1,-4) == 0x01020304)
+
+#- resize -#
+assert(bytes().size() == 0)
+b=bytes("112233")
+b.resize(2)
+assert(str(b) == "bytes('1122')")
+assert(b.size() == 2)
+b.resize(4)
+assert(str(b) == "bytes('11220000')")
+assert(b.size() == 4)
+b.resize(20)
+assert(str(b) == "bytes('1122000000000000000000000000000000000000')")
+assert(b.size() == 20)
+b.resize(0)
+assert(str(b) == "bytes('')")
+assert(b.size() == 0)
+
+#- clear -#
+b=bytes("aabb")
+b.clear()
+assert(str(b) == "bytes('')")
+
+#- == != -#
+assert(bytes() == bytes())
+assert(bytes("11") == bytes("11"))
+assert(bytes("11") == bytes()..0x11)
+assert(! (bytes("11") == bytes(0x12)) )
+assert(! (bytes("11") == 0x11) )
+assert(! (bytes("11") != bytes("11")) )
+assert(bytes("11") != bytes("1122"))
+assert(bytes("11") != bytes("12"))
+assert(bytes("11") != bytes())
+
+#- + -#
+b1 = bytes("1122")
+b2 = bytes("334455")
+b = b1 + b2
+assert(str(b1) == "bytes('1122')")
+assert(str(b2) == "bytes('334455')")
+assert(str(b) == "bytes('1122334455')")
+b = b2 + b1
+assert(str(b) == "bytes('3344551122')")
+
+#- .. -#
+b1 = bytes("1122")
+b2 = bytes("334455")
+b = b1..b2
+assert(str(b1) == "bytes('1122334455')")
+assert(str(b2) == "bytes('334455')")
+assert(str(b) == "bytes('1122334455')")
+
+#- item -#
+b = bytes("334455")
+assert(b[0] == 0x33)
+assert(b[1] == 0x44)
+assert(b[2] == 0x55)
+
+#- item range -#
+b = bytes("00112233445566778899AABBCCDDEEFF")
+assert(str(b[1..1]) =="bytes('11')")
+assert(str(b[-1..1]) =="bytes('')")
+assert(str(b[0..40]) =="bytes('00112233445566778899AABBCCDDEEFF')")
+assert(str(b[1..0]) =="bytes('')")
+
+#- copy -#
+b=bytes("112233")
+b2=b.copy()
+assert(str(b) =="bytes('112233')")
+assert(str(b2) =="bytes('112233')")
+b2.clear()
+assert(str(b) =="bytes('112233')")
+assert(str(b2) =="bytes('')")
+
+#- setitem -#
+b=bytes("112233")
+assert(str(b) =="bytes('112233')")
+b[1]=0xAA
+assert(str(b) =="bytes('11AA33')")
+b[0]=0xBB
+assert(str(b) =="bytes('BBAA33')")
+b[2]=-1
+assert(str(b) =="bytes('BBAAFF')")
+
+#- resize -#
+b=bytes()
+b.resize(20)
+assert(str(b) =="bytes('0000000000000000000000000000000000000000')")
+b2=b.copy()
+assert(str(b2) =="bytes('0000000000000000000000000000000000000000')")
+
+#- asstring -#
+b=bytes()
+assert(b.asstring() == '')
+b=bytes("334455")
+assert(b.asstring() == '3DU')
+b=bytes("33456502")
+assert(b.asstring() == '3Ee\x02')
+
+#- fromstring -#
+b=bytes()
+b.fromstring("Aa0")
+assert(str(b) =="bytes('416130')")
+b=bytes()
+b.fromstring("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
+assert(str(b) =="bytes('4C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73...')")
+assert(b.tostring(0) =="bytes('4C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742C2073656420646F20656975736D6F642074656D706F7220696E6369646964756E74207574206C61626F726520657420646F6C6F7265206D61676E6120616C697175612E')")
+
+assert(size(bytes('4C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742C2073656420646F20656975736D6F642074656D706F7220696E6369646964756E74207574206C61626F726520657420646F6C6F7265206D61676E6120616C697175612E')) == 123)
+
+#- negative index -#
+b=bytes("112233")
+assert(b[0] == 0x11)
+assert(b[-1] == 0x33) #- last element -#
+assert(b[-3] == 0x11)
+
+#- ranges with negative indices -#
+b = bytes("00112233445566778899AABBCCDDEEFF")
+assert(b[0..-1] == b)
+assert(b[1..-2] == bytes("112233445566778899AABBCCDDEE"))
+assert(b[5..10] == bytes("5566778899AA"))
+assert(b[-10..-5] == bytes("66778899AABB"))
+assert(b[5..-10] == bytes("5566"))
+assert(b[7..-12] == bytes())
diff --git a/lib/libesp32/berry/tests/bytes_b64.be b/lib/libesp32/berry/tests/bytes_b64.be
new file mode 100644
index 000000000..a7f57850e
--- /dev/null
+++ b/lib/libesp32/berry/tests/bytes_b64.be
@@ -0,0 +1,15 @@
+#- base64 encode -#
+b=bytes()
+assert(b.tob64() == '')
+b=bytes('00')
+assert(b.tob64() == 'AA==')
+b=bytes('1122334455')
+assert(b.tob64() == 'ESIzRFU=')
+
+#- base64 decode -#
+b=bytes().fromb64('')
+assert(str(b) == str(bytes('')))
+b=bytes().fromb64('AA==')
+assert(str(b) == str(bytes('00')))
+b=bytes().fromb64('ESIzRFU=')
+assert(str(b) == str(bytes('1122334455')))
diff --git a/lib/libesp32/berry/tests/bytes_fixed.be b/lib/libesp32/berry/tests/bytes_fixed.be
new file mode 100644
index 000000000..e4a64f67f
--- /dev/null
+++ b/lib/libesp32/berry/tests/bytes_fixed.be
@@ -0,0 +1,67 @@
+#- test for bytes with fixed sizes -#
+def assert_attribute_error(f)
+ try
+ f()
+ assert(false, 'unexpected execution flow')
+ except .. as e, m
+ assert(e == 'attribute_error')
+ end
+end
+
+#- simple initialization -#
+b=bytes(-1)
+assert(str(b) == "bytes('00')")
+b=bytes(-5)
+assert(str(b) == "bytes('0000000000')")
+
+#- initialization with hex -#
+b=bytes("11", -1)
+assert(str(b) == "bytes('11')")
+b=bytes("11", -5)
+assert(str(b) == "bytes('1100000000')")
+b=bytes("11223344", -4)
+assert(str(b) == "bytes('11223344')")
+assert(str(bytes(-3).fromb64('RFVm')) == "bytes('445566')")
+
+#- check that get and set still works -#
+b=bytes("11223344",-4)
+assert(b.get(0,2) == 0x2211)
+b.set(0,0x5566,2)
+assert(b.get(0,2) == 0x5566)
+assert(b[0] == 0x66)
+b[0]=12
+assert(b[0] == 12)
+
+#- resize -#
+b=bytes("11223344",-4)
+assert(b.resize(4) == bytes('11223344'))
+
+#- check that changing size raises an exception -#
+b=bytes("112233", -3)
+assert_attribute_error(/-> b.add(1))
+assert_attribute_error(/-> b.add(2,2))
+assert_attribute_error(/-> b.resize(4))
+assert_attribute_error(/-> b.fromstring("aaaaa"))
+assert_attribute_error(/-> b.fromb64('RFVmdw=='))
+assert_attribute_error(/-> b.clear())
+assert_attribute_error(/-> b.bytes())
+
+#- add -#
+b=bytes("112233", -3)
+assert(b+b == bytes("112233112233"))
+
+#- bytes mapped -#
+b1=bytes("112233445566")
+ptr=b1._buffer()
+b2=bytes(ptr, -4)
+assert(b2 == bytes("11223344"))
+b2=bytes(ptr, 4)
+assert(b2 == bytes("11223344"))
+b2=bytes(ptr, 6)
+assert(b2 == bytes("112233445566"))
+assert(b1 == b2)
+
+b2.set(0,0xAABB,2)
+assert(b2 == bytes("BBAA33445566"))
+assert(b1 == bytes("BBAA33445566"))
+assert(b1 == b2)
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/checkspace.be b/lib/libesp32/berry/tests/checkspace.be
new file mode 100644
index 000000000..f4079d952
--- /dev/null
+++ b/lib/libesp32/berry/tests/checkspace.be
@@ -0,0 +1,35 @@
+import os
+
+def strfind(str, char)
+ var len = size(str)
+ for i : 0 .. len - 1
+ if str[i] == char
+ return true
+ end
+ end
+ return false
+end
+
+def checkfile(path)
+ var subname = os.path.splitext(path)[1]
+ if (subname == '.c' || subname == '.h' ||
+ subname == '.cpp' || subname == '.be' || subname == '.json')
+ var f = open(path)
+ assert(!strfind(f.read(), '\t'), 'file \'' + path + '\' has tab character')
+ f.close()
+ end
+end
+
+def findpath(path)
+ var ls = os.listdir(path)
+ for name : ls
+ var fullname = os.path.join(path, name)
+ if os.path.isfile(fullname)
+ checkfile(fullname)
+ elif fullname != '.' && fullname != '..'
+ findpath(fullname)
+ end
+ end
+end
+
+findpath('.')
diff --git a/lib/libesp32/berry/tests/class.be b/lib/libesp32/berry/tests/class.be
new file mode 100644
index 000000000..8c194a175
--- /dev/null
+++ b/lib/libesp32/berry/tests/class.be
@@ -0,0 +1,47 @@
+class Test
+ var maximum
+ def init(maximum)
+ self.maximum = maximum
+ end
+ def iter() # method closure upvalues test
+ var i = -1, maximum = self.maximum
+ return def ()
+ i += 1
+ if i > maximum
+ raise 'stop_iteration'
+ end
+ return i
+ end
+ end
+end
+
+var sum = 0
+for i : Test(10)
+ sum += i
+end
+assert(sum == 55, 'iteraion sum is ' + str(sum) + ' (expected 55).')
+
+#- test case for class instanciated from module member #103 -#
+
+m = module()
+g_i = 0 #- detect side effect from init() -#
+class C def init() g_i += 1 end end
+m.C = C
+
+#- normal invocation -#
+assert(type(C()) == 'instance')
+assert(g_i == 1)
+
+#- invoke from module member -#
+assert(type(m.C()) == 'instance')
+assert(g_i == 2)
+
+class C2 var C1 def init(c) self.C1 = c end end
+m.C2 = C2
+c2 = m.C2(m.C)
+
+assert(c2.C1 == C)
+
+c3 = m.C2(m.C())
+assert(type(c3.C1) == 'instance')
+assert(classname(c3.C1) == 'C')
diff --git a/lib/libesp32/berry/tests/class_const.be b/lib/libesp32/berry/tests/class_const.be
new file mode 100644
index 000000000..e8f4c1920
--- /dev/null
+++ b/lib/libesp32/berry/tests/class_const.be
@@ -0,0 +1,122 @@
+def assert_attribute_error(f)
+ try
+ f()
+ assert(false, 'unexpected execution flow')
+ except .. as e, m
+ assert(e == 'attribute_error')
+ end
+end
+
+class A
+ static a
+ def init() self.b = 2 end
+ def f() end
+ var b
+ static c, s, r
+end
+
+assert(A.a == nil)
+assert(A.c == nil)
+assert(A.s == nil)
+assert_attribute_error(/-> A.b)
+assert_attribute_error(/-> A.d)
+
+a = A()
+assert(a.b == 2)
+assert(a.a == nil)
+assert(a.c == nil)
+
+A.a = 1
+A.c = 3
+A.s = "foo"
+A.r = 3.5
+assert(a.a == 1)
+assert(a.c == 3)
+assert(A.a == 1)
+assert(A.c == 3)
+import gc gc.collect()
+assert(A.s == "foo")
+assert(a.s == "foo")
+assert(A.r == 3.5)
+assert(a.r == 3.5)
+
+#- test valid or invalid methods and members -#
+
+def assert_attribute_error(c)
+ try
+ compile(c)()
+ assert(false, 'unexpected execution flow')
+ except .. as e, m
+ assert(e == 'attribute_error')
+ end
+end
+
+class A
+ var a, g
+ static h
+ def init() self.a = 1 end
+ def f(x, y) return type(self) end
+end
+a=A()
+a.g = def (x, y) return type(x) end
+A.h = def (x, y) return type(x) end
+
+assert(type(a.g) == 'function')
+assert(type(a.h) == 'function')
+
+assert(a.g(1) == 'int')
+assert(a.h(1) == 'int')
+assert(A.h(1) == 'int')
+
+
+class A
+ var a
+ static def g(x, y) return [x,y] end
+ static h = def (x, y) return [x,y] end
+ def init() self.a = 1 end
+ def f(x, y) return type(self) end
+end
+a=A()
+assert(type(a.g) == 'function')
+assert(type(a.h) == 'function')
+assert(type(A.g) == 'function')
+assert(type(A.h) == 'function')
+assert(a.g(1,2) == [1,2])
+assert(a.h(1,2) == [1,2])
+assert(A.g(1,2) == [1,2])
+assert(A.h(1,2) == [1,2])
+a.a = def (x,y) return [x,y] end
+assert(a.a(1,2) == [1,2])
+
+
+#- test static initializers -#
+class A
+ static a = 1, b, c = 3.5, d = 42, e = "foo", f = [1], g = {}
+ var aa,ab
+end
+
+assert(A.a == 1)
+assert(A.b == nil)
+assert(A.c == 3.5)
+assert(A.d == 42)
+assert(A.e == "foo")
+assert(A.f == [1])
+
+a = A()
+assert(a.a == 1)
+assert(a.b == nil)
+assert(a.c == 3.5)
+assert(a.d == 42)
+assert(a.e == "foo")
+assert(a.f == [1])
+assert(a.g == A.g)
+assert(a.aa == nil)
+assert(a.ab == nil)
+
+#- used to fail for subclasses -#
+class A static a=1 end
+class B:A static a=A def f() end static b=1 static c=A end
+assert(A.a == 1)
+assert(B.a == A)
+assert(B.b == 1)
+assert(B.c == A)
diff --git a/lib/libesp32/berry/tests/closure.be b/lib/libesp32/berry/tests/closure.be
new file mode 100644
index 000000000..2474fede9
--- /dev/null
+++ b/lib/libesp32/berry/tests/closure.be
@@ -0,0 +1,13 @@
+#- test for issue #105 -#
+
+l=[]
+def tick()
+ var start=100
+ for i : 1..3
+ l.push(def () return [i, start] end)
+ end
+end
+tick()
+assert(l[0]() == [1, 100])
+assert(l[1]() == [2, 100])
+assert(l[2]() == [3, 100])
diff --git a/lib/libesp32/berry/tests/compiler.be b/lib/libesp32/berry/tests/compiler.be
new file mode 100644
index 000000000..90303734f
--- /dev/null
+++ b/lib/libesp32/berry/tests/compiler.be
@@ -0,0 +1,28 @@
+#- test for issue #117 -#
+
+class A var a end
+a=A()
+a.a = ["foo", "bar"]
+
+s = nil
+def fs(m) s = m end
+
+class B
+ var b, i
+ def nok()
+ fs(self.b.a[self.i]) # wrong behavior
+ end
+ def ok()
+ var i = self.i
+ fs(self.b.a[i]) # works correctly
+ end
+end
+b=B()
+b.i=0
+b.b=a
+
+b.nok()
+assert(s == "foo")
+
+b.ok()
+assert(s == "foo")
diff --git a/lib/libesp32/berry/tests/compound.be b/lib/libesp32/berry/tests/compound.be
new file mode 100644
index 000000000..bda74c9e2
--- /dev/null
+++ b/lib/libesp32/berry/tests/compound.be
@@ -0,0 +1,19 @@
+# test bug in compound statements
+
+a = 0
+assert(a == 0)
+a += 1
+assert(a == 1)
+a += 10/2
+assert(a == 6)
+
+class A var a def init() self.a = 1 end def f(x) self.a+=x/2 end def g(x) self.a = self.a + x/2 end end
+
+a = A()
+assert(a.a == 1)
+a.f(10)
+assert(a.a == 6)
+b=A()
+assert(b.a == 1)
+b.g(10)
+assert(b.a == 6)
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/cond_expr.be b/lib/libesp32/berry/tests/cond_expr.be
new file mode 100644
index 000000000..dc70fd306
--- /dev/null
+++ b/lib/libesp32/berry/tests/cond_expr.be
@@ -0,0 +1,10 @@
+assert("" != 0 ? true : false)
+assert(false || !(true ? false : true) && true)
+var t1 = 8, t2 = false
+if t1 ? 7 + t1 : t2
+ var a = 'good'
+ assert((a == 'good' ? a + '!' : a) == 'good!')
+ assert((a == 'good?' ? a + '!' : a) != 'good!')
+else
+ assert('condition expression test failed')
+end
diff --git a/lib/libesp32/berry/tests/debug.be b/lib/libesp32/berry/tests/debug.be
new file mode 100644
index 000000000..9e732f6c3
--- /dev/null
+++ b/lib/libesp32/berry/tests/debug.be
@@ -0,0 +1,4 @@
+import debug
+
+class A end
+debug.attrdump(A) #- should not crash -#
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/exceptions.be b/lib/libesp32/berry/tests/exceptions.be
new file mode 100644
index 000000000..dc2ad54e4
--- /dev/null
+++ b/lib/libesp32/berry/tests/exceptions.be
@@ -0,0 +1,7 @@
+
+try
+ for k: 0..1 assert({'a':1}.contains('b'), 'failure') end
+except .. as e,m
+ assert(e == "assert_failed")
+ assert(m == "failure")
+end
diff --git a/lib/libesp32/berry/tests/for.be b/lib/libesp32/berry/tests/for.be
new file mode 100644
index 000000000..ec4a910cd
--- /dev/null
+++ b/lib/libesp32/berry/tests/for.be
@@ -0,0 +1,44 @@
+var global
+
+global = 0
+for i : 0 .. 10
+ global += i
+end
+assert(global == 55)
+
+global = 0
+for i : 0 .. 20
+ if i > 10
+ break
+ end
+ global += i
+end
+assert(global == 55)
+
+global = 0
+for i : 0 .. 20
+ if i > 10
+ continue
+ end
+ global += i
+end
+assert(global == 55)
+
+assert(def ()
+ for i : 0 .. 20
+ if i > 10
+ return i
+ end
+ end
+ end() == 11)
+
+# test for "stop_iteration" exception as recurrence
+def for_rec(depth)
+ for i : 0 .. 10
+ if i == 4 && depth < 200
+ for_rec(depth + 1)
+ end
+ end
+end
+
+for_rec(0)
diff --git a/lib/libesp32/berry/tests/function.be b/lib/libesp32/berry/tests/function.be
new file mode 100644
index 000000000..81310408b
--- /dev/null
+++ b/lib/libesp32/berry/tests/function.be
@@ -0,0 +1,12 @@
+# CLOSE opcode test
+var gbl
+def func1()
+ var a = 'func1_a'
+ def func2()
+ return a
+ end
+ gbl = func2
+ return 400000 + 500
+end
+assert(func1() == 400500)
+assert(gbl() == 'func1_a')
diff --git a/lib/libesp32/berry/tests/global.be b/lib/libesp32/berry/tests/global.be
new file mode 100644
index 000000000..cb1b1811d
--- /dev/null
+++ b/lib/libesp32/berry/tests/global.be
@@ -0,0 +1,52 @@
+#- test module global -#
+
+def assert_syntax_error(code)
+ try
+ f = compile(code)
+ assert(false, 'unexpected execution flow')
+ except .. as e, m
+ assert(e == 'syntax_error')
+ end
+end
+def assert_attribute_error(f)
+ try
+ f()
+ assert(false, 'unexpected execution flow')
+ except .. as e, m
+ assert(e == 'attribute_error')
+ end
+end
+def findinlist(l, e)
+ var i
+ for i: 0..size(l)-1
+ if l[i] == e return i end
+ end
+ return nil
+end
+
+#- set the scene -#
+global_a = 1
+global_b = "bb"
+assert(global_a == 1)
+assert(global_b == "bb")
+
+assert_syntax_error("c") #- compilation fails because c does not exist -#
+
+import global
+
+assert(global.global_a == 1)
+assert(global.global_b == "bb")
+
+global.global_c = 3
+#- now compilation against 'c' global -#
+f = compile("return global_c")
+assert(f() == 3)
+
+#- check that access to non-existent global returns an exception -#
+assert_attribute_error(/-> global.d)
+
+#- check the glbal list -#
+assert(findinlist(global(), 'global_a') != nil)
+assert(findinlist(global(), 'global_b') != nil)
+assert(findinlist(global(), 'global_c') != nil)
+assert(findinlist(global(), 'global_d') == nil)
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/introspect.be b/lib/libesp32/berry/tests/introspect.be
new file mode 100644
index 000000000..91531f57a
--- /dev/null
+++ b/lib/libesp32/berry/tests/introspect.be
@@ -0,0 +1,28 @@
+#- introspect -#
+import introspect
+
+#- test for modules -#
+m = module("m")
+m.a = 1
+m.b = def () return "foo" end
+
+assert(introspect.members(m) == ['a', 'b'])
+assert(introspect.get(m, 'a') == 1)
+assert(type(introspect.get(m, 'b')) == 'function')
+
+introspect.set(m, 'a', 2)
+assert(m.a == 2)
+
+#- test for instance -#
+class A var a,b static c=1,d=2 def f() end end
+a=A()
+
+assert(introspect.members(A) == ['a', 'f', 'b', 'c', 'd']) #- class members -#
+assert(introspect.members(a) == ['a', 'f', 'b', 'c', 'd']) #- instance members -#
+
+assert(introspect.get(a, 'c') == 1)
+assert(introspect.get(a, 'd') == 2)
+assert(introspect.get(a, 'a') == nil)
+
+introspect.set(a, 'a', 3)
+assert(a.a == 3)
diff --git a/lib/libesp32/berry/tests/json.be b/lib/libesp32/berry/tests/json.be
new file mode 100644
index 000000000..ee009755b
--- /dev/null
+++ b/lib/libesp32/berry/tests/json.be
@@ -0,0 +1,53 @@
+import json
+
+# load tests
+
+def assert_load(text, value)
+ assert(json.load(text) == value)
+end
+
+def assert_load_failed(text)
+ assert(json.load(text) == nil)
+end
+
+assert_load('null', nil)
+assert_load('true', true)
+assert_load('false', false)
+assert_load('123', 123)
+assert_load('12.3', 12.3)
+assert_load('"abc"', 'abc')
+# strings
+assert_load('"\\"\\\\\\/\\b\\f\\n\\r\\t"', '\"\\/\b\f\n\r\t')
+assert_load('"\\u1234\\u2345\\u04aF\\u003A"', 'ሴ⍅ү:')
+assert_load_failed('"\\u3fr"');
+assert_load_failed('"\\q"');
+assert_load_failed('"123');
+# list
+assert_load('[1, null]', [1, nil])
+assert_load_failed('[x]')
+assert_load_failed('[1, nil]')
+assert_load_failed('[1, null')
+# object
+var o = json.load('{"key": 1}')
+assert(o['key'] == 1 && o.size() == 1)
+assert_load_failed('{"ke: 1}')
+assert_load_failed('{"key": 1x}')
+assert_load_failed('{"key"}')
+assert_load_failed('{"key": 1, }')
+
+# dump tests
+
+def assert_dump(value, text, format)
+ assert(json.dump(value, format) == text)
+end
+
+assert_dump(nil, 'null');
+assert_dump(true, 'true');
+assert_dump(false, 'false');
+assert_dump(1.23, '1.23');
+assert_dump('String', '"String"');
+assert_dump([1, 'x'], '[1,"x"]');
+assert_dump({1: 'x'}, '{"1":"x"}');
+assert_dump([1, 'x'], '[\n 1,\n "x"\n]', 'format');
+assert_dump({1: 'x'}, '{\n "1": "x"\n}', 'format');
+assert_dump({1: 'x', 'k': 'v'}, '{"k":"v","1":"x"}');
diff --git a/lib/libesp32/berry/tests/lexer.be b/lib/libesp32/berry/tests/lexer.be
new file mode 100644
index 000000000..abdb4d903
--- /dev/null
+++ b/lib/libesp32/berry/tests/lexer.be
@@ -0,0 +1,62 @@
+import math
+
+def check(a, b)
+ assert(math.abs(a - b) < 1e-6)
+end
+
+def test_source(src, msg)
+ try
+ compile(src)
+ assert(false, 'unexpected execution flow')
+ except .. as e, m
+ assert(e == 'syntax_error')
+ assert(m == 'string:1: ' + msg)
+ end
+end
+
+#----
+ this is a
+ mult-line comment
+----#
+
+compile('x = 5; 0..x')
+assert('\x5a' == 'Z')
+assert('\132' == 'Z')
+assert('\a\b\f\n\r\t\v\\\'\"\?' == '\x07\x08\x0c\x0a\x0d\x09\x0b\x5c\x27\x22\x3f')
+assert(.45 == 0.45)
+assert(0X10 == 16)
+assert(0x10 == 16)
+assert(0X1A == 26)
+assert(0x1a == 26)
+check(45., 45)
+check(45.e-1, 4.5)
+check(45.E-1, 4.5)
+check(45.1e-1, 4.51)
+check(45.1e2, 4510)
+check(45.e2, 4500)
+check(45.e+2, 4500)
+
+test_source('x = 5; 0...x;', 'unexpected symbol near \'.\'')
+test_source('x = 5; 0...x;', 'unexpected symbol near \'.\'')
+# test_source('45..', 'unexpected symbol near \'EOS\'')
+test_source('0xg', 'invalid hexadecimal number')
+test_source('"\\x5g"', 'invalid hexadecimal number')
+test_source('0x5g', 'malformed number')
+test_source('"\\779"', 'invalid octal number')
+test_source('"\n', 'unfinished string')
+
+var malformed_numbers = [
+ '45f',
+ '45.f',
+ '45.ef',
+ '45.e-f',
+ '45.e-1f',
+ '45.e-1.',
+ '45.5.',
+ '0x45.',
+ '0x45j'
+]
+
+for i : malformed_numbers
+ test_source(i, 'malformed number')
+end
diff --git a/lib/libesp32/berry/tests/lexergc.be b/lib/libesp32/berry/tests/lexergc.be
new file mode 100644
index 000000000..155800b95
--- /dev/null
+++ b/lib/libesp32/berry/tests/lexergc.be
@@ -0,0 +1,12 @@
+#- check the gc bug fixed in #110 -#
+#- Berry must be compiled with `#define BE_USE_DEBUG_GC 1` -#
+#- for the initial bug to happen -#
+
+code = "()" #- this code triggers a lexer exception -#
+
+try
+ compile(code)
+ assert(false) #- this should never be reached -#
+except .. as e, m
+ assert(m == "string:1: unexpected symbol near ')'")
+end
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/list.be b/lib/libesp32/berry/tests/list.be
new file mode 100644
index 000000000..a2da2ca47
--- /dev/null
+++ b/lib/libesp32/berry/tests/list.be
@@ -0,0 +1,140 @@
+l = [1, 2, 3, 4, 5]
+assert(l[0] == 1)
+assert(l[1] == 2)
+assert(l[2] == 3)
+assert(l[3] == 4)
+assert(l[4] == 5)
+assert(str(l) == '[1, 2, 3, 4, 5]')
+
+it = l.iter()
+assert(it() == 1)
+assert(it() == 2)
+assert(it() == 3)
+assert(it() == 4)
+assert(it() == 5)
+
+l.insert(0, 10)
+assert(l[0] == 10)
+assert(l.size() == 6)
+l.remove(0)
+assert(l.size() == 5)
+assert(l[0] == 1)
+l.setitem(0, 42)
+assert(l[0] == 42)
+assert(l.item(2) == 3)
+l.resize(10)
+assert(l.size() == 10)
+assert(l.tostring() == '[42, 2, 3, 4, 5, nil, nil, nil, nil, nil]')
+
+assert(([] == []) == true)
+assert(([] != []) == false)
+assert(([1] == [1]) == true)
+assert(([1] != [1]) == false)
+assert(([1] == [0]) == false)
+assert(([1] != [0]) == true)
+assert(([1, 2, 3] == [1, 2, 3]) == true)
+assert(([1, 2, 3] != [1, 2, 3]) == false)
+assert(([1, 2, 3] == [1, 2, 4]) == false)
+assert(([1, 2, 3] != [1, 2, 4]) == true)
+assert(([1, 2, ['w']] == [1, 2, ['w']]) == true)
+assert(([1, 2, ['w']] != [1, 2, ['w']]) == false)
+assert(([1, 2, ['w']] == [1, 2, ['z']]) == false)
+assert(([1, 2, ['w']] != [1, 2, ['z']]) == true)
+assert(([1, 2, ['w']] == [1, 2, []]) == false)
+assert(([1, 2, ['w']] != [1, 2, []]) == true)
+
+var l = [0, 1, 2, 3]
+assert(l[-1] == 3)
+assert(l[-2] == 2)
+var t = l.copy()
+l.insert(-2, 4)
+assert(t == [0, 1, 2, 3] && t != l)
+assert(l == [0, 1, 4, 2, 3])
+l.remove(-2)
+assert(l == [0, 1, 4, 3])
+assert(l.reverse() == [3, 4, 1, 0])
+assert(l + [5, 6] == [3, 4, 1, 0, 5, 6])
+l = [0]
+assert(l .. '3' == [0, '3'])
+l.push(1)
+assert(l == [0, '3', 1])
+assert(l.concat() == '031')
+l.pop()
+assert(l == [0, '3'])
+l.pop(0)
+assert(l == ['3'])
+
+l1 = [0, 1]
+l2 = [2, 3]
+assert(l1+l2==[0, 1, 2, 3])
+assert(l1 == [0, 1])
+assert(l2 == [2, 3])
+assert(l1+[2] == [0, 1, 2])
+assert([-1]+l1 == [-1, 0, 1])
+assert(l1 == [0, 1])
+
+#- find -#
+#- if no argument return nil -#
+assert([].find() == nil)
+assert([1,2].find() == nil)
+assert([1,1,nil,2].find() == nil)
+
+#- nil if not found -#
+assert([1,2].find(3) == nil)
+assert([1,2].find(true) == nil)
+assert([1,2].find('foo') == nil)
+
+#- if found -#
+assert([1,2,3,4].find(1) == 0)
+assert([1,2,3,4].find(2) == 1)
+assert([1,2,3,4].find(3) == 2)
+assert([1,2,3,4].find(4) == 3)
+assert([1,2,"foo",4].find('foo') == 2)
+
+#- if multiple occurrences -#
+assert([1,1,2,2].find(1) == 0)
+assert([1,1,2,2].find(2) == 2)
+
+#- look for nil -#
+assert([1,1,nil,2].find(nil) == 2)
+
+#- sub-structure -#
+assert([1,[1,nil,2],3,[3]].find(3) == 2)
+assert([1,[1,nil,2],3,[3]].find([3]) == 3)
+assert([1,[1,nil,2],3,[3]].find([1,nil,2]) == 1)
+
+#- keys() -#
+assert(str(["a",'b',0].keys()) == "(0..2)")
+assert(str([nil].keys()) == "(0..0)")
+assert(str([].keys()) == "(0..-1)")
+
+#- concat with delimiter -#
+assert(["foo","bar",0].concat() == "foobar0")
+assert([1,2,3].concat() == "123")
+assert(["foo","bar",0].concat('') == "foobar0")
+assert([1,2,3].concat('') == "123")
+
+assert(["foo","bar",0].concat('-') == "foo-bar-0")
+assert([].concat('<->') == "")
+assert(["foo"].concat('<->') == "foo")
+assert(["foo","bar",0].concat('<->') == "foo<->bar<->0")
+
+assert(["","foo","bar",0].concat('<->') == "<->foo<->bar<->0")
+assert(["","",1,"bar",0].concat('<->') == "<-><->1<->bar<->0")
+assert(["","",1,"bar",0].concat('') == "1bar0")
+
+assert([1,2,3].concat('-') == "1-2-3")
+assert([1,"2",3].concat('-') == "1-2-3")
+
+assert(["",2,3].concat('-') == "-2-3")
+
+#- negative indices -#
+assert([1,2,3,4][0] == 1)
+assert([1,2,3,4][-1] == 4)
+assert([1,2,3,4][-2] == 3)
+
+assert([1,2,3,4][1..10] == [2,3,4])
+assert([1,2,3,4][1..-1] == [2,3,4])
+assert([1,2,3,4][1..-2] == [2,3])
+assert([1,2,3,4][3..2] == [])
+assert([1,2,3,4][2..-3] == [])
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/member_indirect.be b/lib/libesp32/berry/tests/member_indirect.be
new file mode 100644
index 000000000..046521acd
--- /dev/null
+++ b/lib/libesp32/berry/tests/member_indirect.be
@@ -0,0 +1,75 @@
+#- new syntax for indirect members -#
+
+#- module accessor -#
+s_pi = 'pi'
+
+import math
+assert(math.('pi') == math.pi)
+assert(math.(s_pi) == math.pi)
+
+#- module writer -#
+m = module("m")
+
+m.('aa') = 1
+m.('a' + 'b') = 2
+s_ac = 'ac'
+m.(s_ac) = 3
+assert(m.aa == 1)
+assert(m.ab == 2)
+assert(m.ac == 3)
+assert(m.('a'+'a') == 1)
+
+#- class accessor -#
+class A1
+ static a = 1, b = 2
+ static s = "foo"
+ def f() return 0 end
+end
+assert(A1.a == 1)
+assert(A1.b == 2)
+assert(A1.s == "foo")
+assert(type(A1.f) == 'function')
+
+#- instance accessor -#
+class A2
+ var a, b
+ static s_a = 'a'
+ def init(a,b)
+ self.(self.('s_a')) = a
+ self.('b') = b
+ end
+ def f(x)
+ return x+1
+ end
+ def g(a,b)
+ return A2(a,b)
+ end
+end
+a = A2(1,2)
+
+#- reading members -#
+assert(a.a == 1)
+assert(a.b == 2)
+assert(a.(A2.s_a) == 1)
+assert(a.('b') == 2)
+
+#- writing members -#
+a.('a') = 10
+a.('bb'[0]) = 11
+assert(a.a == 10)
+assert(a.b == 11)
+
+#- calling methods -#
+assert(a.f(1) == 2)
+assert(a.('f')(2) == 3)
+
+#- mulit-level -#
+assert(a.('g')(3,4).('a') == 3)
+a.('a') = a.g(3,4)
+assert(a.a.b == 4)
+assert(a.('a').b == 4)
+assert(a.('a').('b') == 4)
+assert(a.a.('b') == 4)
+
+a.('a').('b') += 1
+assert(a.a.b == 5)
diff --git a/lib/libesp32/berry/tests/os.be b/lib/libesp32/berry/tests/os.be
new file mode 100644
index 000000000..37811bef1
--- /dev/null
+++ b/lib/libesp32/berry/tests/os.be
@@ -0,0 +1,51 @@
+import os
+
+# os.path.join test
+assert(os.path.join('') == '')
+assert(os.path.join('abc', 'de') == 'abc/de')
+assert(os.path.join('abc', '/de') == '/de')
+assert(os.path.join('a', 'de') == 'a/de')
+assert(os.path.join('abc/', 'de') == 'abc/de')
+assert(os.path.join('abc', 'de', '') == 'abc/de/')
+assert(os.path.join('abc', '', '', 'de') == 'abc/de')
+assert(os.path.join('abc', '/de', 'fghij') == '/de/fghij')
+assert(os.path.join('abc', 'xyz', '/de', 'fghij') == '/de/fghij')
+
+# os.path.split test
+def split(str, list)
+ var res = os.path.split(str)
+ assert(res[0] == list[0] && res[1] == list[1],
+ 'unexpected results: ' .. res .. ', reference value: ' .. list)
+end
+
+split('/', ['/', ''])
+split('//', ['//', ''])
+split('///', ['///', ''])
+split('a/', ['a', ''])
+split('a//', ['a', ''])
+split('a/b/c', ['a/b', 'c'])
+split('a/b/', ['a/b', ''])
+split('a//b//', ['a//b', ''])
+split('a/../b', ['a/..', 'b'])
+split('abcd////ef/////', ['abcd////ef', ''])
+split('abcd////ef', ['abcd', 'ef'])
+
+# os.path.splitext test
+def splitext(str, list)
+ var res = os.path.splitext(str)
+ assert(res[0] == list[0] && res[1] == list[1],
+ 'unexpected results: ' .. res .. ', reference value: ' .. list)
+end
+
+splitext('a.b', ['a', '.b'])
+splitext('a..b', ['a.', '.b'])
+splitext('/a..b', ['/a.', '.b'])
+splitext('/.b', ['/.b', ''])
+splitext('/..b', ['/..b', ''])
+splitext('..b', ['..b', ''])
+splitext('...b', ['...b', ''])
+splitext('.b', ['.b', ''])
+splitext('ac..b', ['ac.', '.b'])
+splitext('ac.b', ['ac', '.b'])
+splitext('ac/.b', ['ac/.b', ''])
+splitext('ac/..b', ['ac/..b', ''])
diff --git a/lib/libesp32/berry/tests/overload.be b/lib/libesp32/berry/tests/overload.be
new file mode 100644
index 000000000..a9e72081b
--- /dev/null
+++ b/lib/libesp32/berry/tests/overload.be
@@ -0,0 +1,14 @@
+class test
+ def init()
+ self._a = 123
+ end
+ def +()
+ return self._a
+ end
+ def ()()
+ return self._a
+ end
+ var _a
+end
+
+print(test() + test())
diff --git a/lib/libesp32/berry/tests/relop.be b/lib/libesp32/berry/tests/relop.be
new file mode 100644
index 000000000..a9a9805f1
--- /dev/null
+++ b/lib/libesp32/berry/tests/relop.be
@@ -0,0 +1,40 @@
+def assert_true(status)
+ assert(status == true, 'assert(true) failed!')
+end
+
+def assert_false(status)
+ assert(status == false, 'assert(false) failed!')
+end
+
+assert_true(0 == 0)
+assert_false(0 != 0)
+assert_true(0 != 1)
+assert_false(0 == 1)
+
+
+assert_true(0.0 == 0)
+assert_false(0.0 != 0)
+assert_true(0.0 != 1.0)
+assert_false(0.0 == 1.0)
+
+assert_true(nil == nil)
+assert_false(nil != nil)
+assert_true(true != nil)
+assert_false(true == nil)
+assert_true(nil != false)
+assert_false(nil == false)
+
+assert_true(list == list)
+assert_false(list == map)
+
+assert_true([] == [])
+assert_true([true] == [true])
+assert_true([[]] == [[]])
+assert_false([[]] != [[]])
+assert_false([0] == [])
+assert_false([] != [])
+assert_true([] != nil)
+assert_false([] == nil)
+
+assert_true({} != nil)
+assert_false({} == nil)
diff --git a/lib/libesp32/berry/tests/string.be b/lib/libesp32/berry/tests/string.be
new file mode 100644
index 000000000..479af1cb4
--- /dev/null
+++ b/lib/libesp32/berry/tests/string.be
@@ -0,0 +1,41 @@
+import string as s
+
+assert(s.find('012345', '23') == 2)
+assert(s.find('012345', '23', 1) == 2)
+assert(s.find('012345', '23', 1, 3) == -1)
+assert(s.find('012345', '23', 2, 4) == 2)
+assert(s.find('012345', '23', 3) == -1)
+
+assert(s.find('012345', '') == 0)
+assert(s.find('012345', '', 0, 0) == 0)
+assert(s.find('012345', '', 1) == 1)
+assert(s.find('012345', '', 1, 1) == 1)
+assert(s.find('012345', '', 1, 0) == -1)
+assert(s.find('012345', '', 6) == 6)
+assert(s.find('012345', '', 7) == -1)
+
+assert(s.count('012345', '') == 7)
+assert(s.count('012345', '', 2) == 5)
+assert(s.count('012345', '', 6) == 1)
+
+assert(s.count('121314', '1') == 3)
+assert(s.count('121314', '1', 1) == 2)
+assert(s.count('121314', '1', 2) == 2)
+assert(s.count('121314', '1', 1, 2) == 0)
+assert(s.count('121314', '1', 1, 3) == 1)
+
+assert(s.split('a b c d e f', '1') == ['a b c d e f'])
+assert(s.split('a b c d e f', ' ') == ['a', 'b', 'c', 'd', 'e', 'f'])
+assert(s.split('a b c d e f', ' ', 2) == ['a', 'b', 'c d e f'])
+assert(s.split('a b c d e f', '') == ['a b c d e f'])
+
+assert(s.format("%%") == "%")
+assert(s.format("%i%%", 12) == "12%")
+assert(s.format("%i%%%i", 12, 13) == "12%13")
+assert(s.format("%s%%", "foo") == "foo%")
+assert(s.format("%.1f%%", 3.5) == "3.5%")
+
+s="azerty"
+assert(s[1..2] == "ze")
+assert(s[1..] == "zerty")
+assert(s[1..-1] == "zerty")
diff --git a/lib/libesp32/berry/tests/subobject.be b/lib/libesp32/berry/tests/subobject.be
new file mode 100644
index 000000000..010e8af29
--- /dev/null
+++ b/lib/libesp32/berry/tests/subobject.be
@@ -0,0 +1,29 @@
+class mylist : classof([]) end
+
+assert(issubclass(mylist, list) == true)
+assert(issubclass(mylist, []) == true)
+assert(issubclass(mylist(), list) == false)
+assert(issubclass(mylist(), []) == false)
+
+assert(isinstance(mylist, list) == false)
+assert(isinstance(mylist, []) == false)
+assert(isinstance(mylist(), list) == true)
+assert(isinstance(mylist(), []) == true)
+
+assert(issubclass(list, list) == true)
+assert(issubclass(list, []) == true)
+assert(issubclass(list(), list) == false)
+assert(issubclass(list(), []) == false)
+
+assert(isinstance(list, list) == false)
+assert(isinstance(list, []) == false)
+assert(isinstance(list(), list) == true)
+assert(isinstance(list(), []) == true)
+
+assert(issubclass(list, list) == true)
+assert(issubclass(list, []) == true)
+assert(issubclass(list(), list) == false)
+assert(issubclass(list(), []) == false)
+
+assert(issubclass(list, mylist) == false)
+assert(isinstance([], mylist) == false)
diff --git a/lib/libesp32/berry/tests/suffix.be b/lib/libesp32/berry/tests/suffix.be
new file mode 100644
index 000000000..11f429aa7
--- /dev/null
+++ b/lib/libesp32/berry/tests/suffix.be
@@ -0,0 +1,28 @@
+var keys = [ 'key1', 'key2', 'key3', 'key4' ]
+var pairs = {
+ keys[0]: 'value1',
+ keys[1]: 'value2',
+ keys[2]: 'value3',
+ keys[3]: 'value4'
+}
+
+for i : 0 .. keys.size() - 1
+ assert(pairs[keys[i]] == 'value' .. i + 1)
+end
+
+#- test cases related to #101 -#
+class C var l end
+c=C()
+c.l=[0,1,2]
+
+def t_101_nok_1() return c.l[0..1] end
+def t_101_ok_1() var l2 = c.l return l2[0..1] end
+
+t_i = 0
+def t_101_nok_2() return c.l[t_i] end
+def t_101_ok_2() return c.l[0] end
+
+assert(t_101_nok_1() == [0, 1])
+assert(t_101_ok_1() == [0, 1])
+assert(t_101_nok_2() == 0)
+assert(t_101_ok_2() == 0)
diff --git a/lib/libesp32/berry/tests/super_auto.be b/lib/libesp32/berry/tests/super_auto.be
new file mode 100644
index 000000000..8d7ede85f
--- /dev/null
+++ b/lib/libesp32/berry/tests/super_auto.be
@@ -0,0 +1,132 @@
+#- test for new auto class inference of super() -#
+
+#- test that we can call init() even if it's not defined -#
+class Z end
+z=Z()
+assert(z.init != nil)
+z.init() #- should do nothing -#
+
+#- check the old way still works -#
+class A1
+ var a
+ def init(a)
+ self.a = a
+ end
+end
+class B1:A1
+ var b
+ def init(a,b)
+ super(self,A1).init(a)
+ self.b = b
+ end
+end
+class C1:B1
+ var c
+ def init(a,b,c)
+ super(self,B1).init(a,b)
+ self.c = c
+ end
+end
+#- -#
+c1=C1(1,2,3)
+assert(c1.a == 1)
+assert(c1.b == 2)
+assert(c1.c == 3)
+
+#- test simple behavior -#
+class A0 var a end
+class B0:A0 var b end
+class C0:B0 end
+c0=C0()
+assert(classof(c0) == C0)
+assert(classof(super(c0)) == B0)
+assert(classof(super(super(c0))) == A0)
+assert(super(super(super(c0))) == nil)
+
+assert(super(C0) == B0)
+assert(super(super(C0)) == A0)
+assert(super(super(super(C0))) == nil)
+
+assert(classof(super(c0,B0)) == B0)
+assert(classof(super(c0,A0)) == A0)
+
+#- test auto inference of target superclass -#
+class A
+ var a
+ def init(a)
+ self.a = a
+ end
+end
+class B:A
+ var b
+ def init(a,b)
+ super(self).init(a)
+ self.b = b
+ end
+end
+class C:B
+ var c
+ def init(a,b,c)
+ super(self).init(a,b)
+ self.c = c
+ end
+end
+#- -#
+c=C(1,2,3)
+
+assert(c.a == 1)
+assert(c.b == 2)
+assert(c.c == 3)class A
+end
+class B:A
+ var b
+ def init(a,b) super(self).init(a) self.b = b end
+end
+class C:B
+ var c
+ def init(a,b,c) super(self).init(a,b) self.c = c end
+end
+c=C(1,2,3)
+
+#- variant if A2 does not have an init() method, still works -#
+class A2
+ static a=1
+end
+class B2:A2
+ var b
+ def init(a,b) super(self).init(a) self.b = b end
+end
+class C2:B2
+ var c
+ def init(a,b,c) super(self).init(a,b) self.c = c end
+end
+#- -#
+c2=C2(1,2,3)
+assert(c2.a == 1)
+assert(c2.b == 2)
+assert(c2.c == 3)
+
+#- difference in behavior whether the second arg is provided or not -#
+class A3
+end
+class B3:A3
+ def b1()
+ return super(self)
+ end
+ def b2(c)
+ return super(self, c)
+ end
+end
+class C3:B3
+end
+#- -#
+b3=B3()
+c3=C3()
+assert(classof(c3.b1()) == A3)
+assert(classof(b3.b1()) == A3)
+assert(classof(c3.b2(B3)) == B3)
+assert(classof(c3.b2(A3)) == A3)
+
+assert(classof(c3.b2(nil)) == B3) #- testing super(self,nil) in B3::b2() -#
+
+assert(c3.b2(C3) == nil) #- if specifying the current class, can't find any relevant class in supers -#
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/super_leveled.be b/lib/libesp32/berry/tests/super_leveled.be
new file mode 100644
index 000000000..e88914941
--- /dev/null
+++ b/lib/libesp32/berry/tests/super_leveled.be
@@ -0,0 +1,43 @@
+#- test for leveled use of super() -#
+
+#- setup -#
+class A def r() return 'a' end def f() return self.r() end end
+class B:A def r() return 'b' end def f() return super(self,A).f() + 'b' end end
+class C:B def r() return 'c' end def f() return super(self,B).f() + 'c' end end
+a=A()
+b=B()
+c=C()
+
+#- regular behavior -#
+assert(classname(a) == 'A')
+assert(classname(b) == 'B')
+assert(classname(c) == 'C')
+assert(a.r() == 'a')
+assert(b.r() == 'b')
+assert(c.r() == 'c')
+assert(a.f() == 'a')
+
+#- standard use of super() -#
+assert(super(a) == nil)
+assert(super(A) == nil)
+assert(classname(super(B)) == 'A')
+assert(classname(super(C)) == 'B')
+assert(classname(super(super(C))) == 'A')
+assert(super(super(super(C))) == nil)
+
+#- super() levele -#
+assert(super(a,A) == nil)
+assert(super(b,B) == nil)
+assert(super(c,C) == nil)
+assert(classname(super(c,B)) == 'B')
+assert(classname(super(c,A)) == 'A')
+assert(super(c,map) == nil) #- not a parent class -#
+
+#- wrapping it all -#
+assert(a.f() == 'a')
+assert(b.f() == 'bb')
+
+#- the last one is tricky:
+ c.f() -> calls f() in class B -> calls f() in class A -> calls r() of overall class hence C
+-#
+assert(c.f() == 'cbc')
\ No newline at end of file
diff --git a/lib/libesp32/berry/tests/vararg.be b/lib/libesp32/berry/tests/vararg.be
new file mode 100644
index 000000000..7dd3541d3
--- /dev/null
+++ b/lib/libesp32/berry/tests/vararg.be
@@ -0,0 +1,14 @@
+#- vararg -#
+def f(a,*b) return b end
+
+assert(f() == [])
+assert(f(1) == [])
+assert(f(1,2) == [2])
+assert(f(1,2,3) == [2, 3])
+
+def g(*a) return a end
+
+assert(g() == [])
+assert(g("foo") == ["foo"])
+assert(g("foo", nil) == ["foo", nil])
+assert(g("foo", nil, 2) == ["foo", nil, 2])
diff --git a/lib/libesp32/berry/tests/virtual_methods.be b/lib/libesp32/berry/tests/virtual_methods.be
new file mode 100644
index 000000000..514fb3cc2
--- /dev/null
+++ b/lib/libesp32/berry/tests/virtual_methods.be
@@ -0,0 +1,66 @@
+#- basic initialization -#
+
+def assert_attribute_error(f)
+ try
+ f()
+ assert(false, 'unexpected execution flow')
+ except .. as e, m
+ assert(e == 'attribute_error')
+ end
+end
+
+class T1
+ var a, b
+ def init()
+ self.a = 1
+ self.b = 2
+ end
+ def f() return true end
+ def g() return false end
+end
+t = T1()
+
+#- warm up -#
+assert(t.a == 1)
+assert(t.b == 2)
+assert(t.f() == true)
+assert(t.g() == false)
+
+#- test normal errors when method does not exist -#
+assert_attribute_error(/-> t.h())
+assert_attribute_error(/-> t.c)
+
+class T2 : T1
+ def member(n)
+ if (n == 'f1') return / n -> n end
+ if (n == 'f2') return /-> 4 end
+ if (n == 'a1') return 10 end
+ end
+end
+t2 = T2()
+
+#- test non-regression -#
+assert(t2.a == 1)
+assert(t2.b == 2)
+assert(t2.f() == true)
+assert(t2.g() == false)
+assert_attribute_error(/-> t2.h())
+
+#- try virtual methods -#
+assert(t2.f1() == t2)
+assert(t2.f2() == 4)
+assert(t2.a1 == 10)
+
+#- module -#
+m = module("m")
+
+m.a = 1
+assert(m.a == 1)
+assert_attribute_error(/-> m.b)
+
+m.member = def(n)
+ if n == "b" return 2 end
+end
+
+assert(m.b == 2)
+assert_attribute_error(/-> m.c)
diff --git a/lib/libesp32/berry/tests/virtual_methods2.be b/lib/libesp32/berry/tests/virtual_methods2.be
new file mode 100644
index 000000000..9bb38a9c5
--- /dev/null
+++ b/lib/libesp32/berry/tests/virtual_methods2.be
@@ -0,0 +1,28 @@
+#- virtual attributes -#
+class Ta
+ var a, b, virtual_c
+ def init()
+ self.a = 1
+ self.b = 2
+ self.virtual_c = 3
+ end
+ def member(n)
+ if n == 'c' return self.virtual_c end
+ return nil
+ end
+ def setmember(n, v)
+ if n == 'c' self.virtual_c = v return true end
+ return false
+ end
+end
+ta = Ta()
+
+assert(ta.a == 1)
+assert(ta.b == 2)
+assert(ta.c == 3)
+ta.a = 10
+assert(ta.a == 10)
+assert(ta.c == 3)
+ta.c = 30
+assert(ta.c == 30)
+assert(ta.virtual_c == 30)
diff --git a/lib/libesp32/berry/tools/coc/.gitignore b/lib/libesp32/berry/tools/coc/.gitignore
new file mode 100644
index 000000000..be1fbe796
--- /dev/null
+++ b/lib/libesp32/berry/tools/coc/.gitignore
@@ -0,0 +1 @@
+coc
diff --git a/lib/libesp32/berry/tools/coc/Makefile b/lib/libesp32/berry/tools/coc/Makefile
new file mode 100644
index 000000000..773994b3c
--- /dev/null
+++ b/lib/libesp32/berry/tools/coc/Makefile
@@ -0,0 +1,26 @@
+TARGET = coc
+CXXFLAGS = -std=c++11 -O2
+CXX = g++
+
+OBJS = coc_string.o \
+ hash_map.o \
+ macro_table.o \
+ main.o \
+ block_builder.o \
+ str_build.o \
+ coc_parser.o
+
+ifeq ($(OS), Windows_NT) # Windows
+ TARGET := $(TARGET).exe
+endif
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(Q) $(CXX) $(OBJS) -o $@
+
+$(OBJS): %.o: %.cpp
+ $(Q) $(CXX) $(CXXFLAGS) -c $< -o $@
+
+clean:
+ $(Q) $(RM) $(OBJS)
diff --git a/lib/libesp32/berry/tools/coc/REEADME.md b/lib/libesp32/berry/tools/coc/REEADME.md
new file mode 100644
index 000000000..329c66d46
--- /dev/null
+++ b/lib/libesp32/berry/tools/coc/REEADME.md
@@ -0,0 +1,3 @@
+# The Constant Object Compiler (coc)
+
+The constant object compiler (coc) is a C preprocessor that generates the corresponding C99 code based on the constant object declaration block.
diff --git a/lib/libesp32/berry/tools/coc/block_builder.cpp b/lib/libesp32/berry/tools/coc/block_builder.cpp
new file mode 100755
index 000000000..bd76cdbf5
--- /dev/null
+++ b/lib/libesp32/berry/tools/coc/block_builder.cpp
@@ -0,0 +1,197 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#include "block_builder.h"
+#include "hash_map.h"
+#include "macro_table.h"
+#include "object_block.h"
+#include
+#include
+
+static bool depend(const object_block *object, const macro_table *macro)
+{
+ auto it = object->attr.find("depend");
+ if (it != object->attr.end()) {
+ return macro->query(it->second);
+ }
+ return true;
+}
+
+block_builder::block_builder(const object_block *object, const macro_table *macro)
+{
+ m_block.name = object->name;
+ if (depend(object, macro)) {
+ m_block.type = object->type;
+ m_block.attr = object->attr;
+
+ auto it = object->attr.find("name");
+ if (it != object->attr.end()) {
+ m_strtab.push_back(it->second);
+ }
+
+ for (auto key : object->data_ordered) {
+ auto second = object->data.at(key);
+ if (second.depend.empty() || macro->query(second.depend)) {
+ m_block.data[key] = second.value;
+ m_strtab.push_back(key);
+ m_block.data_ordered.push_back(key); /* record insertion order */
+ }
+ }
+ }
+}
+
+std::string block_builder::block_tostring(const block &block)
+{
+ std::ostringstream ostr;
+ if (block.type == "map") {
+ ostr << map_tostring(block, block.name);
+ } else if (block.type == "class") {
+ ostr << class_tostring(block);
+ } else if (block.type == "vartab") {
+ ostr << vartab_tostring(block);
+ } else if (block.type == "module") {
+ ostr << module_tostring(block);
+ }
+ return ostr.str();
+}
+
+std::string block_builder::class_tostring(const block &block)
+{
+ bool empty_map = block.data.empty();
+ std::ostringstream ostr;
+ hash_map map(block.data);
+ std::string map_name(block.name + "_map");
+
+ if (!empty_map) {
+ ostr << map_tostring(block, map_name, true) << std::endl;
+ }
+ ostr << scope(block) << " be_define_const_class(\n "
+ << block.name << ",\n "
+ << map.var_count() << ",\n "
+ << super(block) << ",\n "
+ << name(block) << "\n"
+ ");" << std::endl;
+ return ostr.str();
+}
+
+std::string block_builder::map_tostring(const block &block, const std::string &name, bool local)
+{
+ std::ostringstream ostr;
+ hash_map map(block.data);
+
+ hash_map::entry_table list = map.entry_list();
+ ostr << "static be_define_const_map_slots(" << name << ") {\n";
+ for (auto it : list) {
+ ostr << " { be_const_key(" << it.key << ", "
+ << it.next << "), " << it.value << " }," << std::endl;
+ }
+ ostr << "};\n\n";
+
+ ostr << (local ? "static" : scope(block))
+ << " be_define_const_map(\n "
+ << name << ",\n "
+ << list.size() << "\n"
+ ");" << std::endl;
+ return ostr.str();
+}
+
+std::string block_builder::vartab_tostring(const block &block)
+{
+ std::ostringstream ostr;
+ struct block idxblk;
+ std::vector varvec;
+ int index = 0;
+
+ idxblk = block;
+ idxblk.data.clear();
+ for (auto key : block.data_ordered) {
+ varvec.push_back(block.data.at(key));
+ idxblk.data[key] = "int(" + std::to_string(index++) + ")";
+ }
+
+ ostr << map_tostring(idxblk, block.name + "_map", true) << std::endl;
+ ostr << "static const bvalue __vlist_array[] = {\n";
+ for (auto it : varvec) {
+ ostr << " be_const_" << it << "," << std::endl;
+ }
+ ostr << "};\n\n";
+
+ ostr << "static be_define_const_vector(\n "
+ << block.name << "_vector,\n "
+ "__vlist_array,\n "
+ << varvec.size() << "\n"
+ ");" << std::endl;
+ return ostr.str();
+}
+
+std::string block_builder::module_tostring(const block &block)
+{
+ std::ostringstream ostr;
+ std::string name("m_lib" + block.name);
+ std::string map_name(name + "_map");
+
+ ostr << map_tostring(block, map_name, true) << std::endl
+ << "static be_define_const_module(\n "
+ << name << ",\n "
+ "\"" << block.name << "\"\n"
+ ");" << std::endl;
+ std::string scp = scope(block);
+ if (scp != "static") { /* extern */
+ ostr << "\n" << scp
+ << " be_define_const_native_module("
+ << block.name << ");" << std::endl;
+ }
+ return ostr.str();
+}
+
+std::string block_builder::scope(const block &block)
+{
+ auto it = block.attr.find("scope");
+ return it != block.attr.end() && it->second == "local" ?
+ "static" : "BE_EXPORT_VARIABLE";
+}
+
+std::string block_builder::super(const block &block)
+{
+ auto it = block.attr.find("super");
+ return it == block.attr.end() ? "NULL" : "(bclass *)&" + it->second;
+}
+
+std::string block_builder::name(const block &block)
+{
+ auto it = block.attr.find("name");
+ return it == block.attr.end() ? block.name : it->second;
+}
+
+void block_builder::writefile(const std::string &filename, const std::string &text)
+{
+ std::string pathname(filename);
+ std::string otext("#include \"be_constobj.h\"\n\n" + text);
+
+ std::ostringstream buf;
+ std::ifstream fin(pathname);
+ buf << fin.rdbuf();
+ if (buf.str() != otext) {
+ std::ofstream fout;
+ fout.open(pathname, std::ios::out);
+ fout << otext;
+ fout.close();
+ }
+}
+
+void block_builder::dumpfile(const std::string &path)
+{
+ std::string s = block_tostring(m_block);
+ auto it = m_block.attr.find("file");
+ std::string &name = it != m_block.attr.end() ? it->second : m_block.name;
+ writefile(path + "/be_fixed_" + name + ".h", s);
+}
+
+const std::vector& block_builder::strtab() const
+{
+ return m_strtab;
+}
diff --git a/lib/libesp32/berry/tools/coc/block_builder.h b/lib/libesp32/berry/tools/coc/block_builder.h
new file mode 100755
index 000000000..2811419eb
--- /dev/null
+++ b/lib/libesp32/berry/tools/coc/block_builder.h
@@ -0,0 +1,49 @@
+/********************************************************************
+** Copyright (c) 2018-2020 Guan Wenliang
+** This file is part of the Berry default interpreter.
+** skiars@qq.com, https://github.com/Skiars/berry
+** See Copyright Notice in the LICENSE file or at
+** https://github.com/Skiars/berry/blob/master/LICENSE
+********************************************************************/
+#ifndef __BLOCK_BUILDER_H
+#define __BLOCK_BUILDER_H
+
+#include