[Kde-bindings] branches/work/kdebindings-smoke2

Arno Rehn kde at arnorehn.de
Wed Jul 18 00:53:05 UTC 2007


SVN commit 689263 by arnorehn:

* Made some more or less final changes to smoke.h
* Code generation works well, however it could be beautified a bit more.
  Looks more like a big hack than proper code.
  Generation for the type list could also be improved, it still has too
  many redundant types in it.
* The code generation for smoke modules with parents currently relies on
  a text file generated together with each module. Use a smoke
  introspection tool like the one proposed by Thomas Moenicke instead.

CCMAIL: kde-bindings at kde.org



 M  +12 -1     ChangeLog  
 M  +3 -2      kalyptus/kalyptus  
 M  +67 -27    kalyptus/kalyptusCxxToSmoke.pm  
 M  +16 -6     smoke/smoke.h  


--- branches/work/kdebindings-smoke2/ChangeLog #689262:689263
@@ -1,5 +1,16 @@
-2007-07-14  Arno Rehn  <arno at arnorehn.de>
+2007-07-18  Arno Rehn  <arno at arnorehn.de>
 
+	* Made some more or less final changes to smoke.h
+	* Code generation works well, however it could be beautified a bit more.
+	  Looks more like a big hack than proper code.
+	  Generation for the type list could also be improved, it still has too
+	  many redundant types in it.
+	* The code generation for smoke modules with parents currently relies on
+	  a text file generated together with each module. Use a smoke
+	  introspection tool like the one proposed by Thomas Moenicke instead.
+
+2007-07-17  Arno Rehn  <arno at arnorehn.de>
+
 	* Modified smoke.h to work with split smoke libraries
 	* Changed the code generation in kalyptus to produce the desired output.
 	  The cast function and the type array need some additional care, they
--- branches/work/kdebindings-smoke2/kalyptus/kalyptus #689262:689263
@@ -23,7 +23,7 @@
 use vars qw/ %rootNodes $declNodeType @includes_list %options @formats_wanted $allow_k_dcop_accessors
         @includeclasses $includeclasses $skipInternal %defines $defines $match_qt_defines
 	$libdir $libname $outputdir @libs $parse_global_space $qt_embedded $qt4 $striphpath $doPrivate $readstdin
-	$Version $quiet $debug $debuggen $parseonly $currentfile $cSourceNode $exe
+	$Version $quiet $debug $debuggen $parseonly $parentModules $currentfile $cSourceNode $exe
 	%formats %flagnames @allowed_k_dcop_accesors $allowed_k_dcop_accesors_re $rootNode 
 	@classStack $cNode $globalSpaceClassName
 	$lastLine $docNode @includes $cpp $defcppcmd $cppcmd $docincluded
@@ -167,7 +167,8 @@
 	"quiet|q",	\$quiet,
 	"debug|D",	\$debug, # debug the parsing
 	"debuggen",	\$debuggen, # debug the file generation
-	"parse-only",	\$parseonly )
+	"parse-only",	\$parseonly,
+	"parent-modules=s", \$parentModules)
 		|| exit 1;
 
 $| = 1 if $debug or $debuggen;
--- branches/work/kdebindings-smoke2/kalyptus/kalyptusCxxToSmoke.pm #689262:689263
@@ -303,6 +303,7 @@
 			close DAT;
 			chop(@lines);
 			$parentModules{$lines[0]} = $moduleIndex;
+			#$parentModules{$moduleIndex} = $lines[0];
 			for (my $i = 1; $i <= $#lines; $i++) {
 				my @splitLine = split(/\t/, $lines[$i]);
 				if ($splitLine[0] != "0") { # make sure there's no invalid entry
@@ -886,13 +887,19 @@
 		    # Resolve type in full, e.g. for QSessionManager::RestartHint
 		    # (x_QSessionManager doesn't inherit QSessionManager)
 		    $arg->{ArgType} = kalyptusDataDict::resolveType($arg->{ArgType}, $classNode, $rootnode);
-		    registerType( $arg->{ArgType} );
+
+		    # Only add the type if the class using it is not defined in another module.
+		    # If the method is virtual, add the type anyway. A class in the current module might reimplement
+		    # that method.
+		    # TODO: Check if $className is actually an ancestor of any of the classes in this module.
+		    # Only add the types of the virtual method if that's the case.
+		    registerType( $arg->{ArgType} ) unless (defined($excludeClasses{$className}) && !($m->{Flags} =~ "v"));
 		    $argId++;
 		}
 	    }
 	    $m->AddProp( "FirstDefaultParam", $firstDefaultParam );
 	    $m->{ReturnType} = kalyptusDataDict::resolveType($m->{ReturnType}, $classNode, $rootnode) if ($m->{ReturnType});
