java-gobject-introspection r53 - in trunk: src/org/gnome/gir/compiler stub-examples



Author: walters
Date: Thu Sep 11 13:16:39 2008
New Revision: 53
URL: http://svn.gnome.org/viewvc/java-gobject-introspection?rev=53&view=rev

Log:
Use primitives instead of boxed.  Add local variable table class.


Modified:
   trunk/src/org/gnome/gir/compiler/CodeFactory.java
   trunk/stub-examples/Test.java
   trunk/stub-examples/TestStructure.java

Modified: trunk/src/org/gnome/gir/compiler/CodeFactory.java
==============================================================================
--- trunk/src/org/gnome/gir/compiler/CodeFactory.java	(original)
+++ trunk/src/org/gnome/gir/compiler/CodeFactory.java	Thu Sep 11 13:16:39 2008
@@ -29,6 +29,7 @@
 import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
 import static org.objectweb.asm.Opcodes.INVOKESTATIC;
 import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.IRETURN;
 import static org.objectweb.asm.Opcodes.ISTORE;
 import static org.objectweb.asm.Opcodes.LRETURN;
 import static org.objectweb.asm.Opcodes.NEW;
@@ -48,9 +49,11 @@
 import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -101,9 +104,11 @@
 import org.objectweb.asm.Type;
 import org.objectweb.asm.util.CheckClassAdapter;
 
+import com.sun.jna.Function;
 import com.sun.jna.Pointer;
 import com.sun.jna.PointerType;
 import com.sun.jna.ptr.ByteByReference;
+import com.sun.jna.ptr.DoubleByReference;
 import com.sun.jna.ptr.FloatByReference;
 import com.sun.jna.ptr.IntByReference;
 import com.sun.jna.ptr.LongByReference;
@@ -203,20 +208,20 @@
 	
 	public static Type toJavaRef(TypeTag tag) {
 		Type t = toJava(tag);
-		if (t.equals(Type.getType(Integer.class)))
+		if (t.equals(Type.INT_TYPE))
 			return Type.getType(IntByReference.class);
-		if (t.equals(Type.getType(Long.class)))
+		if (t.equals(Type.LONG_TYPE))
 			return Type.getType(LongByReference.class);
-		if (t.equals(Type.getType(Boolean.class)))
+		if (t.equals(Type.BOOLEAN_TYPE))
 			return Type.getType(IntByReference.class);
-		if (t.equals(Type.getType(Byte.class)))
+		if (t.equals(Type.BYTE_TYPE))
 			return Type.getType(ByteByReference.class);
-		if (t.equals(Type.getType(Short.class)))
+		if (t.equals(Type.SHORT_TYPE))
 			return Type.getType(ShortByReference.class);
-		if (t.equals(Type.getType(Float.class)))
+		if (t.equals(Type.FLOAT_TYPE))
 			return Type.getType(FloatByReference.class);
-		if (t.equals(Type.getType(Double.class)))
-			return Type.getType(Double.class);
+		if (t.equals(Type.DOUBLE_TYPE))
+			return Type.getType(DoubleByReference.class);
 		if (t.equals(Type.getType(String.class)) || t.equals(Type.getType(File.class)))
 			return Type.getType(PointerByReference.class);
 		if (t.equals(Type.VOID_TYPE))
@@ -228,21 +233,21 @@
 		if (tag == TypeTag.VOID)
 			return Type.VOID_TYPE;
 		if (tag == TypeTag.BOOLEAN)
-			return Type.getType(Boolean.class);
+			return Type.BOOLEAN_TYPE;
 		if (tag == TypeTag.INT8 || tag == TypeTag.UINT8)
-			return Type.getType(Byte.class);
+			return Type.BYTE_TYPE;
 		if (tag == TypeTag.INT16 || tag == TypeTag.UINT16)
-			return Type.getType(Short.class);
+			return Type.SHORT_TYPE;
 		if (tag == TypeTag.INT32 || tag == TypeTag.UINT32 ||
 				tag == TypeTag.INT || tag == TypeTag.UINT)
-			return Type.getType(Integer.class);
+			return Type.INT_TYPE;
 		if (tag == TypeTag.INT64 || tag == TypeTag.UINT64
 				|| tag == TypeTag.SIZE || tag == TypeTag.SSIZE)
-			return Type.getType(Long.class);
+			return Type.LONG_TYPE;
 		if (tag == TypeTag.FLOAT)
-			return Type.getType(Float.class);
+			return Type.FLOAT_TYPE;
 		if (tag == TypeTag.DOUBLE)
-			return Type.getType(Double.class);
+			return Type.DOUBLE_TYPE;
 		if (tag == TypeTag.UTF8)
 			return Type.getType(String.class);
 		if (tag == TypeTag.FILENAME)
@@ -261,6 +266,26 @@
 		return toJava(info.getTag());
 	}
 	
