Berry improvements

This commit is contained in:
Stephan Hadinger 2021-02-28 20:50:37 +01:00
parent f91ca66a69
commit b613e1db37
25 changed files with 1335 additions and 1097 deletions

View File

@ -1,128 +1,111 @@
extern const bcstring be_const_str_calldepth;
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_type;
extern const bcstring be_const_str_if;
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_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_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_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_list;
extern const bcstring be_const_str_module;
extern const bcstring be_const_str_pop;
extern const bcstring be_const_str_int;
extern const bcstring be_const_str_push;
extern const bcstring be_const_str_setrange;
extern const bcstring be_const_str_sinh;
extern const bcstring be_const_str_elif;
extern const bcstring be_const_str_iter;
extern const bcstring be_const_str_load;
extern const bcstring be_const_str_class;
extern const bcstring be_const_str_if;
extern const bcstring be_const_str_opt_eq;
extern const bcstring be_const_str_ceil;
extern const bcstring be_const_str_floor;
extern const bcstring be_const_str_map;
extern const bcstring be_const_str_print;
extern const bcstring be_const_str_else;
extern const bcstring be_const_str_find;
extern const bcstring be_const_str_str;
extern const bcstring be_const_str___upper__;
extern const bcstring be_const_str_dump;
extern const bcstring be_const_str_atan;
extern const bcstring be_const_str_size;
extern const bcstring be_const_str_tolower;
extern const bcstring be_const_str_opt_add;
extern const bcstring be_const_str_abs;
extern const bcstring be_const_str_lower;
extern const bcstring be_const_str_end;
extern const bcstring be_const_str_import;
extern const bcstring be_const_str_classof;
extern const bcstring be_const_str_concat;
extern const bcstring be_const_str_byte;
extern const bcstring be_const_str_top;
extern const bcstring be_const_str_clear;
extern const bcstring be_const_str_opt_connect;
extern const bcstring be_const_str_collect;
extern const bcstring be_const_str_init;
extern const bcstring be_const_str_log10;
extern const bcstring be_const_str_nil;
extern const bcstring be_const_str_;
extern const bcstring be_const_str_real;
extern const bcstring be_const_str_calldepth;
extern const bcstring be_const_str_format;
extern const bcstring be_const_str_pi;
extern const bcstring be_const_str_do;
extern const bcstring be_const_str___iterator__;
extern const bcstring be_const_str_number;
extern const bcstring be_const_str_type;
extern const bcstring be_const_str_dot_p;
extern const bcstring be_const_str_traceback;
extern const bcstring be_const_str_as;
extern const bcstring be_const_str___lower__;
extern const bcstring be_const_str_exp;
extern const bcstring be_const_str_hex;
extern const bcstring be_const_str_char;
extern const bcstring be_const_str_split;
extern const bcstring be_const_str_toupper;
extern const bcstring be_const_str_deinit;
extern const bcstring be_const_str_tan;
extern const bcstring be_const_str_srand;
extern const bcstring be_const_str_imin;
extern const bcstring be_const_str_input;
extern const bcstring be_const_str_issubclass;
extern const bcstring be_const_str_tostring;
extern const bcstring be_const_str_break;
extern const bcstring be_const_str_insert;
extern const bcstring be_const_str_var;
extern const bcstring be_const_str_open;
extern const bcstring be_const_str_tanh;
extern const bcstring be_const_str_upper;
extern const bcstring be_const_str_allocated;
extern const bcstring be_const_str_rad;
extern const bcstring be_const_str_attrdump;
extern const bcstring be_const_str_copy;
extern const bcstring be_const_str_sqrt;
extern const bcstring be_const_str_for;
extern const bcstring be_const_str_raise;
extern const bcstring be_const_str_opt_neq;
extern const bcstring be_const_str_assert;
extern const bcstring be_const_str_item;
extern const bcstring be_const_str_reverse;
extern const bcstring be_const_str_sin;
extern const bcstring be_const_str_super;
extern const bcstring be_const_str_try;
extern const bcstring be_const_str_range;
extern const bcstring be_const_str_return;
extern const bcstring be_const_str_compile;
extern const bcstring be_const_str_false;
extern const bcstring be_const_str_resize;
extern const bcstring be_const_str_continue;
extern const bcstring be_const_str_log;
extern const bcstring be_const_str_true;
extern const bcstring be_const_str_while;
extern const bcstring be_const_str_pow;
extern const bcstring be_const_str_cos;
extern const bcstring be_const_str_count;
extern const bcstring be_const_str_remove;
extern const bcstring be_const_str_imax;
extern const bcstring be_const_str_rand;
extern const bcstring be_const_str_codedump;
extern const bcstring be_const_str_deg;
extern const bcstring be_const_str_keys;
extern const bcstring be_const_str_setitem;
extern const bcstring be_const_str_def;
extern const bcstring be_const_str_except;
extern const bcstring be_const_str_classname;
extern const bcstring be_const_str_isinstance;
extern const bcstring be_const_str_cosh;

View File

