diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cc245820..ecbf6e258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. - Shelly Pro 4PM using standard MCP23xxx driver and needs one time Auto-Configuration ### Changed +- Refactored Berry rule engine and support for arrays ### Fixed - TuyaMcu v1 sequence fix (#17625) diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index 0f27586ab..a6326653f 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -60,25 +60,26 @@ extern int l_i2cenabled(bvm *vm); extern int tasm_find_op(bvm *vm); #include "solidify/solidified_tasmota_class.h" +#include "solidify/solidified_rule_matcher.h" +#include "solidify/solidified_trigger_class.h" #include "be_fixed_be_class_tasmota.h" - /* @const_object_info_begin class be_class_tasmota (scope: global, name: Tasmota) { - _fl, var - _rules, var - _timers, var - _crons, var - _ccmd, var - _drivers, var - wire1, var - wire2, var - cmd_res, var - global, var - settings, var - wd, var - _debug_present, var + _fl, var // list of active fast-loop object (faster than drivers) + _rules, var // list of active rules + _timers, var // list of active timers + _crons, var // list of active crons + _ccmd, var // list of active Tasmota commands implemented in Berry + _drivers, var // list of active drivers + wire1, var // Tasmota I2C Wire1 + wire2, var // Tasmota I2C Wire2 + cmd_res, var // store the command result, nil if disables, true if capture enabled, contains return value + global, var // mapping to TasmotaGlobal + settings, var // mapping to Tasmota Settings + wd, var // working dir + _debug_present, var // is `import debug` present? _global_def, comptr(&be_tasmota_global_struct) _settings_def, comptr(&be_tasmota_settings_struct) @@ -173,5 +174,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { get_light, closure(Tasmota_get_light_closure) set_light, closure(Tasmota_set_light_closure) + + Rule_Matcher, class(be_class_Rule_Matcher) } @const_object_info_end */ diff --git a/lib/libesp32/berry_tasmota/src/embedded/rule_matcher.be b/lib/libesp32/berry_tasmota/src/embedded/rule_matcher.be new file mode 100644 index 000000000..56e268d5e --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/rule_matcher.be @@ -0,0 +1,333 @@ +#- Native code used for testing and code solidification -# +#- Do not use it directly -# + +#@ solidify:Rule_Matcher_Key +#@ solidify:Rule_Matcher_Wildcard +#@ solidify:Rule_Matcher_Operator +#@ solidify:Rule_Matcher_Array +#@ solidify:Rule_Matcher + + +#- +# tests + +tasmota.Rule_Matcher.parse("AA#BB#CC") +# [, , ] + +tasmota.Rule_Matcher.parse("AA") +# [] + +tasmota.Rule_Matcher.parse("AA#BB#CC=2") +# [, , , ] + +tasmota.Rule_Matcher.parse("AA#BB#CC>=3.5") +# [, , , =' val='3.5'>] + +tasmota.Rule_Matcher.parse("AA#BB#CC!3.5") +# [, , ] + +tasmota.Rule_Matcher.parse("AA#BB#CC==3=5") +# [, , , ] + +tasmota.Rule_Matcher.parse("AA#BB#!CC!==3=5") +# [, , , ] + +tasmota.Rule_Matcher.parse("") +# [] + +tasmota.Rule_Matcher.parse("A#?#B") +# [, , ] + +tasmota.Rule_Matcher.parse("A#?>50") +# [, , ' val='50'>] + +tasmota.Rule_Matcher.parse("A[1]") +# [, ] + +tasmota.Rule_Matcher.parse("A[1]#B[2]>3") +# [, , , , ' val='3'>] + +tasmota.Rule_Matcher.parse("A#B[]>3") +# [, , , ' val='3'>] + +################################################################################# + +m = tasmota.Rule_Matcher.parse("AA") +assert(m.match({'aa':1}) == 1) +assert(m.match({'AA':'1'}) == '1') +assert(m.match({'ab':1}) == nil) + +m = tasmota.Rule_Matcher.parse("AA#BB") +assert(m.match({'aa':1}) == nil) +assert(m.match({'aa':{'bb':1}}) == 1) + +m = tasmota.Rule_Matcher.parse("AA#BB#CC=2") +assert(m.match({'aa':1}) == nil) +assert(m.match({'aa':{'bb':1}}) == nil) +assert(m.match({'aa':{'bb':{'cc':1}}}) == nil) +assert(m.match({'aa':{'bb':{'cc':2}}}) == 2) + +m = tasmota.Rule_Matcher.parse("AA#?#CC=2") +assert(m.match({'aa':1}) == nil) +assert(m.match({'aa':{'bb':{'cc':2}}}) == 2) + +m = tasmota.Rule_Matcher.parse("AA#Power[0]") +assert(m.match({'aa':{'power':[0.5,1.5,2.5]}}) == 0.5) +m = tasmota.Rule_Matcher.parse("AA#Power[1]") +assert(m.match({'aa':{'power':[0.5,1.5,2.5]}}) == 1.5) +m = tasmota.Rule_Matcher.parse("AA#Power[2]") +assert(m.match({'aa':{'power':[0.5,1.5,2.5]}}) == 2.5) +m = tasmota.Rule_Matcher.parse("AA#Power[3]") +assert(m.match({'aa':{'power':[0.5,1.5,2.5]}}) == nil) + +m = tasmota.Rule_Matcher.parse("AA#Power[0]>1") +assert(m.match({'aa':{'power':[0.5,1.5,2.5]}}) == nil) +assert(m.match({'aa':{'power':[1.2,1.5,2.5]}}) == 1.2) + +-# + +class Rule_Matcher + + # We don't actually need a superclass, just implementing `match(val)` + # + # static class Rule_Matcher + # def init() + # end + + # # return the next index in tha val string + # # or `nil` if no match + # def match(val) + # return nil + # end + # end + + # Each matcher is an instance that implements `match(val) -> any or nil` + # + # The method takes a map or value as input, applies the matcher and + # returns a new map or value, or `nil` if the matcher did not match anything. + # + # Example: + # Payload#?#Temperature>50 + # is decomposed as: + # , , + # + # Instance types: + # Rule_Matcher_Key(key): checks that the input map contains the key (case insensitive) and + # returns the sub-value or `nil` if the key does not exist + # + # Rule_Matcher_Wildcard: maps any key, which yields to unpredictable behavior if the map + # has multiple keys (gets the first key returned by the iterator) + # + # Rule_Matcher_Operator: checks is a simple value (numerical or string) matches the operator and the value + # returns the value unchanged if match, or `nil` if no match + + static class Rule_Matcher_Key + var name # literal name of what to match + + def init(name) + self.name = name + end + + # find a key in map, case insensitive, return actual key or nil if not found + static def find_key_i(m, keyi) + import string + var keyu = string.toupper(keyi) + if isinstance(m, map) + for k:m.keys() + if string.toupper(k)==keyu + return k + end + end + end + end + + def match(val) + if val == nil return nil end # safeguard + if !isinstance(val, map) return nil end # literal name can only match a map key + var k = self.find_key_i(val, self.name) + if k == nil return nil end # no key with value self.name + return val[k] + end + + def tostring() + return "" + end + end + + static class Rule_Matcher_Array + var index # index in the array, defaults to zero + + def init(index) + self.index = index + end + + def match(val) + if val == nil return nil end # safeguard + if !isinstance(val, list) return val end # ignore index if not a list + if self.index >= size(val) return nil end # out of bounds + return val[self.index] + end + + def tostring() + return "" + end + end + + static class Rule_Matcher_Wildcard + + def match(val) + if val == nil return nil end # safeguard + if !isinstance(val, map) return nil end # literal name can only match a map key + if size(val) == 0 return nil end + return val.iter()() # get first value from iterator + end + + def tostring() + return "" + end + end + + static class Rule_Matcher_Operator + var op_func # function making the comparison + var op_str # name of the operator like '>' + var op_value # value to compare agains + + def init(op_func, op_value, op_str) + self.op_func = op_func + self.op_value = op_value + self.op_str = op_str + end + + def match(val) + var t = type(val) + if t != 'int' && t != 'real' && t != 'string' return nil end # must be a simple type + return self.op_func(val, self.op_value) ? val : nil + end + + def tostring() + return "" + end + end + + ########################################################################################### + # instance variables + var rule # original pattern of the rules + var trigger # rule pattern of trigger, excluding operator check (ex: "AA#BB>50" would be "AA#BB") + var matchers # array of Rule_Matcher(s) + + def init(rule, trigger, matchers) + self.rule = rule + self.trigger = trigger + self.matchers = matchers + end + + # parses a rule pattern and creates a list of Rule_Matcher(s) + static def parse(pattern) + import string + if pattern == nil return nil end + + var matchers = [] + + # changes "Dimmer>50" to ['Dimmer', '>', '50'] + # Ex: DS18B20#Temperature<20 + var op_list = tasmota.find_op(pattern) + + # ex: 'DS18B20#Temperature' + var value_str = op_list[0] + var op_str = op_list[1] + var op_value = op_list[2] + + var sz = size(value_str) + var idx_start = 0 # index of current cursor + var idx_end = -1 # end of current item + + while idx_start < sz + # split by '#' + var idx_sep = string.find(value_str, '#', idx_start) + var item_str + if idx_sep >= 0 + if idx_sep == idx_start raise "pattern_error", "empty pattern not allowed" end + item_str = value_str[idx_start .. idx_sep - 1] + idx_start = idx_sep + 1 + else + item_str = value_str[idx_start .. ] + idx_start = sz # will end the loop + end + + # check if there is an array accessor + var arr_start = string.find(item_str, '[') + var arr_index = nil + if arr_start >= 0 # we have an array index + var arr_end = string.find(item_str, ']', arr_start) + if arr_end < 0 raise "value_error", "missing ']' in rule pattern" end + var arr_str = item_str[arr_start + 1 .. arr_end - 1] + item_str = item_str[0 .. arr_start - 1] # truncate + arr_index = int(arr_str) + end + + if item_str == '?' + matchers.push(_class.Rule_Matcher_Wildcard()) + else + matchers.push(_class.Rule_Matcher_Key(item_str)) + end + + if arr_index != nil + matchers.push(_class.Rule_Matcher_Array(arr_index)) + end + end + + # if an operator was found, add the operator matcher + if op_str != nil && op_value != nil # we have an operator + var op_func = _class.op_parse(op_str) + if op_func + matchers.push(_class.Rule_Matcher_Operator(op_func, op_value, op_str)) + end + end + + return _class(pattern, value_str, matchers) # `_class` is a reference to the Rule_Matcher class + end + + # apply all matchers, abort if any returns `nil` + def match(val_in) + if self.matchers == nil return nil end + var val = val_in + + var idx = 0 + while idx < size(self.matchers) + val = self.matchers[idx].match(val) + if val == nil return nil end + idx += 1 + end + + return val + end + + def tostring() + return str(self.matchers) + end + + ########################################################################################### + # Functions to compare two values + ########################################################################################### + static def op_parse(op) + + def op_eq_str(a,b) return str(a) == str(b) end + def op_neq_str(a,b) return str(a) != str(b) end + def op_eq(a,b) return real(a) == real(b) end + def op_neq(a,b) return real(a) != real(b) end + def op_gt(a,b) return real(a) > real(b) end + def op_gte(a,b) return real(a) >= real(b) end + def op_lt(a,b) return real(a) < real(b) end + def op_lte(a,b) return real(a) <= real(b) end + + if op=='==' return op_eq_str + elif op=='!==' return op_neq_str + elif op=='=' return op_eq + elif op=='!=' return op_neq + elif op=='>' return op_gt + elif op=='>=' return op_gte + elif op=='<' return op_lt + elif op=='<=' return op_lte + end + end +end diff --git a/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be b/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be index 03d36637a..b12cadbc3 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be +++ b/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be @@ -1,7 +1,8 @@ #- Native code used for testing and code solidification -# #- Do not use it -# -class Trigger end # for compilation +class Trigger end # for compilation +class Rule_Matche end # for compilation tasmota = nil #@ solidify:Tasmota @@ -65,22 +66,18 @@ class Tasmota # split the item when there is an operator, returns a list of (left,op,right) - # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] + #- + assert(tasmota.find_op("Dimmer>50") == ['Dimmer', '>', '50']) + assert(tasmota.find_op("Dimmer") == ['Dimmer', nil, nil]) + assert(tasmota.find_op("Status!==Connected") == ['Status', '!==', 'Connected']) + -# def find_op(item) - import string - var op_chars = '=<>!' - var pos = self._find_op(item, false) # initial run - if pos >= 0 - var op_split = string.split(item,pos) - var op_left = op_split[0] - var op_rest = op_split[1] - pos = self._find_op(op_rest, true) - if pos >= 0 - var op_split2 = string.split(op_rest,pos) - var op_middle = op_split2[0] - var op_right = op_split2[1] - return [op_left,op_middle,op_right] - end + var idx_composite = self._find_op(item) + if idx_composite >= 0 + var idx_start = idx_composite & 0x7FFF + var idx_end = idx_composite >> 16 + + return [ item[0 .. idx_start-1], item[idx_start .. idx_end], item[idx_end+1 ..]] end return [item, nil, nil] end @@ -92,7 +89,7 @@ class Tasmota self._rules=[] end if type(f) == 'function' - self._rules.push(Trigger(pat, f, id)) + self._rules.push(Trigger(self.Rule_Matcher.parse(pat), f, id)) else raise 'value_error', 'the second argument is not a function' end @@ -102,7 +99,7 @@ class Tasmota if self._rules var i = 0 while i < size(self._rules) - if self._rules[i].trig == pat && self._rules[i].id == id + if self._rules[i].trig.rule == pat && self._rules[i].id == id self._rules.remove(i) #- don't increment i since we removed the object -# else i += 1 @@ -112,43 +109,19 @@ class Tasmota end # Rules trigger if match. return true if match, false if not - def try_rule(event, rule, f) - import string - var rl_list = self.find_op(rule) - var sub_event = event - var rl = string.split(rl_list[0],'#') - var i = 0 - while i < size(rl) - # for it:rl - var it = rl[i] - var found=self.find_key_i(sub_event,it) - if found == nil return false end - sub_event = sub_event[found] - i += 1 - end - var op=rl_list[1] - var op2=rl_list[2] - if op - if op=='==' - if str(sub_event) != str(op2) return false end - elif op=='!==' - if str(sub_event) == str(op2) return false end - elif op=='=' - if real(sub_event) != real(op2) return false end - elif op=='!=' - if real(sub_event) == real(op2) return false end - elif op=='>' - if real(sub_event) <= real(op2) return false end - elif op=='>=' - if real(sub_event) < real(op2) return false end - elif op=='<' - if real(sub_event) >= real(op2) return false end - elif op=='<=' - if real(sub_event) > real(op2) return false end + # + # event: native Berry map representing the JSON input + # rule: Rule_Matcher instance + # f: callback to call in case of a match + def try_rule(event, rule_matcher, f) + var sub_event = rule_matcher.match(event) + if sub_event != nil + if f != nil + f(sub_event, rule_matcher.trigger, event) end + return true end - f(sub_event, rl_list[0], event) - return true + return false end # Run rules, i.e. check each individual rule @@ -162,7 +135,7 @@ class Tasmota self.cmd_res = nil # disable sunsequent recording of results var ret = false - var ev = json.load(ev_json) # returns nil if invalid JSON + var ev = json.load(ev_json) # returns nil if invalid JSON if ev == nil self.log('BRY: ERROR, bad json: '+ev_json, 3) ev = ev_json # revert to string @@ -567,7 +540,8 @@ class Tasmota # iterate and call each closure var i = 0 - while i < size(fl) + var sz = size(fl) + while i < sz # note: this is not guarded in try/except for performance reasons. The inner function must not raise exceptions fl[i]() i += 1 diff --git a/lib/libesp32/berry_tasmota/src/embedded/trigger_class.be b/lib/libesp32/berry_tasmota/src/embedded/trigger_class.be index 419a8178c..83a52556a 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/trigger_class.be +++ b/lib/libesp32/berry_tasmota/src/embedded/trigger_class.be @@ -1,21 +1,33 @@ #- Native code used for testing and code solidification -# -#- Do not use it -# +#- Do not use it directly -# #@ solidify:Trigger + class Trigger var trig, f, id var o # optional object + + # trig: trigger of the event, either timestamp (int) or a rule matcher instance + # f: function or closure to call + # id: (any) identifier to allow removal of a specific trigger + # o: (instance, optional) instance implementing `timer_reached(trig)` + # this is used to implement cron with a specific method for matching time reached def init(trig, f, id, o) self.trig = trig self.f = f self.id = id self.o = o end + def tostring() import string return string.format(" 0 return self.o.time_reached(self.trig) diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_rule_matcher.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_rule_matcher.h new file mode 100644 index 000000000..d230651fc --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_rule_matcher.h @@ -0,0 +1,1142 @@ +/* Solidification of rule_matcher.h */ +/********************************************************************\ +* Generated code, don't edit * +\********************************************************************/ +#include "be_constobj.h" + +extern const bclass be_class_Rule_Matcher_Key; + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(Rule_Matcher_Key_tostring, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(_X3CMatcher_X20key_X3D_X27), + /* K1 */ be_nested_str(name), + /* K2 */ be_nested_str(_X27_X3E), + }), + &be_const_str_tostring, + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x60040008, // 0000 GETGBL R1 G8 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x00060001, // 0003 ADD R1 K0 R1 + 0x00040302, // 0004 ADD R1 R1 K2 + 0x80040200, // 0005 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: find_key_i +********************************************************************/ +be_local_closure(Rule_Matcher_Key_find_key_i, /* name */ + be_nested_proto( + 10, /* nstack */ + 2, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_const_class(be_class_Rule_Matcher_Key), + /* K1 */ be_nested_str(string), + /* K2 */ be_nested_str(toupper), + /* K3 */ be_nested_str(keys), + /* K4 */ be_nested_str(stop_iteration), + }), + &be_const_str_find_key_i, + &be_const_str_solidified, + ( &(const binstruction[29]) { /* code */ + 0x58080000, // 0000 LDCONST R2 K0 + 0xA40E0200, // 0001 IMPORT R3 K1 + 0x8C100702, // 0002 GETMET R4 R3 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0x6014000F, // 0005 GETGBL R5 G15 + 0x5C180000, // 0006 MOVE R6 R0 + 0x601C0013, // 0007 GETGBL R7 G19 + 0x7C140400, // 0008 CALL R5 2 + 0x78160011, // 0009 JMPF R5 #001C + 0x60140010, // 000A GETGBL R5 G16 + 0x8C180103, // 000B GETMET R6 R0 K3 + 0x7C180200, // 000C CALL R6 1 + 0x7C140200, // 000D CALL R5 1 + 0xA8020009, // 000E EXBLK 0 #0019 + 0x5C180A00, // 000F MOVE R6 R5 + 0x7C180000, // 0010 CALL R6 0 + 0x8C1C0702, // 0011 GETMET R7 R3 K2 + 0x5C240C00, // 0012 MOVE R9 R6 + 0x7C1C0400, // 0013 CALL R7 2 + 0x1C1C0E04, // 0014 EQ R7 R7 R4 + 0x781E0001, // 0015 JMPF R7 #0018 + 0xA8040001, // 0016 EXBLK 1 1 + 0x80040C00, // 0017 RET 1 R6 + 0x7001FFF5, // 0018 JMP #000F + 0x58140004, // 0019 LDCONST R5 K4 + 0xAC140200, // 001A CATCH R5 1 0 + 0xB0080000, // 001B RAISE 2 R0 R0 + 0x80000000, // 001C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: match +********************************************************************/ +be_local_closure(Rule_Matcher_Key_match, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(find_key_i), + /* K1 */ be_nested_str(name), + }), + &be_const_str_match, + &be_const_str_solidified, + ( &(const binstruction[23]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0001, // 0002 JMPF R2 #0005 + 0x4C080000, // 0003 LDNIL R2 + 0x80040400, // 0004 RET 1 R2 + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100013, // 0007 GETGBL R4 G19 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0001, // 0009 JMPT R2 #000C + 0x4C080000, // 000A LDNIL R2 + 0x80040400, // 000B RET 1 R2 + 0x8C080100, // 000C GETMET R2 R0 K0 + 0x5C100200, // 000D MOVE R4 R1 + 0x88140101, // 000E GETMBR R5 R0 K1 + 0x7C080600, // 000F CALL R2 3 + 0x4C0C0000, // 0010 LDNIL R3 + 0x1C0C0403, // 0011 EQ R3 R2 R3 + 0x780E0001, // 0012 JMPF R3 #0015 + 0x4C0C0000, // 0013 LDNIL R3 + 0x80040600, // 0014 RET 1 R3 + 0x940C0202, // 0015 GETIDX R3 R1 R2 + 0x80040600, // 0016 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Rule_Matcher_Key_init, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(name), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Rule_Matcher_Key +********************************************************************/ +be_local_class(Rule_Matcher_Key, + 1, + NULL, + be_nested_map(5, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(tostring, 3), be_const_closure(Rule_Matcher_Key_tostring_closure) }, + { be_const_key(find_key_i, -1), be_const_static_closure(Rule_Matcher_Key_find_key_i_closure) }, + { be_const_key(name, -1), be_const_var(0) }, + { be_const_key(init, 4), be_const_closure(Rule_Matcher_Key_init_closure) }, + { be_const_key(match, -1), be_const_closure(Rule_Matcher_Key_match_closure) }, + })), + (bstring*) &be_const_str_Rule_Matcher_Key +); +/*******************************************************************/ + +void be_load_Rule_Matcher_Key_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Rule_Matcher_Key); + be_setglobal(vm, "Rule_Matcher_Key"); + be_pop(vm, 1); +} + +extern const bclass be_class_Rule_Matcher_Wildcard; + +/******************************************************************** +** Solidified function: match +********************************************************************/ +be_local_closure(Rule_Matcher_Wildcard_match, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str(iter), + }), + &be_const_str_match, + &be_const_str_solidified, + ( &(const binstruction[23]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0001, // 0002 JMPF R2 #0005 + 0x4C080000, // 0003 LDNIL R2 + 0x80040400, // 0004 RET 1 R2 + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100013, // 0007 GETGBL R4 G19 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0001, // 0009 JMPT R2 #000C + 0x4C080000, // 000A LDNIL R2 + 0x80040400, // 000B RET 1 R2 + 0x6008000C, // 000C GETGBL R2 G12 + 0x5C0C0200, // 000D MOVE R3 R1 + 0x7C080200, // 000E CALL R2 1 + 0x1C080500, // 000F EQ R2 R2 K0 + 0x780A0001, // 0010 JMPF R2 #0013 + 0x4C080000, // 0011 LDNIL R2 + 0x80040400, // 0012 RET 1 R2 + 0x8C080301, // 0013 GETMET R2 R1 K1 + 0x7C080200, // 0014 CALL R2 1 + 0x7C080000, // 0015 CALL R2 0 + 0x80040400, // 0016 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(Rule_Matcher_Wildcard_tostring, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(_X3CMatcher_X20any_X3E), + }), + &be_const_str_tostring, + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80060000, // 0000 RET 1 K0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Rule_Matcher_Wildcard +********************************************************************/ +be_local_class(Rule_Matcher_Wildcard, + 0, + NULL, + be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(match, -1), be_const_closure(Rule_Matcher_Wildcard_match_closure) }, + { be_const_key(tostring, -1), be_const_closure(Rule_Matcher_Wildcard_tostring_closure) }, + })), + (bstring*) &be_const_str_Rule_Matcher_Wildcard +); +/*******************************************************************/ + +void be_load_Rule_Matcher_Wildcard_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Rule_Matcher_Wildcard); + be_setglobal(vm, "Rule_Matcher_Wildcard"); + be_pop(vm, 1); +} + +extern const bclass be_class_Rule_Matcher_Operator; + +/******************************************************************** +** Solidified function: match +********************************************************************/ +be_local_closure(Rule_Matcher_Operator_match, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str(int), + /* K1 */ be_nested_str(real), + /* K2 */ be_nested_str(string), + /* K3 */ be_nested_str(op_func), + /* K4 */ be_nested_str(op_value), + }), + &be_const_str_match, + &be_const_str_solidified, + ( &(const binstruction[20]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x200C0500, // 0003 NE R3 R2 K0 + 0x780E0005, // 0004 JMPF R3 #000B + 0x200C0501, // 0005 NE R3 R2 K1 + 0x780E0003, // 0006 JMPF R3 #000B + 0x200C0502, // 0007 NE R3 R2 K2 + 0x780E0001, // 0008 JMPF R3 #000B + 0x4C0C0000, // 0009 LDNIL R3 + 0x80040600, // 000A RET 1 R3 + 0x8C0C0103, // 000B GETMET R3 R0 K3 + 0x5C140200, // 000C MOVE R5 R1 + 0x88180104, // 000D GETMBR R6 R0 K4 + 0x7C0C0600, // 000E CALL R3 3 + 0x780E0001, // 000F JMPF R3 #0012 + 0x5C0C0200, // 0010 MOVE R3 R1 + 0x70020000, // 0011 JMP #0013 + 0x4C0C0000, // 0012 LDNIL R3 + 0x80040600, // 0013 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Rule_Matcher_Operator_init, /* name */ + be_nested_proto( + 4, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(op_func), + /* K1 */ be_nested_str(op_value), + /* K2 */ be_nested_str(op_str), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x90020403, // 0002 SETMBR R0 K2 R3 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(Rule_Matcher_Operator_tostring, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str(_X3CMatcher_X20op_X20_X27), + /* K1 */ be_nested_str(op_str), + /* K2 */ be_nested_str(_X27_X20val_X3D_X27), + /* K3 */ be_nested_str(op_value), + /* K4 */ be_nested_str(_X27_X3E), + }), + &be_const_str_tostring, + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x88040101, // 0000 GETMBR R1 R0 K1 + 0x00060001, // 0001 ADD R1 K0 R1 + 0x00040302, // 0002 ADD R1 R1 K2 + 0x60080008, // 0003 GETGBL R2 G8 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x7C080200, // 0005 CALL R2 1 + 0x00040202, // 0006 ADD R1 R1 R2 + 0x00040304, // 0007 ADD R1 R1 K4 + 0x80040200, // 0008 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Rule_Matcher_Operator +********************************************************************/ +be_local_class(Rule_Matcher_Operator, + 3, + NULL, + be_nested_map(6, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(op_value, -1), be_const_var(2) }, + { be_const_key(op_func, 2), be_const_var(0) }, + { be_const_key(tostring, -1), be_const_closure(Rule_Matcher_Operator_tostring_closure) }, + { be_const_key(init, -1), be_const_closure(Rule_Matcher_Operator_init_closure) }, + { be_const_key(match, 5), be_const_closure(Rule_Matcher_Operator_match_closure) }, + { be_const_key(op_str, -1), be_const_var(1) }, + })), + (bstring*) &be_const_str_Rule_Matcher_Operator +); +/*******************************************************************/ + +void be_load_Rule_Matcher_Operator_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Rule_Matcher_Operator); + be_setglobal(vm, "Rule_Matcher_Operator"); + be_pop(vm, 1); +} + +extern const bclass be_class_Rule_Matcher_Array; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Rule_Matcher_Array_init, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(index), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(Rule_Matcher_Array_tostring, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(_X3CMatcher_X20_X5B), + /* K1 */ be_nested_str(index), + /* K2 */ be_nested_str(_X5D_X3E), + }), + &be_const_str_tostring, + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x60040008, // 0000 GETGBL R1 G8 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x00060001, // 0003 ADD R1 K0 R1 + 0x00040302, // 0004 ADD R1 R1 K2 + 0x80040200, // 0005 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: match +********************************************************************/ +be_local_closure(Rule_Matcher_Array_match, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(index), + }), + &be_const_str_match, + &be_const_str_solidified, + ( &(const binstruction[22]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0001, // 0002 JMPF R2 #0005 + 0x4C080000, // 0003 LDNIL R2 + 0x80040400, // 0004 RET 1 R2 + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100012, // 0007 GETGBL R4 G18 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0000, // 0009 JMPT R2 #000B + 0x80040200, // 000A RET 1 R1 + 0x88080100, // 000B GETMBR R2 R0 K0 + 0x600C000C, // 000C GETGBL R3 G12 + 0x5C100200, // 000D MOVE R4 R1 + 0x7C0C0200, // 000E CALL R3 1 + 0x28080403, // 000F GE R2 R2 R3 + 0x780A0001, // 0010 JMPF R2 #0013 + 0x4C080000, // 0011 LDNIL R2 + 0x80040400, // 0012 RET 1 R2 + 0x88080100, // 0013 GETMBR R2 R0 K0 + 0x94080202, // 0014 GETIDX R2 R1 R2 + 0x80040400, // 0015 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Rule_Matcher_Array +********************************************************************/ +be_local_class(Rule_Matcher_Array, + 1, + NULL, + be_nested_map(4, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(index, -1), be_const_var(0) }, + { be_const_key(tostring, -1), be_const_closure(Rule_Matcher_Array_tostring_closure) }, + { be_const_key(match, -1), be_const_closure(Rule_Matcher_Array_match_closure) }, + { be_const_key(init, 0), be_const_closure(Rule_Matcher_Array_init_closure) }, + })), + (bstring*) &be_const_str_Rule_Matcher_Array +); +/*******************************************************************/ + +void be_load_Rule_Matcher_Array_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Rule_Matcher_Array); + be_setglobal(vm, "Rule_Matcher_Array"); + be_pop(vm, 1); +} + +extern const bclass be_class_Rule_Matcher; + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(Rule_Matcher_tostring, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(matchers), + }), + &be_const_str_tostring, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x60040008, // 0000 GETGBL R1 G8 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: op_parse +********************************************************************/ +be_local_closure(Rule_Matcher_op_parse, /* name */ + be_nested_proto( + 11, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 8]) { + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_eq_str, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x60080008, // 0000 GETGBL R2 G8 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C0008, // 0003 GETGBL R3 G8 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x1C080403, // 0006 EQ R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_neq_str, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x60080008, // 0000 GETGBL R2 G8 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C0008, // 0003 GETGBL R3 G8 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x20080403, // 0006 NE R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_eq, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x6008000A, // 0000 GETGBL R2 G10 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C000A, // 0003 GETGBL R3 G10 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x1C080403, // 0006 EQ R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_neq, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x6008000A, // 0000 GETGBL R2 G10 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C000A, // 0003 GETGBL R3 G10 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x20080403, // 0006 NE R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_gt, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x6008000A, // 0000 GETGBL R2 G10 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C000A, // 0003 GETGBL R3 G10 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x24080403, // 0006 GT R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_gte, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x6008000A, // 0000 GETGBL R2 G10 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C000A, // 0003 GETGBL R3 G10 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x28080403, // 0006 GE R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_lt, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x6008000A, // 0000 GETGBL R2 G10 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C000A, // 0003 GETGBL R3 G10 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x14080403, // 0006 LT R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + &be_const_str_op_lte, + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x6008000A, // 0000 GETGBL R2 G10 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x600C000A, // 0003 GETGBL R3 G10 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x18080403, // 0006 LE R2 R2 R3 + 0x80040400, // 0007 RET 1 R2 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_const_class(be_class_Rule_Matcher), + /* K1 */ be_nested_str(_X3D_X3D), + /* K2 */ be_nested_str(_X21_X3D_X3D), + /* K3 */ be_nested_str(_X3D), + /* K4 */ be_nested_str(_X21_X3D), + /* K5 */ be_nested_str(_X3E), + /* K6 */ be_nested_str(_X3E_X3D), + /* K7 */ be_nested_str(_X3C), + /* K8 */ be_nested_str(_X3C_X3D), + }), + &be_const_str_op_parse, + &be_const_str_solidified, + ( &(const binstruction[41]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x84080000, // 0001 CLOSURE R2 P0 + 0x840C0001, // 0002 CLOSURE R3 P1 + 0x84100002, // 0003 CLOSURE R4 P2 + 0x84140003, // 0004 CLOSURE R5 P3 + 0x84180004, // 0005 CLOSURE R6 P4 + 0x841C0005, // 0006 CLOSURE R7 P5 + 0x84200006, // 0007 CLOSURE R8 P6 + 0x84240007, // 0008 CLOSURE R9 P7 + 0x1C280101, // 0009 EQ R10 R0 K1 + 0x782A0001, // 000A JMPF R10 #000D + 0x80040400, // 000B RET 1 R2 + 0x7002001A, // 000C JMP #0028 + 0x1C280102, // 000D EQ R10 R0 K2 + 0x782A0001, // 000E JMPF R10 #0011 + 0x80040600, // 000F RET 1 R3 + 0x70020016, // 0010 JMP #0028 + 0x1C280103, // 0011 EQ R10 R0 K3 + 0x782A0001, // 0012 JMPF R10 #0015 + 0x80040800, // 0013 RET 1 R4 + 0x70020012, // 0014 JMP #0028 + 0x1C280104, // 0015 EQ R10 R0 K4 + 0x782A0001, // 0016 JMPF R10 #0019 + 0x80040A00, // 0017 RET 1 R5 + 0x7002000E, // 0018 JMP #0028 + 0x1C280105, // 0019 EQ R10 R0 K5 + 0x782A0001, // 001A JMPF R10 #001D + 0x80040C00, // 001B RET 1 R6 + 0x7002000A, // 001C JMP #0028 + 0x1C280106, // 001D EQ R10 R0 K6 + 0x782A0001, // 001E JMPF R10 #0021 + 0x80040E00, // 001F RET 1 R7 + 0x70020006, // 0020 JMP #0028 + 0x1C280107, // 0021 EQ R10 R0 K7 + 0x782A0001, // 0022 JMPF R10 #0025 + 0x80041000, // 0023 RET 1 R8 + 0x70020002, // 0024 JMP #0028 + 0x1C280108, // 0025 EQ R10 R0 K8 + 0x782A0000, // 0026 JMPF R10 #0028 + 0x80041200, // 0027 RET 1 R9 + 0x80000000, // 0028 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Rule_Matcher_init, /* name */ + be_nested_proto( + 4, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(rule), + /* K1 */ be_nested_str(trigger), + /* K2 */ be_nested_str(matchers), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x90020403, // 0002 SETMBR R0 K2 R3 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse +********************************************************************/ +be_local_closure(Rule_Matcher_parse, /* name */ + be_nested_proto( + 20, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[23]) { /* constants */ + /* K0 */ be_const_class(be_class_Rule_Matcher), + /* K1 */ be_nested_str(string), + /* K2 */ be_nested_str(tasmota), + /* K3 */ be_nested_str(find_op), + /* K4 */ be_const_int(0), + /* K5 */ be_const_int(1), + /* K6 */ be_const_int(2), + /* K7 */ be_nested_str(find), + /* K8 */ be_nested_str(_X23), + /* K9 */ be_nested_str(pattern_error), + /* K10 */ be_nested_str(empty_X20pattern_X20not_X20allowed), + /* K11 */ be_const_int(2147483647), + /* K12 */ be_nested_str(_X5B), + /* K13 */ be_nested_str(_X5D), + /* K14 */ be_nested_str(value_error), + /* K15 */ be_nested_str(missing_X20_X27_X5D_X27_X20in_X20rule_X20pattern), + /* K16 */ be_nested_str(_X3F), + /* K17 */ be_nested_str(push), + /* K18 */ be_nested_str(Rule_Matcher_Wildcard), + /* K19 */ be_nested_str(Rule_Matcher_Key), + /* K20 */ be_nested_str(Rule_Matcher_Array), + /* K21 */ be_nested_str(op_parse), + /* K22 */ be_nested_str(Rule_Matcher_Operator), + }), + &be_const_str_parse, + &be_const_str_solidified, + ( &(const binstruction[113]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x4C0C0000, // 0002 LDNIL R3 + 0x1C0C0003, // 0003 EQ R3 R0 R3 + 0x780E0001, // 0004 JMPF R3 #0007 + 0x4C0C0000, // 0005 LDNIL R3 + 0x80040600, // 0006 RET 1 R3 + 0x600C0012, // 0007 GETGBL R3 G18 + 0x7C0C0000, // 0008 CALL R3 0 + 0xB8120400, // 0009 GETNGBL R4 K2 + 0x8C100903, // 000A GETMET R4 R4 K3 + 0x5C180000, // 000B MOVE R6 R0 + 0x7C100400, // 000C CALL R4 2 + 0x94140904, // 000D GETIDX R5 R4 K4 + 0x94180905, // 000E GETIDX R6 R4 K5 + 0x941C0906, // 000F GETIDX R7 R4 K6 + 0x6020000C, // 0010 GETGBL R8 G12 + 0x5C240A00, // 0011 MOVE R9 R5 + 0x7C200200, // 0012 CALL R8 1 + 0x58240004, // 0013 LDCONST R9 K4 + 0x5429FFFE, // 0014 LDINT R10 -1 + 0x142C1208, // 0015 LT R11 R9 R8 + 0x782E0042, // 0016 JMPF R11 #005A + 0x8C2C0507, // 0017 GETMET R11 R2 K7 + 0x5C340A00, // 0018 MOVE R13 R5 + 0x58380008, // 0019 LDCONST R14 K8 + 0x5C3C1200, // 001A MOVE R15 R9 + 0x7C2C0800, // 001B CALL R11 4 + 0x4C300000, // 001C LDNIL R12 + 0x28341704, // 001D GE R13 R11 K4 + 0x78360008, // 001E JMPF R13 #0028 + 0x1C341609, // 001F EQ R13 R11 R9 + 0x78360000, // 0020 JMPF R13 #0022 + 0xB006130A, // 0021 RAISE 1 K9 K10 + 0x04341705, // 0022 SUB R13 R11 K5 + 0x4034120D, // 0023 CONNECT R13 R9 R13 + 0x94300A0D, // 0024 GETIDX R12 R5 R13 + 0x00381705, // 0025 ADD R14 R11 K5 + 0x5C241C00, // 0026 MOVE R9 R14 + 0x70020002, // 0027 JMP #002B + 0x4034130B, // 0028 CONNECT R13 R9 K11 + 0x94300A0D, // 0029 GETIDX R12 R5 R13 + 0x5C241000, // 002A MOVE R9 R8 + 0x8C340507, // 002B GETMET R13 R2 K7 + 0x5C3C1800, // 002C MOVE R15 R12 + 0x5840000C, // 002D LDCONST R16 K12 + 0x7C340600, // 002E CALL R13 3 + 0x4C380000, // 002F LDNIL R14 + 0x283C1B04, // 0030 GE R15 R13 K4 + 0x783E0012, // 0031 JMPF R15 #0045 + 0x8C3C0507, // 0032 GETMET R15 R2 K7 + 0x5C441800, // 0033 MOVE R17 R12 + 0x5848000D, // 0034 LDCONST R18 K13 + 0x5C4C1A00, // 0035 MOVE R19 R13 + 0x7C3C0800, // 0036 CALL R15 4 + 0x14401F04, // 0037 LT R16 R15 K4 + 0x78420000, // 0038 JMPF R16 #003A + 0xB0061D0F, // 0039 RAISE 1 K14 K15 + 0x00401B05, // 003A ADD R16 R13 K5 + 0x04441F05, // 003B SUB R17 R15 K5 + 0x40402011, // 003C CONNECT R16 R16 R17 + 0x94401810, // 003D GETIDX R16 R12 R16 + 0x04441B05, // 003E SUB R17 R13 K5 + 0x40460811, // 003F CONNECT R17 K4 R17 + 0x94301811, // 0040 GETIDX R12 R12 R17 + 0x60480009, // 0041 GETGBL R18 G9 + 0x5C4C2000, // 0042 MOVE R19 R16 + 0x7C480200, // 0043 CALL R18 1 + 0x5C382400, // 0044 MOVE R14 R18 + 0x1C3C1910, // 0045 EQ R15 R12 K16 + 0x783E0004, // 0046 JMPF R15 #004C + 0x8C3C0711, // 0047 GETMET R15 R3 K17 + 0x8C440312, // 0048 GETMET R17 R1 K18 + 0x7C440200, // 0049 CALL R17 1 + 0x7C3C0400, // 004A CALL R15 2 + 0x70020004, // 004B JMP #0051 + 0x8C3C0711, // 004C GETMET R15 R3 K17 + 0x8C440313, // 004D GETMET R17 R1 K19 + 0x5C4C1800, // 004E MOVE R19 R12 + 0x7C440400, // 004F CALL R17 2 + 0x7C3C0400, // 0050 CALL R15 2 + 0x4C3C0000, // 0051 LDNIL R15 + 0x203C1C0F, // 0052 NE R15 R14 R15 + 0x783E0004, // 0053 JMPF R15 #0059 + 0x8C3C0711, // 0054 GETMET R15 R3 K17 + 0x8C440314, // 0055 GETMET R17 R1 K20 + 0x5C4C1C00, // 0056 MOVE R19 R14 + 0x7C440400, // 0057 CALL R17 2 + 0x7C3C0400, // 0058 CALL R15 2 + 0x7001FFBA, // 0059 JMP #0015 + 0x4C2C0000, // 005A LDNIL R11 + 0x202C0C0B, // 005B NE R11 R6 R11 + 0x782E000D, // 005C JMPF R11 #006B + 0x4C2C0000, // 005D LDNIL R11 + 0x202C0E0B, // 005E NE R11 R7 R11 + 0x782E000A, // 005F JMPF R11 #006B + 0x8C2C0315, // 0060 GETMET R11 R1 K21 + 0x5C340C00, // 0061 MOVE R13 R6 + 0x7C2C0400, // 0062 CALL R11 2 + 0x782E0006, // 0063 JMPF R11 #006B + 0x8C300711, // 0064 GETMET R12 R3 K17 + 0x8C380316, // 0065 GETMET R14 R1 K22 + 0x5C401600, // 0066 MOVE R16 R11 + 0x5C440E00, // 0067 MOVE R17 R7 + 0x5C480C00, // 0068 MOVE R18 R6 + 0x7C380800, // 0069 CALL R14 4 + 0x7C300400, // 006A CALL R12 2 + 0x5C2C0200, // 006B MOVE R11 R1 + 0x5C300000, // 006C MOVE R12 R0 + 0x5C340A00, // 006D MOVE R13 R5 + 0x5C380600, // 006E MOVE R14 R3 + 0x7C2C0600, // 006F CALL R11 3 + 0x80041600, // 0070 RET 1 R11 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: match +********************************************************************/ +be_local_closure(Rule_Matcher_match, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str(matchers), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str(match), + /* K3 */ be_const_int(1), + }), + &be_const_str_match, + &be_const_str_solidified, + ( &(const binstruction[27]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x780A0001, // 0003 JMPF R2 #0006 + 0x4C080000, // 0004 LDNIL R2 + 0x80040400, // 0005 RET 1 R2 + 0x5C080200, // 0006 MOVE R2 R1 + 0x580C0001, // 0007 LDCONST R3 K1 + 0x6010000C, // 0008 GETGBL R4 G12 + 0x88140100, // 0009 GETMBR R5 R0 K0 + 0x7C100200, // 000A CALL R4 1 + 0x14100604, // 000B LT R4 R3 R4 + 0x7812000C, // 000C JMPF R4 #001A + 0x88100100, // 000D GETMBR R4 R0 K0 + 0x94100803, // 000E GETIDX R4 R4 R3 + 0x8C100902, // 000F GETMET R4 R4 K2 + 0x5C180400, // 0010 MOVE R6 R2 + 0x7C100400, // 0011 CALL R4 2 + 0x5C080800, // 0012 MOVE R2 R4 + 0x4C100000, // 0013 LDNIL R4 + 0x1C100404, // 0014 EQ R4 R2 R4 + 0x78120001, // 0015 JMPF R4 #0018 + 0x4C100000, // 0016 LDNIL R4 + 0x80040800, // 0017 RET 1 R4 + 0x000C0703, // 0018 ADD R3 R3 K3 + 0x7001FFED, // 0019 JMP #0008 + 0x80040400, // 001A RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Rule_Matcher +********************************************************************/ +be_local_class(Rule_Matcher, + 3, + NULL, + be_nested_map(12, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(rule, -1), be_const_var(0) }, + { be_const_key(tostring, -1), be_const_closure(Rule_Matcher_tostring_closure) }, + { be_const_key(op_parse, -1), be_const_static_closure(Rule_Matcher_op_parse_closure) }, + { be_const_key(init, 0), be_const_closure(Rule_Matcher_init_closure) }, + { be_const_key(Rule_Matcher_Array, 11), be_const_class(be_class_Rule_Matcher_Array) }, + { be_const_key(Rule_Matcher_Key, 6), be_const_class(be_class_Rule_Matcher_Key) }, + { be_const_key(match, -1), be_const_closure(Rule_Matcher_match_closure) }, + { be_const_key(Rule_Matcher_Operator, 8), be_const_class(be_class_Rule_Matcher_Operator) }, + { be_const_key(trigger, -1), be_const_var(1) }, + { be_const_key(Rule_Matcher_Wildcard, -1), be_const_class(be_class_Rule_Matcher_Wildcard) }, + { be_const_key(matchers, 5), be_const_var(2) }, + { be_const_key(parse, -1), be_const_static_closure(Rule_Matcher_parse_closure) }, + })), + (bstring*) &be_const_str_Rule_Matcher +); +/*******************************************************************/ + +void be_load_Rule_Matcher_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Rule_Matcher); + be_setglobal(vm, "Rule_Matcher"); + be_pop(vm, 1); +} +/********************************************************************/ +/* End of solidification */ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h index af2a338d1..5e5ab68a1 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h @@ -190,43 +190,45 @@ be_local_closure(Tasmota_remove_rule, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ + ( &(const bvalue[ 7]) { /* constants */ /* K0 */ be_nested_str(_rules), /* K1 */ be_const_int(0), /* K2 */ be_nested_str(trig), - /* K3 */ be_nested_str(id), - /* K4 */ be_nested_str(remove), - /* K5 */ be_const_int(1), + /* K3 */ be_nested_str(rule), + /* K4 */ be_nested_str(id), + /* K5 */ be_nested_str(remove), + /* K6 */ be_const_int(1), }), &be_const_str_remove_rule, &be_const_str_solidified, - ( &(const binstruction[26]) { /* code */ + ( &(const binstruction[27]) { /* code */ 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x780E0016, // 0001 JMPF R3 #0019 + 0x780E0017, // 0001 JMPF R3 #001A 0x580C0001, // 0002 LDCONST R3 K1 0x6010000C, // 0003 GETGBL R4 G12 0x88140100, // 0004 GETMBR R5 R0 K0 0x7C100200, // 0005 CALL R4 1 0x14100604, // 0006 LT R4 R3 R4 - 0x78120010, // 0007 JMPF R4 #0019 + 0x78120011, // 0007 JMPF R4 #001A 0x88100100, // 0008 GETMBR R4 R0 K0 0x94100803, // 0009 GETIDX R4 R4 R3 0x88100902, // 000A GETMBR R4 R4 K2 - 0x1C100801, // 000B EQ R4 R4 R1 - 0x78120009, // 000C JMPF R4 #0017 - 0x88100100, // 000D GETMBR R4 R0 K0 - 0x94100803, // 000E GETIDX R4 R4 R3 - 0x88100903, // 000F GETMBR R4 R4 K3 - 0x1C100802, // 0010 EQ R4 R4 R2 - 0x78120004, // 0011 JMPF R4 #0017 - 0x88100100, // 0012 GETMBR R4 R0 K0 - 0x8C100904, // 0013 GETMET R4 R4 K4 - 0x5C180600, // 0014 MOVE R6 R3 - 0x7C100400, // 0015 CALL R4 2 - 0x70020000, // 0016 JMP #0018 - 0x000C0705, // 0017 ADD R3 R3 K5 - 0x7001FFE9, // 0018 JMP #0003 - 0x80000000, // 0019 RET 0 + 0x88100903, // 000B GETMBR R4 R4 K3 + 0x1C100801, // 000C EQ R4 R4 R1 + 0x78120009, // 000D JMPF R4 #0018 + 0x88100100, // 000E GETMBR R4 R0 K0 + 0x94100803, // 000F GETIDX R4 R4 R3 + 0x88100904, // 0010 GETMBR R4 R4 K4 + 0x1C100802, // 0011 EQ R4 R4 R2 + 0x78120004, // 0012 JMPF R4 #0018 + 0x88100100, // 0013 GETMBR R4 R0 K0 + 0x8C100905, // 0014 GETMET R4 R4 K5 + 0x5C180600, // 0015 MOVE R6 R3 + 0x7C100400, // 0016 CALL R4 2 + 0x70020000, // 0017 JMP #0019 + 0x000C0706, // 0018 ADD R3 R3 K6 + 0x7001FFE8, // 0019 JMP #0003 + 0x80000000, // 001A RET 0 }) ) ); @@ -1932,7 +1934,7 @@ be_local_closure(Tasmota_hs2rgb, /* name */ ********************************************************************/ be_local_closure(Tasmota_try_rule, /* name */ be_nested_proto( - 15, /* nstack */ + 9, /* nstack */ 4, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1940,168 +1942,31 @@ be_local_closure(Tasmota_try_rule, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[16]) { /* constants */ - /* K0 */ be_nested_str(string), - /* K1 */ be_nested_str(find_op), - /* K2 */ be_nested_str(split), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_str(_X23), - /* K5 */ be_nested_str(find_key_i), - /* K6 */ be_const_int(1), - /* K7 */ be_const_int(2), - /* K8 */ be_nested_str(_X3D_X3D), - /* K9 */ be_nested_str(_X21_X3D_X3D), - /* K10 */ be_nested_str(_X3D), - /* K11 */ be_nested_str(_X21_X3D), - /* K12 */ be_nested_str(_X3E), - /* K13 */ be_nested_str(_X3E_X3D), - /* K14 */ be_nested_str(_X3C), - /* K15 */ be_nested_str(_X3C_X3D), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(match), + /* K1 */ be_nested_str(trigger), }), &be_const_str_try_rule, &be_const_str_solidified, - ( &(const binstruction[141]) { /* code */ - 0xA4120000, // 0000 IMPORT R4 K0 - 0x8C140101, // 0001 GETMET R5 R0 K1 - 0x5C1C0400, // 0002 MOVE R7 R2 - 0x7C140400, // 0003 CALL R5 2 - 0x5C180200, // 0004 MOVE R6 R1 - 0x8C1C0902, // 0005 GETMET R7 R4 K2 - 0x94240B03, // 0006 GETIDX R9 R5 K3 - 0x58280004, // 0007 LDCONST R10 K4 - 0x7C1C0600, // 0008 CALL R7 3 - 0x58200003, // 0009 LDCONST R8 K3 - 0x6024000C, // 000A GETGBL R9 G12 - 0x5C280E00, // 000B MOVE R10 R7 - 0x7C240200, // 000C CALL R9 1 - 0x14241009, // 000D LT R9 R8 R9 - 0x7826000C, // 000E JMPF R9 #001C - 0x94240E08, // 000F GETIDX R9 R7 R8 - 0x8C280105, // 0010 GETMET R10 R0 K5 - 0x5C300C00, // 0011 MOVE R12 R6 - 0x5C341200, // 0012 MOVE R13 R9 - 0x7C280600, // 0013 CALL R10 3 - 0x4C2C0000, // 0014 LDNIL R11 - 0x1C2C140B, // 0015 EQ R11 R10 R11 - 0x782E0001, // 0016 JMPF R11 #0019 - 0x502C0000, // 0017 LDBOOL R11 0 0 - 0x80041600, // 0018 RET 1 R11 - 0x94180C0A, // 0019 GETIDX R6 R6 R10 - 0x00201106, // 001A ADD R8 R8 K6 - 0x7001FFED, // 001B JMP #000A - 0x94240B06, // 001C GETIDX R9 R5 K6 - 0x94280B07, // 001D GETIDX R10 R5 K7 - 0x78260066, // 001E JMPF R9 #0086 - 0x1C2C1308, // 001F EQ R11 R9 K8 - 0x782E000A, // 0020 JMPF R11 #002C - 0x602C0008, // 0021 GETGBL R11 G8 - 0x5C300C00, // 0022 MOVE R12 R6 - 0x7C2C0200, // 0023 CALL R11 1 - 0x60300008, // 0024 GETGBL R12 G8 - 0x5C341400, // 0025 MOVE R13 R10 - 0x7C300200, // 0026 CALL R12 1 - 0x202C160C, // 0027 NE R11 R11 R12 - 0x782E0001, // 0028 JMPF R11 #002B - 0x502C0000, // 0029 LDBOOL R11 0 0 - 0x80041600, // 002A RET 1 R11 - 0x70020059, // 002B JMP #0086 - 0x1C2C1309, // 002C EQ R11 R9 K9 - 0x782E000A, // 002D JMPF R11 #0039 - 0x602C0008, // 002E GETGBL R11 G8 - 0x5C300C00, // 002F MOVE R12 R6 - 0x7C2C0200, // 0030 CALL R11 1 - 0x60300008, // 0031 GETGBL R12 G8 - 0x5C341400, // 0032 MOVE R13 R10 - 0x7C300200, // 0033 CALL R12 1 - 0x1C2C160C, // 0034 EQ R11 R11 R12 - 0x782E0001, // 0035 JMPF R11 #0038 - 0x502C0000, // 0036 LDBOOL R11 0 0 - 0x80041600, // 0037 RET 1 R11 - 0x7002004C, // 0038 JMP #0086 - 0x1C2C130A, // 0039 EQ R11 R9 K10 - 0x782E000A, // 003A JMPF R11 #0046 - 0x602C000A, // 003B GETGBL R11 G10 - 0x5C300C00, // 003C MOVE R12 R6 - 0x7C2C0200, // 003D CALL R11 1 - 0x6030000A, // 003E GETGBL R12 G10 - 0x5C341400, // 003F MOVE R13 R10 - 0x7C300200, // 0040 CALL R12 1 - 0x202C160C, // 0041 NE R11 R11 R12 - 0x782E0001, // 0042 JMPF R11 #0045 - 0x502C0000, // 0043 LDBOOL R11 0 0 - 0x80041600, // 0044 RET 1 R11 - 0x7002003F, // 0045 JMP #0086 - 0x1C2C130B, // 0046 EQ R11 R9 K11 - 0x782E000A, // 0047 JMPF R11 #0053 - 0x602C000A, // 0048 GETGBL R11 G10 - 0x5C300C00, // 0049 MOVE R12 R6 - 0x7C2C0200, // 004A CALL R11 1 - 0x6030000A, // 004B GETGBL R12 G10 - 0x5C341400, // 004C MOVE R13 R10 - 0x7C300200, // 004D CALL R12 1 - 0x1C2C160C, // 004E EQ R11 R11 R12 - 0x782E0001, // 004F JMPF R11 #0052 - 0x502C0000, // 0050 LDBOOL R11 0 0 - 0x80041600, // 0051 RET 1 R11 - 0x70020032, // 0052 JMP #0086 - 0x1C2C130C, // 0053 EQ R11 R9 K12 - 0x782E000A, // 0054 JMPF R11 #0060 - 0x602C000A, // 0055 GETGBL R11 G10 - 0x5C300C00, // 0056 MOVE R12 R6 - 0x7C2C0200, // 0057 CALL R11 1 - 0x6030000A, // 0058 GETGBL R12 G10 - 0x5C341400, // 0059 MOVE R13 R10 - 0x7C300200, // 005A CALL R12 1 - 0x182C160C, // 005B LE R11 R11 R12 - 0x782E0001, // 005C JMPF R11 #005F - 0x502C0000, // 005D LDBOOL R11 0 0 - 0x80041600, // 005E RET 1 R11 - 0x70020025, // 005F JMP #0086 - 0x1C2C130D, // 0060 EQ R11 R9 K13 - 0x782E000A, // 0061 JMPF R11 #006D - 0x602C000A, // 0062 GETGBL R11 G10 - 0x5C300C00, // 0063 MOVE R12 R6 - 0x7C2C0200, // 0064 CALL R11 1 - 0x6030000A, // 0065 GETGBL R12 G10 - 0x5C341400, // 0066 MOVE R13 R10 - 0x7C300200, // 0067 CALL R12 1 - 0x142C160C, // 0068 LT R11 R11 R12 - 0x782E0001, // 0069 JMPF R11 #006C - 0x502C0000, // 006A LDBOOL R11 0 0 - 0x80041600, // 006B RET 1 R11 - 0x70020018, // 006C JMP #0086 - 0x1C2C130E, // 006D EQ R11 R9 K14 - 0x782E000A, // 006E JMPF R11 #007A - 0x602C000A, // 006F GETGBL R11 G10 - 0x5C300C00, // 0070 MOVE R12 R6 - 0x7C2C0200, // 0071 CALL R11 1 - 0x6030000A, // 0072 GETGBL R12 G10 - 0x5C341400, // 0073 MOVE R13 R10 - 0x7C300200, // 0074 CALL R12 1 - 0x282C160C, // 0075 GE R11 R11 R12 - 0x782E0001, // 0076 JMPF R11 #0079 - 0x502C0000, // 0077 LDBOOL R11 0 0 - 0x80041600, // 0078 RET 1 R11 - 0x7002000B, // 0079 JMP #0086 - 0x1C2C130F, // 007A EQ R11 R9 K15 - 0x782E0009, // 007B JMPF R11 #0086 - 0x602C000A, // 007C GETGBL R11 G10 - 0x5C300C00, // 007D MOVE R12 R6 - 0x7C2C0200, // 007E CALL R11 1 - 0x6030000A, // 007F GETGBL R12 G10 - 0x5C341400, // 0080 MOVE R13 R10 - 0x7C300200, // 0081 CALL R12 1 - 0x242C160C, // 0082 GT R11 R11 R12 - 0x782E0001, // 0083 JMPF R11 #0086 - 0x502C0000, // 0084 LDBOOL R11 0 0 - 0x80041600, // 0085 RET 1 R11 - 0x5C2C0600, // 0086 MOVE R11 R3 - 0x5C300C00, // 0087 MOVE R12 R6 - 0x94340B03, // 0088 GETIDX R13 R5 K3 - 0x5C380200, // 0089 MOVE R14 R1 - 0x7C2C0600, // 008A CALL R11 3 - 0x502C0200, // 008B LDBOOL R11 1 0 - 0x80041600, // 008C RET 1 R11 + ( &(const binstruction[18]) { /* code */ + 0x8C100500, // 0000 GETMET R4 R2 K0 + 0x5C180200, // 0001 MOVE R6 R1 + 0x7C100400, // 0002 CALL R4 2 + 0x4C140000, // 0003 LDNIL R5 + 0x20140805, // 0004 NE R5 R4 R5 + 0x78160009, // 0005 JMPF R5 #0010 + 0x4C140000, // 0006 LDNIL R5 + 0x20140605, // 0007 NE R5 R3 R5 + 0x78160004, // 0008 JMPF R5 #000E + 0x5C140600, // 0009 MOVE R5 R3 + 0x5C180800, // 000A MOVE R6 R4 + 0x881C0501, // 000B GETMBR R7 R2 K1 + 0x5C200200, // 000C MOVE R8 R1 + 0x7C140600, // 000D CALL R5 3 + 0x50140200, // 000E LDBOOL R5 1 0 + 0x80040A00, // 000F RET 1 R5 + 0x50140000, // 0010 LDBOOL R5 0 0 + 0x80040A00, // 0011 RET 1 R5 }) ) ); @@ -2216,7 +2081,7 @@ be_local_closure(Tasmota_add_cmd, /* name */ ********************************************************************/ be_local_closure(Tasmota_find_op, /* name */ be_nested_proto( - 13, /* nstack */ + 7, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -2224,58 +2089,46 @@ be_local_closure(Tasmota_find_op, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str(string), - /* K1 */ be_nested_str(_X3D_X3C_X3E_X21), - /* K2 */ be_nested_str(_find_op), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_str(split), - /* K5 */ be_const_int(1), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str(_find_op), + /* K1 */ be_const_int(0), + /* K2 */ be_const_int(1), + /* K3 */ be_const_int(2147483647), }), &be_const_str_find_op, &be_const_str_solidified, - ( &(const binstruction[41]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x8C100102, // 0002 GETMET R4 R0 K2 - 0x5C180200, // 0003 MOVE R6 R1 - 0x501C0000, // 0004 LDBOOL R7 0 0 - 0x7C100600, // 0005 CALL R4 3 - 0x28140903, // 0006 GE R5 R4 K3 - 0x78160018, // 0007 JMPF R5 #0021 - 0x8C140504, // 0008 GETMET R5 R2 K4 - 0x5C1C0200, // 0009 MOVE R7 R1 - 0x5C200800, // 000A MOVE R8 R4 - 0x7C140600, // 000B CALL R5 3 - 0x94180B03, // 000C GETIDX R6 R5 K3 - 0x941C0B05, // 000D GETIDX R7 R5 K5 - 0x8C200102, // 000E GETMET R8 R0 K2 - 0x5C280E00, // 000F MOVE R10 R7 - 0x502C0200, // 0010 LDBOOL R11 1 0 - 0x7C200600, // 0011 CALL R8 3 - 0x5C101000, // 0012 MOVE R4 R8 - 0x28200903, // 0013 GE R8 R4 K3 - 0x7822000B, // 0014 JMPF R8 #0021 - 0x8C200504, // 0015 GETMET R8 R2 K4 - 0x5C280E00, // 0016 MOVE R10 R7 - 0x5C2C0800, // 0017 MOVE R11 R4 - 0x7C200600, // 0018 CALL R8 3 - 0x94241103, // 0019 GETIDX R9 R8 K3 - 0x94281105, // 001A GETIDX R10 R8 K5 - 0x602C0012, // 001B GETGBL R11 G18 - 0x7C2C0000, // 001C CALL R11 0 - 0x40301606, // 001D CONNECT R12 R11 R6 - 0x40301609, // 001E CONNECT R12 R11 R9 - 0x4030160A, // 001F CONNECT R12 R11 R10 - 0x80041600, // 0020 RET 1 R11 - 0x60140012, // 0021 GETGBL R5 G18 - 0x7C140000, // 0022 CALL R5 0 - 0x40180A01, // 0023 CONNECT R6 R5 R1 - 0x4C180000, // 0024 LDNIL R6 - 0x40180A06, // 0025 CONNECT R6 R5 R6 - 0x4C180000, // 0026 LDNIL R6 - 0x40180A06, // 0027 CONNECT R6 R5 R6 - 0x80040A00, // 0028 RET 1 R5 + ( &(const binstruction[31]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0x280C0501, // 0003 GE R3 R2 K1 + 0x780E0011, // 0004 JMPF R3 #0017 + 0x540E7FFE, // 0005 LDINT R3 32767 + 0x2C0C0403, // 0006 AND R3 R2 R3 + 0x5412000F, // 0007 LDINT R4 16 + 0x3C100404, // 0008 SHR R4 R2 R4 + 0x60140012, // 0009 GETGBL R5 G18 + 0x7C140000, // 000A CALL R5 0 + 0x04180702, // 000B SUB R6 R3 K2 + 0x401A0206, // 000C CONNECT R6 K1 R6 + 0x94180206, // 000D GETIDX R6 R1 R6 + 0x40180A06, // 000E CONNECT R6 R5 R6 + 0x40180604, // 000F CONNECT R6 R3 R4 + 0x94180206, // 0010 GETIDX R6 R1 R6 + 0x40180A06, // 0011 CONNECT R6 R5 R6 + 0x00180902, // 0012 ADD R6 R4 K2 + 0x40180D03, // 0013 CONNECT R6 R6 K3 + 0x94180206, // 0014 GETIDX R6 R1 R6 + 0x40180A06, // 0015 CONNECT R6 R5 R6 + 0x80040A00, // 0016 RET 1 R5 + 0x600C0012, // 0017 GETGBL R3 G18 + 0x7C0C0000, // 0018 CALL R3 0 + 0x40100601, // 0019 CONNECT R4 R3 R1 + 0x4C100000, // 001A LDNIL R4 + 0x40100604, // 001B CONNECT R4 R3 R4 + 0x4C100000, // 001C LDNIL R4 + 0x40100604, // 001D CONNECT R4 R3 R4 + 0x80040600, // 001E RET 1 R3 }) ) ); @@ -2349,18 +2202,20 @@ be_local_closure(Tasmota_add_rule, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ + ( &(const bvalue[ 9]) { /* constants */ /* K0 */ be_nested_str(check_not_method), /* K1 */ be_nested_str(_rules), /* K2 */ be_nested_str(function), /* K3 */ be_nested_str(push), /* K4 */ be_nested_str(Trigger), - /* K5 */ be_nested_str(value_error), - /* K6 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function), + /* K5 */ be_nested_str(Rule_Matcher), + /* K6 */ be_nested_str(parse), + /* K7 */ be_nested_str(value_error), + /* K8 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function), }), &be_const_str_add_rule, &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ + ( &(const binstruction[27]) { /* code */ 0x8C100100, // 0000 GETMET R4 R0 K0 0x5C180400, // 0001 MOVE R6 R2 0x7C100400, // 0002 CALL R4 2 @@ -2373,18 +2228,21 @@ be_local_closure(Tasmota_add_rule, /* name */ 0x5C140400, // 0009 MOVE R5 R2 0x7C100200, // 000A CALL R4 1 0x1C100902, // 000B EQ R4 R4 K2 - 0x78120008, // 000C JMPF R4 #0016 + 0x7812000B, // 000C JMPF R4 #0019 0x88100101, // 000D GETMBR R4 R0 K1 0x8C100903, // 000E GETMET R4 R4 K3 0xB81A0800, // 000F GETNGBL R6 K4 - 0x5C1C0200, // 0010 MOVE R7 R1 - 0x5C200400, // 0011 MOVE R8 R2 - 0x5C240600, // 0012 MOVE R9 R3 - 0x7C180600, // 0013 CALL R6 3 - 0x7C100400, // 0014 CALL R4 2 - 0x70020000, // 0015 JMP #0017 - 0xB0060B06, // 0016 RAISE 1 K5 K6 - 0x80000000, // 0017 RET 0 + 0x881C0105, // 0010 GETMBR R7 R0 K5 + 0x8C1C0F06, // 0011 GETMET R7 R7 K6 + 0x5C240200, // 0012 MOVE R9 R1 + 0x7C1C0400, // 0013 CALL R7 2 + 0x5C200400, // 0014 MOVE R8 R2 + 0x5C240600, // 0015 MOVE R9 R3 + 0x7C180600, // 0016 CALL R6 3 + 0x7C100400, // 0017 CALL R4 2 + 0x70020000, // 0018 JMP #001A + 0xB0060F08, // 0019 RAISE 1 K7 K8 + 0x80000000, // 001A RET 0 }) ) ); @@ -2611,12 +2469,12 @@ be_local_closure(Tasmota_fast_loop, /* name */ 0x600C000C, // 0005 GETGBL R3 G12 0x5C100200, // 0006 MOVE R4 R1 0x7C0C0200, // 0007 CALL R3 1 - 0x140C0403, // 0008 LT R3 R2 R3 - 0x780E0003, // 0009 JMPF R3 #000E - 0x940C0202, // 000A GETIDX R3 R1 R2 - 0x7C0C0000, // 000B CALL R3 0 + 0x14100403, // 0008 LT R4 R2 R3 + 0x78120003, // 0009 JMPF R4 #000E + 0x94100202, // 000A GETIDX R4 R1 R2 + 0x7C100000, // 000B CALL R4 0 0x00080502, // 000C ADD R2 R2 K2 - 0x7001FFF6, // 000D JMP #0005 + 0x7001FFF9, // 000D JMP #0008 0x80000000, // 000E RET 0 }) ) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino index cd44292ad..7b2105f1e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -453,9 +453,7 @@ extern "C" { } // Find for an operator in the string - // takes a string, an offset to start the search from, and works in 2 modes. - // mode1 (false): loog for the first char of an operato - // mode2 (true): finds the last char of the operator + // returns -1 if not found, or returns start in low 16 bits, end in high 16 bits int32_t tasm_find_op(bvm *vm); int32_t tasm_find_op(bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments @@ -463,60 +461,64 @@ extern "C" { int32_t ret = -1; if (top >= 2 && be_isstring(vm, 2)) { const char *c = be_tostring(vm, 2); - if (top >= 3) { - second_phase = be_tobool(vm, 3); - } + // new version, two phases in 1, return start in low 16 bits, end in high 16 bits - if (!second_phase) { - int32_t idx = 0; - // search for `=`, `==`, `!=`, `!==`, `<`, `<=`, `>`, `>=` - while (*c && ret < 0) { - switch (c[0]) { - case '=': - case '<': - case '>': - ret = idx; - break; // anything starting with `=`, `<` or `>` is a valid operator - case '!': - if (c[1] == '=') { - ret = idx; // needs to start with `!=` - } - break; - default: - break; - } - c++; - idx++; + int32_t idx_start = -1; + int32_t idx = 0; + // search for `=`, `==`, `!=`, `!==`, `<`, `<=`, `>`, `>=` + while (*c && idx_start < 0) { + switch (c[0]) { + case '=': + case '<': + case '>': + idx_start = idx; + break; // anything starting with `=`, `<` or `>` is a valid operator + case '!': + if (c[1] == '=') { + idx_start = idx; // needs to start with `!=` + } + break; + default: + break; } - } else { + c++; + idx++; + } + int idx_end = -1; + if (idx_start >= 0) { + idx_end = idx_start; // second phase switch (c[0]) { case '<': case '>': case '=': - if (c[1] != '=') { ret = 1; } // `<` or `>` or `=` - else { ret = 2; } // `<=` or `>=` or `==` + if (c[1] != '=') { idx_end += 1; } // `<` or `>` or `=` + else { idx_end += 2; } // `<=` or `>=` or `==` break; case '!': if (c[1] != '=') { ; } // this is invalid if isolated `!` - if (c[2] != '=') { ret = 2; } // `!=` - else { ret = 3; } // `!==` + if (c[2] != '=') { idx_end += 2; } // `!=` + else { idx_end += 3; } // `!==` break; default: break; } } + + if (idx_start >= 0 && idx_end >= idx_start) { + ret = ((idx_end & 0x7FFF) << 16) | (idx_start & 0x7FFF); + } } be_pushint(vm, ret); be_return(vm); } /* - # test patterns - assert(tasmota._find_op("aaa#bbc==23",false) == 7) - assert(tasmota._find_op("==23",true) == 2) - assert(tasmota._find_op(">23",true) == 1) - assert(tasmota._find_op("aaa#bbc!23",false) == -1) + # test patterns for all-in-one version + assert(tasmota._find_op("aaa#bbc==23") == 0x80007) + assert(tasmota._find_op("az==23") == 0x30002) + assert(tasmota._find_op("a>23") == 0x10001) + assert(tasmota._find_op("aaa#bbc!23") == -1) */