+	private Class<?> getPrimitiveBox(Type type) {
+		if (type.equals(Type.BOOLEAN_TYPE))
+			return Boolean.class;
+		if (type.equals(Type.BYTE_TYPE))
+			return Byte.class;
+		if (type.equals(Type.CHAR_TYPE))
+			return Character.class;
+		if (type.equals(Type.SHORT_TYPE))
+			return Short.class;
+		if (type.equals(Type.INT_TYPE))
+			return Integer.class;
+		if (type.equals(Type.LONG_TYPE))
+			return Long.class;
+		if (type.equals(Type.FLOAT_TYPE))
+			return Float.class;
+		if (type.equals(Type.DOUBLE_TYPE))
+			return Double.class;
+		return null;
+	}
+	
 	private List<Type> getCallableArgs(CallableInfo callable, boolean isMethod,
 				boolean allowError) {
 		ArgInfo[] args = callable.getArgs();
@@ -754,10 +779,13 @@
 		mv.visitLdcInsn(Type.getType("Lcom/sun/jna/Pointer;"));
 		mv.visitIntInsn(BIPUSH, args.size());
 		mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
+		int argOffset = 0;
 		for (int i = 0; i < nArgs; i++) {
 			mv.visitInsn(DUP);
 			mv.visitIntInsn(BIPUSH, i);
-			mv.visitVarInsn(ALOAD, i);
+			Type argType = args.get(i);
+			writeLoadArgument(mv, argOffset, argType);
+			argOffset += argType.getSize();			
 			mv.visitInsn(AASTORE);			
 		}
 		mv.visitFieldInsn(GETSTATIC, globalInternalsName, "invocationOptions", "Ljava/util/Map;");
@@ -776,7 +804,7 @@
 		mv.visitEnd();		
 	}	
 	
-	private void compileConstructor(ObjectInfo info, ClassCompilation compilation, FunctionInfo fi) {	
+	private void writeConstructor(ObjectInfo info, ClassCompilation compilation, FunctionInfo fi) {	
 		String globalInternalsName = getInternals(info);
 
 		ArgInfo[] argInfos = fi.getArgs();
@@ -797,13 +825,15 @@
 		mv.visitFieldInsn(GETSTATIC, globalInternalsName, "library", "Lcom/sun/jna/NativeLibrary;");
 		mv.visitLdcInsn(fi.getSymbol());
 		mv.visitMethodInsn(INVOKEVIRTUAL, "com/sun/jna/NativeLibrary", "getFunction", "(Ljava/lang/String;)Lcom/sun/jna/Function;");
-		mv.visitLdcInsn(Type.getType("Lcom/sun/jna/Pointer;"));
+		mv.visitLdcInsn(Type.getType(Pointer.class));
 		mv.visitIntInsn(BIPUSH, args.size());
 		mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
+		LocalVariableTable locals = new LocalVariableTable(Type.getObjectType(compilation.internalName), args, argInfos, true);
 		for (int i = 0; i < nArgs; i++) {
 			mv.visitInsn(DUP);
 			mv.visitIntInsn(BIPUSH, i);
-			mv.visitVarInsn(ALOAD, i+1);
+			LocalVariable var = locals.get(i+1);
+			writeLoadArgument(mv, var.offset, var.type);
 			mv.visitInsn(AASTORE);			
 		}
 		mv.visitFieldInsn(GETSTATIC, globalInternalsName, "invocationOptions", "Ljava/util/Map;");
@@ -817,10 +847,7 @@
 		mv.visitInsn(RETURN);
 		Label l4 = new Label();
 		mv.visitLabel(l4);
-		mv.visitLocalVariable("this", "L" + compilation.internalName + ";", null, l0, l4, 0);
-		for (int i = 0; i < nArgs; i++) {
-			mv.visitLocalVariable(argInfos[i].getName(), args.get(i).toString(), null, l0, l3, i+1);
-		}
+		locals.writeLocals(mv, l0, l4);
 		mv.visitMaxs(0, 0);
 		mv.visitEnd();		
 	}
@@ -844,11 +871,6 @@
 					sigClass, ACC_PUBLIC + ACC_STATIC + ACC_ABSTRACT + ACC_INTERFACE);
 		
 			writeJnaCallbackTypeMapper(sigCompilation);
