Re: Java interface compatibility.
Artem Gr <[email protected]> Tue, 19 Apr 2005 12:04:12 +0400
| Newsgroups | gmane.comp.lang.nice.devel |
|---|---|
| Message-ID | <[email protected]> |
Attached is the cleaned up version of the patch. ( http://rafb.net/paste/results/LuOiNe27.html ) Before commiting this, I am going to work on testcases. Daniel Bonniot mentioned the possibility to optimize away the instanceof tests from the generated dispatch methods.
LuOiNe27.txt
(text/plain, 6.7 KB)
Index: src/bossa/syntax/compilation.nice
===================================================================
RCS file: /cvsroot/nice/Nice/src/bossa/syntax/compilation.nice,v
retrieving revision 1.8
diff -u -r1.8 compilation.nice
--- src/bossa/syntax/compilation.nice 26 Mar 2005 15:33:02 -0000 1.8
+++ src/bossa/syntax/compilation.nice 18 Apr 2005 19:10:07 -0000
@@ -22,12 +22,10 @@
make("java.lang.Error").getDeclaredMethod("<init>",
[cast(gnu.bytecode.Type.string_type)]);
-public void compileNiceMethod(NiceMethod m,
- Stack<Alternative> sortedAlternatives,
- bossa.modules.Package module)
-{
- gnu.expr.LambdaExp lexp = m.getLambda();
-
+private void makeBody(NiceMethod m,
+ gnu.expr.LambdaExp lexp,
+ Stack<Alternative> sortedAlternatives){
+
// parameters of the alternative function are the same in each case,
// so we compute them just once
int arity = m.getArity();
@@ -39,15 +37,60 @@
params[rank++] = new gnu.expr.ReferenceExp(param);
gnu.expr.Expression body = dispatchNiceMethod
- (sortedAlternatives.iterator(),
- m.javaReturnType(), m.javaReturnType().isVoid(), params);
+ (sortedAlternatives.iterator(),
+ m.javaReturnType(), m.javaReturnType().isVoid(), params);
if (m.isMain())
body = beautifyUncaughtExceptions(body);
- nice.tools.code.Gen.setMethodBody(lexp, m.getContract().compile(body));
+ body = m.getContract().compile(body);
+ nice.tools.code.Gen.setMethodBody(lexp, body);
}
-
+
+public void compileNiceMethod(NiceMethod m,
+ Stack<Alternative> sortedAlternatives,
+ bossa.modules.Package module)
+{
+ gnu.expr.LambdaExp lexp = m.getLambda();
+
+ makeBody( m, lexp, sortedAlternatives );
+
+ if(m.getArity() != 0){
+ ?NiceClass iface = getNiceClass(m.getArgTypes()[0]);
+ if(iface != null && iface.isInterface() && ! ( m instanceof MethodWithDefault )){
+
+ // If alternative method is implementing an interface,
+ // then generate a dispatch method as a class member,
+ // for Java interface invocations to find the implementation.
+
+ if(bossa.util.Debug.codeGeneration)
+ bossa.util.Debug.println("Generating Nice interface signature for " iface );
+ String name = m.getName().toString();
+ let argTypes = m.javaArgTypes();
+ let retType = m.javaReturnType();
+ let fullName = m.getFullName();
+ gnu.expr.LambdaExp res = generateMethod
+ (name, argTypes, retType, m.getSymbols(), toplevel: true, member: true);
+ res.parameterCopies = cast(notNull(m.formalParameters()).getParameterCopies());
+ iface.addJavaMethod(res);
+
+ for(alt : sortedAlternatives){
+ ?NiceClass cl = declaringClass(alt);
+ if(cl == null) continue;
+ if(bossa.util.Debug.codeGeneration)
+ bossa.util.Debug.println("Generating Nice dispatch function (interface implementation) for " alt);
+
+ res = generateMethod
+ (name, argTypes, retType, m.getSymbols(), toplevel: true, member: true);
+ res.parameterCopies = cast(notNull(m.formalParameters()).getParameterCopies());
+ res.addBytecodeAttribute(new gnu.bytecode.MiscAttr("id", fullName.getBytes()));
+ makeBody( m, res, sortedAlternatives );
+ cl.addJavaMethod(res);
+ }
+ }
+ }
+}
+
private gnu.expr.Expression dispatchNiceMethod(Iterator<Alternative> sortedAlternatives,
gnu.bytecode.Type returnType,
boolean voidReturn,
@@ -145,18 +188,24 @@
}
}
-private NiceClass declaringClass(JavaMethod m, Alternative alt)
+private ?NiceClass declaringClass(Alternative alt)
{
?mlsub.typing.TypeConstructor firstArgument = alt.getPatterns()[0].getTC();
let def = getTypeDefinition(firstArgument);
if (def != null && def.getImplementation() instanceof NiceClass)
return cast(def.getImplementation());
+ return null;
+}
+
+private NiceClass declaringClass(JavaMethod m, Alternative alt)
+{
+ let cl = declaringClass(alt); if(cl != null) return cl;
// Explain that this cannot be done.
String msg = m + " is a native method.\n";
- if (firstArgument == null)
+ if (maybeNull(firstArgument) == null)
msg += "It cannot be implemented without dispatch on the first argument";
else
msg += "It cannot be overriden because the first argument " +
Index: src/bossa/syntax/modifiers.nice
===================================================================
RCS file: /cvsroot/nice/Nice/src/bossa/syntax/modifiers.nice,v
retrieving revision 1.1
diff -u -r1.1 modifiers.nice
--- src/bossa/syntax/modifiers.nice 25 Nov 2004 19:28:18 -0000 1.1
+++ src/bossa/syntax/modifiers.nice 18 Apr 2005 19:10:07 -0000
@@ -125,6 +125,7 @@
void makeInterface( )
{
this.setModifier( INTERFACE );
+ this.setModifier( ABSTRACT );
}
boolean isInterface() = this.getModifier( INTERFACE );
@@ -151,7 +152,8 @@
if( this.getModifier( VOLATILE ) ) buf.append(" volatile");
if( this.getModifier( TRANSIENT ) ) buf.append(" transient");
if( this.getModifier( NATIVE ) ) buf.append(" native");
- if( this.getModifier( ABSTRACT ) ) buf.append(" abstract");
+ if( ! this.getModifier( INTERFACE ) )
+ if( this.getModifier( ABSTRACT ) ) buf.append(" abstract");
return buf.toString();
}
}
Index: src/gnu/bytecode/Method.java
===================================================================
RCS file: /cvsroot/nice/Nice/src/gnu/bytecode/Method.java,v
retrieving revision 1.9
diff -u -r1.9 Method.java
--- src/gnu/bytecode/Method.java 2 Mar 2004 20:21:11 -0000 1.9
+++ src/gnu/bytecode/Method.java 18 Apr 2005 19:10:08 -0000
@@ -241,7 +241,7 @@
throws java.io.IOException
{
- if (code == null)
+ if (code == null && !isAbstract())
throw new Error("Method "+this+" has no code");
//return;
Index: src/gnu/expr/LambdaExp.java
===================================================================
RCS file: /cvsroot/nice/Nice/src/gnu/expr/LambdaExp.java,v
retrieving revision 1.30
diff -u -r1.30 LambdaExp.java
--- src/gnu/expr/LambdaExp.java 20 Feb 2005 22:09:39 -0000 1.30
+++ src/gnu/expr/LambdaExp.java 18 Apr 2005 19:10:12 -0000
@@ -1525,13 +1525,17 @@
decl.var = null;
}
}
- comp.method.initCode();
- allocChildClasses(comp);
- allocParameters(comp);
- enterFunction(comp);
-
- compileBody(comp);
- compileEnd(comp);
+ if (comp.curClass.isInterface() && comp.method.isAbstract()){
+ // Interface method. Skip code generation.
+ }else{
+ comp.method.initCode();
+ allocChildClasses(comp);
+ allocParameters(comp);
+ enterFunction(comp);
+
+ compileBody(comp);
+ compileEnd(comp);
+ }
}
}