-	    registerType( $m->{ReturnType} );
+	    registerType( $m->{ReturnType} ) unless (defined($excludeClasses{$className}) && !($m->{Flags} =~ "v"));
 	}
 	elsif( $m->{NodeType} eq "enum" ) {
 	    my $fullEnumName = $className."::".$m->{astNodeName};
@@ -907,10 +914,10 @@
 		if $m->{astNodeName} and $m->{Access} ne 'private';
 
 	    # Define a type for this enum
-	    registerType( $fullEnumName );
+	    registerType( $fullEnumName ) unless (defined $excludeClasses{$className});
 
 	    # Remember that it's an enum
-	    findTypeEntry( $fullEnumName )->{isEnum} = 1;
+	    findTypeEntry( $fullEnumName )->{isEnum} = 1 unless (defined $excludeClasses{$className});
 
 	    #print STDERR "$fullEnumName is an enum\n";
  	}
@@ -939,7 +946,7 @@
 				print STDERR "var: $m->{astNodeName} '$varType'\n" if ($debug);
 
 				# Register the type
-				registerType( $varType );
+				registerType( $varType ) unless (defined $excludeClasses{$className});
 			} else {
 				$m->{NodeType} = 'deleted';
 			}
@@ -966,7 +973,7 @@
 			kdocAstUtil::attachChild( $classNode, $node );
 
 			# Register the type
-			registerType( $varType );
+			registerType( $varType ) unless (defined $excludeClasses{$className});
 		} else {
 			$m->{NodeType} = 'deleted';
 		}
@@ -993,7 +1000,7 @@
 
 	    # Hack the return type for constructors, since constructors return an object pointer
 	    $methodNode->AddProp( "ReturnType", $className."*" );
-	    registerType( $className."*" );
+	    registerType( $className."*" ) unless (defined $excludeClasses{$className});
 	    $methodNode->AddProp( "Access", "public" ); # after attachChild
 	    $defaultConstructor = 'public';
 	    $hasPublicProtectedConstructor = 1;
@@ -1053,7 +1060,7 @@
 	    $methodNode->AddProp( "NodeType", "method" );
 	    $methodNode->AddProp( "Flags", "ix" ); # Only for internal use in marshallers
 	    my $argType = "const ".$className."&";
-	    registerType( $argType );
+	    registerType( $argType ) unless (defined $excludeClasses{$className});
 	    $methodNode->AddProp( "Params", $argType );
 	    # The param node
 		my $node = Ast::New( 1 ); # let's make the arg index the node "name"
@@ -1064,7 +1071,7 @@
 
 	    # Hack the return type for constructors, since constructors return an object pointer
 	    $methodNode->AddProp( "ReturnType", $className."*" );
-	    registerType( $className."*" );
+	    registerType( $className."*" ) unless (defined $excludeClasses{$className});
 	    $methodNode->AddProp( "Access", "public" ); # after attachChild
 	}
 
@@ -1248,7 +1255,8 @@
     my $realType = $typeEntry->{realType};
 
     my $unionfield = $typeEntry->{typeId};
-    die "$type" unless defined( $unionfield );
+    die "coerce_type: $type" unless defined( $unionfield );
+    return '' unless defined( $unionfield );
     $unionfield =~ s/t_/s_/;
 
     $type =~ s/\s+const$//; # for 'char* const'
@@ -1291,6 +1299,7 @@
 	my $typeEntry = findTypeEntry( $type );
 	my $unionfield = $typeEntry->{typeId};
 	die "$type" unless defined( $unionfield );
+	return [] unless defined( $unionfield );
 	$unionfield =~ s/t_/s_/;
 
 	$type =~ s/\s+const$//; # for 'char* const'
@@ -1371,6 +1380,7 @@
     return ('', '') if $returnType eq '~'; # skip destructors
 
     my $className = $classNode->{astNodeName};
+    return ('', '') if (defined $excludeClasses{$className});
     my $flags = $m->{Flags};
     my @argList = @{$m->{ParamList}};
 
@@ -1402,7 +1412,9 @@
     $i = 1;
     for my $arg (@argList) {
 	$methodCode .= "\t";
+# 	print "warning1 ($className" . '::' . "$m->{astNodeName}): ";
 	$methodCode .= coerce_type("x[$i]", "x$i", $arg->{ArgType}, 0);
+# 	print "\n";
 	$i++;
     }
 
@@ -1492,6 +1504,7 @@
     my $name = $m->{astNodeName}; # method name
     my @heritage = kdocAstUtil::heritage($classNode);
     my $className  = join( "::", @heritage );
+    return if (defined $excludeClasses{$className});
     my $xClassName  = "x_" . join( "__", @heritage );
 
     # Check some method flags: constructor, destructor etc.