-		
-			/* public static final String METHOD_NAME = */
-			FieldVisitor fv = sigCompilation.writer.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, 
-					"METHOD_NAME", "Ljava/lang/String;", null, sigHandlerName);
-			fv.visitEnd();
 
 			MethodVisitor mv = sigCompilation.writer.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, sigHandlerName, descriptor, null, null);
 			mv.visitEnd();			
@@ -904,6 +926,12 @@
 			if (type == null)
 				continue;
 			int propFlags = prop.getFlags();
+			Class<?> propBox = getPrimitiveBox(type);
+			Type propTypeBox;
+			if (propBox != null)
+				propTypeBox = Type.getType(propBox);
+			else
+				propTypeBox = type;
 			if ((propFlags & GParamFlags.READABLE) != 0) {
 				String getterName = "get" + ucaseToPascal(prop.getName());
 				String descriptor = Type.getMethodDescriptor(type, new Type[] {});
@@ -922,9 +950,12 @@
 				mv.visitVarInsn(ALOAD, 0);
 				mv.visitLdcInsn(prop.getName());
 				mv.visitMethodInsn(INVOKEVIRTUAL, compilation.internalName, "get", 
-						"(Ljava/lang/String;)" + type.getDescriptor());
-				mv.visitTypeInsn(CHECKCAST, type.getInternalName());
-				mv.visitInsn(ARETURN);
+						"(Ljava/lang/String;)" + propTypeBox.getDescriptor());
+				mv.visitTypeInsn(CHECKCAST, propTypeBox.getInternalName());
+				if (propBox != null)
+					mv.visitMethodInsn(INVOKEVIRTUAL, propTypeBox.getInternalName(), 
+							type.getClassName() + "Value", "()" + type.getDescriptor());				
+				mv.visitInsn(type.getOpcode(IRETURN));
 				Label l1 = new Label();
 				mv.visitLabel(l1);
 				mv.visitLocalVariable("this", "L" + compilation.internalName +";", null, l0, l1, 0);
@@ -948,8 +979,11 @@
 				Label l0 = new Label();
 				mv.visitLabel(l0);
 				mv.visitVarInsn(ALOAD, 0);
-				mv.visitLdcInsn(prop.getName());
-				mv.visitVarInsn(ALOAD, 1);
+				mv.visitLdcInsn(prop.getName());				
+				mv.visitVarInsn(type.getOpcode(ILOAD), 1);
+				if (propBox != null)
+					mv.visitMethodInsn(INVOKESTATIC, propTypeBox.getInternalName(), 
+							"valueOf", "(" + type.getDescriptor() + ")" + propTypeBox.getDescriptor());					
 				mv.visitMethodInsn(INVOKEVIRTUAL, compilation.internalName, "set", 
 						"(Ljava/lang/String;Ljava/lang/Object;)" + type.getDescriptor());
 				mv.visitInsn(RETURN);
