Removed JVM compiler

cvs
Slava Pestov 2004-11-16 17:24:05 +00:00
parent d9f39dbe2e
commit 8e51df2c81
54 changed files with 18 additions and 10861 deletions

View File

@ -29,19 +29,14 @@
package factor;
import factor.compiler.*;
import java.lang.reflect.*;
import java.io.FileOutputStream;
import java.util.*;
import org.objectweb.asm.*;
/**
* : name ... ;
*/
public class FactorCompoundDefinition extends FactorWordDefinition
{
private static int compileCount;
public Cons definition;
private Cons endOfDocs;
@ -49,11 +44,10 @@ public class FactorCompoundDefinition extends FactorWordDefinition
/**
* A new definition.
*/
public FactorCompoundDefinition(FactorWord word, Cons definition,
FactorInterpreter interp)
public FactorCompoundDefinition(FactorWord word, Cons definition)
{
super(word);
fromList(definition,interp);
fromList(definition);
} //}}}
//{{{ eval() method
@ -63,272 +57,8 @@ public class FactorCompoundDefinition extends FactorWordDefinition
interp.call(endOfDocs);
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
RecursiveForm rec = recursiveCheck.get(word);
if(rec.active)
{
if(rec.baseCase == null)
throw new FactorCompilerException("Indeterminate recursive call");
compiler.apply(StackEffect.decompose(rec.effect,rec.baseCase));
}
else
{
compiler.compile(endOfDocs,null,recursiveCheck);
}
} //}}}
//{{{ getClassName() method
private static String getClassName(String name)
{
return FactorJava.getSanitizedName(name)
+ "_" + (compileCount++);
} //}}}
//{{{ compile() method
/**
* Compile the given word, returning a new word definition.
*/
FactorWordDefinition compile(FactorInterpreter interp,
RecursiveState recursiveCheck) throws Exception
{
// Each word has its own class loader
FactorClassLoader loader = new FactorClassLoader(
getClass().getClassLoader());
StackEffect effect = getStackEffect(interp);
if(effect.inR != 0 || effect.outR != 0)
throw new FactorCompilerException("Compiled code cannot manipulate call stack frames");
String className = getClassName(word.name);
ClassWriter cw = new ClassWriter(true);
cw.visit(ACC_PUBLIC, className,
"factor/compiler/CompiledDefinition",
null, null);
compileConstructor(cw,className);
FactorCompiler compiler = compileEval(interp,cw,loader,
className,effect,recursiveCheck);
// Generate auxiliary methods
compiler.generateAuxiliary(cw);
// Generate fields for storing literals and
// word references
compiler.generateFields(cw);
compileToList(interp,compiler,cw);
compileGetStackEffect(cw,effect);
// gets the bytecode of the class, and loads it
// dynamically
byte[] code = cw.toByteArray();
if(interp.dump)
{
FileOutputStream fos = new FileOutputStream(
className + ".class");
try
{
fos.write(code);
}
finally
{
fos.close();
}
}
String javaClassName = className.replace('/','.');
word.setCompiledInfo(compiler.loader,javaClassName);
Class compiledWordClass = loader.addClass(
javaClassName,code,0,code.length);
return CompiledDefinition.create(interp,word,compiledWordClass);
} //}}}
//{{{ compileConstructor() method
private void compileConstructor(ClassVisitor cw, String className)
{
// creates a MethodWriter for the constructor
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"<init>",
"(Lfactor/FactorWord;)V",
null, null);
// pushes the 'this' variable
mw.visitVarInsn(ALOAD, 0);
// pushes the word parameter
mw.visitVarInsn(ALOAD, 1);
// invokes the super class constructor
mw.visitMethodInsn(INVOKESPECIAL,
"factor/compiler/CompiledDefinition", "<init>",
"(Lfactor/FactorWord;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(0,0);
} //}}}
//{{{ compileToList() method
private void compileToList(FactorInterpreter interp,
FactorCompiler compiler, ClassVisitor cw)
{
// creates a MethodWriter for the toList() method
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"toList",
"(Lfactor/FactorInterpreter;)Lfactor/Cons;",
null, null);
// push unparsed string representation of this word and parse it
compiler.generateParse(mw,toList(interp),1);
mw.visitTypeInsn(CHECKCAST,"factor/Cons");
mw.visitInsn(ARETURN);
mw.visitMaxs(0,0);
} //}}}
//{{{ compileGetStackEffect() method
private void compileGetStackEffect(ClassVisitor cw, StackEffect effect)
{
// creates a MethodWriter for the getStackEffect() method
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"getStackEffect",
"(Lfactor/compiler/RecursiveState;"
+ "Lfactor/compiler/FactorCompiler;)V",
null, null);
mw.visitVarInsn(ALOAD,2);
mw.visitTypeInsn(NEW,"factor/compiler/StackEffect");
mw.visitInsn(DUP);
mw.visitLdcInsn(new Integer(effect.inD));
mw.visitLdcInsn(new Integer(effect.outD));
mw.visitLdcInsn(new Integer(effect.inR));
mw.visitLdcInsn(new Integer(effect.outR));
mw.visitMethodInsn(INVOKESPECIAL,"factor/compiler/StackEffect",
"<init>","(IIII)V");
mw.visitMethodInsn(INVOKEVIRTUAL,"factor/compiler/FactorCompiler",
"apply","(Lfactor/compiler/StackEffect;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(0,0);
} //}}}
//{{{ compileEval() method
/**
* Write the definition of the eval() method in the compiled word.
* Local 0 -- this
* Local 1 -- interpreter
*/
protected FactorCompiler compileEval(FactorInterpreter interp,
ClassWriter cw, FactorClassLoader loader,
String className, StackEffect effect,
RecursiveState recursiveCheck)
throws Exception
{
cw.visitField(ACC_PRIVATE | ACC_STATIC, "initialized", "Z",
null, null);
// creates a MethodWriter for the 'eval' method
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"eval", "(Lfactor/FactorInterpreter;)V",
null, null);
// eval() method calls core
mw.visitVarInsn(ALOAD,1);
compileDataStackToJVMStack(effect,mw);
mw.visitMethodInsn(INVOKESTATIC,className,"core",
effect.getCorePrototype());
compileJVMStackToDataStack(effect,mw);
mw.visitInsn(RETURN);
mw.visitMaxs(0,0);
// generate core
FactorCompiler compiler = new FactorCompiler(interp,word,
className,loader);
compiler.init(1,effect.inD,effect.inR,"core");
compiler.compileCore(endOfDocs,cw,effect,recursiveCheck);
return compiler;
} //}}}
//{{{ compileDataStackToJVMStack() method
private void compileDataStackToJVMStack(StackEffect effect,
CodeVisitor mw)
{
if(effect.inD != 0)
{
mw.visitVarInsn(ALOAD,1);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorArray;");
// ensure the stack has enough elements
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,effect.inD);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArray", "ensurePop",
"(I)V");
// datastack.stack -> 2
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArray", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,2);
// datastack.top-args.length -> 3
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArray", "top",
"I");
mw.visitIntInsn(BIPUSH,effect.inD);
mw.visitInsn(ISUB);
// datastack.top -= args.length
mw.visitInsn(DUP_X1);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArray", "top",
"I");
mw.visitVarInsn(ISTORE,3);
for(int i = 0; i < effect.inD; i++)
{
mw.visitVarInsn(ALOAD,2);
mw.visitVarInsn(ILOAD,3);
mw.visitInsn(AALOAD);
if(i != effect.inD - 1)
mw.visitIincInsn(3,1);
}
}
} //}}}
//{{{ compileJVMStackToDataStack() method
private void compileJVMStackToDataStack(StackEffect effect,
CodeVisitor mw)
{
if(effect.outD == 1)
{
// ( datastack )
mw.visitVarInsn(ALOAD,1);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorArray;");
mw.visitInsn(SWAP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArray", "push",
"(Ljava/lang/Object;)V");
}
} //}}}
//{{{ fromList() method
public void fromList(Cons definition, FactorInterpreter interp)
public void fromList(Cons definition)
{
this.definition = definition;
if(definition == null)
@ -343,7 +73,7 @@ public class FactorCompoundDefinition extends FactorWordDefinition
} //}}}
//{{{ toList() method
public Cons toList(FactorInterpreter interp)
public Cons toList()
{
return definition;
} //}}}

View File

@ -29,7 +29,6 @@
package factor;
import factor.compiler.FactorCompiler;
import factor.math.*;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.*;

View File

@ -29,7 +29,6 @@
package factor;
import factor.compiler.*;
import java.util.Set;
/**
@ -47,7 +46,7 @@ public abstract class FactorPrimitiveDefinition extends FactorWordDefinition
} //}}}
//{{{ fromList() method
public void fromList(Cons cons, FactorInterpreter interp)
public void fromList(Cons cons)
{
} //}}}
}

View File

@ -29,9 +29,7 @@
package factor;
import factor.compiler.*;
import java.util.*;
import org.objectweb.asm.*;
/**
* ~<< name ... -- >>~
@ -59,11 +57,11 @@ public class FactorShuffleDefinition extends FactorWordDefinition
private int shuffleRlength;
//{{{ FactorShuffleDefinition constructor
public FactorShuffleDefinition(FactorWord word, Cons definition,
FactorInterpreter interp) throws FactorException
public FactorShuffleDefinition(FactorWord word, Cons definition)
throws FactorException
{
super(word);
fromList(definition,interp);
fromList(definition);
} //}}}
//{{{ FactorShuffleDefinition constructor
@ -113,32 +111,6 @@ public class FactorShuffleDefinition extends FactorWordDefinition
}
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws FactorStackException
{
compileCallTo(null,compiler,recursiveCheck);
} //}}}
//{{{ compile() method
/**
* Compile the given word, returning a new word definition.
*/
FactorWordDefinition compile(FactorInterpreter interp,
RecursiveState recursiveCheck) throws Exception
{
return this;
} //}}}
//{{{ compileCallTo() method
public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
RecursiveState recursiveCheck) throws FactorStackException
{
compiler.ensure(compiler.datastack,consumeD);
compiler.ensure(compiler.callstack,consumeR);
eval(compiler.interp,compiler.datastack,compiler.callstack);
} //}}}
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws FactorStackException
@ -223,7 +195,7 @@ public class FactorShuffleDefinition extends FactorWordDefinition
} //}}}
//{{{ fromList() method
public void fromList(Cons definition, FactorInterpreter interp)
public void fromList(Cons definition)
throws FactorRuntimeException
{
String f = "--";
@ -345,7 +317,7 @@ public class FactorShuffleDefinition extends FactorWordDefinition
} //}}}
//{{{ toList() method
public Cons toList(FactorInterpreter interp)
public Cons toList()
{
Cons list = null;

View File

@ -29,9 +29,6 @@
package factor;
import factor.compiler.*;
import org.objectweb.asm.*;
/**
* SYMBOL: name
*
@ -58,38 +55,14 @@ public class FactorSymbolDefinition extends FactorWordDefinition
interp.datastack.push(symbol);
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compiler.pushLiteral(symbol,recursiveCheck);
} //}}}
//{{{ compile() method
/**
* Compile the given word, returning a new word definition.
*/
FactorWordDefinition compile(FactorInterpreter interp,
RecursiveState recursiveCheck) throws Exception
{
return this;
} //}}}
//{{{ compileCallTo() method
public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
RecursiveState recursiveCheck) throws FactorStackException
{
compiler.pushLiteral(symbol,recursiveCheck);
} //}}}
//{{{ fromList() method
public void fromList(Cons definition, FactorInterpreter interp)
public void fromList(Cons definition)
{
this.symbol = definition.car;
} //}}}
//{{{ toList() method
public Cons toList(FactorInterpreter interp)
public Cons toList()
{
return new Cons(symbol,null);
} //}}}

View File

@ -29,7 +29,6 @@
package factor;
import factor.compiler.*;
import java.util.*;
/**
@ -52,11 +51,6 @@ public class FactorWord implements FactorExternalizable, FactorObject
*/
public FactorParsingDefinition parsing;
/**
* Is this word referenced from a compiled word?
*/
public boolean compileRef;
/**
* Should this word be inlined when compiling?
*/
@ -67,12 +61,6 @@ public class FactorWord implements FactorExternalizable, FactorObject
*/
public boolean interpretOnly;
/**
* Only compiled words have this.
*/
public FactorClassLoader loader;
public String className;
/**
* For text editor integration.
*/
@ -127,72 +115,9 @@ public class FactorWord implements FactorExternalizable, FactorObject
} //}}}
//{{{ define() method
public synchronized void define(FactorWordDefinition def)
public void define(FactorWordDefinition def)
{
if(compileRef)
{
System.err.println("WARNING: " + this
+ " is used in one or more compiled words; old definition will remain until full recompile");
}
else if(this.def != null)
System.err.println("WARNING: redefining " + this);
this.def = def;
loader = null;
className = null;
} //}}}
//{{{ setCompiledInfo() method
synchronized void setCompiledInfo(FactorClassLoader loader,
String className)
{
this.loader = loader;
this.className = className;
} //}}}
//{{{ compile() method
public synchronized void compile(FactorInterpreter interp)
{
RecursiveState recursiveCheck = new RecursiveState();
recursiveCheck.add(this,new StackEffect(),null,null,null);
compile(interp,recursiveCheck);
recursiveCheck.remove(this);
} //}}}
//{{{ compile() method
public synchronized void compile(FactorInterpreter interp,
RecursiveState recursiveCheck)
{
if(def == null)
return;
if(interpretOnly)
{
if(interp.verboseCompile)
System.err.println(this + " is interpret-only");
return;
}
//if(def.compileFailed)
// return;
if(interp.verboseCompile)
System.err.println("Compiling " + this);
try
{
def = def.compile(interp,recursiveCheck);
}
catch(Throwable t)
{
def.compileFailed = true;
if(interp.verboseCompile)
{
System.err.println("WARNING: cannot compile " + this);
t.printStackTrace();
}
}
} //}}}
//{{{ toString() method

View File