@@ -1733,6 +1746,7 @@
 
     my @heritage = kdocAstUtil::heritage($classNode);
     my $className  = join( "::", @heritage );
+    return ('', '') if (defined $excludeClasses{$className});
     my $xClassName  = "x_" . join( "__", @heritage );
 
     my $name = $m->{astNodeName};
@@ -1812,6 +1826,7 @@
 
     #my $className = $classNode->{astNodeName};
     my $className = join( "::", kdocAstUtil::heritage($classNode) );
+    return ('', '', ()) if (defined $excludeClasses{$className});
     my $xClassName = "x_" . join( "__", kdocAstUtil::heritage($classNode) );
     my $isGlobalSpace = ($xClassName eq ("x_".$main::globalSpaceClassName));
     my $sourcename = $classNode->{Source}->{astNodeName};
@@ -2107,7 +2122,7 @@
 	$type = $enumValueToType{$type};
     }
 
-    die "type not known: $type" unless defined $allTypes{$type};
+    print "type not known: $type" unless defined $allTypes{$type};
     return $allTypes{ $type };
 }
 
@@ -2245,6 +2260,7 @@
     # Make list of classes
     my %allIncludes; # list of all header files for all classes
     my @classlist;
+    my @moduleclasslist;
     push @classlist, ""; # Prepend empty item for "no class"
     my %enumclasslist;
 
@@ -2253,14 +2269,17 @@
 	my $className = join( "::", kdocAstUtil::heritage($classNode) );
 	
 	push @classlist, $className;
+	push @moduleclasslist, $className unless defined($excludeClasses{$className});
 	$enumclasslist{$className}++ if keys %{$classNode->{enumerations}};
 	$classNode->{ClassIndex} = $#classlist;
 	addIncludeForClass( $classNode, \%allIncludes, undef );
     } );
 
     my %classidx = do { my $i = 0; map { $_ => $i++ } @classlist };
+    my %moduleclassidx = do { my $i = 0; map { $_ => $i++ } @moduleclasslist };
+
     open OUT, ">$outputdir/${libname}_smoke_classlist";
-    print OUT "${libname}_Smoke\n";
+    print OUT "${libname}\n";
     foreach my $classname (keys(%classidx)) {
 	print OUT "$classidx{$classname}\t$classname\n";
     }
@@ -2290,7 +2309,7 @@
     #print OUT "static Smoke* ${libname}_parentModules[] = { 0 };\n\n";
 
     # gcc optimizes this method like crazy. switch() is godly
-    print OUT "static void *${libname}_cast(void *xptr, Smoke::Index from, Smoke::Index to) {\n";
+    print OUT "static void *${libname}_cast(void *xptr, Smoke::Index from, Smoke::ParentIndex to) {\n";
     print OUT "    switch(from) {\n";
 
     print STDERR "Writing ${libname}_cast function\n" if ($debug);
@@ -2319,14 +2338,15 @@
         if ( defined $descendants{$className} ) {
 	    push @super, @{$descendants{$className}};
 	}
-	my $cur = $classidx{$className};
+	my $cur = $moduleclassidx{$className};
 	
 	return if $classNode->{NodeType} eq 'namespace';
 
 	print OUT "      case $cur:\t//$className\n";
-	print OUT "\tswitch(to) {\n";
+	print OUT "\tswitch(to.parent) {\n";
 	$cur = -1;
 	my %casevalues;
+	my %moduleCases;
 	for my $s (@super) {
 		my $superClassName = join( "::", kdocAstUtil::heritage($s) );
 		next if !defined $classidx{$superClassName}; # inherits from unknown class, see below
@@ -2335,11 +2355,27 @@
 			die "problem with $className missing parent"
 		}
 		next if $s->kdocAstUtil::inheritsAsVirtual($classNode); # can't cast from a virtual base class
-		$cur = $classidx{$superClassName}; # KDE has MI with diamond shaped cycles (cf. KXMLGUIClient)
-		next if $casevalues{$cur};         # ..so skip any duplicate parents
-		print OUT "\t  case $cur: return (void*)($superClassName*)($className*)xptr;\n";
-		$casevalues{$cur} = 1;
+
+		if (defined($excludeClasses{$superClassName})) { # super class is in a parent module
+			my $moduleId = $excludeClasses{$superClassName}{'moduleId'};
+			my $classId = $excludeClasses{$superClassName}{'classId'};
+			next if $casevalues{$moduleId}{$classId};
+			$moduleCases{$moduleId} .= "\t      case $classId: return (void*)($superClassName*)($className*)xptr;\n";
+			$casevalues{$moduleId}{$classId} = 1
+		} else {
+			$cur = $moduleclassidx{$superClassName}; # KDE has MI with diamond shaped cycles (cf. KXMLGUIClient)
+			next if $casevalues{0}{$cur};         # ..so skip any duplicate parents
+			$moduleCases{0} .= "\t      case $cur: return (void*)($superClassName*)($className*)xptr;\n";
+			$casevalues{0}{$cur} = 1;
+		}
 	}