@ -1,190 +1,165 @@
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(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(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(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(asin, "asin", 4272848550u, 0, 4, &be_const_str_list);
be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_module);
be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_pop);
be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL);
be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_push);
be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_setrange);
be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_sinh);
be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_elif);
be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL);
be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_load);
be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_class);
be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_if);
be_define_const_str(if, "if", 959999494u, 50, 2, NULL);
be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_ceil);
be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, NULL);
be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_map);
be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_print);
be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_else);
be_define_const_str(else, "else", 3183434736u, 52, 4, NULL);
be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_str);
be_define_const_str(str, "str", 3259748752u, 0, 3, NULL);
be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_dump);
be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL);
be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_size);
be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_tolower);
be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL);
be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_abs);
be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_lower);
be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_end);
be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_import);
be_define_const_str(import, "import", 288002260u, 66, 6, NULL);
be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_concat);
be_define_const_str(concat, "concat", 4124019837u, 0, 6, NULL);
be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_top);
be_define_const_str(top, "top", 2802900028u, 0, 3, NULL);
be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL);
be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_collect);
be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_init);
be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_log10);
be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_nil);
be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL);
be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_real);
be_define_const_str(real, "real", 3604983901u, 0, 4, NULL);
be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_format);
be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pi);
be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_do);
be_define_const_str(do, "do", 1646057492u, 65, 2, NULL);
be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_number);
be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_type);
be_define_const_str(type, "type", 1361572173u, 0, 4, NULL);
be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_traceback);
be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_as);
be_define_const_str(as, "as", 1579491469u, 67, 2, NULL);
be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_exp);
be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_hex);
be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL);
be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_split);
be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_toupper);
be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL);
be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_tan);
be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL);
be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL);
be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_input);
be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_issubclass);
be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL);
be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, &be_const_str_break);
be_define_const_str(break, "break", 3378807160u, 58, 5, NULL);
be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_var);
be_define_const_str(var, "var", 2317739966u, 64, 3, NULL);
be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_tanh);
be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_upper);
be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL);
be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_rad);
be_define_const_str(rad, "rad", 1358899048u, 0, 3, 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_sqrt);
be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL);
be_define_const_str(for, "for", 2901640080u, 54, 3, &be_const_str_raise);
be_define_const_str(raise, "raise", 1593437475u, 70, 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_item);
be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_reverse);
be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin);
be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_super);
be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try);
be_define_const_str(try, "try", 2887626766u, 68, 3, NULL);
be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_return);
be_define_const_str(return, "return", 2246981567u, 60, 6, NULL);
be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_false);
be_define_const_str(false, "false", 184981848u, 62, 5, NULL);
be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL);
be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL);
be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_true);
be_define_const_str(true, "true", 1303515621u, 61, 4, NULL);
be_define_const_str(while, "while", 231090382u, 53, 5, NULL);
be_define_const_str(pow, "pow", 1479764693u, 0, 3, NULL);
be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_count);
be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_remove);
be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL);
be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_rand);
be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL);
be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_deg);
be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_keys);
be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_setitem);
be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL);
be_define_const_str(def, "def", 3310976652u, 55, 3, &be_const_str_except);
be_define_const_str(except, "except", 950914032u, 69, 6, NULL);
be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_isinstance);
be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL);
be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL);
static const bstring* const m_string_table[] = {
(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_abs,
(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_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_opt_neq,
(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__
NULL,
(const bstring *)&be_const_str_int,
NULL,
(const bstring *)&be_const_str_iter,
(const bstring *)&be_const_str_opt_eq,
(const bstring *)&be_const_str_floor,
(const bstring *)&be_const_str_find,
(const bstring *)&be_const_str___upper__,
(const bstring *)&be_const_str_atan,
(const bstring *)&be_const_str_opt_add,
NULL,
(const bstring *)&be_const_str_classof,
(const bstring *)&be_const_str_byte,
(const bstring *)&be_const_str_clear,
(const bstring *)&be_const_str_opt_connect,
(const bstring *)&be_const_str_,
(const bstring *)&be_const_str_calldepth,
(const bstring *)&be_const_str___iterator__,
(const bstring *)&be_const_str_dot_p,
(const bstring *)&be_const_str___lower__,
(const bstring *)&be_const_str_char,
(const bstring *)&be_const_str_deinit,
(const bstring *)&be_const_str_srand,
(const bstring *)&be_const_str_imin,
(const bstring *)&be_const_str_tostring,
(const bstring *)&be_const_str_insert,
(const bstring *)&be_const_str_open,
(const bstring *)&be_const_str_allocated,
(const bstring *)&be_const_str_attrdump,
(const bstring *)&be_const_str_for,
(const bstring *)&be_const_str_opt_neq,
(const bstring *)&be_const_str_range,
(const bstring *)&be_const_str_compile,
(const bstring *)&be_const_str_resize,
(const bstring *)&be_const_str_continue,
(const bstring *)&be_const_str_log,
(const bstring *)&be_const_str_while,
(const bstring *)&be_const_str_pow,
(const bstring *)&be_const_str_cos,
(const bstring *)&be_const_str_imax,
(const bstring *)&be_const_str_codedump,
(const bstring *)&be_const_str_def,
(const bstring *)&be_const_str_classname,
(const bstring *)&be_const_str_cosh
};
static const struct bconststrtab m_const_string_table = {
.size = 53,
.count = 107,
.size = 45,
.count = 90,
.table = m_string_table
};

View File

@ -1,19 +1,16 @@
#include "be_constobj.h"
static be_define_const_map_slots(m_libdebug_map) {
{ be_const_key(attrdump, -1), be_const_func(m_attrdump) },
{ be_const_key(upvname, -1), be_const_func(m_upvname) },
{ be_const_key(codedump, -1), be_const_func(m_codedump) },
{ be_const_key(top, -1), be_const_func(m_top) },
{ be_const_key(sethook, 3), be_const_func(m_sethook) },
{ be_const_key(varname, 7), be_const_func(m_varname) },
{ be_const_key(calldepth, -1), be_const_func(m_calldepth) },
{ be_const_key(traceback, -1), be_const_func(m_traceback) },
{ be_const_key(codedump, -1), be_const_func(m_codedump) },
{ be_const_key(calldepth, -1), be_const_func(m_calldepth) },
{ be_const_key(top, -1), be_const_func(m_top) },
{ be_const_key(attrdump, 0), be_const_func(m_attrdump) },
};
static be_define_const_map(
m_libdebug_map,
8
5
);
static be_define_const_module(

View File

@ -1,24 +1,2 @@
#include "be_constobj.h"
static be_define_const_map_slots(m_libos_map) {
{ be_const_key(listdir, 1), be_const_func(m_listdir) },
{ be_const_key(mkdir, -1), be_const_func(m_mkdir) },
{ be_const_key(chdir, -1), be_const_func(m_chdir) },
{ be_const_key(exit, 2), be_const_func(m_exit) },
{ be_const_key(system, -1), be_const_func(m_system) },
{ be_const_key(remove, 3), be_const_func(m_remove) },
{ be_const_key(path, -1), be_const_module(m_libpath) },
{ be_const_key(getcwd, -1), be_const_func(m_getcwd) },
};
static be_define_const_map(
m_libos_map,
8
);
static be_define_const_module(
m_libos,
"os"
);
BE_EXPORT_VARIABLE be_define_const_native_module(os, NULL);

View File

@ -0,0 +1,2 @@
#include "be_constobj.h"

View File

@ -1,17 +1,2 @@
#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, NULL);

View File

@ -1,19 +1,2 @@
#include "be_constobj.h"
static be_define_const_map_slots(m_libtime_map) {
{ be_const_key(dump, 1), be_const_func(m_dump) },
{ be_const_key(clock, -1), be_const_func(m_clock) },
{ be_const_key(time, 0), be_const_func(m_time) },
};
static be_define_const_map(
m_libtime_map,
3
);
static be_define_const_module(
m_libtime,
"time"
);
BE_EXPORT_VARIABLE be_define_const_native_module(time, NULL);

View File

@ -310,7 +310,7 @@ static void free_ntvclos(bvm *vm, bgcobject *obj)
while (count--) {
be_free(vm, *uv++, sizeof(bupval));
}
be_free(vm, f, sizeof(bntvclos));
be_free(vm, f, sizeof(bntvclos) + sizeof(bupval*) * f->nupvals);
}
}

View File

@ -13,7 +13,7 @@
#define BE_GCOBJECT BE_STRING
#define gc_object(o) cast(bgcobject*, o)
#define gc_cast(o, t, T) ((o) && pgm_read_byte(&(o)->type) == (t) ? (T*)(o) : NULL)
#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)
@ -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) ((pgm_read_byte(&(o)->marked) & GC_FIXED) != 0)
#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) ((pgm_read_byte(&(o)->marked) & GC_CONST) != 0)
#define gc_exmark(o) ((pgm_read_byte(&(o)->marked) >> 4) & 0x0F)
#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)

View File

@ -105,8 +105,7 @@ static int next(blexer *lexer)
lr->s = s ? s : &eos;
--lr->len;
}
// lexer->cursor = *lr->s++; // SH
lexer->cursor = pgm_read_byte(lr->s++);
lexer->cursor = *lr->s++;
return lexer->cursor;
}