@ -29,18 +29,15 @@
package factor;
import factor.compiler.*;
import java.io.*;
import java.util.*;
import org.objectweb.asm.*;
/**
* A word definition.
*/
public abstract class FactorWordDefinition implements Constants
public abstract class FactorWordDefinition
{
public FactorWord word;
public boolean compileFailed;
//{{{ FactorWordDefinition constructor
/**
@ -55,273 +52,18 @@ public abstract class FactorWordDefinition implements Constants
throws Exception;
//{{{ fromList() method
public void fromList(Cons cons, FactorInterpreter interp)
public void fromList(Cons cons)
throws FactorRuntimeException
{
throw new FactorRuntimeException("Cannot unpickle " + this);
} //}}}
//{{{ toList() method
public Cons toList(FactorInterpreter interp)
public Cons toList()
{
return new Cons(new FactorWord(null,getClass().getName()),null);
} //}}}
//{{{ getStackEffect() method
public final StackEffect getStackEffect(FactorInterpreter interp)
throws Exception
{
return getStackEffect(new RecursiveState(),interp);
} //}}}
//{{{ getStackEffect() method
public final StackEffect getStackEffect(RecursiveState recursiveCheck,
FactorInterpreter interp) throws Exception
{
FactorCompiler compiler = new FactorCompiler(interp);
recursiveCheck.add(word,new StackEffect(),null,null,null);
getStackEffect(recursiveCheck,compiler);
recursiveCheck.remove(word);
return compiler.getStackEffect();
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
throw new FactorCompilerException("Cannot deduce stack effect of " + word);
} //}}}
//{{{ compile() method
FactorWordDefinition compile(FactorInterpreter interp,
RecursiveState recursiveCheck) throws Exception
{
return this;
} //}}}
//{{{ compileCallTo() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
RecursiveState recursiveCheck) throws Exception
{
// normal word
String defclass;
String defmethod;
StackEffect effect;
FactorClassLoader loader;
RecursiveForm rec = recursiveCheck.get(word);
if(rec != null && rec.active)
{
if(compiler.interp.verboseCompile)
System.err.println("Recursive call to " + rec);
effect = StackEffect.decompose(rec.effect,rec.baseCase);
// are we recursing back on a form inside the current
// method?
RecursiveForm last = recursiveCheck.last();
if(recursiveCheck.allTails(rec)
&& last.className.equals(rec.className)
&& last.method.equals(rec.method))
{
if(compiler.interp.verboseCompile)
System.err.println(word + " is tail recursive");
// GOTO instad of INVOKEVIRTUAL; ie a loop!
compiler.normalizeStacks(mw);
mw.visitJumpInsn(GOTO,rec.label);
compiler.apply(effect);
return;
}
/* recursive method call! */
defclass = rec.className;
defmethod = rec.method;
loader = rec.loader;
if(!defclass.equals(compiler.className))
compiler.loader.addDependency(defclass,loader);
}
// not a recursive call but we're still not compiled
// its a bug in the compiler.
else if(this instanceof FactorCompoundDefinition)
{
throw new FactorCompilerException("You are an idiot!");
}
// inlining?
else if(word.inline)
{
compileImmediate(mw,compiler,recursiveCheck);
return;
}
/* ordinary method call! */
else
{
defclass = getClass().getName().replace('.','/');
defmethod = "core";
effect = getStackEffect(compiler.interp);
ClassLoader l = getClass().getClassLoader();
if(l instanceof FactorClassLoader)
{
loader = (FactorClassLoader)l;
compiler.loader.addDependency(getClass().getName(),loader);
}
else
loader = null;
}
mw.visitVarInsn(ALOAD,0);
compiler.generateArgs(mw,effect.inD,effect.inR,null);
String signature = effect.getCorePrototype();
mw.visitMethodInsn(INVOKESTATIC,defclass,defmethod,signature);
compiler.generateReturn(mw,effect.outD,effect.outR);
} //}}}
//{{{ compileNonRecursiveImmediate() method
/**
* Non-recursive immediate words are inlined.
*/
protected void compileNonRecursiveImmediate(CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck,
StackEffect immediateEffect) throws Exception
{
Cons definition = toList(compiler.getInterpreter());
Cons endOfDocs = definition;
while(endOfDocs != null
&& endOfDocs.car instanceof FactorDocComment)
endOfDocs = endOfDocs.next();
compiler.compile(endOfDocs,mw,recursiveCheck);
} //}}}
//{{{ compileRecursiveImmediate() method
/**
* Recursive immediate words are compiled to an auxiliary method
* inside the compiled class definition.
*
* This must be done so that recursion has something to jump to.
*/
protected void compileRecursiveImmediate(CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck,
StackEffect immediateEffect) throws Exception
{
Cons definition = toList(compiler.getInterpreter());
Cons endOfDocs = definition;
while(endOfDocs != null
&& endOfDocs.car instanceof FactorDocComment)
endOfDocs = endOfDocs.next();
String method = compiler.auxiliary(word,
endOfDocs,immediateEffect,recursiveCheck);
mw.visitVarInsn(ALOAD,0);
compiler.generateArgs(mw,immediateEffect.inD,
immediateEffect.inR,null);
String signature = immediateEffect.getCorePrototype();
mw.visitMethodInsn(INVOKESTATIC,compiler.className,
method,signature);
compiler.generateReturn(mw,
immediateEffect.outD,
immediateEffect.outR);
} //}}}
//{{{ compileImmediate() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public void compileImmediate(CodeVisitor mw, FactorCompiler compiler,
RecursiveState recursiveCheck) throws Exception
{
Cons definition = toList(compiler.getInterpreter());
if(definition == null)
return;
Cons endOfDocs = definition;
while(endOfDocs != null
&& endOfDocs.car instanceof FactorDocComment)
endOfDocs = endOfDocs.next();
// determine stack effect of this instantiation, and if its
// recursive.
FactorArray savedDatastack = (FactorArray)
compiler.datastack.clone();
FactorArray savedCallstack = (FactorArray)
compiler.callstack.clone();
StackEffect savedEffect = compiler.getStackEffect();
RecursiveState _recursiveCheck = (RecursiveState)
recursiveCheck.clone();
_recursiveCheck.last().effect = compiler.getStackEffect();
getStackEffect(_recursiveCheck,compiler);
boolean recursive = (_recursiveCheck.last().baseCase != null);
StackEffect effect = compiler.getStackEffect();
StackEffect immediateEffect = StackEffect.decompose(
savedEffect,compiler.getStackEffect());
// restore previous state.
FactorArray afterDatastack = (FactorArray)
compiler.datastack.clone();
FactorArray afterCallstack = (FactorArray)
compiler.callstack.clone();
compiler.datastack = (FactorArray)savedDatastack.clone();
compiler.callstack = (FactorArray)savedCallstack.clone();
compiler.effect = savedEffect;
if(!recursive)
{
// not recursive; inline.
compileNonRecursiveImmediate(mw,compiler,recursiveCheck,
immediateEffect);
}
else
{
// recursive; must generate auxiliary method.
compileRecursiveImmediate(mw,compiler,recursiveCheck,
immediateEffect);
mergeStacks(savedDatastack,afterDatastack,compiler.datastack);
mergeStacks(savedCallstack,afterCallstack,compiler.callstack);
}
} //}}}
//{{{ mergeStacks() method
private void mergeStacks(FactorArray s1, FactorArray s2,
FactorArray into)
{
for(int i = 0; i < s2.top; i++)
{
if(s1.top <= i)
break;
if(FactorLib.objectsEqual(s1.stack[i],
s2.stack[i]))
{
into.stack[i] = s1.stack[i];
}
}
} //}}}
//{{{ toString() method
public String toString()
{

View File

@ -1,105 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import org.objectweb.asm.*;
class AuxiliaryQuotation
{
private String method;
private FactorArray datastack;
private FactorArray callstack;
private Cons code;
private StackEffect effect;
private FactorWord word;
private RecursiveState recursiveCheck;
//{{{ AuxiliaryQuotation constructor
AuxiliaryQuotation(String method,
FactorArray datastack,
FactorArray callstack,
Cons code,
StackEffect effect,
FactorWord word,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
this.method = method;
this.datastack = datastack;
this.callstack = callstack;
this.code = code;
this.effect = effect;
this.word = word;
this.recursiveCheck = new RecursiveState(recursiveCheck);
System.arraycopy(datastack.stack,datastack.top - effect.inD,
datastack.stack,0,effect.inD);
for(int i = 0; i < effect.inD; i++)
{
int index = datastack.top - effect.inD + i;
FlowObject flow = (FlowObject)datastack.stack[index];
datastack.stack[index] = flow.munge(
1,index,compiler,recursiveCheck);
}
System.arraycopy(callstack.stack,callstack.top - effect.inR,
callstack.stack,0,effect.inD);
for(int i = 0; i < effect.inR; i++)
{
int index = callstack.top - effect.inR + i;
FlowObject flow = (FlowObject)callstack.stack[index];
callstack.stack[index] = flow.munge(
1 + effect.inD,index,compiler,recursiveCheck);
}
} //}}}
//{{{ compile() method
void compile(FactorCompiler compiler, ClassWriter cw)
throws Exception
{
// generate core
compiler.init(1,effect.inD,effect.inR,method);
compiler.datastack = datastack;
compiler.callstack = callstack;
//compiler.produce(compiler.datastack,effect.inD);
// important: this.recursiveCheck due to
// lexically-scoped recursion issues
compiler.compileMethod(code,cw,method,effect,word,
new RecursiveState(this.recursiveCheck),false);
} //}}}
//{{{ toString() method
public String toString()
{
return method + effect;
} //}}}
}

View File

@ -1,63 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
/**
* Compiled colon definition.
*/
public abstract class CompiledDefinition
extends FactorWordDefinition
{
//{{{ CompiledDefinition constructor
public CompiledDefinition(FactorWord word)
{
super(word);
} //}}}
//{{{ create() method
public static CompiledDefinition create(FactorInterpreter interp,
FactorWord word, Class compiledWordClass)
throws Exception
{
Constructor constructor = compiledWordClass
.getConstructor(
new Class[] {
FactorWord.class
});
return (CompiledDefinition)constructor.newInstance(
new Object[] { word });
} //}}}
}

View File

@ -1,128 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
public class CompiledList extends FlowObject
{
protected Cons quotation;
protected RecursiveState recursiveCheck;
//{{{ CompiledList constructor
CompiledList(Cons quotation, FactorCompiler compiler,
RecursiveState recursiveCheck)
{
super(compiler,recursiveCheck.lastCallable());
this.quotation = quotation;
// clone it
this.recursiveCheck = new RecursiveState(
recursiveCheck);
expectedType = Cons.class;
} //}}}
//{{{ pop() method
public void pop(CodeVisitor mw)
{
mw.visitFieldInsn(GETSTATIC,compiler.className,
compiler.literal(quotation),
"Ljava/lang/Object;");
} //}}}
//{{{ munge() method
/**
* Munging transforms the flow object such that it is now stored in
* a local variable and hence can be mutated by compiled code, however
* its original compileCallTo() semantics remain (for example, if it is
* a quotation).
*/
FlowObject munge(int base, int index,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
return new CompiledListResult(index + base,
quotation,compiler,
this.recursiveCheck);
} //}}}
//{{{ getLiteral() method
Object getLiteral()
{
return quotation;
} //}}}
//{{{ compileCallTo()
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public void compileCallTo(CodeVisitor mw,
RecursiveState recursiveCheck)
throws Exception
{
RecursiveForm last = this.recursiveCheck.last();
FactorWord word = FactorWord.gensym();
try
{
recursiveCheck.add(word,new StackEffect(),
last.className,last.loader,last.method,last);
recursiveCheck.last().callable = false;
compiler.compile(quotation,mw,recursiveCheck);
}
finally
{
recursiveCheck.remove(word);
}
} //}}}
//{{{ equals() method
public boolean equals(Object o)
{
if(o instanceof CompiledList)
{
CompiledList c = (CompiledList)o;
return FactorLib.objectsEqual(c.quotation,quotation);
}
else if(o instanceof Null)
return quotation == null;
else
return false;
} //}}}
//{{{ clone() method
public Object clone()
{
return new CompiledList(quotation,compiler,recursiveCheck);
} //}}}
}

View File

@ -1,81 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
public class CompiledListResult extends CompiledList implements Constants
{
private int local;
//{{{ CompiledListResult constructor
CompiledListResult(int local, Cons quotation,
FactorCompiler compiler,
RecursiveState recursiveCheck)
{
super(quotation,compiler,recursiveCheck);
this.local = local;
} //}}}
//{{{ push() method
public void push(CodeVisitor mw)
throws Exception
{
mw.visitVarInsn(ASTORE,local);
} //}}}
//{{{ pop() method
public void pop(CodeVisitor mw)
{
mw.visitVarInsn(ALOAD,local);
} //}}}
//{{{ getLocal() method
public int getLocal()
{
return local;
} //}}}
//{{{ usingLocal() method
boolean usingLocal(int local)
{
return (this.local == local);
} //}}}
//{{{ clone() method
public Object clone()
{
return new CompiledListResult(local,quotation,compiler,
recursiveCheck);
} //}}}
}

View File

@ -1,231 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
public class CompilerState
{
public FactorArray datastack;
public FactorArray callstack;
public StackEffect effect;
public Cons inDtypes;
public Cons inRtypes;
//{{{ CompilerState constructor
public CompilerState(FactorCompiler compiler)
{
datastack = (FactorArray)compiler.datastack.clone();
callstack = (FactorArray)compiler.callstack.clone();
effect = (StackEffect)compiler.getStackEffect();
inDtypes = cloneTypespec(compiler,compiler.inDtypes);
inRtypes = cloneTypespec(compiler,compiler.inRtypes);
} //}}}
//{{{ restore() method
public void restore(FactorCompiler compiler)
{
compiler.datastack = (FactorArray)datastack.clone();
compiler.callstack = (FactorArray)callstack.clone();
compiler.effect = (StackEffect)effect.clone();
compiler.inDtypes = cloneTypespec(compiler,inDtypes);
compiler.inRtypes = cloneTypespec(compiler,inRtypes);
} //}}}
//{{{ findResult() method
private static Result findResult(Result result,
FactorArray stack)
{
for(int i = 0; i < stack.top; i++)
{
if(stack.stack[i] instanceof Result)
{
Result r = (Result)stack.stack[i];
if(r.getLocal() == result.getLocal())
return r;
}
}
return null;
} //}}}
//{{{ cloneResult() method
private static Result cloneResult(Result result,
FactorArray datastack,
FactorArray callstack)
{
Result r = findResult(result,datastack);
if(r != null)
return r;
r = findResult(result,callstack);
if(r != null)
return r;
return (Result)result.clone();
} //}}}
//{{{ cloneTypespec() method
private static Cons cloneTypespec(FactorCompiler compiler, Cons spec)
{
Cons newSpec = null;
while(spec != null)
{
newSpec = new Cons(cloneResult((Result)spec.car,
compiler.datastack,compiler.callstack),
newSpec);
spec = spec.next();
}
return Cons.reverse(newSpec);
} //}}}
//{{{ commonAncestor() method
private static Class commonAncestor(Class ca, Class cb)
{
if(ca.isAssignableFrom(cb))
return ca;
else if(cb.isAssignableFrom(ca))
return cb;
else if(ca.isInterface() || cb.isInterface())
return Object.class;
else
return commonAncestor(ca.getSuperclass(),cb);
} //}}}
//{{{ unifyTypes() method
private static Cons unifyTypes(FactorCompiler compiler,
RecursiveState recursiveCheck,
Cons a, Cons b)
{
Cons cons = null;
for(;;)
{
if(a == null && b == null)
return Cons.reverse(cons);
int la, lb;
Class ca, cb;
if(a == null)
{
la = -1;
ca = Object.class;
}
else
{
FlowObject fa = (FlowObject)a.car;
la = fa.getLocal();
ca = fa.getType();
a = a.next();
}
if(b == null)
{
lb = -1;
cb = Object.class;
}
else
{
FlowObject fb = (FlowObject)b.car;
lb = fb.getLocal();
//if(la != -1 && la != lb)
// System.err.println("? " + a + "," + b);
cb = fb.getType();
b = b.next();
}
//System.err.println("Common ancestor of " + ca + " and " + cb + " is " + commonAncestor(ca,cb));
cons = new Cons(
new Result(la,compiler,recursiveCheck.last(),
commonAncestor(ca,cb)),cons);
}
} //}}}
//{{{ mergeStacks() method
private static void mergeStacks(FactorCompiler compiler,
RecursiveState recursiveCheck,
FactorArray s1, FactorArray s2,
FactorArray into)
{
for(int i = Math.min(s1.top,s2.top) - 1; i >= 0; i--)
{
FlowObject fa = (FlowObject)s1.stack[s1.top - i - 1];
FlowObject fb = (FlowObject)s2.stack[s2.top - i - 1];
into.stack[into.top - i - 1]
= new Result(i,compiler,recursiveCheck.last(),
commonAncestor(fa.getType(),fb.getType()));
}
} //}}}
//{{{ unifyStates() method
public static void unifyStates(
FactorCompiler compiler,
RecursiveState recursiveCheck,
FlowObject t, FlowObject f,
CompilerState a, CompilerState b)
throws Exception
{
StackEffect te = a.effect;
StackEffect fe = b.effect;
// we can only balance out a conditional if
// both sides leave the same amount of elements
// on the stack.
// eg, 1/1 -vs- 2/2 is ok, 3/1 -vs- 4/2 is ok,
// but 1/2 -vs- 2/1 is not.
if(te.outD - te.inD != fe.outD - fe.inD
|| te.outR - te.inR != fe.outR - fe.inR)
{
throw new FactorCompilerException(
"Stack effect of " + t + " " + a.effect + " is inconsistent with " + f + " " + b.effect
+ "\nRecursive state:\n"
+ recursiveCheck);
}
compiler.ensure(compiler.datastack,Math.max(te.outD,fe.outD));
compiler.ensure(compiler.callstack,Math.max(te.outR,fe.outR));
// replace results from the f branch with
// dummy values so that subsequent code
// doesn't assume these values always
// result from this
mergeStacks(compiler,recursiveCheck,a.datastack,
b.datastack,compiler.datastack);
mergeStacks(compiler,recursiveCheck,a.callstack,
b.callstack,compiler.callstack);
compiler.inDtypes = unifyTypes(compiler,recursiveCheck,
a.inDtypes,b.inDtypes);
compiler.inRtypes = unifyTypes(compiler,recursiveCheck,
a.inRtypes,b.inRtypes);
} //}}}
}

View File

@ -1,67 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
public class ConstantPoolString extends FlowObject
{
private String str;
//{{{ ConstantPoolString constructor
ConstantPoolString(String str, FactorCompiler compiler,
RecursiveForm word)
{
super(compiler,word);
this.str = str;
expectedType = String.class;
} //}}}
//{{{ pop() method
public void pop(CodeVisitor mw)
{
mw.visitLdcInsn(str);
} //}}}
//{{{ getLiteral() method
Object getLiteral()
{
return str;
} //}}}
//{{{ clone() method
public Object clone()
{
return new Null(compiler,word);
} //}}}
}

View File

@ -1,117 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003, 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.util.*;
/**
* Each word class has a class loader.
*
* When compiling a word; add each dependent word to new class loader's
* delegates map.
*/
public class FactorClassLoader extends ClassLoader
{
private long id;
private FactorNamespace table = new FactorNamespace();
private ClassLoader delegate;
//{{{ FactorClassLoader constructor
public FactorClassLoader(ClassLoader delegate)
{
this.delegate = delegate;
} //}}}
//{{{ addDependency() method
public void addDependency(String name, FactorClassLoader loader)
{
try
{
table.setVariable(name,loader);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
} //}}}
//{{{ addClass() method
public Class addClass(String name, byte[] code, int off, int len)
{
return defineClass(name,code,off,len);
} //}}}
//{{{ loadClass() method
public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
if(c != null)
{
if(resolve)
resolveClass(c);
return c;
}
// See if another known class loader has this
try
{
Object obj = table.getVariable(name);
if(obj instanceof FactorClassLoader)
{
return ((FactorClassLoader)obj)
.loadClass(name,resolve);
}
else if(obj != null)
{
System.err.println("WARNING: unknown object in class loader table for " + this + ": " + obj);
}
if(delegate == null)
return super.loadClass(name,resolve);
else
{
c = delegate.loadClass(name);
if(resolve)
resolveClass(c);
return c;
}
}
catch(ClassNotFoundException e)
{
throw e;
}
catch(Exception e)
{
throw new RuntimeException(e);
}
} //}}}
}

View File

@ -1,899 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
public class FactorCompiler implements Constants
{
public final FactorInterpreter interp;
public final FactorWord word;
public final String className;
public final FactorClassLoader loader;
public String method;
private int base;
private int allotD;
private int allotR;
public FactorArray datastack;
public FactorArray callstack;
private int literalCount;
private Map literals;
public StackEffect effect;
/**
* getStackEffect() turns these into arrays and places them in the
* returned object.
*/
public Cons inDtypes, inRtypes;
private Cons aux;
private int auxCount;
//{{{ FactorCompiler constructor
/**
* For balancing.
*/
public FactorCompiler(FactorInterpreter interp)
{
this(interp,null,null,null);
init(0,0,0,null);
} //}}}
//{{{ FactorCompiler constructor
/**
* For compiling.
*/
public FactorCompiler(FactorInterpreter interp,
FactorWord word, String className,
FactorClassLoader loader)
{
this.interp = interp;
this.word = word;
this.className = className;
this.loader = loader;
literals = new HashMap();
datastack = new FactorArray();
callstack = new FactorArray();
} //}}}
//{{{ getInterpreter() method
public FactorInterpreter getInterpreter()
{
return interp;
} //}}}
//{{{ init() method
public void init(int base, int allotD, int allotR, String method)
{
effect = new StackEffect();
this.base = base;
datastack.top = 0;
callstack.top = 0;
for(int i = 0; i < allotD; i++)
{
Result r = new Result(base + i,this,null,
Object.class,true);
datastack.push(r);
inDtypes = new Cons(r,inDtypes);
}
for(int i = 0; i < allotR; i++)
{
Result r = new Result(base + allotD + i,this,null,
Object.class,true);
callstack.push(r);
inRtypes = new Cons(r,inRtypes);
}
this.allotD = allotD;
this.allotR = allotR;
effect.inD = allotD;
effect.inR = allotR;
this.method = method;
} //}}}
//{{{ getAllotedEffect() method
public StackEffect getAllotedEffect()
{
return new StackEffect(allotD,allotR,0,0);
} //}}}
//{{{ ensure() method
public void ensure(FactorArray stack, Class type)
{
if(stack.top == 0)
{
Result r = new Result(allocate(),this,null,type);
if(stack == datastack)
{
inDtypes = new Cons(r,inDtypes);
effect.inD++;
}
else if(stack == callstack)
{
inRtypes = new Cons(r,inRtypes);
effect.inR++;
}
stack.push(r);
}
} //}}}
//{{{ ensure() method
/**
* Ensure stack has at least 'count' elements.
* Eg, if count is 4 and stack is A B,
* stack will become RESULT RESULT A B.
* Used when deducing stack effects.
*/
public void ensure(FactorArray stack, Class[] types)
{
int top = stack.top;
if(top < types.length)
{
Cons typespec = null;
if(stack == datastack)
effect.inD += (types.length - top);
else if(stack == callstack)
effect.inR += (types.length - top);
stack.ensurePush(types.length - top);
System.arraycopy(stack.stack,0,stack.stack,
types.length - top,top);
for(int i = 0; i < types.length - top; i++)
{
int local = allocate();
Result r = new Result(
local,this,null,types[i]);
stack.stack[i] = r;
typespec = new Cons(r,typespec);
}
stack.top = types.length;
if(stack == datastack)
inDtypes = Cons.nappend(inDtypes,typespec);
else if(stack == callstack)
inRtypes = Cons.nappend(inRtypes,typespec);
}
} //}}}
//{{{ ensure() method
/**
* Ensure stack has at least 'count' elements.
* Eg, if count is 4 and stack is A B,
* stack will become RESULT RESULT A B.
* Used when deducing stack effects.
*/
public void ensure(FactorArray stack, int count)
{
Class[] types = new Class[count];
for(int i = 0; i < types.length; i++)
types[i] = Object.class;
ensure(stack,types);
} //}}}
//{{{ consume() method
public void consume(FactorArray stack, int count)
{
ensure(stack,count);
stack.top -= count;
} //}}}
//{{{ produce() method
public void produce(FactorArray stack, int count)
{
for(int i = 0; i < count; i++)
{
int local = allocate();
stack.push(new Result(local,this,null,Object.class));
}
} //}}}
//{{{ apply() method
public void apply(StackEffect se)
{
consume(datastack,se.inD);
produce(datastack,se.outD);
consume(callstack,se.inR);
produce(callstack,se.outR);
} //}}}
//{{{ getTypeSpec() method
private Class[] getTypeSpec(Cons list)
{
if(list == null)
return new Class[0];
int length = list.length();
Class[] typespec = new Class[length];
int i = 0;
while(list != null)
{
typespec[length - i - 1]
= ((FlowObject)list.car).getType();
i++;
list = list.next();
}
return typespec;
} //}}}
//{{{ getStackEffect() method
public StackEffect getStackEffect()
{
effect.inDtypes = getTypeSpec(inDtypes);
effect.outD = datastack.top;
effect.outDtypes = new Class[datastack.top];
for(int i = 0; i < datastack.top; i++)
{
effect.outDtypes[i] = ((FlowObject)datastack.stack[i])
.getType();
}
effect.inRtypes = getTypeSpec(inRtypes);
effect.outR = callstack.top;
effect.outRtypes = new Class[callstack.top];
for(int i = 0; i < callstack.top; i++)
{
effect.outRtypes[i] = ((FlowObject)callstack.stack[i])
.getType();
}
return (StackEffect)effect.clone();
} //}}}
//{{{ compileCore() method
public void compileCore(Cons definition, ClassWriter cw,
StackEffect effect, RecursiveState recursiveCheck)
throws Exception
{
RecursiveForm last = recursiveCheck.last();
last.method = "core";
last.className = className;
last.loader = loader;
compileMethod(definition,cw,"core",effect,word,recursiveCheck,true);
} //}}}
//{{{ compileFieldInit() method
private void compileFieldInit(CodeVisitor mw, Label start)
{
mw.visitFieldInsn(GETSTATIC,className,"initialized","Z");
mw.visitJumpInsn(IFNE,start);
mw.visitInsn(ICONST_1);
mw.visitFieldInsn(PUTSTATIC,className,"initialized","Z");
mw.visitVarInsn(ALOAD,0);
mw.visitMethodInsn(INVOKESTATIC,className,"setFields",
"(Lfactor/FactorInterpreter;)V");
} //}}}
//{{{ compileReturn() method
/**
* Once the word finishes executing, any return values need to be
* passed up.
*/
private void compileReturn(CodeVisitor mw, Label end,
StackEffect effect) throws Exception
{
// special case where return value is passed on
// JVM operand stack
// note: in each branch, must visit end label before RETURN!
if(effect.outD == 0 && effect.outR == 0)
{
mw.visitLabel(end);
mw.visitInsn(RETURN);
}
else if(effect.outD == 1 && effect.outR == 0)
{
pop(datastack,mw,Object.class);
mw.visitLabel(end);
mw.visitInsn(ARETURN);
}
else
{
// store datastack in a local
mw.visitVarInsn(ALOAD,0);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter",
"datastack",
"Lfactor/FactorArray;");
int datastackLocal = allocate();
mw.visitVarInsn(ASTORE,datastackLocal);
for(int i = 0; i < datastack.top; i++)
{
mw.visitVarInsn(ALOAD,datastackLocal);
((FlowObject)datastack.stack[i])
.pop(mw,Object.class);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArray",
"push",
"(Ljava/lang/Object;)V");
}
datastack.top = 0;
// store callstack in a local
mw.visitVarInsn(ALOAD,0);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter",
"callstack",
"Lfactor/FactorArray;");
int callstackLocal = allocate();
mw.visitVarInsn(ASTORE,callstackLocal);
for(int i = 0; i < callstack.top; i++)
{
mw.visitVarInsn(ALOAD,callstackLocal);
((FlowObject)callstack.stack[i])
.pop(mw,Object.class);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArray",
"push",
"(Ljava/lang/Object;)V");
}
callstack.top = 0;
mw.visitLabel(end);
mw.visitInsn(RETURN);
}
} //}}}
//{{{ compileMethod() method
/**
* Compiles a method.
*/
public void compileMethod(Cons definition, ClassWriter cw,
String methodName, StackEffect effect, FactorWord word,
RecursiveState recursiveCheck, boolean fieldInit)
throws Exception
{
String signature = effect.getCorePrototype();
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC | ACC_STATIC,
methodName,signature,null,null);
Label start = recursiveCheck.get(word).label;
if(fieldInit)
compileFieldInit(mw,start);
mw.visitLabel(start);
compile(definition,mw,recursiveCheck);
Label end = new Label();
compileReturn(mw,end,effect);
compileExceptionHandler(mw,start,end,word);
mw.visitMaxs(0,0);
} //}}}
//{{{ compileExceptionHandler() method
private void compileExceptionHandler(CodeVisitor mw,
Label start, Label end, FactorWord word)
{
// otherwise no code can throw exception etc
if(start.getOffset() != end.getOffset())
{
// Now compile exception handler.
Label target = new Label();
mw.visitLabel(target);
mw.visitVarInsn(ASTORE,1);
mw.visitVarInsn(ALOAD,0);
mw.visitFieldInsn(GETSTATIC,className,literal(word),
"Ljava/lang/Object;");
mw.visitTypeInsn(CHECKCAST,"factor/FactorWord");
mw.visitVarInsn(ALOAD,1);
mw.visitMethodInsn(INVOKEVIRTUAL,"factor/FactorInterpreter",
"compiledException",
"(Lfactor/FactorWord;Ljava/lang/Throwable;)V");
mw.visitVarInsn(ALOAD,1);
mw.visitInsn(ATHROW);
mw.visitTryCatchBlock(start,end,target,"java/lang/Throwable");
}
} //}}}
//{{{ compile() method
/**
* Compiles a quotation.
*/
public void compile(Cons definition, CodeVisitor mw,
RecursiveState recursiveCheck) throws Exception
{
while(definition != null)
{
Object obj = definition.car;
if(obj instanceof FactorWord)
{
compileWord((FactorWord)obj,mw,recursiveCheck,
definition.cdr == null);
}
else
pushLiteral(obj,recursiveCheck);
definition = definition.next();
}
} //}}}
//{{{ compileWord() method
private void compileWord(FactorWord w, CodeVisitor mw,
RecursiveState recursiveCheck,
boolean tail) throws Exception
{
if(tail && interp != null && interp.verboseCompile)
System.err.println("Tail: " + recursiveCheck.last());
recursiveCheck.last().tail = tail;
RecursiveForm rec = recursiveCheck.get(w);
try
{
boolean recursiveCall;
if(rec == null)
{
recursiveCall = false;
recursiveCheck.add(w,
new StackEffect(),
className,loader,
"core");
recursiveCheck.last().tail
= (w.def instanceof FactorPrimitiveDefinition);
}
else
{
recursiveCall = true;
rec.active = true;
}
compileCallTo(w,mw,recursiveCheck,recursiveCall);
}
finally
{
if(rec == null)
recursiveCheck.remove(w);
else
{
rec.active = false;
rec.tail = false;
}
}
} //}}}
//{{{ compileCallTo() method
private void compileCallTo(FactorWord w, CodeVisitor mw,
RecursiveState recursiveCheck,
boolean recursiveCall) throws Exception
{
if(w.def == null)
throw new FactorUndefinedWordException(w.name);
FactorWordDefinition d = w.def;
if(mw == null)
{
recursiveCheck.last().effect = getStackEffect();
d.getStackEffect(recursiveCheck,this);
return;
}
if(!recursiveCall)
{
if(w.inline)
{
recursiveCheck.last().effect = getStackEffect();
d.compileImmediate(mw,this,recursiveCheck);
return;
}
else if(d instanceof FactorCompoundDefinition)
{
w.compile(interp,recursiveCheck);
if(d == w.def)
{
throw new FactorCompilerException(word + " depends on " + w + " which cannot be compiled");
}
d = w.def;
}
}
d.compileCallTo(mw,this,recursiveCheck);
} //}}}
//{{{ push() method
/**
* Generates code for pushing the top of the JVM stack onto the
* data stack. Also generates code for converting this value to
* the given type.
*/
public void push(FactorArray stack, CodeVisitor mw, Class type)
throws Exception
{
int local = allocate();
Result r = new Result(local,this,null,type);
stack.push(r);
r.push(mw,type);
} //}}}
//{{{ pushLiteral() method
public void pushLiteral(Object literal, RecursiveState recursiveCheck)
{
RecursiveForm word = recursiveCheck.last();
if(literal == null)
datastack.push(new Null(this,word));
else if(literal instanceof Cons)
{
datastack.push(new CompiledList((Cons)literal,this,
recursiveCheck));
}
else if(literal instanceof String)
{
datastack.push(new ConstantPoolString((String)literal,
this,word));
}
else
datastack.push(new Literal(literal,this, word));
} //}}}
//{{{ pop() method
/**
* Generates code for popping the top of the data stack onto
* the JVM stack. Also generates code for converting this value to
* the given type.
*/
public void pop(FactorArray stack, CodeVisitor mw, Class type)
throws Exception
{
FlowObject obj = (FlowObject)datastack.pop();
obj.pop(mw,type);
} //}}}
//{{{ popLiteral() method
/**
* Pops a literal off the datastack or throws an exception.
*/
public Object popLiteral() throws FactorException
{
FlowObject obj = (FlowObject)datastack.pop();
return obj.getLiteral();
} //}}}
//{{{ allocate() method
/**
* Allocate a local variable.
*/
public int allocate()
{
// inefficient!
int i = base;
for(;;)
{
if(allocate(i,datastack) && allocate(i,callstack))
return i;
else
i++;
}
} //}}}
//{{{ allocate() method
/**
* Return true if not in use, false if in use.
*/
private boolean allocate(int local, FactorArray stack)
{
for(int i = 0; i < stack.top; i++)
{
FlowObject obj = (FlowObject)stack.stack[i];
if(obj.usingLocal(local))
return false;
}
return true;
} //}}}
//{{{ literal() method
public String literal(Object obj)
{
Integer i = (Integer)literals.get(obj);
int literal;
if(i == null)
{
literal = literalCount++;
literals.put(obj,new Integer(literal));
}
else
literal = i.intValue();
return "literal_" + literal;
} //}}}
//{{{ auxiliary() method
public String auxiliary(FactorWord word, Cons code, StackEffect effect,
RecursiveState recursiveCheck) throws Exception
{
FactorArray savedDatastack = (FactorArray)
datastack.clone();
FactorArray savedCallstack = (FactorArray)
callstack.clone();
String method = "aux_" + FactorJava.getSanitizedName(word.name)
+ "_" + (auxCount++);
recursiveCheck.last().method = method;
aux = new Cons(new AuxiliaryQuotation(
method,savedDatastack,savedCallstack,
code,effect,word,this,recursiveCheck),aux);
return method;
} //}}}
//{{{ generateAuxiliary() method
public void generateAuxiliary(ClassWriter cw) throws Exception
{
while(aux != null)
{
AuxiliaryQuotation q = (AuxiliaryQuotation)aux.car;
// order of these two important, in case
// compilation of q adds more quotations to aux list
aux = aux.next();
q.compile(this,cw);
}
} //}}}
//{{{ normalizeStacks() method
public void normalizeStacks(CodeVisitor mw)
throws Exception
{
int datastackTop = datastack.top;
datastack.top = 0;
int callstackTop = callstack.top;
callstack.top = 0;
localsToStack(callstack,callstackTop,mw);
localsToStack(datastack,datastackTop,mw);
stackToLocals(datastack,datastackTop,mw);
stackToLocals(callstack,callstackTop,mw);
} //}}}
//{{{ localsToStack() method
private void localsToStack(FactorArray stack, int top,
CodeVisitor mw) throws Exception
{
for(int i = top - 1; i >= 0; i--)
{
FlowObject obj = (FlowObject)stack.stack[i];
obj.pop(mw,Object.class);
}
} //}}}
//{{{ stackToLocals() method
private void stackToLocals(FactorArray stack, int top,
CodeVisitor mw) throws Exception
{
for(int i = 0; i < top; i++)
push(stack,mw,Object.class);
} //}}}
//{{{ generateArgs() method
/**
* Generate instructions for copying arguments from the allocated
* local variables to the JVM stack, doing type conversion in the
* process.
*/
public void generateArgs(CodeVisitor mw, int inD, int inR, Class[] args)
throws Exception
{
for(int i = 0; i < inD; i++)
{
FlowObject obj = (FlowObject)datastack.stack[
datastack.top - inD + i];
obj.pop(mw,args == null ? Object.class : args[i]);
}
datastack.top -= inD;
for(int i = 0; i < inR; i++)
{
FlowObject obj = (FlowObject)callstack.stack[
callstack.top - inR + i];
obj.pop(mw,args == null ? Object.class : args[i]);
}
callstack.top -= inR;
} //}}}
//{{{ generateReturn() method
public void generateReturn(CodeVisitor mw, int outD, int outR)
throws Exception
{
if(outD == 0 && outR == 0)
{
// do nothing
}
else if(outD == 1 && outR == 0)
{
push(datastack,mw,Object.class);
}
else
{
// transfer from data stack to JVM locals
// allocate the appropriate number of locals
if(outD != 0)
{
produce(datastack,outD);
// store the datastack instance somewhere
mw.visitVarInsn(ALOAD,0);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter",
"datastack",
"Lfactor/FactorArray;");
int datastackLocal = allocate();
mw.visitVarInsn(ASTORE,datastackLocal);
// put all elements from the real datastack
// into locals
for(int i = 0; i < outD; i++)
{
mw.visitVarInsn(ALOAD,datastackLocal);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArray",
"pop",
"()Ljava/lang/Object;");
Result destination = (Result)
datastack.stack[
datastack.top - i - 1];
destination.push(mw,Object.class);
}
}
if(outR != 0)
{
produce(callstack,outR);
mw.visitVarInsn(ALOAD,0);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter",
"callstack",
"Lfactor/FactorArray;");
int callstackLocal = allocate();
mw.visitVarInsn(ASTORE,callstackLocal);
// put all elements from the real callstack
// into locals
for(int i = 0; i < outR; i++)
{
mw.visitVarInsn(ALOAD,callstackLocal);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArray",
"pop",
"()Ljava/lang/Object;");
Result destination = (Result)
callstack.stack[
callstack.top - i - 1];
destination.push(mw,Object.class);
}
}
}
} //}}}
//{{{ generateFields() method
public void generateFields(ClassWriter cw)
throws Exception
{
for(int i = 0; i < literalCount; i++)
{
cw.visitField(ACC_PRIVATE | ACC_STATIC,"literal_" + i,
"Ljava/lang/Object;",null,null);
}
CodeVisitor mw = cw.visitMethod(ACC_PRIVATE | ACC_STATIC,
"setFields","(Lfactor/FactorInterpreter;)V",null,null);
Iterator entries = literals.entrySet().iterator();
while(entries.hasNext())
{
Map.Entry entry = (Map.Entry)entries.next();
Object literal = entry.getKey();
int index = ((Integer)entry.getValue()).intValue();
generateParse(mw,literal,0);
mw.visitFieldInsn(PUTSTATIC,
className,
"literal_" + index,
"Ljava/lang/Object;");
}
mw.visitInsn(RETURN);
mw.visitMaxs(0,0);
} //}}}
//{{{ generateParse() method
public void generateParse(CodeVisitor mw, Object obj, int interpLocal)
{
mw.visitLdcInsn(FactorReader.getVocabularyDeclaration(obj)
+ FactorReader.unparseObject(obj));
mw.visitVarInsn(ALOAD,interpLocal);
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorReader",
"parseObject",
"(Ljava/lang/String;Lfactor/FactorInterpreter;)"
+ "Ljava/lang/Object;");
} //}}}
//{{{ getStackEffectOrNull() method
public StackEffect getStackEffectOrNull(FactorWordDefinition def)
{
try
{
return def.getStackEffect(interp);
}
catch(Exception e)
{
//System.err.println("WARNING: " + e);
//System.err.println(def);
return null;
}
} //}}}
}

