/interpreter/tags/at2dist220411/src/edu/vub/at/objects/symbiosis/JavaClosure.java
Java | 131 lines | 63 code | 15 blank | 53 comment | 14 complexity | 311e1ff571ee1898da0c1928747fe47c MD5 | raw file
1/** 2 * AmbientTalk/2 Project 3 * JavaClosure.java created on 9-dec-2006 at 21:16:12 4 * (c) Programming Technology Lab, 2006 - 2007 5 * Authors: Tom Van Cutsem & Stijn Mostinckx 6 * 7 * Permission is hereby granted, free of charge, to any person 8 * obtaining a copy of this software and associated documentation 9 * files (the "Software"), to deal in the Software without 10 * restriction, including without limitation the rights to use, 11 * copy, modify, merge, publish, distribute, sublicense, and/or 12 * sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following 14 * conditions: 15 * 16 * The above copyright notice and this permission notice shall be 17 * included in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 * OTHER DEALINGS IN THE SOFTWARE. 27 */ 28package edu.vub.at.objects.symbiosis; 29 30import edu.vub.at.exceptions.InterpreterException; 31import edu.vub.at.exceptions.XSymbiosisFailure; 32import edu.vub.at.objects.ATClosure; 33import edu.vub.at.objects.ATContext; 34import edu.vub.at.objects.ATObject; 35import edu.vub.at.objects.natives.NATClosure; 36import edu.vub.at.objects.natives.NATContext; 37import edu.vub.at.objects.natives.NATNumber; 38import edu.vub.at.objects.natives.NATTable; 39import edu.vub.at.objects.natives.NATText; 40 41import java.lang.reflect.Array; 42import java.lang.reflect.Method; 43import java.util.Vector; 44 45/** 46 * A JavaClosure pairs a JavaMethod (a bundle of native overloaded java.lang.reflect.Method objects) 47 * together with a Java object receiver. 48 * 49 * It also provides the possibility of casting the JavaMethod instances to fit a 50 * narrower static type signature. 51 * 52 * @author tvcutsem 53 */ 54public final class JavaClosure extends NATClosure implements ATJavaClosure { 55 56 private final ATObject scope_; 57 58 public JavaClosure(ATObject scope, JavaMethod meth) { 59 super(meth, null); 60 scope_ = scope; 61 } 62 63 /** 64 * Overridden to allow for lazy instantiation of the context. 65 * 66 * A 'default' context is lazily constructed and returned. 67 */ 68 public ATContext base_context() throws InterpreterException { 69 if (context_ == null) 70 context_ = new NATContext(scope_, scope_); 71 return context_; 72 } 73 74 public NATText meta_print() throws InterpreterException { 75 return NATText.atValue("<java closure:"+base_method().base_name().base_text().asNativeText().javaValue+">"); 76 } 77 78 /** 79 * For each Method in the wrapped JavaMethod's choices_, check whether it is compatible with 80 * the given types. If so, add it to the choices_ array of the new JavaMethod. 81 */ 82 public ATClosure base_cast(ATObject[] types) throws InterpreterException { 83 Method[] choices = ((JavaMethod) method_).choices_; 84 85 // unwrap the JavaClass wrappers 86 Class[] actualTypes = new Class[types.length]; 87 for (int i = 0; i < actualTypes.length; i++) { 88 // Array types may be represented as one-arg tables of a type: [Type] 89 // TODO: properly refactor the instanceof test 90 // problem: cannot do base_isTable because JavaObject/JavaClass objects will say yes! 91 if (types[i] instanceof NATTable) { 92 // Array.newInstance([Type][1],0).getClass() 93 actualTypes[i] = Array.newInstance(types[i].asTable(). 94 base_at(NATNumber.ONE).asJavaClassUnderSymbiosis().getWrappedClass(), 0).getClass(); 95 } else { 96 actualTypes[i] = types[i].asJavaClassUnderSymbiosis().getWrappedClass(); 97 } 98 } 99 Vector matchingMethods = new Vector(); 100 101 for (int i = 0; i < choices.length; i++) { 102 if(matches(choices[i].getParameterTypes(), actualTypes)) { 103 matchingMethods.add(choices[i]); 104 } 105 } 106 107 Method[] matches = (Method[]) matchingMethods.toArray(new Method[matchingMethods.size()]); 108 if (matches.length > 0) { 109 return new JavaClosure(scope_, new JavaMethod(matches)); 110 } else { 111 throw new XSymbiosisFailure(scope_, choices[0], types); 112 } 113 } 114 115 /** 116 * Compares two Class arrays and returns true iff both arrays have equal size and all members are the same. 117 */ 118 private static final boolean matches(Class[] formals, Class[] actuals) { 119 if (formals.length != actuals.length) 120 return false; 121 122 for (int i = 0; i < formals.length; i++) { 123 if (!(formals[i] == actuals[i])) { 124 return false; 125 } 126 } 127 128 return true; 129 } 130 131}