From 2220b2d3e339e6784abd205f50936e2d59926ad2 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 13 Feb 2021 12:01:45 +0100 Subject: [PATCH] Berry language improved Tasmota integration --- CHANGELOG.md | 1 + .../Berry-0.1.10/generate/be_const_strtab.h | 239 +++++----- .../generate/be_const_strtab_def.h | 340 +++++++------- .../generate/be_fixed_be_class_map.h | 21 +- .../Berry-0.1.10/generate/be_fixed_string.h | 16 +- lib/lib_div/Berry-0.1.10/src/be_gc.h | 8 +- lib/lib_div/Berry-0.1.10/src/be_lexer.c | 3 +- lib/lib_div/Berry-0.1.10/src/be_maplib.c | 33 ++ lib/lib_div/Berry-0.1.10/src/be_object.h | 31 ++ lib/lib_div/Berry-0.1.10/src/be_parser.c | 2 +- lib/lib_div/Berry-0.1.10/src/be_string.c | 19 +- lib/lib_div/Berry-0.1.10/src/be_string.h | 2 +- lib/lib_div/Berry-0.1.10/src/be_strlib.c | 41 +- lib/lib_div/Berry-0.1.10/src/be_vector.c | 8 +- lib/lib_div/Berry-0.1.10/src/port/be_modtab.c | 5 + lib/lib_div/Berry-0.1.10/src/port/be_port.cpp | 63 ++- .../Berry-0.1.10/src/port/be_tasmotalib.c | 34 ++ .../Berry-0.1.10/src/port/berry_conf.h | 14 +- tasmota/berry/tasmota.be | 157 +++++++ tasmota/support_command.ino | 78 +++- tasmota/tasmota.h | 4 +- tasmota/xdrv_52_berry.ino | 416 +++++++++++++++--- tasmota/xdrv_interface.ino | 7 + 23 files changed, 1081 insertions(+), 461 deletions(-) create mode 100644 lib/lib_div/Berry-0.1.10/src/port/be_tasmotalib.c create mode 100644 tasmota/berry/tasmota.be diff --git a/CHANGELOG.md b/CHANGELOG.md index 671dbbc94..196566592 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - Support for Eastron SDM72D-M three phase 100A Modbus energy meter (#10862) - Support for Frysk language translations by Christiaan Heerze - ESP8266 Fallback to ``*.bin.gz`` binary when OTA upload of ``*.bin`` binary fails +- Berry language improved Tasmota integration ## [9.2.0.6] 20210210 ### Changed diff --git a/lib/lib_div/Berry-0.1.10/generate/be_const_strtab.h b/lib/lib_div/Berry-0.1.10/generate/be_const_strtab.h index df695ac4a..9234199bb 100644 --- a/lib/lib_div/Berry-0.1.10/generate/be_const_strtab.h +++ b/lib/lib_div/Berry-0.1.10/generate/be_const_strtab.h @@ -1,125 +1,128 @@ -extern const bcstring be_const_str_count; -extern const bcstring be_const_str_rad; -extern const bcstring be_const_str_str; -extern const bcstring be_const_str_import; -extern const bcstring be_const_str_opt_connect; -extern const bcstring be_const_str_open; -extern const bcstring be_const_str_codedump; -extern const bcstring be_const_str_imax; -extern const bcstring be_const_str_item; -extern const bcstring be_const_str_splitext; -extern const bcstring be_const_str___upper__; -extern const bcstring be_const_str_byte; -extern const bcstring be_const_str_isfile; -extern const bcstring be_const_str_issubclass; -extern const bcstring be_const_str_iter; -extern const bcstring be_const_str_classname; -extern const bcstring be_const_str_cos; -extern const bcstring be_const_str_number; -extern const bcstring be_const_str_true; -extern const bcstring be_const_str_hex; -extern const bcstring be_const_str_range; -extern const bcstring be_const_str_cosh; -extern const bcstring be_const_str_exp; -extern const bcstring be_const_str_exit; -extern const bcstring be_const_str_list; -extern const bcstring be_const_str_path; -extern const bcstring be_const_str_dot_p; -extern const bcstring be_const_str___iterator__; -extern const bcstring be_const_str_dump; -extern const bcstring be_const_str_deinit; -extern const bcstring be_const_str_size; -extern const bcstring be_const_str_false; -extern const bcstring be_const_str_clock; -extern const bcstring be_const_str_floor; -extern const bcstring be_const_str_module; -extern const bcstring be_const_str_tostring; -extern const bcstring be_const_str_type; -extern const bcstring be_const_str_upvname; -extern const bcstring be_const_str_opt_add; -extern const bcstring be_const_str___lower__; -extern const bcstring be_const_str_pi; -extern const bcstring be_const_str_assert; -extern const bcstring be_const_str_ceil; -extern const bcstring be_const_str_setitem; -extern const bcstring be_const_str_except; -extern const bcstring be_const_str_pow; -extern const bcstring be_const_str_sin; -extern const bcstring be_const_str_traceback; extern const bcstring be_const_str_calldepth; -extern const bcstring be_const_str_classof; -extern const bcstring be_const_str_init; -extern const bcstring be_const_str_sinh; -extern const bcstring be_const_str_split; -extern const bcstring be_const_str_raise; -extern const bcstring be_const_str_map; -extern const bcstring be_const_str_srand; -extern const bcstring be_const_str_allocated; -extern const bcstring be_const_str_asin; -extern const bcstring be_const_str_int; -extern const bcstring be_const_str_lower; -extern const bcstring be_const_str_var; -extern const bcstring be_const_str_abs; -extern const bcstring be_const_str_deg; -extern const bcstring be_const_str_setrange; -extern const bcstring be_const_str_time; -extern const bcstring be_const_str_real; -extern const bcstring be_const_str_end; -extern const bcstring be_const_str_isdir; -extern const bcstring be_const_str_; -extern const bcstring be_const_str_getcwd; -extern const bcstring be_const_str_attrdump; -extern const bcstring be_const_str_copy; -extern const bcstring be_const_str_imin; +extern const bcstring be_const_str_clock; +extern const bcstring be_const_str_size; extern const bcstring be_const_str_system; -extern const bcstring be_const_str_top; -extern const bcstring be_const_str_nil; -extern const bcstring be_const_str_push; -extern const bcstring be_const_str_remove; -extern const bcstring be_const_str_compile; -extern const bcstring be_const_str_atan; -extern const bcstring be_const_str_class; -extern const bcstring be_const_str_insert; -extern const bcstring be_const_str_pop; -extern const bcstring be_const_str_tanh; -extern const bcstring be_const_str_chdir; -extern const bcstring be_const_str_load; -extern const bcstring be_const_str_log; -extern const bcstring be_const_str_varname; -extern const bcstring be_const_str_find; -extern const bcstring be_const_str_isinstance; +extern const bcstring be_const_str_type; extern const bcstring be_const_str_if; -extern const bcstring be_const_str_super; -extern const bcstring be_const_str_break; -extern const bcstring be_const_str_do; -extern const bcstring be_const_str_else; -extern const bcstring be_const_str_for; +extern const bcstring be_const_str_int; +extern const bcstring be_const_str_isfile; +extern const bcstring be_const_str_log; +extern const bcstring be_const_str_raise; extern const bcstring be_const_str_concat; -extern const bcstring be_const_str_resize; -extern const bcstring be_const_str_reverse; -extern const bcstring be_const_str_while; -extern const bcstring be_const_str_input; -extern const bcstring be_const_str_sqrt; -extern const bcstring be_const_str_elif; -extern const bcstring be_const_str_log10; -extern const bcstring be_const_str_print; -extern const bcstring be_const_str_continue; -extern const bcstring be_const_str_collect; -extern const bcstring be_const_str_clear; -extern const bcstring be_const_str_rand; -extern const bcstring be_const_str_opt_neq; -extern const bcstring be_const_str_opt_eq; -extern const bcstring be_const_str_acos; -extern const bcstring be_const_str_listdir; +extern const bcstring be_const_str_list; +extern const bcstring be_const_str_map; +extern const bcstring be_const_str_for; +extern const bcstring be_const_str_dot_p; +extern const bcstring be_const_str_isdir; extern const bcstring be_const_str_mkdir; -extern const bcstring be_const_str_sethook; -extern const bcstring be_const_str_tan; -extern const bcstring be_const_str_def; -extern const bcstring be_const_str_char; -extern const bcstring be_const_str_exists; -extern const bcstring be_const_str_join; -extern const bcstring be_const_str_as; +extern const bcstring be_const_str_remove; +extern const bcstring be_const_str_cosh; +extern const bcstring be_const_str_abs; +extern const bcstring be_const_str_reverse; +extern const bcstring be_const_str_sinh; +extern const bcstring be_const_str_hex; +extern const bcstring be_const_str_tostring; +extern const bcstring be_const_str_opt_add; +extern const bcstring be_const_str_atan; +extern const bcstring be_const_str_real; +extern const bcstring be_const_str_iter; +extern const bcstring be_const_str_top; +extern const bcstring be_const_str_except; +extern const bcstring be_const_str_getcwd; +extern const bcstring be_const_str_listdir; +extern const bcstring be_const_str_log10; +extern const bcstring be_const_str_allocated; +extern const bcstring be_const_str_init; +extern const bcstring be_const_str_module; +extern const bcstring be_const_str_ceil; +extern const bcstring be_const_str_clear; +extern const bcstring be_const_str_collect; +extern const bcstring be_const_str_find; +extern const bcstring be_const_str_item; extern const bcstring be_const_str_format; -extern const bcstring be_const_str_try; -extern const bcstring be_const_str_upper; +extern const bcstring be_const_str_sqrt; +extern const bcstring be_const_str_classname; +extern const bcstring be_const_str_byte; +extern const bcstring be_const_str_else; +extern const bcstring be_const_str_deinit; +extern const bcstring be_const_str_end; +extern const bcstring be_const_str_true; +extern const bcstring be_const_str___upper__; +extern const bcstring be_const_str_char; +extern const bcstring be_const_str_load; +extern const bcstring be_const_str_resize; +extern const bcstring be_const_str_sethook; +extern const bcstring be_const_str_varname; +extern const bcstring be_const_str_deg; +extern const bcstring be_const_str_srand; +extern const bcstring be_const_str_str; +extern const bcstring be_const_str_range; +extern const bcstring be_const_str_toupper; +extern const bcstring be_const_str_; +extern const bcstring be_const_str_copy; +extern const bcstring be_const_str_exp; +extern const bcstring be_const_str_time; +extern const bcstring be_const_str_break; +extern const bcstring be_const_str_opt_neq; +extern const bcstring be_const_str_assert; +extern const bcstring be_const_str_attrdump; +extern const bcstring be_const_str_chdir; +extern const bcstring be_const_str_isinstance; +extern const bcstring be_const_str_continue; +extern const bcstring be_const_str_do; +extern const bcstring be_const_str_lower; +extern const bcstring be_const_str_pow; +extern const bcstring be_const_str_false; +extern const bcstring be_const_str_count; +extern const bcstring be_const_str_exit; +extern const bcstring be_const_str_print; +extern const bcstring be_const_str_def; +extern const bcstring be_const_str_pop; +extern const bcstring be_const_str_tolower; +extern const bcstring be_const_str_classof; +extern const bcstring be_const_str_cos; +extern const bcstring be_const_str_dump; +extern const bcstring be_const_str_join; +extern const bcstring be_const_str_push; +extern const bcstring be_const_str_sin; extern const bcstring be_const_str_return; +extern const bcstring be_const_str_path; +extern const bcstring be_const_str_rand; +extern const bcstring be_const_str_class; +extern const bcstring be_const_str_nil; +extern const bcstring be_const_str_input; +extern const bcstring be_const_str_floor; +extern const bcstring be_const_str_keys; +extern const bcstring be_const_str_number; +extern const bcstring be_const_str_rad; +extern const bcstring be_const_str_imin; +extern const bcstring be_const_str_pi; +extern const bcstring be_const_str_splitext; +extern const bcstring be_const_str_compile; +extern const bcstring be_const_str_setrange; +extern const bcstring be_const_str_traceback; +extern const bcstring be_const_str_upper; +extern const bcstring be_const_str_var; +extern const bcstring be_const_str_opt_eq; +extern const bcstring be_const_str_codedump; +extern const bcstring be_const_str_tan; +extern const bcstring be_const_str_setitem; +extern const bcstring be_const_str_tanh; +extern const bcstring be_const_str_as; +extern const bcstring be_const_str_issubclass; +extern const bcstring be_const_str_upvname; +extern const bcstring be_const_str_opt_connect; +extern const bcstring be_const_str_try; +extern const bcstring be_const_str_while; +extern const bcstring be_const_str_import; +extern const bcstring be_const_str___lower__; +extern const bcstring be_const_str_open; +extern const bcstring be_const_str_acos; +extern const bcstring be_const_str_asin; +extern const bcstring be_const_str_imax; +extern const bcstring be_const_str_insert; +extern const bcstring be_const_str_split; +extern const bcstring be_const_str___iterator__; +extern const bcstring be_const_str_exists; +extern const bcstring be_const_str_super; +extern const bcstring be_const_str_elif; diff --git a/lib/lib_div/Berry-0.1.10/generate/be_const_strtab_def.h b/lib/lib_div/Berry-0.1.10/generate/be_const_strtab_def.h index f3503a6f5..25b5b9221 100644 --- a/lib/lib_div/Berry-0.1.10/generate/be_const_strtab_def.h +++ b/lib/lib_div/Berry-0.1.10/generate/be_const_strtab_def.h @@ -1,186 +1,190 @@ -be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_rad); -be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_str); -be_define_const_str(str, "str", 3259748752u, 0, 3, &be_const_str_import); -be_define_const_str(import, "import", 288002260u, 66, 6, NULL); -be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_open); -be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); -be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_imax); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_item); -be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_splitext); -be_define_const_str(splitext, "splitext", 2150391934u, 0, 8, NULL); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_byte); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_isfile); -be_define_const_str(isfile, "isfile", 3131505107u, 0, 6, &be_const_str_issubclass); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_iter); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, NULL); -be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_cos); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_number); -be_define_const_str(number, "number", 467038368u, 0, 6, NULL); -be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_range); -be_define_const_str(range, "range", 4208725202u, 0, 5, NULL); -be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_exp); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, NULL); -be_define_const_str(exit, "exit", 3454868101u, 0, 4, &be_const_str_list); -be_define_const_str(list, "list", 217798785u, 0, 4, NULL); -be_define_const_str(path, "path", 2223459638u, 0, 4, NULL); -be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str___iterator__); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_dump); -be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_size); -be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_false); -be_define_const_str(false, "false", 184981848u, 62, 5, NULL); -be_define_const_str(clock, "clock", 363073373u, 0, 5, &be_const_str_floor); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_module); -be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_tostring); -be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, &be_const_str_type); -be_define_const_str(type, "type", 1361572173u, 0, 4, &be_const_str_upvname); -be_define_const_str(upvname, "upvname", 3848760617u, 0, 7, NULL); -be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str___lower__); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_pi); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, NULL); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_setitem); -be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, &be_const_str_except); -be_define_const_str(except, "except", 950914032u, 69, 6, NULL); -be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_sin); -be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_traceback); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, NULL); -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_classof); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, NULL); -be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_sinh); -be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_split); -be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_raise); -be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); -be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_srand); -be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); -be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_asin); -be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_int); -be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_lower); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_var); -be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); -be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_deg); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, NULL); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_time); -be_define_const_str(time, "time", 1564253156u, 0, 4, NULL); -be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); -be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); -be_define_const_str(isdir, "isdir", 2340917412u, 0, 5, NULL); -be_define_const_str(, "", 2166136261u, 0, 0, NULL); -be_define_const_str(getcwd, "getcwd", 652026575u, 0, 6, NULL); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_copy); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_imin); -be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_system); -be_define_const_str(system, "system", 1226705564u, 0, 6, &be_const_str_top); -be_define_const_str(top, "top", 2802900028u, 0, 3, &be_const_str_nil); -be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_remove); -be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); -be_define_const_str(compile, "compile", 1000265118u, 0, 7, NULL); -be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_class); -be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_pop); -be_define_const_str(pop, "pop", 1362321360u, 0, 3, &be_const_str_tanh); -be_define_const_str(tanh, "tanh", 153638352u, 0, 4, NULL); -be_define_const_str(chdir, "chdir", 806634853u, 0, 5, &be_const_str_load); -be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_log); -be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_varname); -be_define_const_str(varname, "varname", 2273276445u, 0, 7, NULL); -be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_isinstance); -be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_if); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_clock); +be_define_const_str(clock, "clock", 363073373u, 0, 5, &be_const_str_size); +be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_system); +be_define_const_str(system, "system", 1226705564u, 0, 6, &be_const_str_type); +be_define_const_str(type, "type", 1361572173u, 0, 4, &be_const_str_if); be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_break); -be_define_const_str(break, "break", 3378807160u, 58, 5, &be_const_str_do); -be_define_const_str(do, "do", 1646057492u, 65, 2, &be_const_str_else); -be_define_const_str(else, "else", 3183434736u, 52, 4, &be_const_str_for); +be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_isfile); +be_define_const_str(isfile, "isfile", 3131505107u, 0, 6, &be_const_str_log); +be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_raise); +be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); +be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_list); +be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_map); +be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_for); be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); -be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_resize); -be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_reverse); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL); -be_define_const_str(while, "while", 231090382u, 53, 5, NULL); -be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_sqrt); -be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, &be_const_str_elif); -be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); -be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_print); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_continue); -be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); -be_define_const_str(collect, "collect", 2399039025u, 0, 7, NULL); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_rand); -be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL); -be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_opt_eq); -be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_acos); -be_define_const_str(acos, "acos", 1006755615u, 0, 4, NULL); -be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_mkdir); -be_define_const_str(mkdir, "mkdir", 2883839448u, 0, 5, &be_const_str_sethook); -be_define_const_str(sethook, "sethook", 3963967276u, 0, 7, &be_const_str_tan); -be_define_const_str(tan, "tan", 2633446552u, 0, 3, &be_const_str_def); +be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_isdir); +be_define_const_str(isdir, "isdir", 2340917412u, 0, 5, &be_const_str_mkdir); +be_define_const_str(mkdir, "mkdir", 2883839448u, 0, 5, &be_const_str_remove); +be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); +be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL); +be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_reverse); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sinh); +be_define_const_str(sinh, "sinh", 282220607u, 0, 4, NULL); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL); +be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); +be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_atan); +be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_real); +be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_top); +be_define_const_str(top, "top", 2802900028u, 0, 3, &be_const_str_except); +be_define_const_str(except, "except", 950914032u, 69, 6, NULL); +be_define_const_str(getcwd, "getcwd", 652026575u, 0, 6, &be_const_str_listdir); +be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_log10); +be_define_const_str(log10, "log10", 2346846000u, 0, 5, NULL); +be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_init); +be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_module); +be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_clear); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_collect); +be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_find); +be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_item); +be_define_const_str(item, "item", 2671260646u, 0, 4, NULL); +be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_sqrt); +be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); +be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, NULL); +be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_end); +be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_true); +be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, NULL); +be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_load); +be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_resize); +be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_sethook); +be_define_const_str(sethook, "sethook", 3963967276u, 0, 7, &be_const_str_varname); +be_define_const_str(varname, "varname", 2273276445u, 0, 7, NULL); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_srand); +be_define_const_str(srand, "srand", 465518633u, 0, 5, &be_const_str_str); +be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); +be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_toupper); +be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_copy); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_exp); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_time); +be_define_const_str(time, "time", 1564253156u, 0, 4, &be_const_str_break); +be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); +be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_assert); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_attrdump); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_chdir); +be_define_const_str(chdir, "chdir", 806634853u, 0, 5, &be_const_str_isinstance); +be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_continue); +be_define_const_str(continue, "continue", 2977070660u, 59, 8, &be_const_str_do); +be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_pow); +be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_false); +be_define_const_str(false, "false", 184981848u, 62, 5, NULL); +be_define_const_str(count, "count", 967958004u, 0, 5, NULL); +be_define_const_str(exit, "exit", 3454868101u, 0, 4, &be_const_str_print); +be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_def); be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); -be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_exists); -be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_join); -be_define_const_str(join, "join", 3374496889u, 0, 4, &be_const_str_as); -be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_try); -be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); -be_define_const_str(upper, "upper", 176974407u, 0, 5, &be_const_str_return); +be_define_const_str(pop, "pop", 1362321360u, 0, 3, &be_const_str_tolower); +be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_cos); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_dump); +be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_join); +be_define_const_str(join, "join", 3374496889u, 0, 4, &be_const_str_push); +be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_sin); +be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_return); be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); +be_define_const_str(path, "path", 2223459638u, 0, 4, &be_const_str_rand); +be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_class); +be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_nil); +be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); +be_define_const_str(input, "input", 4191711099u, 0, 5, NULL); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_keys); +be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_number); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_rad); +be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); +be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_pi); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL); +be_define_const_str(splitext, "splitext", 2150391934u, 0, 8, NULL); +be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_setrange); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_traceback); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_upper); +be_define_const_str(upper, "upper", 176974407u, 0, 5, &be_const_str_var); +be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); +be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, NULL); +be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_tan); +be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); +be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); +be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_as); +be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_upvname); +be_define_const_str(upvname, "upvname", 3848760617u, 0, 7, NULL); +be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, NULL); +be_define_const_str(try, "try", 2887626766u, 68, 3, &be_const_str_while); +be_define_const_str(while, "while", 231090382u, 53, 5, NULL); +be_define_const_str(import, "import", 288002260u, 66, 6, NULL); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_open); +be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); +be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_asin); +be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_imax); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_insert); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_split); +be_define_const_str(split, "split", 2276994531u, 0, 5, NULL); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_exists); +be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_super); +be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_elif); +be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); static const bstring* const m_string_table[] = { - (const bstring *)&be_const_str_count, - (const bstring *)&be_const_str_opt_connect, - (const bstring *)&be_const_str_codedump, - (const bstring *)&be_const_str___upper__, - (const bstring *)&be_const_str_classname, - (const bstring *)&be_const_str_true, - (const bstring *)&be_const_str_hex, + (const bstring *)&be_const_str_calldepth, + (const bstring *)&be_const_str_int, + (const bstring *)&be_const_str_concat, + (const bstring *)&be_const_str_dot_p, NULL, (const bstring *)&be_const_str_cosh, - (const bstring *)&be_const_str_exit, - (const bstring *)&be_const_str_path, - (const bstring *)&be_const_str_dot_p, - (const bstring *)&be_const_str_deinit, - (const bstring *)&be_const_str_clock, - (const bstring *)&be_const_str_opt_add, - (const bstring *)&be_const_str_assert, - (const bstring *)&be_const_str_ceil, - (const bstring *)&be_const_str_pow, - (const bstring *)&be_const_str_calldepth, - (const bstring *)&be_const_str_init, - NULL, - (const bstring *)&be_const_str_map, - (const bstring *)&be_const_str_allocated, (const bstring *)&be_const_str_abs, - (const bstring *)&be_const_str_setrange, - (const bstring *)&be_const_str_real, - (const bstring *)&be_const_str_end, + (const bstring *)&be_const_str_hex, + (const bstring *)&be_const_str_tostring, + (const bstring *)&be_const_str_opt_add, + (const bstring *)&be_const_str_iter, + (const bstring *)&be_const_str_getcwd, NULL, - (const bstring *)&be_const_str_isdir, + (const bstring *)&be_const_str_allocated, + (const bstring *)&be_const_str_ceil, + (const bstring *)&be_const_str_format, + (const bstring *)&be_const_str_classname, + (const bstring *)&be_const_str_byte, + (const bstring *)&be_const_str_else, + (const bstring *)&be_const_str_deinit, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str_char, + NULL, + (const bstring *)&be_const_str_deg, + NULL, + (const bstring *)&be_const_str_range, (const bstring *)&be_const_str_, NULL, - (const bstring *)&be_const_str_getcwd, - (const bstring *)&be_const_str_attrdump, - (const bstring *)&be_const_str_push, - (const bstring *)&be_const_str_compile, - (const bstring *)&be_const_str_atan, - (const bstring *)&be_const_str_insert, - (const bstring *)&be_const_str_chdir, - (const bstring *)&be_const_str_find, - NULL, - (const bstring *)&be_const_str_super, - (const bstring *)&be_const_str_concat, - (const bstring *)&be_const_str_while, - (const bstring *)&be_const_str_input, - (const bstring *)&be_const_str_log10, - (const bstring *)&be_const_str_collect, - (const bstring *)&be_const_str_clear, (const bstring *)&be_const_str_opt_neq, - (const bstring *)&be_const_str_listdir, - (const bstring *)&be_const_str_char, - (const bstring *)&be_const_str_format, - (const bstring *)&be_const_str_upper + (const bstring *)&be_const_str_lower, + (const bstring *)&be_const_str_count, + (const bstring *)&be_const_str_exit, + (const bstring *)&be_const_str_pop, + (const bstring *)&be_const_str_classof, + (const bstring *)&be_const_str_path, + (const bstring *)&be_const_str_input, + (const bstring *)&be_const_str_floor, + (const bstring *)&be_const_str_imin, + (const bstring *)&be_const_str_splitext, + NULL, + (const bstring *)&be_const_str_compile, + (const bstring *)&be_const_str_opt_eq, + (const bstring *)&be_const_str_codedump, + (const bstring *)&be_const_str_setitem, + (const bstring *)&be_const_str_tanh, + (const bstring *)&be_const_str_issubclass, + (const bstring *)&be_const_str_opt_connect, + (const bstring *)&be_const_str_try, + (const bstring *)&be_const_str_import, + (const bstring *)&be_const_str___lower__, + NULL, + (const bstring *)&be_const_str_acos, + (const bstring *)&be_const_str___iterator__ }; static const struct bconststrtab m_const_string_table = { - .size = 52, - .count = 104, + .size = 53, + .count = 107, .table = m_string_table }; diff --git a/lib/lib_div/Berry-0.1.10/generate/be_fixed_be_class_map.h b/lib/lib_div/Berry-0.1.10/generate/be_fixed_be_class_map.h index eebf1b658..06c75a050 100644 --- a/lib/lib_div/Berry-0.1.10/generate/be_fixed_be_class_map.h +++ b/lib/lib_div/Berry-0.1.10/generate/be_fixed_be_class_map.h @@ -1,21 +1,22 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_map_map) { - { be_const_key(init, -1), be_const_func(m_init) }, - { be_const_key(remove, 7), be_const_func(m_remove) }, - { be_const_key(find, -1), be_const_func(m_find) }, - { be_const_key(insert, 8), be_const_func(m_insert) }, + { be_const_key(dot_p, 2), be_const_int(0) }, + { be_const_key(insert, -1), be_const_func(m_insert) }, + { be_const_key(remove, -1), be_const_func(m_remove) }, + { be_const_key(tostring, -1), be_const_func(m_tostring) }, + { be_const_key(iter, 5), be_const_func(m_iter) }, { be_const_key(size, -1), be_const_func(m_size) }, - { be_const_key(tostring, 0), be_const_func(m_tostring) }, - { be_const_key(setitem, 3), be_const_func(m_setitem) }, - { be_const_key(iter, -1), be_const_func(m_iter) }, - { be_const_key(item, -1), be_const_func(m_item) }, - { be_const_key(dot_p, 1), be_const_int(0) }, + { be_const_key(keys, -1), be_const_func(m_keys) }, + { be_const_key(setitem, -1), be_const_func(m_setitem) }, + { be_const_key(find, 0), be_const_func(m_find) }, + { be_const_key(init, -1), be_const_func(m_init) }, + { be_const_key(item, 1), be_const_func(m_item) }, }; static be_define_const_map( be_class_map_map, - 10 + 11 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/lib_div/Berry-0.1.10/generate/be_fixed_string.h b/lib/lib_div/Berry-0.1.10/generate/be_fixed_string.h index c2da8b838..906c11f55 100644 --- a/lib/lib_div/Berry-0.1.10/generate/be_fixed_string.h +++ b/lib/lib_div/Berry-0.1.10/generate/be_fixed_string.h @@ -1,18 +1,20 @@ #include "be_constobj.h" static be_define_const_map_slots(m_libstring_map) { - { be_const_key(hex, 2), be_const_func(str_i2hex) }, - { be_const_key(byte, -1), be_const_func(str_byte) }, - { be_const_key(format, 5), be_const_func(str_format) }, - { be_const_key(find, -1), be_const_func(str_find) }, - { be_const_key(char, 1), be_const_func(str_char) }, - { be_const_key(split, -1), be_const_func(str_split) }, + { be_const_key(tolower, -1), be_const_func(str_tolower) }, { be_const_key(count, -1), be_const_func(str_count) }, + { be_const_key(hex, -1), be_const_func(str_i2hex) }, + { be_const_key(split, 5), be_const_func(str_split) }, + { be_const_key(byte, -1), be_const_func(str_byte) }, + { be_const_key(char, 6), be_const_func(str_char) }, + { be_const_key(toupper, 1), be_const_func(str_toupper) }, + { be_const_key(find, -1), be_const_func(str_find) }, + { be_const_key(format, -1), be_const_func(str_format) }, }; static be_define_const_map( m_libstring_map, - 7 + 9 ); static be_define_const_module( diff --git a/lib/lib_div/Berry-0.1.10/src/be_gc.h b/lib/lib_div/Berry-0.1.10/src/be_gc.h index 16ca7e766..5943a7392 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_gc.h +++ b/lib/lib_div/Berry-0.1.10/src/be_gc.h @@ -13,7 +13,7 @@ #define BE_GCOBJECT BE_STRING #define gc_object(o) cast(bgcobject*, o) -#define gc_cast(o, t, T) ((o) && (o)->type == (t) ? (T*)(o) : NULL) +#define gc_cast(o, t, T) ((o) && pgm_read_byte(&(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) @@ -38,11 +38,11 @@ if (!gc_isconst(o)) { \ #define gc_setwhite(o) gc_setmark((o), GC_WHITE) #define gc_setgray(o) gc_setmark((o), GC_GRAY) #define gc_setdark(o) gc_setmark((o), GC_DARK) -#define gc_isfixed(o) (((o)->marked & GC_FIXED) != 0) +#define gc_isfixed(o) ((pgm_read_byte(&(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_isconst(o) ((pgm_read_byte(&(o)->marked) & GC_CONST) != 0) +#define gc_exmark(o) ((pgm_read_byte(&(o)->marked) >> 4) & 0x0F) #define gc_setexmark(o, k) ((o)->marked |= (k) << 4) #define be_isgctype(t) ((t) >= BE_GCOBJECT) diff --git a/lib/lib_div/Berry-0.1.10/src/be_lexer.c b/lib/lib_div/Berry-0.1.10/src/be_lexer.c index eea82109d..b201e8df2 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_lexer.c +++ b/lib/lib_div/Berry-0.1.10/src/be_lexer.c @@ -105,7 +105,8 @@ static int next(blexer *lexer) lr->s = s ? s : &eos; --lr->len; } - lexer->cursor = *lr->s++; + // lexer->cursor = *lr->s++; // SH + lexer->cursor = pgm_read_byte(lr->s++); return lexer->cursor; } diff --git a/lib/lib_div/Berry-0.1.10/src/be_maplib.c b/lib/lib_div/Berry-0.1.10/src/be_maplib.c index 2d8446edd..936e3164d 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_maplib.c +++ b/lib/lib_div/Berry-0.1.10/src/be_maplib.c @@ -172,6 +172,37 @@ static int m_iter(bvm *vm) 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); +} + #if !BE_USE_PRECOMPILED_OBJECT void be_load_maplib(bvm *vm) { @@ -186,6 +217,7 @@ void be_load_maplib(bvm *vm) { "size", m_size }, { "insert", m_insert }, { "iter", m_iter }, + { "keys", m_keys }, { NULL, NULL } }; be_regclass(vm, "map", members); @@ -203,6 +235,7 @@ class be_class_map (scope: global, name: map) { size, func(m_size) insert, func(m_insert) iter, func(m_iter) + keys, func(m_keys) } @const_object_info_end */ #include "../generate/be_fixed_be_class_map.h" diff --git a/lib/lib_div/Berry-0.1.10/src/be_object.h b/lib/lib_div/Berry-0.1.10/src/be_object.h index d465138ec..dd73a8a87 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_object.h +++ b/lib/lib_div/Berry-0.1.10/src/be_object.h @@ -10,6 +10,37 @@ #include "berry.h" +/* support for PROGMEM on ESP8266 and AVR */ +#ifdef _PGMSPACE_H_ + #define strncmp strncmp_PP + #define strcmp(str1P, str2P) strncmp_PP((str1P), (str2P), SIZE_IRRELEVANT) + #define strncasecmp strncasecmp_P + #define strcasecmp_P(str1, str2P) strncasecmp_P((str1), (str2P), SIZE_IRRELEVANT) + #define strlen strlen_P + #define strchr strchr_P + #define strcat strcat_P + #define strncat strncat_P + #define strcpy strcpy_P + #define strncpy strncpy_P + #define memcpy memcpy_P + #define memccpy memccpy_P + #define memmove memmove_P + #define memcmp memcmp_P + #define memmem memmem_P + #define memchr memchr_P + #define sprintf sprintf_P + #define snprintf snprintf_P +#endif + +#ifndef pgm_read_byte +#define pgm_read_byte(addr) (*(const uint8_t*)(addr)) +#endif + +#ifndef pgm_read_word +#define pgm_read_word(addr) (*(const uint16_t*)(addr)) +#endif + + /* basic types, do not change value */ #define BE_NONE (-1) /* unknow type */ #define BE_COMPTR (-2) /* common pointer */ diff --git a/lib/lib_div/Berry-0.1.10/src/be_parser.c b/lib/lib_div/Berry-0.1.10/src/be_parser.c index 1839e9392..bdfdcaf3d 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_parser.c +++ b/lib/lib_div/Berry-0.1.10/src/be_parser.c @@ -31,7 +31,7 @@ #define FUNC_ANONYMOUS 2 /* get binary operator priority */ -#define binary_op_prio(op) (binary_op_prio_tab[cast_int(op) - OptAdd]) +#define binary_op_prio(op) (pgm_read_byte(&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) diff --git a/lib/lib_div/Berry-0.1.10/src/be_string.c b/lib/lib_div/Berry-0.1.10/src/be_string.c index db7dcaebf..0590fb396 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_string.c +++ b/lib/lib_div/Berry-0.1.10/src/be_string.c @@ -44,9 +44,9 @@ int be_eqstr(bstring *s1, bstring *s2) if (s1 == s2) { /* short string or the same string */ return 1; } - slen = s1->slen; + slen = pgm_read_byte(&s1->slen); /* long string */ - if (slen == 255 && slen == s2->slen) { + if (slen == 255 && slen == pgm_read_byte(&s2->slen)) { blstring *ls1 = cast(blstring*, s1); blstring *ls2 = cast(blstring*, s2); return ls1->llen == ls2->llen && !strcmp(lstr(ls1), lstr(ls2)); @@ -88,7 +88,7 @@ static void resize(bvm *vm, int size) static void free_sstring(bvm *vm, bstring *str) { - be_free(vm, str, sizeof(bsstring) + str->slen + 1); + be_free(vm, str, sizeof(bsstring) + pgm_read_byte(&str->slen) + 1); } /* FNV-1a Hash */ @@ -97,7 +97,8 @@ 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; + hash = (hash ^ (unsigned char)pgm_read_byte(str)) * 16777619u; + str++; } return hash; } @@ -149,7 +150,7 @@ static bstring* find_conststr(const char *str, size_t len) 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)) { + if (len == pgm_read_byte(&s->slen) && !strncmp(str, s->s, len)) { return (bstring*)s; } } @@ -165,7 +166,7 @@ static bstring* newshortstr(bvm *vm, const char *str, size_t 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)) { + if (len == pgm_read_byte(&s->slen) && !strncmp(str, sstr(s), len)) { return s; } } @@ -252,7 +253,7 @@ uint32_t be_strhash(const bstring *s) return cast(bcstring*, s)->hash; } #if BE_USE_STR_HASH_CACHE - if (s->slen != 255) { + if (pgm_read_byte(&s->slen) != 255) { return cast(bsstring*, s)->hash; } #endif @@ -265,7 +266,7 @@ const char* be_str2cstr(const bstring *s) if (gc_isconst(s)) { return cstr(s); } - if (s->slen == 255) { + if (pgm_read_byte(&s->slen) == 255) { return lstr(s); } return sstr(s); @@ -276,4 +277,4 @@ void be_str_setextra(bstring *s, int extra) if (!gc_isconst(s)) { s->extra = cast(bbyte, extra); } -} +} \ No newline at end of file diff --git a/lib/lib_div/Berry-0.1.10/src/be_string.h b/lib/lib_div/Berry-0.1.10/src/be_string.h index 51b3fd016..8d3fba49e 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_string.h +++ b/lib/lib_div/Berry-0.1.10/src/be_string.h @@ -33,7 +33,7 @@ typedef struct { } bcstring; #define str_len(_s) \ - ((_s)->slen == 255 ? cast(blstring*, _s)->llen : (_s)->slen) + (pgm_read_byte(&(_s)->slen) == 255 ? cast(blstring*, _s)->llen : pgm_read_byte(&(_s)->slen)) #define str(_s) be_str2cstr(_s) #define str_extra(_s) ((_s)->extra) diff --git a/lib/lib_div/Berry-0.1.10/src/be_strlib.c b/lib/lib_div/Berry-0.1.10/src/be_strlib.c index f4bda16c4..37fe8e12b 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_strlib.c +++ b/lib/lib_div/Berry-0.1.10/src/be_strlib.c @@ -14,6 +14,7 @@ #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') @@ -175,7 +176,7 @@ const char* be_pushvfstr(bvm *vm, const char *format, va_list arg) } pushstr(vm, format, p - format); concat2(vm); - switch (p[1]) { + switch (pgm_read_byte(&p[1])) { case 's': { const char *s = va_arg(arg, char*); if (s == NULL) { @@ -338,8 +339,8 @@ bstring* be_strindex(bvm *vm, bstring *str, bvalue *idx) const char* be_splitpath(const char *path) { const char *p; - for (p = path - 1; *path != '\0'; ++path) { - if (*path == '/') { + for (p = path - 1; pgm_read_byte(path) != '\0'; ++path) { + if (pgm_read_byte(path) == '/') { p = path; } } @@ -708,6 +709,34 @@ static int str_char(bvm *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); +} + + #if !BE_USE_PRECOMPILED_OBJECT be_native_module_attr_table(string) { be_native_module_function("format", str_format), @@ -716,7 +745,9 @@ be_native_module_attr_table(string) { 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("char", str_char), + be_native_module_function("tolower", str_tolower), + be_native_module_function("toupper", str_toupper), }; be_define_native_module(string, NULL); @@ -730,6 +761,8 @@ module string (scope: global, depend: BE_USE_STRING_MODULE) { hex, func(str_i2hex) byte, func(str_byte) char, func(str_char) + tolower, func(str_tolower) + toupper, func(str_toupper) } @const_object_info_end */ #include "../generate/be_fixed_string.h" diff --git a/lib/lib_div/Berry-0.1.10/src/be_vector.c b/lib/lib_div/Berry-0.1.10/src/be_vector.c index b73479601..2cd3f1e2e 100644 --- a/lib/lib_div/Berry-0.1.10/src/be_vector.c +++ b/lib/lib_div/Berry-0.1.10/src/be_vector.c @@ -122,16 +122,16 @@ static int binary_search(int value) 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 (pgm_read_word(mid) == value) { + return pgm_read_word(&mid[1]); } - if (*mid < value) { + if (pgm_read_word(mid) < value) { low = mid + 1; } else { high = mid - 1; } } - return *low; + return pgm_read_word(low); } static int nextpow(int value) diff --git a/lib/lib_div/Berry-0.1.10/src/port/be_modtab.c b/lib/lib_div/Berry-0.1.10/src/port/be_modtab.c index 9250e83e2..eb83cf5a2 100644 --- a/lib/lib_div/Berry-0.1.10/src/port/be_modtab.c +++ b/lib/lib_div/Berry-0.1.10/src/port/be_modtab.c @@ -19,6 +19,9 @@ be_extern_native_module(sys); be_extern_native_module(debug); be_extern_native_module(gc); +/* Tasmota specific */ +be_extern_native_module(tasmota); + /* user-defined modules declare start */ /* user-defined modules declare end */ @@ -52,6 +55,8 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #endif /* user-defined modules register start */ + &be_native_module(tasmota), + /* user-defined modules register end */ NULL /* do not remove */ }; diff --git a/lib/lib_div/Berry-0.1.10/src/port/be_port.cpp b/lib/lib_div/Berry-0.1.10/src/port/be_port.cpp index 7233f57dc..fd9ac48d6 100644 --- a/lib/lib_div/Berry-0.1.10/src/port/be_port.cpp +++ b/lib/lib_div/Berry-0.1.10/src/port/be_port.cpp @@ -16,44 +16,35 @@ /* standard input and output */ extern "C" { - void serial(const char *sp) { - char s[200]; - snprintf_P(s, sizeof(s), "%s", sp); - Serial.printf(s); - Serial.flush(); - } - void serial3(const char *sp, uint32_t a, uint32_t b, uint32_t c) { - char s[200]; - snprintf_P(s, sizeof(s), "%s 0x%08X 0x%08X 0x%08X\n", sp, a, b, c); - Serial.printf(s); - Serial.flush(); - } - void serial2s1(const char *sp, const char * a, const char * b, uint32_t c) { - char s[200]; - snprintf_P(s, sizeof(s), "%s '%s' '%s' 0x%08X\n", sp, a, b, c); - Serial.printf(s); - Serial.flush(); + int strncmp_PP(const char * str1P, const char * str2P, size_t size) + { + int result = 0; + + while (size > 0) + { + char ch1 = pgm_read_byte(str1P++); + char ch2 = pgm_read_byte(str2P++); + result = ch1 - ch2; + if (result != 0 || ch2 == '\0') + { + break; + } + + size--; + } + + return result; } -// int strncmp_PP(const char * str1P, const char * str2P, size_t size) -// { -// int result = 0; - -// while (size > 0) -// { -// char ch1 = pgm_read_byte(str1P++); -// char ch2 = pgm_read_byte(str2P++); -// result = ch1 - ch2; -// if (result != 0 || ch2 == '\0') -// { -// break; -// } - -// size--; -// } - -// return result; -// } + // + char * strchr_P(const char *s, int c) { + do { + if (pgm_read_byte(s) == c) { + return (char*)s; + } + } while (pgm_read_byte(s++)); + return (0); + } } BERRY_API void be_writebuffer(const char *buffer, size_t length) diff --git a/lib/lib_div/Berry-0.1.10/src/port/be_tasmotalib.c b/lib/lib_div/Berry-0.1.10/src/port/be_tasmotalib.c new file mode 100644 index 000000000..7f17998cb --- /dev/null +++ b/lib/lib_div/Berry-0.1.10/src/port/be_tasmotalib.c @@ -0,0 +1,34 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `import tasmota` + *******************************************************************/ +#include "be_object.h" + +extern int l_getFreeHeap(bvm *vm); +extern int l_publish(bvm *vm); +extern int l_cmd(bvm *vm); +extern int l_getoption(bvm *vm); +extern int l_millis(bvm *vm); +extern int l_timereached(bvm *vm); + +// #if !BE_USE_PRECOMPILED_OBJECT +#if 1 // TODO we will do pre-compiled later +be_native_module_attr_table(tasmota) { + be_native_module_function("getfreeheap", l_getFreeHeap), + be_native_module_function("publish", l_publish), + be_native_module_function("cmd", l_cmd), + be_native_module_function("getoption", l_getoption), + be_native_module_function("millis", l_millis), + be_native_module_function("timereached", l_timereached), +}; + +be_define_native_module(tasmota, NULL); +#else +/* @const_object_info_begin +module tasmota (scope: global, depend: 1) { + getfreeheap, func(l_getFreeHeap) +} +@const_object_info_end */ +#include "../generate/be_fixed_tasmota.h" +#endif diff --git a/lib/lib_div/Berry-0.1.10/src/port/berry_conf.h b/lib/lib_div/Berry-0.1.10/src/port/berry_conf.h index aee1214aa..5228f567f 100644 --- a/lib/lib_div/Berry-0.1.10/src/port/berry_conf.h +++ b/lib/lib_div/Berry-0.1.10/src/port/berry_conf.h @@ -8,14 +8,14 @@ #ifndef BERRY_CONF_H #define BERRY_CONF_H +#include + #ifdef __cplusplus extern "C" { #endif - extern void serial(const char *sp); - extern void serial3(const char *sp, uint32_t a, uint32_t b, uint32_t c); - extern void serial2s1(const char *sp, const char *a, const char *b, uint32_t c); extern int strncmp_PP(const char * str1P, const char * str2P, size_t size); + extern char * strchr_P(const char *s, int c); #ifdef __cplusplus } @@ -54,7 +54,11 @@ extern "C" { * runtime. Enable this macro can greatly optimize RAM usage. * Default: 1 **/ -#define BE_USE_PRECOMPILED_OBJECT 1 +#ifdef ESP8266 +#define BE_USE_PRECOMPILED_OBJECT 0 +#else +#define BE_USE_PRECOMPILED_OBJECT 0 // will enable later when stabilized +#endif /* Macro: BE_DEBUG_RUNTIME_INFO * Set runtime error debugging information. @@ -157,7 +161,7 @@ extern "C" { #define BE_USE_OS_MODULE 0 #define BE_USE_SYS_MODULE 0 #define BE_USE_DEBUG_MODULE 0 -#define BE_USE_GC_MODULE 0 +#define BE_USE_GC_MODULE 1 /* Macro: BE_EXPLICIT_XXX * If these macros are defined, the corresponding function will diff --git a/tasmota/berry/tasmota.be b/tasmota/berry/tasmota.be new file mode 100644 index 000000000..3393ea1bd --- /dev/null +++ b/tasmota/berry/tasmota.be @@ -0,0 +1,157 @@ +import json import string +tasmota = module("tasmota") +def charsinstring(s,c) + for i:0..size(s)-1 + for j:0..size(c)-1 + if s[i] == c[j] return i end + end + end + return -1 +end + +tasmota._eqstr=/s1,s2-> str(s1) == str(s2) +tasmota._neqstr=/s1,s2-> str(s1) != str(s2) +tasmota._eq=/f1,f2-> real(f1) == real(f2) +tasmota._neq=/f1,f2-> real(f1) != real(f2) +tasmota._gt=/f1,f2-> real(f1) > real(f2) +tasmota._lt=/f1,f2-> real(f1) < real(f2) +tasmota._ge=/f1,f2-> real(f1) >= real(f2) +tasmota._le=/f1,f2-> real(f1) <= real(f2) +tasmota._op=[ + ['==',tasmota._eqstr], + ['!==',tasmota._neqstr], + ['=',tasmota._eq], + ['!=',tasmota._neq], + ['>=',tasmota._ge], + ['<=',tasmota._le], + ['>',tasmota._gt], + ['<',tasmota._lt], +] +tasmota._operators="=<>!|" + +# split the item when there is an operator, returns a list of (left,op,right) +# ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] +tasmota.find_op = def (item) + pos = charsinstring(item, tasmota._operators) + if pos>=0 + op_split = string.split(item,pos) + #print(op_split) + op_left = op_split[0] + op_rest = op_split[1] + # iterate through operators + for op:tasmota._op + if string.find(op_rest,op[0]) == 0 + op_func = op[1] + op_right = string.split(op_rest,size(op[0]))[1] + return [op_left,op_func,op_right] + end + end + end + return [item, nil, nil] +end + + +def findkeyi(m,keyi) + keyu=string.toupper(keyi) + if classof(m) == map + for k:m.keys() + if string.toupper(k)==keyu || keyi=='?' + return k + end + end + end +end + + +tasmota.try_rule = def (ev, rule, f) + rl_list = tasmota.find_op(rule) + e=ev + rl=string.split(rl_list[0],'#') + for it:rl + found=findkeyi(e,it) + if found == nil + return false + end + e=e[found] + end + # check if condition is true + if rl_list[1] + # did we find a function + if !rl_list[1](e,rl_list[2]) + # condition is not met + return false + end + end + f(e,ev) + return true +end +tasmota_rules={} +tasmota.rule = def(pat,f) tasmota_rules[pat] = f end + +tasmota.exec_rules = def (ev_json) + ev = json.load(ev_json) + if ev == nil + log("ERROR, bad json: "+ev_json, 3) + end + ret = false + for r:tasmota_rules.keys() + ret = tasmota.try_rule(ev,r,tasmota_rules[r]) || ret + end + return ret +end + +#- Test +################################################################# + +def log(m) print(m) end +def my_rule(e,ev) log("e1="+str(e)+" e2="+str(ev)) end + +tasmota.rule("ZBRECEIVED#?#LINKQUALITY", my_rule) +tasmota.rule("ZBRECEIVED#0x1234", my_rule) + +tasmota.rule("ZBRECEIVED#?#LINKQUALITY<10", my_rule) + +tasmota.rule("Dimmer>50", my_rule) +tasmota.rule("Dimmer=01", my_rule) + + +tasmota.rule("Color==022600", my_rule) + +tasmota.exec_rules('{"Color":"022600"}') + +tasmota.exec_rules('{"ZbReceived":{"0x1234":{"Device":"0x1234","LinkQuality":50}}}') + +tasmota.exec_rules('{"Dimmer":10}') + + + +# tasmota.rule("DIMMER", my_rule) +# tasmota.rule("DIMMER#DATA#DATA", my_rule) +# tasmota.exec_rules('{"Dimmer":{"Data":50}}') + + +-# + +#- +tasmota.find_op("aaa") +tasmota.find_op("aaa>50") +-# + +#- +# Example of backlog equivalent + +def backlog(cmd_list) + delay_backlog = tasmota.getoption(34) # in milliseconds + delay = 0 + for cmd:cmd_list + tasmota.timer(delay, /-> tasmota.cmd(cmd)) + delay = delay + delay_backlog + end +end + + +br def backlog(cmd_list) delay_backlog = tasmota.getoption(34) delay = 0 for cmd:cmd_list tasmota.timer(delay, /-> tasmota.cmd(cmd)) delay = delay + delay_backlog end end + +br backlog( [ "Power 0", "Status 4", "Power 1" ] ) + +-# \ No newline at end of file diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 139631e74..065fabbcc 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -844,35 +844,67 @@ void CmndSetoption(void) { CmndSetoptionBase(1); } +// Code called by SetOption and by Berrt +bool SetoptionDecode(uint32_t index, uint32_t *ptype, uint32_t *pindex) { + if (index < 146) { + if (index <= 31) { // SetOption0 .. 31 = Settings.flag + *ptype = 2; + *pindex = index; // 0 .. 31 + } + else if (index <= 49) { // SetOption32 .. 49 = Settings.param + *ptype = 1; + *pindex = index -32; // 0 .. 17 (= PARAM8_SIZE -1) + } + else if (index <= 81) { // SetOption50 .. 81 = Settings.flag3 + *ptype = 3; + *pindex = index -50; // 0 .. 31 + } + else if (index <= 113) { // SetOption82 .. 113 = Settings.flag4 + *ptype = 4; + *pindex = index -82; // 0 .. 31 + } + else { // SetOption114 .. 145 = Settings.flag5 + *ptype = 5; + *pindex = index -114; // 0 .. 31 + } + return true; + } + return false; +} + +uint32_t GetOption(uint32_t index) { + uint32_t ptype; + uint32_t pindex; + if (SetoptionDecode(index, &ptype, &pindex)) { + if (1 == ptype) { + return Settings.param[pindex]; + } else { + uint32_t flag = Settings.flag.data; + if (3 == ptype) { + flag = Settings.flag3.data; + } + else if (4 == ptype) { + flag = Settings.flag4.data; + } + else if (5 == ptype) { + flag = Settings.flag5.data; + } + return bitRead(flag, pindex); + } + } else { + return 0; // fallback + } +} + void CmndSetoptionBase(bool indexed) { // Allow a command to access a single SetOption by it's command name // indexed = 0 : No index will be returned attached to the command // {"ClockDirection":"OFF"} // indexed = 1 : The SetOption index will be returned with the command // {"SetOption16":"OFF"} - if (XdrvMailbox.index < 146) { - uint32_t ptype; - uint32_t pindex; - if (XdrvMailbox.index <= 31) { // SetOption0 .. 31 = Settings.flag - ptype = 2; - pindex = XdrvMailbox.index; // 0 .. 31 - } - else if (XdrvMailbox.index <= 49) { // SetOption32 .. 49 = Settings.param - ptype = 1; - pindex = XdrvMailbox.index -32; // 0 .. 17 (= PARAM8_SIZE -1) - } - else if (XdrvMailbox.index <= 81) { // SetOption50 .. 81 = Settings.flag3 - ptype = 3; - pindex = XdrvMailbox.index -50; // 0 .. 31 - } - else if (XdrvMailbox.index <= 113) { // SetOption82 .. 113 = Settings.flag4 - ptype = 4; - pindex = XdrvMailbox.index -82; // 0 .. 31 - } - else { // SetOption114 .. 145 = Settings.flag5 - ptype = 5; - pindex = XdrvMailbox.index -114; // 0 .. 31 - } + uint32_t ptype; + uint32_t pindex; + if (SetoptionDecode(XdrvMailbox.index, &ptype, &pindex)) { if (XdrvMailbox.payload >= 0) { if (1 == ptype) { // SetOption32 .. 49 diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index c4daf839b..34e2a562a 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -370,10 +370,10 @@ enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER, - SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_MAX }; + SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_BERRY, SRC_MAX }; const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|" "Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter|" - "Thermostat|Chat|TCL"; + "Thermostat|Chat|TCL|Berry"; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/tasmota/xdrv_52_berry.ino b/tasmota/xdrv_52_berry.ino index 04d73bf29..ce0f0b2b6 100644 --- a/tasmota/xdrv_52_berry.ino +++ b/tasmota/xdrv_52_berry.ino @@ -19,7 +19,6 @@ #ifdef USE_BERRY -// #ifdef ESP32 #define XDRV_52 52 @@ -67,6 +66,7 @@ void (* const BerryCommand[])(void) PROGMEM = { class BerrySupport { public: bvm *vm = nullptr; // berry vm + bool rules_busy = false; // are we already processing rules, avoid infinite loop #ifdef USE_BERRY_ASYNC // Alternate stack for the Berry VM uint8_t *stack_alloc = nullptr; // stack malloc address @@ -99,25 +99,126 @@ void checkBeTop(void) { /*********************************************************************************************\ * Native functions mapped to Berry functions * + * log(msg:string [,log_level:int]) ->nil + * + * import tasmota + * + * tasmota.getfreeheap() -> int + * tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil + * tasmota.cmd(command:string) -> string + * tasmota.getoption(index:int) -> int + * tasmota.millis([delay:int]) -> int + * tasmota.timereached(timer:int) -> bool + * \*********************************************************************************************/ -// Berry: `log(string) -> nil` -// Logs the string at LOG_LEVEL_INFO (loglevel=2) -int32_t l_logInfo(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted - const char * msg = be_tostring(vm, 1); - AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "LOG: %s", msg); - be_return(vm); // Return +extern "C" { + // Berry: `log(msg:string [,log_level:int]) ->nil` + // Logs the string at LOG_LEVEL_INFO (loglevel=2) + int32_t l_logInfo(struct bvm *vm); + int32_t l_logInfo(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted + const char * msg = be_tostring(vm, 1); + uint32_t log_level = LOG_LEVEL_INFO; + if (top >= 2 && be_isint(vm, 2)) { + log_level = be_toint(vm, 2); + if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; } + } + AddLog(log_level, PSTR("%s"), msg); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `getFreeHeap() -> int` + // ESP object + int32_t l_getFreeHeap(bvm *vm); + int32_t l_getFreeHeap(bvm *vm) { + be_pushint(vm, ESP.getFreeHeap()); + be_return(vm); + } + + // Berry: `tasmota.publish(topic, payload [,retain]) -> nil`` + // + int32_t l_publish(struct bvm *vm); + int32_t l_publish(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { // 2 mandatory string arguments + if (top == 2 || (top == 3 && be_isbool(vm, 3))) { // 3rd optional argument must be bool + const char * topic = be_tostring(vm, 1); + const char * payload = be_tostring(vm, 2); + bool retain = false; + if (top == 3) { + retain = be_tobool(vm, 3); + } + strlcpy(TasmotaGlobal.mqtt_data, payload, sizeof(TasmotaGlobal.mqtt_data)); + MqttPublish(topic, retain); + be_return(vm); // Return + } + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `tasmota.cmd(command:string) -> string` + // + int32_t l_cmd(struct bvm *vm); + int32_t l_cmd(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted + const char * command = be_tostring(vm, 1); + ExecuteCommand(command, SRC_BERRY); + be_pushstring(vm, TasmotaGlobal.mqtt_data); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: tasmota.millis([delay:int]) -> int + // + int32_t l_millis(struct bvm *vm); + int32_t l_millis(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 0 || (top == 1 && be_isint(vm, 1))) { // only 1 argument of type string accepted + uint32_t delay = 0; + if (top == 1) { + delay = be_toint(vm, 1); + } + uint32_t ret_millis = millis() + delay; + be_pushint(vm, ret_millis); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: tasmota.getoption(index:int) -> int + // + int32_t l_getoption(struct bvm *vm); + int32_t l_getoption(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isint(vm, 1)) { + uint32_t opt = GetOption(be_toint(vm, 1)); + be_pushint(vm, opt); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: tasmota.timereached(timer:int) -> bool + // + int32_t l_timereached(struct bvm *vm); + int32_t l_timereached(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted + uint32_t timer = be_toint(vm, 1); + bool reached = TimeReached(timer); + be_pushbool(vm, reached); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong } - be_return_nil(vm); // Return nil when something goes wrong } -// Berry: `getFreeHeap() -> int` -// ESP object -int32_t l_getFreeHeap(bvm *vm) { - be_pushint(vm, ESP.getFreeHeap()); - be_return(vm); -} + // Berry: `printStack() -> nul` // print stack pointer @@ -128,7 +229,7 @@ int32_t l_getFreeHeap(bvm *vm) { // } // Yield -int32_t l_yield(bvm *vm) { +int32_t l_yield(struct bvm *vm) { #ifdef USE_BERRY_ASYNC if (berry.ta_cont_ok) { // if no ta_cont address, then ignore if (setjmp(berry.vm_cont) == 0) { // record the current state @@ -157,25 +258,80 @@ int32_t l_yield(bvm *vm) { // callBerryFunctionVoid(berry.fname); // } +bool callBerryRule(void) { + if (berry.rules_busy) { return false; } + berry.rules_busy = true; + char * json_event = TasmotaGlobal.mqtt_data; + bool serviced = false; + + checkBeTop(); + be_getglobal(berry.vm, "_exec_rules"); + if (!be_isnil(berry.vm, -1)) { + + // { + // String event_saved = TasmotaGlobal.mqtt_data; + // // json_event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} + // // json_event = {"System":{"Boot":1}} + // // json_event = {"SerialReceived":"on"} - invalid but will be expanded to {"SerialReceived":{"Data":"on"}} + // char *p = strchr(json_event, ':'); + // if ((p != NULL) && !(strchr(++p, ':'))) { // Find second colon + // event_saved.replace(F(":"), F(":{\"Data\":")); + // event_saved += F("}"); + // // event_saved = {"SerialReceived":{"Data":"on"}} + // } + // be_pushstring(berry.vm, event_saved.c_str()); + // } + be_pushstring(berry.vm, TasmotaGlobal.mqtt_data); + int ret = be_pcall(berry.vm, 1); + serviced = be_tobool(berry.vm, 1); + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Event (%s) serviced=%d"), TasmotaGlobal.mqtt_data, serviced); + be_pop(berry.vm, 2); // remove function object + } else { + be_pop(berry.vm, 1); // remove nil object + } + checkBeTop(); + berry.rules_busy = false; + + return serviced; // TODO event not handled +} + +// void callBerryMqttData(void) { +// AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "callBerryMqttData"); +// if (nullptr == berry.vm) { return; } +// if (XdrvMailbox.data_len < 1) { +// return; +// } +// const char * topic = XdrvMailbox.topic; +// const char * payload = XdrvMailbox.data; + +// checkBeTop(); +// be_getglobal(berry.vm, "mqtt_data_dispatch"); +// if (!be_isnil(berry.vm, -1)) { +// be_pushstring(berry.vm, topic); +// be_pushstring(berry.vm, payload); +// be_pcall(berry.vm, 0); +// be_pop(berry.vm, 3); // remove function object +// } else { +// be_pop(berry.vm, 1); // remove nil object +// } +// checkBeTop(); +// } + // call a function (if exists) of type void -> void void callBerryFunctionVoid(const char * fname) { if (nullptr == berry.vm) { return; } checkBeTop(); be_getglobal(berry.vm, fname); if (!be_isnil(berry.vm, -1)) { - // AddLog(LOG_LEVEL_DEBUG, D_LOG_BERRY "Calling '%s'", fname); be_pcall(berry.vm, 0); - be_pop(berry.vm, 1); // remove function object - } else { - // AddLog(LOG_LEVEL_DEBUG, D_LOG_BERRY "Function '%s' not found", fname); - be_pop(berry.vm, 1); // remove nil object } + be_pop(berry.vm, 1); // remove function or nil object checkBeTop(); } void test_input(void) { int i = 0; - AddLog(LOG_LEVEL_INFO, "test_input stack = 0x%08X", &i); + AddLog(LOG_LEVEL_INFO, PSTR("test_input stack = 0x%08X"), &i); callBerryFunctionVoid("noop"); } @@ -217,7 +373,7 @@ int32_t callTrampoline(void *func) { // ---------------------------------- // the call has completed normally, and `yield` was not called berry.ta_cont_ok = false; - AddLog(LOG_LEVEL_INFO, "Trampo: old stack restored"); + AddLog(LOG_LEVEL_INFO, PSTR("Trampo: old stack restored")); // printStack(); } else { // WARNING @@ -229,7 +385,7 @@ int32_t callTrampoline(void *func) { // printStack(); berry.ta_cont_ok = true; // Berry can call back Tasmota thread callBerryFunctionVoid("noop"); - AddLog(LOG_LEVEL_INFO, "Trampo: after callBerryFunctionVoid"); + AddLog(LOG_LEVEL_INFO, PSTR("Trampo: after callBerryFunctionVoid")); // printStack(); longjmp(berry.ta_cont, -1); // this part is unreachable (longjmp does not return) @@ -254,23 +410,153 @@ int32_t callTrampoline(void *func) { * \*********************************************************************************************/ -const char berry_prog[] = +const char berry_prog[] PROGMEM = + "" //"def func(x) for i:1..x print('a') end end " //"def testreal() return str(1.2+1) end " //"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end " //"log(\"foobar\") " - // - def l_getFreeHeap() return 1234 end - // - def l_log(m) print(m) end - // Simulate Tasmota module - "class Tasmota " - "def getFreeHeap() return l_getFreeHeap() end " - // "def log(m) return l_log(m) end " - "end " - "tasmota = Tasmota() " + // auto-import modules + "import string " + "import json " + "import gc " + "import tasmota " + // import alias + "import tasmota as t " - "n = 1;" - "def every_second() n = n + 1; if (n % 100 == 10) log('foobar '+str(n)+' free_heap = '+str(tasmota.getFreeHeap())) end end; " + // add `charsinstring(s:string,c:string) -> int`` + // looks for any char in c, and return the position of the first chat + // or -1 if not found + "def charsinstring(s,c) " + "for i:0..size(s)-1 " + "for j:0..size(c)-1 " + "if s[i] == c[j] return i end " + "end " + "end " + "return -1 " + "end " + + // find a key in map, case insensitive, return actual key or nil if not found + "def findkeyi(m,keyi) " + "keyu=string.toupper(keyi) " + "if classof(m) == map " + "for k:m.keys() " + "if string.toupper(k)==keyu || keyi=='?' " + "return k " + "end " + "end " + "end " + "end " + + // Rules + + "tasmota._operators='=<>!' " // operators used in rules + // Rules comparisong functions + "tasmota._eqstr=/s1,s2-> str(s1) == str(s2) " + "tasmota._neqstr=/s1,s2-> str(s1) != str(s2) " + "tasmota._eq=/f1,f2-> real(f1) == real(f2) " + "tasmota._neq=/f1,f2-> real(f1) != real(f2) " + "tasmota._gt=/f1,f2-> real(f1) > real(f2) " + "tasmota._lt=/f1,f2-> real(f1) < real(f2) " + "tasmota._ge=/f1,f2-> real(f1) >= real(f2) " + "tasmota._le=/f1,f2-> real(f1) <= real(f2) " + + "tasmota._op=[" + "['==',tasmota._eqstr]," + "['!==',tasmota._neqstr]," + "['=',tasmota._eq]," + "['!=',tasmota._neq]," + "['>=',tasmota._ge]," + "['<=',tasmota._le]," + "['>',tasmota._gt]," + "['<',tasmota._lt]," + "] " + "tasmota_rules={} " + "tasmota.rule = def(pat,f) tasmota_rules[pat] = f end " + + // # split the item when there is an operator, returns a list of (left,op,right) + // # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] + "tasmota.find_op = def (item) " + "pos = charsinstring(item, tasmota._operators) " + "if pos>=0 " + "op_split = string.split(item,pos) " + // #print(op_split) + "op_left = op_split[0] " + "op_rest = op_split[1] " + // # iterate through operators + "for op:tasmota._op " + "if string.find(op_rest,op[0]) == 0 " + "op_func = op[1] " + "op_right = string.split(op_rest,size(op[0]))[1] " + "return [op_left,op_func,op_right] " + "end " + "end " + "end " + "return [item, nil, nil] " + "end " + + // Rules trigger if match. return true if match, false if not + // Note: condition is not yet managed + "tasmota.try_rule = def (ev, rule, f) " + "rl_list = tasmota.find_op(rule) " + "e=ev " + "rl=string.split(rl_list[0],'#') " + "for it:rl " + "found=findkeyi(e,it) " + "if found == nil " + "return false " + "end " + "e=e[found] " + "end " + // # check if condition is true + "if rl_list[1] " + // # did we find a function + "if !rl_list[1](e,rl_list[2]) " + // # condition is not met + "return false " + "end " + "end " + "f(e,ev) " + "return true " + "end " + // Run rules, i.e. check each individual rule + // Returns true if at least one rule matched, false if none + "tasmota.exec_rules = def (ev_json) " + "ev = json.load(ev_json) " + "ret = false " + "if ev == nil " + "log('BRY: ERROR, bad json: '+ev_json, 3) " + "end " + "for r:tasmota_rules.keys() " + "ret = tasmota.try_rule(ev,r,tasmota_rules[r]) || ret " + "end " + "return ret " + "end " + // Not sure how to run `tasmota.exec_rules` from C code, so alias with `_exec_rules()`` + "def _exec_rules(e) return tasmota.exec_rules(e) end " + + // Timers + "tasmota_timers=[] " + "tasmota.timer = def (delay,f) tasmota_timers.push([tasmota.millis(delay),f]) end " + + "def _run_deferred() " + "i=0 " + "while ion("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); - // Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); - // Webserver->on("/exs", HTTP_POST,[]() { Webserver->sendHeader("Location","/exs");Webserver->send(303);}, script_upload_start); - // Webserver->on("/exs", HTTP_GET, ScriptExecuteUploadSuccess); break; #endif // USE_WEBSERVER case FUNC_SAVE_BEFORE_RESTART: - // if (bitRead(Settings.rule_enabled, 0)) { - // Run_Scripter(">R", 2, 0); - // Scripter_save_pvars(); - // } break; case FUNC_MQTT_DATA: + // callBerryMqttData(); break; case FUNC_WEB_SENSOR: break; @@ -542,5 +823,4 @@ bool Xdrv52(uint8_t function) return result; } -// #endif // ESP32 #endif // USE_BERRY diff --git a/tasmota/xdrv_interface.ino b/tasmota/xdrv_interface.ino index 77c93c6da..f95c0652f 100644 --- a/tasmota/xdrv_interface.ino +++ b/tasmota/xdrv_interface.ino @@ -1081,7 +1081,14 @@ void XsnsDriverState(void) bool XdrvRulesProcess(void) { +#ifdef USE_BERRY + // events are passed to both Rules engine AND Berry engine + bool rule_handled = XdrvCallDriver(10, FUNC_RULES_PROCESS); + bool berry_handled = XdrvCallDriver(52, FUNC_RULES_PROCESS); + return rule_handled || berry_handled; +#else return XdrvCallDriver(10, FUNC_RULES_PROCESS); +#endif } #ifdef USE_DEBUG_DRIVER