/*
* $Id: DispatcherFactory.java,v 1.9 2002/09/16 08:05:04 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script.compiler;
import java.io.File;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayOutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import anvil.java.util.BindingEnumeration;
import anvil.java.util.Hashlist;
import anvil.script.CompilableFunction;
import anvil.script.Function;
import anvil.script.ClassType;
import anvil.script.Type;
import anvil.script.Scope;
import anvil.script.ClassDispatcher;
import anvil.script.FunctionDispatcher;
import anvil.script.GeneratorDispatcher;
import anvil.script.NativeJava;
import anvil.core.Any;
import anvil.core.Register;
import anvil.codec.ClassRoom;
import anvil.codec.Code;
import anvil.codec.ConstantPool;
import anvil.codec.ExceptionHandler;
import anvil.codec.Method;
import anvil.codec.Field;
import anvil.codec.CodecConstants;
import anvil.codec.Switch;
import anvil.codec.Source;
import anvil.server.ZoneClassLoader;
public class DispatcherFactory implements CodecConstants
{
private static int _index;
private static synchronized String getNextName()
{
return "anvil/script/compiler/GeneratedDispatcher_"+(_index++);
}
private static String[] EXECUTE_SIGNATURES =
{
"(Lanvil/script/Context;Lanvil/core/Any;)Lanvil/core/Any;",
"(Lanvil/script/Context;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;",
"(Lanvil/script/Context;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;",
"(Lanvil/script/Context;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;",
"(Lanvil/script/Context;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;"
};
private static String[] GATHER1 =
{
"()Lanvil/core/Array;",
"(Lanvil/core/Any;)Lanvil/core/Array;",
"(Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Array;",
"(Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Array;",
"(Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Array;"
};
private static String[] GATHER2 =
{
"()[Lanvil/core/Any;",
"(Lanvil/core/Any;)[Lanvil/core/Any;",
"(Lanvil/core/Any;Lanvil/core/Any;)[Lanvil/core/Any;",
"(Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)[Lanvil/core/Any;",
"(Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)[Lanvil/core/Any;",
};
private static String[] GATHER3 =
{
"()Lanvil/core/AnyTuple;",
"(Lanvil/core/Any;)Lanvil/core/AnyTuple;",
"(Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/AnyTuple;",
"(Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/AnyTuple;",
"(Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/AnyTuple;",
};
public static FunctionDispatcher create(CompilableFunction function, boolean isstatic, ZoneClassLoader loader)
throws Throwable
{
ClassRoom clazz = new ClassRoom();
ConstantPool pool = clazz.getPool();
String classname = getNextName();
clazz.setClassname(classname, null);
clazz.setSuperClassname("java/lang/Object");
clazz.addInterface("anvil/script/FunctionDispatcher");
clazz.setAccessFlags(ACC_PUBLIC|ACC_FINAL);
Hashlist constants = new Hashlist();
//generic
{
Method method = clazz.createMethod("execute",
"(Lanvil/script/Context;Lanvil/core/Any;[Lanvil/core/Any;)Lanvil/core/Any;",
ACC_PUBLIC|ACC_FINAL);
Code code = method.getCode();
int l_context = code.addLocal();
int l_self = code.addLocal();
int l_parameters = code.addLocal();
compileDispatch(function, isstatic, clazz, code, pool, l_context, l_self, l_parameters, constants);
}
for(int params=0; params<=4; params++) {
Method method = clazz.createMethod("execute", EXECUTE_SIGNATURES[params], ACC_PUBLIC|ACC_FINAL);
Code code = method.getCode();
int l_context = code.addLocal();
int l_self = code.addLocal();
int l_base = code.addLocal();
code.addLocals(params);
compileDispatch(function, isstatic, clazz, code, pool, l_context, l_self, l_base, params, constants);
}
createConstructor(clazz, constants);
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
clazz.write(new DataOutputStream(bytestream));
bytestream.close();
//FileOutputStream fout = new FileOutputStream("/data/projects/anvil/src/"+classname+".class");
//bytestream.writeTo(fout);
//fout.close();
Class cls = loader.define(classname, bytestream.toByteArray());
return (FunctionDispatcher)cls.newInstance();
}
private static void createConstructor(ClassRoom clazz, Hashlist constants)
{
Method method = clazz.createMethod("<init>", "()V", ACC_PUBLIC);
ConstantPool pool = clazz.getPool();
Code code = method.getCode();
code.self();
code.invokespecial(pool.addMethodRef(clazz.getSuperClassIndex(), "<init>", "()V"));
Enumeration enum = constants.keys();
for(int i=0; enum.hasMoreElements(); i++) {
Any defaultvalue = (Any)enum.nextElement();
Field field = clazz.createField("const_"+i, "Lanvil/core/Any;", ACC_PUBLIC);
code.self();
defaultvalue.toCode(code);
code.putfield(field);
}
code.vreturn();
}
private static void compileDispatch(
CompilableFunction function,
boolean isstatic,
ClassRoom clazz,
Code code,
ConstantPool pool,
int l_context,
int l_self,
int l_parameters,
Hashlist constants)
{
int minparams = function.getMinimumParameterCount();
int maxparams = function.getParameterCount();
int helperclass = pool.addClass("anvil/script/compiler/DispatcherHelper");
boolean collector = false;
int realparams = 0;
for(int i=0; i<maxparams; i++) {
int type = function.getParameterType(i);
if (type == CompilableFunction.PARAMETER_CONTEXT) {
continue;
}
if (type>=CompilableFunction.PARAMETER_ARRAY) {
collector = true;
continue;
}
realparams++;
}
if (!isstatic) {
code.aload(l_self);
Source nonnull = code.if_nonnull();
code.aload(l_context);
code.astring(function.toString());
code.invokevirtual(pool.addMethodRef("anvil/script/Context", "NoInstance",
"(Ljava/lang/String;)Lanvil/script/ScriptException;"));
code.athrow();
nonnull.bind();
}
code.aload(l_parameters);
code.arraylength();
Switch select = code.select();
for(int params=0; params<=realparams; params++) {
select.addCase(params);
}
select.end();
for(int params=0; params<=realparams; params++) {
select.bindCase(params);
if (params < minparams-1) {
// fall through
} else if (params == minparams-1) {
code.aload(l_context);
code.astring(function.toString());
code.invokevirtual(pool.addMethodRef("anvil/script/Context", "NotEnoughParameters",
"(Ljava/lang/String;)Lanvil/script/ScriptException;"));
code.athrow();
} else {
if (params == realparams) {
select.bindDefault();
}
/*int l_index = 0;
ExceptionHandler handler = null;
if (function instanceof NativeJava) {
code.addLocal();
code.aload(l_context);
code.invokevirtual(pool.addMethodRef("anvil/script/StackFrameStack", "size", "()I"));
code.istore(l_index);
handler = code.startExceptionHandler(false);
}*/
if (!isstatic) {
code.aload(l_self);
code.checkcast(function.getParent().getTypeRef(pool));
}
int c = 0;
for(int i=0; i<maxparams; i++) {
int type = function.getParameterType(i);
switch(type) {
case CompilableFunction.PARAMETER_CONTEXT:
code.aload(l_context);
break;
case CompilableFunction.PARAMETER_ARRAY:
code.aload(l_parameters);
code.iconst(params);
code.invokestatic(pool.addMethodRef(helperclass, "rest1", "([Lanvil/core/Any;I)Lanvil/core/Array;"));
break;
case CompilableFunction.PARAMETER_LIST:
if (params == 0) {
code.aload(l_parameters);
} else {
code.aload(l_parameters);
code.iconst(params);
code.invokestatic(pool.addMethodRef(helperclass, "rest2", "([Lanvil/core/Any;I)[Lanvil/core/Any;"));
}
break;
case CompilableFunction.PARAMETER_ANYLIST:
case CompilableFunction.PARAMETER_REST:
code.aload(l_parameters);
code.iconst(params);
code.invokestatic(pool.addMethodRef(helperclass, "rest3", "([Lanvil/core/Any;I)Lanvil/core/AnyTuple;"));
break;
default:
if (c>=params) {
anvil.core.Any defaultvalue = function.getParameterDefault(i);
switch(type) {
case CompilableFunction.PARAMETER_ANY:
if (defaultvalue != null) {
code.self();
int index = addConstant(constants, defaultvalue);
code.getfield(pool.addFieldRef(clazz.getClassnameIndex(), "const_"+index, "Lanvil/core/Any;"));
if (defaultvalue.isMutable()) {
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "copy", "()Lanvil/core/Any;"));
}
} else {
code.aconst_null();
}
break;
case CompilableFunction.PARAMETER_OBJECT:
if (defaultvalue != null) {
code.self();
int index = addConstant(constants, defaultvalue);
code.getfield(pool.addFieldRef(clazz.getClassnameIndex(), "const_"+index, "Lanvil/core/Any;"));
if (defaultvalue.isMutable()) {
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "copy", "()Lanvil/core/Any;"));
}
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toObject",
"()Ljava/lang/Object;"));
} else {
code.aconst_null();
}
break;
case CompilableFunction.PARAMETER_STRING:
if (defaultvalue != null) {
code.astring(defaultvalue.toString());
} else {
code.aconst_null();
}
break;
case CompilableFunction.PARAMETER_DOUBLE:
if (defaultvalue != null) {
code.dconst(defaultvalue.toDouble());
} else {
code.dconst(0.0);
}
break;
case CompilableFunction.PARAMETER_INT:
if (defaultvalue != null) {
code.iconst(defaultvalue.toInt());
} else {
code.iconst(0);
}
break;
case CompilableFunction.PARAMETER_LONG:
if (defaultvalue != null) {
code.lconst(defaultvalue.toLong());
} else {
code.lconst(0);
}
break;
case CompilableFunction.PARAMETER_BOOLEAN:
if (defaultvalue != null) {
code.iconst(defaultvalue.toBoolean());
} else {
code.iconst(false);
}
break;
}
} else {
code.aload(l_parameters);
code.iconst(c++);
code.aaload();
switch(type) {
case CompilableFunction.PARAMETER_ANY:
break;
case CompilableFunction.PARAMETER_STRING:
code.invokevirtual(pool.addMethodRef("java/lang/Object", "toString",
"()Ljava/lang/String;"));
break;
case CompilableFunction.PARAMETER_OBJECT:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toObject",
"()Ljava/lang/Object;"));
break;
case CompilableFunction.PARAMETER_DOUBLE:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toDouble",
"()D"));
break;
case CompilableFunction.PARAMETER_INT:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toInt",
"()I"));
break;
case CompilableFunction.PARAMETER_LONG:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toLong",
"()J"));
break;
case CompilableFunction.PARAMETER_BOOLEAN:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toBoolean",
"()Z"));
break;
}
}
}
}
if (isstatic) {
code.invokestatic(function.getTypeRef(pool));
} else {
code.invokevirtual(function.getTypeRef(pool));
}
code.areturn();
/*if (handler != null) {
handler.endTry();
handler.startCatch(pool.addClass("anvil/script/ScriptException"));
int l_throwable = code.addLocal();
code.astore(l_throwable);
code.aload(l_throwable);
code.aload(l_self);
code.iload(l_index);
code.iconst(Register.register(function.getName()));
code.invokevirtual(pool.addMethodRef("anvil/script/ScriptException", "fill",
"(Ljava/lang/Object;II)Lanvil/script/ScriptException;"));
code.athrow();
code.endLocal(l_throwable);
handler.endProtectedRegion();
handler.endCatches();
handler.end();
code.endLocal(l_index);
}*/
}
}
}
private static int addConstant(Hashlist constants, Any value)
{
Integer index = (Integer)constants.get(value);
if (index == null) {
int next = constants.size();
constants.put(value, anvil.core.ObjectPool.createInteger(next));
return next;
}
return index.intValue();
}
private static void compileDispatch(
CompilableFunction function,
boolean isstatic,
ClassRoom clazz,
Code code,
ConstantPool pool,
int l_context,
int l_self,
int l_base,
int parameters,
Hashlist constants)
{
int minparams = function.getMinimumParameterCount();
int maxparams = function.getParameterCount();
int helperclass = pool.addClass("anvil/script/compiler/DispatcherHelper");
boolean collector = false;
int realparameters = 0;
for(int i=0; i<maxparams; i++) {
int type = function.getParameterType(i);
if (type == CompilableFunction.PARAMETER_CONTEXT) {
continue;
}
if (type>=CompilableFunction.PARAMETER_ARRAY) {
collector = true;
continue;
}
realparameters++;
}
if (parameters < minparams) {
code.aload(l_context);
code.astring(function.toString());
code.invokevirtual(pool.addMethodRef("anvil/script/Context", "NotEnoughParameters",
"(Ljava/lang/String;)Lanvil/script/ScriptException;"));
code.athrow();
return;
}
if (!isstatic) {
code.aload(l_self);
Source nonnull = code.if_nonnull();
code.aload(l_context);
code.astring(function.toString());
code.invokevirtual(pool.addMethodRef("anvil/script/Context", "NoInstance",
"(Ljava/lang/String;)Lanvil/script/ScriptException;"));
code.athrow();
nonnull.bind();
}
/*int l_index = 0;
ExceptionHandler handler = null;
if (function instanceof NativeJava) {
l_index = code.addLocal();
code.aload(l_context);
code.invokevirtual(pool.addMethodRef("anvil/script/StackFrameStack", "size", "()I"));
code.istore(l_index);
handler = code.startExceptionHandler(false);
}*/
if (!isstatic) {
code.aload(l_self);
code.checkcast(function.getParent().getTypeRef(pool));
}
int c = 0;
for(int i=0; i<maxparams; i++) {
int type = function.getParameterType(i);
switch(type) {
case CompilableFunction.PARAMETER_CONTEXT:
code.aload(l_context);
break;
case CompilableFunction.PARAMETER_ARRAY:
{
int left = (parameters - c);
while(c < parameters) {
code.aload(l_base + c++);
}
code.invokestatic(pool.addMethodRef(helperclass, "gather1", GATHER1[left]));
}
break;
case CompilableFunction.PARAMETER_LIST:
{
int left = (parameters - c);
while(c < parameters) {
code.aload(l_base + c++);
}
code.invokestatic(pool.addMethodRef(helperclass, "gather2", GATHER2[left]));
}
break;
case CompilableFunction.PARAMETER_ANYLIST:
case CompilableFunction.PARAMETER_REST:
{
int left = (parameters - c);
while(c < parameters) {
code.aload(l_base + c++);
}
code.invokestatic(pool.addMethodRef(helperclass, "gather3", GATHER3[left]));
}
break;
default:
if (c>=parameters) {
anvil.core.Any defaultvalue = function.getParameterDefault(i);
switch(type) {
case CompilableFunction.PARAMETER_ANY:
if (defaultvalue != null) {
code.self();
int index = addConstant(constants, defaultvalue);
code.getfield(pool.addFieldRef(clazz.getClassnameIndex(), "const_"+index, "Lanvil/core/Any;"));
if (defaultvalue.isMutable()) {
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "copy", "()Lanvil/core/Any;"));
}
} else {
code.aconst_null();
}
break;
case CompilableFunction.PARAMETER_OBJECT:
if (defaultvalue != null) {
code.self();
int index = addConstant(constants, defaultvalue);
code.getfield(pool.addFieldRef(clazz.getClassnameIndex(), "const_"+index, "Lanvil/core/Any;"));
if (defaultvalue.isMutable()) {
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "copy", "()Lanvil/core/Any;"));
}
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toObject",
"()Ljava/lang/Object;"));
} else {
code.aconst_null();
}
break;
case CompilableFunction.PARAMETER_STRING:
if (defaultvalue != null) {
code.astring(defaultvalue.toString());
} else {
code.aconst_null();
}
break;
case CompilableFunction.PARAMETER_DOUBLE:
if (defaultvalue != null) {
code.dconst(defaultvalue.toDouble());
} else {
code.dconst(0.0);
}
break;
case CompilableFunction.PARAMETER_INT:
if (defaultvalue != null) {
code.iconst(defaultvalue.toInt());
} else {
code.iconst(0);
}
break;
case CompilableFunction.PARAMETER_LONG:
if (defaultvalue != null) {
code.lconst(defaultvalue.toLong());
} else {
code.lconst(0);
}
break;
case CompilableFunction.PARAMETER_BOOLEAN:
if (defaultvalue != null) {
code.iconst(defaultvalue.toBoolean());
} else {
code.iconst(false);
}
break;
}
} else {
code.aload(l_base + c++);
switch(type) {
case CompilableFunction.PARAMETER_ANY:
break;
case CompilableFunction.PARAMETER_STRING:
code.invokevirtual(pool.addMethodRef("java/lang/Object", "toString",
"()Ljava/lang/String;"));
break;
case CompilableFunction.PARAMETER_OBJECT:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toObject",
"()Ljava/lang/Object;"));
break;
case CompilableFunction.PARAMETER_DOUBLE:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toDouble",
"()D"));
break;
case CompilableFunction.PARAMETER_INT:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toInt",
"()I"));
break;
case CompilableFunction.PARAMETER_LONG:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toLong",
"()J"));
break;
case CompilableFunction.PARAMETER_BOOLEAN:
code.invokevirtual(pool.addMethodRef("anvil/core/Any", "toBoolean",
"()Z"));
break;
}
}
}
}
if (isstatic) {
code.invokestatic(function.getTypeRef(pool));
} else {
code.invokevirtual(function.getTypeRef(pool));
}
code.areturn();
/*if (handler != null) {
handler.endTry();
handler.startCatch(pool.addClass("anvil/script/ScriptException"));
int l_throwable = code.addLocal();
code.astore(l_throwable);
code.aload(l_throwable);
code.aload(l_self);
code.iload(l_index);
code.iconst(Register.register(function.getName()));
code.invokevirtual(pool.addMethodRef("anvil/script/ScriptException", "fill",
"(Ljava/lang/Object;II)Lanvil/script/ScriptException;"));
code.athrow();
code.endLocal(l_throwable);
handler.endProtectedRegion();
handler.endCatches();
handler.end();
code.endLocal(l_index);
}*/
}
private static String[] INVOKE_SIGNATURES =
{
"(Lanvil/script/Context;Ljava/lang/Object;I)Lanvil/core/Any;",
"(Lanvil/script/Context;Ljava/lang/Object;ILanvil/core/Any;)Lanvil/core/Any;",
"(Lanvil/script/Context;Ljava/lang/Object;ILanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;",
"(Lanvil/script/Context;Ljava/lang/Object;ILanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;",
"(Lanvil/script/Context;Ljava/lang/Object;ILanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;"
};
public static ClassDispatcher create(ClassType cls, ZoneClassLoader loader)
throws Throwable
{
HashMap set = new HashMap();
ClassType c = cls;
while(c != null) {
Enumeration enum = c.getDeclarations();
while(enum.hasMoreElements()) {
Type type = (Type)enum.nextElement();
int typeOf = type.getType();
if (typeOf == Type.METHOD || typeOf == Type.FUNCTION) {
Integer index = new Integer(Register.register(type.getName()));
if (!set.containsKey(index)) {
set.put(index, type);
}
}
}
c = c.getBaseClass();
}
ClassRoom clazz = new ClassRoom();
ConstantPool pool = clazz.getPool();
String classname = getNextName();
clazz.setClassname(classname, null);
clazz.setSuperClassname("java/lang/Object");
clazz.addInterface("anvil/script/ClassDispatcher");
clazz.setAccessFlags(ACC_PUBLIC|ACC_FINAL);
Method method1 = clazz.createMethod("invoke",
"(Lanvil/script/Context;Ljava/lang/Object;I[Lanvil/core/Any;)Lanvil/core/Any;",
ACC_PUBLIC|ACC_FINAL);
Code code1 = method1.getCode();
code1.addLocals(4);
Method[] methods = new Method[5];
for(int i=0; i<5; i++) {
Method method = clazz.createMethod("invoke", INVOKE_SIGNATURES[i], ACC_PUBLIC|ACC_FINAL);;
methods[i] = method;
Code code = method.getCode();
code.addLocals(3 + i);
}
Method method2 = clazz.createMethod("hasMethod", "(I)Z", ACC_PUBLIC|ACC_FINAL);
Code code2 = method2.getCode();
code2.addLocal();
code1.iload(3);
for(int i=0; i<5; i++) {
methods[i].getCode().iload(3);
}
code2.iload(1);
Switch select1 = code1.select();
Switch[] select = new Switch[] {
methods[0].getCode().select(),
methods[1].getCode().select(),
methods[2].getCode().select(),
methods[3].getCode().select(),
methods[4].getCode().select()
};
Switch select2 = code2.select();
Iterator iter = set.keySet().iterator();
while(iter.hasNext()) {
int index = ((Integer)iter.next()).intValue();
select1.addCase(index);
for(int i=0; i<5; i++) {
select[i].addCase(index);
}
select2.addCase(index);
}
select1.end();
for(int i=0; i<5; i++) {
select[i].end();
}
select2.end();
Hashlist constants = new Hashlist();
iter = set.keySet().iterator();
while(iter.hasNext()) {
Integer index = (Integer)iter.next();
int value = index.intValue();
select1.bindCase(value);
for(int i=0; i<5; i++) {
select[i].bindCase(value);
}
select2.bindCase(value);
CompilableFunction function = (CompilableFunction)set.get(index);
boolean isStatic = (function.getType() == Type.FUNCTION);
compileDispatch(function, isStatic, clazz, code1, pool, 1, 2, 4, constants);
for(int i=0; i<5; i++) {
compileDispatch(function, isStatic, clazz, methods[i].getCode(), pool, 1, 2, 4, i, constants);
}
}
code2.iconst(true);
code2.ireturn();
select1.bindDefault();
for(int i=0; i<5; i++) {
select[i].bindDefault();
}
select2.bindDefault();
code1.aload(1);
code1.astring(cls.getQualifiedName());
code1.iload(3);
code1.invokevirtual(pool.addMethodRef("anvil/script/Context", "NoSuchMethod",
"(Ljava/lang/String;I)Lanvil/script/ScriptException;"));
code1.athrow();
for(int i=0; i<5; i++) {
Code code = methods[i].getCode();
code.aload(1);
code.astring(cls.getQualifiedName());
code.iload(3);
code.invokevirtual(pool.addMethodRef("anvil/script/Context", "NoSuchMethod",
"(Ljava/lang/String;I)Lanvil/script/ScriptException;"));
code.athrow();
}
code2.iconst(false);
code2.ireturn();
createConstructor(clazz, constants);
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
clazz.write(new DataOutputStream(bytestream));
bytestream.close();
/*FileOutputStream fout = new FileOutputStream("/data/projects/anvil/src/"+classname+".class");
bytestream.writeTo(fout);
fout.close();*/
Class javaclass = loader.define(classname, bytestream.toByteArray());
return (ClassDispatcher)javaclass.newInstance();
}
public static GeneratorDispatcher createGenerator(CompilableFunction function, ZoneClassLoader loader)
throws Throwable
{
ClassRoom clazz = new ClassRoom();
ConstantPool pool = clazz.getPool();
String classname = getNextName();
clazz.setClassname(classname, null);
clazz.setSuperClassname("java/lang/Object");
clazz.addInterface("anvil/script/GeneratorDispatcher");
clazz.setAccessFlags(ACC_PUBLIC|ACC_FINAL);
Method method = clazz.createMethod("<init>", "()V", ACC_PUBLIC);
Code code = method.getCode();
code.self();
code.invokespecial(pool.addMethodRef(clazz.getSuperClassIndex(), "<init>", "()V"));
code.vreturn();
method = clazz.createMethod("execute",
"(Lanvil/script/Context;Lanvil/core/AnyClass;Lanvil/script/Generator;)Lanvil/core/Any;",
ACC_PUBLIC|ACC_FINAL);
code = method.getCode();
code.addLocals(4);
boolean ismethod = (function.getType() == Type.METHOD);
Scope parent = function.getParent();
int parent_ref = parent.getTypeRef(pool);
if (ismethod) {
code.aload(2);
code.checkcast(parent_ref);
}
code.aload(1);
code.aload(3);
int method_ref = pool.addMethodRef(
parent_ref, "h_"+function.getName(), "(Lanvil/script/Context;Lanvil/script/Generator;)Lanvil/core/Any;");
if (ismethod) {
code.invokevirtual(method_ref);
} else {
code.invokestatic(method_ref);
}
code.areturn();
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
clazz.write(new DataOutputStream(bytestream));
bytestream.close();
Class cls = loader.define(classname, bytestream.toByteArray());
return (GeneratorDispatcher)cls.newInstance();
}
}