[Nice-commit] Nice/src/bossa/link SourceAlternative.java,1.1,1.2 ImportedAlternative.java,1.3,1.4 Di
Brought to you by:
bonniot
Update of /cvsroot/nice/Nice/src/bossa/link
In directory sc8-pr-cvs1:/tmp/cvs-serv18316/src/bossa/link
Modified Files:
SourceAlternative.java ImportedAlternative.java Dispatch.java
Compilation.java Alternative.java
Log Message:
Allow implementations of native methods to dispatch on all their arguments.
Index: SourceAlternative.java
===================================================================
RCS file: /cvsroot/nice/Nice/src/bossa/link/SourceAlternative.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** SourceAlternative.java 6 Nov 2002 09:56:26 -0000 1.1
--- SourceAlternative.java 18 Apr 2003 14:50:27 -0000 1.2
***************
*** 23,32 ****
*/
! public class SourceAlternative extends Alternative
{
public SourceAlternative(MethodBodyDefinition implementation)
{
super(implementation.getDeclaration().getName().toString(),
! ((NiceMethod) implementation.getDeclaration()).getFullName(),
implementation.getPatterns());
this.implementation = implementation;
--- 23,32 ----
*/
! public class SourceAlternative extends Alternative implements Located
{
public SourceAlternative(MethodBodyDefinition implementation)
{
super(implementation.getDeclaration().getName().toString(),
! implementation.getDeclaration().getFullName(),
implementation.getPatterns());
this.implementation = implementation;
***************
*** 34,37 ****
--- 34,42 ----
private MethodBodyDefinition implementation;
+
+ public Location location()
+ {
+ return implementation.location();
+ }
String printLocated()
Index: ImportedAlternative.java
===================================================================
RCS file: /cvsroot/nice/Nice/src/bossa/link/ImportedAlternative.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** ImportedAlternative.java 17 Sep 2002 16:29:34 -0000 1.3
--- ImportedAlternative.java 18 Apr 2003 14:50:27 -0000 1.4
***************
*** 14,17 ****
--- 14,20 ----
import bossa.syntax.Pattern;
+ import bossa.syntax.LocatedString;
+ import bossa.syntax.MethodDeclaration;
+ import bossa.syntax.JavaMethod;
import nice.tools.code.*;
***************
*** 20,23 ****
--- 23,27 ----
import java.util.*;
import bossa.util.*;
+ import bossa.util.Location;
/**
***************
*** 33,37 ****
* When read from a bytecode file.
*/
! public static void read(ClassType c, Method method)
{
MiscAttr attr = (MiscAttr) Attribute.get(method, "definition");
--- 37,41 ----
* When read from a bytecode file.
*/
! public static void read(ClassType c, Method method, Location location)
{
MiscAttr attr = (MiscAttr) Attribute.get(method, "definition");
***************
*** 42,45 ****
--- 46,51 ----
String fullName = new String(attr.data);
+ registerJavaMethod(fullName);
+
attr = (MiscAttr) Attribute.get(method, "patterns");
if (attr == null)
***************
*** 71,86 ****
new ImportedAlternative(method.getName(), fullName, (Pattern[])
patterns.toArray(new Pattern[patterns.size()]),
! new QuoteExp(new PrimProcedure(method)));
}
! private ImportedAlternative(String name, String fullName, Pattern[] patterns,
! gnu.expr.Expression code)
{
super(name, fullName, patterns);
this.code = code;
! }
public Expression methodExp() { return code; }
private Expression code;
}
--- 77,127 ----
new ImportedAlternative(method.getName(), fullName, (Pattern[])
patterns.toArray(new Pattern[patterns.size()]),
! new QuoteExp(new PrimProcedure(method)),
! location);
}
! /**
! If this full name refers to a java method, make sure it participates
! to the link tests and dispatch code generation.
! */
! private static void registerJavaMethod(String fullName)
! {
! if (! fullName.startsWith(JavaMethod.fullNamePrefix))
! return;
!
! int end = fullName.lastIndexOf(':');
! LocatedString methodName = new LocatedString
! (fullName.substring(JavaMethod.fullNamePrefix.length(), end),
! bossa.util.Location.nowhereAtAll());
!
! List methods = bossa.syntax.Node.getGlobalScope().lookup(methodName);
! for (Iterator i = methods.iterator(); i.hasNext();)
! {
! Object next = i.next();
! if (! (next instanceof MethodDeclaration.Symbol))
! continue;
! MethodDeclaration md = ((MethodDeclaration.Symbol) next).getDefinition();
! if (md.getFullName().equals(fullName))
! {
! ((JavaMethod) md).registerForDispatch();
! return;
! }
! }
! }
!
! private ImportedAlternative(String name, String fullName, Pattern[] patterns,
! gnu.expr.Expression code, Location location)
{
super(name, fullName, patterns);
this.code = code;
! this.location = location;
! }
public Expression methodExp() { return code; }
private Expression code;
+
+ public Location location() { return location; }
+
+ private Location location;
}
Index: Dispatch.java
===================================================================
RCS file: /cvsroot/nice/Nice/src/bossa/link/Dispatch.java,v
retrieving revision 1.52
retrieving revision 1.53
diff -C2 -d -r1.52 -r1.53
*** Dispatch.java 20 Mar 2003 00:03:52 -0000 1.52
--- Dispatch.java 18 Apr 2003 14:50:27 -0000 1.53
***************
*** 25,28 ****
--- 25,30 ----
import mlsub.typing.lowlevel.Element;
+ import gnu.bytecode.ClassType;
+
import java.util.*;
***************
*** 47,52 ****
}
! private static Collection methods;
! public static void reset() { methods = new ArrayList(); }
private static Chronometer chrono = Chronometer.make("Dispatch tests");
--- 49,63 ----
}
! public static void register(JavaMethod m)
! {
! javaMethods.add(m);
! }
!
! private static Collection methods, javaMethods;
! public static void reset()
! {
! methods = new ArrayList();
! javaMethods = new ArrayList();
! }
private static Chronometer chrono = Chronometer.make("Dispatch tests");
***************
*** 58,61 ****
--- 69,75 ----
for(Iterator i = methods.iterator(); i.hasNext();)
test((NiceMethod) i.next(), module);
+
+ for (Iterator i = javaMethods.iterator(); i.hasNext();)
+ test((JavaMethod) i.next(), module);
}
finally {
***************
*** 69,73 ****
if (!(m.isMain() || trivialTestOK(sortedAlternatives)))
! test(m, sortedAlternatives);
if(Debug.codeGeneration)
--- 83,87 ----
if (!(m.isMain() || trivialTestOK(sortedAlternatives)))
! test(m, sortedAlternatives, false);
if(Debug.codeGeneration)
***************
*** 77,80 ****
--- 91,107 ----
}
+ private static void test(JavaMethod m, bossa.modules.Package module)
+ {
+ Stack sortedAlternatives = Alternative.sortedAlternatives(m);
+
+ if (! trivialTestOK(sortedAlternatives))
+ test(m, sortedAlternatives, true);
+
+ if(Debug.codeGeneration)
+ Debug.println("Generating dispatch function for " + m);
+
+ Compilation.compile(m, sortedAlternatives, module);
+ }
+
private static boolean trivialTestOK(Stack alternatives)
{
***************
*** 109,114 ****
}
! private static void test(NiceMethod method,
! final Stack sortedAlternatives)
{
if(Debug.linkTests)
--- 136,142 ----
}
! private static void test(MethodDeclaration method,
! final Stack sortedAlternatives,
! boolean isJavaMethod)
{
if(Debug.linkTests)
***************
*** 135,140 ****
{
TypeConstructor[] tags = (TypeConstructor[]) i.next();
! if (test(method, tags, sortedAlternatives))
{
if (++nb_errors > 9)
--- 163,178 ----
{
TypeConstructor[] tags = (TypeConstructor[]) i.next();
+
+ // For java methods, we are only concerned with cases
+ // where the first argument is a Nice class.
+ ClassType firstArg = null;
+ if (isJavaMethod)
+ {
+ firstArg = classTypeOfNiceClass(tags[0]);
+ if (firstArg == null)
+ continue;
+ }
! if (test(method, tags, sortedAlternatives, firstArg))
{
if (++nb_errors > 9)
***************
*** 151,155 ****
method.getName());
}
!
/**
Tests that the 'tags' tuple has a best-match in alternatives
--- 189,203 ----
method.getName());
}
!
! private static ClassType classTypeOfNiceClass(TypeConstructor tc)
! {
! ClassDefinition def = ClassDefinition.get(tc);
!
! if (def == null || ! (def.getImplementation() instanceof NiceClass))
! return null;
!
! return ((NiceClass) def.getImplementation()).getClassExp().getClassType();
! }
!
/**
Tests that the 'tags' tuple has a best-match in alternatives
***************
*** 161,167 ****
@return true if the test failed
*/
! private static boolean test(NiceMethod method,
TypeConstructor[] tags,
! final Stack sortedAlternatives)
{
boolean failed = false;
--- 209,216 ----
@return true if the test failed
*/
! private static boolean test(MethodDeclaration method,
TypeConstructor[] tags,
! final Stack sortedAlternatives,
! ClassType firstArg)
{
boolean failed = false;
***************
*** 192,197 ****
}
}
! if(first==null)
{
failed = true;
if(sortedAlternatives.size()==0)
--- 241,256 ----
}
}
! if (first == null)
{
+ if (firstArg != null)
+ {
+ gnu.bytecode.Method superImplementation = SuperExp.getImplementationAbove
+ ((JavaMethod) method, firstArg);
+ if (superImplementation != null &&
+ superImplementation.isAbstract() == false)
+ // It's OK, this case is covered by a Java implementation.
+ return false;
+ }
+
failed = true;
if(sortedAlternatives.size()==0)
***************
*** 211,219 ****
Special version of above that tests tags with all combinations of integer values.
*/
! private static boolean testValues(NiceMethod method,
! TypeConstructor[] tags,
! List valueCombis,
! boolean[] isValue,
! final Stack sortedAlternatives)
{
boolean failed = false;
--- 270,279 ----
Special version of above that tests tags with all combinations of integer values.
*/
! private static boolean testValues
! (MethodDeclaration method,
! TypeConstructor[] tags,
! List valueCombis,
! boolean[] isValue,
! final Stack sortedAlternatives)
{
boolean failed = false;
Index: Compilation.java
===================================================================
RCS file: /cvsroot/nice/Nice/src/bossa/link/Compilation.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** Compilation.java 29 Mar 2003 19:26:24 -0000 1.10
--- Compilation.java 18 Apr 2003 14:50:29 -0000 1.11
***************
*** 22,25 ****
--- 22,26 ----
import nice.tools.code.Gen;
+ import bossa.util.User;
import java.util.*;
***************
*** 95,101 ****
else
return gnu.expr.SimpleIfExp.make
! (alt.matchTest(params),
matchCase,
dispatch(sortedAlternatives, returnType, voidReturn, params));
}
}
--- 96,211 ----
else
return gnu.expr.SimpleIfExp.make
! (alt.matchTest(params, false),
matchCase,
dispatch(sortedAlternatives, returnType, voidReturn, params));
+ }
+
+ /****************************************************************
+ * Java Methods
+ ****************************************************************/
+
+ static void compile(JavaMethod m,
+ Stack sortedAlternatives,
+ bossa.modules.Package module)
+ {
+ int arity = m.getArity();
+
+ while (sortedAlternatives.size() > 0)
+ {
+ // We pick a class, and compile all implementations whose
+ // first argument is at that class.
+ Iterator i = sortedAlternatives.iterator();
+ Alternative a = (Alternative) i.next();
+ NiceClass c = declaringClass(m, a);
+ i.remove();
+
+ List l = new LinkedList();
+ l.add(a);
+ while (i.hasNext())
+ {
+ a = (Alternative) i.next();
+ if (declaringClass(m, a) == c)
+ {
+ l.add(a);
+ i.remove();
+ }
+ }
+
+ Expression[] params = new Expression[arity];
+ LambdaExp lambda =
+ Gen.createMemberMethod
+ (m.getName().toString(),
+ c.getClassExp().getType(),
+ m.javaArgTypes(),
+ m.javaReturnType(),
+ params);
+
+ c.addJavaMethod(lambda);
+ Expression body = dispatchJavaMethod
+ (l.iterator(), m.javaReturnType(), m.javaReturnType().isVoid(),
+ params, (ClassType) c.getClassExp().getType(), m);
+ Gen.setMethodBody(lambda, body);
+ }
+ }
+
+ private static NiceClass declaringClass(JavaMethod m, Alternative alt)
+ {
+ mlsub.typing.TypeConstructor firstArgument = alt.getPatterns()[0].tc;
+ ClassDefinition def = ClassDefinition.get(firstArgument);
+
+ if (def == null || ! (def.getImplementation() instanceof NiceClass))
+ throw User.error(alt,
+ m + " is a native method.\n" +
+ "It can not be overriden because the first argument" +
+ (firstArgument == null
+ ? ""
+ : " " + firstArgument.toString())
+ + " is not a class defined in Nice");
+
+ return (NiceClass) def.getImplementation();
+ }
+
+ private static Expression dispatchJavaMethod
+ (Iterator sortedAlternatives,
+ Type returnType,
+ boolean voidReturn,
+ Expression[] params,
+ ClassType c, JavaMethod m)
+ {
+ if (!sortedAlternatives.hasNext())
+ {
+ // Call super.
+ ClassType superClass = c.getSuperclass();
+ gnu.bytecode.Method superMethod = superClass.getMethod
+ (m.getName().toString(), m.javaArgTypes());
+ if (superMethod != null)
+ return new ApplyExp
+ (new QuoteExp(PrimProcedure.specialCall(superMethod)), params);
+
+ // We produce code that should never be reached at run-time.
+
+ Expression message = new QuoteExp("Message not understood");
+ Expression exception = new ApplyExp(new InstantiateProc(newError),
+ new Expression[]{ message });
+ Expression throwExp =
+ new ApplyExp(nice.lang.inline.Throw.instance,
+ new Expression[]{exception});
+
+ return throwExp;
+ }
+
+ Alternative alt = (Alternative) sortedAlternatives.next();
+ Expression matchCase = new ApplyExp(alt.methodExp(), params);
+
+ if(voidReturn)
+ matchCase = new BeginExp(matchCase, Gen.returnVoid());
+ else
+ matchCase = Gen.returnValue(matchCase);
+
+ return gnu.expr.SimpleIfExp.make
+ (alt.matchTest(params, /* skip first */ true),
+ matchCase,
+ dispatchJavaMethod(sortedAlternatives, returnType, voidReturn,
+ params, c, m));
}
}
Index: Alternative.java
===================================================================
RCS file: /cvsroot/nice/Nice/src/bossa/link/Alternative.java,v
retrieving revision 1.40
retrieving revision 1.41
diff -C2 -d -r1.40 -r1.41
*** Alternative.java 29 Mar 2003 19:26:24 -0000 1.40
--- Alternative.java 18 Apr 2003 14:50:29 -0000 1.41
***************
*** 17,21 ****
import mlsub.typing.*;
! import bossa.syntax.NiceMethod;
import bossa.syntax.Pattern;
import bossa.syntax.LocatedString;
--- 17,21 ----
import mlsub.typing.*;
! import bossa.syntax.MethodDeclaration;
import bossa.syntax.Pattern;
import bossa.syntax.LocatedString;
***************
*** 38,42 ****
*/
! public abstract class Alternative
{
/**
--- 38,42 ----
*/
! public abstract class Alternative implements Located
{
/**
***************
*** 139,143 ****
the tuple <code>parameters</code>.
*/
! Expression matchTest(Expression[] parameters)
{
if (parameters.length != patterns.length)
--- 139,143 ----
the tuple <code>parameters</code>.
*/
! Expression matchTest(Expression[] parameters, boolean skipFirst)
{
if (parameters.length != patterns.length)
***************
*** 146,157 ****
" for " + this);
! if (parameters.length == 0)
return QuoteExp.trueExp;
! if (parameters.length == 1)
! return patterns[0].matchTest(parameters[0]);
Expression result = QuoteExp.trueExp;
- int index = 0;
//find the first non-trivial test
--- 146,158 ----
" for " + this);
! int index = skipFirst ? 1 : 0;
!
! if (parameters.length == index)
return QuoteExp.trueExp;
! if (parameters.length == index + 1)
! return patterns[index].matchTest(parameters[index]);
Expression result = QuoteExp.trueExp;
//find the first non-trivial test
***************
*** 212,216 ****
}
! public static Stack sortedAlternatives(NiceMethod m)
{
List list = (List) alternatives.get(m.getFullName());
--- 213,217 ----
}
! public static Stack sortedAlternatives(MethodDeclaration m)
{
List list = (List) alternatives.get(m.getFullName());
|