/*
* Copyright (C) 2011 René Jeschke <rene_jeschke@yahoo.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.rjeschke.weel;
import java.lang.reflect.Method;
/**
* Class responsible for wrapping 'nice' methods.
*
* @author René Jeschke <rene_jeschke@yahoo.de>
*/
class MethodWrapper
{
/** The ClassWriter. */
JvmClassWriter classWriter;
/**
* Constructor.
*
* @param name
* The class name.
*/
public MethodWrapper(final String name)
{
this.classWriter = new JvmClassWriter("com.github.rjeschke.wrappers."
+ name);
}
/**
* Gets the class name of this class writer's class.
*
* @return The class name.
*/
public String getClassName()
{
return this.classWriter.className;
}
/**
* Wraps a method.
*
* @param m
* The method to wrap.
* @return The gerated method name.
*/
public String wrap(final Method m, final WeelFunction func)
{
for(int i = 0; i < m.getParameterTypes().length; i++)
{
if(m.getParameterTypes()[i] == com.github.rjeschke.weel.WeelRuntime.class)
func.arguments--;
}
final String mname = "wrap$" + m.getName() + "$" + func.arguments;
final JvmMethodWriter mw = this.classWriter.createMethod(mname,
"(Lcom/github/rjeschke/weel/WeelRuntime;)V");
mw.aload(0);
mw.ldc(func.arguments);
mw.ldc(0);
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime", "openFrame",
"(II)V");
final boolean returns;
if(m.getReturnType() != void.class)
{
returns = true;
mw.aload(0);
}
else
{
returns = false;
}
for(int i = 0, p = 0; i < m.getParameterTypes().length; i++)
{
final Class<?> t = m.getParameterTypes()[i];
if(t == com.github.rjeschke.weel.WeelRuntime.class)
{
mw.aload(0);
continue;
}
mw.aload(0);
mw.ldc(p++);
if(t == double.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getNumberLocal", "(I)D");
}
else if(t == int.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getNumberLocal", "(I)D");
mw.addOp(JvmOp.D2I);
mw.curStack--;
}
else if(t == boolean.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getBooleanLocal", "(I)Z");
}
else if(t == String.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getStringLocal", "(I)Ljava/lang/String;");
}
else if(t == WeelFunction.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getFunctionLocal",
"(I)Lcom/github/rjeschke/weel/WeelFunction;");
}
else if(t == Value.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getValueLocal", "(I)Lcom/github/rjeschke/weel/Value;");
}
else if(t == ValueMap.class)
{
mw
.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getMapLocal",
"(I)Lcom/github/rjeschke/weel/ValueMap;");
}
else
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"getObjectLocal", "(I)Ljava/lang/Object;");
if(t != Object.class)
{
mw.addOp(JvmOp.CHECKCAST);
mw.code.addShort(this.classWriter
.addConstant(new JvmConstant(
JvmConstant.CONSTANT_Class,
this.classWriter
.addConstant(new JvmConstant(t
.getCanonicalName()
.replace('.', '/'))))));
}
}
}
mw.invokeStatic(m.getDeclaringClass().getCanonicalName(), m.getName(),
"(" + JvmClassWriter.buildDescriptor(m.getParameterTypes())
+ ")"
+ JvmClassWriter.buildDescriptor(m.getReturnType()));
if(returns)
{
final Class<?> t = m.getReturnType();
if(t == double.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(D)V");
}
else if(t == int.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(I)V");
}
else if(t == boolean.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(Z)V");
}
else if(t == String.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(Ljava/lang/String;)V");
}
else if(t == ValueMap.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(Lcom/github/rjeschke/weel/ValueMap;)V");
}
else if(t == Value.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(Lcom/github/rjeschke/weel/Value;)V");
}
else if(t == WeelFunction.class)
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(Lcom/github/rjeschke/weel/WeelFunction;)V");
}
else
{
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"load", "(Ljava/lang/Object;)V");
}
mw.aload(0);
mw.ldc(1);
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"closeFrameRet", "(I)V");
}
else
{
mw.aload(0);
mw.ldc(0);
mw.invokeVirtual("com.github.rjeschke.weel.WeelRuntime",
"closeFrame", "(I)V");
}
mw.addOp(JvmOp.RETURN);
return mname;
}
}