View File

@ -1,45 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
public class FactorCompilerException extends FactorRuntimeException
{
public FactorCompilerException(String str)
{
super(str);
}
public FactorCompilerException(String str, Throwable t)
{
super(str,t);
}
}

View File

@ -1,332 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.math.BigInteger;
import java.util.*;
import org.objectweb.asm.*;
public abstract class FlowObject
implements Constants, FactorExternalizable, PublicCloneable
{
protected FactorCompiler compiler;
protected RecursiveForm word;
protected Class expectedType;
//{{{ FlowObject constructor
FlowObject(FactorCompiler compiler,
RecursiveForm word)
{
this.compiler = compiler;
this.word = word;
expectedType = Object.class;
} //}}}
//{{{ push() method
protected void push(CodeVisitor mw)
throws Exception
{
throw new FactorCompilerException("Cannot push: " + this);
} //}}}
//{{{ push() method
public void push(CodeVisitor mw, Class type)
throws Exception
{
if(type == null)
throw new NullPointerException();
expectedType = (type.isPrimitive()
? FactorJava.getBoxingType(type)
: type);
if(mw != null)
{
generateToConversion(mw,type);
push(mw);
}
} //}}}
protected abstract void pop(CodeVisitor mw);
//{{{ pop() method
public void pop(CodeVisitor mw, Class type)
throws Exception
{
if(mw != null)
pop(mw);
Class actualType;
if(type.isPrimitive())
actualType = FactorJava.getBoxingType(type);
else
actualType = type;
// if we're looking for a subclass the expected type,
// specialize the expected type.
if(expectedType.isAssignableFrom(actualType))
expectedType = actualType;
// if we're looking for a superclass, that is ok too,
// eg we can generate every flow object as a
// java.lang.Object instance
else if(actualType.isAssignableFrom(expectedType))
/* do nothing */;
// otherwise, type error!
else
{
/* System.err.println(new TypeInferenceException(
this,expectedType,actualType)); */
}
if(mw != null)
generateFromConversion(mw,type);
} //}}}
//{{{ getConversionMethodName() method
/**
* Returns method name for converting an object to the given type.
* Only for primitives.
*/
private static String getConversionMethodName(Class type)
{
if(type.isPrimitive())
{
String name = type.getName();
return "to"
+ Character.toUpperCase(name.charAt(0))
+ name.substring(1);
}
else
return null;
} //}}}
//{{{ generateFromConversion() method
/**
* Unbox value at top of the stack.
*/
private static void generateFromConversion(CodeVisitor mw, Class type)
throws Exception
{
if(type == Object.class)
return;
String methodName = null;
if(type == Number.class)
methodName = "toNumber";
if(type == BigInteger.class)
methodName = "toBigInteger";
else if(type == String.class)
methodName = "toString";
else if(type == CharSequence.class)
methodName = "toCharSequence";
else if(type.isPrimitive())
methodName = getConversionMethodName(type);
else if(type == Class.class)
methodName = "toClass";
else if(type == FactorNamespace.class)
methodName = "toNamespace";
else if(type.isArray())
{
Class comp = type.getComponentType();
if(comp.isPrimitive())
{
methodName = getConversionMethodName(comp)
+ "Array";
}
else
methodName = "toArray";
}
if(methodName == null)
{
mw.visitTypeInsn(CHECKCAST,
type.getName()
.replace('.','/'));
}
else
{
String signature;
if(type.isArray())
{
signature = "(Ljava/lang/Object;)"
+ "[Ljava/lang/Object;";
}
else
{
signature = "(Ljava/lang/Object;)"
+ FactorJava.javaClassToVMClass(type);
}
mw.visitMethodInsn(INVOKESTATIC,"factor/FactorJava",
methodName,signature);
/* if(type.isArray())
{
mw.visitTypeInsn(CHECKCAST,
type.getName()
.replace('.','/'));
} */
}
} //}}}
//{{{ generateToConversionPre() method
/**
* Avoid having to deal with category 1/2 computational type
* distinction.
*/
public static void generateToConversionPre(CodeVisitor mw, Class type)
throws Exception
{
if(type == boolean.class)
return;
Class boxingType = FactorJava.getBoxingType(type);
if(boxingType != null)
{
String boxingName = boxingType.getName()
.replace('.','/');
mw.visitTypeInsn(NEW,boxingName);
mw.visitInsn(DUP);
}
} //}}}
//{{{ generateToConversion() method
/**
* Box return value, if needed.
*/
private static void generateToConversion(CodeVisitor mw, Class type)
throws Exception
{
if(type == boolean.class)
{
// this case is handled specially
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorJava",
"fromBoolean",
"(Z)Ljava/lang/Object;");
}
else
{
Class boxingType = FactorJava.getBoxingType(type);
if(boxingType != null)
{
String boxingName = boxingType.getName()
.replace('.','/');
mw.visitMethodInsn(INVOKESPECIAL,boxingName,
"<init>",
"(" + FactorJava.javaClassToVMClass(
type) + ")V");
}
}
} //}}}
//{{{ munge() method
/**
* Munging transforms the flow object such that it is now stored in
* a local variable and hence can be mutated by compiled code, however
* its original compileCallTo() semantics remain (for example, if it is
* a quotation).
*/
FlowObject munge(int base, int index,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
return new Result(index + base,compiler,recursiveCheck.last(),
expectedType);
} //}}}
//{{{ usingLocal() method
boolean usingLocal(int local)
{
return false;
} //}}}
//{{{ getLiteral() method
Object getLiteral()
throws FactorCompilerException
{
throw new FactorCompilerException("Cannot compile unless literal on stack: " + this);
} //}}}
//{{{ getLocal() method
/**
* @return -1 if the result is not store in a local variable.
*/
public int getLocal()
{
return -1;
} //}}}
//{{{ compileCallTo() method
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public void compileCallTo(CodeVisitor mw, RecursiveState recursiveCheck)
throws Exception
{
throw new FactorCompilerException("Cannot compile call to non-literal quotation");
} //}}}
//{{{ getWord() method
/**
* Returns the word where this flow object originated from.
*/
public RecursiveForm getWord()
{
return word;
} //}}}
//{{{ getType() method
public Class getType()
{
return expectedType;
} //}}}
//{{{ toString() method
public String toString()
{
try
{
return FactorReader.unparseObject(getLiteral());
}
catch(Exception e)
{
throw new RuntimeException("Override toString() if your getLiteral() bombs!");
}
} //}}}
//{{{ clone() method
public Object clone()
{
// cannot be abstract, and cannot be left undefined!
throw new InternalError();
} //}}}
}

