Start migrating to the visitor pattern.
authorJosé Fonseca <jfonseca@vmware.com>
Fri, 19 Nov 2010 20:41:18 +0000 (20:41 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Fri, 19 Nov 2010 20:41:18 +0000 (20:41 +0000)
base.py
glretrace.py
trace_model.cpp
trace_model.hpp
trace_parser.hpp

diff --git a/base.py b/base.py
index 3c93c42..ab2382f 100644 (file)
--- a/base.py
+++ b/base.py
@@ -31,6 +31,45 @@ import debug
 
 all_types = {}
 
+
+class Visitor:
+
+    def visit(self, type, *args, **kwargs):
+        return type.visit(self, *args, **kwargs)
+
+    __call__ = visit
+
+    def visit_void(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_literal(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_const(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_struct(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_array(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_enum(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_bitmask(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_pointer(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_alias(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+    def visit_opaque(self, type, *args, **kwargs):
+        raise NotImplementedError
+
+
 class Type:
 
     __seq = 0
@@ -55,6 +94,9 @@ class Type:
     def __str__(self):
         return self.expr
 
+    def visit(self, visitor, *args, **kwargs):
+        raise NotImplementedError
+
     def isoutput(self):
         return False
 
@@ -79,6 +121,9 @@ class _Void(Type):
     def __init__(self):
         Type.__init__(self, "void")
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_void(self, *args, **kwargs)
+
 Void = _Void()
 
 
@@ -106,6 +151,9 @@ class Literal(Concrete):
         Concrete.__init__(self, expr)
         self.format = format
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_literal(self, *args, **kwargs)
+
     def _dump(self, instance):
         print '    Log::Literal%s(%s);' % (self.format, instance)
 
@@ -123,6 +171,9 @@ class Const(Type):
 
         self.type = type
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_const(self, *args, **kwargs)
+
     def dump(self, instance):
         self.type.dump(instance)
 
@@ -133,6 +184,9 @@ class Pointer(Type):
         Type.__init__(self, type.expr + " *", 'P' + type.id)
         self.type = type
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_pointer(self, *args, **kwargs)
+
     def dump(self, instance):
         print '    if(%s) {' % instance
         print '        Log::BeginPointer("%s", (const void *)%s);' % (self.type, instance)
@@ -168,6 +222,9 @@ class Enum(Concrete):
         Concrete.__init__(self, name)
         self.values = values
     
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_enum(self, *args, **kwargs)
+
     def _dump(self, instance):
         print '    switch(%s) {' % instance
         for value in self.values:
@@ -180,20 +237,20 @@ class Enum(Concrete):
         print '    }'
 
 
-class FakeEnum(Enum):
-
-    def __init__(self, type, values):
-        Enum.__init__(self, type.expr, values)
-        self.type = type
+def FakeEnum(type, values):
+    return Enum(type.expr, values)
 
 
-class Flags(Concrete):
+class Bitmask(Concrete):
 
     def __init__(self, type, values):
         Concrete.__init__(self, type.expr)
         self.type = type
         self.values = values
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_bitmask(self, *args, **kwargs)
+
     def _dump(self, instance):
         print '    %s l_Value = %s;' % (self.type, instance)
         print '    Log::BeginBitmask("%s");' % (self.type,)
@@ -207,6 +264,8 @@ class Flags(Concrete):
         print '    }'
         print '    Log::EndBitmask();'
 
+Flags = Bitmask
+
 
 class Array(Type):
 
@@ -215,6 +274,9 @@ class Array(Type):
         self.type = type
         self.length = length
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_array(self, *args, **kwargs)
+
     def dump(self, instance):
         index = '__i' + self.type.id
         print '    Log::BeginArray("%s", %s);' % (self.type, self.length)
@@ -245,6 +307,9 @@ class Struct(Concrete):
         self.name = name
         self.members = members
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_struct(self, *args, **kwargs)
+
     def _dump(self, instance):
         print '    Log::BeginStruct("%s");' % (self.name,)
         for type, name in self.members:
@@ -260,6 +325,9 @@ class Alias(Type):
         Type.__init__(self, name)
         self.type = type
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_alias(self, *args, **kwargs)
+
     def dump(self, instance):
         self.type.dump(instance)
 
@@ -505,6 +573,9 @@ class _String(Type):
     def __init__(self):
         Type.__init__(self, "char *")
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_literal(self, *args, **kwargs)
+
     def dump(self, instance):
         print '    Log::LiteralString((const char *)%s);' % instance
 
@@ -516,6 +587,9 @@ class _Opaque(Type):
     def __init__(self):
         Type.__init__(self, "void")
 
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visit_opaque(self, *args, **kwargs)
+
     def dump(self, instance):
         print '    Log::LiteralOpaque();'
 
index 82cd713..49a467a 100644 (file)
@@ -43,15 +43,45 @@ def is_function_supported(function):
     return True
 
 
-def extract_value(arg_type, arg_value):
-    if isinstance(arg_type, base.Literal):
-        return 'Trace::as%s(%s)' % (arg_type.format, value)
-    if isinstance(arg_type, base.Enum):
-        return 'Trace::asSInt(%s)' % (value)
-    if isinstance(arg_type, (base.Alias, base.Flags)):
-        return extract_value(arg_type.type, value)
-    assert false
-    return '0'
+class ValueExtractor(base.Visitor):
+
+    def visit_literal(self, type, lvalue, rvalue):
+        #print '    %s = static_cast<%s>(Trace::as%s(%s));' % (lvalue, type, type.format, rvalue)
+        print '    %s = Trace::as%s(%s);' % (lvalue, type.format, rvalue)
+
+    def visit_alias(self, type, lvalue, rvalue):
+        self.visit(type.type, lvalue, rvalue)
+    
+    def visit_enum(self, type, lvalue, rvalue):
+        #print '    %s = static_cast<%s>(Trace::as%s(%s));' % (lvalue, type, 'SInt', rvalue)
+        print '    %s = Trace::as%s(%s);' % (lvalue, 'SInt', rvalue)
+
+    def visit_bitmask(self, type, lvalue, rvalue):
+        self.visit(type.type, lvalue, rvalue)
+
+
+
+def retrace_function(function):
+    print 'static void retrace_%s(Trace::Call &call) {' % function.name
+    if not function.name.startswith('glX'):
+        success = True
+        for arg_type, arg_name in function.args:
+            print '    %s %s;' % (arg_type, arg_name)
+        for arg_type, arg_name in function.args:
+            rvalue = 'call.arg("%s")' % (arg_name,)
+            lvalue = arg_name
+            try:
+                ValueExtractor().visit(arg_type, lvalue, rvalue)
+            except NotImplementedError:
+                success = False
+                print '    %s = 0; // FIXME' % arg_name
+        if not success:
+            print '    std::cerr << "warning: unsupported call %s\\n";' % function.name
+            print '    return;'
+        arg_names = ", ".join([arg_name for arg_type, arg_name in function.args])
+        print '    %s(%s);' % (function.name, arg_names)
+    print '}'
+    print
 
 
 if __name__ == '__main__':
@@ -66,26 +96,16 @@ if __name__ == '__main__':
 
     functions = filter(is_function_supported, libgl.functions)
    
-    for function in functions:
-        print 'static void retrace_%s(Trace::Call &call) {' % function.name
-        for arg_type, arg_name in function.args:
-            print '    %s %s;' % (arg_type, arg_name)
-        for arg_type, arg_name in function.args:
-            value = 'call.get_arg("%s")' % (arg_name,)
-            value = extract_value(arg_type, value)
-            print '    %s = static_cast<%s>(%s);' % (arg_name, arg_type, value)
-        arg_names = ", ".join([arg_name for arg_type, arg_name in function.args])
-        print '    %s(%s);' % (function.name, arg_names)
-        print '}'
-        print
+    for function in libgl.functions:
+        retrace_function(function)
 
     print 'static bool retrace_call(Trace::Call &call) {'
-    for function in functions:
+    for function in libgl.functions:
         print '    if (call.name == "%s") {' % function.name
         print '        retrace_%s(call);' % function.name
         print '        return true;'
         print '    }'
-    print '    std::cerr << "Unsupported call " << call.name << "\\n";'
+    print '    std::cerr << "warning: unsupported call " << call.name << "\\n";'
     print '    return false;'
     print '}'
     print '''
index 1d33ba6..8f10224 100644 (file)
@@ -121,28 +121,26 @@ std::ostream & operator <<(std::ostream &os, Value *value) {
 }
 
 
-static const Value *unwrap(const Value *node) {
-   const Const *c = dynamic_cast<const Const *>(node);
+static const Value *unwrap(const Value &node) {
+   const Const *c = dynamic_cast<const Const *>(&node);
    if (c)
       return c->value;
-   return node;
+   return &node;
 }
 
-signed long long asSInt(const Value *node) {
-   node = unwrap(node);
-   const SInt *sint = dynamic_cast<const SInt *>(node);
+signed long long asSInt(const Value &node) {
+   const SInt *sint = dynamic_cast<const SInt *>(unwrap(node));
    if (sint)
       return sint->value;
-   const UInt *uint = dynamic_cast<const UInt *>(node);
+   const UInt *uint = dynamic_cast<const UInt *>(unwrap(node));
    if (uint)
       return uint->value;
    assert(0);
    return 0;
 }
 
-unsigned long long asUInt(const Value *node) {
-   node = unwrap(node);
-   const UInt *uint = dynamic_cast<const UInt *>(node);
+unsigned long long asUInt(const Value &node) {
+   const UInt *uint = dynamic_cast<const UInt *>(unwrap(node));
    if (uint)
       return uint->value;
    assert(0);
@@ -150,13 +148,22 @@ unsigned long long asUInt(const Value *node) {
 }
 
 
-double asFloat(const Value *node) {
-   node = unwrap(node);
-   const Float *fl = dynamic_cast<const Float *>(node);
+double asFloat(const Value &node) {
+   const Float *fl = dynamic_cast<const Float *>(unwrap(node));
    assert(fl);
    return fl->value;
 }
 
+static Void void_;
+
+Value & Call::arg(const char *name) {
+   for (std::list<Arg>::iterator it = args.begin(); it != args.end(); ++it) {
+      if (it->first == name) {
+         return *it->second;
+      }
+   }
+   return void_;
+}
 
 std::ostream & operator <<(std::ostream &os, Call &call) {
    const char *sep = "";
index 9bb3e1d..8702374 100644 (file)
@@ -153,9 +153,9 @@ public:
 std::ostream & operator <<(std::ostream &os, Value *value);
 
 
-signed long long asSInt(const Value *node);
-unsigned long long asUInt(const Value *node);
-double asFloat(const Value *node);
+signed long long asSInt(const Value &node);
+unsigned long long asUInt(const Value &node);
+double asFloat(const Value &node);
 
 
 typedef std::pair<std::string, Value *> Arg;
@@ -169,14 +169,7 @@ public:
 
    Call() : ret(0) { }
 
-   Value * get_arg(const char *name) {
-      for (std::list<Arg>::iterator it = args.begin(); it != args.end(); ++it) {
-         if (it->first == name) {
-            return it->second;
-         }
-      }
-      return NULL;
-   }
+   Value & arg(const char *name);
 };
 
 
index 50f315c..221957b 100644 (file)
@@ -59,7 +59,7 @@ public:
 
       version = read_uint();
       if (version != TRACE_VERSION) {
-         std::cerr << "Unsupported format version" << version << "\n";
+         std::cerr << "error: unsupported format version" << version << "\n";
          return false;
       }
 
@@ -90,7 +90,7 @@ public:
             break;
          default:
             assert(0);
-            std::cerr << "Unknown call detail " << c << "\n";
+            std::cerr << "error: unknown call detail " << c << "\n";
             break;
          }
       } while(true);
@@ -134,7 +134,7 @@ public:
       case Trace::TYPE_VOID:
          return NULL;
       default:
-         std::cerr << "Unknown type " << c << "\n";
+         std::cerr << "error: unknown type " << c << "\n";
          assert(0);
          return NULL;
       }
@@ -194,7 +194,7 @@ public:
          case Trace::TYPE_VOID:
             goto done;
          default:
-            std::cerr << "Unexpected type " << c << "\n";
+            std::cerr << "error: uexpected type " << c << "\n";
             assert(0);
             return NULL;
          }