Changeset: 0d3c319ac98a for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=0d3c319ac98a Modified Files: testing/melcheck.py Branch: Oct2020 Log Message:
Check arguments of MEL commands. diffs (107 lines): diff --git a/testing/melcheck.py b/testing/melcheck.py --- a/testing/melcheck.py +++ b/testing/melcheck.py @@ -12,21 +12,69 @@ except ImportError: from MonetDBtesting import exportutils # MEL pattern -argreg = r'\s*,\s*(?:bat)?(?:var)?arg(?:any)?\s*\(\s*(?P<argname>"[^"]*")\s*,\s*(?P<argval>\w*)\s*\)' +argreg = r'\s*,\s*(?P<bat>bat)?(?P<var>var)?arg(?P<any>any)?\s*\(\s*(?P<argname>"[^"]*")\s*,\s*(?P<argval>\w*)\s*\)' patreg = r'^\s*(?P<cmdpat>pattern|command)\s*\(\s*"(?P<mod>[^"]*)"\s*,\s*"(?P<fcn>[^"]*)"\s*,\s*(?P<imp>\w+)\s*,[^,]*,\s*"[^\"]*(?:\\.[^\"]*)*"\s*,\s*args\s*\(\s*(?P<retc>\d+)\s*,\s*(?P<argc>\d+)(?P<args>(?:'+argreg+')*)\s*\)\s*\)' argre = re.compile(argreg) patre = re.compile(patreg, re.MULTILINE) -fcnreg = r'(?:static\s+)?(?:str|char\s*\*)\s+(?P<name>\w+)\s*\(\s*(?:(?P<pattern>Client\s+\w+\s*,\s*MalBlkPtr\s+\w+\s*,\s*MalStkPtr\s+\w+\s*,\s*InstrPtr\s+\w+)|(?P<command>(?:\w+\s*\*+|ptr\s)\s*\w+(?:\s*,\s*(?:const\s+)?(?:\w+\s*\*(?:\s*(?:const\s*)?\*)*|ptr\s)\s*\w+)*))\s*\)\s*{' +fcnargreg = r'\s*,\s*(?:const\s+)?(?:(?P<type>\w+)\s*\*(?:\s*(?:const\s*)?\*)*|ptr\s)\s*(?P<argname>\w+)' +fcnreg = r'(?:static\s+)?(?:str|char\s*\*)\s+(?P<name>\w+)\s*\(\s*(?:(?P<pattern>Client\s+\w+\s*,\s*MalBlkPtr\s+\w+\s*,\s*MalStkPtr\s+\w+\s*,\s*InstrPtr\s+\w+)|(?P<command>(?:\w+\s*\*+|ptr\s)\s*\w+(?:'+ fcnargreg + r')*))\s*\)\s*{' fcnre = re.compile(fcnreg) +fcnargre = re.compile(fcnargreg) gpats = {} gcmds = {} mel = [] +mappings = { + 'streams': 'Stream', + 'bstream': 'Bstream', +} + +def checkcommand(imp, mod, fcn, decl, retc, argc, args): + if argc < retc: + print('bad argc < retc for command {}.{} with implementation {}'.format(mod, fcn, imp)) + return + decl = ',' + decl # makes processing easier + pos = 0 + cpos = 0 + if retc == 0: + retc = 1 + argc += 1 + args = ',arg("",void)' + args + for i in range(argc): + res = argre.match(args, pos) + if res is None: + print('not enough arguments in command {}.{} with implementation {}'.format(mod, fcn, imp)) + return + if res.group('var'): + print('cannot have variable number of arguments in command {}.{} with implementation {}'.format(mod, fcn, imp)) + return + if res.group('bat'): + cmaltype = 'bat' + elif res.group('any'): + cmaltype = 'void' + else: + cmaltype = res.group('argval') + cmaltype = mappings.get(cmaltype, cmaltype) + cres = fcnargre.match(decl, cpos) + if cres is None: + print('not enough arguments in implementation {} for command {}.{}'.format(imp, mod, fcn)) + return + ctype = cres.group('type') + if not ctype: + ctype = 'void' # declared as "ptr val", so type is void * + if i < retc and 'const' in cres.group(0): + print('const return pointer in implementation {} for command {}.{} (arg {})'.format(imp, mod, fcn, i)) + if ctype != cmaltype: + if cmaltype != 'str' or ctype != 'char' or cres.group(0).count('*') != 2: + print('type mismatch for arg {} in implementation {} for command {}.{}'.format(i, imp, mod, fcn)) + pos = res.end(0) + cpos = cres.end(0) + def process1(f): data = exportutils.preprocess(f) pats = {} @@ -51,17 +99,19 @@ def process1(f): if imp in cmds or imp in gcmds: print('command implementation {} for pattern {}.{}'.format(imp, res.group('mod'), res.group('fcn'))) else: - mel.append(('pattern', imp, res.group('mod'), res.group('fcn'))) + mel.append(('pattern', imp, res.group('mod'), res.group('fcn'), res.group('retc'), res.group('argc'), res.group('args'))) else: if imp not in cmds and imp not in gcmds: if imp in pats or imp in gpats: print('pattern implementation {} for command {}.{}'.format(imp, res.group('mod'), res.group('fcn'))) else: - mel.append(('command ', imp, res.group('mod'), res.group('fcn'))) + mel.append(('command', imp, res.group('mod'), res.group('fcn'), res.group('retc'), res.group('argc'), res.group('args'))) + else: + checkcommand(imp, res.group('mod'), res.group('fcn'), cmds.get(imp, gcmds.get(imp)), int(res.group('retc')), int(res.group('argc')), res.group('args')) res = patre.search(data, pos=res.end(0)) def process2(): - for (cmdpat, imp, mod, fcn) in mel: + for (cmdpat, imp, mod, fcn, retc, argc, args) in mel: if cmdpat == 'pattern': if imp not in gpats: if imp in gcmds: @@ -74,6 +124,8 @@ def process2(): print('pattern implementation {} for command {}.{}'.format(imp, res.group('mod'), res.group('fcn'))) else: print('command implementation {} for {}.{} is missing'.format(imp, mod, fcn)) + else: + checkcommand(imp, mod, fcn, gcmds[imp], int(retc), int(argc), args) if len(sys.argv) > 1: files = sys.argv[1:] _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list