View File

@ -1,80 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
public class Literal extends FlowObject
{
private Object literal;
//{{{ Literal constructor
Literal(Object literal, FactorCompiler compiler,
RecursiveForm word)
{
super(compiler,word);
this.literal = literal;
expectedType = literal.getClass();
} //}}}
//{{{ pop() method
public void pop(CodeVisitor mw)
{
mw.visitFieldInsn(GETSTATIC,compiler.className,
compiler.literal(literal),
"Ljava/lang/Object;");
} //}}}
//{{{ getLiteral() method
Object getLiteral()
{
return literal;
} //}}}
//{{{ compileCallTo() method
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public void compileCallTo(CodeVisitor mw, RecursiveState recursiveCheck)
throws Exception
{
throw new FactorCompilerException("Not a quotation: " + literal);
} //}}}
//{{{ clone() method
public Object clone()
{
return new Literal(literal,compiler,word);
} //}}}
}

View File

@ -1,99 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
public class Null extends FlowObject
{
//{{{ Null constructor
Null(FactorCompiler compiler, RecursiveForm word)
{
super(compiler,word);
} //}}}
//{{{ pop() Method
public void pop(CodeVisitor mw)
{
mw.visitInsn(ACONST_NULL);
} //}}}
//{{{ munge() method
/**
* Munging transforms the flow object such that it is now stored in
* a local variable and hence can be mutated by compiled code, however
* its original compileCallTo() semantics remain (for example, if it is
* a quotation).
*/
FlowObject munge(int base, int index,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
return new CompiledListResult(index + base,null,
compiler,recursiveCheck);
} //}}}
//{{{ getLiteral() method
Object getLiteral()
{
return null;
} //}}}
//{{{ compileCallTo() method
/**
* Write code for evaluating this. Returns maximum JVM stack
* usage.
*/
public void compileCallTo(CodeVisitor mw, RecursiveState recursiveCheck)
throws Exception
{
} //}}}
//{{{ equals() method
public boolean equals(Object o)
{
if(o instanceof Null)
return true;
else if(o instanceof CompiledList)
return ((CompiledList)o).getLiteral() == null;
else
return false;
} //}}}
//{{{ clone() method
public Object clone()
{
return new Null(compiler,word);
} //}}}
}

View File

@ -1,129 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import org.objectweb.asm.Label;
public class RecursiveForm implements PublicCloneable
{
/**
* Word represented by this form.
*/
public final FactorWord word;
/**
* The effect on entry into this form.
* (?) only for immediates
*/
public StackEffect effect;
/**
* Base case of recursive form. This is left-composed with the
* effect above.
*/
public StackEffect baseCase;
/**
* Is the word being compiled right now?
*/
public boolean active;
/**
* Name of class to call to recurse.
*/
public String className;
/**
* Class loader containing this definition.
*/
public FactorClassLoader loader;
/**
* Name of method to call to recurse.
*/
public String method;
/**
* Are we compiling the last factor in the word right now?
*/
public boolean tail;
/**
* A label to jump to the beginning of the definition.
*/
public Label label = new Label();
/**
* See RecursiveState.lastCallable().
*/
public boolean callable = true;
/**
* The containing recursive form, lexically.
*/
public RecursiveForm next;
public RecursiveForm(FactorWord word, StackEffect effect,
String className, FactorClassLoader loader,
String method)
{
this.word = word;
this.effect = effect;
this.className = className;
this.loader = loader;
this.method = method;
}
public RecursiveForm(RecursiveForm form)
{
this.word = form.word;
this.effect = form.effect;
this.baseCase = form.baseCase;
this.effect = form.effect;
this.className = form.className;
this.loader = form.loader;
this.method = form.method;
}
public String toString()
{
return word.toString() + ",base=" + baseCase
+ ",effect=" + effect
+ (active?",active":"")
+ (tail?",tail":"")
+ "; " + className + "." + method + "()";
}
public Object clone()
{
return new RecursiveForm(this);
}
}

View File

@ -1,148 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
public class RecursiveState implements PublicCloneable
{
private Cons words;
//{{{ RecursiveState constructor
public RecursiveState()
{
} //}}}
//{{{ RecursiveState constructor
public RecursiveState(RecursiveState clone)
{
if(clone.words != null)
words = clone.words;
} //}}}
//{{{ add() method
public void add(FactorWord word, StackEffect effect,
String className, FactorClassLoader loader, String method)
{
add(word,effect,className,loader,method,
words == null ? null : last());
} //}}}
//{{{ add() method
public void add(FactorWord word, StackEffect effect,
String className, FactorClassLoader loader, String method,
RecursiveForm next)
{
if(get(word) != null)
{
throw new RuntimeException("Calling add() twice on " + word);
}
RecursiveForm newForm = new RecursiveForm(
word,effect,className,loader,method);
words = new Cons(newForm,words);
newForm.next = next;
} //}}}
//{{{ remove() method
public void remove(FactorWord word)
{
//System.err.println(this + ": removing " + word);
if(last().word != word)
throw new RuntimeException("Expected " + word + ", found " + last().word);
words = words.next();
} //}}}
//{{{ get() method
public RecursiveForm get(FactorWord word)
{
if(words != null)
{
RecursiveForm iter = last();
while(iter != null)
{
if(iter.word == word)
return iter;
iter = iter.next;
}
}
return null;
} //}}}
//{{{ last() method
public RecursiveForm last()
{
return (RecursiveForm)words.car;
} //}}}
//{{{ lastCallable() method
public RecursiveForm lastCallable()
{
RecursiveForm word = (RecursiveForm)words.car;
while(word != null)
{
if(word.callable)
return word;
word = word.next;
}
return null;
} //}}}
//{{{ allTails() method
/**
* Returns if all forms from the given form upward are at their tail,
* so that we can do a direct GOTO to the given form to recurse on it.
*/
public boolean allTails(RecursiveForm form)
{
Cons iter = words;
for(;;)
{
if(!((RecursiveForm)iter.car).tail)
return false;
if(iter.car == form)
return true;
iter = iter.next();
}
} //}}}
//{{{ toString() method
public String toString()
{
return FactorReader.unparseObject(words);
} //}}}
//{{{ clone() method
public Object clone()
{
return new RecursiveState(this);
} //}}}
}

View File

@ -1,101 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.util.*;
import org.objectweb.asm.*;
public class Result extends FlowObject
{
private int local;
private boolean input;
public Result(int local, FactorCompiler compiler,
RecursiveForm word, Class type)
{
this(local,compiler,word,type,false);
}
/**
* @param input An input result contains a parameter passed to a
* compiled word's core() method.
*/
public Result(int local, FactorCompiler compiler,
RecursiveForm word, Class type,
boolean input)
{
super(compiler,word);
this.local = local;
if(type == null)
throw new NullPointerException();
this.expectedType = (type.isPrimitive()
? FactorJava.getBoxingType(type)
: type);
this.input = input;
}
public void push(CodeVisitor mw)
throws Exception
{
mw.visitVarInsn(ASTORE,local);
}
public void pop(CodeVisitor mw)
{
mw.visitVarInsn(ALOAD,local);
}
public int getLocal()
{
return local;
}
boolean usingLocal(int local)
{
return (this.local == local);
}
public boolean isInput()
{
return input;
}
public String toString()
{
return expectedType.getName() + "#" + local;
}
//{{{ clone() method
public Object clone()
{
return new Result(local,compiler,word,expectedType);
} //}}}
}

View File

@ -1,194 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
import java.util.*;
public class StackEffect implements PublicCloneable, FactorExternalizable
{
public int inD;
public Class[] inDtypes;
public int outD;
public Class[] outDtypes;
public int inR;
public Class[] inRtypes;
public int outR;
public Class[] outRtypes;
//{{{ StackEffect constructor
public StackEffect() {}
//}}}
//{{{ StackEffect constructor
public StackEffect(int inD, int outD, int inR, int outR)
{
this.inD = inD;
this.outD = outD;
this.inR = inR;
this.outR = outR;
} //}}}
//{{{ StackEffect constructor
public StackEffect(int inD, Class[] inDtypes,
int outD, Class[] outDtypes,
int inR, Class[] inRtypes,
int outR, Class[] outRtypes)
{
this.inD = inD;
this.inDtypes = inDtypes;
this.outD = outD;
this.outDtypes = outDtypes;
this.inR = inR;
this.inRtypes = inRtypes;
this.outR = outR;
this.outRtypes = outRtypes;
} //}}}
//{{{ compose() method
public static StackEffect compose(StackEffect first,
StackEffect second)
{
if(first == null || second == null)
return null;
int inD = first.inD + Math.max(0,second.inD - first.outD);
int outD = second.outD + Math.max(0,first.outD - second.inD);
int inR = first.inR + Math.max(0,second.inR - first.outR);
int outR = second.outR + Math.max(0,first.outR - second.inR);
return new StackEffect(inD,outD,inR,outR);
} //}}}
//{{{ decompose() method
/**
* Returns a stack effect E such that compose(first,E) == second.
*/
public static StackEffect decompose(StackEffect first,
StackEffect second)
{
if(first == null)
throw new NullPointerException("first == null");
if(second == null)
throw new NullPointerException("second == null");
if(second.inD < first.inD || second.inR < first.inR)
throw new IllegalArgumentException();
return new StackEffect(
first.outD + second.inD - first.inD,
second.outD,
first.outR + second.inR - first.inR,
second.outR);
} //}}}
//{{{ getCorePrototype() method
public String getCorePrototype()
{
StringBuffer signatureBuf = new StringBuffer(
"(Lfactor/FactorInterpreter;");
for(int i = 0; i < inD + inR; i++)
signatureBuf.append("Ljava/lang/Object;");
if(outD + outR != 1)
signatureBuf.append(")V");
else
signatureBuf.append(")Ljava/lang/Object;");
return signatureBuf.toString();
} //}}}
//{{{ equals() method
public boolean equals(Object o)
{
if(!(o instanceof StackEffect))
return false;
StackEffect effect = (StackEffect)o;
return effect.inD == inD
&& effect.outD == outD
&& effect.inR == inR
&& effect.outR == outR;
} //}}}
//{{{ hashCode() method
public int hashCode()
{
return inD + inR + outD + outR;
} //}}}
//{{{ typespec() method
private String typespec(int index, Class[] types)
{
if(types != null)
return types[index].getName();
else
return "X";
} //}}}
//{{{ toString() method
public String toString()
{
StringBuffer buf = new StringBuffer("( ");
for(int i = 0; i < inD; i++)
{
buf.append(typespec(i,inDtypes));
buf.append(' ');
}
for(int i = 0; i < inR; i++)
{
buf.append("r:");
buf.append(typespec(i,inRtypes));
buf.append(' ');
}
buf.append("--");
for(int i = 0; i < outD; i++)
{
buf.append(' ');
buf.append(typespec(i,outDtypes));
}
for(int i = 0; i < outR; i++)
{
buf.append(" r:");
buf.append(typespec(i,outRtypes));
}
buf.append(" )");
return buf.toString();
} //}}}
//{{{ clone() method
public Object clone()
{
return new StackEffect(inD,inDtypes,
outD,outDtypes,
inR,inRtypes,
outR,outRtypes);
} //}}}
}

View File

@ -1,42 +0,0 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package factor.compiler;
import factor.*;
public class TypeInferenceException extends FactorCompilerException
{
public TypeInferenceException(Object obj, Class expected, Class got)
{
super(obj + "\n"
+ "Expected: " + expected + "\n"
+ "Got: " + got);
}
}

View File

@ -56,8 +56,7 @@ public class Ine extends FactorParsingDefinition
reader.append(w.vocabulary);
reader.append(w.name);
reader.append(new FactorCompoundDefinition(
w,state.first,interp));
reader.append(new FactorCompoundDefinition(w,state.first));
reader.append(reader.intern("define",false));
}
}

View File

@ -71,8 +71,7 @@ public class Shuffle extends FactorParsingDefinition
reader.append(newWord.vocabulary);
reader.append(newWord.name);
reader.append(new FactorShuffleDefinition(
newWord,first,interp));
reader.append(new FactorShuffleDefinition(newWord,first));
reader.append(reader.intern("define",false));
}
}

View File

@ -29,11 +29,9 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
public class Call extends FactorPrimitiveDefinition
{
@ -52,27 +50,4 @@ public class Call extends FactorPrimitiveDefinition
{
interp.call((Cons)interp.datastack.pop());
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
/**
* Compile a call to this word. Returns maximum JVM stack use.
*/
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,Cons.class);
FlowObject quot = (FlowObject)compiler.datastack.pop();
quot.compileCallTo(mw,recursiveCheck);
} //}}}
}

View File

