Skip to content

Commit 65d5646

Browse files
author
prepicky
committed
Fixed dynamicjava so that it supports variable arguments in Methods
git-svn-id: file:///tmp/test-svn/trunk@3030 fe72c1cf-3628-48e9-8b72-1c46755d3cff
1 parent c349790 commit 65d5646

File tree

6 files changed

+343
-18
lines changed

6 files changed

+343
-18
lines changed

dynamicjava/src/koala/Version.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
* This file is copied to Version.java by the build process, which also
5454
* fills in the right values of the date and time.
5555
*
56-
* This javadoc corresponds to build drjava-20050328-1824;
56+
* This javadoc corresponds to build drjava-20050413-0716;
5757
*
5858
* @version $Id$
5959
*/
@@ -62,7 +62,7 @@ public abstract class Version {
6262
* This string will be automatically expanded upon "ant commit".
6363
* Do not edit it by hand!
6464
*/
65-
private static final String BUILD_TIME_STRING = "20050328-1824";
65+
private static final String BUILD_TIME_STRING = "20050413-0716";
6666

6767
/** A {@link Date} version of the build time. */
6868
private static final Date BUILD_TIME = _getBuildDate();

dynamicjava/src/koala/dynamicjava/interpreter/EvaluationVisitor.java

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,52 @@ public Object visit(OrExpression node) {
22272227
public Object visit(FunctionCall node) {
22282228
MethodDeclaration md;
22292229
md = (MethodDeclaration)node.getProperty(NodeProperties.FUNCTION);
2230+
List<Expression> larg = node.getArguments();
2231+
2232+
//If the invoked method is a varargs method the parameters must be packaged in an array
2233+
if(md.isVarArgs())
2234+
{
2235+
if(larg == null) //A varargs function was called with no parameters
2236+
{
2237+
ArrayInitializer array = new ArrayInitializer(new LinkedList<Expression>());
2238+
List<Expression> le = new LinkedList<Expression>();
2239+
List<FormalParameter> lfp = md.getParameters();
2240+
Iterator<FormalParameter> itfp = lfp.iterator();
2241+
if(!itfp.hasNext())
2242+
throw new IllegalStateException("Variable Arguments function does not have a formal parameter list");
2243+
array.setElementType(itfp.next().getType());
2244+
2245+
le.add(array);
2246+
node.setArguments(le);
2247+
}
2248+
else //A varargs function was called with parameters
2249+
{
2250+
Iterator<FormalParameter> params = md.getParameters().iterator();
2251+
Iterator<Expression> args = larg.iterator();
2252+
LinkedList<Expression> le = new LinkedList<Expression>();
2253+
FormalParameter fp = null;
2254+
while(params.hasNext())
2255+
{
2256+
fp = params.next();
2257+
if(params.hasNext())
2258+
le.add(args.next());
2259+
}
2260+
2261+
LinkedList<Expression> cells = new LinkedList<Expression>();
2262+
while(args.hasNext())
2263+
{
2264+
cells.add(args.next());
2265+
}
2266+
2267+
ArrayInitializer array = new ArrayInitializer(cells);
2268+
koala.dynamicjava.tree.Type t = fp.getType();
2269+
if(!(t instanceof ArrayType))
2270+
throw new IllegalStateException("Varargs method does not have an array type for its final parameter");
2271+
array.setElementType(((ArrayType)t).getElementType());
2272+
le.add(array);
2273+
node.setArguments(le);
2274+
}
2275+
}
22302276

22312277
// Enter a new scope and define the parameters as local variables
22322278
Context c = new GlobalContext(context.getInterpreter());
@@ -2257,6 +2303,7 @@ public Object visit(FunctionCall node) {
22572303
while (it.hasNext()) {
22582304
it.next().acceptVisitor(nv);
22592305
}
2306+
22602307
body.acceptVisitor(nv);
22612308

22622309
ctx = new GlobalContext(context.getInterpreter());
@@ -2270,7 +2317,18 @@ public Object visit(FunctionCall node) {
22702317
}
22712318
body.acceptVisitor(tc);
22722319
}
2273-
2320+
2321+
List<FormalParameter> params = md.getParameters();
2322+
Iterator<FormalParameter> itParam = params.iterator();
2323+
Class<?>[] typs = new Class<?>[params.size()];
2324+
2325+
//Get the types of parameters that this function accepts
2326+
int i = 0;
2327+
while(itParam.hasNext()){
2328+
typs[i++] = (Class<?>)itParam.next().getProperty(NodeProperties.TYPE);
2329+
}
2330+
2331+
22742332
// Interpret the body of the function
22752333
try {
22762334
body.acceptVisitor(new EvaluationVisitor(c));

dynamicjava/src/koala/dynamicjava/interpreter/context/GlobalContext.java

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,9 @@ public MethodDeclaration lookupFunction(String mname, Class<?>[] params)
700700
throws NoSuchFunctionException {
701701
Iterator<MethodDeclaration> it = functions.iterator();
702702
List<MethodDeclaration> f = new LinkedList<MethodDeclaration>();
703-
703+
List<MethodDeclaration> compatible = new LinkedList<MethodDeclaration>();
704+
705+
//Do a first pass to find basic methods that match the parameters
704706
while (it.hasNext()) {
705707
MethodDeclaration md = it.next();
706708
if (md.getName().equals(mname)) {
@@ -714,7 +716,7 @@ public MethodDeclaration lookupFunction(String mname, Class<?>[] params)
714716
List<FormalParameter> l = md.getParameters();
715717

716718
if (l.size() != params.length) {
717-
continue;
719+
//continue;
718720
}
719721

720722
Class<?>[] p = new Class<?>[l.size()];
@@ -724,13 +726,80 @@ public MethodDeclaration lookupFunction(String mname, Class<?>[] params)
724726
p[i++] = NodeProperties.getType(it2.next());
725727
}
726728

727-
if (ReflectionUtilities.hasCompatibleSignatures(p, params)) {
728-
return md;
729+
if(ReflectionUtilities.hasCompatibleSignatures(p, params)) {
730+
compatible.add(md);
731+
}
732+
}
733+
734+
if(!compatible.isEmpty())
735+
{
736+
return ReflectionUtilities.selectTheMostSpecificFunction(compatible);
737+
}
738+
739+
//Do a second pass to find methods that match using autoboxing
740+
741+
it = f.iterator();
742+
743+
while(it.hasNext()) {
744+
MethodDeclaration md = it.next();
745+
List<FormalParameter> l = md.getParameters();
746+
747+
//With autoboxing the arguments must still be the same length
748+
if(l.size() != params.length)
749+
continue;
750+
751+
Class<?>[] p = new Class<?>[l.size()];
752+
Iterator<FormalParameter> it2 = l.iterator();
753+
int i = 0;
754+
while(it2.hasNext()) {
755+
p[i++] = NodeProperties.getType(it2.next());
729756
}
757+
758+
ReflectionUtilities.TigerUsage tu = new ReflectionUtilities.TigerUsage();
759+
760+
if(ReflectionUtilities.hasAutoBoxingCompatibleSignatures(p, params, tu)) {
761+
compatible.add(md);
762+
//throw new RuntimeException("Found a function that matches using Autoboxing!");
763+
}
764+
}
765+
766+
//Select the most specific function using autoboxing
767+
if (!compatible.isEmpty()) {
768+
return ReflectionUtilities.selectTheMostSpecificBoxingFunction(compatible);
730769
}
731-
732770

733-
throw new NoSuchFunctionException(mname);
771+
//Do a third pass now trying to find methods that match using varArgs constructs
772+
773+
it = f.iterator();
774+
while(it.hasNext()) {
775+
MethodDeclaration md = it.next();
776+
List<FormalParameter> l = md.getParameters();
777+
778+
Class<?>[] p = new Class<?>[l.size()];
779+
Iterator<FormalParameter> it2 = l.iterator();
780+
int i = 0;
781+
while(it2.hasNext()) {
782+
p[i++] = NodeProperties.getType(it2.next());
783+
}
784+
ReflectionUtilities.TigerUsage tu = new ReflectionUtilities.TigerUsage();
785+
786+
if (ReflectionUtilities.hasVarArgsCompatibleSignatures(p, params, tu)) {
787+
tu.checkForCompatibleUsage();
788+
compatible.add(md);
789+
}
790+
}
791+
792+
if(compatible.isEmpty()){
793+
throw new NoSuchFunctionException("No such function: " + mname);
794+
}
795+
else if (compatible.size() == 1) {
796+
return compatible.get(0);
797+
}
798+
else {
799+
// It is ambiguous if more than one variable-argument
800+
// method matches the given parameter type list.
801+
throw new NoSuchFunctionException("Ambiguous Methods: " + mname + " " + compatible.get(0).getParameters() + ", " + compatible.get(1).getParameters());
802+
}
734803
}
735804

736805
/**

dynamicjava/src/koala/dynamicjava/tree/MethodDeclaration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,12 @@ public void setBody(BlockStatement bs) {
257257
public boolean isVarArgs(){
258258
return (accessFlags & 0x00000080) != 0; // java.lang.reflect.Modifier.VARARGS == 0x00000080 /**/
259259
}
260+
261+
// Not strictly needed. just added as a convenience /**/
262+
public boolean isBridge(){
263+
return (accessFlags & 0x00000040) != 0; // java.lang.reflect.Modifier.BRIDGE == 0x00000040 /**/
264+
}
265+
260266

261267
/**
262268
* Allows a visitor to traverse the tree
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*BEGIN_COPYRIGHT_BLOCK
2+
*
3+
* This file is part of DrJava. Download the current version of this project:
4+
* http://sourceforge.net/projects/drjava/ or http://www.drjava.org/
5+
*
6+
* DrJava Open Source License
7+
*
8+
* Copyright (C) 2001-2003 JavaPLT group at Rice University (javaplt@rice.edu)
9+
* All rights reserved.
10+
*
11+
* Developed by: Java Programming Languages Team
12+
* Rice University
13+
* http://www.cs.rice.edu/~javaplt/
14+
*
15+
* Permission is hereby granted, free of charge, to any person obtaining a
16+
* copy of this software and associated documentation files (the "Software"),
17+
* to deal with the Software without restriction, including without
18+
* limitation the rights to use, copy, modify, merge, publish, distribute,
19+
* sublicense, and/or sell copies of the Software, and to permit persons to
20+
* whom the Software is furnished to do so, subject to the following
21+
* conditions:
22+
*
23+
* - Redistributions of source code must retain the above copyright
24+
* notice, this list of conditions and the following disclaimers.
25+
* - Redistributions in binary form must reproduce the above copyright
26+
* notice, this list of conditions and the following disclaimers in the
27+
* documentation and/or other materials provided with the distribution.
28+
* - Neither the names of DrJava, the JavaPLT, Rice University, nor the
29+
* names of its contributors may be used to endorse or promote products
30+
* derived from this Software without specific prior written permission.
31+
* - Products derived from this software may not be called "DrJava" nor
32+
* use the term "DrJava" as part of their names without prior written
33+
* permission from the JavaPLT group. For permission, write to
34+
* javaplt@rice.edu.
35+
*
36+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
39+
* THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
40+
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
41+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
42+
* OTHER DEALINGS WITH THE SOFTWARE.
43+
*
44+
END_COPYRIGHT_BLOCK*/
45+
46+
package koala.dynamicjava.util;
47+
48+
import koala.dynamicjava.tree.MethodDeclaration;
49+
50+
/**
51+
* This exception is thrown when more than one method is acceptable
52+
* during a method lookup due to the new features added in 1.5
53+
*/
54+
public class AmbiguousFunctionException extends RuntimeException {
55+
56+
private MethodDeclaration[] _methods;
57+
58+
/**
59+
* Public constructor - calls the super class constructor
60+
* @param e - the message to be shown when the exception occurs
61+
*/
62+
public AmbiguousFunctionException(String e) {
63+
super(e);
64+
_methods = new MethodDeclaration[0];
65+
}
66+
public AmbiguousFunctionException(MethodDeclaration m1, MethodDeclaration m2) {
67+
super("Both functions match:" + m1 + ", and " + m2);
68+
_methods = new MethodDeclaration[]{m1,m2};
69+
}
70+
}

0 commit comments

Comments
 (0)