Changeset: b5a2b03c4010 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b5a2b03c4010
Modified Files:
        testing/malcheck.py
Branch: Oct2014
Log Message:

Also check for MAL commands that implement methods for new atoms.


diffs (182 lines):

diff --git a/testing/malcheck.py b/testing/malcheck.py
--- a/testing/malcheck.py
+++ b/testing/malcheck.py
@@ -13,15 +13,18 @@ comreg = re.compile(r'\bcommand\s+' + ma
 # recognize MAL "pattern" declarations
 patreg = re.compile(r'\bpattern\s+' + malfre + 
r'\(\s*(?P<args>[^()]*)\)\s*(?P<rets>\([^()]*\)|:\s*bat\[[^]]*\](?:\.\.\.)?|:\s*[a-zA-Z_][a-zA-Z_0-9]*(?:\.\.\.)?|)\s+'
 + addrre + r'\b')
 
+atmreg = 
re.compile(r'\batom\s+(?P<atom>[a-zA-Z_][a-zA-Z0-9_]*)(?:\s*[:=]\s*(?P<base>[a-zA-Z_][a-zA-Z0-9_]*))?\s*;')
+
 treg = re.compile(r':\s*(bat\[[^]]*\]|[a-zA-Z_][a-zA-Z_0-9]*)')
 
 expre = re.compile(r'\b[a-zA-Z_0-9]+export\s+(?P<decl>[^;]*;)', re.MULTILINE)
 nmere = re.compile(r'\b(?P<name>[a-zA-Z_][a-zA-Z_0-9]*)\s*[[(;]')
 
-freg = re.compile(r'str (?P<name>\w+)\((?P<args>[^()]*)\)')
+freg = 
re.compile(r'(?P<rtype>\w+(?:\s*\*)*)\s*\b(?P<name>\w+)\((?P<args>[^()]*)\)')
 creg = re.compile(r'\bconst\b')
 sreg = re.compile(r'\bchar\s*\*')
 areg = re.compile(r'\w+')
+argreg = re.compile(r'\s*\w+$')
 
 mappings = {
     'zrule': 'rule',
@@ -37,6 +40,25 @@ mappings = {
 cmappings = {
     'sqlblob': 'blob',
 }
+atomfunctypes = {
+    # MAL name: (return type, (argument...))
+    # where each argument is (type, const)
+    'cmp': ('int', (('void *', True), ('void *', True))),
+    'del': ('void', (('Heap *', False), ('var_t *', False))),
+    'fix': ('int', (('void *', True),)),
+    'fromstr': ('int', (('char *', True), ('int *', False), ('ptr *', False))),
+    'hash': ('BUN', (('void *', True),)),
+    'heap': ('void', (('Heap *', False), ('size_t', False))),
+    'length': ('int', (('void *', False),)),
+    'nequal': ('int', (('void *', True), ('void *', True))),
+    'null': ('void *', (('void', False),)),
+    'put': ('var_t', (('Heap *', False), ('var_t *', False), ('void *', 
True))),
+    'read': ('void *', (('void *', False), ('stream *', False), ('size_t', 
False))),
+    'storage': ('long', (('void', False),)),
+    'tostr': ('int', (('str *', False), ('int *', False), ('void *', True))),
+    'unfix': ('int', (('void *', True),)),
+    'write': ('int', (('void *', True), ('stream *', False), ('size_t', 
False))),
+    }
 
 defre = re.compile(r'^[ \t]*#[ \t]*define[ 
\t]+(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)\((?P<args>[a-zA-Z0-9_, \t]*)\)[ 
\t]*(?P<def>.*)$', re.MULTILINE)
 
@@ -44,7 +66,9 @@ cldef = re.compile(r'^[ \t]*#', re.MULTI
 
 malfuncs = []
 malpats = []
+atomfuncs = []
 decls = {}
+odecls = {}
 pdecls = {}
 
 def process(f):
@@ -53,7 +77,7 @@ def process(f):
         data = re.sub(r'[ \t]*#.*', '', data) # remove comments
         for res in comreg.finditer(data):
             malf, args, rets, func = res.groups()
-            if malf not in ('del', 'cmp', 'fromstr', 'fix', 'heap', 'hash', 
'length', 'null', 'nequal', 'put', 'storage', 'tostr', 'unfix', 'read', 
'write') or args.strip():
+            if not atomfunctypes.has_key(malf) or args.strip():
                 rtypes = []
                 atypes = []
                 if not rets:
@@ -69,6 +93,20 @@ def process(f):
                         typ = 'bat'
                     atypes.append(mappings.get(typ, typ))
                 malfuncs.append((tuple(rtypes), tuple(atypes), malf, func, f))
+            elif args.strip():
+                print 'atom function %s should be declared without arguments 
in %s' % (malf, f)
+            else:
+                if rets:
+                    print 'atom function %s should be declared without return 
type in %s' % (malf, f)
+                atom = None
+                base = None
+                for ares in atmreg.finditer(data, 0, res.start(0)):
+                    atom = ares.group('atom')
+                    base = ares.group('base')
+                if not atom:
+                    print 'atom function %s declared without known atom name 
in %s' % (malf, f)
+                    continue
+                atomfuncs.append((malf, atom, base, func, f))
         for res in patreg.finditer(data):
             malf, args, rets, func = res.groups()
             malpats.append((malf, func, f))
@@ -81,18 +119,19 @@ def process(f):
             res = nmere.search(decl)
             if decl.startswith('char *'):
                 decl = 'str ' + decl[6:]
-            if '(' in decl and decl.startswith('str '):
+            if '(' in decl:
                 res = freg.match(decl)
                 if res is not None:
-                    name, args = res.groups()
+                    rtype, name, args = res.groups()
                     args = map(lambda x: x.strip(), args.split(','))
                     if len(args) == 4 and \
                        args[0].startswith('Client ') and \
                        args[1].startswith('MalBlkPtr ') and \
                        args[2].startswith('MalStkPtr ') and \
-                       args[3].startswith('InstrPtr '):
+                       args[3].startswith('InstrPtr ') and \
+                       rtype == 'str':
                         pdecls[name] = f
-                    else:
+                    elif rtype == 'str':
                         a = []
                         for arg in args:
                             if '(' in arg:
@@ -106,13 +145,42 @@ def process(f):
                             arg = arg.strip()
                             if arg.startswith('ptr ') and not '*' in arg:
                                 arg = 'void *' + arg[4:]
+                            # normalize "char *" to "str"
+                            if arg.startswith('char **'):
+                                arg = 'str ' + arg[6:]
+                            elif arg.startswith('char *'):
+                                arg = 'str' + arg[6:]
+                            if '*' in arg or ' ' in arg:
+                                # remove argument name (just keeping type)
+                                arg = argreg.sub('', arg)
                             if '*' not in arg:
                                 break
-                            arg = sreg.sub('str', arg)
                             typ = areg.match(arg).group(0)
                             a.append((cmappings.get(typ, typ), rdonly))
                         else:
                             decls[name] = (tuple(a), f)
+                    else:
+                        if rtype == 'ptr':
+                            rtype = 'void *'
+                        a = []
+                        for arg in args:
+                            if '(' in arg:
+                                # complicated (function pointer) argument
+                                break
+                            if creg.search(arg) is not None:
+                                rdonly = True
+                                arg = creg.sub('', arg)
+                            else:
+                                rdonly = False
+                            arg = arg.strip()
+                            if '*' in arg or ' ' in arg:
+                                # remove argument name (just keeping type)
+                                arg = argreg.sub('', arg)
+                            if arg == 'str':
+                                arg = 'char *'
+                            a.append((arg, rdonly))
+                        else:
+                            odecls[name] = (rtype, tuple(a), f)
 
 report_const = False
 coverage = False
@@ -177,3 +245,24 @@ else:
     for malf, func, f in malpats:
         if not pdecls.has_key(func):
             print '%s: missing for MAL pattern %s in %s' % (func, malf, f)
+
+    for malf, atom, base, func, f in atomfuncs:
+        if not odecls.has_key(func):
+            print '%s: missing for MAL atom command %s in %s' % (func, malf, f)
+        else:
+            atm = mappings.get(atom, atom)
+            rtype, args = atomfunctypes[malf]
+            crtype, cargs, funcf = odecls[func]
+            if len(args) != len(cargs):
+                print '%s in %s: argument count mismatch for command %s for 
atom %s in %s' % (func, funcf, malf, atom, f)
+            elif rtype != crtype and rtype == 'void *' and crtype != atm + ' 
*' and (base != 'str' or (crtype != atm and crtype != 'char *')):
+                print '%s in %s: return type mismatch for command %s for atom 
%s in %s (%s vs %s)' % (func, funcf, malf, atom, f, rtype, crtype)
+            else:
+                for i in range(len(args)):
+                    a1, r1 = args[i]
+                    a2, r2 = cargs[i]
+                    if r2 and not r1:
+                        print 'argument %d of %s in %s incorrectly declared 
const for atom command %s in %s' % (i+1, func, funcf, malf, f)
+                    if a1 != a2 and a1 == 'void *' and a2 != atm + ' *' and 
(base != 'str' or (a2 != atm and a2 != 'char *')):
+                        print (a1,a2,atom,base)
+                        print '%s in %s: argument %d mismatch for command %s 
for atom %s in %s (%s vs %s)' % (func, funcf, i+1, malf, atom, f, a1, a2)
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to