@ -29,9 +29,7 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import org.objectweb.asm.*;
public class Coerce extends FactorPrimitiveDefinition
{
@ -54,29 +52,4 @@ public class Coerce extends FactorPrimitiveDefinition
datastack.push(FactorJava.convertToJavaType(
datastack.pop(),type));
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,Class.class);
Class type = FactorJava.toClass(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,type);
else
FlowObject.generateToConversionPre(mw,type);
compiler.pop(compiler.datastack,mw,type);
compiler.push(compiler.datastack,mw,type);
} //}}}
}

View File

@ -29,7 +29,6 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
public class Define extends FactorPrimitiveDefinition
@ -66,16 +65,4 @@ public class Define extends FactorPrimitiveDefinition
word.define(definition);
interp.last = word;
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compiler.ensure(compiler.datastack,FactorWordDefinition.class);
compiler.pop(compiler.datastack,null,FactorWordDefinition.class);
compiler.ensure(compiler.datastack,String.class);
compiler.pop(compiler.datastack,null,String.class);
compiler.ensure(compiler.datastack,String.class);
compiler.pop(compiler.datastack,null,String.class);
} //}}}
}

View File

@ -29,7 +29,6 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;

View File

@ -29,9 +29,7 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import org.objectweb.asm.*;
public class Ifte extends FactorPrimitiveDefinition
{
@ -58,134 +56,4 @@ public class Ifte extends FactorPrimitiveDefinition
else
interp.call(f);
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compiler.ensure(compiler.datastack,Cons.class);
boolean fPossiblyRecursive = false;
FlowObject f = (FlowObject)compiler.datastack.pop();
compiler.ensure(compiler.datastack,Cons.class);
boolean tPossiblyRecursive = false;
FlowObject t = (FlowObject)compiler.datastack.pop();
compiler.ensure(compiler.datastack,Object.class);
FlowObject cond = (FlowObject)compiler.datastack.pop();
CompilerState savedState = new CompilerState(compiler);
try
{
t.compileCallTo(null,recursiveCheck);
}
catch(Exception e)
{
tPossiblyRecursive = true;
}
CompilerState tState = new CompilerState(compiler);
savedState.restore(compiler);
try
{
f.compileCallTo(null,recursiveCheck);
}
catch(Exception e)
{
fPossiblyRecursive = true;
}
CompilerState fState = new CompilerState(compiler);
if(!fPossiblyRecursive && tPossiblyRecursive)
{
RecursiveForm rec = t.getWord();
rec.baseCase = fState.effect;
savedState.restore(compiler);
t.compileCallTo(null,recursiveCheck);
tState = new CompilerState(compiler);
}
else if(fPossiblyRecursive && !tPossiblyRecursive)
{
RecursiveForm rec = f.getWord();
rec.baseCase = tState.effect;
savedState.restore(compiler);
f.compileCallTo(null,recursiveCheck);
fState = new CompilerState(compiler);
}
else if(fPossiblyRecursive && tPossiblyRecursive)
throw new FactorCompilerException("Indeterminate ifte effect\ntrue branch: " + t + "\nfalse branch: " + f);
CompilerState.unifyStates(compiler,recursiveCheck,t,f,tState,fState);
} //}}}
//{{{ compileNonRecursiveImmediate() method
/**
* Non-recursive immediate words are inlined.
*/
protected void compileNonRecursiveImmediate(CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck,
StackEffect immediateEffect) throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,Cons.class);
FlowObject f = (FlowObject)compiler.datastack.pop();
if(mw == null)
compiler.ensure(compiler.datastack,Cons.class);
FlowObject t = (FlowObject)compiler.datastack.pop();
if(mw == null)
compiler.ensure(compiler.datastack,Object.class);
FlowObject cond = (FlowObject)compiler.datastack.pop();
// if null jump to F
// T
// jump END
// F: F
// END: ...
Label fl = new Label();
Label endl = new Label();
cond.pop(mw,Object.class);
mw.visitJumpInsn(IFNULL,fl);
FactorArray datastackCopy = (FactorArray)
compiler.datastack.clone();
FactorArray callstackCopy = (FactorArray)
compiler.callstack.clone();
t.compileCallTo(mw,recursiveCheck);
compiler.normalizeStacks(mw);
compiler.datastack = datastackCopy;
compiler.callstack = callstackCopy;
mw.visitJumpInsn(GOTO,endl);
mw.visitLabel(fl);
f.compileCallTo(mw,recursiveCheck);
compiler.normalizeStacks(mw);
mw.visitLabel(endl);
} //}}}
//{{{ compileRecursiveImmediate() method
/**
* Recursive immediate words are compiled to an auxiliary method
* inside the compiled class definition.
*
* This must be done so that recursion has something to jump to.
*/
protected void compileRecursiveImmediate(CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck,
StackEffect immediateEffect) throws Exception
{
throw new FactorCompilerException("ifte is not recursive");
} //}}}
}

View File

@ -29,10 +29,8 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;
import org.objectweb.asm.*;
public class InterpreterGet extends FactorPrimitiveDefinition
{
@ -52,23 +50,4 @@ public class InterpreterGet extends FactorPrimitiveDefinition
{
interp.datastack.push(interp);
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw != null)
mw.visitVarInsn(ALOAD,0);
compiler.push(compiler.datastack,mw,FactorInterpreter.class);
} //}}}
}

View File

@ -29,11 +29,9 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
public class JInvoke extends FactorPrimitiveDefinition
{
@ -112,70 +110,4 @@ public class JInvoke extends FactorPrimitiveDefinition
throw new FactorStackException(_args.length);
}
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,String.class);
String name = FactorJava.toString(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,Class.class);
Class clazz = FactorJava.toClass(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,Cons.class);
Cons args = (Cons)compiler.popLiteral();
Class[] _args = FactorJava.classNameToClassList(args);
Method method = clazz.getMethod(name,_args);
checkStatic(method);
Class returnType = method.getReturnType();
if(mw != null)
FlowObject.generateToConversionPre(mw,returnType);
if(!staticMethod)
{
if(mw == null)
compiler.ensure(compiler.datastack,clazz);
compiler.pop(compiler.datastack,mw,clazz);
}
if(mw == null)
compiler.ensure(compiler.datastack,_args);
compiler.generateArgs(mw,_args.length,0,_args);
if(mw != null)
{
int opcode;
if(staticMethod)
opcode = INVOKESTATIC;
else if(clazz.isInterface())
opcode = INVOKEINTERFACE;
else
opcode = INVOKEVIRTUAL;
mw.visitMethodInsn(opcode,
clazz.getName().replace('.','/'),
name,
FactorJava.javaSignatureToVMSignature(
_args,returnType));
}
if(returnType != Void.TYPE)
compiler.push(compiler.datastack,mw,returnType);
} //}}}
}

View File

@ -29,11 +29,9 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
public class JNew extends FactorPrimitiveDefinition
{
@ -66,51 +64,4 @@ public class JNew extends FactorPrimitiveDefinition
datastack.push(constructor.newInstance(params));
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,Class.class);
Class clazz = FactorJava.toClass(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,Cons.class);
Cons args = (Cons)compiler.popLiteral();
Class[] _args = FactorJava.classNameToClassList(args);
Constructor constructor = clazz.getConstructor(_args);
if(mw != null)
{
FlowObject.generateToConversionPre(mw,clazz);
mw.visitTypeInsn(NEW,clazz.getName().replace('.','/'));
mw.visitInsn(DUP);
}
if(mw == null)
compiler.ensure(compiler.datastack,_args);
compiler.generateArgs(mw,_args.length,0,_args);
if(mw != null)
{
mw.visitMethodInsn(INVOKESPECIAL,
clazz.getName().replace('.','/'),
"<init>",
FactorJava.javaSignatureToVMSignature(
_args,Void.TYPE));
}
compiler.push(compiler.datastack,mw,clazz);
} //}}}
}

View File

@ -29,11 +29,9 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
public class JVarGet extends FactorPrimitiveDefinition
{
@ -61,43 +59,4 @@ public class JVarGet extends FactorPrimitiveDefinition
FactorJava.convertFromJavaType(
field.get(obj)));
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,String.class);
String fieldName = FactorJava.toString(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,Class.class);
Class clazz = FactorJava.toClass(compiler.popLiteral());
Field field = clazz.getField(fieldName);
if(mw != null)
FlowObject.generateToConversionPre(mw,field.getType());
if(mw == null)
compiler.ensure(compiler.datastack,clazz);
compiler.pop(compiler.datastack,mw,clazz);
if(mw != null)
{
mw.visitFieldInsn(GETFIELD,
clazz.getName().replace('.','/'),
fieldName,
FactorJava.javaClassToVMClass(field.getType()));
}
compiler.push(compiler.datastack,mw,field.getType());
} //}}}
}

View File

@ -29,11 +29,9 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
public class JVarGetStatic extends FactorPrimitiveDefinition
{
@ -59,38 +57,4 @@ public class JVarGetStatic extends FactorPrimitiveDefinition
FactorJava.convertFromJavaType(
field.get(null)));
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,String.class);
String fieldName = FactorJava.toString(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,Class.class);
Class clazz = FactorJava.toClass(compiler.popLiteral());
Field field = clazz.getField(fieldName);
if(mw != null)
{
FlowObject.generateToConversionPre(mw,field.getType());
mw.visitFieldInsn(GETSTATIC,
clazz.getName().replace('.','/'),
fieldName,
FactorJava.javaClassToVMClass(field.getType()));
}
compiler.push(compiler.datastack,mw,field.getType());
} //}}}
}

View File

@ -29,11 +29,9 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
public class JVarSet extends FactorPrimitiveDefinition
{
@ -61,41 +59,4 @@ public class JVarSet extends FactorPrimitiveDefinition
field.getType());
field.set(obj,value);
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,String.class);
String fieldName = FactorJava.toString(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,Class.class);
Class clazz = FactorJava.toClass(compiler.popLiteral());
Field field = clazz.getField(fieldName);
if(mw == null)
compiler.ensure(compiler.datastack,clazz);
compiler.pop(compiler.datastack,mw,clazz);
if(mw == null)
compiler.ensure(compiler.datastack,field.getType());
compiler.pop(compiler.datastack,mw,field.getType());
if(mw != null)
{
mw.visitFieldInsn(PUTFIELD,
clazz.getName().replace('.','/'),
fieldName,
FactorJava.javaClassToVMClass(field.getType()));
}
} //}}}
}

View File

@ -29,11 +29,9 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
import org.objectweb.asm.*;
public class JVarSetStatic extends FactorPrimitiveDefinition
{
@ -59,38 +57,4 @@ public class JVarSetStatic extends FactorPrimitiveDefinition
field.getType());
field.set(null,value);
} //}}}
//{{{ getStackEffect() method
public void getStackEffect(RecursiveState recursiveCheck,
FactorCompiler compiler) throws Exception
{
compileImmediate(null,compiler,recursiveCheck);
} //}}}
//{{{ compileImmediate() method
public void compileImmediate(
CodeVisitor mw,
FactorCompiler compiler,
RecursiveState recursiveCheck)
throws Exception
{
if(mw == null)
compiler.ensure(compiler.datastack,String.class);
String fieldName = FactorJava.toString(compiler.popLiteral());
if(mw == null)
compiler.ensure(compiler.datastack,Class.class);
Class clazz = FactorJava.toClass(compiler.popLiteral());
Field field = clazz.getField(fieldName);
if(mw == null)
compiler.ensure(compiler.datastack,field.getType());
compiler.pop(compiler.datastack,mw,field.getType());
if(mw != null)
{
mw.visitFieldInsn(PUTSTATIC,
clazz.getName().replace('.','/'),
fieldName,
FactorJava.javaClassToVMClass(field.getType()));
}
} //}}}
}

View File

@ -29,7 +29,6 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;

View File

@ -29,7 +29,6 @@
package factor.primitives;
import factor.compiler.*;
import factor.*;
import java.util.Set;

View File

@ -1,213 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* A non standard class, field, method or code attribute.
*/
public abstract class Attribute {
/**
* The type of this attribute.
*/
public final String type;
/**
* The next attribute in this attribute list. May be <tt>null</tt>.
*/
public Attribute next;
/**
* Constructs a new empty attribute.
*
* @param type the type of the attribute.
*/
public Attribute (final String type) {
this.type = type;
}
/**
* Returns the labels corresponding to this attribute.
*
* @return the labels corresponding to this attribute, or <tt>null</tt> if
* this attribute is not a code attribute that contains labels.
*/
protected Label[] getLabels () {
return null;
}
/**
* Reads a {@link #type type} attribute. This method must return a <i>new</i>
* {@link Attribute} object, of type {@link #type type}, corresponding to the
* <tt>len</tt> bytes starting at the given offset, in the given class reader.
*
* @param cr the class that contains the attribute to be read.
* @param off index of the first byte of the attribute's content in {@link
* ClassReader#b cr.b}. The 6 attribute header bytes, containing the type
* and the length of the attribute, are not taken into account here.
* @param len the length of the attribute's content.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass readClass} or {@link
* ClassReader#readConst readConst}.
* @param codeOff index of the first byte of code's attribute content in
* {@link ClassReader#b cr.b}, or -1 if the attribute to be read is not a
* code attribute. The 6 attribute header bytes, containing the type and
* the length of the attribute, are not taken into account here.
* @param labels the labels of the method's code, or <tt>null</tt> if the
* attribute to be read is not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the given
* bytes.
*/
protected abstract Attribute read (
ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels);
/**
* Returns the byte array form of this attribute.
*
* @param cw the class to which this attribute must be added. This parameter
* can be used to add to the constant pool of this class the items that
* corresponds to this attribute.
* @param code the bytecode of the method corresponding to this code
* attribute, or <tt>null</tt> if this attribute is not a code
* attributes.
* @param len the length of the bytecode of the method corresponding to this
* code attribute, or <tt>null</tt> if this attribute is not a code
* attribute.
* @param maxStack the maximum stack size of the method corresponding to this
* code attribute, or -1 if this attribute is not a code attribute.
* @param maxLocals the maximum number of local variables of the method
* corresponding to this code attribute, or -1 if this attribute is not
* a code attribute.
* @return the byte array form of this attribute.
*/
protected abstract ByteVector write (
ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals);
/**
* Returns the length of the attribute list that begins with this attribute.
*
* @return the length of the attribute list that begins with this attribute.
*/
final int getCount () {
int count = 0;
Attribute attr = this;
while (attr != null) {
count += 1;
attr = attr.next;
}
return count;
}
/**
* Returns the size of all the attributes in this attribute list.
*
* @param cw the class writer to be used to convert the attributes into byte
* arrays, with the {@link #write write} method.
* @param code the bytecode of the method corresponding to these code
* attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param len the length of the bytecode of the method corresponding to these
* code attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param maxStack the maximum stack size of the method corresponding to these
* code attributes, or -1 if these attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method
* corresponding to these code attributes, or -1 if these attributes are
* not code attributes.
* @return the size of all the attributes in this attribute list. This size
* includes the size of the attribute headers.
*/
final int getSize (
final ClassWriter cw,
final byte[] code,
final int len,
final int maxStack,
final int maxLocals)
{
int size = 0;
Attribute attr = this;
while (attr != null) {
cw.newUTF8(attr.type);
size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
attr = attr.next;
}
return size;
}
/**
* Writes all the attributes of this attribute list in the given byte vector.
*
* @param cw the class writer to be used to convert the attributes into byte
* arrays, with the {@link #write write} method.
* @param code the bytecode of the method corresponding to these code
* attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param len the length of the bytecode of the method corresponding to these
* code attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param maxStack the maximum stack size of the method corresponding to these
* code attributes, or -1 if these attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method
* corresponding to these code attributes, or -1 if these attributes are
* not code attributes.
* @param out where the attributes must be written.
*/
final void put (
final ClassWriter cw,
final byte[] code,
final int len,
final int maxStack,
final int maxLocals,
final ByteVector out)
{
Attribute attr = this;
while (attr != null) {
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
out.putByteArray(b.data, 0, b.length);
attr = attr.next;
}
}
}

View File

