use of org.apache.xalan.xsltc.compiler.util.Type in project servicemix-bundles by apache.
the class FunctionCall method typeCheckConstructor.
public Type typeCheckConstructor(SymbolTable stable) throws TypeCheckError {
final Vector constructors = findConstructors();
if (constructors == null) {
// Constructor not found in this class
throw new TypeCheckError(ErrorMsg.CONSTRUCTOR_NOT_FOUND, _className);
}
final int nConstructors = constructors.size();
final int nArgs = _arguments.size();
final Vector argsType = typeCheckArgs(stable);
// Try all constructors
int bestConstrDistance = Integer.MAX_VALUE;
// reset
_type = null;
for (int j, i = 0; i < nConstructors; i++) {
// Check if all parameters to this constructor can be converted
final Constructor constructor = (Constructor) constructors.elementAt(i);
final Class[] paramTypes = constructor.getParameterTypes();
Class extType = null;
int currConstrDistance = 0;
for (j = 0; j < nArgs; j++) {
// Convert from internal (translet) type to external (Java) type
extType = paramTypes[j];
final Type intType = (Type) argsType.elementAt(j);
Object match = _internal2Java.maps(intType, extType);
if (match != null) {
currConstrDistance += ((JavaType) match).distance;
} else if (intType instanceof ObjectType) {
ObjectType objectType = (ObjectType) intType;
if (objectType.getJavaClass() == extType)
continue;
else if (extType.isAssignableFrom(objectType.getJavaClass()))
currConstrDistance += 1;
else {
currConstrDistance = Integer.MAX_VALUE;
break;
}
} else {
// no mapping available
currConstrDistance = Integer.MAX_VALUE;
break;
}
}
if (j == nArgs && currConstrDistance < bestConstrDistance) {
_chosenConstructor = constructor;
_isExtConstructor = true;
bestConstrDistance = currConstrDistance;
_type = (_clazz != null) ? Type.newObjectType(_clazz) : Type.newObjectType(_className);
}
}
if (_type != null) {
return _type;
}
throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType));
}
use of org.apache.xalan.xsltc.compiler.util.Type in project servicemix-bundles by apache.
the class FunctionCall method getMethodSignature.
/**
* Return the signature of the current method
*/
private String getMethodSignature(Vector argsType) {
final StringBuffer buf = new StringBuffer(_className);
buf.append('.').append(_fname.getLocalPart()).append('(');
int nArgs = argsType.size();
for (int i = 0; i < nArgs; i++) {
final Type intType = (Type) argsType.elementAt(i);
buf.append(intType.toString());
if (i < nArgs - 1)
buf.append(", ");
}
buf.append(')');
return buf.toString();
}
use of org.apache.xalan.xsltc.compiler.util.Type in project servicemix-bundles by apache.
the class FunctionCall method translate.
/**
* Translate a function call. The compiled code will leave the function's
* return value on the JVM's stack.
*/
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
final int n = argumentCount();
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
final boolean isSecureProcessing = classGen.getParser().getXSLTC().isSecureProcessing();
int index;
// Translate calls to methods in the BasisLibrary
if (isStandard() || isExtension()) {
for (int i = 0; i < n; i++) {
final Expression exp = argument(i);
exp.translate(classGen, methodGen);
exp.startIterator(classGen, methodGen);
}
// append "F" to the function's name
final String name = _fname.toString().replace('-', '_') + "F";
String args = Constants.EMPTYSTRING;
// Special precautions for some method calls
if (name.equals("sumF")) {
args = DOM_INTF_SIG;
il.append(methodGen.loadDOM());
} else if (name.equals("normalize_spaceF")) {
if (_chosenMethodType.toSignature(args).equals("()Ljava/lang/String;")) {
args = "I" + DOM_INTF_SIG;
il.append(methodGen.loadContextNode());
il.append(methodGen.loadDOM());
}
}
// Invoke the method in the basis library
index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name, _chosenMethodType.toSignature(args));
il.append(new INVOKESTATIC(index));
} else // run-time error message for unsupported external functions
if (unresolvedExternal) {
index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "unresolved_externalF", "(Ljava/lang/String;)V");
il.append(new PUSH(cpg, _fname.toString()));
il.append(new INVOKESTATIC(index));
} else if (_isExtConstructor) {
if (isSecureProcessing)
translateUnallowedExtension(cpg, il);
final String clazz = _chosenConstructor.getDeclaringClass().getName();
Class[] paramTypes = _chosenConstructor.getParameterTypes();
LocalVariableGen[] paramTemp = new LocalVariableGen[n];
for (int i = 0; i < n; i++) {
final Expression exp = argument(i);
Type expType = exp.getType();
exp.translate(classGen, methodGen);
// Convert the argument to its Java type
exp.startIterator(classGen, methodGen);
expType.translateTo(classGen, methodGen, paramTypes[i]);
paramTemp[i] = methodGen.addLocalVariable("function_call_tmp" + i, expType.toJCType(), null, null);
paramTemp[i].setStart(il.append(expType.STORE(paramTemp[i].getIndex())));
}
il.append(new NEW(cpg.addClass(_className)));
il.append(InstructionConstants.DUP);
for (int i = 0; i < n; i++) {
final Expression arg = argument(i);
paramTemp[i].setEnd(il.append(arg.getType().LOAD(paramTemp[i].getIndex())));
}
final StringBuffer buffer = new StringBuffer();
buffer.append('(');
for (int i = 0; i < paramTypes.length; i++) {
buffer.append(getSignature(paramTypes[i]));
}
buffer.append(')');
buffer.append("V");
index = cpg.addMethodref(clazz, "<init>", buffer.toString());
il.append(new INVOKESPECIAL(index));
// Convert the return type back to our internal type
(Type.Object).translateFrom(classGen, methodGen, _chosenConstructor.getDeclaringClass());
} else // Invoke function calls that are handled in separate classes
{
if (isSecureProcessing)
translateUnallowedExtension(cpg, il);
final String clazz = _chosenMethod.getDeclaringClass().getName();
Class[] paramTypes = _chosenMethod.getParameterTypes();
// Push "this" if it is an instance method
if (_thisArgument != null) {
_thisArgument.translate(classGen, methodGen);
}
for (int i = 0; i < n; i++) {
final Expression exp = argument(i);
exp.translate(classGen, methodGen);
// Convert the argument to its Java type
exp.startIterator(classGen, methodGen);
exp.getType().translateTo(classGen, methodGen, paramTypes[i]);
}
final StringBuffer buffer = new StringBuffer();
buffer.append('(');
for (int i = 0; i < paramTypes.length; i++) {
buffer.append(getSignature(paramTypes[i]));
}
buffer.append(')');
buffer.append(getSignature(_chosenMethod.getReturnType()));
if (_thisArgument != null && _clazz.isInterface()) {
index = cpg.addInterfaceMethodref(clazz, _fname.getLocalPart(), buffer.toString());
il.append(new INVOKEINTERFACE(index, n + 1));
} else {
index = cpg.addMethodref(clazz, _fname.getLocalPart(), buffer.toString());
il.append(_thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) : (InvokeInstruction) new INVOKESTATIC(index));
}
// Convert the return type back to our internal type
_type.translateFrom(classGen, methodGen, _chosenMethod.getReturnType());
}
}
use of org.apache.xalan.xsltc.compiler.util.Type in project servicemix-bundles by apache.
the class FunctionCall method translateDesynthesized.
/**
* Compile the function call and treat as an expression
* Update true/false-lists.
*/
public void translateDesynthesized(ClassGenerator classGen, MethodGenerator methodGen) {
Type type = Type.Boolean;
if (_chosenMethodType != null)
type = _chosenMethodType.resultType();
final InstructionList il = methodGen.getInstructionList();
translate(classGen, methodGen);
if ((type instanceof BooleanType) || (type instanceof IntType)) {
_falseList.add(il.append(new IFEQ(null)));
}
}
use of org.apache.xalan.xsltc.compiler.util.Type in project servicemix-bundles by apache.
the class FunctionCall method typeCheckExternal.
/**
* Type check a call to an external (Java) method.
* The method must be static an public, and a legal type conversion
* must exist for all its arguments and its return type.
* Every method of name <code>_fname</code> is inspected
* as a possible candidate.
*/
public Type typeCheckExternal(SymbolTable stable) throws TypeCheckError {
int nArgs = _arguments.size();
final String name = _fname.getLocalPart();
// check if function is a contructor 'new'
if (_fname.getLocalPart().equals("new")) {
return typeCheckConstructor(stable);
} else // check if we are calling an instance method
{
boolean hasThisArgument = false;
if (nArgs == 0)
_isStatic = true;
if (!_isStatic) {
if (_namespace_format == NAMESPACE_FORMAT_JAVA || _namespace_format == NAMESPACE_FORMAT_PACKAGE)
hasThisArgument = true;
Expression firstArg = (Expression) _arguments.elementAt(0);
Type firstArgType = (Type) firstArg.typeCheck(stable);
if (_namespace_format == NAMESPACE_FORMAT_CLASS && firstArgType instanceof ObjectType && _clazz != null && _clazz.isAssignableFrom(((ObjectType) firstArgType).getJavaClass()))
hasThisArgument = true;
if (hasThisArgument) {
_thisArgument = (Expression) _arguments.elementAt(0);
_arguments.remove(0);
nArgs--;
if (firstArgType instanceof ObjectType) {
_className = ((ObjectType) firstArgType).getJavaClassName();
} else
throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, name);
}
} else if (_className.length() == 0) {
/*
* Warn user if external function could not be resolved.
* Warning will _NOT_ be issued is the call is properly
* wrapped in an <xsl:if> or <xsl:when> element. For details
* see If.parserContents() and When.parserContents()
*/
final Parser parser = getParser();
if (parser != null) {
reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR, _fname.toString());
}
unresolvedExternal = true;
// use "Int" as "unknown"
return _type = Type.Int;
}
}
final Vector methods = findMethods();
if (methods == null) {
// Method not found in this class
throw new TypeCheckError(ErrorMsg.METHOD_NOT_FOUND_ERR, _className + "." + name);
}
Class extType = null;
final int nMethods = methods.size();
final Vector argsType = typeCheckArgs(stable);
// Try all methods to identify the best fit
int bestMethodDistance = Integer.MAX_VALUE;
// reset internal type
_type = null;
for (int j, i = 0; i < nMethods; i++) {
// Check if all paramteters to this method can be converted
final Method method = (Method) methods.elementAt(i);
final Class[] paramTypes = method.getParameterTypes();
int currMethodDistance = 0;
for (j = 0; j < nArgs; j++) {
// Convert from internal (translet) type to external (Java) type
extType = paramTypes[j];
final Type intType = (Type) argsType.elementAt(j);
Object match = _internal2Java.maps(intType, extType);
if (match != null) {
currMethodDistance += ((JavaType) match).distance;
} else {
// the moment. The real type checking is performed at runtime.
if (intType instanceof ReferenceType) {
currMethodDistance += 1;
} else if (intType instanceof ObjectType) {
ObjectType object = (ObjectType) intType;
if (extType.getName().equals(object.getJavaClassName()))
currMethodDistance += 0;
else if (extType.isAssignableFrom(object.getJavaClass()))
currMethodDistance += 1;
else {
currMethodDistance = Integer.MAX_VALUE;
break;
}
} else {
currMethodDistance = Integer.MAX_VALUE;
break;
}
}
}
if (j == nArgs) {
// Check if the return type can be converted
extType = method.getReturnType();
_type = (Type) _java2Internal.get(extType);
if (_type == null) {
_type = Type.newObjectType(extType);
}
// Use this method if all parameters & return type match
if (_type != null && currMethodDistance < bestMethodDistance) {
_chosenMethod = method;
bestMethodDistance = currMethodDistance;
}
}
}
// have a this argument.
if (_chosenMethod != null && _thisArgument == null && !Modifier.isStatic(_chosenMethod.getModifiers())) {
throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, getMethodSignature(argsType));
}
if (_type != null) {
if (_type == Type.NodeSet) {
getXSLTC().setMultiDocument(true);
}
return _type;
}
throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType));
}
Aggregations