View File

@ -10,37 +10,6 @@
#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 */

View File

@ -31,7 +31,7 @@
#define FUNC_ANONYMOUS 2
/* get binary operator priority */
#define binary_op_prio(op) (pgm_read_byte(&binary_op_prio_tab[cast_int(op) - OptAdd]))
#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)

View File

@ -44,9 +44,9 @@ int be_eqstr(bstring *s1, bstring *s2)
if (s1 == s2) { /* short string or the same string */
return 1;
}
slen = pgm_read_byte(&s1->slen);
slen = s1->slen;
/* long string */
if (slen == 255 && slen == pgm_read_byte(&s2->slen)) {
if (slen == 255 && slen == 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) + pgm_read_byte(&str->slen) + 1);
be_free(vm, str, sizeof(bsstring) + str->slen + 1);
}
/* FNV-1a Hash */
@ -97,8 +97,7 @@ 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)pgm_read_byte(str)) * 16777619u;
str++;
hash = (hash ^ (unsigned char)*str++) * 16777619u;
}
return hash;
}
@ -150,7 +149,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 == pgm_read_byte(&s->slen) && !strncmp(str, s->s, len)) {
if (len == s->slen && !strncmp(str, s->s, len)) {
return (bstring*)s;
}
}
@ -166,7 +165,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 == pgm_read_byte(&s->slen) && !strncmp(str, sstr(s), len)) {
if (len == s->slen && !strncmp(str, sstr(s), len)) {
return s;
}
}
@ -253,7 +252,7 @@ uint32_t be_strhash(const bstring *s)
return cast(bcstring*, s)->hash;
}
#if BE_USE_STR_HASH_CACHE
if (pgm_read_byte(&s->slen) != 255) {
if (s->slen != 255) {
return cast(bsstring*, s)->hash;
}
#endif
@ -266,7 +265,7 @@ const char* be_str2cstr(const bstring *s)
if (gc_isconst(s)) {
return cstr(s);
}
if (pgm_read_byte(&s->slen) == 255) {
if (s->slen == 255) {
return lstr(s);
}
return sstr(s);
@ -277,4 +276,4 @@ void be_str_setextra(bstring *s, int extra)
if (!gc_isconst(s)) {
s->extra = cast(bbyte, extra);
}
}
}

View File

@ -33,7 +33,7 @@ typedef struct {
} bcstring;
#define str_len(_s) \
(pgm_read_byte(&(_s)->slen) == 255 ? cast(blstring*, _s)->llen : pgm_read_byte(&(_s)->slen))
((_s)->slen == 255 ? cast(blstring*, _s)->llen : (_s)->slen)
#define str(_s) be_str2cstr(_s)
#define str_extra(_s) ((_s)->extra)

View File