@ -1,293 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* A dynamically extensible vector of bytes. This class is roughly equivalent to
* a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
*/
public class ByteVector {
/**
* The content of this vector.
*/
byte[] data;
/**
* Actual number of bytes in this vector.
*/
int length;
/**
* Constructs a new {@link ByteVector ByteVector} with a default initial size.
*/
public ByteVector () {
data = new byte[64];
}
/**
* Constructs a new {@link ByteVector ByteVector} with the given initial size.
*
* @param initialSize the initial size of the byte vector to be constructed.
*/
public ByteVector (final int initialSize) {
data = new byte[initialSize];
}
/**
* Puts a byte into this byte vector. The byte vector is automatically
* enlarged if necessary.
*
* @param b a byte.
* @return this byte vector.
*/
public ByteVector putByte (final int b) {
int length = this.length;
if (length + 1 > data.length) {
enlarge(1);
}
data[length++] = (byte)b;
this.length = length;
return this;
}
/**
* Puts two bytes into this byte vector. The byte vector is automatically
* enlarged if necessary.
*
* @param b1 a byte.
* @param b2 another byte.
* @return this byte vector.
*/
ByteVector put11 (final int b1, final int b2) {
int length = this.length;
if (length + 2 > data.length) {
enlarge(2);
}
byte[] data = this.data;
data[length++] = (byte)b1;
data[length++] = (byte)b2;
this.length = length;
return this;
}
/**
* Puts a short into this byte vector. The byte vector is automatically
* enlarged if necessary.
*
* @param s a short.
* @return this byte vector.
*/
public ByteVector putShort (final int s) {
int length = this.length;
if (length + 2 > data.length) {
enlarge(2);
}
byte[] data = this.data;
data[length++] = (byte)(s >>> 8);
data[length++] = (byte)s;
this.length = length;
return this;
}
/**
* Puts a byte and a short into this byte vector. The byte vector is
* automatically enlarged if necessary.
*
* @param b a byte.
* @param s a short.
* @return this byte vector.
*/
ByteVector put12 (final int b, final int s) {
int length = this.length;
if (length + 3 > data.length) {
enlarge(3);
}
byte[] data = this.data;
data[length++] = (byte)b;
data[length++] = (byte)(s >>> 8);
data[length++] = (byte)s;
this.length = length;
return this;
}
/**
* Puts an int into this byte vector. The byte vector is automatically
* enlarged if necessary.
*
* @param i an int.
* @return this byte vector.
*/
public ByteVector putInt (final int i) {
int length = this.length;
if (length + 4 > data.length) {
enlarge(4);
}
byte[] data = this.data;
data[length++] = (byte)(i >>> 24);
data[length++] = (byte)(i >>> 16);
data[length++] = (byte)(i >>> 8);
data[length++] = (byte)i;
this.length = length;
return this;
}
/**
* Puts a long into this byte vector. The byte vector is automatically
* enlarged if necessary.
*
* @param l a long.
* @return this byte vector.
*/
public ByteVector putLong (final long l) {
int length = this.length;
if (length + 8 > data.length) {
enlarge(8);
}
byte[] data = this.data;
int i = (int)(l >>> 32);
data[length++] = (byte)(i >>> 24);
data[length++] = (byte)(i >>> 16);
data[length++] = (byte)(i >>> 8);
data[length++] = (byte)i;
i = (int)l;
data[length++] = (byte)(i >>> 24);
data[length++] = (byte)(i >>> 16);
data[length++] = (byte)(i >>> 8);
data[length++] = (byte)i;
this.length = length;
return this;
}
/**
* Puts an UTF8 string into this byte vector. The byte vector is automatically
* enlarged if necessary.
*
* @param s a String.
* @return this byte vector.
*/
public ByteVector putUTF8 (final String s) {
int charLength = s.length();
int byteLength = 0;
for (int i = 0; i < charLength; ++i) {
char c = s.charAt(i);
if (c >= '\001' && c <= '\177') {
byteLength++;
} else if (c > '\u07FF') {
byteLength += 3;
} else {
byteLength += 2;
}
}
if (byteLength > 65535) {
throw new IllegalArgumentException();
}
int length = this.length;
if (length + 2 + byteLength > data.length) {
enlarge(2 + byteLength);
}
byte[] data = this.data;
data[length++] = (byte)(byteLength >>> 8);
data[length++] = (byte)(byteLength);
for (int i = 0; i < charLength; ++i) {
char c = s.charAt(i);
if (c >= '\001' && c <= '\177') {
data[length++] = (byte)c;
} else if (c > '\u07FF') {
data[length++] = (byte)(0xE0 | c >> 12 & 0xF);
data[length++] = (byte)(0x80 | c >> 6 & 0x3F);
data[length++] = (byte)(0x80 | c & 0x3F);
} else {
data[length++] = (byte)(0xC0 | c >> 6 & 0x1F);
data[length++] = (byte)(0x80 | c & 0x3F);
}
}
this.length = length;
return this;
}
/**
* Puts an array of bytes into this byte vector. The byte vector is
* automatically enlarged if necessary.
*
* @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt> null
* bytes into this byte vector.
* @param off index of the fist byte of b that must be copied.
* @param len number of bytes of b that must be copied.
* @return this byte vector.
*/
public ByteVector putByteArray (
final byte[] b,
final int off,
final int len)
{
if (length + len > data.length) {
enlarge(len);
}
if (b != null) {
System.arraycopy(b, off, data, length, len);
}
length += len;
return this;
}
/**
* Enlarge this byte vector so that it can receive n more bytes.
*
* @param size number of additional bytes that this byte vector should be
* able to receive.
*/
private void enlarge (final int size) {
int length1 = 2 * data.length;
int length2 = length + size;
byte[] newData = new byte[length1 > length2 ? length1 : length2];
System.arraycopy(data, 0, newData, 0, length);
data = newData;
}
}

View File