+	foreach my $case (keys(%moduleCases)) {
+		print OUT "\t  case $case:\n";
+		print OUT "\t    switch(to.index) {\n";
+		print OUT "$moduleCases{$case}";
+		print OUT "\t      default: return xptr;\n";
+		print OUT "\t    }\n";
+	}
 	print OUT "\t  default: return xptr;\n";
 	print OUT "\t}\n";
     } );
@@ -2951,23 +2987,27 @@
 #    print OUT "    void init_${libname}_Smoke();\n";
 #    print OUT "}\n";
     print OUT "\n";
-    print OUT "Smoke* ${libname}_Smoke = 0L;\n";
+    my @modules = keys(%parentModules);
+    for (my $i = 0; $i < $#modules; $i++) {
+	print OUT "Smoke *$modules[$i]_Smoke;\n";
+	print OUT "void init_$modules[$i]_Smoke();\n\n";
+    }
+    print OUT "Smoke *${libname}_Smoke = 0;\n";
     print OUT "\n";
     print OUT "// Create the Smoke instance encapsulating all the above.\n";
     print OUT "void init_${libname}_Smoke() {\n";
-    my @modules = keys(%parentModules);
-    for (my $i = 1; $i <= $#modules; $i++) {
-	print OUT "    init_$modules[$i]();\n";
+    for (my $i = 0; $i < $#modules; $i++) {
+	print OUT "    init_$modules[$i]_Smoke();\n";
     }
-    print OUT "    Smoke* ${libname}_parentModules[] = { 0";
-    for (my $i = 1; $i <= $#modules; $i++) {
-	print OUT ", $modules[$i]";
+    print OUT "    static Smoke *${libname}_parentModules[] = { 0";
+    for (my $i = 0; $i < $#modules; $i++) {
+	print OUT ", $modules[$i]_Smoke";
     }
     print OUT " };\n";
     print OUT "    ${libname}_Smoke = new Smoke(\n";
     print OUT "        \"${libname}\",\n";
     print OUT "        ${libname}_parentModules, ". int($#modules+1) .",\n";
-    print OUT "        ${libname}_classes, ".$#classlist.",\n";
+    print OUT "        ${libname}_classes, ".$#moduleclasslist.",\n";
     print OUT "        ${libname}_methods, $methodCount,\n";
     print OUT "        ${libname}_methodMaps, $methodMapCount,\n";
     print OUT "        ${libname}_methodNames, $methodNameCount,\n";
--- branches/work/kdebindings-smoke2/smoke/smoke.h #689262:689263
@@ -56,17 +56,19 @@
 	EnumToLong
     };
 
+    struct ParentIndex; // defined below
+
     typedef short Index;
     typedef void (*ClassFn)(Index method, void* obj, Stack args);
-    typedef void* (*CastFn)(void* obj, Index from, Index to);
+    typedef void* (*CastFn)(void* obj, Index from, ParentIndex to);
     typedef void (*EnumFn)(EnumOperation, Index, void*&, long&);
 
     // We could set references to the different Smoke modules in the arrays to avoid
     // using an extra struct like ParentIndex. I want to keep those arrays
     // reference-free, though.
-    // Use moduleIndexFromParentIndex to obtain a ModuleIndex from a Parent Index. -ar
+    // Use moduleIndexFromParentIndex to obtain a ModuleIndex from a ParentIndex. -ar
     /**
-     * Describe one index in one direct parent module.
+     * Describe one index in one parent module.
      */
     struct ParentIndex {
 	Index parent;
@@ -315,7 +317,17 @@
 	return ret;
     }
 
-    inline void *cast(void *ptr, Index from, Index to) {
+    inline ParentIndex parentIndexFromModuleIndex(ModuleIndex idx) {
+	for (Index i = 0; i < numParentModules; ++i) {
+	    if (parentModules[i] == idx.smoke) {
+		ParentIndex ret = { i, idx.index };
+		return ret;
+	    }
+	}
+	return NullParentIndex;
+    }
+
+    inline void *cast(void *ptr, Index from, ParentIndex to) {
 	if(!castFn) return ptr;
 	return (*castFn)(ptr, from, to);
     }
@@ -442,8 +454,6 @@
     }
 
     inline ModuleIndex findMethod(ModuleIndex c, ModuleIndex name) {
-	// If method is in a parent module, forward the call from here
-	
 	// Index is invalid
 	if(!c.index || !name.index) return NullModuleIndex;
 	



More information about the Kde-bindings mailing list