@@ -1029,7 +1063,7 @@
 		for (Set<FunctionInfo> ctorGroup : ctors.values()) {
 			FunctionInfo first = ctorGroup.iterator().next();			
 			if (ctorGroup.size() == 1) {
-				compileConstructor(info, compilation, first);
+				writeConstructor(info, compilation, first);
 			} else {
 				logger.info("Constructor name " + first.getSymbol() + " clashes");
 				FunctionInfo defaultCtor = null;
@@ -1038,7 +1072,7 @@
 						defaultCtor = ctor;
 				}
 				if (defaultCtor != null) {
-					compileConstructor(info, compilation, defaultCtor);
+					writeConstructor(info, compilation, defaultCtor);
 				}
 				for (FunctionInfo ctor : ctorGroup) {
 					if (ctor != defaultCtor) {
@@ -1201,6 +1235,85 @@
 		return new CallableCompilationContext(returnType, argInfos, args, throwsGError);
 	}
 	
+	private Type writeLoadArgument(MethodVisitor mv, int loadOffset, Type argType) {
+		Class<?> box = getPrimitiveBox(argType);
+		mv.visitVarInsn(argType.getOpcode(ILOAD), loadOffset);		
+		if (box != null) {
+			Type boxedType = Type.getType(box);	
+			mv.visitMethodInsn(INVOKESTATIC, boxedType.getInternalName(), 
+					"valueOf", "(" + argType.getDescriptor() + ")" + boxedType.getDescriptor());
+			return boxedType;
+		}
+		return argType;
+	}
+	
+	private static final class LocalVariable {
+		String name;
+		int offset;
+		Type type;
+		public LocalVariable(String name, int offset, Type type) {
+			super();
+			this.name = name;
+			this.offset = offset;
+			this.type = type;
+		}
+	}
+	
+	private static final class LocalVariableTable {
+		private Map<String,LocalVariable> locals;
+		private int lastOffset;
+		
+		public LocalVariableTable(Type thisArg, List<Type> args, ArgInfo[] argInfos, boolean isCtor) {
+			lastOffset = 0;
+			locals = new LinkedHashMap<String,LocalVariable>();
+			if (thisArg != null) {
+				locals.put("this", new LocalVariable("this", 0, thisArg));
+				lastOffset += thisArg.getSize();
+			}
+			final int thisOffset = (thisArg != null && !isCtor) ? 1 : 0;
+			int i = 0;
+			for (Type arg: args) {
+				String name = argInfos[i+thisOffset].getName();
+				locals.put(name, new LocalVariable(name, lastOffset, arg));
+				lastOffset += arg.getSize();
+				i++;
+			}
+		}
+		
+		public int allocTmp(String name, Type type) {
+			name = "tmp_" + name;
+			LocalVariable ret = new LocalVariable(name, lastOffset, type);
+			lastOffset += type.getSize();
+			locals.put(name, ret);
+			return ret.offset;
+		}
+		
+		public Collection<LocalVariable> getAll() {
+			return locals.values();
+		}
+		
+		public LocalVariable get(int index) {
+			int i = 0;
+			for (LocalVariable variable : locals.values()) {
+				if (i == index)
+					return variable;
+				i++;
+			}
+			throw new IllegalArgumentException();
+		}
+		
+		public int getOffset(String name) {
+			LocalVariable var = locals.get(name);
+			return var.offset;
+		}
+		
+		private void writeLocals(MethodVisitor mv, Label start, Label end) {
+			for (LocalVariable var : getAll()) {
+				mv.visitLocalVariable(var.name, var.type.getDescriptor(), null, start, end, var.offset);
+			}			
+		}
+	}
+	
 	private void writeCallable(int accessFlags, ClassCompilation compilation, FunctionInfo fi,
 			CallableCompilationContext ctx) {
 		String descriptor = Type.getMethodDescriptor(ctx.returnType, ctx.argTypes.toArray(new Type[0]));
@@ -1217,18 +1330,29 @@
 		boolean includeThis = (fi.getFlags() & FunctionInfoFlags.IS_METHOD) > 0;			
 		String symbol = fi.getSymbol();
 		
+		Class<?> returnBox = getPrimitiveBox(ctx.returnType);
+		Type returnTypeBox;
+		if (returnBox != null)
+			returnTypeBox = Type.getType(returnBox);
+		else
+			returnTypeBox = ctx.returnType;
+		
 		mv.visitCode();
 		int nArgs = ctx.argTypes.size();
+		LocalVariableTable locals = new LocalVariableTable(includeThis ? Type.getObjectType(compilation.internalName) : null,
+				ctx.argTypes, ctx.args, false);
+		int functionOffset = locals.allocTmp("function", Type.getType(Function.class));
+		int argsOffset = locals.allocTmp("args", Type.getType(Object[].class));
+		int resultOffset = 0;
+		if (!ctx.returnType.equals(Type.VOID_TYPE))
+			resultOffset = locals.allocTmp("result", returnTypeBox);
+		int errorOffset = 0;
+		if (ctx.throwsGError)
+			errorOffset = locals.allocTmp("error", Type.getType(PointerByReference.class));
 		int nInvokeArgs = nArgs;
 		if (includeThis)
 			nInvokeArgs += 1;
-		int functionOffset = nInvokeArgs+1;
-		int arrayOffset = functionOffset+1;
-		int resultOffset = arrayOffset+1;		
-		int errorOffset = resultOffset;
-		if (ctx.throwsGError)
-			errorOffset += 1;
-		Label jtarget;		
+		Label jtarget;
 		Label l0 = new Label();
 		mv.visitLabel(l0);
 		if (ctx.throwsGError) {
@@ -1246,10 +1370,15 @@
 		mv.visitLabel(l1);
 		mv.visitIntInsn(BIPUSH, nInvokeArgs + (ctx.throwsGError ? 1 : 0));
 		mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
-		for (int i = 0; i < nInvokeArgs; i++) {		
+		for (int i = 0; i < nInvokeArgs; i++) {
 			mv.visitInsn(DUP);
 			mv.visitIntInsn(BIPUSH, i);
-			mv.visitVarInsn(ALOAD, i);
+			if (!includeThis || i > 0) {
+				LocalVariable var = locals.get(i);			
+				writeLoadArgument(mv, var.offset, var.type);			
+			} else {
+				mv.visitVarInsn(ALOAD, 0);
+			}
 			mv.visitInsn(AASTORE);
 		}
 		if (ctx.throwsGError) {
@@ -1258,18 +1387,19 @@
 			mv.visitVarInsn(ALOAD, errorOffset);
 			mv.visitInsn(AASTORE);
 		}
-		mv.visitVarInsn(ASTORE, arrayOffset);
+		mv.visitVarInsn(ASTORE, argsOffset);
 		Label l2 = new Label();
 		mv.visitLabel(l2);
 		mv.visitVarInsn(ALOAD, functionOffset);
 		if (ctx.returnType.equals(Type.VOID_TYPE)) {
 			mv.visitLdcInsn(Type.getType(Void.class));
 		} else {
-			mv.visitLdcInsn(ctx.returnType);
+			mv.visitLdcInsn(returnTypeBox);
 		}
-		mv.visitVarInsn(ALOAD, arrayOffset);
+		mv.visitVarInsn(ALOAD, argsOffset);
 		mv.visitFieldInsn(GETSTATIC, globalInternalsName, "invocationOptions", "Ljava/util/Map;");
-		mv.visitMethodInsn(INVOKEVIRTUAL, "com/sun/jna/Function", "invoke", "(Ljava/lang/Class;[Ljava/lang/Object;Ljava/util/Map;)Ljava/lang/Object;");
+		mv.visitMethodInsn(INVOKEVIRTUAL, "com/sun/jna/Function", "invoke", 
+				"(Ljava/lang/Class;[Ljava/lang/Object;Ljava/util/Map;)Ljava/lang/Object;");
 		Label l3 = new Label();
 		mv.visitLabel(l3);		
 		if (!ctx.throwsGError) {
@@ -1277,20 +1407,24 @@
 				mv.visitInsn(POP);
 				mv.visitInsn(RETURN);
 			} else {
-				mv.visitTypeInsn(CHECKCAST, ctx.returnType.getInternalName());			
-				mv.visitInsn(ARETURN);
+				mv.visitTypeInsn(CHECKCAST, returnTypeBox.getInternalName());
+				if (returnBox != null)
+					mv.visitMethodInsn(INVOKEVIRTUAL, returnTypeBox.getInternalName(), 
+							ctx.returnType.getClassName() + "Value", "()" + ctx.returnType.getDescriptor());
+				mv.visitInsn(ctx.returnType.getOpcode(IRETURN));
 			}
 		} else {
 			jtarget = new Label();
 			if (ctx.returnType.equals(Type.VOID_TYPE)) {
 				mv.visitInsn(POP);
 			} else {
-				mv.visitTypeInsn(CHECKCAST, ctx.returnType.getInternalName());
-				mv.visitInsn(DUP);			
-				mv.visitVarInsn(ASTORE, resultOffset);	
+				mv.visitTypeInsn(CHECKCAST, returnTypeBox.getInternalName());
+				mv.visitInsn(DUP);
+				mv.visitVarInsn(ASTORE, resultOffset);
 			}
 			mv.visitVarInsn(ALOAD, errorOffset);
-			mv.visitMethodInsn(INVOKEVIRTUAL, "com/sun/jna/ptr/PointerByReference", "getPointer", "()Lcom/sun/jna/Pointer;");	
+			mv.visitMethodInsn(INVOKEVIRTUAL, "com/sun/jna/ptr/PointerByReference", 
+					"getPointer", "()Lcom/sun/jna/Pointer;");	
 			mv.visitJumpInsn(IFNONNULL, jtarget);
 			mv.visitTypeInsn(NEW, "org/gnome/gir/gobject/GErrorException");
 			mv.visitInsn(DUP);
@@ -1306,22 +1440,15 @@
 				mv.visitInsn(RETURN);
 			} else {
 				mv.visitVarInsn(ALOAD, resultOffset);
-				mv.visitInsn(ARETURN);
+				if (returnBox != null)
+					mv.visitMethodInsn(INVOKEVIRTUAL, returnTypeBox.getInternalName(), 
+							ctx.returnType.getClassName() + "Value", "()" + ctx.returnType.getDescriptor());				
+				mv.visitInsn(ctx.returnType.getOpcode(IRETURN));
 			}
 		}
 		Label l4 = new Label();
 		mv.visitLabel(l4);
-		if (includeThis) 
-			mv.visitLocalVariable("this", "L" + compilation.internalName + ";", null, l0, l4, 0);
-		int off = includeThis ? 1 : 0;
-		for (int i = 0; i < nArgs; i++) {
-			mv.visitLocalVariable(ctx.args[i+off].getName(), ctx.argTypes.get(i).toString(), null, l0, l4, i+off);		
-		}
-		mv.visitLocalVariable("f", "Lcom/sun/jna/Function;", null, l1, l4, functionOffset);
-		mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l2, l4, arrayOffset);
-		if (!ctx.returnType.equals(Type.VOID_TYPE)) {		
-			mv.visitLocalVariable("result", "L" + ctx.returnType.getInternalName() + ";", null, l2, l4, resultOffset);
-		}
+		locals.writeLocals(mv, l0, l4);
 		mv.visitMaxs(0, 0);
 		mv.visitEnd();
 	}

Modified: trunk/stub-examples/Test.java
==============================================================================
--- trunk/stub-examples/Test.java	(original)
+++ trunk/stub-examples/Test.java	Thu Sep 11 13:16:39 2008
@@ -28,8 +28,15 @@
 	public void setFoo(String arg) {
 		set("foo", arg);
 	}
+	
+	public float moo(long q, String z) {
+		Function target = Internals.library.getFunction("gtk_foo_bar");	
+		Object[] args = new Object[] { q, z };
+		Float result = (Float) target.invoke(Float.class, args, Internals.invocationOptions);
+		return result;
+	}
 
-	public void foo(String x, Double y, Integer z) throws GErrorException {
+	public void foo(String x, double y, Integer z) throws GErrorException {
 		PointerByReference error = new PointerByReference(null);
 		Function target = Internals.library.getFunction("gtk_foo_bar");
 		Object[] args = new Object[] { x, y, z };

Modified: trunk/stub-examples/TestStructure.java
==============================================================================
--- trunk/stub-examples/TestStructure.java	(original)
+++ trunk/stub-examples/TestStructure.java	Thu Sep 11 13:16:39 2008
@@ -5,7 +5,9 @@
 import com.sun.jna.Structure;
 
 public class TestStructure extends Structure {
-	public static class ByValue extends TestStructure implements Structure.ByValue {};
+	public static class ByValue extends TestStructure implements Structure.ByValue {
+		
+	};
 	public static class ByRereference extends TestStructure implements Structure.ByReference {};
 	
 	public TestStructure() {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]