@ -1,109 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* An empty {@link ClassVisitor ClassVisitor} that delegates to another {@link
* ClassVisitor ClassVisitor}. This class can be used as a super class to
* quickly implement usefull class adapter classes, just by overriding the
* necessary methods.
*/
public class ClassAdapter implements ClassVisitor {
/**
* The {@link ClassVisitor ClassVisitor} to which this adapter delegates
* calls.
*/
protected ClassVisitor cv;
/**
* Constructs a new {@link ClassAdapter ClassAdapter} object.
*
* @param cv the class visitor to which this adapter must delegate calls.
*/
public ClassAdapter (final ClassVisitor cv) {
this.cv = cv;
}
public void visit (
final int access,
final String name,
final String superName,
final String[] interfaces,
final String sourceFile)
{
cv.visit(access, name, superName, interfaces, sourceFile);
}
public void visitInnerClass (
final String name,
final String outerName,
final String innerName,
final int access)
{
cv.visitInnerClass(name, outerName, innerName, access);
}
public void visitField (
final int access,
final String name,
final String desc,
final Object value,
final Attribute attrs)
{
cv.visitField(access, name, desc, value, attrs);
}
public CodeVisitor visitMethod (
final int access,
final String name,
final String desc,
final String[] exceptions,
final Attribute attrs)
{
return new CodeAdapter(cv.visitMethod(access, name, desc, exceptions, attrs));
}
public void visitAttribute (final Attribute attr) {
cv.visitAttribute(attr);
}
public void visitEnd () {
cv.visitEnd();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,158 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* A visitor to visit a Java class. The methods of this interface must be called
* in the following order: <tt>visit</tt> (<tt>visitField</tt> |
* <tt>visitMethod</tt> | <tt>visitInnerClass</tt> | <tt>visitAttribute</tt>)*
* <tt>visitEnd</tt>.
*/
public interface ClassVisitor {
/**
* Visits the header of the class.
*
* @param access the class's access flags (see {@link Constants}). This
* parameter also indicates if the class is deprecated.
* @param name the internal name of the class (see {@link Type#getInternalName
* getInternalName}).
* @param superName the internal of name of the super class (see {@link
* Type#getInternalName getInternalName}). For interfaces, the super
* class is {@link Object}. May be <tt>null</tt>, but only for the {@link
* Object java.lang.Object} class.
* @param interfaces the internal names of the class's interfaces (see {@link
* Type#getInternalName getInternalName}). May be <tt>null</tt>.
* @param sourceFile the name of the source file from which this class was
* compiled. May be <tt>null</tt>.
*/
void visit (
int access,
String name,
String superName,
String[] interfaces,
String sourceFile);
/**
* Visits information about an inner class. This inner class is not
* necessarily a member of the class being visited.
*
* @param name the internal name of an inner class (see {@link
* Type#getInternalName getInternalName}).
* @param outerName the internal name of the class to which the inner class
* belongs (see {@link Type#getInternalName getInternalName}). May be
* <tt>null</tt>.
* @param innerName the (simple) name of the inner class inside its enclosing
* class. May be <tt>null</tt> for anonymous inner classes.
* @param access the access flags of the inner class as originally declared
* in the enclosing class.
*/
void visitInnerClass (
String name,
String outerName,
String innerName,
int access);
/**
* Visits a field of the class.
*
* @param access the field's access flags (see {@link Constants}). This
* parameter also indicates if the field is synthetic and/or deprecated.
* @param name the field's name.
* @param desc the field's descriptor (see {@link Type Type}).
* @param value the field's initial value. This parameter, which may be
* <tt>null</tt> if the field does not have an initial value, must be an
* {@link java.lang.Integer Integer}, a {@link java.lang.Float Float}, a
* {@link java.lang.Long Long}, a {@link java.lang.Double Double} or a
* {@link String String}. <i>This parameter is only used for static
* fields</i>. Its value is ignored for non static fields, which must be
* initialized through bytecode instructions in constructors or methods.
* @param attrs the non standard method attributes, linked together by their
* <tt>next</tt> field. May be <tt>null</tt>.
*/
void visitField (
int access,
String name,
String desc,
Object value,
Attribute attrs);
/**
* Visits a method of the class. This method <i>must</i> return a new
* {@link CodeVisitor CodeVisitor} instance (or <tt>null</tt>) each time it
* is called, i.e., it should not return a previously returned visitor.
*
* @param access the method's access flags (see {@link Constants}). This
* parameter also indicates if the method is synthetic and/or deprecated.
* @param name the method's name.
* @param desc the method's descriptor (see {@link Type Type}).
* @param exceptions the internal names of the method's exception
* classes (see {@link Type#getInternalName getInternalName}). May be
* <tt>null</tt>.
* @param attrs the non standard method attributes, linked together by their
* <tt>next</tt> field. May be <tt>null</tt>.
* @return an object to visit the byte code of the method, or <tt>null</tt> if
* this class visitor is not interested in visiting the code of this
* method.
*/
CodeVisitor visitMethod (
int access,
String name,
String desc,
String[] exceptions,
Attribute attrs);
/**
* Visits a non standard attribute of the class. This method must visit only
* the first attribute in the given attribute list.
*
* @param attr a non standard class attribute. Must not be <tt>null</tt>.
*/
void visitAttribute (Attribute attr);
/**
* Visits the end of the class. This method, which is the last one to be
* called, is used to inform the visitor that all the fields and methods of
* the class have been visited.
*/
void visitEnd ();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,163 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* An empty {@link CodeVisitor CodeVisitor} that delegates to another {@link
* CodeVisitor CodeVisitor}. This class can be used as a super class to quickly
* implement usefull code adapter classes, just by overriding the necessary
* methods.
*/
public class CodeAdapter implements CodeVisitor {
/**
* The {@link CodeVisitor CodeVisitor} to which this adapter delegates calls.
*/
protected CodeVisitor cv;
/**
* Constructs a new {@link CodeAdapter CodeAdapter} object.
*
* @param cv the code visitor to which this adapter must delegate calls.
*/
public CodeAdapter (final CodeVisitor cv) {
this.cv = cv;
}
public void visitInsn (final int opcode) {
cv.visitInsn(opcode);
}
public void visitIntInsn (final int opcode, final int operand) {
cv.visitIntInsn(opcode, operand);
}
public void visitVarInsn (final int opcode, final int var) {
cv.visitVarInsn(opcode, var);
}
public void visitTypeInsn (final int opcode, final String desc) {
cv.visitTypeInsn(opcode, desc);
}
public void visitFieldInsn (
final int opcode,
final String owner,
final String name,
final String desc)
{
cv.visitFieldInsn(opcode, owner, name, desc);
}
public void visitMethodInsn (
final int opcode,
final String owner,
final String name,
final String desc)
{
cv.visitMethodInsn(opcode, owner, name, desc);
}
public void visitJumpInsn (final int opcode, final Label label) {
cv.visitJumpInsn(opcode, label);
}
public void visitLabel (final Label label) {
cv.visitLabel(label);
}
public void visitLdcInsn (final Object cst) {
cv.visitLdcInsn(cst);
}
public void visitIincInsn (final int var, final int increment) {
cv.visitIincInsn(var, increment);
}
public void visitTableSwitchInsn (
final int min,
final int max,
final Label dflt,
final Label labels[])
{
cv.visitTableSwitchInsn(min, max, dflt, labels);
}
public void visitLookupSwitchInsn (
final Label dflt,
final int keys[],
final Label labels[])
{
cv.visitLookupSwitchInsn(dflt, keys, labels);
}
public void visitMultiANewArrayInsn (final String desc, final int dims) {
cv.visitMultiANewArrayInsn(desc, dims);
}
public void visitTryCatchBlock (
final Label start,
final Label end,
final Label handler,
final String type)
{
cv.visitTryCatchBlock(start, end, handler, type);
}
public void visitMaxs (final int maxStack, final int maxLocals) {
cv.visitMaxs(maxStack, maxLocals);
}
public void visitLocalVariable (
final String name,
final String desc,
final Label start,
final Label end,
final int index)
{
cv.visitLocalVariable(name, desc, start, end, index);
}
public void visitLineNumber (final int line, final Label start) {
cv.visitLineNumber(line, start);
}
public void visitAttribute (final Attribute attr) {
cv.visitAttribute(attr);
}
}

View File

@ -1,310 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* A visitor to visit the bytecode instructions of a Java method. The methods
* of this visitor must be called in the sequential order of the bytecode
* instructions of the visited code. The {@link #visitMaxs visitMaxs} method
* must be called after all the instructions have been visited. The {@link
* #visitTryCatchBlock visitTryCatchBlock}, {@link #visitLocalVariable
* visitLocalVariable} and {@link #visitLineNumber visitLineNumber} methods may
* be called in any order, at any time (provided the labels passed as arguments
* have already been visited with {@link #visitLabel visitLabel}).
*/
public interface CodeVisitor {
/**
* Visits a zero operand instruction.
*
* @param opcode the opcode of the instruction to be visited. This opcode is
* either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
* ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1,
* FCONST_2, DCONST_0, DCONST_1,
*
* IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
* IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
* SASTORE,
*
* POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP,
*
* IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL,
* DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG,
* FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR,
* LOR, IXOR, LXOR,
*
* I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C,
* I2S,
*
* LCMP, FCMPL, FCMPG, DCMPL, DCMPG,
*
* IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, RETURN,
*
* ARRAYLENGTH,
*
* ATHROW,
*
* MONITORENTER, or MONITOREXIT.
*/
void visitInsn (int opcode);
/**
* Visits an instruction with a single int operand.
*
* @param opcode the opcode of the instruction to be visited. This opcode is
* either BIPUSH, SIPUSH or NEWARRAY.
* @param operand the operand of the instruction to be visited.
*/
void visitIntInsn (int opcode, int operand);
/**
* Visits a local variable instruction. A local variable instruction is an
* instruction that loads or stores the value of a local variable.
*
* @param opcode the opcode of the local variable instruction to be visited.
* This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
* LSTORE, FSTORE, DSTORE, ASTORE or RET.
* @param var the operand of the instruction to be visited. This operand is
* the index of a local variable.
*/
void visitVarInsn (int opcode, int var);
/**
* Visits a type instruction. A type instruction is an instruction that
* takes a type descriptor as parameter.
*
* @param opcode the opcode of the type instruction to be visited. This opcode
* is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
* @param desc the operand of the instruction to be visited. This operand is
* must be a fully qualified class name in internal form, or the type
* descriptor of an array type (see {@link Type Type}).
*/
void visitTypeInsn (int opcode, String desc);
/**
* Visits a field instruction. A field instruction is an instruction that
* loads or stores the value of a field of an object.
*
* @param opcode the opcode of the type instruction to be visited. This opcode
* is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
* @param owner the internal name of the field's owner class (see {@link
* Type#getInternalName getInternalName}).
* @param name the field's name.
* @param desc the field's descriptor (see {@link Type Type}).
*/
void visitFieldInsn (int opcode, String owner, String name, String desc);
/**
* Visits a method instruction. A method instruction is an instruction that
* invokes a method.
*
* @param opcode the opcode of the type instruction to be visited. This opcode
* is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
* INVOKEINTERFACE.
* @param owner the internal name of the method's owner class (see {@link
* Type#getInternalName getInternalName}).
* @param name the method's name.
* @param desc the method's descriptor (see {@link Type Type}).
*/
void visitMethodInsn (int opcode, String owner, String name, String desc);
/**
* Visits a jump instruction. A jump instruction is an instruction that may
* jump to another instruction.
*
* @param opcode the opcode of the type instruction to be visited. This opcode
* is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE,
* IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE,
* GOTO, JSR, IFNULL or IFNONNULL.
* @param label the operand of the instruction to be visited. This operand is
* a label that designates the instruction to which the jump instruction
* may jump.
*/
void visitJumpInsn (int opcode, Label label);
/**
* Visits a label. A label designates the instruction that will be visited
* just after it.
*
* @param label a {@link Label Label} object.
*/
void visitLabel (Label label);
// -------------------------------------------------------------------------
// Special instructions
// -------------------------------------------------------------------------
/**
* Visits a LDC instruction.
*
* @param cst the constant to be loaded on the stack. This parameter must be
* a non null {@link java.lang.Integer Integer}, a {@link java.lang.Float
* Float}, a {@link java.lang.Long Long}, a {@link java.lang.Double
* Double} or a {@link String String}.
*/
void visitLdcInsn (Object cst);
/**
* Visits an IINC instruction.
*
* @param var index of the local variable to be incremented.
* @param increment amount to increment the local variable by.
*/
void visitIincInsn (int var, int increment);
/**
* Visits a TABLESWITCH instruction.
*
* @param min the minimum key value.
* @param max the maximum key value.
* @param dflt beginning of the default handler block.
* @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
* beginning of the handler block for the <tt>min + i</tt> key.
*/
void visitTableSwitchInsn (int min, int max, Label dflt, Label labels[]);
/**
* Visits a LOOKUPSWITCH instruction.
*
* @param dflt beginning of the default handler block.
* @param keys the values of the keys.
* @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
* beginning of the handler block for the <tt>keys[i]</tt> key.
*/
void visitLookupSwitchInsn (Label dflt, int keys[], Label labels[]);
/**
* Visits a MULTIANEWARRAY instruction.
*
* @param desc an array type descriptor (see {@link Type Type}).
* @param dims number of dimensions of the array to allocate.
*/
void visitMultiANewArrayInsn (String desc, int dims);
// -------------------------------------------------------------------------
// Exceptions table entries, max stack size and max locals
// -------------------------------------------------------------------------
/**
* Visits a try catch block.
*
* @param start beginning of the exception handler's scope (inclusive).
* @param end end of the exception handler's scope (exclusive).
* @param handler beginning of the exception handler's code.
* @param type internal name of the type of exceptions handled by the handler,
* or <tt>null</tt> to catch any exceptions (for "finally" blocks).
* @throws IllegalArgumentException if one of the labels has not already been
* visited by this visitor (by the {@link #visitLabel visitLabel}
* method).
*/
void visitTryCatchBlock (Label start, Label end, Label handler, String type);
/**
* Visits the maximum stack size and the maximum number of local variables of
* the method.
*
* @param maxStack maximum stack size of the method.
* @param maxLocals maximum number of local variables for the method.
*/
void visitMaxs (int maxStack, int maxLocals);
// -------------------------------------------------------------------------
// Debug information
// -------------------------------------------------------------------------
/**
* Visits a local variable declaration.
*
* @param name the name of a local variable.
* @param desc the type descriptor of this local variable.
* @param start the first instruction corresponding to the scope of this
* local variable (inclusive).
* @param end the last instruction corresponding to the scope of this
* local variable (exclusive).
* @param index the local variable's index.
* @throws IllegalArgumentException if one of the labels has not already been
* visited by this visitor (by the {@link #visitLabel visitLabel}
* method).
*/
void visitLocalVariable (
String name,
String desc,
Label start,
Label end,
int index);
/**
* Visits a line number declaration.
*
* @param line a line number. This number refers to the source file
* from which the class was compiled.
* @param start the first instruction corresponding to this line number.
* @throws IllegalArgumentException if <tt>start</tt> has not already been
* visited by this visitor (by the {@link #visitLabel visitLabel}
* method).
*/
void visitLineNumber (int line, Label start);
// -------------------------------------------------------------------------
// Non standard attributes
// -------------------------------------------------------------------------
/**
* Visits a non standard attribute of the code. This method must visit only
* the first attribute in the given attribute list.
*
* @param attr a non standard code attribute. Must not be <tt>null</tt>.
*/
void visitAttribute (Attribute attr);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,288 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* Defines the JVM opcodes, access flags and array type codes. This interface
* does not define all the JVM opcodes because some opcodes are automatically
* handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
* opcodes are therefore not defined in this interface. Likewise for LDC,
* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
* JSR_W.
*/
public interface Constants {
// access flags
int ACC_PUBLIC = 1;
int ACC_PRIVATE = 2;
int ACC_PROTECTED = 4;
int ACC_STATIC = 8;
int ACC_FINAL = 16;
int ACC_SYNCHRONIZED = 32;
int ACC_VOLATILE = 64; // fields
int ACC_BRIDGE = 64; // methods
int ACC_VARARGS = 128; // methods
int ACC_TRANSIENT = 128; // fields
int ACC_NATIVE = 256; // methods
int ACC_ENUM = 256; // classes and fields
// TODO find out what is the value for ACC_ANNOTATION constant
int ACC_INTERFACE = 512;
int ACC_ABSTRACT = 1024;
int ACC_STRICT = 2048;
int ACC_SUPER = 32;
int ACC_SYNTHETIC = 65536;
int ACC_DEPRECATED = 131072;
// types for NEWARRAY
int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
// opcodes // visit method (- = idem)
int NOP = 0; // visitInsn
int ACONST_NULL = 1; // -
int ICONST_M1 = 2; // -
int ICONST_0 = 3; // -
int ICONST_1 = 4; // -
int ICONST_2 = 5; // -
int ICONST_3 = 6; // -
int ICONST_4 = 7; // -
int ICONST_5 = 8; // -
int LCONST_0 = 9; // -
int LCONST_1 = 10; // -
int FCONST_0 = 11; // -
int FCONST_1 = 12; // -
int FCONST_2 = 13; // -
int DCONST_0 = 14; // -
int DCONST_1 = 15; // -
int BIPUSH = 16; // visitIntInsn
int SIPUSH = 17; // -
int LDC = 18; // visitLdcInsn
//int LDC_W = 19; // -
//int LDC2_W = 20; // -
int ILOAD = 21; // visitVarInsn
int LLOAD = 22; // -
int FLOAD = 23; // -
int DLOAD = 24; // -
int ALOAD = 25; // -
//int ILOAD_0 = 26; // -
//int ILOAD_1 = 27; // -
//int ILOAD_2 = 28; // -
//int ILOAD_3 = 29; // -
//int LLOAD_0 = 30; // -
//int LLOAD_1 = 31; // -
//int LLOAD_2 = 32; // -
//int LLOAD_3 = 33; // -
//int FLOAD_0 = 34; // -
//int FLOAD_1 = 35; // -
//int FLOAD_2 = 36; // -
//int FLOAD_3 = 37; // -
//int DLOAD_0 = 38; // -
//int DLOAD_1 = 39; // -
//int DLOAD_2 = 40; // -
//int DLOAD_3 = 41; // -
//int ALOAD_0 = 42; // -
//int ALOAD_1 = 43; // -
//int ALOAD_2 = 44; // -
//int ALOAD_3 = 45; // -
int IALOAD = 46; // visitInsn
int LALOAD = 47; // -
int FALOAD = 48; // -
int DALOAD = 49; // -
int AALOAD = 50; // -
int BALOAD = 51; // -
int CALOAD = 52; // -
int SALOAD = 53; // -
int ISTORE = 54; // visitVarInsn
int LSTORE = 55; // -
int FSTORE = 56; // -
int DSTORE = 57; // -
int ASTORE = 58; // -
//int ISTORE_0 = 59; // -
//int ISTORE_1 = 60; // -
//int ISTORE_2 = 61; // -
//int ISTORE_3 = 62; // -
//int LSTORE_0 = 63; // -
//int LSTORE_1 = 64; // -
//int LSTORE_2 = 65; // -
//int LSTORE_3 = 66; // -
//int FSTORE_0 = 67; // -
//int FSTORE_1 = 68; // -
//int FSTORE_2 = 69; // -
//int FSTORE_3 = 70; // -
//int DSTORE_0 = 71; // -
//int DSTORE_1 = 72; // -
//int DSTORE_2 = 73; // -
//int DSTORE_3 = 74; // -
//int ASTORE_0 = 75; // -
//int ASTORE_1 = 76; // -
//int ASTORE_2 = 77; // -
//int ASTORE_3 = 78; // -
int IASTORE = 79; // visitInsn
int LASTORE = 80; // -
int FASTORE = 81; // -
int DASTORE = 82; // -
int AASTORE = 83; // -
int BASTORE = 84; // -
int CASTORE = 85; // -
int SASTORE = 86; // -
int POP = 87; // -
int POP2 = 88; // -
int DUP = 89; // -
int DUP_X1 = 90; // -
int DUP_X2 = 91; // -
int DUP2 = 92; // -
int DUP2_X1 = 93; // -
int DUP2_X2 = 94; // -
int SWAP = 95; // -
int IADD = 96; // -
int LADD = 97; // -
int FADD = 98; // -
int DADD = 99; // -
int ISUB = 100; // -
int LSUB = 101; // -
int FSUB = 102; // -
int DSUB = 103; // -
int IMUL = 104; // -
int LMUL = 105; // -
int FMUL = 106; // -
int DMUL = 107; // -
int IDIV = 108; // -
int LDIV = 109; // -
int FDIV = 110; // -
int DDIV = 111; // -
int IREM = 112; // -
int LREM = 113; // -
int FREM = 114; // -
int DREM = 115; // -
int INEG = 116; // -
int LNEG = 117; // -
int FNEG = 118; // -
int DNEG = 119; // -
int ISHL = 120; // -
int LSHL = 121; // -
int ISHR = 122; // -
int LSHR = 123; // -
int IUSHR = 124; // -
int LUSHR = 125; // -
int IAND = 126; // -
int LAND = 127; // -
int IOR = 128; // -
int LOR = 129; // -
int IXOR = 130; // -
int LXOR = 131; // -
int IINC = 132; // visitIincInsn
int I2L = 133; // visitInsn
int I2F = 134; // -
int I2D = 135; // -
int L2I = 136; // -
int L2F = 137; // -
int L2D = 138; // -
int F2I = 139; // -
int F2L = 140; // -
int F2D = 141; // -
int D2I = 142; // -
int D2L = 143; // -
int D2F = 144; // -
int I2B = 145; // -
int I2C = 146; // -
int I2S = 147; // -
int LCMP = 148; // -
int FCMPL = 149; // -
int FCMPG = 150; // -
int DCMPL = 151; // -
int DCMPG = 152; // -
int IFEQ = 153; // visitJumpInsn
int IFNE = 154; // -
int IFLT = 155; // -
int IFGE = 156; // -
int IFGT = 157; // -
int IFLE = 158; // -
int IF_ICMPEQ = 159; // -
int IF_ICMPNE = 160; // -
int IF_ICMPLT = 161; // -
int IF_ICMPGE = 162; // -
int IF_ICMPGT = 163; // -
int IF_ICMPLE = 164; // -
int IF_ACMPEQ = 165; // -
int IF_ACMPNE = 166; // -
int GOTO = 167; // -
int JSR = 168; // -
int RET = 169; // visitVarInsn
int TABLESWITCH = 170; // visiTableSwitchInsn
int LOOKUPSWITCH = 171; // visitLookupSwitch
int IRETURN = 172; // visitInsn
int LRETURN = 173; // -
int FRETURN = 174; // -
int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -
int GETSTATIC = 178; // visitFieldInsn
int PUTSTATIC = 179; // -
int GETFIELD = 180; // -
int PUTFIELD = 181; // -
int INVOKEVIRTUAL = 182; // visitMethodInsn
int INVOKESPECIAL = 183; // -
int INVOKESTATIC = 184; // -
int INVOKEINTERFACE = 185; // -
//int UNUSED = 186; // NOT VISITED
int NEW = 187; // visitTypeInsn
int NEWARRAY = 188; // visitIntInsn
int ANEWARRAY = 189; // visitTypeInsn
int ARRAYLENGTH = 190; // visitInsn
int ATHROW = 191; // -
int CHECKCAST = 192; // visitTypeInsn
int INSTANCEOF = 193; // -
int MONITORENTER = 194; // visitInsn
int MONITOREXIT = 195; // -
//int WIDE = 196; // NOT VISITED
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
//int GOTO_W = 200; // -
//int JSR_W = 201; // -
}

View File

@ -1,70 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* An edge in the control flow graph of a method body. See {@link Label Label}.
*/
class Edge {
/**
* The (relative) stack size in the basic block from which this edge
* originates. This size is equal to the stack size at the "jump" instruction
* to which this edge corresponds, relatively to the stack size at the
* beginning of the originating basic block.
*/
int stackSize;
/**
* The successor block of the basic block from which this edge originates.
*/
Label successor;
/**
* The next edge in the list of successors of the originating basic block.
* See {@link Label#successors successors}.
*/
Edge next;
/**
* The next available edge in the pool. See {@link CodeWriter#pool pool}.
*/
Edge poolNext;
}

View File

@ -1,266 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* A constant pool item. Constant pool items can be created with the 'newXXX'
* methods in the {@link ClassWriter} class.
*/
final class Item {
/**
* Index of this item in the constant pool.
*/
short index;
/**
* Type of this constant pool item. A single class is used to represent all
* constant pool item types, in order to minimize the bytecode size of this
* package. The value of this field is one of the constants defined in the
* {@link ClassWriter ClassWriter} class.
*/
int type;
/**
* Value of this item, for a {@link ClassWriter#INT INT} item.
*/
int intVal;
/**
* Value of this item, for a {@link ClassWriter#LONG LONG} item.
*/
long longVal;
/**
* Value of this item, for a {@link ClassWriter#FLOAT FLOAT} item.
*/
float floatVal;
/**
* Value of this item, for a {@link ClassWriter#DOUBLE DOUBLE} item.
*/
double doubleVal;
/**
* First part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal1;
/**
* Second part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal2;
/**
* Third part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal3;
/**
* The hash code value of this constant pool item.
*/
int hashCode;
/**
* Link to another constant pool item, used for collision lists in the
* constant pool's hash table.
*/
Item next;
/**
* Constructs an uninitialized {@link Item Item} object.
*/
Item () {
}
/**
* Constructs a copy of the given item.
*
* @param index index of the item to be constructed.
* @param i the item that must be copied into the item to be constructed.
*/
Item (final short index, final Item i) {
this.index = index;
type = i.type;
intVal = i.intVal;
longVal = i.longVal;
floatVal = i.floatVal;
doubleVal = i.doubleVal;
strVal1 = i.strVal1;
strVal2 = i.strVal2;
strVal3 = i.strVal3;
hashCode = i.hashCode;
}
/**
* Sets this item to an {@link ClassWriter#INT INT} item.
*
* @param intVal the value of this item.
*/
void set (final int intVal) {
this.type = ClassWriter.INT;
this.intVal = intVal;
this.hashCode = 0x7FFFFFFF & (type + intVal);
}
/**
* Sets this item to a {@link ClassWriter#LONG LONG} item.
*
* @param longVal the value of this item.
*/
void set (final long longVal) {
this.type = ClassWriter.LONG;
this.longVal = longVal;
this.hashCode = 0x7FFFFFFF & (type + (int)longVal);
}
/**
* Sets this item to a {@link ClassWriter#FLOAT FLOAT} item.
*
* @param floatVal the value of this item.
*/
void set (final float floatVal) {
this.type = ClassWriter.FLOAT;
this.floatVal = floatVal;
this.hashCode = 0x7FFFFFFF & (type + (int)floatVal);
}
/**
* Sets this item to a {@link ClassWriter#DOUBLE DOUBLE} item.
*
* @param doubleVal the value of this item.
*/
void set (final double doubleVal) {
this.type = ClassWriter.DOUBLE;
this.doubleVal = doubleVal;
this.hashCode = 0x7FFFFFFF & (type + (int)doubleVal);
}
/**
* Sets this item to an item that do not hold a primitive value.
*
* @param type the type of this item.
* @param strVal1 first part of the value of this item.
* @param strVal2 second part of the value of this item.
* @param strVal3 third part of the value of this item.
*/
void set (
final int type,
final String strVal1,
final String strVal2,
final String strVal3)
{
this.type = type;
this.strVal1 = strVal1;
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
return;
case ClassWriter.NAME_TYPE:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()*strVal2.hashCode());
return;
//case ClassWriter.FIELD:
//case ClassWriter.METH:
//case ClassWriter.IMETH:
default:
hashCode = 0x7FFFFFFF & (type +
strVal1.hashCode()*strVal2.hashCode()*strVal3.hashCode());
}
}
/**
* Indicates if the given item is equal to this one.
*
* @param i the item to be compared to this one.
* @return <tt>true</tt> if the given item if equal to this one,
* <tt>false</tt> otherwise.
*/
boolean isEqualTo (final Item i) {
if (i.type == type) {
switch (type) {
case ClassWriter.INT:
return i.intVal == intVal;
case ClassWriter.LONG:
return i.longVal == longVal;
case ClassWriter.FLOAT:
return i.floatVal == floatVal;
case ClassWriter.DOUBLE:
return i.doubleVal == doubleVal;
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
return i.strVal1.equals(strVal1);
case ClassWriter.NAME_TYPE:
return i.strVal1.equals(strVal1) &&
i.strVal2.equals(strVal2);
//case ClassWriter.FIELD:
//case ClassWriter.METH:
//case ClassWriter.IMETH:
default:
return i.strVal1.equals(strVal1) &&
i.strVal2.equals(strVal2) &&
i.strVal3.equals(strVal3);
}
}
return false;
}
}

View File

@ -1,327 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
*/
package org.objectweb.asm;
/**
* A label represents a position in the bytecode of a method. Labels are used
* for jump, goto, and switch instructions, and for try catch blocks.
*/
public class Label {
/**
* The code writer to which this label belongs, or <tt>null</tt> if unknown.
*/
CodeWriter owner;
/**
* Indicates if the position of this label is known.
*/
boolean resolved;
/**
* The position of this label in the code, if known.
*/
int position;
/**
* If the label position has been updated, after instruction resizing.
*/
boolean resized;
/**
* Number of forward references to this label, times two.
*/
private int referenceCount;
/**
* Informations about forward references. Each forward reference is described
* by two consecutive integers in this array: the first one is the position
* of the first byte of the bytecode instruction that contains the forward
* reference, while the second is the position of the first byte of the
* forward reference itself. In fact the sign of the first integer indicates
* if this reference uses 2 or 4 bytes, and its absolute value gives the
* position of the bytecode instruction.
*/
private int[] srcAndRefPositions;
// --------------------------------------------------------------------------
// Fields for the control flow graph analysis algorithm (used to compute the
// maximum stack size). A control flow graph contains one node per "basic
// block", and one edge per "jump" from one basic block to another. Each node
// (i.e., each basic block) is represented by the Label object that
// corresponds to the first instruction of this basic block. Each node also
// stores the list of it successors in the graph, as a linked list of Edge
// objects.
// --------------------------------------------------------------------------
/**
* The stack size at the beginning of this basic block.
* This size is initially unknown. It is computed by the control flow
* analysis algorithm (see {@link CodeWriter#visitMaxs visitMaxs}).
*/
int beginStackSize;
/**
* The (relative) maximum stack size corresponding to this basic block. This
* size is relative to the stack size at the beginning of the basic block,
* i.e., the true maximum stack size is equal to {@link #beginStackSize
* beginStackSize} + {@link #maxStackSize maxStackSize}.
*/
int maxStackSize;
/**
* The successors of this node in the control flow graph. These successors
* are stored in a linked list of {@link Edge Edge} objects, linked to each
* other by their {@link Edge#next} field.
*/
Edge successors;
/**
* The next basic block in the basic block stack.
* See {@link CodeWriter#visitMaxs visitMaxs}.
*/
Label next;
/**
* <tt>true</tt> if this basic block has been pushed in the basic block stack.
* See {@link CodeWriter#visitMaxs visitMaxs}.
*/
boolean pushed;
// --------------------------------------------------------------------------
// Constructor
// --------------------------------------------------------------------------
/**
* Constructs a new label.
*/
public Label () {
}
// --------------------------------------------------------------------------
// Methods to compute offsets and to manage forward references
// --------------------------------------------------------------------------
/**
* Returns the offset corresponding to this label. This offset is computed
* from the start of the method's bytecode. <i>This method is intended for
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @return the offset corresponding to this label.
* @throws IllegalStateException if this label is not resolved yet.
*/
public int getOffset () {
if (!resolved) {
throw new IllegalStateException(
"Label offset position has not been resolved yet");
}
return position;
}
/**
* Puts a reference to this label in the bytecode of a method. If the position
* of the label is known, the offset is computed and written directly.
* Otherwise, a null offset is written and a new forward reference is declared
* for this label.
*
* @param owner the code writer that calls this method.
* @param out the bytecode of the method.
* @param source the position of first byte of the bytecode instruction that
* contains this label.
* @param wideOffset <tt>true</tt> if the reference must be stored in 4 bytes,
* or <tt>false</tt> if it must be stored with 2 bytes.
* @throws IllegalArgumentException if this label has not been created by the
* given code writer.
*/
void put (
final CodeWriter owner,
final ByteVector out,
final int source,
final boolean wideOffset)
{
if (CodeWriter.CHECK) {
if (this.owner == null) {
this.owner = owner;
} else if (this.owner != owner) {
throw new IllegalArgumentException();
}
}
if (resolved) {
if (wideOffset) {
out.putInt(position - source);
} else {
out.putShort(position - source);
}
} else {
if (wideOffset) {
addReference(-1 - source, out.length);
out.putInt(-1);
} else {
addReference(source, out.length);
out.putShort(-1);
}
}
}
/**
* Adds a forward reference to this label. This method must be called only for
* a true forward reference, i.e. only if this label is not resolved yet. For
* backward references, the offset of the reference can be, and must be,
* computed and stored directly.
*
* @param sourcePosition the position of the referencing instruction. This
* position will be used to compute the offset of this forward reference.
* @param referencePosition the position where the offset for this forward
* reference must be stored.
*/
private void addReference (
final int sourcePosition,
final int referencePosition)
{
if (srcAndRefPositions == null) {
srcAndRefPositions = new int[6];
}
if (referenceCount >= srcAndRefPositions.length) {
int[] a = new int[srcAndRefPositions.length + 6];
System.arraycopy(srcAndRefPositions, 0, a, 0, srcAndRefPositions.length);
srcAndRefPositions = a;
}
srcAndRefPositions[referenceCount++] = sourcePosition;
srcAndRefPositions[referenceCount++] = referencePosition;
}
/**
* Resolves all forward references to this label. This method must be called
* when this label is added to the bytecode of the method, i.e. when its
* position becomes known. This method fills in the blanks that where left in
* the bytecode by each forward reference previously added to this label.
*
* @param owner the code writer that calls this method.
* @param position the position of this label in the bytecode.
* @param data the bytecode of the method.
* @return <tt>true</tt> if a blank that was left for this label was to small
* to store the offset. In such a case the corresponding jump instruction
* is replaced with a pseudo instruction (using unused opcodes) using an
* unsigned two bytes offset. These pseudo instructions will need to be
* replaced with true instructions with wider offsets (4 bytes instead of
* 2). This is done in {@link CodeWriter#resizeInstructions}.
* @throws IllegalArgumentException if this label has already been resolved,
* or if it has not been created by the given code writer.
*/
boolean resolve (
final CodeWriter owner,
final int position,
final byte[] data)
{
if (CodeWriter.CHECK) {
if (this.owner == null) {
this.owner = owner;
}
if (resolved || this.owner != owner) {
throw new IllegalArgumentException();
}
}
boolean needUpdate = false;
this.resolved = true;
this.position = position;
int i = 0;
while (i < referenceCount) {
int source = srcAndRefPositions[i++];
int reference = srcAndRefPositions[i++];
int offset;
if (source >= 0) {
offset = position - source;
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
// changes the opcode of the jump instruction, in order to be able to
// find it later (see resizeInstructions in CodeWriter). These
// temporary opcodes are similar to jump instruction opcodes, except
// that the 2 bytes offset is unsigned (and can therefore represent
// values from 0 to 65535, which is sufficient since the size of a
// method is limited to 65535 bytes).
int opcode = data[reference - 1] & 0xFF;
if (opcode <= Constants.JSR) {
// changes IFEQ ... JSR to opcodes 202 to 217 (inclusive)
data[reference - 1] = (byte)(opcode + 49);
} else {
// changes IFNULL and IFNONNULL to opcodes 218 and 219 (inclusive)
data[reference - 1] = (byte)(opcode + 20);
}
needUpdate = true;
}
data[reference++] = (byte)(offset >>> 8);
data[reference] = (byte)offset;
} else {
offset = position + source + 1;
data[reference++] = (byte)(offset >>> 24);
data[reference++] = (byte)(offset >>> 16);
data[reference++] = (byte)(offset >>> 8);
data[reference] = (byte)offset;
}
}
return needUpdate;
}
// --------------------------------------------------------------------------
// Overriden Object methods
// --------------------------------------------------------------------------
/**
* Returns a string representation of this label.
*
* @return a string representation of this label.
*/
public String toString () {
return "L" + System.identityHashCode(this);
}
}

View File

@ -1,763 +0,0 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact: Eric.Bruneton@rd.francetelecom.com
*
* Author: Eric Bruneton
* with contributions from: Chris Nokleberg
*/
package org.objectweb.asm;
import java.lang.reflect.Method;
/**
* A Java type. This class can be used to make it easier to manipulate type
* and method descriptors.
*/
public class Type {
/**
* The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
*/
public final static int VOID = 0;
/**
* The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
*/
public final static int BOOLEAN = 1;
/**
* The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
*/
public final static int CHAR = 2;
/**
* The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
*/
public final static int BYTE = 3;
/**
* The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
*/
public final static int SHORT = 4;
/**
* The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
*/
public final static int INT = 5;
/**
* The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
*/
public final static int FLOAT = 6;
/**
* The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
*/
public final static int LONG = 7;
/**
* The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
*/
public final static int DOUBLE = 8;
/**
* The sort of array reference types. See {@link #getSort getSort}.
*/
public final static int ARRAY = 9;
/**
* The sort of object reference type. See {@link #getSort getSort}.
*/
public final static int OBJECT = 10;
/**
* The <tt>void</tt> type.
*/
public final static Type VOID_TYPE = new Type(VOID);
/**
* The <tt>boolean</tt> type.
*/
public final static Type BOOLEAN_TYPE = new Type(BOOLEAN);
/**
* The <tt>char</tt> type.
*/
public final static Type CHAR_TYPE = new Type(CHAR);
/**
* The <tt>byte</tt> type.
*/
public final static Type BYTE_TYPE = new Type(BYTE);
/**
* The <tt>short</tt> type.
*/
public final static Type SHORT_TYPE = new Type(SHORT);
/**
* The <tt>int</tt> type.
*/
public final static Type INT_TYPE = new Type(INT);
/**
* The <tt>float</tt> type.
*/
public final static Type FLOAT_TYPE = new Type(FLOAT);
/**
* The <tt>long</tt> type.
*/
public final static Type LONG_TYPE = new Type(LONG);
/**
* The <tt>double</tt> type.
*/
public final static Type DOUBLE_TYPE = new Type(DOUBLE);
// --------------------------------------------------------------------------
// Fields
// --------------------------------------------------------------------------
/**
* The sort of this Java type.
*/
private final int sort;
/**
* A buffer containing the descriptor of this Java type.
* This field is only used for reference types.
*/
private char[] buf;
/**
* The offset of the descriptor of this Java type in {@link #buf buf}.
* This field is only used for reference types.
*/
private int off;
/**
* The length of the descriptor of this Java type.
*/
private int len;
// --------------------------------------------------------------------------
// Constructors
// --------------------------------------------------------------------------
/**
* Constructs a primitive type.
*
* @param sort the sort of the primitive type to be constructed.
*/
private Type (final int sort) {
this.sort = sort;
this.len = 1;
}
/**
* Constructs a reference type.
*
* @param sort the sort of the reference type to be constructed.
* @param buf a buffer containing the descriptor of the previous type.
* @param off the offset of this descriptor in the previous buffer.
* @param len the length of this descriptor.
*/
private Type (
final int sort,
final char[] buf,
final int off,
final int len)
{
this.sort = sort;
this.buf = buf;
this.off = off;
this.len = len;
}
/**
* Returns the Java type corresponding to the given type descriptor.
*
* @param typeDescriptor a type descriptor.
* @return the Java type corresponding to the given type descriptor.
*/
public static Type getType (final String typeDescriptor) {
return getType(typeDescriptor.toCharArray(), 0);
}
/**
* Returns the Java type corresponding to the given class.
*
* @param c a class.
* @return the Java type corresponding to the given class.
*/
public static Type getType (final Class c) {
if (c.isPrimitive()) {
if (c == Integer.TYPE) {
return INT_TYPE;
} else if (c == Void.TYPE) {
return VOID_TYPE;
} else if (c == Boolean.TYPE) {
return BOOLEAN_TYPE;
} else if (c == Byte.TYPE) {
return BYTE_TYPE;
} else if (c == Character.TYPE) {
return CHAR_TYPE;
} else if (c == Short.TYPE) {
return SHORT_TYPE;
} else if (c == Double.TYPE) {
return DOUBLE_TYPE;
} else if (c == Float.TYPE) {
return FLOAT_TYPE;
} else /*if (c == Long.TYPE)*/ {
return LONG_TYPE;
}
} else {
return getType(getDescriptor(c));
}
}
/**
* Returns the Java types corresponding to the argument types of the given
* method descriptor.
*
* @param methodDescriptor a method descriptor.
* @return the Java types corresponding to the argument types of the given
* method descriptor.
*/
public static Type[] getArgumentTypes (final String methodDescriptor) {
char[] buf = methodDescriptor.toCharArray();
int off = 1;
int size = 0;
while (true) {
char car = buf[off++];
if (car == ')') {
break;
} else if (car == 'L') {
while (buf[off++] != ';') {
}
++size;
} else if (car != '[') {
++size;
}
}
Type[] args = new Type[size];
off = 1;
size = 0;
while (buf[off] != ')') {
args[size] = getType(buf, off);
off += args[size].len;
size += 1;
}
return args;
}
/**
* Returns the Java types corresponding to the argument types of the given
* method.
*
* @param method a method.
* @return the Java types corresponding to the argument types of the given
* method.
*/
public static Type[] getArgumentTypes (final Method method) {
Class[] classes = method.getParameterTypes();
Type[] types = new Type[classes.length];
for (int i = classes.length - 1; i >= 0; --i) {
types[i] = getType(classes[i]);
}
return types;
}
/**
* Returns the Java type corresponding to the return type of the given
* method descriptor.
*
* @param methodDescriptor a method descriptor.
* @return the Java type corresponding to the return type of the given
* method descriptor.
*/
public static Type getReturnType (final String methodDescriptor) {
char[] buf = methodDescriptor.toCharArray();
return getType(buf, methodDescriptor.indexOf(')') + 1);
}
/**
* Returns the Java type corresponding to the return type of the given
* method.
*
* @param method a method.
* @return the Java type corresponding to the return type of the given
* method.
*/
public static Type getReturnType (final Method method) {
return getType(method.getReturnType());
}
/**
* Returns the Java type corresponding to the given type descriptor.
*
* @param buf a buffer containing a type descriptor.
* @param off the offset of this descriptor in the previous buffer.
* @return the Java type corresponding to the given type descriptor.
*/
private static Type getType (final char[] buf, final int off) {
int len;
switch (buf[off]) {
case 'V': return VOID_TYPE;
case 'Z': return BOOLEAN_TYPE;
case 'C': return CHAR_TYPE;
case 'B': return BYTE_TYPE;
case 'S': return SHORT_TYPE;
case 'I': return INT_TYPE;
case 'F': return FLOAT_TYPE;
case 'J': return LONG_TYPE;
case 'D': return DOUBLE_TYPE;
case '[':
len = 1;
while (buf[off + len] == '[') {
++len;
}
if (buf[off + len] == 'L') {
++len;
while (buf[off + len] != ';') {
++len;
}
}
return new Type(ARRAY, buf, off, len + 1);
//case 'L':
default:
len = 1;
while (buf[off + len] != ';') {
++len;
}
return new Type(OBJECT, buf, off, len + 1);
}
}
// --------------------------------------------------------------------------
// Accessors
// --------------------------------------------------------------------------
/**
* Returns the sort of this Java type.
*
* @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
* {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, {@link
* #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, {@link
* #ARRAY ARRAY} or {@link #OBJECT OBJECT}.
*/
public int getSort () {
return sort;
}
/**
* Returns the number of dimensions of this array type.
* This method should only be used for an array type.
*
* @return the number of dimensions of this array type.
*/
public int getDimensions () {
int i = 1;
while (buf[off + i] == '[') {
++i;
}
return i;
}
/**
* Returns the type of the elements of this array type.
* This method should only be used for an array type.
*
* @return Returns the type of the elements of this array type.
*/
public Type getElementType () {
return getType(buf, off + getDimensions());
}
/**
* Returns the name of the class corresponding to this object type.
* This method should only be used for an object type.
*
* @return the fully qualified name of the class corresponding to this object
* type.
*/
public String getClassName () {
return new String(buf, off + 1, len - 2).replace('/', '.');
}
/**
* Returns the internal name of the class corresponding to this object type.
* The internal name of a class is its fully qualified name, where '.' are
* replaced by '/'. * This method should only be used for an object type.
*
* @return the internal name of the class corresponding to this object type.
*/
public String getInternalName () {
return new String(buf, off + 1, len - 2);
}
// --------------------------------------------------------------------------
// Conversion to type descriptors
// --------------------------------------------------------------------------
/**
* Returns the descriptor corresponding to this Java type.
*
* @return the descriptor corresponding to this Java type.
*/
public String getDescriptor () {
StringBuffer buf = new StringBuffer();
getDescriptor(buf);
return buf.toString();
}
/**
* Returns the descriptor corresponding to the given argument and return
* types.
*
* @param returnType the return type of the method.
* @param argumentTypes the argument types of the method.
* @return the descriptor corresponding to the given argument and return
* types.
*/
public static String getMethodDescriptor (
final Type returnType,
final Type[] argumentTypes)
{
StringBuffer buf = new StringBuffer();
buf.append('(');
for (int i = 0; i < argumentTypes.length; ++i) {
argumentTypes[i].getDescriptor(buf);
}
buf.append(')');
returnType.getDescriptor(buf);
return buf.toString();
}
/**
* Appends the descriptor corresponding to this Java type to the given string
* buffer.
*
* @param buf the string buffer to which the descriptor must be appended.
*/
private void getDescriptor (final StringBuffer buf) {
switch (sort) {
case VOID: buf.append('V'); return;
case BOOLEAN: buf.append('Z'); return;
case CHAR: buf.append('C'); return;
case BYTE: buf.append('B'); return;
case SHORT: buf.append('S'); return;
case INT: buf.append('I'); return;
case FLOAT: buf.append('F'); return;
case LONG: buf.append('J'); return;
case DOUBLE: buf.append('D'); return;
//case ARRAY:
//case OBJECT:
default: buf.append(this.buf, off, len);
}
}
// --------------------------------------------------------------------------
// Direct conversion from classes to type descriptors,
// without intermediate Type objects
// --------------------------------------------------------------------------
/**
* Returns the internal name of the given class. The internal name of a class
* is its fully qualified name, where '.' are replaced by '/'.
*
* @param c an object class.
* @return the internal name of the given class.
*/
public static String getInternalName (final Class c) {
return c.getName().replace('.', '/');
}
/**
* Returns the descriptor corresponding to the given Java type.
*
* @param c an object class, a primitive class or an array class.
* @return the descriptor corresponding to the given class.
*/
public static String getDescriptor (final Class c) {
StringBuffer buf = new StringBuffer();
getDescriptor(buf, c);
return buf.toString();
}
/**
* Returns the descriptor corresponding to the given method.
*
* @param m a {@link Method Method} object.
* @return the descriptor of the given method.
*/
public static String getMethodDescriptor (final Method m) {
Class[] parameters = m.getParameterTypes();
StringBuffer buf = new StringBuffer();
buf.append('(');
for (int i = 0; i < parameters.length; ++i) {
getDescriptor(buf, parameters[i]);
}
buf.append(')');
getDescriptor(buf, m.getReturnType());
return buf.toString();
}
/**
* Appends the descriptor of the given class to the given string buffer.
*
* @param buf the string buffer to which the descriptor must be appended.
* @param c the class whose descriptor must be computed.
*/
private static void getDescriptor (final StringBuffer buf, final Class c) {
Class d = c;
while (true) {
if (d.isPrimitive()) {
char car;
if (d == Integer.TYPE) {
car = 'I';
} else if (d == Void.TYPE) {
car = 'V';
} else if (d == Boolean.TYPE) {
car = 'Z';
} else if (d == Byte.TYPE) {
car = 'B';
} else if (d == Character.TYPE) {
car = 'C';
} else if (d == Short.TYPE) {
car = 'S';
} else if (d == Double.TYPE) {
car = 'D';
} else if (d == Float.TYPE) {
car = 'F';
} else /*if (d == Long.TYPE)*/ {
car = 'J';
}
buf.append(car);
return;
} else if (d.isArray()) {
buf.append('[');
d = d.getComponentType();
} else {
buf.append('L');
String name = d.getName();
int len = name.length();
for (int i = 0; i < len; ++i) {
char car = name.charAt(i);
buf.append(car == '.' ? '/' : car);
}
buf.append(';');
return;
}
}
}
// --------------------------------------------------------------------------
// Corresponding size and opcodes
// --------------------------------------------------------------------------
/**
* Returns the size of values of this type.
*
* @return the size of values of this type, i.e., 2 for <tt>long</tt> and
* <tt>double</tt>, and 1 otherwise.
*/
public int getSize () {
return (sort == LONG || sort == DOUBLE ? 2 : 1);
}
/**
* Returns a JVM instruction opcode adapted to this Java type.
*
* @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
* ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
* ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
* @return an opcode that is similar to the given opcode, but adapted to this
* Java type. For example, if this type is <tt>float</tt> and
* <tt>opcode</tt> is IRETURN, this method returns FRETURN.
*/
public int getOpcode (final int opcode) {
if (opcode == Constants.IALOAD || opcode == Constants.IASTORE) {
switch (sort) {
case BOOLEAN:
case BYTE:
return opcode + 5;
case CHAR:
return opcode + 6;
case SHORT:
return opcode + 7;
case INT:
return opcode;
case FLOAT:
return opcode + 2;
case LONG:
return opcode + 1;
case DOUBLE:
return opcode + 3;
//case ARRAY:
//case OBJECT:
default:
return opcode + 4;
}
} else {
switch (sort) {
case VOID:
return opcode + 5;
case BOOLEAN:
case CHAR:
case BYTE:
case SHORT:
case INT:
return opcode;
case FLOAT:
return opcode + 2;
case LONG:
return opcode + 1;
case DOUBLE:
return opcode + 3;
//case ARRAY:
//case OBJECT:
default:
return opcode + 4;
}
}
}
// --------------------------------------------------------------------------
// Equals, hashCode and toString
// --------------------------------------------------------------------------
/**
* Tests if the given object is equal to this type.
*
* @param o the object to be compared to this type.
* @return <tt>true</tt> if the given object is equal to this type.
*/
public boolean equals (final Object o) {
if (this == o) {
return true;
}
if (o == null || !(o instanceof Type)) {
return false;
}
Type t = (Type)o;
if (sort != t.sort) {
return false;
}
if (sort == Type.OBJECT || sort == Type.ARRAY) {
if (len != t.len) {
return false;
}
for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
if (buf[i] != t.buf[j]) {
return false;
}
}
}
return true;
}
/**
* Returns a hash code value for this type.
*
* @return a hash code value for this type.
*/
public int hashCode () {
int hc = 13 * sort;
if (sort == Type.OBJECT || sort == Type.ARRAY) {
for (int i = off, end = i + len; i < end; i++) {
hc = 17 * (hc + buf[i]);
}
}
return hc;
}
/**
* Returns a string representation of this type.
*
* @return the descriptor of this type.
*/
public String toString () {
return getDescriptor();
}
}