@ -176,7 +176,7 @@ const char* be_pushvfstr(bvm *vm, const char *format, va_list arg)
}
pushstr(vm, format, p - format);
concat2(vm);
switch (pgm_read_byte(&p[1])) {
switch (p[1]) {
case 's': {
const char *s = va_arg(arg, char*);
if (s == NULL) {
@ -339,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; pgm_read_byte(path) != '\0'; ++path) {
if (pgm_read_byte(path) == '/') {
for (p = path - 1; *path != '\0'; ++path) {
if (*path == '/') {
p = path;
}
}

View File

@ -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 (pgm_read_word(mid) == value) {
return pgm_read_word(&mid[1]);
if (*mid == value) {
return mid[1];
}
if (pgm_read_word(mid) < value) {
if (*mid < value) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return pgm_read_word(low);
return *low;
}
static int nextpow(int value)

View File

@ -20,7 +20,8 @@ be_extern_native_module(debug);
be_extern_native_module(gc);
/* Tasmota specific */
be_extern_native_module(tasmota);
be_extern_native_module(tasmota_ntv);
be_extern_native_module(wire);
/* user-defined modules declare start */
@ -55,7 +56,8 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
#endif
/* user-defined modules register start */
&be_native_module(tasmota),
&be_native_module(tasmota_ntv),
&be_native_module(wire),
/* user-defined modules register end */
NULL /* do not remove */

View File

@ -13,9 +13,16 @@ extern int l_millis(bvm *vm);
extern int l_timereached(bvm *vm);
extern int l_yield(bvm *vm);
extern int l_respCmnd(bvm *vm);
extern int l_respCmndStr(bvm *vm);
extern int l_respCmndDone(bvm *vm);
extern int l_respCmndError(bvm *vm);
extern int l_respCmndFailed(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_attr_table(tasmota_ntv) {
be_native_module_function("getfreeheap", l_getFreeHeap),
be_native_module_function("publish", l_publish),
be_native_module_function("cmd", l_cmd),
@ -23,9 +30,17 @@ be_native_module_attr_table(tasmota) {
be_native_module_function("millis", l_millis),
be_native_module_function("timereached", l_timereached),
be_native_module_function("yield", l_yield),
be_native_module_function("respcmnd", l_respCmnd),
be_native_module_function("respcmndstr", l_respCmndStr),
be_native_module_function("respcmnd_done", l_respCmndDone),
be_native_module_function("respcmnd_error", l_respCmndError),
be_native_module_function("respcmnd_failed", l_respCmndFailed),
be_native_module_str("_operators", "=<>!|"),
};
be_define_native_module(tasmota, NULL);
be_define_native_module(tasmota_ntv, NULL);
#else
/* @const_object_info_begin
module tasmota (scope: global, depend: 1) {

View File

@ -0,0 +1,36 @@
/********************************************************************
* Tasmota lib
*
* To use: `import wire`
*
* 2 wire communication - I2C
*******************************************************************/
#include "be_object.h"
extern int b_wire_begintransmission(bvm *vm);
extern int b_wire_endtransmission(bvm *vm);
extern int b_wire_requestfrom(bvm *vm);
extern int b_wire_available(bvm *vm);
extern int b_wire_write(bvm *vm);
extern int b_wire_read(bvm *vm);
// #if !BE_USE_PRECOMPILED_OBJECT
#if 1 // TODO we will do pre-compiled later
be_native_module_attr_table(wire) {
be_native_module_function("begintransmission", b_wire_begintransmission),
be_native_module_function("endtransmission", b_wire_endtransmission),
be_native_module_function("requestfrom", b_wire_requestfrom),
be_native_module_function("available", b_wire_available),
be_native_module_function("write", b_wire_write),
be_native_module_function("read", b_wire_read),
};
be_define_native_module(wire, 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

View File

@ -8,19 +8,6 @@
#ifndef BERRY_CONF_H
#define BERRY_CONF_H
#include <pgmspace.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int strncmp_PP(const char * str1P, const char * str2P, size_t size);
extern char * strchr_P(const char *s, int c);
#ifdef __cplusplus
}
#endif
#include <assert.h>
/* Macro: BE_DEBUG
@ -53,12 +40,12 @@ extern "C" {
* Use precompiled objects to avoid creating these objects at
* runtime. Enable this macro can greatly optimize RAM usage.
* Default: 1
**/
#ifdef ESP8266
#define BE_USE_PRECOMPILED_OBJECT 0
#else
#define BE_USE_PRECOMPILED_OBJECT 0 // will enable later when stabilized
#endif
// **/
// #ifdef ESP8266
// #define BE_USE_PRECOMPILED_OBJECT 0
// #else
#define BE_USE_PRECOMPILED_OBJECT 1 // will enable later when stabilized
// #endif
/* Macro: BE_DEBUG_RUNTIME_INFO
* Set runtime error debugging information.

View File

@ -20,6 +20,26 @@ def charsinstring(s,c)
return -1
end
###
class Tasmota
var _op, _operators, _rules
def init()
self._operators = "=<>!|"
self._op = [
['==', /s1,s2-> str(s1) == str(s2)],
['!==',/s1,s2-> str(s1) != str(s2)],
['=', /f1,f2-> real(f1) == real(f2)],
['!=', /f1,f2-> real(f1) != real(f2)],
['>=', /f1,f2-> real(f1) >= real(f2)],
['<=', /f1,f2-> real(f1) <= real(f2)],
['>', /f1,f2-> real(f1) > real(f2)],
['<', /f1,f2-> real(f1) < real(f2)],
]
self._rules = {}
end
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)

View File

@ -0,0 +1,323 @@
/*
xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#include <berry.h>
#include <Wire.h>
/*********************************************************************************************\
* 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
* tasmota.yield() -> nil
*
\*********************************************************************************************/
extern "C" {
// 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
}
// Berry: `yield() -> nil`
// ESP object
int32_t l_yield(bvm *vm);
int32_t l_yield(bvm *vm) {
optimistic_yield(10);
be_return(vm);
}
// Berry: `save(file:string, f:closure) -> bool`
int32_t l_save(struct bvm *vm);
int32_t l_save(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top ==2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted
const char *fname = be_tostring(vm, 1);
int32_t ret = be_savecode(vm, fname);
be_pushint(vm, ret);
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
int32_t l_respCmnd(bvm *vm);
int32_t l_respCmnd(bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top == 1) {
const char *msg = be_tostring(vm, 1);
Response_P("%s", msg);
}
be_return_nil(vm); // Return nil when something goes wrong
}
int32_t l_respCmndStr(bvm *vm);
int32_t l_respCmndStr(bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top == 1) {
const char *msg = be_tostring(vm, 1);
ResponseCmndChar(msg);
}
be_return_nil(vm); // Return nil when something goes wrong
}
int32_t l_respCmndDone(bvm *vm);
int32_t l_respCmndDone(bvm *vm) {
ResponseCmndDone();
be_return_nil(vm);
}
int32_t l_respCmndError(bvm *vm);
int32_t l_respCmndError(bvm *vm) {
ResponseCmndError();
be_return_nil(vm);
}
int32_t l_respCmndFailed(bvm *vm);
int32_t l_respCmndFailed(bvm *vm) {
ResponseCmndFailed();
be_return_nil(vm);
}
}
/*********************************************************************************************\
* Native functions mapped to Berry functions
*
* import wire
*
* wire.getfreeheap() -> int
*
\*********************************************************************************************/
extern "C" {
// Berry: `begintransmission(address:int) -> nil`
int32_t b_wire_begintransmission(struct bvm *vm);
int32_t b_wire_begintransmission(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
int32_t address = be_toint(vm, 1);
Wire.beginTransmission(address);
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
// Berry: `endtransmission([stop:bool]) -> nil`
int32_t b_wire_endtransmission(struct bvm *vm);
int32_t b_wire_endtransmission(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top == 0 || (top == 1 && be_isbool(vm, 1))) { // only 1 argument of type string accepted
bool stop = true;
if (top == 1) {
stop = be_tobool(vm, 1);
}
uint32_t ret = Wire.endTransmission(stop);
be_pushint(vm, ret);
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
// Berry: `requestfrom(address:int, quantity:int [stop:bool = true]) -> nil`
int32_t b_wire_requestfrom(struct bvm *vm);
int32_t b_wire_requestfrom(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if ( (top == 2 || (top == 3 && be_isbool(vm, 3)))
&& be_isint(vm, 1) && be_isint(vm, 2) ) {
int32_t address = be_toint(vm, 1);
int32_t quantity = be_toint(vm, 2);
bool stop = true;
if (top == 3) {
stop = be_tobool(vm, 3);
}
Wire.requestFrom((uint16_t)address, (uint8_t)quantity, stop);
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
// Berry: `available() -> bool`
int32_t b_wire_available(struct bvm *vm);
int32_t b_wire_available(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top == 0) {
size_t available = Wire.available();
be_pushint(vm, available);
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
// Berry: `write(value:int | s:string) -> nil`
int32_t b_wire_write(struct bvm *vm);
int32_t b_wire_write(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top == 1 && (be_isint(vm, 1) || be_isint(vm, 1))) {
if (be_isint(vm, 1)) {
int32_t value = be_toint(vm, 1);
Wire.write(value);
} else if (be_isstring(vm, 1)) {
const char * s = be_tostring(vm, 1);
Wire.write(s);
} else {
be_return_nil(vm);
}
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
// Berry: `read() -> int`
int32_t b_wire_read(struct bvm *vm);
int32_t b_wire_read(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top == 0) {
int32_t value = Wire.read();
be_pushint(vm, value);
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
}
/*********************************************************************************************\
* Native functions mapped to Berry functions
*
* log(msg:string [,log_level:int]) ->nil
*
\*********************************************************************************************/
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);
}
}
// called as a replacement to Berry `print()`
void berry_log(const char * berry_buf);
void berry_log(const char * berry_buf) {
AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf);
}
#endif // USE_BERRY

View File

@ -0,0 +1,281 @@
/*
xdrv_52_3_berry_embedded.ino - Berry scripting language, embedded code
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
/*********************************************************************************************\
* Handlers for Berry calls and async
*
\*********************************************************************************************/
const char berry_prog[] =
""
//"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\") "
// auto-import modules
// // import alias
"import wire "
// Phase 1
// Prepare the super class that will be eventually in Flash
"class Tasmota_ntv "
"var _op, _operators, _rules, _timers, _cmd "
// Map all native functions to methods
// Again, this will be eventually pre-compiled
"var getfreeheap, publish, cmd, getoption, millis, timereached, yield "
"var respcmnd, respcmndstr, respcmnd_done, respcmnd_error, respcmnd_failed "
"def init_ntv() "
"import tasmota_ntv "
"self.getfreeheap = tasmota_ntv.getfreeheap "
"self.publish = tasmota_ntv.publish "
"self.cmd = tasmota_ntv.cmd "
"self.getoption = tasmota_ntv.getoption "
"self.millis = tasmota_ntv.millis "
"self.timereached = tasmota_ntv.timereached "
"self.yield = tasmota_ntv.yield "
"self._operators = tasmota_ntv._operators "
"self.respcmnd = tasmota_ntv.respcmnd "
"self.respcmndstr = tasmota_ntv.respcmndstr "
"self.respcmnd_done = tasmota_ntv.respcmnd_done "
"self.respcmnd_error = tasmota_ntv.respcmnd_error "
"self.respcmnd_failed = tasmota_ntv.respcmnd_failed "
"end "
"def init() "
"self._op = [ "
"['==', /s1,s2-> str(s1) == str(s2)],"
"['!==',/s1,s2-> str(s1) != str(s2)],"
"['=', /f1,f2-> real(f1) == real(f2)],"
"['!=', /f1,f2-> real(f1) != real(f2)],"
"['>=', /f1,f2-> real(f1) >= real(f2)],"
"['<=', /f1,f2-> real(f1) <= real(f2)],"
"['>', /f1,f2-> real(f1) > real(f2)],"
"['<', /f1,f2-> real(f1) < real(f2)],"
"] "
"self._rules = {} "
"self._timers = [] "
"self._cmd = {} "
"self.init_ntv() "
"end "
"end "
"class Tasmota: Tasmota_ntv "
// 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) "
"import string "
"var 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
"def addrule(pat,f) self._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"]
"def find_op(item) "
"import string "
"var pos = self.charsinstring(item, self._operators) "
"if pos>=0 "
"var op_split = string.split(item,pos) "
// #print(op_split)
"var op_left = op_split[0] "
"var op_rest = op_split[1] "
// # iterate through operators
"for op: self._op "
"if string.find(op_rest,op[0]) == 0 "
"var op_func = op[1] "
"var 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
"def try_rule(ev, rule, f) "
"import string "
"var rl_list = self.find_op(rule) "
"var e=ev "
"var rl=string.split(rl_list[0],'#') "
"for it:rl "
"found=self.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
"def exec_rules(ev_json) "
"import json "
"var ev = json.load(ev_json) "
"var ret = false "
"if ev == nil "
"print('BRY: ERROR, bad json: '+ev_json, 3) "
"else "
"for r: self._rules.keys() "
"ret = self.try_rule(ev,r,self._rules[r]) || ret "
"end "
"end "
"return ret "
"end "
"def settimer(delay,f) self._timers.push([self.millis(delay),f]) end "
"def run_deferred() "
"var i=0 "
"while i<self._timers.size() "
"if self.timereached(self._timers[i][0]) "
"f=self._timers[i][1] "
"self._timers.remove(i) "
"f() "
"else "
"i=i+1 "
"end "
"end "
"end "
// Delay function, internally calls yield() every 10ms to avoid WDT
"def delay(ms) "
"var tend = self.millis(ms) "
"while !self.timereached(tend) "
"self.yield() "
"end "
"end "
// Add command to list
"def addcommand(c,f) "
"self._cmd[c]=f "
"end "
"def exec_cmd(cmd, idx, payload) "
"import json "
"var payload_json = json.load(payload) "
"var cmd_found = self.findkeyi(self._cmd, cmd) "
"if cmd_found != nil "
"return self._cmd[cmd_found](cmd_found, idx, payload, payload_json) "
"end "
"end "
// Force gc and return allocated memory
"def gc() "
"import gc "
"gc.collect() "
"return gc.allocated() "
"end "
"end "
// Instantiate tasmota object
"tasmota = Tasmota() "
// Not sure how to run call methods from C
"def _exec_rules(e) return tasmota.exec_rules(e) end "
"def _run_deferred() return tasmota.run_deferred() end "
"def _exec_cmd(cmd, idx, payload) return tasmota.exec_cmd(cmd, idx, payload) end "
"def _gc() return tasmota.gc() end "
// simple wrapper to load a file
// prefixes '/' if needed, and simpler to use than `compile()`
"def load(f) "
"import string "
"try "
// check that the file ends with '.be' of '.bec'
"var fl = string.split(f,'.') "
"if (size(fl) <= 1 || (fl[-1] != 'be' && fl[-1] != 'bec')) "
"raise \"file extension is not '.be' or '.bec'\" "
"end "
"var native = f[size(f)-1] == 'c' "
// add prefix if needed
"if f[0] != '/' f = '/' + f end "
// load - works the same for .be and .bec
"var c = compile(f,'file') "
// save the compiled bytecode
"if !native "
"save(f+'c', c) "
"end "
// call the compiled code
"c() "
"except .. as e "
"log(string.format(\"BRY: could not load file '%s' - %s\",f,e)) "
"end "
"end "
// try to load "/autoexec.be"
// "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end "
// Wire
"wire.validread = def(addr, reg, size) "
"var ret = nil "
"for i:0..2 "
"wire.begintransmission(addr) "
"wire.write(reg) "
"if wire.endtransmission(false) == 0 "
"wire.requestfrom(addr, size) "
"if wire.available() == size "
"for j:0..size-1 "
"ret = ((ret != nil ? ret : 0) << 8) + wire.read() "
"end "
"return ret "
"end "
"end "
"end "
"wire.endtransmission() "
"end "
;
#endif // USE_BERRY

354
tasmota/xdrv_52_9_berry.ino Normal file
View File

@ -0,0 +1,354 @@
/*
xdrv_52_9_berry.ino - Berry scripting language
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#define XDRV_52 52
#include <berry.h>
const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix
D_CMND_BR_RUN "|" D_CMND_BR_RESET
;
void (* const BerryCommand[])(void) PROGMEM = {
CmndBrRun, CmndBrReset,
};
class BerrySupport {
public:
bvm *vm = nullptr; // berry vm
bool rules_busy = false; // are we already processing rules, avoid infinite loop
const char *fname = nullptr; // name of berry function to call
int32_t fret = 0;
};
BerrySupport berry;
//
// Sanity Check for be_top()
//
// Checks that the Berry stack is empty, if not print a Warning and empty it
//
void checkBeTop(void) {
int32_t top = be_top(berry.vm);
if (top != 0) {
be_pop(berry.vm, top); // TODO should not be there
AddLog(LOG_LEVEL_ERROR, D_LOG_BERRY "Error be_top is non zero=%d", top);
}
}
/*********************************************************************************************\
* Handlers for Berry calls and async
*
\*********************************************************************************************/
// // call a function (if exists) of type void -> void
// void callBerryFunctionVoid_berry(const char * fname) {
// berry.fret = 0;
// 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
}
bool callBerryCommand(void) {
const char * command = nullptr;
checkBeTop();
be_getglobal(berry.vm, "_exec_cmd");
if (!be_isnil(berry.vm, -1)) {
be_pushstring(berry.vm, XdrvMailbox.topic);
be_pushint(berry.vm, XdrvMailbox.index);
be_pushstring(berry.vm, XdrvMailbox.data);
int ret = be_pcall(berry.vm, 3);
command = be_tostring(berry.vm, 3);
strlcpy(XdrvMailbox.topic, command, CMDSZ);
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Command (%s) serviced=%d"), XdrvMailbox.command, serviced);
be_pop(berry.vm, 4); // remove function object
} else {
be_pop(berry.vm, 1); // remove nil object
}
checkBeTop();
return command != nullptr; // TODO event not handled
}
size_t callBerryGC(void) {
size_t ram_used = 0;
checkBeTop();
be_getglobal(berry.vm, "_gc");
if (!be_isnil(berry.vm, -1)) {
int ret = be_pcall(berry.vm, 0);
ram_used = be_toint(berry.vm, 1);
be_pop(berry.vm, 1); // remove function object
} else {
be_pop(berry.vm, 1); // remove nil object
}
checkBeTop();
return ram_used;
}
// 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)) {
be_pcall(berry.vm, 0);
}
be_pop(berry.vm, 1); // remove function or nil object
checkBeTop();
}
/*********************************************************************************************\
* VM Init
\*********************************************************************************************/
extern "C" {
extern size_t be_gc_memcount(bvm *vm);
extern void be_gc_collect(bvm *vm);
}
void BrReset(void) {
// clean previous VM if any
if (berry.vm != nullptr) {
be_vm_delete(berry.vm);
berry.vm = nullptr;
}
int32_t ret_code1, ret_code2;
bool berry_init_ok = false;
do {
berry.vm = be_vm_new(); /* create a virtual machine instance */
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry VM created, RAM used=%u"), be_gc_memcount(berry.vm));
// Register functions
be_regfunc(berry.vm, PSTR("log"), l_logInfo);
be_regfunc(berry.vm, PSTR("save"), l_save);
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry function registered, RAM used=%u"), be_gc_memcount(berry.vm));
ret_code1 = be_loadstring(berry.vm, berry_prog);
if (ret_code1 != 0) {
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_loadstring [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
be_pop(berry.vm, 2);
break;
}
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code loaded, RAM used=%u"), be_gc_memcount(berry.vm));
ret_code2 = be_pcall(berry.vm, 0);
if (ret_code1 != 0) {
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
be_pop(berry.vm, 2);
break;
}
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm));
be_pop(berry.vm, 1);
be_gc_collect(berry.vm);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM used=%u"), callBerryGC());
// AddLog(LOG_LEVEL_INFO, PSTR("Delete Berry VM"));
// be_vm_delete(vm);
// AddLog(LOG_LEVEL_INFO, PSTR("After Berry"));
berry_init_ok = true;
} while (0);
if (!berry_init_ok) {
// free resources
if (berry.vm != nullptr) {
be_vm_delete(berry.vm);
berry.vm = nullptr;
}
}
}
/*********************************************************************************************\
* Tasmota Commands
\*********************************************************************************************/
//
// Command `BrRun`
//
void CmndBrRun(void) {
int32_t ret_code;
const char * ret_type, * ret_val;
if (berry.vm == nullptr) { ResponseCmndChar_P(PSTR(D_BR_NOT_STARTED)); return; }
char br_cmd[XdrvMailbox.data_len+12];
// encapsulate into a function, copied from `be_repl.c` / `try_return()`
snprintf_P(br_cmd, sizeof(br_cmd), PSTR("return (%s)"), XdrvMailbox.data);
checkBeTop();
do {
// First try with the `return ()` wrapper
ret_code = be_loadbuffer(berry.vm, PSTR("input"), br_cmd, strlen(br_cmd));
if (be_getexcept(berry.vm, ret_code) == BE_SYNTAX_ERROR) {
be_pop(berry.vm, 2); // remove exception values
// if fails, try the direct command
ret_code = be_loadbuffer(berry.vm, PSTR("input"), XdrvMailbox.data, strlen(XdrvMailbox.data));
}
if (0 != ret_code) break;
ret_code = be_pcall(berry.vm, 0); // execute code
} while (0);
if (0 == ret_code) {
// code taken from REPL, look first at top, and if nil, look at return value
if (be_isnil(berry.vm, 0)) {
ret_val = be_tostring(berry.vm, -1);
} else {
ret_val = be_tostring(berry.vm, 0);
}
Response_P("{\"" D_PRFX_BR "\":\"%s\"}", ret_val); // can't use XdrvMailbox.command as it may have been overwritten by subcommand
be_pop(berry.vm, 1);
} else {
Response_P(PSTR("{\"" D_PRFX_BR "\":\"[%s] %s\"}"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
be_pop(berry.vm, 2);
}
checkBeTop();
}
//
// Command `BrReset`
//
void CmndBrReset(void) {
if (berry.vm == nullptr) { ResponseCmndChar_P(PSTR(D_BR_NOT_STARTED)); return; }
BrReset();
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv52(uint8_t function)
{
bool result = false;
switch (function) {
//case FUNC_PRE_INIT:
case FUNC_INIT:
BrReset();
break;
case FUNC_EVERY_50_MSECOND:
callBerryFunctionVoid(PSTR("_run_deferred"));
break;
case FUNC_EVERY_100_MSECOND:
callBerryFunctionVoid(PSTR("every_100ms"));
break;
case FUNC_EVERY_SECOND:
callBerryFunctionVoid(PSTR("every_second"));
break;
case FUNC_COMMAND:
result = DecodeCommand(kBrCommands, BerryCommand);
if (!result) {
result = callBerryCommand();
}
break;
// case FUNC_SET_POWER:
// break;
case FUNC_RULES_PROCESS:
result = callBerryRule();
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_ADD_BUTTON:
break;
case FUNC_WEB_ADD_MAIN_BUTTON:
break;
case FUNC_WEB_ADD_HANDLER:
break;
#endif // USE_WEBSERVER
case FUNC_SAVE_BEFORE_RESTART:
break;
case FUNC_MQTT_DATA:
// callBerryMqttData();
break;
case FUNC_WEB_SENSOR:
break;
case FUNC_JSON_APPEND:
break;
case FUNC_BUTTON_PRESSED:
break;
case FUNC_LOOP:
break;
}
return result;
}
#endif // USE_BERRY

View File

@ -1,650 +0,0 @@
/*
xdrv_52_berry.ino - Berry scripting language
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#define XDRV_52 52
#include <berry.h>
#include <csetjmp>
const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix
D_CMND_BR_RUN "|" D_CMND_BR_RESET
;
void (* const BerryCommand[])(void) PROGMEM = {
CmndBrRun, CmndBrReset,
};
class BerrySupport {
public:
bvm *vm = nullptr; // berry vm
bool rules_busy = false; // are we already processing rules, avoid infinite loop
const char *fname = nullptr; // name of berry function to call
int32_t fret = 0;
};
BerrySupport berry;
//
// Sanity Check for be_top()
//
// Checks that the Berry stack is empty, if not print a Warning and empty it
//
void checkBeTop(void) {
int32_t top = be_top(berry.vm);
if (top != 0) {
be_pop(berry.vm, top); // TODO should not be there
AddLog(LOG_LEVEL_ERROR, D_LOG_BERRY "Error be_top is non zero=%d", top);
}
}
/*********************************************************************************************\
* 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
* tasmota.yield() -> nil
*
\*********************************************************************************************/
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
}
// Berry: `yield() -> nil`
// ESP object
int32_t l_yield(bvm *vm);
int32_t l_yield(bvm *vm) {
optimistic_yield(10);
be_return(vm);
}
// Berry: `save(file:string, f:closure) -> bool`
int32_t l_save(struct bvm *vm);
int32_t l_save(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top ==2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted
const char *fname = be_tostring(vm, 1);
int32_t ret = be_savecode(vm, fname);
be_pushint(vm, ret);
be_return(vm); // Return
}
be_return_nil(vm); // Return nil when something goes wrong
}
}
// called as a replacement to Berry `print()`
void berry_log(const char * berry_buf);
void berry_log(const char * berry_buf) {
AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf);
}
/*********************************************************************************************\
* Handlers for Berry calls and async
*
\*********************************************************************************************/
// // call a function (if exists) of type void -> void
// void callBerryFunctionVoid_berry(const char * fname) {
// berry.fret = 0;
// 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)) {
be_pcall(berry.vm, 0);
}
be_pop(berry.vm, 1); // remove function or nil object
checkBeTop();
}
/*********************************************************************************************\
* Handlers for Berry calls and async
*
\*********************************************************************************************/
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\") "
// auto-import modules
"import string "
"import json "
"import gc "
"import tasmota "
// import alias
"import tasmota as t "
// 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) "
"var 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) "
"var pos = charsinstring(item, tasmota._operators) "
"if pos>=0 "
"var op_split = string.split(item,pos) "
// #print(op_split)
"var op_left = op_split[0] "
"var op_rest = op_split[1] "
// # iterate through operators
"for op:tasmota._op "
"if string.find(op_rest,op[0]) == 0 "
"var op_func = op[1] "
"var 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) "
"var rl_list = tasmota.find_op(rule) "
"var e=ev "
"var 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) "
"var ev = json.load(ev_json) "
"var 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() "
"var i=0 "
"while i<tasmota_timers.size() "
"if tasmota.timereached(tasmota_timers[i][0]) "
"f=tasmota_timers[i][1] "
"tasmota_timers.remove(i) "
"f() "
"else "
"i=i+1 "
"end "
"end "
"end "
// Delay function, internally calls yield() every 10ms to avoid WDT
"tasmota.delay = def(ms) "
"var tend = tasmota.millis(ms) "
"while !tasmota.timereached(tend) "
"tasmota.yield() "
"end "
"end "
// simple wrapper to load a file
// prefixes '/' if needed, and simpler to use than `compile()`
"def load(f) "
"try "
// check that the file ends with '.be' of '.bec'
"var fl = string.split(f,'.') "
"if (size(fl) <= 1 || (fl[-1] != 'be' && fl[-1] != 'bec')) "
"raise \"file extension is not '.be' or '.bec'\" "
"end "
"var native = f[size(f)-1] == 'c' "
// add prefix if needed
"if f[0] != '/' f = '/' + f end "
// load - works the same for .be and .bec
"var c = compile(f,'file') "
// save the compiled bytecode
"if !native "
"save(f+'c', c) "
"end "
// call the compiled code
"c() "
"except .. as e "
"log(string.format(\"BRY: could not load file '%s' - %s\",f,e)) "
"end "
"end "
// try to load "/autoexec.be"
// "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end "
// trigger Garbage Collector
"gc.collect() "
;
/*********************************************************************************************\
* VM Init
\*********************************************************************************************/
void BrReset(void) {
// clean previous VM if any
if (berry.vm != nullptr) {
be_vm_delete(berry.vm);
berry.vm = nullptr;
}
int32_t ret_code1, ret_code2;
bool berry_init_ok = false;
do {
uint32_t heap_before = ESP.getFreeHeap();
berry.vm = be_vm_new(); /* create a virtual machine instance */
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry VM created, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
// Register functions
be_regfunc(berry.vm, PSTR("log"), l_logInfo);
be_regfunc(berry.vm, PSTR("save"), l_save);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry function registered, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
ret_code1 = be_loadstring(berry.vm, berry_prog);
if (ret_code1 != 0) {
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_loadstring [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
be_pop(berry.vm, 2);
break;
}
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code loaded, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
ret_code2 = be_pcall(berry.vm, 0);
if (ret_code1 != 0) {
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
be_pop(berry.vm, 2);
break;
}
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
be_pop(berry.vm, 1);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
// AddLog(LOG_LEVEL_INFO, PSTR("Delete Berry VM"));
// be_vm_delete(vm);
// AddLog(LOG_LEVEL_INFO, PSTR("After Berry"));
berry_init_ok = true;
} while (0);
if (!berry_init_ok) {
// free resources
if (berry.vm != nullptr) {
be_vm_delete(berry.vm);
berry.vm = nullptr;
}
}
}
/*********************************************************************************************\
* Tasmota Commands
\*********************************************************************************************/
//
// Command `BrRun`
//
void CmndBrRun(void) {
int32_t ret_code;
const char * ret_type, * ret_val;
if (berry.vm == nullptr) { ResponseCmndChar_P(PSTR(D_BR_NOT_STARTED)); return; }
char br_cmd[XdrvMailbox.data_len+12];
// encapsulate into a function, copied from `be_repl.c` / `try_return()`
snprintf_P(br_cmd, sizeof(br_cmd), PSTR("return (%s)"), XdrvMailbox.data);
checkBeTop();
do {
// First try with the `return ()` wrapper
ret_code = be_loadbuffer(berry.vm, PSTR("input"), br_cmd, strlen(br_cmd));
if (be_getexcept(berry.vm, ret_code) == BE_SYNTAX_ERROR) {
be_pop(berry.vm, 2); // remove exception values
// if fails, try the direct command
ret_code = be_loadbuffer(berry.vm, PSTR("input"), XdrvMailbox.data, strlen(XdrvMailbox.data));
}
if (0 != ret_code) break;
ret_code = be_pcall(berry.vm, 0); // execute code
} while (0);
if (0 == ret_code) {
// code taken from REPL, look first at top, and if nil, look at return value
if (be_isnil(berry.vm, 0)) {
ret_val = be_tostring(berry.vm, -1);
} else {
ret_val = be_tostring(berry.vm, 0);
}
Response_P("{\"" D_PRFX_BR "\":\"%s\"}", ret_val); // can't use XdrvMailbox.command as it may have been overwritten by subcommand
be_pop(berry.vm, 1);
} else {
Response_P(PSTR("{\"" D_PRFX_BR "\":\"[%s] %s\"}"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
be_pop(berry.vm, 2);
}
checkBeTop();
}
//
// Command `BrReset`
//
void CmndBrReset(void) {
if (berry.vm == nullptr) { ResponseCmndChar_P(PSTR(D_BR_NOT_STARTED)); return; }
BrReset();
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv52(uint8_t function)
{
bool result = false;
switch (function) {
//case FUNC_PRE_INIT:
case FUNC_INIT:
BrReset();
break;
case FUNC_EVERY_50_MSECOND:
callBerryFunctionVoid(PSTR("_run_deferred"));
break;
case FUNC_EVERY_100_MSECOND:
callBerryFunctionVoid(PSTR("every_100ms"));
break;
case FUNC_EVERY_SECOND:
callBerryFunctionVoid(PSTR("every_second"));
break;
case FUNC_COMMAND:
result = DecodeCommand(kBrCommands, BerryCommand);
break;
// case FUNC_SET_POWER:
// break;
case FUNC_RULES_PROCESS:
result = callBerryRule();
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_ADD_BUTTON:
break;
case FUNC_WEB_ADD_MAIN_BUTTON:
break;
case FUNC_WEB_ADD_HANDLER:
break;
#endif // USE_WEBSERVER
case FUNC_SAVE_BEFORE_RESTART:
break;
case FUNC_MQTT_DATA:
// callBerryMqttData();
break;
case FUNC_WEB_SENSOR:
break;
case FUNC_JSON_APPEND:
break;
case FUNC_BUTTON_PRESSED:
break;
case FUNC_LOOP:
break;
}
return result;
}
#endif // USE_BERRY