nomennescio 2019-10-18 15:04:30 +02:00
parent e65177754e
commit 01ed138a92
106 changed files with 23014 additions and 0 deletions

View File

@ -0,0 +1,45 @@
./factor/random.factor:! $Id: random.factor,v 1.3 2004/01/09 01:51:30 slava Exp $
./factor/FactorExternalizable.java: * $Id: FactorExternalizable.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorJava.java: * $Id: FactorJava.java,v 1.12 2004/01/06 06:59:38 slava Exp $
./factor/FactorDictionary.java: * $Id: FactorDictionary.java,v 1.12 2004/01/14 01:58:37 slava Exp $
./factor/combinators.factor:! $Id: combinators.factor,v 1.17 2004/01/11 23:00:34 slava Exp $
./factor/FactorDataStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $
./factor/continuations.factor:! $Id: continuations.factor,v 1.8 2003/12/20 05:31:01 slava Exp $
./factor/network.factor:! $Id: io.factor,v 1.2 2003/12/20 05:31:01 slava Exp $
./factor/FactorLib.java: * $Id: FactorLib.java,v 1.10 2004/01/03 20:58:09 slava Exp $
./factor/FactorRuntimeException.java: * $Id: FactorRuntimeException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorRatio.java: * $Id: FactorRatio.java,v 1.1 2003/12/16 08:03:08 slava Exp $
./factor/FactorCallStack.java: * $Id: FactorCallStack.java,v 1.1 2003/12/20 02:13:09 slava Exp $
./factor/FactorStackException.java: * $Id: FactorStackException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorUndefinedWordException.java: * $Id: FactorUndefinedWordException.java,v 1.1 2003/12/09 09:52:26 slava Exp $
./factor/lists.factor:! $Id: lists.factor,v 1.10 2004/01/06 06:59:38 slava Exp $
./factor/FactorCallFrame.java: * $Id: FactorCallFrame.java,v 1.3 2003/12/26 00:36:30 slava Exp $
./factor/examples/httpd.factor:! $Id: httpd.factor,v 1.1 2004/01/15 03:00:18 slava Exp $
./factor/FactorPrimitive.java: * $Id: FactorPrimitive.java,v 1.5 2004/01/11 23:00:34 slava Exp $
./factor/FactorList.java: * $Id: FactorList.java,v 1.9 2004/01/03 20:58:09 slava Exp $
./factor/FactorNamespace.java: * $Id: FactorNamespace.java,v 1.10 2004/01/08 04:14:14 slava Exp $
./factor/PublicCloneable.java: * $Id: PublicCloneable.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/examples.factor:! $Id: examples.factor,v 1.4 2004/01/12 02:07:31 slava Exp $
./factor/FactorCompoundDefinition.java:* $Id: FactorCompoundDefinition.java,v 1.2 2004/01/14 01:58:37 slava Exp $
./factor/FactorObject.java: * $Id: FactorObject.java,v 1.5 2003/12/19 21:40:00 slava Exp $
./factor/FactorParser.java: * $Id: FactorParser.java,v 1.13 2004/01/10 23:24:30 slava Exp $
./factor/FactorMath.java: * $Id: FactorMath.java,v 1.7 2003/12/26 00:36:30 slava Exp $
./factor/parser.factor:! $Id: parser.factor,v 1.2 2003/12/20 04:30:06 slava Exp $
./factor/FactorMissingDefinition.java: * $Id: FactorWordDefinition.java,v 1.10 2003/12/18 00:01:39 slava Exp $
./factor/stream.factor:! $Id: stream.factor,v 1.1 2004/01/03 20:58:09 slava Exp $
./factor/FactorReflectionForm.java:* $Id: FactorReflectionForm.java,v 1.1 2004/01/14 01:58:37 slava Exp $
./factor/strings.factor:! $Id: strings.factor,v 1.4 2004/01/06 06:59:38 slava Exp $
./factor/FactorInterpreter.java: * $Id: FactorInterpreter.java,v 1.32 2004/01/12 02:07:31 slava Exp $
./factor/FactorDomainException.java: * $Id: FactorDomainException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorWord.java: * $Id: FactorWord.java,v 1.10 2004/01/08 04:14:14 slava Exp $
./factor/math.factor:! $Id: math.factor,v 1.11 2004/01/11 23:00:34 slava Exp $
./factor/FactorWordDefinition.java: * $Id: FactorWordDefinition.java,v 1.17 2004/01/14 01:58:37 slava Exp $
./factor/interpreter.factor:! $Id: interpreter.factor,v 1.14 2004/01/11 23:00:34 slava Exp $
./factor/miscellaneous.factor:! $Id: miscellaneous.factor,v 1.5 2003/12/21 05:29:46 slava Exp $
./factor/FactorArrayStack.java: * $Id: FactorArrayStack.java,v 1.3 2003/12/20 05:31:01 slava Exp $
./factor/boot.factor:! $Id: boot.factor,v 1.12 2004/01/12 02:07:31 slava Exp $
./factor/FactorParseException.java: * $Id: FactorParseException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/namespaces.factor:! $Id: namespaces.factor,v 1.4 2004/01/05 05:03:36 slava Exp $
./factor/FactorException.java: * $Id: FactorException.java,v 1.3 2003/12/09 09:40:18 slava Exp $
./factor/FactorShuffleDefinition.java: * $Id: FactorShuffleDefinition.java,v 1.5 2004/01/14 01:58:37 slava Exp $
./factor/dictionary.factor:! $Id: dictionary.factor,v 1.6 2004/01/12 02:07:31 slava Exp $

5
META-INF/MANIFEST.MF Normal file
View File

@ -0,0 +1,5 @@
Manifest-Version: 1.0
Created-By: 1.4.2-p6-slava_18_jan_2004_13_00 (Sun Microsystems Inc.)
Ant-Version: Apache Ant 1.5.4
Main-Class: factor.FactorInterpreter

View File

@ -0,0 +1,160 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
/**
* Factor is a stack-based language.
* @author Slava Pestov
*/
public abstract class FactorArrayStack implements FactorExternalizable
{
public Object[] stack;
public int top;
//{{{ FactorArrayStack constructor
public FactorArrayStack()
{
} //}}}
//{{{ FactorArrayStack constructor
public FactorArrayStack(FactorList list)
{
if(list != null)
{
ensurePush(list.length());
while(list != null)
{
push(list.car);
list = list.next();
}
}
} //}}}
//{{{ FactorArrayStack constructor
public FactorArrayStack(Object[] stack, int top)
{
this.stack = stack;
this.top = top;
} //}}}
//{{{ pop() method
public Object pop(Class clas) throws Exception
{
return FactorJava.convertToJavaType(pop(),clas);
} //}}}
//{{{ pop() method
public Object pop() throws FactorStackException
{
ensurePop(1);
Object returnValue = stack[--top];
if(shouldClear(returnValue))
stack[top] = null;
return returnValue;
} //}}}
//{{{ shouldClear() method
/**
* Some data (arbitrary objects) should be removed from the stack as
* soon as they're popped, but some (callframes) should be left on and
* reused later.
*/
public abstract boolean shouldClear(Object o);
//}}}
//{{{ ensurePop() method
public void ensurePop(int amount) throws FactorStackException
{
if(amount > top)
throw new FactorStackException(amount);
} //}}}
//{{{ push() method
public void push(Object o)
{
ensurePush(1);
stack[top++] = o;
} //}}}
//{{{ pushAll() method
public void pushAll(Object[] array)
{
ensurePush(array.length);
System.arraycopy(array,0,stack,top,array.length);
top += array.length;
} //}}}
//{{{ ensurePush() method
public void ensurePush(int amount)
{
if(stack == null)
stack = new Object[64];
if(top + amount > stack.length)
{
Object[] newStack = new Object[stack.length * 2 + 1];
System.arraycopy(stack,0,newStack,0,top);
stack = newStack;
}
} //}}}
//{{{ toList() method
public FactorList toList()
{
FactorList first = null, last = null;
for(int i = 0; i < top; i++)
{
FactorList cons = new FactorList(stack[i],null);
if(first == null)
first = cons;
else
last.cdr = cons;
last = cons;
}
return first;
} //}}}
//{{{ toString() method
public String toString()
{
StringBuffer buf = new StringBuffer();
for(int i = 0; i < top; i++)
{
if(i != 0)
buf.append('\n');
buf.append(i).append(": ");
if(stack[i] == this)
buf.append("THIS STACK");
else
buf.append(FactorJava.factorTypeToString(stack[i]));
}
return buf.toString();
} //}}}
}

115
factor/FactorCallFrame.java Normal file
View File

@ -0,0 +1,115 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public class FactorCallFrame implements PublicCloneable, FactorExternalizable
{
/**
* Word being evaluated.
*/
public FactorWord word;
/**
* Namespace.
*/
public FactorNamespace namespace;
/**
* Next word to be evaluated.
*/
public FactorList ip;
/**
* Collapsed tail calls? See call().
*/
public boolean collapsed;
//{{{ FactorCallFrame constructor
public FactorCallFrame()
{
} //}}}
//{{{ FactorCallFrame constructor
public FactorCallFrame(FactorWord word,
FactorNamespace namespace,
FactorList ip)
{
this.word = word;
this.namespace = namespace;
this.ip = ip;
} //}}}
//{{{ toString() method
public String toString()
{
return toString(0);
} //}}}
//{{{ toString() method
public String toString(int level)
{
StringBuffer buf = new StringBuffer();
for(int i = 0; i < level; i++)
{
buf.append(" ");
}
String indent = buf.toString();
buf = new StringBuffer();
buf.append(indent);
if(collapsed)
buf.append("at ... then ");
buf.append("at ").append(word);
buf.append('\n').append(indent);
buf.append(" namespace: ").append(namespace)
.append('\n').append(indent);
buf.append(" ip: ").append(ip);
return buf.toString();
} //}}}
//{{{ clone() method
public Object clone()
{
try
{
return super.clone();
}
catch(Exception e)
{
return null;
}
} //}}}
}

View File

@ -0,0 +1,65 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
/**
* The call stack. Stores call frames.
* @author Slava Pestov
*/
public class FactorCallStack extends FactorArrayStack implements PublicCloneable
{
//{{{ FactorCallStack constructor
public FactorCallStack()
{
} //}}}
//{{{ FactorCallStack constructor
public FactorCallStack(Object[] stack, int top)
{
super(stack,top);
} //}}}
//{{{ shouldClear() method
/**
* Some data (arbitrary objects) should be removed from the stack as
* soon as they're popped, but some (callframes) should be left on and
* reused later.
*/
public boolean shouldClear(Object o)
{
return !(o instanceof FactorCallFrame);
} //}}}
//{{{ clone() method
public Object clone()
{
return new FactorCallStack(FactorLib.deepCloneArray(stack),top);
} //}}}
}

View File

@ -0,0 +1,317 @@
/* :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;
import java.lang.reflect.*;
import org.objectweb.asm.*;
/**
* : name ... ;
*/
public class FactorCompoundDefinition extends FactorWordDefinition
{
public FactorList definition;
public FactorCompoundDefinition(FactorList definition)
{
this.definition = definition;
}
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.call(word,definition);
}
//{{{ canCompile() method
boolean canCompile()
{
return true;
} //}}}
//{{{ compile() method
/**
* Write the definition of the eval() method in the compiled word.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
*/
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
{
if(definition == null)
{
mw.visitInsn(RETURN);
// Max stack and locals
mw.visitMaxs(1,1);
return true;
}
FactorList fdef = compilePass1(interp,definition);
if(fdef.car instanceof FactorReflectionForm
&& fdef.cdr == null)
{
return ((FactorReflectionForm)fdef.car).compile(
word,interp,cw,mw);
}
/* else
System.err.println("WARNING: cannot compile reflection & more"); */
return false;
} //}}}
//{{{ compilePass1() method
/**
* Turn reflection calls into ReflectionForm objects.
*/
private FactorList compilePass1(FactorInterpreter interp, FactorList def)
{
if(!def.isProperList())
return def;
FactorList rdef = def.reverse();
FactorDictionary dict = interp.dict;
// A list of words and Java reflection forms
FactorList fdef = null;
while(rdef != null)
{
Object car = rdef.car;
if(car == dict.jvarGet
|| car == dict.jvarSet
|| car == dict.jvarGetStatic
|| car == dict.jvarSetStatic
|| car == dict.jnew)
{
FactorList form = rdef;
rdef = form._get(3);
fdef = new FactorList(new FactorReflectionForm(form),
fdef);
}
else if(car == dict.jinvoke
|| car == dict.jinvokeStatic)
{
FactorList form = rdef;
rdef = form._get(4);
fdef = new FactorList(new FactorReflectionForm(form),
fdef);
}
else if(car instanceof FactorList)
{
fdef = new FactorList(compilePass1(
interp,((FactorList)car)),fdef);
}
else
fdef = new FactorList(car,fdef);
rdef = rdef.next();
}
return fdef;
} //}}}
//{{{ precompile() method
void precompile(FactorWord newWord, FactorInterpreter interp)
throws Exception
{
FactorDictionary dict = interp.dict;
if(definition != null)
{
FactorList before = definition;
FactorList fed = definition.reverse();
precompile(interp,newWord,fed);
definition = fed.reverse();
/* if(!def.equals(before))
{
System.out.println("BEFORE: " + before);
System.out.println("AFTER: " + def);
} */
}
} //}}}
//{{{ precompile() method
/**
* Precompiling turns jconstructor, jfield and jmethod calls
* with all-literal arguments into inline
* Constructor/Field/Method literals. This improves performance.
*/
private void precompile(FactorInterpreter interp,
FactorWord newWord, FactorList list)
throws Exception
{
if(interp.compile)
return;
FactorDictionary dict = interp.dict;
while(list != null)
{
Object o = list.car;
if(o instanceof FactorWord)
{
FactorWord word = (FactorWord)o;
if(word.def != FactorMissingDefinition.INSTANCE)
{
word.def.references++;
}
else
{
/*System.err.println(
"WARNING: "
+ newWord
+ " references "
+ o
+ " before its defined");*/
}
if(o == dict.jconstructor)
{
jconstructorPrecompile(
interp,list);
}
else if(o == dict.jmethod)
{
jmethodPrecompile(
interp,list);
}
else if(o == dict.jfield)
{
jfieldPrecompile(
interp,list);
}
}
else if(o instanceof FactorList)
{
if(((FactorList)o).isProperList())
{
FactorList l = (FactorList)o;
FactorList _l = l.reverse();
precompile(interp,newWord,_l);
list.car = _l.reverse();
}
}
list = list.next();
}
} //}}}
//{{{ jconstructorPrecompile() method
private void jconstructorPrecompile(
FactorInterpreter interp, FactorList list)
throws Exception
{
FactorList cdr = list.next();
if(cdr == null)
return;
if(!(cdr.car instanceof String))
return;
String clazz = (String)cdr.car;
FactorList cddr = cdr.next();
if(cddr == null)
return;
if(!(cddr.car instanceof FactorList))
return;
FactorList args = (FactorList)cddr.car;
Constructor c = FactorJava.jconstructor(clazz,args);
list.car = c;
list.cdr = cddr.next();
} //}}}
//{{{ jfieldPrecompile() method
private void jfieldPrecompile(
FactorInterpreter interp, FactorList list)
throws Exception
{
FactorList cdr = list.next();
if(cdr == null)
return;
if(!(cdr.car instanceof String))
return;
String field = (String)cdr.car;
FactorList cddr = cdr.next();
if(cddr == null)
return;
if(!(cddr.car instanceof String))
return;
String clazz = (String)cddr.car;
Field f = FactorJava.jfield(field,clazz);
list.car = f;
list.cdr = cddr.next();
} //}}}
//{{{ jmethodPrecompile() method
/**
* Check if this jmethod has all-literal arguments, and if so,
* inline the result.
*/
private void jmethodPrecompile(
FactorInterpreter interp, FactorList list)
throws Exception
{
FactorList cdr = list.next();
if(cdr == null)
return;
if(!(cdr.car instanceof String))
return;
String method = (String)cdr.car;
FactorList cddr = cdr.next();
if(cddr == null)
return;
if(!(cddr.car instanceof String))
return;
String clazz = (String)cddr.car;
FactorList cdddr = cddr.next();
if(cdddr == null)
return;
if(!(cdddr.car instanceof FactorList))
return;
FactorList args = (FactorList)cdddr.car;
Method m = FactorJava.jmethod(method,clazz,args);
list.car = m;
list.cdr = cdddr.next();
} //}}}
public String toString()
{
return definition.elementsToString();
}
}

View File

@ -0,0 +1,71 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
/**
* The data stack. Stores parameters passed between words.
* @author Slava Pestov
*/
public class FactorDataStack extends FactorArrayStack implements PublicCloneable
{
//{{{ FactorDataStack constructor
public FactorDataStack()
{
} //}}}
//{{{ FactorDataStack constructor
public FactorDataStack(FactorList list)
{
super(list);
} //}}}
//{{{ FactorDataStack constructor
public FactorDataStack(Object[] stack, int top)
{
super(stack,top);
} //}}}
//{{{ shouldClear() method
/**
* Some data (arbitrary objects) should be removed from the stack as
* soon as they're popped, but some (callframes) should be left on and
* reused later.
*/
public boolean shouldClear(Object o)
{
return true;
} //}}}
//{{{ clone() method
public Object clone()
{
return new FactorDataStack(FactorLib.cloneArray(stack),top);
} //}}}
}

View File

@ -0,0 +1,137 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class FactorDictionary
{
// these are defined here for use by the precompiler
FactorWord jconstructor;
FactorWord jnew;
FactorWord jfield;
FactorWord jvarGet;
FactorWord jvarSet;
FactorWord jvarGetStatic;
FactorWord jvarSetStatic;
FactorWord jmethod;
FactorWord jinvoke;
FactorWord jinvokeStatic;
private Map intern;
//{{{ init() method
public void init()
{
intern = new TreeMap();
// data stack primitives
intern("datastack$").def = new FactorPrimitive.P_datastackGet();
intern("datastack@").def = new FactorPrimitive.P_datastackSet();
intern("clear").def = new FactorPrimitive.P_clear();
// call stack primitives
intern("callstack$").def = new FactorPrimitive.P_callstackGet();
intern("callstack@").def = new FactorPrimitive.P_callstackSet();
intern("restack").def = new FactorPrimitive.P_restack();
intern("unstack").def = new FactorPrimitive.P_unstack();
intern("unwind").def = new FactorPrimitive.P_unwind();
// reflection primitives
jconstructor = intern("jconstructor");
jconstructor.def = new FactorPrimitive.P_jconstructor();
jfield = intern("jfield");
jfield.def = new FactorPrimitive.P_jfield();
jinvoke = intern("jinvoke");
jinvoke.def = new FactorPrimitive.P_jinvoke();
jinvokeStatic = intern("jinvokeStatic");
jinvokeStatic.def = new FactorPrimitive.P_jinvokeStatic();
jmethod = intern("jmethod");
jmethod.def = new FactorPrimitive.P_jmethod();
jnew = intern("jnew");
jnew.def = new FactorPrimitive.P_jnew();
jvarGet = intern("jvar$");
jvarGet.def = new FactorPrimitive.P_jvarGet();
jvarGetStatic = intern("jvarStatic$");
jvarGetStatic.def = new FactorPrimitive.P_jvarGetStatic();
jvarSet = intern("jvar@");
jvarSet.def = new FactorPrimitive.P_jvarSet();
jvarSetStatic = intern("jvarStatic@");
jvarSetStatic.def = new FactorPrimitive.P_jvarSetStatic();
// namespaces
intern("$").def = new FactorPrimitive.P_get();
intern("@").def = new FactorPrimitive.P_set();
intern("s@").def = new FactorPrimitive.P_swap_set();
// definition
intern("define").def = new FactorPrimitive.P_define();
// combinators
intern("call").def = new FactorPrimitive.P_call();
intern("bind").def = new FactorPrimitive.P_bind();
} //}}}
//{{{ intern() method
public FactorWord intern(String name)
{
FactorWord w = (FactorWord)intern.get(name);
if(w == null)
{
w = new FactorWord(name);
intern.put(name,w);
}
return w;
} //}}}
//{{{ toWordList() method
public FactorList toWordList()
{
FactorList first = null;
FactorList last = null;
Iterator iter = intern.values().iterator();
while(iter.hasNext())
{
FactorWord word = (FactorWord)iter.next();
if(word.def != FactorMissingDefinition.INSTANCE)
{
FactorList cons = new FactorList(word,null);
if(first == null)
first = cons;
else
last.cdr = cons;
last = cons;
}
}
return first;
} //}}}
}

View File

@ -0,0 +1,38 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public class FactorDomainException extends FactorRuntimeException
{
public FactorDomainException(Object arg, Class clas)
{
super("Cannot turn " + arg + " into " + clas);
}
}

View File

@ -0,0 +1,54 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.lang.reflect.InvocationTargetException;
public class FactorException extends Exception
{
public FactorException(String str)
{
super(str);
}
public FactorException(String str, Throwable t)
{
super(str,unwrap(t));
}
private static Throwable unwrap(Throwable t)
{
if(t instanceof InvocationTargetException)
return ((InvocationTargetException)t)
.getTargetException();
else
return t;
}
}

View File

@ -0,0 +1,39 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
/**
* Called if the object has a string representation that is understood
* by the parser.
*/
public interface FactorExternalizable
{
String toString();
}

View File

@ -0,0 +1,357 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.io.*;
public class FactorInterpreter
{
/**
* boot.factor checks this, if its true, an interpreter is run on
* standard input.
*/
public boolean interactive = false;
public boolean trace = false;
public boolean errorFlag = false;
public boolean compile = true;
public FactorCallFrame callframe;
public FactorCallStack callstack = new FactorCallStack();
public FactorDataStack datastack = new FactorDataStack();
public final FactorDictionary dict = new FactorDictionary();
public FactorNamespace global;
//{{{ main() method
/**
* Need to refactor this into Factor.
*/
public static void main(String[] args) throws Exception
{
FactorInterpreter interp = new FactorInterpreter();
boolean virgin = false;
for(int i = 0; i < args.length; i++)
{
if(args[i].equals("-trace"))
interp.trace = true;
else if(args[i].equals("-virgin"))
virgin = true;
else if(args[i].equals("-interp"))
interp.compile = false;
}
interp.interactive = true;
interp.init(null,!virgin);
if(virgin)
{
System.out.println("Mini-interpreter");
BufferedReader in = new BufferedReader(
new InputStreamReader(
System.in));
String line;
for(;;)
{
System.out.print("] ");
System.out.flush();
line = in.readLine();
if(line == null)
break;
FactorParser parser = new FactorParser(
"<mini>",new StringReader(line),
interp.dict);
FactorList parsed = parser.parse();
interp.call(parsed);
interp.run();
System.out.println(interp.datastack);
}
}
else
{
interp.run();
}
System.exit(0);
} //}}}
//{{{ init() method
public void init(Object root, boolean bootstrap) throws Exception
{
callstack.top = 0;
datastack.top = 0;
dict.init();
initNamespace(root);
topLevel();
if(bootstrap)
runBootstrap();
} //}}}
//{{{ initNamespace() method
private void initNamespace(Object root) throws Exception
{
global = new FactorNamespace(null,root);
global.setVariable("interpreter",this);
String[] boundFields = { "compile", "interactive", "trace",
"dict", "errorFlag" };
for(int i = 0; i < boundFields.length; i++)
{
global.setVariable(boundFields[i],
new FactorNamespace.VarBinding(
getClass().getField(boundFields[i]),
this));
}
} //}}}
//{{{ runBootstrap() method
private void runBootstrap() throws Exception
{
final String initFile = "boot.factor";
FactorParser parser = new FactorParser(
initFile,
new InputStreamReader(
getClass().getResourceAsStream(
initFile)),
dict);
call(dict.intern("[init]"),parser.parse());
run();
} //}}}
//{{{ run() method
/**
* Runs the top-level loop until there is no more code to execute.
*/
public void run()
{
for(;;)
{
try
{
if(callframe == null)
break;
FactorList ip = callframe.ip;
if(ip == null)
{
if(callstack.top == 0)
break;
try
{
callframe = (FactorCallFrame)
callstack.pop();
continue;
}
catch(ClassCastException e)
{
throw new FactorRuntimeException(
"Unbalanced >r/r> or "
+ "restack/unstack");
}
}
callframe.ip = ip.next();
eval(ip.car);
}
catch(Exception e)
{
if(handleError(e))
return;
}
}
callframe = null;
} //}}}
//{{{ handleError() method
private boolean handleError(Exception e)
{
/* if(throwErrors)
{
throw e;
}
else */ if(errorFlag)
{
System.err.println("Exception inside"
+ " error handler:");
e.printStackTrace();
System.err.println(
"Original exception:");
e.printStackTrace();
System.err.println("Factor callstack:");
System.err.println(callstack);
return true;
}
else
{
errorFlag = true;
datastack.push(FactorJava.unwrapException(e));
try
{
eval(dict.intern("break"));
return false;
}
catch(Exception e2)
{
System.err.println("Exception when calling break:");
e.printStackTrace();
System.err.println("Factor callstack:");
System.err.println(callstack);
return true;
}
}
} //}}}
//{{{ call() method
/**
* Pushes the given list of code onto the callstack.
*/
public final void call(FactorList code)
{
call(dict.intern("call"),code);
} //}}}
//{{{ call() method
/**
* Pushes the given list of code onto the callstack.
*/
public final void call(FactorWord word, FactorList code)
{
if(callframe == null)
call(word,global,code);
else
call(word,callframe.namespace,code);
} //}}}
//{{{ call() method
/**
* Pushes the given list of code onto the callstack.
*/
public final void call(FactorWord word, FactorNamespace namespace, FactorList code)
{
FactorCallFrame newcf;
// tail call optimization
if(callframe != null && callframe.ip == null)
{
if(trace)
System.err.println("-- TAIL CALL --");
newcf = getRecycledCallFrame(callstack.top);
newcf.collapsed = true;
}
// try to get a recycled callframe from the stack
else
{
newcf = getRecycledCallFrame(callstack.top + 1);
newcf.collapsed = false;
if(callframe != null)
callstack.push(callframe);
}
newcf.word = word;
newcf.namespace = namespace;
newcf.ip = code;
callframe = newcf;
} //}}}
//{{{ getRecycledCallFrame() method
private FactorCallFrame getRecycledCallFrame(int next)
{
/* if(callstack.stack != null && next < callstack.stack.length)
{
Object o = callstack.stack[next];
if(o instanceof FactorCallFrame)
return (FactorCallFrame)o;
else
return new FactorCallFrame();
}
else */
return new FactorCallFrame();
} //}}}
//{{{ eval() method
/**
* Evaluates a word.
*/
private void eval(Object obj) throws Exception
{
if(trace)
{
StringBuffer buf = new StringBuffer();
for(int i = 0; i < callstack.top; i++)
buf.append(' ');
buf.append(FactorJava.factorTypeToString(obj));
System.err.println(buf);
}
if(obj instanceof FactorWord)
{
FactorWord w = (FactorWord)obj;
try
{
w.def.eval(w,this);
}
catch(Exception e)
{
callstack.push(callframe);
callframe = new FactorCallFrame(
w,
callframe.namespace,
null);
throw e;
}
}
else
datastack.push(obj);
} //}}}
//{{{ topLevel() method
/**
* Returns the parser to the top level context.
*/
public void topLevel()
{
callstack.top = 0;
datastack.top = 0;
callframe = new FactorCallFrame(
dict.intern("[toplevel]"),
global,
null);
} //}}}
}

522
factor/FactorJava.java Normal file
View File

@ -0,0 +1,522 @@
/* :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;
import java.lang.reflect.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* A few methods for converting between Java types, and making reflection calls.
* Note that the compiler incorporates calls to some of these methods in
* generated bytecode.
*/
public class FactorJava
{
public static final Class[] EMPTY_ARRAY = new Class[0];
//{{{ classNameToClassList() method
public static Class[] classNameToClassList(FactorList classes)
throws Exception
{
if(classes == null)
return EMPTY_ARRAY;
Class[] _classes = new Class[classes.length()];
int i = 0;
while(classes != null)
{
_classes[i++] = (Class)classes.car(Class.class);
classes = classes.next();
}
return _classes;
} //}}}
//{{{ toNumber() method
public static Number toNumber(Object arg)
throws FactorDomainException
{
if(arg instanceof Number)
return (Number)arg;
else if(arg instanceof String)
{
String str = (String)arg;
if(str.indexOf('.') != -1)
return new Float(str);
else
return new Integer(str);
}
else
throw new FactorDomainException(arg,Number.class);
} //}}}
//{{{ toString() method
public static String toString(Object arg)
{
if(arg == null)
return null;
else if(arg instanceof String)
return (String)arg;
else
return String.valueOf(arg);
} //}}}
//{{{ toBoolean() method
public static boolean toBoolean(Object arg)
{
if(Boolean.FALSE.equals(arg) || arg == null)
return false;
else
return true;
} //}}}
//{{{ toChar() method
public static char toChar(Object arg)
throws FactorDomainException
{
if(arg instanceof Character)
return ((Character)arg).charValue();
else if(arg == null)
return '\0';
else if(arg instanceof String)
{
String s = (String)arg;
if(s.length() != 1)
throw new FactorDomainException(arg,char.class);
return s.charAt(0);
}
else if(arg instanceof Number)
{
return (char)((Number)arg).intValue();
}
else
throw new FactorDomainException(arg,char.class);
} //}}}
//{{{ toInt() method
public static int toInt(Object arg)
throws FactorDomainException
{
if(arg instanceof Number)
return ((Number)arg).intValue();
else if(arg instanceof String)
return Integer.parseInt((String)arg);
else
throw new FactorDomainException(arg,int.class);
} //}}}
//{{{ toLong() method
public static long toLong(Object arg)
throws FactorDomainException
{
if(arg instanceof Number)
return ((Number)arg).longValue();
else if(arg instanceof String)
return Long.parseLong((String)arg);
else
throw new FactorDomainException(arg,long.class);
} //}}}
//{{{ toFloat() method
public static float toFloat(Object arg)
throws FactorDomainException
{
if(arg instanceof Number)
return ((Number)arg).floatValue();
else if(arg instanceof String)
return Float.parseFloat((String)arg);
else
throw new FactorDomainException(arg,float.class);
} //}}}
//{{{ toDouble() method
public static double toDouble(Object arg)
throws FactorDomainException
{
if(arg instanceof Number)
return ((Number)arg).doubleValue();
else if(arg instanceof String)
return Double.parseDouble((String)arg);
else
throw new FactorDomainException(arg,double.class);
} //}}}
//{{{ toClass() method
public static Class toClass(Object arg)
throws Exception
{
if(arg instanceof Class)
return (Class)arg;
else
{
return getClass((String)
convertToJavaType(arg,String.class));
}
} //}}}
//{{{ toArray() method
public static Object[] toArray(Object arg)
throws FactorDomainException
{
return toArray(arg,Object.class);
} //}}}
//{{{ toArray() method
public static Object[] toArray(Object arg, Class clas)
throws FactorDomainException
{
if(arg instanceof FactorList)
{
FactorList list = (FactorList)arg;
Object[] array = (Object[])
Array.newInstance(
clas.getComponentType(),
list.length());
list.toArray(array);
return array;
}
else if(arg.getClass().isArray())
return (Object[])arg;
else
throw new FactorDomainException(arg,Object[].class);
} //}}}
//{{{ convertToJavaType() method
public static Object convertToJavaType(Object arg, Class clas)
throws Exception
{
if(clas == Object.class)
return arg;
else if(clas == Number.class)
{
return toNumber(arg);
}
else if(clas == String.class)
{
return toString(arg);
}
else if(clas == boolean.class)
{
return toBoolean(arg)
? Boolean.TRUE
: Boolean.FALSE;
}
else if(clas == char.class)
{
return new Character(toChar(arg));
}
else if(clas == int.class)
{
return new Integer(toInt(arg));
}
else if(clas == long.class)
{
return new Long(toLong(arg));
}
else if(clas == float.class)
{
return new Float(toFloat(arg));
}
else if(clas == double.class)
{
return new Double(toDouble(arg));
}
else if(clas == Class.class)
{
return toClass(arg);
}
else if(clas.isArray())
{
return toArray(arg,clas);
}
if(arg != null && !clas.isInstance(arg))
throw new FactorDomainException(arg,clas);
else
return arg;
} //}}}
//{{{ fromBoolean() method
public static Object fromBoolean(boolean b)
{
return (b ? Boolean.TRUE : null);
} //}}}
//{{{ convertFromJavaType() method
public static Object convertFromJavaType(Object arg)
{
if(Boolean.FALSE.equals(arg))
return null;
else
return arg;
} //}}}
//{{{ factorTypeToString() method
public static String factorTypeToString(Object obj)
{
// this is for string representations of lists and stacks
if(obj == null || obj.equals(Boolean.FALSE))
return "f";
else if(obj.equals(Boolean.TRUE))
return "t";
else if(obj instanceof String)
return '"' + obj.toString() + '"'; //XXX: escape
else if(obj instanceof Number
|| obj instanceof FactorExternalizable)
return obj.toString();
else if(obj instanceof Character)
return "#\\" + ((Character)obj).charValue();
else
return "(" + obj + ")";
} //}}}
//{{{ javaClassToVMClass() method
public static String javaClassToVMClass(Class clazz)
{
String name = clazz.getName();
if(clazz.isArray())
return clazz.getName().replace('.','/');
else if(name.equals("boolean"))
return "Z";
else if(name.equals("byte"))
return "B";
else if(name.equals("char"))
return "C";
else if(name.equals("double"))
return "D";
else if(name.equals("float"))
return "F";
else if(name.equals("int"))
return "I";
else if(name.equals("long"))
return "J";
else if(name.equals("short"))
return "S";
else if(name.equals("void"))
return "V";
else
return "L" + clazz.getName().replace('.','/') + ";";
} //}}}
//{{{ javaBoxingType() method
public static Class javaBoxingType(Class clazz)
{
if(clazz == Byte.TYPE)
return Byte.class;
else if(clazz == Character.TYPE)
return Character.class;
else if(clazz == Double.TYPE)
return Double.class;
else if(clazz == Float.TYPE)
return Float.class;
else if(clazz == Integer.TYPE)
return Integer.class;
else if(clazz == Long.TYPE)
return Long.class;
else if(clazz == Short.TYPE)
return Short.class;
else
return null;
} //}}}
//{{{ javaSignatureToVMSignature() method
public static String javaSignatureToVMSignature(Class[] args,
Class returnType)
{
StringBuffer buf = new StringBuffer("(");
for(int i = 0; i < args.length; i++)
{
buf.append(javaClassToVMClass(args[i]));
}
buf.append(")");
buf.append(javaClassToVMClass(returnType));
return buf.toString();
} //}}}
//{{{ getClass() method
public static Class getClass(String name) throws ClassNotFoundException
{
if(name.equals("boolean"))
return Boolean.TYPE;
else if(name.equals("byte"))
return Byte.TYPE;
else if(name.equals("char"))
return Character.TYPE;
else if(name.equals("double"))
return Double.TYPE;
else if(name.equals("float"))
return Float.TYPE;
else if(name.equals("int"))
return Integer.TYPE;
else if(name.equals("long"))
return Long.TYPE;
else if(name.equals("short"))
return Short.TYPE;
else
return Class.forName(name);
} //}}}
//{{{ jconstructor() method
public static Constructor jconstructor(String inClass, FactorList args)
throws Exception
{
return Class.forName(inClass).getConstructor(
classNameToClassList(args));
} //}}}
//{{{ jfield() method
public static Field jfield(String field, String inClass)
throws Exception
{
return Class.forName(inClass).getField(field);
} //}}}
//{{{ jinvoke() method
public static void jinvoke(FactorDataStack stack, Method method,
Object instance) throws Exception
{
if(instance != null)
{
instance = convertToJavaType(instance,
method.getDeclaringClass());
}
Class[] paramTypes = method.getParameterTypes();
Object[] args = new Object[paramTypes.length];
try
{
for(int i = args.length - 1; i >= 0; i--)
{
args[i] = convertToJavaType(stack.pop(),
paramTypes[i]);
}
if(Modifier.isStatic(method.getModifiers()))
{
if(instance != null)
throw new FactorRuntimeException(
"Use jinvokeStatic with static methods");
}
else
{
if(instance == null)
throw new FactorRuntimeException(
"Cannot jinvoke on f");
}
if(method.getReturnType() == Void.TYPE)
method.invoke(instance,args);
else
{
stack.push(convertFromJavaType(
method.invoke(instance,args)));
}
}
catch(FactorStackException e)
{
throw new FactorStackException(paramTypes.length);
}
} //}}}
//{{{ jinvokeStatic() method
public static void jinvokeStatic(FactorDataStack stack, Method method)
throws Exception
{
jinvoke(stack,method,null);
} //}}}
//{{{ jmethod() method
public static Method jmethod(String method, String inClass,
FactorList args) throws Exception
{
return Class.forName(inClass).getMethod(method,
classNameToClassList(args));
} //}}}
//{{{ jnew() method
public static void jnew(FactorDataStack stack, Constructor method)
throws Exception
{
Class[] paramTypes = method.getParameterTypes();
Object[] args = new Object[paramTypes.length];
for(int i = args.length - 1; i >= 0; i--)
{
args[i] = convertToJavaType(stack.pop(),
paramTypes[i]);
}
stack.push(method.newInstance(args));
} //}}}
//{{{ jvarGet() method
public static Object jvarGet(Field field, Object obj) throws Exception
{
return convertFromJavaType(field.get(obj));
} //}}}
//{{{ jvarGetStatic() method
public static Object jvarGetStatic(Field field) throws Exception
{
return convertFromJavaType(field.get(null));
} //}}}
//{{{ jvarSet() method
public static void jvarSet(Field field, Object obj, Object value)
throws Exception
{
field.set(obj,convertToJavaType(value,field.getType()));
} //}}}
//{{{ jvarSetStatic() method
public static void jvarSetStatic(Field field, Object value)
throws Exception
{
field.set(null,convertToJavaType(value,field.getType()));
} //}}}
//{{{ unwrapException() method
public static Throwable unwrapException(Throwable e)
{
if(e instanceof InvocationTargetException)
{
return unwrapException(
((InvocationTargetException)e)
.getTargetException());
}
else if(e.getCause() != null)
return unwrapException(e.getCause());
else
return e;
} //}}}
}

255
factor/FactorLib.java Normal file
View File

@ -0,0 +1,255 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.io.*;
/**
* A few useful words.
*/
public class FactorLib
{
//{{{ branch2() method
public static Object branch2(boolean condition, Object o1, Object o2)
{
return (condition ? o1 : o2);
} //}}}
//{{{ branch3() method
public static Object branch3(float x, float y,
Object o1, Object o2, Object o3)
{
if(x > y)
return o1;
else if(x == y)
return o2;
else
return o3;
} //}}}
//{{{ cat() method
public static String cat(FactorList list)
{
StringBuffer buf = new StringBuffer();
while(list != null)
{
if(list.car instanceof FactorList)
buf.append(cat((FactorList)list.car));
else
buf.append(list.car);
list = list.next();
}
return buf.toString();
} //}}}
//{{{ cat2() method
public static String cat2(Object str1, Object str2)
{
return new StringBuffer().append(str1).append(str2).toString();
} //}}}
//{{{ cat3() method
public static String cat3(Object str1, Object str2, Object str3)
{
return new StringBuffer().append(str1).append(str2).append(str3)
.toString();
} //}}}
//{{{ cloneArray() method
public static Object[] cloneArray(Object[] array)
{
Object[] newArray = new Object[array.length];
System.arraycopy(array,0,newArray,0,array.length);
return newArray;
} //}}}
//{{{ deepCloneArray() method
public static Object[] deepCloneArray(Object[] array)
{
Object[] newArray = new Object[array.length];
for(int i = 0; i < array.length; i++)
{
Object o = array[i];
if(o instanceof PublicCloneable)
newArray[i] = ((PublicCloneable)o).clone();
else
newArray[i] = o;
}
return newArray;
} //}}}
//{{{ error() method
public static void error(String str) throws FactorRuntimeException
{
throw new FactorRuntimeException(str);
} //}}}
//{{{ equal() method
public static boolean equal(Object o1, Object o2)
{
if(o1 == null)
return o2 == null;
else if(o1 instanceof Number
&& o2 instanceof Number
&& o1.getClass() != o2.getClass())
{
// to compare different types of numbers, cast to a
// double first
return ((Number)o1).doubleValue()
== ((Number)o2).doubleValue();
}
else if(o1 instanceof Number
&& o2 instanceof String)
{
try
{
return Double.parseDouble((String)o2)
== ((Number)o1).doubleValue();
}
catch(NumberFormatException nf)
{
return false;
}
}
else if(o1 instanceof String
&& o2 instanceof Number)
{
try
{
return Double.parseDouble((String)o1)
== ((Number)o2).doubleValue();
}
catch(NumberFormatException nf)
{
return false;
}
}
else
return o1.equals(o2);
} //}}}
//{{{ exec() method
public static int exec(String[] args) throws Exception
{
int exitCode = -1;
try
{
Process process = Runtime.getRuntime().exec(args);
process.getInputStream().close();
process.getOutputStream().close();
process.getErrorStream().close();
exitCode = process.waitFor();
}
catch(Exception e)
{
e.printStackTrace();
// this needs to be handled better
/* stack.push(MiscUtilities.throwableToString(e));
Console.print(stack,namespace); */
}
return exitCode;
} //}}}
//{{{ objectsEqual() method
/**
* Returns if two objects are equal. This correctly handles null
* pointers, as opposed to calling <code>o1.equals(o2)</code>.
*/
public static boolean objectsEqual(Object o1, Object o2)
{
if(o1 == null)
{
if(o2 == null)
return true;
else
return false;
}
else if(o2 == null)
return false;
else
return o1.equals(o2);
} //}}}
//{{{ copy() method
/**
* Copies the contents of an input stream to an output stream.
*/
public static void copy(InputStream in, OutputStream out)
throws IOException
{
byte[] buf = new byte[4096];
int count;
for(;;)
{
count = in.read(buf,0,buf.length);
if(count == -1 || count == 0)
break;
out.write(buf,0,count);
}
in.close();
out.close();
} //}}}
//{{{ readLine() method
/**
* Reads a line of text from the given input stream.
*/
public static String readLine(InputStream in) throws IOException
{
StringBuffer buf = new StringBuffer();
int b;
while((b = in.read()) != -1)
{
if(b == '\n')
{
if(in.markSupported() && in.available() >= 1)
{
in.mark(1);
b = in.read();
if(b != '\r')
in.reset();
}
break;
}
else if(b == '\r')
break;
buf.append((char)b);
}
return buf.toString();
} //}}}
}

347
factor/FactorList.java Normal file
View File

@ -0,0 +1,347 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.util.LinkedList;
import java.util.List;
/**
* Used to build up linked lists.
*/
public class FactorList implements PublicCloneable, FactorExternalizable
{
public static int COUNT;
public Object car;
public Object cdr;
//{{{ FactorList constructor
public FactorList(Object car, Object cdr)
{
this.car = car;
this.cdr = cdr;
COUNT++;
} //}}}
//{{{ car() method
public Object car(Class clas) throws Exception
{
return FactorJava.convertToJavaType(car,clas);
} //}}}
//{{{ cdr() method
public Object cdr(Class clas) throws Exception
{
return FactorJava.convertToJavaType(cdr,clas);
} //}}}
//{{{ next() method
public FactorList next()
{
return (FactorList)cdr;
} //}}}
//{{{ get() method
public Object get(int index)
{
return _get(index).car;
} //}}}
//{{{ _get() method
public FactorList _get(int index)
{
FactorList iter = this;
while(index != 0)
{
iter = (FactorList)iter.cdr;
index--;
}
return iter;
} //}}}
//{{{ contains() method
public boolean contains(Object obj)
{
FactorList iter = this;
while(iter != null)
{
if(FactorLib.objectsEqual(obj,iter.car))
return true;
iter = iter.next();
}
return false;
} //}}}
//{{{ set() method
/**
* Returns a new list where the item at the given index is changed.
*/
public FactorList set(int index, Object car, Object cdr)
{
if(index == 0)
return new FactorList(car,cdr);
else
{
return new FactorList(this.car,
this.next().set(index - 1,car,cdr));
}
} //}}}
//{{{ set() method
/**
* Returns a new list containing the first n elements of this list.
*/
public FactorList head(int n)
{
if(n == 0)
return null;
else if(cdr == null && n == 1)
return this;
else
{
FactorList head = next().head(n - 1);
if(head == cdr)
return this;
else
return new FactorList(car,head);
}
} //}}}
//{{{ length() method
public int length()
{
int size = 0;
FactorList iter = this;
while(iter != null)
{
iter = (FactorList)iter.cdr;
size++;
}
return size;
} //}}}
//{{{ append() method
public FactorList append(FactorList list)
{
if(list == null)
return this;
FactorList returnValue = null;
FactorList end = null;
FactorList iter = this;
for(;;)
{
FactorList cons = new FactorList(iter.car,null);
if(end != null)
end.cdr = cons;
end = cons;
if(returnValue == null)
returnValue = cons;
if(iter.cdr == null)
{
end.cdr = list;
break;
}
else
iter = iter.next();
}
return returnValue;
} //}}}
//{{{ reverse() method
public FactorList reverse()
{
FactorList returnValue = null;
FactorList iter = this;
while(iter != null)
{
returnValue = new FactorList(iter.car,returnValue);
iter = iter.next();
}
return returnValue;
} //}}}
//{{{ isProperList() method
public boolean isProperList()
{
return cdr == null || (cdr instanceof FactorList
&& ((FactorList)cdr).isProperList());
} //}}}
//{{{ elementsToString() method
/**
* Returns a whitespace separated string of the toString() of each
* item.
*/
public String elementsToString()
{
StringBuffer buf = new StringBuffer();
FactorList iter = this;
while(iter != null)
{
if(iter.car == this)
buf.append("<circular reference>");
else
buf.append(FactorJava.factorTypeToString(iter.car));
if(iter.cdr instanceof FactorList)
{
buf.append(' ');
iter = (FactorList)iter.cdr;
continue;
}
else if(iter.cdr == null)
break;
else
{
buf.append(" , ");
buf.append(FactorJava.factorTypeToString(iter.cdr));
iter = null;
}
}
return buf.toString();
} //}}}
//{{{ toString() method
/**
* Returns elementsToString() enclosed with [ and ].
*/
public String toString()
{
return "[ " + elementsToString() + " ]";
} //}}}
//{{{ toJavaList() method
public List toJavaList()
{
LinkedList returnValue = new LinkedList();
FactorList iter = this;
while(iter != null)
{
returnValue.add(iter.car);
iter = (FactorList)iter.cdr;
}
return returnValue;
} //}}}
//{{{ toArray() method
/**
* Note that unlike Java list toArray(), the given array must already
* be the right size.
*/
public Object[] toArray(Object[] returnValue)
{
int i = 0;
FactorList iter = this;
while(iter != null)
{
returnValue[i++] = iter.car;
iter = iter.next();
}
return returnValue;
} //}}}
//{{{ fromArray() method
public static FactorList fromArray(Object[] array)
{
if(array == null || array.length == 0)
return null;
else
{
FactorList first = new FactorList(array[0],null);
FactorList last = first;
for(int i = 1; i < array.length; i++)
{
FactorList cons = new FactorList(array[i],null);
last.cdr = cons;
last = cons;
}
return first;
}
} //}}}
//{{{ equals() method
public boolean equals(Object o)
{
if(o instanceof FactorList)
{
FactorList l = (FactorList)o;
return FactorLib.objectsEqual(car,l.car)
&& FactorLib.objectsEqual(cdr,l.cdr);
}
else
return false;
} //}}}
//{{{ hashCode() method
public int hashCode()
{
if(car == null)
return 0;
else
return car.hashCode();
} //}}}
//{{{ clone() method
public Object clone()
{
if(cdr instanceof FactorList)
return new FactorList(car,((FactorList)cdr).clone());
else
return new FactorList(car,cdr);
} //}}}
//{{{ deepClone() method
public Object deepClone()
{
Object ccar;
if(car instanceof PublicCloneable)
ccar = ((PublicCloneable)car).clone();
else
ccar = car;
if(cdr instanceof FactorList)
{
return new FactorList(ccar,next().deepClone());
}
else if(cdr == null)
{
return new FactorList(ccar,null);
}
else
{
Object ccdr;
if(cdr instanceof PublicCloneable)
ccdr = ((PublicCloneable)cdr).clone();
else
ccdr = cdr;
return new FactorList(ccar,ccdr);
}
} //}}}
}

363
factor/FactorMath.java Normal file
View File

@ -0,0 +1,363 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.math.*;
import java.util.Random;
/**
* Math-related words.
*/
public class FactorMath
{
private static Random random = new Random();
//{{{ add() method
public static Number add(Number x, Number y)
{
if(x instanceof FactorRatio)
return ((FactorRatio)x).add(y);
else if(y instanceof FactorRatio)
return ((FactorRatio)y).add(x);
else if(x instanceof Integer)
{
int _x = ((Integer)x).intValue();
if(y instanceof Integer)
{
int _y = ((Integer)y).intValue();
long result = (long)_x + (long)_y;
if(result > Integer.MAX_VALUE
|| result < Integer.MIN_VALUE)
{
return BigInteger.valueOf(result);
}
else
{
return new Integer((int)result);
}
}
else if(y instanceof BigInteger)
{
return BigInteger.valueOf(_x)
.add((BigInteger)y);
}
}
else if(x instanceof BigInteger)
{
BigInteger _x = (BigInteger)x;
if(y instanceof Integer)
{
return _x.add(BigInteger.valueOf(
((Integer)y).intValue()));
}
else if(y instanceof BigInteger)
return _x.add((BigInteger)y);
}
return new Double(
((Number)x).doubleValue()
+ ((Number)y).doubleValue());
} //}}}
//{{{ _divide() method
/**
* Truncating division.
*/
public static Number _divide(Number x, Number y)
{
if(x instanceof Integer)
{
int _x = ((Integer)x).intValue();
if(y instanceof Integer)
{
int _y = ((Integer)y).intValue();
return new Integer(_x / _y);
}
else if(y instanceof BigInteger)
{
return BigInteger.valueOf(_x)
.divide((BigInteger)y);
}
}
else if(x instanceof BigInteger)
{
BigInteger _x = (BigInteger)x;
if(y instanceof Integer)
{
return _x.divide(BigInteger.valueOf(
((Integer)y).intValue()));
}
else if(y instanceof BigInteger)
return _x.divide((BigInteger)y);
}
return new Double(
((Number)x).doubleValue()
/ ((Number)y).doubleValue());
} //}}}
//{{{ divide() method
public static Number divide(Number x, Number y)
{
if(x instanceof FactorRatio)
return ((FactorRatio)x).divide(y);
else if(y instanceof FactorRatio)
return ((FactorRatio)y)._divide(x);
else if(
(x instanceof Integer
|| x instanceof BigInteger)
&&
(y instanceof Integer
|| y instanceof BigInteger))
{
return FactorRatio.reduce(x,y);
}
return new Double(
((Number)x).doubleValue()
/ ((Number)y).doubleValue());
} //}}}
//{{{ gcd() method
public static Number gcd(Number x, Number y)
{
if(x instanceof BigInteger)
{
BigInteger _x = (BigInteger)x;
if(y instanceof BigInteger)
return _x.gcd((BigInteger)y);
else
{
return _x.gcd(BigInteger.valueOf(
y.longValue()));
}
}
else
{
BigInteger _x = BigInteger.valueOf(x.longValue());
if(y instanceof BigInteger)
return _x.gcd((BigInteger)y);
else
{
return _x.gcd(BigInteger.valueOf(
y.longValue()));
}
}
} //}}}
//{{{ is1() method
public static boolean is1(Number x)
{
if(x instanceof BigInteger)
return x.equals(BigInteger.ONE);
else if(x instanceof Integer)
return x.intValue() == 1;
else
return x.floatValue() == 1.0f;
} //}}}
//{{{ greater() method
public static boolean greater(float x, float y)
{
return x > y;
} //}}}
//{{{ greaterEqual() method
public static boolean greaterEqual(float x, float y)
{
return x >= y;
} //}}}
//{{{ less() method
public static boolean less(float x, float y)
{
return x < y;
} //}}}
//{{{ lessEqual() method
public static boolean lessEqual(float x, float y)
{
return x <= y;
} //}}}
//{{{ multiply() method
public static Number multiply(Number x, Number y)
{
if(x instanceof FactorRatio)
return ((FactorRatio)x).multiply(y);
else if(y instanceof FactorRatio)
return ((FactorRatio)y).multiply(x);
else if(x instanceof Integer)
{
int _x = ((Integer)x).intValue();
if(y instanceof Integer)
{
int _y = ((Integer)y).intValue();
long result = (long)_x * (long)_y;
if(result > Integer.MAX_VALUE
|| result < Integer.MIN_VALUE)
{
return BigInteger.valueOf(result);
}
else
{
return new Integer((int)result);
}
}
else if(y instanceof BigInteger)
{
return BigInteger.valueOf(_x)
.multiply((BigInteger)y);
}
}
else if(x instanceof BigInteger)
{
BigInteger _x = (BigInteger)x;
if(y instanceof Integer)
{
return _x.multiply(BigInteger.valueOf(
((Integer)y).intValue()));
}
else if(y instanceof BigInteger)
return _x.multiply((BigInteger)y);
}
return new Double(
((Number)x).doubleValue()
* ((Number)y).doubleValue());
} //}}}
//{{{ randomAngle() method
public static float randomAngle()
{
return (float)Math.PI * randomInt(0,360) / 180;
} //}}}
//{{{ randomBoolean() method
public static boolean randomBoolean()
{
return random.nextBoolean();
} //}}}
//{{{ randomInt() method
public static int randomInt(int min, int max)
{
if(min == max)
return min;
int nextInt = random.nextInt();
return min + Math.abs(nextInt % (max - min + 1));
} //}}}
//{{{ sgn() method
public static int sgn(float num)
{
if(num < 0.0f)
return -1;
else if(num == 0.0f)
return 0;
else
return 1;
} //}}}
//{{{ sgn() method
public static int sgn(Number num)
{
if(num instanceof FactorRatio)
return sgn(((FactorRatio)num).numerator);
else if(num instanceof BigInteger)
return ((BigInteger)num).signum();
else
{
double value = num.doubleValue();
if(value < 0.0)
return -1;
else if(value == 0.0)
return 0;
else
return 1;
}
} //}}}
//{{{ subtract() method
public static Number subtract(Number x, Number y)
{
if(x instanceof FactorRatio)
return ((FactorRatio)x).subtract(y);
else if(y instanceof FactorRatio)
return ((FactorRatio)y)._subtract(x);
else if(x instanceof Integer)
{
int _x = ((Integer)x).intValue();
if(y instanceof Integer)
{
int _y = ((Integer)y).intValue();
long result = (long)_x - (long)_y;
if(result > Integer.MAX_VALUE
|| result < Integer.MIN_VALUE)
{
return BigInteger.valueOf(result);
}
else
{
return new Integer((int)result);
}
}
else if(y instanceof BigInteger)
{
return BigInteger.valueOf(_x)
.subtract((BigInteger)y);
}
}
else if(x instanceof BigInteger)
{
BigInteger _x = (BigInteger)x;
if(y instanceof Integer)
{
return _x.subtract(BigInteger.valueOf(
((Integer)y).intValue()));
}
else if(y instanceof BigInteger)
return _x.subtract((BigInteger)y);
}
return new Double(
((Number)x).doubleValue()
- ((Number)y).doubleValue());
} //}}}
}

View File

@ -0,0 +1,52 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
/**
* A placeholder for an undefined word.
*/
public class FactorMissingDefinition extends FactorWordDefinition
{
public static final FactorMissingDefinition INSTANCE
= new FactorMissingDefinition();
//{{{ eval() method
public void eval(FactorWord word, FactorInterpreter interp)
throws FactorUndefinedWordException
{
throw new FactorUndefinedWordException(word);
} //}}}
//{{{ toString() method
public String toString()
{
return "undefined";
} //}}}
}

336
factor/FactorNamespace.java Normal file
View File

@ -0,0 +1,336 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.TreeMap;
import java.util.Iterator;
import java.util.Map;
import java.util.LinkedList;
import java.util.List;
/**
* Manages the set of available words.
*/
public class FactorNamespace implements PublicCloneable
{
private static FactorWord NULL = new FactorWord("(represent-f)");
private static FactorWord CHECK_PARENT = new FactorWord("(check-parent)");
public Object obj;
private FactorNamespace parent;
private Map words;
//{{{ FactorNamespace constructor
public FactorNamespace(FactorNamespace parent) throws Exception
{
this(parent,null,null);
} //}}}
//{{{ FactorNamespace constructor
public FactorNamespace(FactorNamespace parent, Object obj) throws Exception
{
this(parent,null,obj);
} //}}}
//{{{ FactorNamespace constructor
/**
* Cloning constructor.
*/
public FactorNamespace(FactorNamespace parent, Map words, Object obj)
throws Exception
{
this.parent = parent;
this.words = new TreeMap();
// used by clone()
if(words != null)
{
Iterator iter = words.entrySet().iterator();
while(iter.hasNext())
{
Map.Entry entry = (Map.Entry)iter.next();
Object key = entry.getKey();
Object value = entry.getValue();
if(!(value instanceof VarBinding))
this.words.put(key,value);
}
}
try
{
setVariable("namespace",this);
setVariable("parent",parent);
}
catch(Exception e)
{
e.printStackTrace();
}
if(obj != null)
{
this.obj = obj;
setVariable("this",obj);
}
} //}}}
//{{{ getParent() method
public FactorNamespace getParent()
{
return parent;
} //}}}
//{{{ importVars() method
/**
* Defines a variable bound to a Java field.
*/
public void importVars(String clazz, FactorList vars)
throws Exception
{
Class clas = Class.forName(clazz);
while(vars != null)
{
String field = (String)vars.car(String.class);
vars = vars.next();
String word = (String)vars.car(String.class);
setVariable(word,new VarBinding(
clas.getField(field),
null));
vars = vars.next();
}
} //}}}
//{{{ getVariable() method
public Object getVariable(String name) throws Exception
{
Object o = words.get(name);
if(o instanceof VarBinding)
return ((VarBinding)o).get();
else if(o == NULL)
return null;
else if(o == CHECK_PARENT)
{
// we know this is not a field binding
return parent == null ? null
: parent.getVariable(name);
}
else if(o == null)
{
// lazily instantiate object field binding
lazyFieldInit(name);
return getVariable(name);
}
else
return o;
} //}}}
//{{{ _setVariable() method
/**
* Alternative form for bindings.
*/
public void _setVariable(Object value, String name)
throws Exception
{
setVariable(name,value);
} //}}}
//{{{ setVariable() method
public void setVariable(String name, Object value)
throws Exception
{
Object o = words.get(name);
if(o instanceof VarBinding && !(value instanceof VarBinding))
((VarBinding)o).set(value);
else if(o == null)
{
// lazily instantiate object field binding
lazyFieldInit(name);
setVariable(name,value);
return;
}
else if(value == null)
words.put(name,NULL);
else
words.put(name,value);
} //}}}
//{{{ lazyFieldInit() method
private void lazyFieldInit(String name)
{
if(obj != null)
{
try
{
Field f = obj.getClass().getField(name);
if(!Modifier.isStatic(f.getModifiers()))
{
words.put(name,new VarBinding(f,obj));
return;
}
}
catch(Exception e)
{
}
}
// not a field, don't check again
words.put(name,CHECK_PARENT);
} //}}}
//{{{ toVarList() method
/**
* Returns a list of variable and word names defined in this namespace.
*/
public FactorList toVarList()
{
FactorList first = null;
FactorList last = null;
Iterator iter = words.entrySet().iterator();
while(iter.hasNext())
{
Map.Entry entry = (Map.Entry)iter.next();
if(entry.getValue() == CHECK_PARENT)
continue;
String name = (String)entry.getKey();
FactorList cons = new FactorList(name,null);
if(first == null)
first = last = cons;
else
{
last.cdr = cons;
last = cons;
}
}
return first;
} //}}}
//{{{ toValueList() method
/**
* Returns a list of pairs of variable and word names, and their values.
*/
public FactorList toValueList()
{
FactorList first = null;
FactorList last = null;
Iterator iter = words.entrySet().iterator();
while(iter.hasNext())
{
Map.Entry entry = (Map.Entry)iter.next();
if(entry.getValue() == CHECK_PARENT)
continue;
FactorList cons = new FactorList(
new FactorList(entry.getKey(),
entry.getValue()),null);
if(first == null)
first = last = cons;
else
{
last.cdr = cons;
last = cons;
}
}
return first;
} //}}}
//{{{ VarBinding class
/**
* This is messy.
*/
static class VarBinding
{
private Field field;
private Object instance;
VarBinding(Field field, Object instance)
throws FactorRuntimeException
{
this.field = field;
this.instance = instance;
}
Object get() throws Exception
{
return FactorJava.jvarGet(field,instance);
}
void set(Object value) throws Exception
{
FactorJava.jvarSet(field,instance,value);
}
} //}}}
//{{{ toString() method
public String toString()
{
return "Namespace[" + obj + "]";
} //}}}
//{{{ clone() method
public FactorNamespace clone(Object rebind)
{
if(rebind.getClass() != obj.getClass())
throw new RuntimeException("Cannot rebind to different type");
try
{
return new FactorNamespace(parent,words,rebind);
}
catch(Exception e)
{
throw new InternalError();
}
} //}}}
//{{{ clone() method
public Object clone()
{
if(obj != null)
throw new RuntimeException("Cannot clone namespace that's bound to an object");
try
{
return new FactorNamespace(parent,new TreeMap(words),null);
}
catch(Exception e)
{
throw new InternalError();
}
} //}}}
}

35
factor/FactorObject.java Normal file
View File

@ -0,0 +1,35 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public interface FactorObject
{
FactorNamespace getNamespace(FactorInterpreter interp) throws Exception;
}

View File

@ -0,0 +1,38 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public class FactorParseException extends FactorException
{
public FactorParseException(String filename, int lineno, String str)
{
super(filename + ":" + lineno + ":" + str);
}
}

540
factor/FactorParser.java Normal file
View File

@ -0,0 +1,540 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.io.*;
import java.util.HashMap;
public class FactorParser
{
private static final Object EOF = new Object();
private FactorWord DEF;
private FactorWord INE;
private FactorWord SHU;
private FactorWord F;
private FactorWord FLE;
private FactorWord DEFINE;
private FactorWord BRA;
private FactorWord KET;
private FactorWord COMMA;
private String filename;
private Reader in;
private FactorDictionary dict;
private StreamTokenizer st;
// sometimes one token is expanded into two words
private Object next;
//{{{ FactorParser constructor
public FactorParser(String filename, Reader in, FactorDictionary dict)
{
this.filename = (filename == null ? "<eval>" : filename);
this.in = in;
this.dict = dict;
DEF = dict.intern(":");
INE = dict.intern(";");
SHU = dict.intern("~<<");
F = dict.intern("--");
FLE = dict.intern(">>~");
DEFINE = dict.intern("define");
BRA = dict.intern("[");
KET = dict.intern("]");
COMMA = dict.intern(",");
st = new StreamTokenizer(in);
st.resetSyntax();
st.whitespaceChars(0,' ');
/* all printable ASCII characters */
st.wordChars('#','~');
st.wordChars('0','9');
st.commentChar('!');
st.quoteChar('"');
st.commentChar('(');
st.eolIsSignificant(false);
} //}}}
//{{{ isParsingWord() method
private boolean isParsingWord(Object word)
{
return word == DEF
|| word == INE
|| word == SHU
|| word == FLE
|| word == BRA
|| word == KET
|| word == COMMA;
} //}}}
//{{{ parse() method
/**
* Reads the file being parsed, and returns a list of all tokens that
* were read in. This list can be evaluated to run the file.
*/
public FactorList parse() throws IOException, FactorParseException
{
FactorList first = null;
FactorList last = null;
try
{
for(;;)
{
Object next = next();
if(next == EOF)
return first;
/* : foo bar baz ; is equivalent to
"foo" [ bar baz ] define */
else if(next == DEF)
{
Object obj = next();
if(!(obj instanceof FactorWord)
|| isParsingWord(obj))
{
error("Expected word name after " + next);
}
FactorWordDefinition def = readDef();
FactorList l = new FactorList(DEFINE,null);
FactorList cons = new FactorList(
((FactorWord)obj).name,
new FactorList(def,l));
if(first == null)
first = cons;
else
last.cdr = cons;
last = l;
}
else if(next == SHU)
{
Object obj = next();
if(!(obj instanceof FactorWord)
|| isParsingWord(obj))
{
error("Expected word name after " + next);
}
FactorWordDefinition def = readShuffle();
FactorList l = new FactorList(DEFINE,null);
FactorList cons = new FactorList(
((FactorWord)obj).name,
new FactorList(def,l));
if(first == null)
first = cons;
else
last.cdr = cons;
last = l;
}
else if(next == BRA)
{
FactorList cons = new FactorList(
readList(),null);
if(first == null)
first = cons;
else
last.cdr = cons;
last = cons;
}
else if(isParsingWord(next))
{
error("Unexpected " + next);
}
else
{
FactorList cons = new FactorList(next,null);
if(first == null)
first = cons;
else
last.cdr = cons;
last = cons;
}
}
}
finally
{
try
{
in.close();
}
catch(IOException io)
{
}
}
} //}}}
//{{{ next() method
private Object next() throws IOException, FactorParseException
{
if(next != null)
{
Object _next = next;
next = null;
return _next;
}
int type = st.nextToken();
switch(type)
{
case StreamTokenizer.TT_EOF:
return EOF;
case StreamTokenizer.TT_WORD:
boolean number = true;
boolean floating = false;
boolean exponent = false;
for(int i = 0; i < st.sval.length(); i++)
{
char ch = st.sval.charAt(i);
if(ch == '-')
{
if((i != 0 && Character.toLowerCase(
st.sval.charAt(i - 1))
!= 'e') || st.sval.length() == 1)
{
number = false;
break;
}
}
else if((ch == 'e' || ch == 'E')
&& st.sval.length() != 1)
{
if(exponent)
{
number = false;
break;
}
else
exponent = true;
}
else if(ch == '.' && st.sval.length() != 1)
{
if(floating)
{
number = false;
break;
}
else
floating = true;
}
else if(!Character.isDigit(ch))
{
number = false;
break;
}
}
if(number)
{
if(floating || exponent)
return new Float(st.sval);
else
return new Integer(st.sval);
}
if(st.sval.length() == 1)
{
switch(st.sval.charAt(0))
{
case 'f':
return null;
case 't':
return Boolean.TRUE;
}
}
else if(st.sval.startsWith("#\\"))
return toChar(st.sval.substring(2));
else
{
// $foo is expanded into "foo" $
if(st.sval.charAt(0) == '$')
{
next = dict.intern("$");
return st.sval.substring(1);
}
// @foo is expanded into "foo" @
else if(st.sval.charAt(0) == '@')
{
next = dict.intern("@");
return st.sval.substring(1);
}
}
// |foo is the same as "foo"
if(st.sval.charAt(0) == '|')
return st.sval.substring(1);
return dict.intern(st.sval);
case '"': case '\'':
return st.sval;
default:
throw new FactorParseException(filename,
st.lineno(),"Unknown error: " + type);
}
} //}}}
//{{{ toChar() method
private Character toChar(String spec) throws FactorParseException
{
if(spec.length() != 1)
error("Not a character literal: #\\" + spec);
return new Character(spec.charAt(0));
} //}}}
//{{{ readDef() method
/**
* Read list until ;.
*/
private FactorWordDefinition readDef()
throws IOException, FactorParseException
{
return new FactorCompoundDefinition(readList(INE,false));
} //}}}
//{{{ readShuffle() method
/**
* Shuffle notation looks like this:
* ~<< a b -- b a >>~
* On the left is inputs, on the right is their arrangement on the
* stack.
*/
private FactorWordDefinition readShuffle()
throws IOException, FactorParseException
{
// 0 in consume map is last consumed, n is first consumed.
HashMap consumeMap = new HashMap();
int consumeD = 0;
int consumeR = 0;
for(;;)
{
Object next = next();
if(next == EOF)
error("Unexpected EOF");
if(next == F)
break;
else if(next instanceof FactorWord)
{
String name = ((FactorWord)next).name;
int counter;
if(name.startsWith("r:"))
{
next = dict.intern(name.substring(2));
counter = (FactorShuffleDefinition
.FROM_R_MASK
| consumeR++);
}
else
counter = consumeD++;
Object existing = consumeMap.put(next,
new Integer(counter));
if(existing != null)
error("Appears twice in shuffle LHS: " + next);
}
else
{
error("Unexpected " + FactorJava.factorTypeToString(
next));
}
}
FactorList _shuffle = readList(FLE,false);
int consume = consumeMap.size();
if(_shuffle == null)
{
return new FactorShuffleDefinition(consumeD,consumeR,
null,0,null,0);
}
int[] shuffle = new int[_shuffle.length()];
int shuffleDlength = 0;
int shuffleRlength = 0;
int i = 0;
while(_shuffle != null)
{
if(_shuffle.car instanceof FactorWord)
{
FactorWord word = ((FactorWord)_shuffle.car);
String name = word.name;
if(name.startsWith("r:"))
word = dict.intern(name.substring(2));
Integer _index = (Integer)consumeMap.get(word);
if(_index == null)
error("Does not appear in shuffle LHS: " + _shuffle.car);
int index = _index.intValue();
if(name.startsWith("r:"))
{
shuffleRlength++;
shuffle[i++] = (index
| FactorShuffleDefinition
.TO_R_MASK);
}
else
{
shuffleDlength++;
shuffle[i++] = index;
}
}
else
{
error("Unexpected " + FactorJava.factorTypeToString(
_shuffle.car));
}
_shuffle = _shuffle.next();
}
int[] shuffleD = new int[shuffleDlength];
int[] shuffleR = new int[shuffleRlength];
int j = 0, k = 0;
for(i = 0; i < shuffle.length; i++)
{
int index = shuffle[i];
if((index & FactorShuffleDefinition.TO_R_MASK)
== FactorShuffleDefinition.TO_R_MASK)
{
index = (index
& ~FactorShuffleDefinition.TO_R_MASK);
shuffleR[j++] = index;
}
else
shuffleD[k++] = index;
}
return new FactorShuffleDefinition(consumeD,consumeR,
shuffleD,shuffleDlength,shuffleR,shuffleRlength);
} //}}}
//{{{ readList() method
/**
* Read list until ].
*/
private FactorList readList()
throws IOException, FactorParseException
{
return readList(KET,true);
} //}}}
//{{{ readList() method
/**
* Read list until a given word.
*/
private FactorList readList(FactorWord until, boolean allowCommaPair)
throws IOException, FactorParseException
{
FactorList first = null;
FactorList last = null;
for(;;)
{
Object next = next();
if(next == until)
return first;
else if(next == EOF)
{
error("Unexpected EOF");
}
// read a dotted pair
else if(allowCommaPair && next == COMMA)
{
if(first == null)
{
error("Expected at least 1 word before " + next);
}
next = next();
if(next == BRA)
{
last.cdr = readList();
next = next();
if(next == EOF)
error("Unexpected EOF");
else if(next != KET)
error("Expected 1 word after ,");
return first;
}
else if(next != EOF && !isParsingWord(next))
{
last.cdr = next;
next = next();
if(next == until)
return first;
}
error("Expected 1 word after ,");
}
else if(next == BRA)
{
FactorList list = readList();
if(first == null)
first = last = new FactorList(list,null);
else
{
FactorList nextList = new FactorList(list,null);
last.cdr = nextList;
last = nextList;
}
}
else if(isParsingWord(next))
error("Unexpected " + next);
else if(first == null)
first = last = new FactorList(next,null);
else
{
FactorList nextList = new FactorList(next,null);
last.cdr = nextList;
last = nextList;
}
}
} //}}}
//{{{ error() method
private void error(String msg) throws FactorParseException
{
throw new FactorParseException(filename,st.lineno(),msg);
} //}}}
}

374
factor/FactorPrimitive.java Normal file
View File

@ -0,0 +1,374 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.lang.reflect.*;
public abstract class FactorPrimitive extends FactorWordDefinition
{
//{{{ P_callstackGet class
static class P_callstackGet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack.push(interp.callstack.clone());
}
} //}}}
//{{{ P_callstackSet class
static class P_callstackSet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.callstack = (FactorCallStack)((FactorCallStack)
interp.datastack.pop(FactorCallStack.class))
.clone();
}
} //}}}
//{{{ P_datastackGet class
static class P_datastackGet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack.push(interp.datastack.clone());
}
} //}}}
//{{{ P_datastackSet class
static class P_datastackSet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack = (FactorDataStack)((FactorDataStack)
interp.datastack.pop(FactorDataStack.class))
.clone();
}
} //}}}
//{{{ P_clear class
static class P_clear extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.datastack.top = 0;
}
} //}}}
//{{{ P_restack class
static class P_restack extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorList list = (FactorList)datastack.pop(FactorList.class);
interp.callstack.push(datastack);
interp.datastack = new FactorDataStack(list);
}
} //}}}
//{{{ P_unstack class
static class P_unstack extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorList unstack = interp.datastack.toList();
interp.datastack = (FactorDataStack)interp.callstack.pop();
interp.datastack.push(unstack);
}
} //}}}
//{{{ P_unwind class
static class P_unwind extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.callstack.top = 0;
}
} //}}}
//{{{ P_jconstructor class
static class P_jconstructor extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jconstructor(
(String)datastack.pop(String.class),
(FactorList)datastack.pop(FactorList.class)));
}
} //}}}
//{{{ P_jfield class
static class P_jfield extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jfield(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class)));
}
} //}}}
//{{{ P_jinvoke class
static class P_jinvoke extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jinvoke(datastack,
(Method)datastack.pop(),
datastack.pop());
}
} //}}}
//{{{ P_jinvokeStatic class
static class P_jinvokeStatic extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jinvokeStatic(datastack,
(Method)datastack.pop());
}
} //}}}
//{{{ P_jmethod class
static class P_jmethod extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jmethod(
(String)datastack.pop(String.class),
(String)datastack.pop(String.class),
(FactorList)datastack.pop(FactorList.class)));
}
} //}}}
//{{{ P_jnew class
static class P_jnew extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jnew(datastack,
(Constructor)datastack.pop());
}
} //}}}
//{{{ P_jvarGet class
static class P_jvarGet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jvarGet(
(Field)datastack.pop(Field.class),
datastack.pop()));
}
} //}}}
//{{{ P_jvarGetStatic class
static class P_jvarGetStatic extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(
FactorJava.jvarGetStatic(
(Field)datastack.pop(Field.class)));
}
} //}}}
//{{{ P_jvarSet class
static class P_jvarSet extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jvarSet(
(Field)datastack.pop(Field.class),
datastack.pop(),
datastack.pop());
}
} //}}}
//{{{ P_jvarSetStatic class
static class P_jvarSetStatic extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorJava.jvarSetStatic(
(Field)datastack.pop(Field.class),
datastack.pop());
}
} //}}}
//{{{ P_get class
static class P_get extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
datastack.push(interp.callframe.namespace.getVariable(
(String)datastack.pop(String.class)));
}
} //}}}
//{{{ P_set class
static class P_set extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
interp.callframe.namespace.setVariable(
(String)datastack.pop(String.class),
datastack.pop());
}
} //}}}
//{{{ P_swap_set class
static class P_swap_set extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
interp.callframe.namespace._setVariable(datastack.pop(),
(String)datastack.pop(String.class));
}
} //}}}
//{{{ P_define class
static class P_define extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorDictionary dict = interp.dict;
// handle old define syntax
Object obj = datastack.pop();
if(obj instanceof FactorList)
obj = new FactorCompoundDefinition((FactorList)obj);
FactorWordDefinition def = (FactorWordDefinition)obj;
FactorWord newWord = interp.dict.intern(
(String)datastack.pop(String.class));
def.precompile(newWord,interp);
try
{
if(interp.compile)
def = def.compile(newWord,interp);
}
catch(Throwable t)
{
System.err.println("WARNING: cannot compile " + newWord);
t.printStackTrace();
}
if(newWord.def != FactorMissingDefinition.INSTANCE)
{
System.err.println("WARNING: redefining " + newWord);
newWord.history = new FactorList(newWord.def,
newWord.history);
}
newWord.def = def;
}
} //}}}
//{{{ P_call class
static class P_call extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
interp.call(word,(FactorList)interp.datastack.pop(
FactorList.class));
}
} //}}}
//{{{ P_bind class
static class P_bind extends FactorPrimitive
{
public void eval(FactorWord word, FactorInterpreter interp)
throws Exception
{
FactorDataStack datastack = interp.datastack;
FactorList code = (FactorList)datastack.pop(FactorList.class);
Object obj = datastack.pop();
FactorNamespace ns;
if(obj instanceof FactorNamespace)
ns = (FactorNamespace)obj;
else if(obj instanceof FactorObject)
{
ns = ((FactorObject)obj).getNamespace(interp);
if(ns == null)
throw new FactorRuntimeException(
obj + " has a null"
+ " namespace");
}
else
{
throw new FactorDomainException(obj,
FactorObject.class);
}
interp.call(word,ns,code);
}
} //}}}
}

286
factor/FactorRatio.java Normal file
View File

@ -0,0 +1,286 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public class FactorRatio extends Number implements FactorExternalizable
{
public final Number numerator, denominator;
//{{{ FactorRatio constructor
/**
* Creates a new ratio.
*/
public FactorRatio(Number numerator, Number denominator)
{
this.numerator = numerator;
this.denominator = denominator;
} //}}}
//{{{ add() method
public Number add(Number num)
{
if(num instanceof FactorRatio)
{
// a c ad + bc
// - + - = -------
// b d bd
FactorRatio r = (FactorRatio)num;
return reduce(
FactorMath.add(
FactorMath.multiply(numerator,r.denominator),
FactorMath.multiply(denominator,r.numerator)),
FactorMath.multiply(denominator,r.denominator));
}
else if(num instanceof Float
|| num instanceof Double)
{
return new Double(doubleValue() + num.doubleValue());
}
else
{
return reduce(
FactorMath.add(numerator,
FactorMath.multiply(denominator,num)),
denominator);
}
} //}}}
//{{{ subtract() method
/**
* this - num
*/
public Number subtract(Number num)
{
if(num instanceof FactorRatio)
{
// a c ad - bc
// - - - = -------
// b d bd
FactorRatio r = (FactorRatio)num;
return reduce(
FactorMath.subtract(
FactorMath.multiply(numerator,r.denominator),
FactorMath.multiply(denominator,r.numerator)),
FactorMath.multiply(denominator,r.denominator));
}
else if(num instanceof Float
|| num instanceof Double)
{
return new Double(doubleValue() - num.doubleValue());
}
else
{
return reduce(
FactorMath.subtract(numerator,
FactorMath.multiply(denominator,num)),
denominator);
}
} //}}}
//{{{ _subtract() method
/**
* num - this
*/
public Number _subtract(Number num)
{
if(num instanceof FactorRatio)
{
// a c bc - ad
// - - - = -------
// b d bd
FactorRatio r = (FactorRatio)num;
return reduce(
FactorMath.subtract(
FactorMath.multiply(denominator,r.numerator),
FactorMath.multiply(numerator,r.denominator)),
FactorMath.multiply(denominator,r.denominator));
}
else if(num instanceof Float
|| num instanceof Double)
{
return new Double(num.doubleValue() - doubleValue());
}
else
{
return reduce(
FactorMath.subtract(FactorMath.multiply(denominator,num),
numerator),
denominator);
}
} //}}}
//{{{ multiply() method
public Number multiply(Number num)
{
if(num instanceof FactorRatio)
{
// a c ac
// - * - = --
// b d bd
FactorRatio r = (FactorRatio)num;
return reduce(
FactorMath.multiply(numerator,r.numerator),
FactorMath.multiply(denominator,r.denominator));
}
else if(num instanceof Float
|| num instanceof Double)
{
return new Double(doubleValue() * num.doubleValue());
}
else
{
return reduce(
FactorMath.multiply(numerator,num),
denominator);
}
} //}}}
//{{{ divide() method
/**
* this / num
*/
public Number divide(Number num)
{
if(num instanceof FactorRatio)
{
// a c ad
// - / - = --
// b d bc
FactorRatio r = (FactorRatio)num;
return reduce(
FactorMath.multiply(numerator,r.denominator),
FactorMath.multiply(denominator,r.numerator));
}
else if(num instanceof Float
|| num instanceof Double)
{
return new Double(doubleValue() / num.doubleValue());
}
else
{
return reduce(numerator,
FactorMath.multiply(denominator,num));
}
} //}}}
//{{{ _divide() method
/**
* num / this
*/
public Number _divide(Number num)
{
if(num instanceof FactorRatio)
{
// c a cb
// - / - = --
// d b da
FactorRatio r = (FactorRatio)num;
return reduce(
FactorMath.multiply(denominator,r.numerator),
FactorMath.multiply(numerator,r.denominator));
}
else if(num instanceof Float
|| num instanceof Double)
{
return new Double(num.doubleValue() / doubleValue());
}
else
{
return reduce(
FactorMath.multiply(denominator,num),
numerator);
}
} //}}}
//{{{ reduce() method
public static Number reduce(Number numerator, Number denominator)
{
/* if(FactorMath.sgn(denominator) == 0)
signal(new DivisionByZero()); */
/* if(FactorMath.sgn(denominator) == -1)
{
numerator = FactorMath.neg(numerator);
denominator = FactorMath.neg(denominator);
} */
Number gcd = FactorMath.gcd(numerator,denominator);
if(!FactorMath.is1(gcd))
{
numerator = FactorMath._divide(numerator,gcd);
denominator = FactorMath._divide(denominator,gcd);
}
if(FactorMath.is1(denominator))
return numerator;
else
return new FactorRatio(numerator,denominator);
} //}}}
//{{{ intValue() method
public int intValue()
{
return (int)doubleValue();
} //}}}
//{{{ longValue() method
public long longValue()
{
return (long)doubleValue();
} //}}}
//{{{ floatValue() method
public float floatValue()
{
return (float)doubleValue();
} //}}}
//{{{ doubleValue() method
public double doubleValue()
{
return numerator.doubleValue() / denominator.doubleValue();
} //}}}
//{{{ byteValue() method
public byte byteValue()
{
return (byte)doubleValue();
} //}}}
//{{{ shortValue() method
public short shortValue()
{
return (short)doubleValue();
} //}}}
//{{{ toString() method
public String toString()
{
return numerator + "/" + denominator;
} //}}}
}

View File

@ -0,0 +1,394 @@
/* :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;
import java.lang.reflect.*;
import org.objectweb.asm.*;
class FactorReflectionForm implements Constants
{
private FactorList form;
//{{{ FactorReflectionForm constructor
FactorReflectionForm(FactorList form)
{
this.form = form;
} //}}}
//{{{ compile() method
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car == dict.jvarGet)
{
return compileVarGet(word,interp,cw,mw,
form.next(),false);
}
else if(form.car == dict.jvarGetStatic)
{
return compileVarGet(word,interp,cw,mw,
form.next(),true);
}
else if(form.car == dict.jinvoke)
{
return compileInvoke(word,interp,cw,mw,
form.next(),false);
}
else if(form.car == dict.jinvokeStatic)
{
return compileInvoke(word,interp,cw,mw,
form.next(),true);
}
else if(form.car == dict.jnew)
{
return compileNew(word,interp,cw,mw,
form.next());
}
else
throw new FactorRuntimeException("Cannot compile " + form.car);
} //}}}
//{{{ compileVarGet() method
private boolean compileVarGet(FactorWord word,
FactorInterpreter interp,
ClassWriter cw,
CodeVisitor mw,
FactorList form,
boolean staticGet) throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car != dict.jfield)
return false;
form = form.next();
String field = (String)form.car;
String clazz = (String)form.next().car;
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
if(!staticGet)
{
mw.visitInsn(DUP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "pop",
"()Ljava/lang/Object;");
}
Class cls = FactorJava.getClass(clazz);
generateFromConversion(mw,cls);
Field fld = cls.getField(field);
clazz = clazz.replace('.','/');
mw.visitFieldInsn(staticGet ? GETSTATIC : GETFIELD,
clazz,
field,
FactorJava.javaClassToVMClass(fld.getType()));
generateToConversion(mw,fld.getType());
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "push",
"(Ljava/lang/Object;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(3,3);
return true;
} //}}}
//{{{ compileInvoke() method
private boolean compileInvoke(FactorWord word,
FactorInterpreter interp,
ClassWriter cw,
CodeVisitor mw,
FactorList form,
boolean staticInvoke) throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car != dict.jmethod)
return false;
form = form.next();
String method = (String)form.car;
String clazz = (String)form.next().car;
Class[] args = FactorJava.classNameToClassList(
(FactorList)form.next().next().car);
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
Class cls = FactorJava.getClass(clazz);
clazz = clazz.replace('.','/');
if(!staticInvoke)
{
mw.visitInsn(DUP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "pop",
"()Ljava/lang/Object;");
generateFromConversion(mw,cls);
if(args.length != 0)
mw.visitInsn(SWAP);
}
generateArgs(mw,args,!staticInvoke);
Method mth = cls.getMethod(method,args);
Class returnType = mth.getReturnType();
int opcode;
if(staticInvoke)
opcode = INVOKESTATIC;
else if(cls.isInterface())
opcode = INVOKEINTERFACE;
else
opcode = INVOKEVIRTUAL;
mw.visitMethodInsn(opcode,
clazz,
method,
FactorJava.javaSignatureToVMSignature(
args,returnType));
if(returnType != Void.TYPE)
{
generateToConversion(mw,returnType);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "push",
"(Ljava/lang/Object;)V");
}
else
mw.visitInsn(POP);
mw.visitInsn(RETURN);
mw.visitMaxs(4 + args.length,5);
return true;
} //}}}
//{{{ compileNew() method
private boolean compileNew(FactorWord word,
FactorInterpreter interp,
ClassWriter cw,
CodeVisitor mw,
FactorList form) throws Exception
{
FactorDictionary dict = interp.dict;
if(form.car != dict.jconstructor)
return false;
form = form.next();
String clazz = (String)form.car;
Class[] args = FactorJava.classNameToClassList(
(FactorList)form.next().car);
clazz = clazz.replace('.','/');
mw.visitTypeInsn(NEW,clazz);
mw.visitInsn(DUP);
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
generateArgs(mw,args,true);
mw.visitMethodInsn(INVOKESPECIAL,
clazz,
"<init>",
FactorJava.javaSignatureToVMSignature(
args,void.class));
mw.visitInsn(SWAP);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "push",
"(Ljava/lang/Object;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(5 + args.length,5);
return true;
} //}}}
//{{{ generateArgs() method
/**
* Generate instructions for copying arguments from the Factor
* datastack to the JVM stack. The types array is used to
* perform type conversions.
*/
private void generateArgs(CodeVisitor mw, Class[] args,
boolean generateSwap) throws Exception
{
if(args.length != 0)
{
// ensure the stack has enough elements
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,args.length);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
// datastack.stack -> 3
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,3);
// datastack.top-args.length -> 4
mw.visitInsn(DUP);
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
mw.visitIntInsn(BIPUSH,args.length);
mw.visitInsn(ISUB);
// datastack.top -= args.length
mw.visitInsn(DUP2);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
mw.visitVarInsn(ISTORE,4);
if(generateSwap)
mw.visitInsn(SWAP);
for(int i = 0; i < args.length; i++)
{
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitInsn(AALOAD);
generateFromConversion(mw,args[i]);
if(i != args.length - 1)
mw.visitIincInsn(4,1);
}
}
} //}}}
//{{{ generateFromConversion() method
/**
* Unbox value at top of the stack.
*/
private void generateFromConversion(CodeVisitor mw, Class type)
throws Exception
{
if(type == Object.class)
return;
String methodName = null;
if(type == Number.class)
methodName = "toNumber";
else if(type == String.class)
methodName = "toString";
else if(type == boolean.class)
methodName = "toBoolean";
else if(type == char.class)
methodName = "toChar";
else if(type == int.class)
methodName = "toInt";
else if(type == long.class)
methodName = "toLong";
else if(type == float.class)
methodName = "toFloat";
else if(type == double.class)
methodName = "toDouble";
else if(type == Class.class)
methodName = "toClass";
else if(type.isArray())
methodName = "toArray";
if(methodName == null)
{
mw.visitTypeInsn(CHECKCAST,
type.getName()
.replace('.','/'));
}
else
{
mw.visitMethodInsn(INVOKESTATIC,
"factor/FactorJava",
methodName,
"(Ljava/lang/Object;)"
+ FactorJava.javaClassToVMClass(type));
}
} //}}}
//{{{ generateToConversion() method
/**
* Box return value, if needed.
*/
private 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.javaBoxingType(type);
if(boxingType != null)
{
String boxingName = boxingType.getName()
.replace('.','/');
mw.visitTypeInsn(NEW,boxingName);
mw.visitInsn(DUP_X1);
mw.visitInsn(SWAP);
mw.visitMethodInsn(INVOKESPECIAL,boxingName,
"<init>",
"(" + FactorJava.javaClassToVMClass(
type) + ")V");
}
}
} //}}}
//{{{ toString() method
public String toString()
{
return form.toString();
} //}}}
}

View File

@ -0,0 +1,43 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public class FactorRuntimeException extends FactorException
{
public FactorRuntimeException(String str)
{
super(str);
}
public FactorRuntimeException(String str, Throwable t)
{
super(str,t);
}
}

View File

@ -0,0 +1,490 @@
/* :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;
import org.objectweb.asm.*;
/**
* ~<< name ... -- >>~
*/
public class FactorShuffleDefinition extends FactorWordDefinition
{
public static final int FROM_R_MASK = (1<<15);
public static final int TO_R_MASK = (1<<16);
public static final int SPECIFIER = FROM_R_MASK | TO_R_MASK;
/**
* Elements to consume from stacks.
*/
private int consumeD;
private int consumeR;
/**
* Permutation for elements on stack.
*/
private int[] shuffleD;
private int shuffleDstart;
private int shuffleDlength;
private int[] shuffleR;
private int shuffleRstart;
private int shuffleRlength;
/**
* This is not thread-safe!
*/
private Object[] temporaryD;
private Object[] temporaryR;
//{{{ FactorShuffleDefinition constructor
public FactorShuffleDefinition(int consumeD, int consumeR,
int[] shuffleD, int shuffleDlength,
int[] shuffleR, int shuffleRlength)
{
this.consumeD = consumeD;
this.consumeR = consumeR;
this.shuffleD = shuffleD;
this.shuffleDlength = shuffleDlength;
this.shuffleR = shuffleR;
this.shuffleRlength = shuffleRlength;
if(this.shuffleD != null && this.shuffleDlength == 0)
this.shuffleD = null;
if(this.shuffleR != null && this.shuffleRlength == 0)
this.shuffleR = null;
if(this.shuffleD != null)
{
temporaryD = new Object[shuffleDlength];
for(int i = 0; i < shuffleDlength; i++)
{
if(shuffleD[i] == i)
shuffleDstart++;
else
break;
}
}
if(this.shuffleR != null)
{
temporaryR = new Object[shuffleRlength];
for(int i = 0; i < shuffleRlength; i++)
{
if(shuffleR[i] == (i | FROM_R_MASK))
shuffleRstart++;
else
break;
}
}
} //}}}
//{{{ canCompile() method
boolean canCompile()
{
return true;
} //}}}
//{{{ compile() method
/**
* Write the definition of the eval() method in the compiled word.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
*/
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
{
boolean fromD = false;
boolean fromR = false;
for(int i = 0; i < shuffleDlength; i++)
{
fromD = true;
if((shuffleD[i] & FROM_R_MASK) == FROM_R_MASK)
{
fromR = true;
break;
}
}
for(int i = 0; i < shuffleRlength; i++)
{
fromR = true;
if((shuffleR[i] & FROM_R_MASK) == FROM_R_MASK)
{
fromR = true;
break;
}
}
// Local 3 -- datastack
// Local 4 -- datastack top-consumeD
// Local 5 -- datastack array
if(consumeD != 0 || fromD)
{
// (datastack datastack datastack)
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "datastack",
"Lfactor/FactorDataStack;");
mw.visitInsn(DUP);
if(consumeD != 0)
{
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,consumeD);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
}
mw.visitInsn(DUP);
// datastack -> 3
mw.visitVarInsn(ASTORE,3);
// datastack.top-consumeD -> 4
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
if(consumeD != 0)
{
mw.visitIntInsn(BIPUSH,consumeD);
mw.visitInsn(ISUB);
}
mw.visitVarInsn(ISTORE,4);
// datastack.stack -> 5
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,5);
}
// Local 6 -- callstack
// Local 7 -- callstack top-consumeR
// Local 8 -- callstack array
if(consumeR != 0 || fromR)
{
// (callstack callstack)
mw.visitVarInsn(ALOAD,2);
mw.visitFieldInsn(GETFIELD,
"factor/FactorInterpreter", "callstack",
"Lfactor/FactorCallStack;");
mw.visitInsn(DUP);
if(consumeR != 0)
{
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,consumeR);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePop",
"(I)V");
}
mw.visitInsn(DUP);
// callstack -> 6
mw.visitVarInsn(ASTORE,6);
// callstack.top-consumeR -> 7
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "top",
"I");
if(consumeR != 0)
{
mw.visitIntInsn(BIPUSH,consumeR);
mw.visitInsn(ISUB);
}
mw.visitVarInsn(ISTORE,7);
// callstack.stack -> 8
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,8);
}
int locals = 9;
if(shuffleD != null)
{
for(int i = shuffleDstart; i < shuffleDlength; i++)
{
// stack[top-consumeD+shuffleD[i]] -> 9+i
int index = shuffleD[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
{
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
index &= ~FROM_R_MASK;
}
else
{
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
}
if(index != 0)
{
mw.visitIntInsn(BIPUSH,index);
mw.visitInsn(IADD);
}
mw.visitInsn(AALOAD);
mw.visitVarInsn(ASTORE,9 + i);
}
locals += shuffleDlength;
}
if(shuffleR != null)
{
for(int i = shuffleRstart; i < shuffleRlength; i++)
{
// stack[top-consumeR+shuffleR[i]] -> 9+i
int index = shuffleR[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
{
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
index &= ~FROM_R_MASK;
}
else
{
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
}
if(index != 0)
{
mw.visitIntInsn(BIPUSH,index);
mw.visitInsn(IADD);
}
mw.visitInsn(AALOAD);
mw.visitVarInsn(ASTORE,locals + i);
}
}
if(shuffleD != null)
{
// ensure that the stack array has enough space.
mw.visitVarInsn(ALOAD,3);
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePush", "(I)V");
// the datastack.stack array might have changed.
// reload it.
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,5);
for(int i = shuffleDstart; i < shuffleDlength; i++)
{
// stack[top - consumeD + i] <- 9+i
mw.visitVarInsn(ALOAD,5);
mw.visitVarInsn(ILOAD,4);
if(i != 0)
{
mw.visitIntInsn(BIPUSH,i);
mw.visitInsn(IADD);
}
mw.visitVarInsn(ALOAD,9 + i);
mw.visitInsn(AASTORE);
}
// increment the 'top' field.
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitInsn(IADD);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
else if(consumeD != 0)
{
mw.visitVarInsn(ALOAD,3);
mw.visitVarInsn(ILOAD,4);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
if(shuffleR != null)
{
// ensure that the stack array has enough space.
mw.visitVarInsn(ALOAD,6);
mw.visitInsn(DUP);
mw.visitIntInsn(BIPUSH,shuffleDlength);
mw.visitMethodInsn(INVOKEVIRTUAL,
"factor/FactorArrayStack", "ensurePush", "(I)V");
// the callstack.stack array might have changed.
// reload it.
mw.visitFieldInsn(GETFIELD,
"factor/FactorArrayStack", "stack",
"[Ljava/lang/Object;");
mw.visitVarInsn(ASTORE,8);
for(int i = shuffleRstart; i < shuffleRlength; i++)
{
// stack[top - consumeD + i] <- locals+i
mw.visitVarInsn(ALOAD,8);
mw.visitVarInsn(ILOAD,7);
if(i != 0)
{
mw.visitIntInsn(BIPUSH,i);
mw.visitInsn(IADD);
}
mw.visitVarInsn(ALOAD,locals + i);
mw.visitInsn(AASTORE);
}
// increment the 'top' field.
mw.visitVarInsn(ALOAD,6);
mw.visitVarInsn(ILOAD,7);
mw.visitIntInsn(BIPUSH,shuffleRlength);
mw.visitInsn(IADD);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
else if(consumeR != 0)
{
mw.visitVarInsn(ALOAD,6);
mw.visitVarInsn(ILOAD,7);
mw.visitFieldInsn(PUTFIELD,
"factor/FactorArrayStack", "top",
"I");
}
mw.visitInsn(RETURN);
// Max stack and locals
mw.visitMaxs(4,9 + shuffleDlength + shuffleRlength);
return true;
} //}}}
//{{{ eval() method
public void eval(FactorWord word, FactorInterpreter interp)
throws FactorStackException
{
FactorArrayStack datastack = interp.datastack;
FactorArrayStack callstack = interp.callstack;
if(datastack.top < consumeD)
throw new FactorStackException(consumeD);
if(callstack.top < consumeR)
throw new FactorStackException(consumeR);
if(shuffleD != null)
shuffle(interp,datastack,consumeD,consumeR,shuffleD,temporaryD);
if(shuffleR != null)
shuffle(interp,callstack,consumeD,consumeR,shuffleR,temporaryR);
datastack.top -= consumeD;
if(temporaryD != null)
datastack.pushAll(temporaryD);
callstack.top -= consumeR;
if(temporaryR != null)
callstack.pushAll(temporaryR);
} //}}}
//{{{ shuffle() method
private void shuffle(FactorInterpreter interp, FactorArrayStack stack,
int consumeD, int consumeR, int[] shuffle, Object[] temporary)
throws FactorStackException
{
for(int i = 0; i < temporary.length; i++)
{
Object[] array;
int top;
int index = shuffle[i];
int consume;
if((index & FROM_R_MASK) == FROM_R_MASK)
{
array = interp.callstack.stack;
top = interp.callstack.top;
index = (index & ~FROM_R_MASK);
consume = consumeR;
}
else
{
array = interp.datastack.stack;
top = interp.datastack.top;
consume = consumeD;
}
temporary[i] = array[top - consume + index];
}
} //}}}
//{{{ toString() method
public String toString()
{
StringBuffer buf = new StringBuffer();
for(int i = 0; i < consumeD; i++)
{
buf.append((char)('A' + i));
buf.append(' ');
}
for(int i = 0; i < consumeR; i++)
{
buf.append("r:");
buf.append((char)('A' + i));
buf.append(' ');
}
buf.append("--");
if(shuffleD != null)
{
for(int i = 0; i < shuffleDlength; i++)
{
int index = shuffleD[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
index &= ~FROM_R_MASK;
buf.append(' ');
buf.append((char)('A' + index));
}
}
if(shuffleR != null)
{
for(int i = 0; i < shuffleRlength; i++)
{
int index = shuffleR[i];
if((index & FROM_R_MASK) == FROM_R_MASK)
index &= ~FROM_R_MASK;
buf.append(" r:");
buf.append((char)('A' + index));
}
}
return buf.toString();
} //}}}
}

View File

@ -0,0 +1,38 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public class FactorStackException extends FactorRuntimeException
{
public FactorStackException(int expected)
{
super("Expected " + expected);
}
}

View File

@ -0,0 +1,38 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public class FactorUndefinedWordException extends FactorRuntimeException
{
public FactorUndefinedWordException(FactorWord word)
{
super(word + " not defined");
}
}

69
factor/FactorWord.java Normal file
View File

@ -0,0 +1,69 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.util.HashMap;
import java.util.Map;
/**
* An internalized symbol.
*/
public class FactorWord implements FactorExternalizable
{
public final String name;
/**
* Always non-null.
*/
public FactorWordDefinition def;
/**
* "define" pushes previous definitions onto this list, like a stack.
*/
public FactorList history;
//{{{ FactorWord constructor
/**
* Do not use this constructor unless you're writing a packages
* implementation or something. Use an FactorDictionary's
* intern() method instead.
*/
public FactorWord(String name)
{
this.name = name;
def = FactorMissingDefinition.INSTANCE;
} //}}}
//{{{ toString() method
public String toString()
{
return name;
} //}}}
}

View File

@ -0,0 +1,191 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
import java.io.FileOutputStream;
import java.util.Iterator;
import org.objectweb.asm.*;
import org.objectweb.asm.util.*;
/**
* A word definition.
*/
public abstract class FactorWordDefinition implements FactorObject, Constants
{
private FactorNamespace namespace;
/**
* Number of times this word has been referenced from a
* compound word (incremented by the precompiler).
*/
public int references;
public abstract void eval(FactorWord word, FactorInterpreter interp)
throws Exception;
void precompile(FactorWord word, FactorInterpreter interp)
throws Exception {}
public FactorNamespace getNamespace(FactorInterpreter interp) throws Exception
{
if(namespace == null)
namespace = new FactorNamespace(interp.global,this);
return namespace;
}
//{{{ canCompile() method
boolean canCompile()
{
return false;
} //}}}
private static int compileCount;
//{{{ compile() method
/**
* Compile the given word, returning a new word definition.
*/
FactorWordDefinition compile(FactorWord word, FactorInterpreter interp)
throws Exception
{
if(!canCompile())
return this;
//System.out.println("Compiling " + word);
StringBuffer sanitizedName = new StringBuffer();
for(int i = 0; i < word.name.length(); i++)
{
char ch = word.name.charAt(i);
if(!Character.isJavaIdentifierStart(ch))
sanitizedName.append("_");
else
sanitizedName.append(ch);
}
String className = "factor/__compiler__/" + sanitizedName
+ "_" + (compileCount++);
ClassWriter cw = new ClassWriter(false);
cw.visit(ACC_PUBLIC, className,
"factor/FactorWordDefinition", null, null);
// creates a MethodWriter for the (implicit) constructor
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
"<init>", "()V", null, null);
// pushes the 'this' variable
mw.visitVarInsn(ALOAD, 0);
// invokes the super class constructor
mw.visitMethodInsn(INVOKESPECIAL,
"factor/FactorWordDefinition", "<init>", "()V");
mw.visitInsn(RETURN);
// this code uses a maximum of one stack element and one local
// variable
mw.visitMaxs(1, 1);
// creates a MethodWriter for the 'toString' method
mw = cw.visitMethod(ACC_PUBLIC,
"toString", "()Ljava/lang/String;", null, null);
mw.visitLdcInsn("( compiled ) " + toString());
mw.visitInsn(ARETURN);
mw.visitMaxs(1, 1);
// pushes the 'this' variable
mw.visitVarInsn(ALOAD, 0);
// invokes the super class constructor
mw.visitMethodInsn(INVOKESPECIAL,
"factor/FactorWordDefinition", "<init>", "()V");
mw.visitInsn(RETURN);
// this code uses a maximum of one stack element and one local
// variable
mw.visitMaxs(1, 1);
// creates a MethodWriter for the 'eval' method
mw = cw.visitMethod(ACC_PUBLIC,
"eval", "(Lfactor/FactorWord;Lfactor/FactorInterpreter;)V",
null, null);
// We store a string with disassembly for debugging
// purposes.
TraceCodeVisitor disasm = new TraceCodeVisitor(mw);
if(!compile(word,interp,cw,disasm))
return this;
// Save the disassembly
StringBuffer buf = new StringBuffer();
Iterator bytecodes = disasm.getText().iterator();
while(bytecodes.hasNext())
{
buf.append(bytecodes.next());
}
// gets the bytecode of the class, and loads it dynamically
byte[] code = cw.toByteArray();
/* FileOutputStream fos = new FileOutputStream(className + ".class");
fos.write(code);
fos.close(); */
SimpleClassLoader loader = new SimpleClassLoader();
Class compiledWordClass = loader._defineClass(className,
code, 0, code.length);
FactorWordDefinition compiledWord = (FactorWordDefinition)
compiledWordClass.newInstance();
compiledWord.getNamespace(interp).setVariable("asm",buf.toString());
return compiledWord;
} //}}}
//{{{ compile() method
/**
* Write the definition of the eval() method in the compiled word.
* Local 0 -- this
* Local 1 -- word
* Local 2 -- interpreter
*/
boolean compile(FactorWord word, FactorInterpreter interp,
ClassWriter cw, CodeVisitor mw)
throws Exception
{
throw new FactorRuntimeException("Don't know how to compile " + word);
} //}}}
//{{{ SimpleClassLoader class
static class SimpleClassLoader extends ClassLoader
{
public Class _defineClass(String name,
byte[] code, int off, int len)
{
return defineClass(name,code,off,len);
}
} //}}}
}

View File

@ -0,0 +1,35 @@
/* :folding=explicit:collapseFolds=1: */
/*
* $Id$
*
* Copyright (C) 2003 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;
public interface PublicCloneable extends Cloneable
{
Object clone();
}

102
factor/boot.factor Normal file
View File

@ -0,0 +1,102 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
!!! The stack operators are defined using shuffle notation. This saves several
!!! hundred lines of code!
~<< drop A -- >>~
~<< 2drop A B -- >>~
~<< dup A -- A A >>~
~<< 2dup A B -- A B A B >>~
~<< dupd A B -- A A B >>~
~<< 2dupd A B C D -- A B A B C D >>~
~<< nip A B -- B >>~
~<< 2nip A B C D -- C D >>~
~<< nop -- >>~ ! Does nothing!
~<< over A B -- A B A >>~
~<< 2over A B C D -- A B C D A B >>~
~<< pick A B C -- A B C A >>~ ! Not the Forth pick!
~<< rot A B C -- B C A >>~
~<< 2rot A B C D E F -- C D E F A B >>~
~<< -rot A B C -- C A B >>~
~<< 2-rot A B C D E F -- E F A B C D >>~
~<< swap A B -- B A >>~
~<< 2swap A B C D -- C D A B >>~
~<< swapd A B C -- B A C >>~
~<< 2swapd A B C D E F -- C D A B E F >>~
~<< tuck A B -- B A B >>~
~<< 2tuck A B C D -- C D A B C D >>~
~<< rdrop r:A -- >>~
~<< >r A -- r:A >>~
~<< 2>r A B -- r:A r:B >>~
~<< r> r:A -- A >>~
~<< 2r> r:A r:B -- A B >>~
!!! Minimum amount of I/O words needed to be able to read other resources.
!!! Remaining I/O operations are defined in io.factor and parser.factor.
: <breader> (reader -- breader)
[ |java.io.Reader ] |java.io.BufferedReader jconstructor jnew ;
: <ireader> (inputstream -- breader)
[ |java.io.InputStream ] |java.io.InputStreamReader jconstructor jnew ;
: <rreader> (path -- inputstream)
|factor.FactorInterpreter
[ |java.lang.String ] |java.lang.Class |getResourceAsStream jmethod jinvoke
<ireader> <breader> ;
: parse* (filename reader -- list)
$dict
[ |java.lang.String |java.io.Reader |factor.FactorDictionary ]
|factor.FactorParser jconstructor jnew
[ ] |factor.FactorParser |parse jmethod jinvoke ;
: runResource (path --)
dup <rreader> parse* call ;
!!!
!!! Load the standard library.
"/version.factor" runResource
"/factor/combinators.factor" runResource
"/factor/continuations.factor" runResource
"/factor/dictionary.factor" runResource
"/factor/examples.factor" runResource
"/factor/interpreter.factor" runResource
"/factor/lists.factor" runResource
"/factor/math.factor" runResource
"/factor/miscellaneous.factor" runResource
"/factor/namespaces.factor" runResource
"/factor/network.factor" runResource
"/factor/parser.factor" runResource
"/factor/random.factor" runResource
"/factor/stream.factor" runResource
"/factor/strings.factor" runResource
! If we're run stand-alone, start the interpreter in the current tty.
$interactive [ initialInterpreterLoop ] when

228
factor/combinators.factor Normal file
View File

@ -0,0 +1,228 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: apply2 (x y [ code ] --)
! First applies the code to x, then to y.
2dup 2>r
nip call
2r>
call ;
~<< binrecP
! Put P on top of the data stack, save everything on callstack.
P T R1 R2 -- P r:P r:T r:R1 r:R2 >>~
~<< binrecT
! Put T on top of the data stack, discard all saved objects from
! callstack.
r:P r:T r:R1 r:R2 -- T >>~
~<< binrecR1
! Put R1 on top of the data stack, retaining all saved objects on the
! callstack.
r:P r:T r:R1 r:R2 -- R1 r:P r:T r:R1 r:R2 >>~
~<< binrecLeft
! Left recursion setup; put second value on callstack, put P, T, R1, R2
! on data stack (and leave them on the callstack too).
Value2 r:P r:T r:R1 r:R2 -- P T R1 R2 r:Value2 r:P r:T r:R1 r:R2 >>~
~<< binrecRight
! Right recursion setup; put second value back on datastack, put
! P, T, R1, R2 on data stack. All quotations except for R2 are
! discarded from the callstack, since they're not needed anymore.
r:Value2 r:P r:T r:R1 r:R2 -- Value2 P T R1 R2 r:R2 >>~
: binrec ( [ P ] [ T ] [ R1 ] [ R2 ] -- ... )
! Evaluate P. If it evaluates to t, evaluate T. Otherwise, evaluate R1,
! which is expected to produce two values, recurse on each value, and
! evaluate R2.
binrecP call [
binrecT call
] [
binrecR1 call
! R1 has now produced two values on top of the data stack.
! Recurse twice.
binrecLeft binrec
binrecRight binrec
! Now call R2.
r> call
] ifte ;
: compare (x y [if x < y] [if x = y] [if x > y] --)
>=< call ;
: cleave (x [ code1 ] [ code2 ] --)
! Executes each quotation, with x on top of the stack.
>r
over >r
call
r>
r>
call ;
: cond (list --)
! The list is of this form:
! [ [ condition 1 ] [ code 1 ]
! [ condition 2 ] [ code 2 ]
! ... ]
! Each condition is evaluated in turn. If it returns true, the code
! is evaluated. If it returns false, the next condition is checked.
[
uncons >r
call
r>
swap [
car call
] [
cdr cond
] ifte
] when* ;
: dip (a [ b ] -- b a)
! Calls b as if b was not even present on the stack -- b has no way of
! knowing that a even exists.
swap
>r
call
r> ;
: 2dip (a b [ c ] -- c a b)
! Calls c as if a and b were not even present on the stack -- c has no way
! of knowing that a and b even exist.
-rot
2>r
call
2r> ;
: each ([ list ] [ code ] --)
! Applies the code to each element of the list.
over [
>r
uncons
r>
tuck
2>r
call
2r>
each
] [
2drop
] ifte ;
: expand (list -- list)
! Evaluates the list on a new stack, and pushes the reversed stack onto the
! original stack. For example, "[ 0 1 2 dup * + ] expand" will evaluate to
! [ 0 5 ].
unit
restack
call
unstack ;
: interleave ( X list -- ... )
! Evaluate each element of the list with X on top of the
! stack.
dup [
over [ unswons dip ] dip swap interleave
] [
2drop
] ifte ;
: ifte (cond [if true] [if false] --)
? call ;
: linrec ( [ P ] [ T ] [ R1 ] [ R2 ] -- )
! Evaluate P, if it pushes t, evaluate T. Otherwise, evaluate R1, recurse,
! and evaluate R2. This combinator is similar to the linrec combinator in
! Joy, except in Joy, P does not affect the stack.
>r >r >r dup >r call [
r> drop r> call
r> drop r> drop
] [
r> r> r> dup >r swap >r swap >r call
r> r> r> r> dup >r linrec
r> call
] ifte ;
: map ([ items ] [ initial ] [ code ] -- [ mapping ])
! Applies the code to each item, returns a list that begins with the initial
! list and contains the result of each application.
swapd 2list append
restack
each
unstack ;
: push ([ a b c ... ] -- a b c ...)
! Pushes values onto the stack literally (even if they are words).
[ uncons push ] when* ;
: subset (list code -- list)
! Applies code to each element of the given list, creating a new list
! containing the elements where the code returned a non-null value.
[ dupd call [ drop ] unless ] cons 2list
restack
each
unstack ;
: times (n [ code ] --)
! Evaluates code n times.
[
over 0 >
] [
tuck >r pred >r call r> r>
] while 2drop ;
: times* (n [ code ] --)
! Evaluates code n times, each time the index is pushed onto the stack.
! The index ranges from 0 to n-1.
0 rot
[
2dup <
] [
>r 2dup succ >r >r swap call r> r> r>
] while
drop drop drop ;
: unless (cond [if false] --)
f swap ? call ;
: when (cond [if true] --)
f ? call ;
: when* (cond [ code ] --)
! If the condition is true, it is left on the stack, and the code is
! evaluated. Otherwise, the condition is popped off the stack.
dupd [ drop ] ifte ;
: while ( [ P ] [ R ] -- ... )
! Evaluates P. If it leaves t on the stack, evaluate R, and recurse.
>r dup >r call [
r> r> dup >r swap >r call
r> r> while
] [
r> drop r> drop
] ifte ;

View File

@ -0,0 +1,73 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: continue (datastack callstack push --)
! Do not call this directly. Used by callcc.
! Use a trick to carry the push parameter onto the new data stack.
2dip
callstack@ (push` datastack)
swap (datastack push`)
>r (datastack)
datastack@ (... [ code ])
drop (...)
r> (... push`)
call ;
: callcc ([ code ] --)
! Calls the code with a special object on the top of the stack. This object,
! when called, restores execution state to just after the callcc call that
! generated this object, and pushes each element of the list at the top of
! the caller's data stack onto the original data stack.
! We do a cdr since we don't want the [ code ] to be at the top of the
! stack when execution is restored. Also note that $callstack's car is the
! parent callframe, not the current callframe -- the current callframe is in
! $callframe.
datastack$ callstack$ [ [ ] continue ] cons cons
swap call ;
: callcc0 ([ code ] --)
! Like callcc except no data is pushed onto the original datastack.
datastack$ callstack$ [ [ f ] continue ] cons cons
swap call ;
: callcc1 ([ code ] --)
! Like callcc except the continuation that is pushed onto the stack before
! executing the given code takes the top of the caller's data stack and
! pushes it onto the original datastack, instead of prepending it to the
! original datastack as a list.
datastack$ callstack$ [ [ unit ] continue ] cons cons
swap call ;
: suspend (--)
! Suspend the current fiber.
! Not really implemented yet.
$initialInterpreterContinuation dup [
call
] [
clear unwind
] ifte ;

67
factor/dictionary.factor Normal file
View File

@ -0,0 +1,67 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
! Undefined words's def field is equal to this.
"factor.FactorMissingDefinition" "INSTANCE" jfield jvarStatic$ @undefinedWord
: asm. (word -- assembly)
! Prints JVM bytecode disassembly of the given word.
worddef [ $asm ] bind dup [
print
] [
drop "Not a compiled word." print
] ifte ;
: word? (obj -- boolean)
"factor.FactorWord" is ;
: str>word ("word" -- word)
! Returns the top of the stack if it already been interned.
dup word? [
$dict [ "java.lang.String" ] "factor.FactorDictionary" "intern"
jmethod jinvoke
] unless ;
: worddef? (obj -- boolean)
"factor.FactorWordDefinition" is ;
: compound? (obj -- boolean)
"factor.FactorCompoundDefinition" is ;
: shuffle? (obj -- boolean)
"factor.FactorShuffleDefinition" is ;
: worddef (word -- worddef)
str>word
! Get the 'def' field
"factor.FactorWord" "def" jfield jvar$
! Is it equal to the missing word placeholder? Then push f.
dup $undefinedWord = [ drop f ] when ;
: words (-- list)
! Pushes a list of all defined words.
$dict [ ] "factor.FactorDictionary" "toWordList" jmethod jinvoke ;

38
factor/examples.factor Normal file
View File

@ -0,0 +1,38 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: examples/httpd
"/factor/examples/httpd.factor" runResource
"Enter a port number: " write
read >fixnum
"Enter document root (eg, /home/www/): " write
read
httpd ;
: examples/httpd*
"/factor/examples/httpd.factor" runResource
8888 "/home/slava/ExampleHTTPD/" httpd ;

View File

@ -0,0 +1,151 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
! To make this a bit more useful:
! - URL encoding
! - log with date
! - log user agent
! - add a socket timeout
! - if a directory is requested and URL does not end with /, redirect
! - return more header fields, like Content-Length, Last-Modified, and so on
! - HEAD request
! - make httpdFiletype generic, specify file types in a list of comma pairs
! - basic authentication, using httpdAuth function from a config file
! - when string formatting is added, some code can be simplified
! - use nio to handle multiple requests
! - implement an LSP that does an "apropos" search
: httpdGetPath ( request -- file )
dup ".*\\.\\.*" matches [
f
] [
dup [ "GET (.*?)( HTTP.*|)" groups dup [ car ] when ] when
] ifte ;
: httpdResponse (stream msg contentType --)
[ "HTTP/1.0 " over fwrite ] 2dip
[ over fwriteln "Content-type: " over fwriteln ] dip
swap fwriteln ;
: httpdError (stream error --)
"Error: " write dup print
2dup "text/html" httpdResponse
"\n<html><body><h1>" swap "</h1></body></html>" cat3 swap fwriteln ;
: httpdFiletype (filename -- mime-type)
[
[ dup ".*\.gif" matches ] [ drop "image/gif" ]
[ dup ".*\.png" matches ] [ drop "image/png" ]
[ dup ".*\.html" matches ] [ drop "text/html" ]
[ dup ".*\.txt" matches ] [ drop "text/plain" ]
[ dup ".*\.lsd" matches ] [ drop "text/plain" ]
[ t ] [ drop "application/octet-stream" ]
] cond ;
: httpdUriToPath (uri -- path)
$httpdDocRoot swap
dup "http://.*?(/.*)" groups [ car ] when*
cat2 ;
: httpdPathToAbsolute (path -- absolute)
$httpdDocRoot swap cat2
"Serving " over cat2 print
dup directory? [ "/index.html" cat2 ] when ;
: httpdServeFile (stream argument filename --)
nip
2dup "200 Document follows" swap httpdFiletype httpdResponse
[ "" over fwriteln ] dip
<filebr> swap fcopy ;
: httpdListDirectory (stream directory -- string)
[ "<html><head><title>" over fwrite ] dip
2dup swap fwrite
[ "</title></head><body><h1>" over fwrite ] dip
2dup swap fwrite
[ "</h1><ul>" over fwrite ] dip
directory [
chars>entities
dup directory? [ "/" cat2 ] when
[ "<li><a href=\"" over fwrite ] dip
2dup swap fwrite
[ "\">" over fwrite ] dip
2dup swap fwrite
[ "</a></li>" over fwrite ] dip
drop
] each
"</ul></body></html>" swap fwrite ;
: httpdServeDirectory (stream argument directory --)
dup "/index.html" cat2 dup exists? [
nip httpdServeFile
] [
drop nip
over "200 Document follows" "text/plain" httpdResponse
[ "" over fwriteln ] dip
httpdListDirectory
] ifte ;
: httpdServeScript (stream argument filename --)
<namespace> [ [ @argument @stdio ] dip runFile ] bind ;
: httpdParseObjectName ( filename -- argument filename )
dup "(.*?)\\?(.*)" groups dup [ nip push ] when swap ;
: httpdServeObject (stream filename --)
"Serving " write dup print
httpdParseObjectName
dup exists? [
dup directory? [
httpdServeDirectory
] [
dup ".*\.lhtml" matches [
httpdServeScript
] [
httpdServeFile
] ifte
] ifte
] [
2drop "404 Not Found" httpdError
] ifte ;
: httpdRequest (stream request --)
httpdGetPath dup [
httpdUriToPath httpdServeObject
] [
drop "400 Bad request" httpdError
] ifte ;
: httpdClient (socket --)
"Accepted connection from " write dup [ $socket ] bind .
[ dup freadln httpdRequest ] [ fclose ] cleave ;
: httpdLoop (server --)
dup accept httpdClient $httpdQuit [ fclose ] [ httpdLoop ] ifte ;
: httpd (port docroot --)
@httpdDocRoot <server> httpdLoop ;

175
factor/interpreter.factor Normal file
View File

@ -0,0 +1,175 @@
!:folding=indent: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.
: exception? (exception -- boolean)
"java.lang.Throwable" is ;
: printStackTrace (exception --)
[ ] "java.lang.Throwable" "printStackTrace" jmethod jinvoke ;
: exception. (exception --)
! If this is an Factor exception, just print the message, otherwise print
! the entire exception as a string.
dup "factor.FactorException" is [
[ ] "java.lang.Throwable" "getMessage" jmethod jinvoke
] [
>str
] ifte print ;
: break (exception --)
dup @error
! Called when the interpreter catches an exception.
"break called." print
"" print
":w prints the callstack." print
":j prints the Java stack." print
":r returns to top level." print
":s returns to top level, retaining the data stack." print
":g continues execution (but expect another error)." print
"" print
"ERROR: " write exception.
callstack$ @errorCallStack
[
@errorContinuation
interpreterLoop
! If we end up here, the user just exited the err interpreter.
! If we just call returnFromError here, its like :g and this
! is probably not what they wanted. So we :r instead.
:r
] callcc0 ;
: returnFromError (--)
"Returning from break." print
f @errorCallStack
f @errorFlag
f @error ;
: :g (--)
! Continues execution from the point of the error. Can be dangerous.
returnFromError
$errorContinuation call ;
: :r (--)
! Returns to the top level.
returnFromError
!XXX
$initialInterpreterContinuation dup [
call
] [
suspend
] ifte ;
: :s (--)
! Returns to the top level, retaining the stack.
returnFromError
$initialInterpreterCallStack callstack@ ;
: :j (--)
! Print the stack trace from the exception that caused the last break.
$error dup exception? [
printStackTrace
] [
"Not an exception: " write .
] ifte ;
: :w (--)
! Print the current callstack, or the callstack of the last error inside an
! error context.
$errorCallStack dup [
drop callstack$
] unless . ;
: printPrompt (--)
$errorFlag " err> " " ok> " ? write ;
: interpreterLoop (--)
printPrompt read [
eval
$quitFlag [ interpreterLoop ] unless
] when* ;
: initialInterpreterLoop (--)
! Run the stand-alone interpreter
"Factor " $version cat2 print
"Copyright (C) 2003, 2004 Slava Pestov" print
"Enter ``help'' for help." print
"Enter ``exit'' to exit." print
! Used by :r
[ @initialInterpreterContinuation ] callcc0
! Used by :s
! We use the slightly redundant 'call' to push the current callframe.
[ callstack$ @initialInterpreterCallStack ] call
interpreterLoop ;
: words. (--)
! Print all defined words.
words [ . ] each ;
: see (word --)
dup worddef [
(word -- worddef word)
dup [ worddef dup shuffle? "~<< " ": " ? write ] dip
(worddef word -- worddef)
write "\n " write
dup >str write
shuffle? " >>~\n" " ;\n" ? write
] [
"Not defined: " write print
] ifte ;
: vars. (--)
! Print a list of defined variables.
vars [ . ] each ;
: .s (--)
! Prints the contents of the data stack
datastack$ . ;
: help
"" print
"= Dynamic, interpreted, stack-based scripting language" print
"= Arbitrary precision math, ratio math" print
"= First-class, higher-order, and anonymous functions" print
"= Prototype-based object system" print
"= Continuations" print
"= Tail call optimization" print
"= Rich set of primitives based on recursion" print
"" print
"Some basic commands:" print
"clear -- clear stack." print
".s -- print stack." print
". -- print top of stack." print
"vars. -- list all variables." print
"$variable . -- show value of variable." print
"words. -- list all words." print
"\"word\" see -- show definition of word." print
"exit -- exit the interpreter." print
"" print ;

149
factor/lists.factor Normal file
View File

@ -0,0 +1,149 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: 2list (a b -- [ a b ])
unit cons ;
: 2rlist (a b -- [ b a ])
swap unit cons ;
: append ([ list1 ] [ list2 ] -- [ list1 list2 ])
swap rappend ;
: add ([ list1 ] elem -- [ list1 elem ])
unit append ;
: append@ ([ list ] variable --)
! Adds the list to the end of the list stored in the given variable.
dup [ $ swap append ] dip @ ;
: array>list ( array -- list )
[ "[Ljava.lang.Object;" ] "factor.FactorList" "fromArray" jmethod jinvokeStatic ;
: add@ (elem variable --)
! Adds the element to the end of the list stored in the given variable.
dup [ $ swap add ] dip @ ;
: assoc (key alist -- value)
! Looks up the key in the given alist. An alist is a list of comma pairs,
! the car of each pair is a key, the cdr is the value. For example:
! [ [ 1 , "one" ] [ 2 , "two" ] [ 3 , "three" ] ]
dup [
2dup car car = [
nip car cdr
] [
cdr assoc
] ifte
] [
2drop f
] ifte ;
: car ([ car , cdr ] -- car)
|factor.FactorList |car jfield jvar$ ;
: cdr ([ car , cdr ] -- cdr)
|factor.FactorList |cdr jfield jvar$ ;
: caar (list -- caar)
car car ;
: cdar (list -- cadr)
cdr car ;
: cadr (list -- cdar)
car cdr ;
: cddr (list -- cddr)
cdr cdr ;
: cloneList (list -- list)
! Returns a new list where each element is a clone of the elements of
! the given list.
dup [ [ ] "factor.FactorList" "deepClone" jmethod jinvoke ] when ;
: cons (car cdr -- [ car , cdr ])
[ |java.lang.Object |java.lang.Object ] |factor.FactorList jconstructor jnew ;
: contains (elem list -- boolean)
dup [
2dup car = [
2drop t
] [
cdr contains
] ifte
] [
2drop f
] ifte ;
: cons@ (x var --)
! Prepends x to the list stored in var.
dup [ $ cons ] dip @ ;
: count (n -- [ 1 2 3 ... n ])
[ [ ] times* ] cons expand ;
: swons@ (var x --)
! Prepends x to the list stored in var.
over $ cons s@ ;
: get (list n -- list[n])
[ cdr ] times car ;
: last (list -- last)
! Pushes last element of the list.
[ dup cdr ] [ cdr ] while car ;
: length (list -- length)
0 swap [ drop succ ] each ;
: list (list[0] ... list[n] n -- list)
[ ] swap [ cons ] times ;
: list? (list -- boolean)
dup pair? [ cdr list? ] [ f ] ifte ;
: pair? (list -- boolean)
|factor.FactorList is ;
: rappend ([ list2 ] [ list1 ] -- [ list1 list2 ])
[ [ |factor.FactorList ] |factor.FactorList |append jmethod jinvoke ] when* ;
: reverse (list -- list)
[ ] swap [ swons ] each ;
: swons (cdr car -- [ car , cdr ])
swap [ |java.lang.Object |java.lang.Object ]
|factor.FactorList jconstructor jnew ;
: uncons ([ car , cdr ] -- car cdr)
dup car swap cdr ;
: unit (a -- [ a ])
f cons ;
: unswons ([ car , cdr ] -- cdr car)
dup cdr swap car ;

174
factor/math.factor Normal file
View File

@ -0,0 +1,174 @@
!:folding=indent:collapseFolds=0:
! $Id$
!
! Copyright (C) 2003 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.
: 0= (x -- boolean)
0 = ;
: 1= (x -- boolean)
1 = ;
: fixnum? (obj -- boolean)
"java.lang.Integer" is ;
: >fixnum (num -- fixnum)
[ ] "java.lang.Number" "intValue" jmethod jinvoke ;
: bignum? (obj -- boolean)
"java.math.BigInteger" is ;
: >bignum (num -- bignum)
[ ] "java.lang.Number" "longValue" jmethod jinvoke
[ "long" ] "java.math.BigInteger" "valueOf" jmethod jinvokeStatic ;
: realnum? (obj -- boolean)
dup "java.lang.Float" is
swap "java.lang.Double" is or ;
: >realnum (num -- realnum)
[ ] "java.lang.Number" "doubleValue" jmethod jinvoke ;
: ratio? (obj -- boolean)
"factor.FactorRatio" is ;
: + (a b -- a+b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "add"
jmethod jinvokeStatic ;
: +@ (num var --)
dup [ $ + ] dip @ ;
: - (a b -- a-b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "subtract"
jmethod jinvokeStatic ;
: -@ (num var --)
dup [ $ -- ] dip @ ;
: -- (a b -- b-a)
swap - ;
: --@ (var num --)
[ dup $ - ] dip s@ ;
: * (a b -- a*b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "multiply"
jmethod jinvokeStatic ;
: *@ (num var --)
dup [ $ * ] dip @ ;
: / (a b -- a/b)
[ "java.lang.Number" "java.lang.Number" ] "factor.FactorMath" "divide"
jmethod jinvokeStatic ;
: /@ (num var --)
dup [ $ / ] dip @ ;
: // (a b -- b/a)
swap / ;
: //@ (num var --)
[ dup $ / ] dip s@ ;
: > (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "greater" jmethod jinvokeStatic ;
: >= (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "greaterEqual" jmethod jinvokeStatic ;
: < (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "less" jmethod jinvokeStatic ;
: <= (a b -- boolean)
[ "float" "float" ] "factor.FactorMath" "lessEqual" jmethod jinvokeStatic ;
: and (a b -- a&b)
f ? ;
: mag2 (x y -- mag)
! Returns the magnitude of the vector (x,y).
sq swap sq + sqrt ;
: neg (x -- -x)
0 swap - ;
: neg@ (var --)
dup $ 0 swap - s@ ;
: not (a -- a)
! Pushes f is the object is not f, t if the object is f.
f t ? ;
: not@ (boolean -- boolean)
dup $ not s@ ;
: pred (n -- n-1)
1 - ;
: succ (n -- nsucc)
1 + ;
: pred@ (var --)
dup $ 1 - s@ ;
: or (a b -- a|b)
t swap ? ;
: recip (x -- 1/x)
1 // ;
: sq (x -- x^2)
dup * ;
: sqrt (x -- sqrt x)
[ "double" ] "java.lang.Math" "sqrt" jmethod jinvokeStatic ;
: succ@ (var --)
dup $ 1 + s@ ;
: deg2rad (degrees -- radians)
$pi * 180 / ;
: rad2deg (radians -- degrees)
180 * $pi / ;
: fib (n -- nth fibonacci number)
! This is the naive implementation, for benchmarking purposes.
[ dup 1 <= ] [ ] [ pred dup pred ] [ + ] binrec ;
: fac (n -- n!)
! This is the naive implementation, for benchmarking purposes.
1 swap [ succ * ] times* ;
: harmonic (n -- 1 + 1/2 + 1/3 + ... + 1/n)
0 swap [ succ recip + ] times* ;
2.7182818284590452354 @e
3.14159265358979323846 @pi
1.0 0.0 / @inf
-1.0 0.0 / @-inf

View File

@ -0,0 +1,93 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: >str (obj -- string)
! Returns the Java string representation of this object.
[ ] "java.lang.Object" "toString" jmethod jinvoke ;
: = (a b -- boolean)
! Returns true if a = b.
[ "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "equal" jmethod jinvokeStatic ;
: clone (obj -- obj)
[ ] "factor.PublicCloneable" "clone" jmethod jinvoke ;
: cloneArray (obj -- obj)
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "cloneArray"
jmethod jinvokeStatic ;
: deepCloneArray (obj -- obj)
[ "[Ljava.lang.Object;" ] "factor.FactorLib" "deepCloneArray"
jmethod jinvokeStatic ;
: is (obj class -- boolean)
! Like "instanceof" in Java.
[ "java.lang.Object" ] "java.lang.Class" "isInstance"
jmethod jinvoke ;
: not= (a b -- boolean)
= not ;
: 2= (a b c d -- boolean)
! Returns true if a = c, b = d.
swapd = [ = ] dip and ;
: ? (cond obj1 obj2 -- obj)
! Pushes obj1 if cond is true, obj2 if cond is false.
[ "boolean" "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "branch2" jmethod jinvokeStatic ;
: >=< (x y obj1 obj2 obj3 -- obj)
! If x > y, pushes obj1, if x = y, pushes obj2, else obj3.
[
"float" "float"
"java.lang.Object" "java.lang.Object" "java.lang.Object"
]
"factor.FactorLib" "branch3" jmethod jinvokeStatic ;
: error (msg --)
[ "java.lang.String" ] "factor.FactorLib" "error" jmethod jinvokeStatic ;
: exit* (code --)
[ |int ] |java.lang.System |exit jmethod jinvokeStatic ;
: exit (--)
0 exit* ;
: millis (-- millis)
! Pushes the current time, in milliseconds.
[ ] |java.lang.System |currentTimeMillis jmethod jinvokeStatic
>bignum ;
: stack>list (stack -- list)
! Turns a callstack or datastack object into a list.
[ ] "factor.FactorArrayStack" "toList" jmethod jinvoke ;
: time (code --)
! Evaluates the given code and prints the time taken to execute it.
millis swap dip millis -- . ;

68
factor/namespaces.factor Normal file
View File

@ -0,0 +1,68 @@
!:folding=indent: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.
: lazy (var [ a ] -- value)
! If the value of the variable is f, set the value to the result of
! evaluating [ a ].
over $ [ drop $ ] [ dip dupd @ ] ifte ;
: namespace? (a -- boolean)
|factor.FactorNamespace is ;
: <namespace> (-- namespace)
$namespace [ |factor.FactorNamespace ] |factor.FactorNamespace
jconstructor jnew ;
: <objnamespace> ( object -- namespace )
$namespace swap
[ "factor.FactorNamespace" "java.lang.Object" ]
"factor.FactorNamespace" jconstructor jnew ;
: extend (object code -- object)
! Used in code like this:
! : <subclass>
! <superclass> [
! ....
! ] extend ;
over [ bind ] dip ;
: import (class pairs --)
! Import some static variables from a Java class into the current namespace.
$namespace [ |java.lang.String |factor.FactorList ]
|factor.FactorNamespace |importVars
jmethod jinvoke ;
: vars (-- list)
$namespace [ ] |factor.FactorNamespace |toVarList jmethod jinvoke ;
: uvar? (name --)
[ "namespace" "parent" ] contains not ;
: uvars (-- list)
! Does not include "namespace" and "parent" variables; ie, all user-defined
! variables in given namespace.
vars [ uvar? ] subset ;

60
factor/network.factor Normal file
View File

@ -0,0 +1,60 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: <server> ( port -- stream )
! Starts listening on localhost:port. Returns a stream that you can close
! with fclose. No other stream operations are supported.
[ "int" ] "java.net.ServerSocket" jconstructor jnew
<stream> [
@socket
( -- )
[
$socket [ ] "java.net.ServerSocket" "close" jmethod jinvoke
] @fclose
] extend ;
: <socketstream> ( socket -- stream )
! Wraps a socket inside a bytestream.
dup
[ [ ] "java.net.Socket" "getInputStream" jmethod jinvoke ]
[ [ ] "java.net.Socket" "getOutputStream" jmethod jinvoke ]
cleave
<bytestream> [
@socket
! We "extend" bytestream's fclose.
( -- )
$fclose [
$socket [ ] "java.net.Socket" "close" jmethod jinvoke
] append @fclose
] extend ;
: accept ( server -- client )
! Accept a connection from a server socket.
[ $socket ] bind
[ ] "java.net.ServerSocket" "accept" jmethod jinvoke <socketstream> ;

42
factor/parser.factor Normal file
View File

@ -0,0 +1,42 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: parse (string -- list)
f swap <sreader> parse* ;
: eval ("X" -- X)
parse call ;
: runFile (path --)
dup <freader> parse* call ;
: unparse (X -- "X")
[ |java.lang.Object ] |factor.FactorJava |factorTypeToString
jmethod jinvokeStatic ;
: . (expr --)
unparse print ;

95
factor/random.factor Normal file
View File

@ -0,0 +1,95 @@
!:folding=indent:collapseFolds=0:
! $Id$
!
! Copyright (C) 2003 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.
: randomAngle (-- theta)
[ ] "factor.FactorMath" "randomAngle" jmethod jinvokeStatic ;
: randomBoolean (-- boolean)
[ ] "factor.FactorMath" "randomBoolean" jmethod jinvokeStatic ;
: randomInt (min max -- random)
[ "int" "int" ] "factor.FactorMath" "randomInt" jmethod jinvokeStatic ;
: randomSymmetricInt (max -- random)
! Return a random integer between -max and max.
dup neg swap randomInt ;
: chance (n -- boolean)
! Returns true with a 1/n probability, false with a (n-1)/n probability.
1 swap randomInt 1 = ;
: randomElement (list -- random)
! Returns a random element from the given list.
dup length pred 0 swap randomInt get ;
: randomSubset (list -- list)
! Returns a random subset of the given list. Each item is chosen with a 50%
! probability.
[ ] [ randomBoolean [ drop ] when ] map ;
: car+ (list -- sum)
! Adds the car of each element of the given list.
0 swap [ car + ] each ;
: randomProbability (list -- sum)
! Adds the car of each element of the given list, and returns a random
! number between 1 and this sum.
1 swap car+ randomInt ;
: randomElementIter (list index -- elem)
! Used by randomElement*. Do not call directly.
[ unswons unswons ] dip (list elem probability index)
-- (list elem index)
dup 0 <= [
drop nip
] [
nip randomElementIter
] ifte ;
: randomElement* (list -- elem)
! Returns a random element of the given list of comma pairs. The
! car of each pair is a probability, the cdr is the item itself.
! Only the cdr of the comma pair is returned.
dup 1 swap car+ randomInt randomElementIter ;
: randomSubset* (list -- list)
! Returns a random subset of the given list of comma pairs. The
! car of each pair is a probability, the cdr is the item itself.
! Only the cdr of the comma pair is returned.
dup [ [ [ ] ] dip car+ ] dip ([ ] probabilitySum list)
[
[ 1 over randomInt ] dip ([ ] probabilitySum probability elem)
uncons ([ ] probabilitySum probability elema elemd)
-rot ([ ] probabilitySum elemd probability elema)
> ([ ] probabilitySum elemd boolean)
[
drop
] [
-rot (elemd [ ] probabilitySum)
[ cons ] dip ([ elemd ] probabilitySum)
] ifte
] each drop ;

230
factor/stream.factor Normal file
View File

@ -0,0 +1,230 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
: <stream> ( -- stream )
! Create a stream object. A stream is a namespace with the following
! entries:
! - fflush
! - freadln -- you must provide an implementation!
! - fwriteln
! - fwrite -- you must provide an implementation!
! - fclose
! Note that you must extend this object and provide your own implementations
! of all entries except for fwriteln, which is defined to fwrite the string
! followed by the newline by default.
<namespace> [
( -- string )
[ "freadln not implemented." break ] @freadln
( string -- )
[ "fwrite not implemented." break ] @fwrite
( -- )
[ ] @fflush
( -- )
[ ] @fclose
( string -- )
[ $namespace fwrite "\n" $namespace fwrite ] @fwriteln
] extend ;
: <bytestream> ( in out -- stream )
! Creates a new stream for reading from the java.io.InputStream in, and
! writing to the java.io.OutputStream out.
<stream> [
@out
@in
( -- string )
[
$in [ "java.io.InputStream" ] "factor.FactorLib" "readLine"
jmethod jinvokeStatic
] @freadln
( string -- )
[
>bytes
$out [ "[B" ] "java.io.OutputStream" "write" jmethod jinvoke
] @fwrite
( -- )
[
$out [ ] "java.io.OutputStream" "flush" jmethod jinvoke
] @fflush
( -- )
[
$in [ ] "java.io.InputStream" "close" jmethod jinvoke
$out [ ] "java.io.OutputStream" "close" jmethod jinvoke
] @fclose
] extend ;
: <charstream> ( in out -- stream )
! Creates a new stream for reading from the java.io.BufferedReader in, and
! writing to the java.io.Reader out.
<stream> [
@out
@in
( -- string )
[
$in [ ] "java.io.BufferedReader" "readLine" jmethod jinvoke
] @freadln
( string -- )
[
$out [ "java.lang.String" ] "java.io.Writer" "write" jmethod jinvoke
] @fwrite
( -- )
[
$out [ ] "java.io.Writer" "flush" jmethod jinvoke
] @fflush
( -- )
[
$in [ ] "java.io.Reader" "close" jmethod jinvoke
$out [ ] "java.io.Writer" "close" jmethod jinvoke
] @fclose
] extend ;
: <filecr> ( path -- stream )
[ |java.lang.String ] |java.io.FileReader jconstructor jnew <breader>
f
<charstream> ;
: <filecw> ( path -- stream )
f
[ |java.lang.String ] |java.io.FileWriter jconstructor jnew <bwriter>
<charstream> ;
: <filebr> ( path -- stream )
[ |java.lang.String ] |java.io.FileInputStream jconstructor jnew
f
<bytestream> ;
: <filebw> ( path -- stream )
f
[ |java.lang.String ] |java.io.FileOutputStream jconstructor jnew
<bytestream> ;
: <bwriter> (writer -- bwriter)
[ |java.io.Writer ] |java.io.BufferedWriter jconstructor jnew ;
: <owriter> (outputstream -- owriter)
[ |java.io.OutputStream ] |java.io.OutputStreamWriter jconstructor jnew ;
: read ( -- string )
$stdio freadln ;
: write ( string -- )
$stdio [ fwrite ] [ fflush ] cleave ;
: print ( string -- )
$stdio [ fwriteln ] [ fflush ] cleave ;
: fflush ( stream -- )
[ $fflush call ] bind ;
: freadln ( stream -- string )
[ $freadln call ] bind ;
: fwriteln ( string stream -- )
[ $fwriteln call ] bind ;
: fwrite ( string stream -- )
[ $fwrite call ] bind ;
: fclose ( stream -- )
[ $fclose call ] bind ;
: fcopy ( from to -- )
! Copy the contents of the bytestream 'from' to the bytestream 'to'.
[ [ $in ] bind ] dip
[ $out ] bind
[ "java.io.InputStream" "java.io.OutputStream" ]
"factor.FactorLib" "copy" jmethod jinvokeStatic ;
"java.lang.System" "in" jfield jvarStatic$ <ireader> <breader> @stdin
"java.lang.System" "out" jfield jvarStatic$ <owriter> @stdout
$stdin $stdout <charstream> @stdio
!(file -- freader)
|<freader> [
[ |java.lang.String ] |java.io.FileReader jconstructor jnew <breader>
] define
: <file> (path -- file)
dup "java.io.File" is not [
[ "java.lang.String" ] "java.io.File" jconstructor jnew
] when ;
: exists? (file -- boolean)
<file> [ ] "java.io.File" "exists" jmethod jinvoke ;
: directory? (file -- boolean)
<file> [ ] "java.io.File" "isDirectory" jmethod jinvoke ;
: directory ( file -- listing )
<file> [ ] "java.io.File" "list" jmethod jinvoke
array>list ;
: rename ( from to -- )
! Rename file 'from' to 'to'. These can be paths or
! java.io.File instances.
<file> swap <file>
[ "java.io.File" ] "java.io.File" "renameTo"
jmethod jinvoke ;
!(string -- reader)
|<sreader> [
[ |java.lang.String ] |java.io.StringReader jconstructor jnew
] define
: close (stream --)
dup "java.io.Reader" is
[ ] "java.io.Reader" "close" jmethod
[ ] "java.io.Writer" "close" jmethod
?
jinvoke ;
: exec (args -- exitCode)
[ "[Ljava.lang.String;" ] "factor.FactorLib" "exec" jmethod jinvokeStatic ;
!(stream -- string)
|read* [
[ ] |java.io.BufferedReader |readLine jmethod jinvoke
] define
: print* (string stream --)
tuck write*
"\n" swap write* ;
!(string stream --)
|write* [
tuck
[ |java.lang.String ] |java.io.Writer |write jmethod jinvoke
[ ] |java.io.Writer |flush jmethod jinvoke
] define

137
factor/strings.factor Normal file
View File

@ -0,0 +1,137 @@
!:folding=indent:collapseFolds=1:
! $Id$
!
! Copyright (C) 2003 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.
! Used by chars>entities
[
[ #\< , "&lt;" ]
[ #\> , "&gt;" ]
[ #\& , "&amp;" ]
! Bad parser!
! [ #\' , "&apos;" ]
! [ #\" , "&quot;" ]
] @entities
: >bytes ( string -- array )
! Converts a string to an array of ASCII bytes. An exception is thrown
! if the string contains non-ASCII characters.
"ASCII" swap
[ "java.lang.String" ] "java.lang.String" "getBytes" jmethod jinvoke ;
: cat ([ "a" "b" "c" ] -- "abc")
[ "factor.FactorList" ] "factor.FactorLib" "cat" jmethod jinvokeStatic ;
: cat2 ("a" "b" -- "ab")
[ "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "cat2" jmethod jinvokeStatic ;
: cat3 ("a" "b" "c" -- "abc")
[ "java.lang.Object" "java.lang.Object" "java.lang.Object" ]
"factor.FactorLib" "cat3" jmethod jinvokeStatic ;
: cat4 ("a" "b" "c" "d" -- "abcd")
cat2 cat3 ;
: chars>entities (str -- str)
! Convert <, >, &, ' and " to HTML entities.
"" [ dup $entities assoc dup [ nip ] [ drop ] ifte ] strmap ;
: group (index match --)
[ "int" ] "java.util.regex.Matcher" "group"
jmethod jinvoke ;
: groupCount (matcher -- count)
[ ] "java.util.regex.Matcher" "groupCount"
jmethod jinvoke ;
: groups* (matcher -- list)
[
[
dup groupCount [
succ over group swap
] times* drop
] cons expand
] [matches] ;
: groups (input regex -- list)
<regex> <matcher> groups* ;
: [matches] ( matcher code -- boolean )
! If the matcher's matches* function returns true,
! evaluate the code with the matcher at the top of the
! stack. Otherwise, pop the matcher off the stack and
! push f.
[ dup matches* ] dip [ drop f ] ifte ;
: <matcher> (string pattern -- matcher)
[ "java.lang.CharSequence" ]
"java.util.regex.Pattern" "matcher"
jmethod jinvoke ;
: matches* (matcher -- boolean)
[ ] "java.util.regex.Matcher" "matches"
jmethod jinvoke ;
: matches (input regex -- boolean)
<regex> <matcher> matches* ;
: replace* ( replace matcher -- string )
[ "java.lang.String" ] "java.util.regex.Matcher"
"replaceAll" jmethod jinvoke ;
: replace ( input regex replace -- string )
! Replaces all occurrences of the regex in the input string
! with the replace string.
-rot <regex> <matcher> replace* ;
: <regex> (pattern -- regex)
! Compile the regex, if its not already compiled.
dup "java.util.regex.Pattern" is not [
[ "java.lang.String" ] "java.util.regex.Pattern" "compile"
jmethod jinvokeStatic
] when ;
: strget (index str -- char)
[ "int" ] "java.lang.String" "charAt" jmethod jinvoke ;
: strlen (str -- length)
[ ] "java.lang.String" "length" jmethod jinvoke ;
: streach (str [ code ] --)
! Execute the code, with each character of the string pushed onto the
! stack.
over strlen [
-rot 2dup [ [ strget ] dip call ] 2dip
] times* 2drop ;
: strmap (str initial [ code ] -- [ mapping ])
! If the 'initial' parameter is f, turn it into "".
! Maybe cat should handle this instead?
[ dup [ drop "" ] unless ] dip
swapd [ ] cons cons cons
restack
streach
unstack cat ;

View File

@ -0,0 +1,213 @@
/***
* 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

@ -0,0 +1,293 @@
/***
* 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

@ -0,0 +1,109 @@
/***
* 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

@ -0,0 +1,158 @@
/***
* 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

@ -0,0 +1,163 @@
/***
* 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

@ -0,0 +1,310 @@
/***
* 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

@ -0,0 +1,288 @@
/***
* 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

@ -0,0 +1,70 @@
/***
* 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;
}

266
org/objectweb/asm/Item.java Normal file
View File

@ -0,0 +1,266 @@
/***
* 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

@ -0,0 +1,327 @@
/***
* 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);
}
}

763
org/objectweb/asm/Type.java Normal file
View File

@ -0,0 +1,763 @@
/***
* 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();
}
}

View File

@ -0,0 +1,335 @@
/**
* 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.attrs;
import java.util.LinkedList;
import java.util.List;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
/**
* Annotation data contains an annotated type and its array of the member-value
* pairs. Structure is in the following format:
* <pre>
* annotation {
* u2 type_index;
* u2 num_member_value_pairs;
* {
* u2 member_name_index;
* member_value value;
* } member_value_pairs[num_member_value_pairs];
* }
* </pre>
* The items of the annotation structure are as follows:
* <dl>
* <dt>type_index</dt>
* <dd>The value of the type_index item must be a valid index into the constant_pool
* table. The constant_pool entry at that index must be a CONSTANT_Class_info
* structure representing the annotation interface corresponding to the
* annotation represented by this annotation structure.</dd>
* <dt>num_member_value_pairs</dt>
* <dd>The value of the num_member_value_pairs item gives the number of member-value
* pairs in the annotation represented by this annotation structure. Note that a
* maximum of 65535 member-value pairs may be contained in a single annotation.</dd>
* <dt>member_value_pairs</dt>
* <dd>Each value of the member_value_pairs table represents a single member-value
* pair in the annotation represented by this annotation structure.
* Each member_value_pairs entry contains the following two items:
* <dt>member_name_index</dt>
* <dd>The value of the member_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the name of the annotation type
* member corresponding to this member_value_pairs entry.</dd>
* <dt>value</dt>
* <dd>The value item represents the value in the member-value pair represented by
* this member_value_pairs entry.</dd>
* </dl>
* </dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=175">JSR 175 : A Metadata
* Facility for the Java Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class Annotation {
public String type;
public List memberValues = new LinkedList();
public void add (String name, Object value) {
memberValues.add(new Object[]{name, value});
}
/**
* Reads annotation data structures.
*
* @param cr the class that contains the attribute to be read.
* @param off index of the first byte of the data structure.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass readClass} or {@link
* ClassReader#readConst readConst}.
*
* @return offset position in bytecode after reading annotation
*/
public int read (ClassReader cr, int off, char[] buf) {
type = cr.readClass(off, buf);
int numMemberValuePairs = cr.readUnsignedShort(off + 2);
off += 4;
for (int i = 0; i < numMemberValuePairs; i++) {
String memberName = cr.readUTF8(off, buf);
AnnotationMemberValue value = new AnnotationMemberValue();
off = value.read(cr, off + 2, buf);
memberValues.add(new Object[]{memberName, value});
}
return off;
}
/**
* Writes annotation data structures.
*
* @param bv the byte array form to store data structures.
* @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.
*/
public void write (ByteVector bv, ClassWriter cw) {
bv.putShort(cw.newClass(type));
bv.putShort(memberValues.size());
for (int i = 0; i < memberValues.size(); i++) {
Object[] value = (Object[])memberValues.get(i);
bv.putShort(cw.newUTF8((String)value[0]));
((AnnotationMemberValue)value[1]).write(bv, cw);
}
}
public void dump (StringBuffer buf, String varName) {
buf.append("Annotation ").append(varName).append(" = new Annotation();\n");
buf.append(varName).append(".type = \"").append(type).append("\";\n");
if (memberValues.size() > 0) {
buf.append("{\n");
for (int i = 0; i < memberValues.size(); i++) {
Object[] values = (Object[])memberValues.get(i);
String val = varName + "val" + i;
((AnnotationMemberValue)values[1]).dump(buf, val);
buf.append(varName).append(".add( \"")
.append(values[0]).append("\", ").append(val).append(");\n");
}
buf.append("}\n");
}
}
/**
* Utility method to read List of annotations. Each element of annotations
* List will have Annotation instance.
*
* @param annotations the List to store parameters annotations.
* @param cr the class that contains the attribute to be read.
* @param off index of the first byte of the data structure.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass readClass} or {@link
* ClassReader#readConst readConst}.
*
* @return offset position in bytecode after reading annotations
*/
public static int readAnnotations (
List annotations, ClassReader cr, int off, char[] buf) {
int size = cr.readUnsignedShort(off);
off += 2;
for (int i = 0; i < size; i++) {
Annotation ann = new Annotation();
off = ann.read(cr, off, buf);
annotations.add(ann);
}
return off;
}
/**
* Utility method to read List of parameters annotations.
*
* @param parameters the List to store parameters annotations.
* Each element of the parameters List will have List of Annotation
* instances.
* @param cr the class that contains the attribute to be read.
* @param off index of the first byte of the data structure.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass readClass} or {@link
* ClassReader#readConst readConst}.
*/
public static void readParameterAnnotations (
List parameters, ClassReader cr, int off, char[] buf) {
int numParameters = cr.b[off++] & 0xff;
for (int i = 0; i < numParameters; i++) {
List annotations = new LinkedList();
off = Annotation.readAnnotations(annotations, cr, off, buf);
parameters.add(annotations);
}
}
/**
* Utility method to write List of annotations.
*
* @param bv the byte array form to store data structures.
* @param annotations the List of annotations to write.
* Elements should be instances of the Annotation class.
* @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.
*
* @return the byte array form with saved annotations.
*/
public static ByteVector writeAnnotations (ByteVector bv,
List annotations, ClassWriter cw) {
bv.putShort(annotations.size());
for (int i = 0; i < annotations.size(); i++) {
((Annotation)annotations.get(i)).write(bv, cw);
}
return bv;
}
/**
* Utility method to write List of parameters annotations.
*
* @param bv the byte array form to store data structures.
* @param parametars the List of parametars to write. Elements should be
* instances of the List that contains instances of the Annotation class.
* @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.
*
* @return the byte array form with saved annotations.
*/
public static ByteVector writeParametersAnnotations (ByteVector bv,
List parameters,
ClassWriter cw) {
bv.putByte(parameters.size());
for (int i = 0; i < parameters.size(); i++) {
writeAnnotations(bv, (List)parameters.get(i), cw);
}
return bv;
}
public static void dumpAnnotations (StringBuffer buf,
String varName, List annotations) {
if (annotations.size() > 0) {
buf.append("{\n");
for (int i = 0; i < annotations.size(); i++) {
String val = varName + "ann" + i;
((Annotation)annotations.get(i)).dump(buf, val);
buf.append(varName).append(".add( ").append(val).append(");\n");
}
buf.append("}\n");
}
}
public static void dumpParameterAnnotations (StringBuffer buf,
String varName,
List parameters) {
// TODO implement method Annotation.dumpParameterAnnotations
if (parameters.size() > 0) {
buf.append("{\n");
for (int i = 0; i < parameters.size(); i++) {
String val = varName + "param" + i;
dumpAnnotations(buf, val, (List)parameters.get(i));
buf.append(varName).append(".add( ").append(val).append(");\n");
}
buf.append("}\n");
}
}
/**
* Returns annotation values in the format described in JSR-175 for Java
* source code.
*/
public static String stringAnnotations (List annotations) {
StringBuffer sb = new StringBuffer();
if (annotations.size() > 0) {
for (int i = 0; i < annotations.size(); i++) {
sb.append('\n').append(annotations.get(i));
}
}
return sb.toString();
}
/**
* Returns parameter annotation values in the format described in JSR-175
* for Java source code.
*/
public static String stringParameterAnnotations (List parameters) {
StringBuffer sb = new StringBuffer();
String sep = "";
for (int i = 0; i < parameters.size(); i++) {
sb.append(sep).append(stringAnnotations((List)parameters.get(i)));
sep = ", ";
}
return sb.toString();
}
/**
* Returns value in the format described in JSR-175 for Java source code.
*/
public String toString () {
StringBuffer sb = new StringBuffer("@").append(type);
// shorthand syntax for marker annotation
if (memberValues.size() > 0) {
sb.append(" ( ");
String sep = "";
for (int i = 0; i < memberValues.size(); i++) {
Object[] value = (Object[])memberValues.get(i);
// using shorthand syntax for single-member annotation
if (memberValues.size() > 1) {
sb.append(sep).append(value[0]).append(" = ");
}
sb.append(value[1]);
sep = ", ";
}
sb.append(" )");
}
return sb.toString();
}
}

View File

@ -0,0 +1,120 @@
/**
* 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.attrs;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import java.util.Map;
/**
* The AnnotationDefault attribute is a variable length attribute in the
* attributes table of certain method_info structures, namely those representing
* members of annotation types. The AnnotationDefault attribute records the
* default value for the member represented by the method_info structure. Each
* method_info structures representing a member of an annotation types may contain
* at most one AnnotationDefault attribute. The JVM must make this default value
* available so it can be applied by appropriate reflective APIs.
* <p>
* The AnnotationDefault attribute has the following format:
* <pre>
* AnnotationDefault_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* member_value default_value;
* }
* </pre>
* The items of the AnnotationDefault structure are as follows:
* <dl>
* <dt>attribute_name_index</dt>
* <dd>The value of the attribute_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the string "AnnotationDefault".</dd>
* <dt>attribute_length</dt>
* <dd>The value of the attribute_length item indicates the length of the attribute,
* excluding the initial six bytes. The value of the attribute_length item is
* thus dependent on the default value.</dd>
* <dt>default_value</dt>
* <dd>The default_value item represents the default value of the annotation type
* {@link org.objectweb.asm.attrs.AnnotationMemberValue member} whose default
* value is represented by this AnnotationDefault attribute.</dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=175">JSR 175 : A Metadata
* Facility for the Java Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class AnnotationDefaultAttribute extends Attribute implements Dumpable {
public AnnotationMemberValue defaultValue;
public AnnotationDefaultAttribute () {
super("AnnotationDefault");
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
AnnotationDefaultAttribute ann = new AnnotationDefaultAttribute();
ann.defaultValue = new AnnotationMemberValue();
ann.defaultValue.read(cr, off, buf);
return ann;
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
return defaultValue.write(new ByteVector(), cw);
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("AnnotationDefaultAttribute ").append(varName)
.append(" = new AnnotationDefaultAttribute();\n");
defaultValue.dump(buf, varName + "Val");
buf.append(varName).append(".defaultValue = ")
.append(varName).append("Val;\n");
}
/**
* Returns value in the format described in JSR-175 for Java source code.
*/
public String toString () {
return "default " + defaultValue;
}
}

View File

@ -0,0 +1,466 @@
/**
* 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.attrs;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
/**
* The member_value structure is a discriminated union representing the value of a
* member-value pair. It is used to represent values in all class file attributes
* that describe annotations ( RuntimeVisibleAnnotations, RuntimeInvisibleAnnotations,
* RuntimeVisibleParameterAnnotations, and RuntimeInvisibleParameterAnnotations).
* <p>
* The member_value structure has the following format:
* <pre>
* member_value {
* u1 tag;
* union {
* u2 const_value_index;
* {
* u2 type_name_index;
* u2 const_name_index;
* } enum_const_value;
* u2 class_info_index;
* annotation annotation_value;
* {
* u2 num_values;
* member_value values[num_values];
* } array_value;
* } value;
* }
* </pre>
* The items of the member_value structure are as follows:
* <dl>
* <dt>tag</dt>
* <dd>The tag item indicates the member type of this member-value pair. The letters
* 'B', 'C', 'D', 'F', 'I', 'J', 'S', and 'Z' indicate a primitive type. These
* letters are interpreted as BaseType characters (Table 4.2). The other legal
* values for tag are listed with their interpretations in this table:
* <pre>
* tag value Member Type
* 's' String
* 'e' enum constant
* 'c' class
* '@' annotation type
* '[' array
* </pre>
* </dd>
* <dt>value</dt>
* <dd>The value item represents the value of this annotation element. This item is
* a union. The tag item, above, determines which item of the union is to be used:
* <dl>
* <dt>const_value_index</dt>
* <dd>The const_value_index item is used if the tag item is one of 'B', 'C', 'D',
* 'F', 'I', 'J', 'S', 'Z', or 's'. The value of the const_value_index item must
* be a valid index into the constant_pool table. The constant_pool entry at
* that index must be of the correct entry type for the field type designated by
* the tag item, as specified in table 4.6, with one exception: if the tag is
* 's', the the value of the const_value_index item must be the index of a
* CONSTANT_Utf8 structure, rather than a CONSTANT_String.</dd>
* <dt>enum_const_value</dt>
* <dd>The enum_const_value item is used if the tag item is 'e'. The
* enum_const_value item consists of the following two items:
* <dl>
* <dt>type_name_index</dt>
* <dd>The value of the type_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the binary name (JLS 13.1) of the
* type of the enum constant represented by this member_value structure.</dd>
* <dt>const_name_index</dt>
* <dd>The value of the const_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the simple name of the enum
* constant represented by this member_value structure.</dd>
* </dl>
* </dd>
* <dt>class_info_index</dt>
* <dd>The class_info_index item is used if the tag item is 'c'. The
* class_info_index item must be a valid index into the constant_pool table.
* The constant_pool entry at that index must be a CONSTANT_Class_info
* structure representing the class represented by this member_value
* structure.</dd>
* <dt>annotation_value</dt>
* <dd>The annotation_value item is used if the tag item is '@'. The member_value
* structure represents a "nested" {@link org.objectweb.asm.attrs.Annotation annotation}.</dd>
* <dt>array_value</dt>
* <dd>The array_value item is used if the tag item is '['. The array_value item
* consists of the following two items:
* <dl>
* <dt>num_values</dt>
* <dd>The value of the num_values item gives the number of elements in the
* array-typed value represented by this member_value structure. Note that a
* maximum of 65535 elements are permitted in an array-typed member value.</dd>
* <dt>values</dt>
* <dd>Each element of the values table gives the value of an element of the
* array-typed value represented by this {@link AnnotationMemberValue member_value structure}.</dd>
* </dl>
* </dd>
* </dl>
* </dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=175">JSR 175 : A Metadata
* Facility for the Java Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class AnnotationMemberValue {
private static final String TAGS = "BCDFIJSZsec@[";
private static final Class[] TYPES = new Class[]{
Byte.class,
Character.class,
Double.class,
Float.class,
Integer.class,
Long.class,
Short.class,
Boolean.class,
String.class,
EnumConstValue.class, // should we use java.lang.Enum in the future?
Type.class,
Annotation.class,
AnnotationMemberValue[].class};
// private int tag;
private Object value;
public AnnotationMemberValue () {
}
public AnnotationMemberValue (Object value) {
this.value = value;
}
public int getTag () {
for (int i = 0; i < TYPES.length; i++) {
if (value.getClass().equals(TYPES[i])) return TAGS.charAt(i);
}
return -1;
}
public Object getValue () {
return value;
}
/**
* Reads member_value data structures.
*
* @param cr the class that contains the attribute to be read.
* @param off index of the first byte of the data structure.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass readClass} or {@link
* ClassReader#readConst readConst}.
*
* @return offset position in bytecode after reading annotation
*/
public int read (ClassReader cr, int off, char[] buf) {
int tag = cr.readByte(off++);
switch (tag) {
case 'B': // pointer to CONSTANT_Byte
case 'C': // pointer to CONSTANT_Char
case 'D': // pointer to CONSTANT_Double
case 'F': // pointer to CONSTANT_Float
case 'I': // pointer to CONSTANT_Integer
case 'J': // pointer to CONSTANT_Long
case 'S': // pointer to CONSTANT_Short
case 'Z': // pointer to CONSTANT_Boolean
value = cr.readConst(cr.readUnsignedShort(off), buf);
off += 2;
break;
case 's': // pointer to CONSTANT_Utf8
value = cr.readUTF8(off, buf);
off += 2;
break;
case 'e': // enum_const_value
// TODO verify the data structures
value = new EnumConstValue(cr.readUTF8(off, buf), cr.readUTF8(off + 2, buf));
off += 4;
break;
case 'c': // class_info
value = Type.getType(cr.readClass(off, buf));
off += 2;
break;
case '@': // annotation_value
value = new Annotation();
off = ((Annotation)value).read(cr, off, buf);
break;
case '[': // array_value
int size = cr.readUnsignedShort(off);
off += 2;
AnnotationMemberValue[] v = new AnnotationMemberValue[size];
value = v;
for (int i = 0; i < size; i++) {
v[i] = new AnnotationMemberValue();
off = v[i].read(cr, off, buf);
}
break;
}
return off;
}
/**
* Writes member_value data structures.
*
* @param bv the byte array form to store data structures.
* @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.
*/
public ByteVector write (ByteVector bv, ClassWriter cw) {
int tag = getTag();
bv.putByte(tag);
switch (tag) {
case 'B': // pointer to CONSTANT_Byte
case 'C': // pointer to CONSTANT_Char
case 'D': // pointer to CONSTANT_Double
case 'F': // pointer to CONSTANT_Float
case 'I': // pointer to CONSTANT_Integer
case 'J': // pointer to CONSTANT_Long
case 'S': // pointer to CONSTANT_Short
case 'Z': // pointer to CONSTANT_Boolean
bv.putShort(cw.newConst(value));
break;
case 's': // pointer to CONSTANT_Utf8
bv.putShort(cw.newUTF8((String)value));
break;
case 'e': // enum_const_value
((EnumConstValue)value).write(bv, cw);
break;
case 'c': // class_info
bv.putShort(cw.newClass(((Type)value).getDescriptor()));
break;
case '@': // annotation_value
((Annotation)value).write(bv, cw);
break;
case '[': // array_value
AnnotationMemberValue[] v = (AnnotationMemberValue[])value;
bv.putShort(v.length);
for (int i = 0; i < v.length; i++) {
v[i].write(bv, cw);
}
break;
}
return bv;
}
public void dump (StringBuffer buf, String valName) {
int tag = getTag();
String objName = valName.concat("obj");
switch (tag) {
case 'B': // pointer to CONSTANT_Byte
buf.append("Object ").append(objName)
.append(" = new Byte(").append(value).append(");\n");
break;
case 'C': // pointer to CONSTANT_Char
buf.append("Object ").append(objName)
.append(" = new Character((char)").append(value).append(");\n");
break;
case 'D': // pointer to CONSTANT_Double
buf.append("Object ").append(objName)
.append(" = new Double((double)").append(value).append(");\n");
break;
case 'F': // pointer to CONSTANT_Float
buf.append("Object ").append(objName)
.append(" = new Float((float)").append(value).append(");\n");
break;
case 'I': // pointer to CONSTANT_Integer
buf.append("Object ").append(objName)
.append(" = new Integer((int)").append(value).append(");\n");
break;
case 'J': // pointer to CONSTANT_Long
buf.append("Object ").append(objName)
.append(" = new Long((long)").append(value).append(");\n");
break;
case 'S': // pointer to CONSTANT_Short
buf.append("Object ").append(objName)
.append(" = new Short((short)").append(value).append(");\n");
break;
case 'Z': // pointer to CONSTANT_Boolean
buf.append("Object ").append(objName)
.append(" = new Boolean(").append(value).append(");\n");
break;
case 's': // pointer to CONSTANT_Utf8
buf.append("Object ").append(objName)
.append(" = \"").append(value).append("\";\n");
break;
case 'e': // enum_const_value
EnumConstValue e = (EnumConstValue)value;
buf.append("Object ").append(objName)
.append(" = new AnnotationMemberValue.EnumConstValue(\"")
.append(e.typeName).append("\", \"").append(e.constName)
.append("\"));\n");
break;
case 'c': // class_info
Type t = (Type)value;
buf.append("Object ").append(objName).
append(" = Type.getType(\"" + t.getDescriptor() + "\");\n");
break;
case '@': // annotation_value
((Annotation)value).dump(buf, objName);
break;
case '[': // array_value
AnnotationMemberValue[] v = (AnnotationMemberValue[])value;
buf.append("AnnotationMemberValue[] ").append(objName)
.append(" = new AnnotationMemberValue[")
.append(v.length).append("]\n;");
buf.append("{\n");
buf.append("Object av = null;\n");
for (int i = 0; i < v.length; i++) {
v[i].dump(buf, objName + i);
buf.append(objName)
.append("[").append(i).append("] = ").append(objName + i);
}
buf.append("};\n");
break;
}
buf.append("AnnotationMemberValue ").append(valName);
buf.append(" = new AnnotationMemberValue( ").append(objName).append(");\n");
}
/**
* Returns value in the format described in JSR-175 for Java source code.
*/
public String toString () {
StringBuffer sb = new StringBuffer();
// TODO
int tag = getTag();
switch (tag) {
case 's': // pointer to CONSTANT_Utf8
sb.append('"').append(value).append('"');
break;
case 'B': // pointer to CONSTANT_Byte
case 'C': // pointer to CONSTANT_Char
case 'D': // pointer to CONSTANT_Double
case 'F': // pointer to CONSTANT_Float
case 'I': // pointer to CONSTANT_Integer
case 'J': // pointer to CONSTANT_Long
case 'S': // pointer to CONSTANT_Short
case 'Z': // pointer to CONSTANT_Boolean
case 'e': // enum_const_value
sb.append(value);
break;
case 'c': // class_info
// TODO verify if the following is correct
sb.append(value);
break;
case '@': // annotation_value
// TODO verify if the following is correct
sb.append(value);
break;
case '[': // array_value
AnnotationMemberValue[] v = (AnnotationMemberValue[])value;
if (v.length > 0) {
sb.append("{ ");
String sep = "";
for (int i = 0; i < v.length; i++) {
sb.append(sep).append(v[i].toString());
sep = ", ";
}
sb.append(" }");
}
break;
}
return sb.toString();
}
/**
* Container class used to store enum_const_value structure.
*/
public static class EnumConstValue {
public String typeName;
public String constName;
public EnumConstValue (String typeName, String constName) {
this.typeName = typeName;
this.constName = constName;
}
public void write (ByteVector bv, ClassWriter cw) {
// TODO verify the data structures
bv.putShort(cw.newUTF8(typeName));
bv.putShort(cw.newUTF8(constName));
}
// public boolean equals( Object o) {
// EnumConstValue v = ( EnumConstValue) o;
// return v.constName.equals( )
// }
public String toString () {
// TODO verify print enum
return typeName + "." + constName;
}
}
}

View File

@ -0,0 +1,61 @@
/**
* 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.attrs;
import java.util.Map;
/**
* Dumpable interface has to be implemented by the Attribute class
* in order to support DumpClassVisitor and DumpCodeVisitor.
*
* Implementation should print the ASM code that generates
* attribute data structures for current attribute state.
*
* @author Eugene Kuleshov
*/
public interface Dumpable {
/**
* Dump attribute data into ASM code.
*
* @param buf A buffer used for printing java code.
* @param varName name of the variable in a printed code used to store
* attribute instance.
* @param labelNames map of label instances to their names.
*/
void dump (StringBuffer buf, String varName, Map labelNames);
}

View File

@ -0,0 +1,115 @@
/**
* 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.attrs;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* The EnclosingMethod attribute is an optional fixed-length attribute
* in the attributes table of the ClassFile structure. A class must
* have an EnclosingMethod attribute if and only if it is a local
* class or an anonymous class. A class may have no more than one
* EnclosingMethod attribute.
* <p>
* The EnclosingMethod attribute has the following format:
* <pre>
* EnclosingMethod_attribute {
* u2 attribute_name;
* u4 attribute_length;
* u2 method_descriptor_index;
* }
* </pre>
* The items of the EnclosingMethod_attribute structure are as follows:
* <dl>
* <dt>attribute_name_index</dt>
* <dd>The value of the attribute_name_index item must be a valid index
* into the constant_pool table. The constant_pool entry at that index
* must be a CONSTANT_Utf8_info structure representing the string
* "EnclosingMethod".</dd>
* <dt>attribute_length</dt>
* <dd>The value of the attribute_length item is zero.</dd>
* <dt>method_descriptor_index</dt>
* <dd>The value of the method_descriptor_index item must be a valid
* index into the constant_pool table. The constant_pool entry at that
* index must be a CONSTANT_Utf8_info structure representing a valid
* method descriptor (JLS 4.4.3). It is the responsibility of the
* Java compiler to ensure that the method identified via the
* method_descriptor_index is indeed the closest lexically enclosing
* method of the class that contains this EnclosingMethod attribute.</dd>
* </dl>
*
* @author Eugene Kuleshov
*/
public class EnclosingMethodAttribute extends Attribute implements Dumpable {
public String methodDescriptor;
public EnclosingMethodAttribute () {
super("EnclosingMethod");
}
public EnclosingMethodAttribute (String methodDescriptor) {
this();
this.methodDescriptor = methodDescriptor;
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
return new EnclosingMethodAttribute(cr.readUTF8(off, buf));
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
return new ByteVector().putShort(cw.newUTF8(methodDescriptor));
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("EnclosingMethodAttribute ").append(varName)
.append(" = new EnclosingMethodAttribute(\"")
.append(methodDescriptor).append("\");\n");
}
public String toString () {
return methodDescriptor;
}
}

View File

@ -0,0 +1,133 @@
/**
* 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.attrs;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* The RuntimeInvisibleAnnotations attribute is similar to the
* RuntimeVisibleAnnotations attribute, except that the annotations represented by
* a RuntimeInvisibleAnnotations attribute must not be made available for return
* by reflective APIs, unless the JVM has been instructed to retain these
* annotations via some implementation-specific mechanism such as a command line
* flag. In the absence of such instructions, the JVM ignores this attribute.
* <p>
* The RuntimeInvisibleAnnotations attribute is a variable length attribute in the
* attributes table of the ClassFile, field_info, and method_info structures. The
* RuntimeInvisibleAnnotations attribute records runtime-invisible Java
* programming language annotations on the corresponding class, method, or field.
* Each ClassFile, field_info, and method_info structure may contain at most one
* RuntimeInvisibleAnnotations attribute, which records all the runtime-invisible
* Java programming language annotations on the corresponding program element.
* <p>
* The RuntimeInvisibleAnnotations attribute has the following format:
* <pre>
* RuntimeInvisibleAnnotations_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 num_annotations;
* annotation annotations[num_annotations];
* }
* </pre>
* The items of the RuntimeInvisibleAnnotations structure are as follows:
* <dl>
* <dt>attribute_name_index</dt>
* <dd>The value of the attribute_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the string
* "RuntimeInvisibleAnnotations".</dd>
* <dt>attribute_length</dt>
* <dd>The value of the attribute_length item indicates the length of the
* attribute, excluding the initial six bytes. The value of the
* attribute_length item is thus dependent on the number of runtime-invisible
* annotations represented by the structure, and their values.</dd>
* <dt>num_annotations</dt>
* <dd>The value of the num_annotations item gives the number of runtime-invisible
* annotations represented by the structure. Note that a maximum of 65535
* runtime-invisible Java programming language annotations may be directly
* attached to a program element.</dd>
* <dt>annotations</dt>
* <dd>Each value of the annotations table represents a single runtime-invisible
* {@link org.objectweb.asm.attrs.Annotation annotation} on a program element.</dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=175">JSR 175 : A Metadata
* Facility for the Java Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class RuntimeInvisibleAnnotations extends Attribute implements Dumpable {
public List annotations = new LinkedList();
public RuntimeInvisibleAnnotations () {
super("RuntimeInvisibleAnnotations");
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
RuntimeInvisibleAnnotations atr = new RuntimeInvisibleAnnotations();
Annotation.readAnnotations(atr.annotations, cr, off, buf);
return atr;
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
return Annotation.writeAnnotations(new ByteVector(), annotations, cw);
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("RuntimeInvisibleAnnotations ").append(varName)
.append(" = new RuntimeInvisibleAnnotations();\n");
Annotation.dumpAnnotations(buf, varName, annotations);
}
/**
* Returns value in the format described in JSR-175 for Java source code.
*/
public String toString () {
return Annotation.stringAnnotations(annotations);
}
}

View File

@ -0,0 +1,152 @@
/**
* 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.attrs;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* The RuntimeInvisibleParameterAnnotations attribute is similar to the
* RuntimeVisibleParameterAnnotations attribute, except that the annotations
* represented by a RuntimeInvisibleParameterAnnotations attribute must not be
* made available for return by reflective APIs, unless the JVM has specifically
* been instructed to retain these annotations via some implementation-specific
* mechanism such as a command line flag. In the absence of such instructions, the
* JVM ignores this attribute.
* <p>
* The RuntimeInvisibleParameterAnnotations attribute is a variable length
* attribute in the attributes table of the method_info structure. The
* RuntimeInvisibleParameterAnnotations attribute records runtime-invisible Java
* programming language annotations on the parameters of the corresponding method.
* Each method_info structure may contain at most one
* RuntimeInvisibleParameterAnnotations attribute, which records all the
* runtime-invisible Java programming language annotations on the parameters of
* the corresponding method.
* <p>
* The RuntimeInvisibleParameterAnnotations attribute has the following format:
* <pre>
* RuntimeInvisibleParameterAnnotations_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u1 num_parameters;
* {
* u2 num_annotations;
* annotation annotations[num_annotations];
* } parameter_annotations[num_parameters];
* }
* </pre>
* The items of the RuntimeInvisibleParameterAnnotations structure are as follows:
* <dl>
* <dt>attribute_name_index</dt>
* <dd>The value of the attribute_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the string
* "RuntimeInvisibleParameterAnnotations".</dd>
* <dt>attribute_length</dt>
* <dd>The value of the attribute_length item indicates the length of the attribute,
* excluding the initial six bytes. The value of the attribute_length item is
* thus dependent on the number of parameters, the number of runtime-invisible
* annotations on each parameter, and their values.</dd>
* <dt>num_parameters</dt>
* <dd>The value of the num_parameters item gives the number of parameters of the
* method represented by the method_info structure on which the annotation
* occurs. (This duplicates information that could be extracted from the method
* descriptor.)</dd>
* <dt>parameter_annotations</dt>
* <dd>Each value of the parameter_annotations table represents all of the
* runtime-invisible annotations on a single parameter. The sequence of values
* in the table corresponds to the sequence of parameters in the method
* signature. Each parameter_annotations entry contains the following two items:
* <dl>
* <dt>num_annotations</dt>
* <dd>The value of the num_annotations item indicates the number of
* runtime-invisible annotations on the parameter corresponding to the sequence
* number of this parameter_annotations element.</dd>
* <dt>annotations</dt>
* <dd>Each value of the annotations table represents a single runtime-invisible
* {@link Annotation annotation} on the parameter corresponding to the sequence
* number of this parameter_annotations element.</dd>
* </dl>
* </dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=175">JSR 175 : A Metadata
* Facility for the Java Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class RuntimeInvisibleParameterAnnotations
extends Attribute implements Dumpable
{
public List parameters = new LinkedList();
public RuntimeInvisibleParameterAnnotations () {
super("RuntimeInvisibleParameterAnnotations");
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
RuntimeInvisibleParameterAnnotations atr =
new RuntimeInvisibleParameterAnnotations();
Annotation.readParameterAnnotations(atr.parameters, cr, off, buf);
return atr;
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
return Annotation.writeParametersAnnotations(
new ByteVector(), parameters, cw);
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("RuntimeInvisibleParameterAnnotations ").append(varName)
.append(" = new RuntimeInvisibleParameterAnnotations();\n");
Annotation.dumpParameterAnnotations(buf, varName, parameters);
}
public String toString () {
return Annotation.stringParameterAnnotations(parameters);
}
}

View File

@ -0,0 +1,129 @@
/**
* 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.attrs;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* The RuntimeVisibleAnnotations attribute is a variable length attribute in the
* attributes table of the ClassFile, field_info, and method_info structures. The
* RuntimeVisibleAnnotations attribute records runtime-visible Java programming
* language annotations on the corresponding class, method, or field. Each
* ClassFile, field_info, and method_info structure may contain at most one
* RuntimeVisibleAnnotations attribute, which records all the runtime-visible Java
* programming language annotations on the corresponding program element. The JVM
* must make these annotations available so they can be returned by the
* appropriate reflective APIs.
* <p>
* The RuntimeVisibleAnnotations attribute has the following format:
* <pre>
* RuntimeVisibleAnnotations_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 num_annotations;
* annotation annotations[num_annotations];
* }
* </pre>
* The items of the RuntimeVisibleAnnotations structure are as follows:
* <dl>
* <dt>attribute_name_index</dt>
* <dd>The value of the attribute_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the string
* "RuntimeVisibleAnnotations".</dd>
* <dt>attribute_length</dt>
* <dd>The value of the attribute_length item indicates the length of the attribute,
* excluding the initial six bytes. The value of the attribute_length item is
* thus dependent on the number of runtime-visible annotations represented by
* the structure, and their values.</dd>
* <dt>num_annotations</dt>
* <dd>The value of the num_annotations item gives the number of runtime-visible
* annotations represented by the structure. Note that a maximum of 65535
* runtime-visible Java programming language annotations may be directly
* attached to a program element.</dd>
* <dt>annotations</dt>
* <dd>Each value of the annotations table represents a single runtime-visible
* {@link Annotation annotation} on a program element.</dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=175">JSR 175 : A Metadata
* Facility for the Java Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class RuntimeVisibleAnnotations extends Attribute implements Dumpable {
public List annotations = new LinkedList();
public RuntimeVisibleAnnotations () {
super("RuntimeVisibleAnnotations");
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
RuntimeVisibleAnnotations atr = new RuntimeVisibleAnnotations();
Annotation.readAnnotations(atr.annotations, cr, off, buf);
return atr;
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
return Annotation.writeAnnotations(new ByteVector(), annotations, cw);
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("RuntimeVisibleAnnotations ").append(varName)
.append(" = new RuntimeVisibleAnnotations();\n");
Annotation.dumpAnnotations(buf, varName, annotations);
}
/**
* Returns value in the format described in JSR-175 for Java source code.
*/
public String toString () {
return Annotation.stringAnnotations(annotations);
}
}

View File

@ -0,0 +1,144 @@
/**
* 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.attrs;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* The RuntimeVisibleParameterAnnotations attribute is a variable length attribute
* in the attributes table of the method_info structure. The
* RuntimeVisibleParameterAnnotations attribute records runtime-visible Java
* programming language annotations on the parameters of the corresponding method.
* Each method_info structure may contain at most one
* RuntimeVisibleParameterAnnotations attribute, which records all the
* runtime-visible Java programming language annotations on the parameters of the
* corresponding method. The JVM must make these annotations available so they can
* be returned by the appropriate reflective APIs.
* <p>
* The RuntimeVisibleParameterAnnotations attribute has the following format:
* <pre>
* RuntimeVisibleParameterAnnotations_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u1 num_parameters;
* {
* u2 num_annotations;
* annotation annotations[num_annotations];
* } parameter_annotations[num_parameters];
* }
* <pre>
* The items of the RuntimeVisibleParameterAnnotations structure are as follows:
* <dl>
* <dt>attribute_name_index</dt>
* <dd>The value of the attribute_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the string
* "RuntimeVisibleParameterAnnotations".</dd>
* <dt>attribute_length</dt>
* <dd>The value of the attribute_length item indicates the length of the attribute,
* excluding the initial six bytes. The value of the attribute_length item is
* thus dependent on the number of parameters, the number of runtime-visible
* annotations on each parameter, and their values.</dd>
* <dt>num_parameters</dt>
* <dd>The value of the num_parameters item gives the number of parameters of the
* method represented by the method_info structure on which the annotation
* occurs. (This duplicates information that could be extracted from the method
* descriptor.)</dd>
* <dt>parameter_annotations</dt>
* <dd>Each value of the parameter_annotations table represents all of the
* runtime-visible annotations on a single parameter. The sequence of values in
* the table corresponds to the sequence of parameters in the method signature.
* Each parameter_annotations entry contains the following two items:</dd>
* <dl>
* <dt>num_annotations</dt>
* <dd>The value of the num_annotations item indicates the number of runtime-visible
* annotations on the parameter corresponding to the sequence number of this
* parameter_annotations element.</dd>
* <dt>annotations</dt>
* <dd>Each value of the annotations table represents a single runtime-visible
* {@link org.objectweb.asm.attrs.Annotation annotation} on the parameter
* corresponding to the sequence number of this parameter_annotations element.</dd>
* </dl>
* </dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=175">JSR 175 : A Metadata
* Facility for the Java Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class RuntimeVisibleParameterAnnotations
extends Attribute implements Dumpable
{
public List parameters = new LinkedList();
public RuntimeVisibleParameterAnnotations () {
super("RuntimeVisibleParameterAnnotations");
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
RuntimeInvisibleParameterAnnotations atr =
new RuntimeInvisibleParameterAnnotations();
Annotation.readParameterAnnotations(atr.parameters, cr, off, buf);
return atr;
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
return Annotation.writeParametersAnnotations(
new ByteVector(), parameters, cw);
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("RuntimeVisibleParameterAnnotations ").append(varName)
.append(" = new RuntimeVisibleParameterAnnotations();\n");
Annotation.dumpParameterAnnotations(buf, varName, parameters);
}
public String toString () {
return Annotation.stringParameterAnnotations(parameters);
}
}

View File

@ -0,0 +1,129 @@
/**
* 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.attrs;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* The Signature Attribute introduced in JSR-14 (Adding Generics to the
* Java Programming Language) and also defined in the Java Virtual Machine
* Specification, 3rd edition draft. This atribute is used for classes,
* fields and methods.
* <p>
* Classfiles need to carry generic type information in a backwards
* compatible way. This is accomplished by introducing a new "Signature"
* attribute for classes, methods and fields. The structure of this
* attribute is as follows:
* <pre>
* "Signature" (u4 attr-length, u2 signature-index)
* </pre>
* When used as an attribute of a method or field, a signature gives the
* full (possibly generic) type of that method or field.
* When used as a class attribute, a signature indicates the type
* parameters of the class, followed by its supertype, followed by
* all its interfaces.
* <p>
* The type syntax in signatures is extended to parameterized types and
* type variables. There is also a new signature syntax for formal type
* parameters. The syntax extensions for signature strings are as follows:
* <pre>
* MethodOrFieldSignature ::= TypeSignature
* ClassSignature ::= ParameterPartOpt super_TypeSignature interface_TypeSignatures
* TypeSignatures ::= TypeSignatures TypeSignature
* |
* TypeSignature ::= ...
* | ClassTypeSignature
* | MethodTypeSignature
* | TypeVariableSignature
* ClassTypeSignature ::= 'L' Ident TypeArgumentsOpt ';'
* | ClassTypeSignature '.' Ident ';' TypeArgumentsOpt
* MethodTypeSignature ::= TypeArgumentsOpt '(' TypeSignatures ')'
* TypeSignature ThrowsSignatureListOpt
* ThrowsSignatureList ::= ThrowsSignature ThrowsSignatureList
* | ThrowsSignature
* ThrowsSignature ::= '^' TypeSignature
* TypeVariableSignature ::= 'T' Ident ';'
* TypeArguments ::= '<' TypeSignature TypeSignatures '>'
* ParameterPart ::= '<' ParameterSignature ParameterSignatures '>'
* ParameterSignatures ::= ParameterSignatures ParameterSignature
* |
* ParameterSignature ::= Ident ':' bound_TypeSignature
* </pre>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=14">JSR 14 : Add Generic
* Types To The JavaTM Programming Language</a>
*
* @author Eugene Kuleshov
*/
public class SignatureAttribute extends Attribute implements Dumpable {
public String signature;
public SignatureAttribute () {
super("Signature");
}
public SignatureAttribute (String signature) {
this();
this.signature = signature;
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
return new SignatureAttribute(cr.readUTF8(off, buf));
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
return new ByteVector().putShort(cw.newUTF8(signature));
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("SignatureAttribute ").append(varName)
.append(" = new SignatureAttribute(\"")
.append(signature).append("\");\n");
}
public String toString () {
return signature;
}
}

View File

@ -0,0 +1,189 @@
/**
* 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.attrs;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import java.util.Map;
/**
* The SourceDebugExtension attribute is an optional attribute defined in JSR-045
* in the attributes table of the ClassFile structure. There can be no more than one
* SourceDebugExtension attribute in the attributes table of a given ClassFile
* structure. The SourceDebugExtension attribute has the following format:
* <pre>
* SourceDebugExtension_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u1 debug_extension[attribute_length];
* }
* </pre>
* The items of the SourceDebugExtension_attribute structure are as follows:
* <dl>
* <dt>attribute_name_index</dt>
* <dd>The value of the attribute_name_index item must be a valid index into the
* constant_pool table. The constant_pool entry at that index must be a
* CONSTANT_Utf8_info structure representing the string "SourceDebugExtension".</dd>
* <dt>attribute_length</dt>
* <dd>The value of the attribute_length item indicates the length of
* the attribute, excluding the initial six bytes. The value of the
* attribute_length item is thus the number of bytes in the debug_extension[]
* item.</dd>
* <dt>debug_extension[]</dt>
* <dd>The debug_extension array holds a string, which must be in UTF-8 format.
* There is no terminating zero byte. The string in the debug_extension item
* will be interpreted as extended debugging information. The content of this
* string has no semantic effect on the Java Virtual Machine.</dd>
* </dl>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=45">JSR-045: Debugging
* Support for Other Languages</a>
*
* @author Eugene Kuleshov
*/
public class SourceDebugExtensionAttribute
extends Attribute implements Dumpable
{
public String debugExtension;
public SourceDebugExtensionAttribute () {
super("SourceDebugExtension");
}
public SourceDebugExtensionAttribute (String debugExtension) {
this();
this.debugExtension = debugExtension;
}
protected Attribute read (ClassReader cr, int off,
int len, char[] buf, int codeOff, Label[] labels) {
return new SourceDebugExtensionAttribute(readUTF8(cr, off, len));
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
byte[] b = putUTF8(debugExtension);
return new ByteVector().putByteArray(b, 0, b.length);
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("SourceDebugExtensionAttribute ").append(varName)
.append(" = new SourceDebugExtensionAttribute(\"")
.append(debugExtension).append("\");\n");
}
private String readUTF8 (ClassReader cr, int index, int utfLen) {
int endIndex = index + utfLen;
byte[] b = cr.b;
char[] buf = new char[utfLen];
int strLen = 0;
int c, d, e;
while (index < endIndex) {
c = b[index++] & 0xFF;
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx
buf[strLen++] = (char)c;
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
d = b[index++];
buf[strLen++] = (char)(((c & 0x1F) << 6) | (d & 0x3F));
break;
default:
// 1110 xxxx 10xx xxxx 10xx xxxx
d = b[index++];
e = b[index++];
buf[strLen++] = (char)(((c & 0x0F) << 12) | ((d & 0x3F) << 6) | (e & 0x3F));
break;
}
}
return new String(buf, 0, strLen);
}
private byte[] putUTF8 (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();
}*/
byte[] data = new byte[byteLength];
for (int i = 0; i < charLength;) {
char c = s.charAt(i);
if (c >= '\001' && c <= '\177') {
data[i++] = (byte)c;
} else if (c > '\u07FF') {
data[i++] = (byte)(0xE0 | c >> 12 & 0xF);
data[i++] = (byte)(0x80 | c >> 6 & 0x3F);
data[i++] = (byte)(0x80 | c & 0x3F);
} else {
data[i++] = (byte)(0xC0 | c >> 6 & 0x1F);
data[i++] = (byte)(0x80 | c & 0x3F);
}
}
return data;
}
public String toString () {
return debugExtension;
}
}

View File

@ -0,0 +1,232 @@
/**
* 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.attrs;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* StackMapAttribute is used by CDLC preverifier and also by javac compiller
* starting from J2SE 1.5. Definition is given in appendix "CLDC Byte Code
* Typechecker Specification" from CDLC 1.1 specification.
* <p>
* <i>Note that this implementation does not calculate StackMapFrame structures
* from the method bytecode. If method code is changed or generated from scratch,
* then developer is responsible to prepare a correct StackMapFrame structures.</i>
* <p>
* The format of the stack map in the class file is given below. In the following,
* <ul>
* <li>if the length of the method's byte code1 is 65535 or less, then <tt>uoffset</tt>
* represents the type u2; otherwise <tt>uoffset</tt> represents the type u4.</li>
* <li>If the maximum number of local variables for the method is 65535 or less,
* then <tt>ulocalvar</tt> represents the type u2; otherwise <tt>ulocalvar</tt>
* represents the type u4.</li>
* <li>If the maximum size of the operand stack is 65535 or less, then <tt>ustack</tt>
* represents the type u2; otherwise ustack represents the type u4.</li>
* </ul>
*
* <pre>
* stack_map { // attribute StackMap
* u2 attribute_name_index;
* u4 attribute_length
* uoffset number_of_entries;
* stack_map_frame entries[number_of_entries];
* }
* </pre>
* Each stack map frame has the following format:
* <pre>
* stack_map_frame {
* uoffset offset;
* ulocalvar number_of_locals;
* verification_type_info locals[number_of_locals];
* ustack number_of_stack_items;
* verification_type_info stack[number_of_stack_items];
* }
* </pre>
* The <tt>verification_type_info</tt> structure consists of a one-byte tag
* followed by zero or more bytes, giving more information about the tag.
* Each <tt>verification_type_info</tt> structure specifies the verification
* type of one or two locations.
* <pre>
* union verification_type_info {
* Top_variable_info;
* Integer_variable_info;
* Float_variable_info;
* Long_variable_info;
* Double_variable_info;
* Null_variable_info;
* UninitializedThis_variable_info;
* Object_variable_info;
* Uninitialized_variable_info;
* }
*
* Top_variable_info {
* u1 tag = ITEM_Top; // 0
* }
*
* Integer_variable_info {
* u1 tag = ITEM_Integer; // 1
* }
*
* Float_variable_info {
* u1 tag = ITEM_Float; // 2
* }
*
* Long_variable_info {
* u1 tag = ITEM_Long; // 4
* }
*
* Double_variable_info {
* u1 tag = ITEM_Double; // 3
* }
*
* Null_variable_info {
* u1 tag = ITEM_Null; // 5
* }
*
* UninitializedThis_variable_info {
* u1 tag = ITEM_UninitializedThis; // 6
* }
*
* Object_variable_info {
* u1 tag = ITEM_Object; // 7
* u2 cpool_index;
* }
*
* Uninitialized_variable_info {
* u1 tag = ITEM_Uninitialized // 8
* uoffset offset;
* }
* </pre>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
* Limited Device Configuration 1.1</a>
*
* @author Eugene Kuleshov
*/
public class StackMapAttribute extends Attribute implements Dumpable {
static final int MAX_SIZE = 65535;
public LinkedList frames = new LinkedList();
public StackMapAttribute () {
super("StackMap");
}
public StackMapFrame getFrame (Label label) {
for (int i = 0; i < frames.size(); i++) {
StackMapFrame frame = (StackMapFrame)frames.get(i);
if (frame.label == label) {
return frame;
}
}
return null;
}
protected Attribute read (ClassReader cr, int off, int len,
char[] buf, int codeOff, Label[] labels) {
StackMapAttribute attr = new StackMapAttribute();
// note that this is not the size of Code attribute
int codeSize = cr.readInt(codeOff + 4);
int size = 0;
if (codeSize > MAX_SIZE) {
size = cr.readInt(off);
off += 4;
} else {
size = cr.readShort(off);
off += 2;
}
for (int i = 0; i < size; i++) {
StackMapFrame frame = new StackMapFrame();
off = frame.read(cr, off, buf, codeOff, labels);
attr.frames.add(frame);
}
return attr;
}
protected ByteVector write (ClassWriter cw, byte[] code,
int len, int maxStack, int maxLocals) {
ByteVector bv = new ByteVector();
if (code.length > MAX_SIZE) {
bv.putInt(frames.size());
} else {
bv.putShort(frames.size());
}
for (int i = 0; i < frames.size(); i++) {
((StackMapFrame)frames.get(i)).write(cw, maxStack, maxLocals, bv);
}
return bv;
}
protected Label[] getLabels () {
HashSet labels = new HashSet();
for (int i = 0; i < frames.size(); i++) {
((StackMapFrame)frames.get(i)).getLabels(labels);
}
return (Label[])labels.toArray(new Label[labels.size()]);
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
buf.append("{\n");
buf.append("StackMapAttribute ").append(varName).append("Attr");
buf.append(" = new StackMapAttribute();\n");
if (frames.size() > 0) {
for (int i = 0; i < frames.size(); i++) {
((StackMapFrame)frames.get(i))
.dump(buf, varName + "frame" + i, labelNames);
}
}
buf.append(varName).append(".visitAttribute(").append(varName);
buf.append("Attr);\n}\n");
}
public String toString () {
StringBuffer sb = new StringBuffer("StackMap[");
for (int i = 0; i < frames.size(); i++) {
sb.append('\n').append('[').append(frames.get(i)).append(']');
}
sb.append("\n]");
return sb.toString();
}
}

View File

@ -0,0 +1,227 @@
/**
* 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.attrs;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* StackMapFrame is used by {@link StackMapAttribute} to hold state of the stack
* and local variables for a single execution branch.
*
* <i>Note that Long and Double types are represented by two entries in locals
* and stack. Second entry sohould be always of type Top.</i>
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
* Limited Device Configuration 1.1</a>
*
* @author Eugene Kuleshov
*/
public class StackMapFrame {
public Label label;
public List locals = new LinkedList();
public List stack = new LinkedList();
public int read (ClassReader cr,
int off, char[] buf, int codeOff, Label[] labels) {
int n = cr.readUnsignedShort(off);
off += 2;
if (labels[n] == null) {
labels[n] = new Label();
}
label = labels[n];
off = readTypeInfo(cr, off, locals, labels, buf,
cr.readUnsignedShort(codeOff + 2)); // maxLocals
off = readTypeInfo(cr, off, stack, labels, buf,
cr.readUnsignedShort(codeOff)); // maxStack
return off;
}
public void write (ClassWriter cw,
int maxStack, int maxLocals, ByteVector bv) {
bv.putShort(label.getOffset());
writeTypeInfo(bv, cw, locals, maxLocals);
writeTypeInfo(bv, cw, stack, maxStack);
}
public void getLabels (Set labels) {
labels.add(label);
getTypeInfoLabels(labels, locals);
getTypeInfoLabels(labels, stack);
}
private void getTypeInfoLabels (Set labels, List info) {
for (Iterator it = info.iterator(); it.hasNext();) {
StackMapType typeInfo = (StackMapType)it.next();
if (typeInfo.getType() == StackMapType.ITEM_Uninitialized) {
labels.add(typeInfo.getLabel());
}
}
}
private int readTypeInfo (ClassReader cr, int off,
List info, Label[] labels, char[] buf, int max) {
int n = 0;
if (max > StackMapAttribute.MAX_SIZE) {
n = cr.readInt(off);
off += 4;
} else {
n = cr.readUnsignedShort(off);
off += 2;
}
for (int j = 0; j < n; j++) {
int itemType = cr.readByte(off++);
StackMapType typeInfo = StackMapType.getTypeInfo(itemType);
info.add(typeInfo);
switch (itemType) {
case StackMapType.ITEM_Long: //
case StackMapType.ITEM_Double: //
info.add(StackMapType.getTypeInfo(StackMapType.ITEM_Top));
break;
case StackMapType.ITEM_Object: //
typeInfo.setObject(cr.readClass(off, buf));
off += 2;
break;
case StackMapType.ITEM_Uninitialized: //
int o = cr.readUnsignedShort(off);
off += 2;
if (labels[o] == null) {
labels[o] = new Label();
}
typeInfo.setLabel(labels[o]);
break;
}
}
return off;
}
private void writeTypeInfo (ByteVector bv,
ClassWriter cw, List info, int max) {
if (max > StackMapAttribute.MAX_SIZE) {
bv.putInt(info.size());
} else {
bv.putShort(info.size());
}
for (int j = 0; j < info.size(); j++) {
StackMapType typeInfo = (StackMapType)info.get(j);
bv = new ByteVector().putByte(typeInfo.getType());
switch (typeInfo.getType()) {
case StackMapType.ITEM_Long: //
case StackMapType.ITEM_Double: //
// skip Top in the stack/locals after long/double
j++;
break;
case StackMapType.ITEM_Object: //
bv.putShort(cw.newClass(typeInfo.getObject()));
break;
case StackMapType.ITEM_Uninitialized: //
bv.putShort(typeInfo.getLabel().getOffset());
break;
}
}
}
public void dump (StringBuffer buf, String varName, Map labelNames) {
declareLabel(buf, labelNames, label);
buf.append(varName).append(".label = ")
.append(labelNames.get(label)).append(";\n");
dumpTypeInfo(buf, varName, labelNames, locals);
dumpTypeInfo(buf, varName, labelNames, stack);
}
private void dumpTypeInfo (StringBuffer buf,
String varName, Map labelNames, List infos) {
if (infos.size() > 0) {
buf.append("{\n");
for (int i = 0; i < infos.size(); i++) {
StackMapType typeInfo = (StackMapType)infos.get(i);
String localName = varName + "Info" + i;
int type = typeInfo.getType();
buf.append("StackMapType ").append(localName)
.append(" = new StackMapType( StackMapType.ITEM_")
.append(StackMapType.ITEM_NAMES[type]).append(");\n");
switch (type) {
case StackMapType.ITEM_Object: //
buf.append(localName).append(".setObject(")
.append(typeInfo.getObject()).append(");\n");
break;
case StackMapType.ITEM_Uninitialized: //
declareLabel(buf, labelNames, typeInfo.getLabel());
buf.append(localName).append(".setLabel(")
.append(labelNames.get(typeInfo.getLabel())).append(");\n");
break;
}
buf.append(varName).append(".add(").append(localName).append(");\n");
}
buf.append("}\n");
}
}
public static void declareLabel (StringBuffer buf, Map labelNames, Label l) {
String name = (String)labelNames.get(l);
if (name == null) {
name = "l" + labelNames.size();
labelNames.put(l, name);
buf.append("Label ").append(name).append(" = new Label();\n");
}
}
public String toString () {
StringBuffer sb = new StringBuffer("Frame:L");
sb.append(System.identityHashCode(label));
sb.append(" locals").append(locals);
sb.append(" stack").append(stack);
return sb.toString();
}
}

View File

@ -0,0 +1,124 @@
/**
* 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.attrs;
import org.objectweb.asm.Label;
/**
* Verification type info used by {@link StackMapAttribute}.
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
* Limited Device Configuration 1.1</a>
*
* @author Eugene Kuleshov
*/
public class StackMapType {
public static final int ITEM_Top = 0;
public static final int ITEM_Integer = 1;
public static final int ITEM_Float = 2;
public static final int ITEM_Double = 3;
public static final int ITEM_Long = 4;
public static final int ITEM_Null = 5;
public static final int ITEM_UninitializedThis = 6;
public static final int ITEM_Object = 7;
public static final int ITEM_Uninitialized = 8;
public static final String[] ITEM_NAMES = {
"Top",
"Integer",
"Float",
"Double",
"Long",
"Null",
"UninitializedThis",
"Object",
"Uninitialized"
};
private int type;
private Label offset;
private String object;
private StackMapType (int type) {
this.type = type;
}
public int getType () {
return type;
}
public static StackMapType getTypeInfo (int itemType) {
return new StackMapType(itemType);
}
public void setLabel (Label offset) {
this.offset = offset;
}
public void setObject (String object) {
this.object = object;
}
public Label getLabel () {
return offset;
}
public String getObject () {
return object;
}
public String toString () {
StringBuffer sb = new StringBuffer(ITEM_NAMES[type]);
if (type == ITEM_Object) {
sb.append(":").append(object);
}
if (type == ITEM_Uninitialized) {
sb.append(":L").append(System.identityHashCode(offset));
}
return sb.toString();
}
}

View File

@ -0,0 +1,78 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a bytecode instruction.
*/
public abstract class AbstractInsnNode {
/**
* The opcode of this instruction.
*/
protected int opcode;
/**
* Constructs a new {@link AbstractInsnNode AbstractInsnNode} object.
*
* @param opcode the opcode of the instruction to be constructed.
*/
protected AbstractInsnNode (final int opcode) {
this.opcode = opcode;
}
/**
* Returns the opcode of this instruction.
*
* @return the opcode of this instruction.
*/
public int getOpcode () {
return opcode;
}
/**
* Makes the given code visitor visit this instruction.
*
* @param cv a code visitor.
*/
public abstract void accept (final CodeVisitor cv);
}

View File

@ -0,0 +1,186 @@
/***
* 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.tree;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Attribute;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
/**
* A node that represents a class.
*/
public class ClassNode {
/**
* The class's access flags (see {@link org.objectweb.asm.Constants}). This
* field also indicates if the class is deprecated.
*/
public int access;
/**
* The internal name of the class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
*/
public String name;
/**
* The internal of name of the super class (see {@link
* org.objectweb.asm.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.
*/
public String superName;
/**
* The internal names of the class's interfaces (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}). This list is a
* list of {@link String} objects.
*/
public final List interfaces;
/**
* The name of the source file from which this class was compiled. May be
* <tt>null</tt>.
*/
public String sourceFile;
/**
* Informations about the inner classes of this class. This list is a list of
* {@link InnerClassNode InnerClassNode} objects.
*/
public final List innerClasses;
/**
* The fields of this class. This list is a list of {@link FieldNode
* FieldNode} objects.
*/
public final List fields;
/**
* The methods of this class. This list is a list of {@link MethodNode
* MethodNode} objects.
*/
public final List methods;
/**
* The non standard attributes of the class.
*/
public Attribute attrs;
/**
* Constructs a new {@link ClassNode ClassNode} object.
*
* @param access the class's access flags (see {@link
* org.objectweb.asm.Constants}). This parameter also indicates if the
* class is deprecated.
* @param name the internal name of the class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
* @param superName the internal of name of the super class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}). For
* interfaces, the super class is {@link Object}.
* @param interfaces the internal names of the class's interfaces (see {@link
* org.objectweb.asm.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>.
*/
public ClassNode (
final int access,
final String name,
final String superName,
final String[] interfaces,
final String sourceFile)
{
this.access = access;
this.name = name;
this.superName = superName;
this.interfaces = new ArrayList();
this.sourceFile = sourceFile;
this.innerClasses = new ArrayList();
this.fields = new ArrayList();
this.methods = new ArrayList();
if (interfaces != null) {
this.interfaces.addAll(Arrays.asList(interfaces));
}
}
/**
* Makes the given class visitor visit this class.
*
* @param cv a class visitor.
*/
public void accept (final ClassVisitor cv) {
// visits header
String[] interfaces = new String[this.interfaces.size()];
this.interfaces.toArray(interfaces);
cv.visit(access, name, superName, interfaces, sourceFile);
// visits inner classes
int i;
for (i = 0; i < innerClasses.size(); ++i) {
((InnerClassNode)innerClasses.get(i)).accept(cv);
}
// visits fields
for (i = 0; i < fields.size(); ++i) {
((FieldNode)fields.get(i)).accept(cv);
}
// visits methods
for (i = 0; i < methods.size(); ++i) {
((MethodNode)methods.get(i)).accept(cv);
}
// visits attributes
Attribute attrs = this.attrs;
while (attrs != null) {
cv.visitAttribute(attrs);
attrs = attrs.next;
}
// visits end
cv.visitEnd();
}
}

View File

@ -0,0 +1,103 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a field instruction. A field instruction is an
* instruction that loads or stores the value of a field of an object.
*/
public class FieldInsnNode extends AbstractInsnNode {
/**
* The internal name of the field's owner class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
*/
public String owner;
/**
* The field's name.
*/
public String name;
/**
* The field's descriptor (see {@link org.objectweb.asm.Type Type}).
*/
public String desc;
/**
* Constructs a new {@link FieldInsnNode FieldInsnNode} object.
*
* @param opcode the opcode of the type instruction to be constructed. This
* opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
* @param owner the internal name of the field's owner class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
* @param name the field's name.
* @param desc the field's descriptor (see {@link org.objectweb.asm.Type
* Type}).
*/
public FieldInsnNode (
final int opcode,
final String owner,
final String name,
final String desc)
{
super(opcode);
this.owner = owner;
this.name = name;
this.desc = desc;
}
/**
* Sets the opcode of this instruction.
*
* @param opcode the new instruction opcode. This opcode must be GETSTATIC,
* PUTSTATIC, GETFIELD or PUTFIELD.
*/
public void setOpcode (final int opcode) {
this.opcode = opcode;
}
public void accept (final CodeVisitor cv) {
cv.visitFieldInsn(opcode, owner, name, desc);
}
}

View File

@ -0,0 +1,120 @@
/***
* 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.tree;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Attribute;
/**
* A node that represents a field.
*/
public class FieldNode {
/**
* The field's access flags (see {@link org.objectweb.asm.Constants}). This
* field also indicates if the field is synthetic and/or deprecated.
*/
public int access;
/**
* The field's name.
*/
public String name;
/**
* The field's descriptor (see {@link org.objectweb.asm.Type Type}).
*/
public String desc;
/**
* The field's initial value. This field, 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}.
*/
public Object value;
/**
* The non standard attributes of the field.
*/
public Attribute attrs;
/**
* Constructs a new {@link FieldNode FieldNode} object.
*
* @param access the field's access flags (see {@link
* org.objectweb.asm.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 org.objectweb.asm.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}.
* @param attrs the non standard attributes of the field.
*/
public FieldNode (
final int access,
final String name,
final String desc,
final Object value,
final Attribute attrs)
{
this.access = access;
this.name = name;
this.desc = desc;
this.value = value;
this.attrs = attrs;
}
/**
* Makes the given class visitor visit this field.
*
* @param cv a class visitor.
*/
public void accept (final ClassVisitor cv) {
cv.visitField(access, name, desc, value, attrs);
}
}

View File

@ -0,0 +1,74 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
/**
* A node that represents an IINC instruction.
*/
public class IincInsnNode extends AbstractInsnNode {
/**
* Index of the local variable to be incremented.
*/
public int var;
/**
* Amount to increment the local variable by.
*/
public int incr;
/**
* Constructs a new {@link IincInsnNode IincInsnNode} node.
*
* @param var index of the local variable to be incremented.
* @param incr increment amount to increment the local variable by.
*/
public IincInsnNode (final int var, final int incr) {
super(Constants.IINC);
this.var = var;
this.incr = incr;
}
public void accept (final CodeVisitor cv) {
cv.visitIincInsn(var, incr);
}
}

View File

@ -0,0 +1,109 @@
/***
* 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.tree;
import org.objectweb.asm.ClassVisitor;
/**
* A node that represents an inner class.
*/
public class InnerClassNode {
/**
* The internal name of an inner class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
*/
public String name;
/**
* The internal name of the class to which the inner class belongs (see
* {@link org.objectweb.asm.Type#getInternalName getInternalName}). May be
* <tt>null</tt>.
*/
public String outerName;
/**
* The (simple) name of the inner class inside its enclosing class. May be
* <tt>null</tt> for anonymous inner classes.
*/
public String innerName;
/**
* The access flags of the inner class as originally declared in the enclosing
* class.
*/
public int access;
/**
* Constructs a new {@link InnerClassNode InnerClassNode} object.
*
* @param name the internal name of an inner class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
* @param outerName the internal name of the class to which the inner class
* belongs (see {@link org.objectweb.asm.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.
*/
public InnerClassNode (
final String name,
final String outerName,
final String innerName,
final int access)
{
this.name = name;
this.outerName = outerName;
this.innerName = innerName;
this.access = access;
}
/**
* Makes the given class visitor visit this inner class.
*
* @param cv a class visitor.
*/
public void accept (final ClassVisitor cv) {
cv.visitInnerClass(name, outerName, innerName, access);
}
}

View File

@ -0,0 +1,126 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a zero operand instruction.
*/
public class InsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link InsnNode InsnNode} object.
*
* @param opcode the opcode of the instruction to be constructed. This opcode
* must be 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.
*/
public InsnNode (final int opcode) {
super(opcode);
}
/**
* Sets the opcode of this instruction.
*
* @param opcode the new instruction opcode. This opcode must be 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.
*/
public void setOpcode (final int opcode) {
this.opcode = opcode;
}
/**
* Makes the given code visitor visit this instruction.
*/
public void accept (final CodeVisitor cv) {
cv.visitInsn(opcode);
}
}

View File

@ -0,0 +1,78 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents an instruction with a single int operand.
*/
public class IntInsnNode extends AbstractInsnNode {
/**
* The operand of this instruction.
*/
public int operand;
/**
* Constructs a new {@link IntInsnNode IntInsnNode} object.
*
* @param opcode the opcode of the instruction to be constructed. This opcode
* must be BIPUSH, SIPUSH or NEWARRAY.
* @param operand the operand of the instruction to be constructed.
*/
public IntInsnNode (final int opcode, final int operand) {
super(opcode);
this.operand = operand;
}
/**
* Sets the opcode of this instruction.
*
* @param opcode the new instruction opcode. This opcode must be BIPUSH,
* SIPUSH or NEWARRAY.
*/
public void setOpcode (final int opcode) {
this.opcode = opcode;
}
public void accept (final CodeVisitor cv) {
cv.visitIntInsn(opcode, operand);
}
}

View File

@ -0,0 +1,87 @@
/***
* 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.tree;
import org.objectweb.asm.Label;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a jump instruction. A jump instruction is an
* instruction that may jump to another instruction.
*/
public class JumpInsnNode extends AbstractInsnNode {
/**
* The operand of this instruction. This operand is a label that designates
* the instruction to which this instruction may jump.
*/
public Label label;
/**
* Constructs a new {@link JumpInsnNode JumpInsnNode} object.
*
* @param opcode the opcode of the type instruction to be constructed. This
* opcode must be 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 constructed. This operand
* is a label that designates the instruction to which the jump
* instruction may jump.
*/
public JumpInsnNode (final int opcode, final Label label) {
super(opcode);
this.label = label;
}
/**
* Sets the opcode of this instruction.
*
* @param opcode the new instruction opcode. This opcode must be
* 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.
*/
public void setOpcode (final int opcode) {
this.opcode = opcode;
}
public void accept (final CodeVisitor cv) {
cv.visitJumpInsn(opcode, label);
}
}

View File

@ -0,0 +1,72 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
/**
* A node that represents an LDC instruction.
*/
public class LdcInsnNode extends AbstractInsnNode {
/**
* 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}.
*/
public Object cst;
/**
* Constructs a new {@link LdcInsnNode LdcInsnNode} object.
*
* @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}.
*/
public LdcInsnNode (final Object cst) {
super(Constants.LDC);
this.cst = cst;
}
public void accept (final CodeVisitor cv) {
cv.visitLdcInsn(cst);
}
}

View File

@ -0,0 +1,81 @@
/***
* 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.tree;
import org.objectweb.asm.Label;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a line number declaration.
*/
public class LineNumberNode {
/**
* A line number. This number refers to the source file from which the class
* was compiled.
*/
public int line;
/**
* The first instruction corresponding to this line number.
*/
public Label start;
/**
* Constructs a new {@link LineNumberNode LineNumberNode} object.
*
* @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.
*/
public LineNumberNode (final int line, final Label start) {
this.line = line;
this.start = start;
}
/**
* Makes the given code visitor visit this line number declaration.
*
* @param cv a code visitor.
*/
public void accept (final CodeVisitor cv) {
cv.visitLineNumber(line, start);
}
}

View File

@ -0,0 +1,113 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Label;
/**
* A node that represents a local variable declaration.
*/
public class LocalVariableNode {
/**
* The name of a local variable.
*/
public String name;
/**
* The type descriptor of this local variable.
*/
public String desc;
/**
* The first instruction corresponding to the scope of this local variable
* (inclusive).
*/
public Label start;
/**
* The last instruction corresponding to the scope of this local variable
* (exclusive).
*/
public Label end;
/**
* The local variable's index.
*/
public int index;
/**
* Constructs a new {@link LocalVariableNode LocalVariableNode} object.
*
* @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.
*/
public LocalVariableNode (
final String name,
final String desc,
final Label start,
final Label end,
final int index)
{
this.name = name;
this.desc = desc;
this.start = start;
this.end = end;
this.index = index;
}
/**
* Makes the given code visitor visit this local variable declaration.
*
* @param cv a code visitor.
*/
public void accept (final CodeVisitor cv) {
cv.visitLocalVariable(name, desc, start, end, index);
}
}

View File

@ -0,0 +1,108 @@
/***
* 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.tree;
import org.objectweb.asm.Label;
import org.objectweb.asm.Constants;
import org.objectweb.asm.CodeVisitor;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
/**
* A node that represents a LOOKUPSWITCH instruction.
*/
public class LookupSwitchInsnNode extends AbstractInsnNode {
/**
* Beginning of the default handler block.
*/
public Label dflt;
/**
* The values of the keys. This list is a list a {@link java.lang.Integer
* Integer} objects.
*/
public final List keys;
/**
* Beginnings of the handler blocks. This list is a list of {@link Label
* Label} objects.
*/
public final List labels;
/**
* Constructs a new {@link LookupSwitchInsnNode LookupSwitchInsnNode} object.
*
* @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.
*/
public LookupSwitchInsnNode (
final Label dflt,
final int[] keys,
final Label[] labels)
{
super(Constants.LOOKUPSWITCH);
this.dflt = dflt;
this.keys = new ArrayList();
this.labels = new ArrayList();
if (keys != null) {
for (int i = 0; i < keys.length; ++i) {
this.keys.add(new Integer(keys[i]));
}
}
if (labels != null) {
this.labels.addAll(Arrays.asList(labels));
}
}
public void accept (final CodeVisitor cv) {
int[] keys = new int[this.keys.size()];
for (int i = 0; i < keys.length; ++i) {
keys[i] = ((Integer)this.keys.get(i)).intValue();
}
Label[] labels = new Label[this.labels.size()];
this.labels.toArray(labels);
cv.visitLookupSwitchInsn(dflt, keys, labels);
}
}

View File

@ -0,0 +1,104 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a method instruction. A method instruction is an
* instruction that invokes a method.
*/
public class MethodInsnNode extends AbstractInsnNode {
/**
* The internal name of the method's owner class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
*/
public String owner;
/**
* The method's name.
*/
public String name;
/**
* The method's descriptor (see {@link org.objectweb.asm.Type Type}).
*/
public String desc;
/**
* Constructs a new {@link MethodInsnNode MethodInsnNode} object.
*
* @param opcode the opcode of the type instruction to be constructed. This
* opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
* INVOKEINTERFACE.
* @param owner the internal name of the method's owner class (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}).
* @param name the method's name.
* @param desc the method's descriptor (see {@link org.objectweb.asm.Type
* Type}).
*/
public MethodInsnNode (
final int opcode,
final String owner,
final String name,
final String desc)
{
super(opcode);
this.owner = owner;
this.name = name;
this.desc = desc;
}
/**
* Sets the opcode of this instruction.
*
* @param opcode the new instruction opcode. This opcode must be
* INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
*/
public void setOpcode (final int opcode) {
this.opcode = opcode;
}
public void accept (final CodeVisitor cv) {
cv.visitMethodInsn(opcode, owner, name, desc);
}
}

View File

@ -0,0 +1,210 @@
/***
* 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.tree;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Attribute;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
/**
* A node that represents a method.
*/
public class MethodNode {
/**
* The method's access flags (see {@link org.objectweb.asm.Constants}). This
* field also indicates if the method is synthetic and/or deprecated.
*/
public int access;
/**
* The method's name.
*/
public String name;
/**
* The method's descriptor (see {@link org.objectweb.asm.Type Type}).
*/
public String desc;
/**
* The internal names of the method's exception classes (see {@link
* org.objectweb.asm.Type#getInternalName getInternalName}). This list is a
* list of {@link String} objects.
*/
public final List exceptions;
/**
* The non standard attributes of the method.
*/
public Attribute attrs;
/**
* The instructions of this method. This list is a list of {@link
* AbstractInsnNode AbstractInsnNode} and {@link Label Label} objects.
*/
public final List instructions;
/**
* The try catch blocks of this method. This list is a list of {@link
* TryCatchBlockNode TryCatchBlockNode} objects.
*/
public final List tryCatchBlocks;
/**
* The maximum stack size of this method.
*/
public int maxStack;
/**
* The maximum number of local variables of this method.
*/
public int maxLocals;
/**
* The local variables of this method. This list is a list of {@link
* LocalVariableNode LocalVariableNode} objects.
*/
public final List localVariables;
/**
* The line numbers of this method. This list is a list of {@link
* LineNumberNode LineNumberNode} objects.
*/
public final List lineNumbers;
/**
* The non standard attributes of the method's code.
*/
public Attribute codeAttrs;
/**
* Constructs a new {@link MethodNode MethodNode} object.
*
* @param access the method's access flags (see {@link
* org.objectweb.asm.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 org.objectweb.asm.Type
* Type}).
* @param exceptions the internal names of the method's exception
* classes (see {@link org.objectweb.asm.Type#getInternalName
* getInternalName}). May be <tt>null</tt>.
* @param attrs the non standard attributes of the method.
*/
public MethodNode (
final int access,
final String name,
final String desc,
final String[] exceptions,
final Attribute attrs)
{
this.access = access;
this.name = name;
this.desc = desc;
this.exceptions = new ArrayList();
this.instructions = new ArrayList();
this.tryCatchBlocks = new ArrayList();
this.localVariables = new ArrayList();
this.lineNumbers = new ArrayList();
if (exceptions != null) {
this.exceptions.addAll(Arrays.asList(exceptions));
}
this.attrs = attrs;
}
/**
* Makes the given class visitor visit this method.
*
* @param cv a class visitor.
*/
public void accept (final ClassVisitor cv) {
String[] exceptions = new String[this.exceptions.size()];
this.exceptions.toArray(exceptions);
CodeVisitor mv = cv.visitMethod(access, name, desc, exceptions, attrs);
if (mv != null && instructions.size() > 0) {
int i;
// visits instructions
for (i = 0; i < instructions.size(); ++i) {
Object insn = instructions.get(i);
if (insn instanceof Label) {
mv.visitLabel((Label)insn);
} else {
((AbstractInsnNode)insn).accept(mv);
}
}
// visits try catch blocks
for (i = 0; i < tryCatchBlocks.size(); ++i) {
((TryCatchBlockNode)tryCatchBlocks.get(i)).accept(mv);
}
// visits maxs
mv.visitMaxs(maxStack, maxLocals);
// visits local variables
for (i = 0; i < localVariables.size(); ++i) {
((LocalVariableNode)localVariables.get(i)).accept(mv);
}
// visits line numbers
for (i = 0; i < lineNumbers.size(); ++i) {
((LineNumberNode)lineNumbers.get(i)).accept(mv);
}
// visits the code attributes
Attribute attrs = codeAttrs;
while (attrs != null) {
mv.visitAttribute(attrs);
attrs = attrs.next;
}
}
}
}

View File

@ -0,0 +1,76 @@
/***
* 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.tree;
import org.objectweb.asm.Constants;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a MULTIANEWARRAY instruction.
*/
public class MultiANewArrayInsnNode extends AbstractInsnNode {
/**
* An array type descriptor (see {@link org.objectweb.asm.Type Type}).
*/
public String desc;
/**
* Number of dimensions of the array to allocate.
*/
public int dims;
/**
* Constructs a new {@link MultiANewArrayInsnNode MultiANewArrayInsnNode}
* object.
*
* @param desc an array type descriptor (see {@link org.objectweb.asm.Type
* Type}).
* @param dims number of dimensions of the array to allocate.
*/
public MultiANewArrayInsnNode (final String desc, final int dims) {
super(Constants.MULTIANEWARRAY);
this.desc = desc;
this.dims = dims;
}
public void accept (final CodeVisitor cv) {
cv.visitMultiANewArrayInsn(desc, dims);
}
}

View File

@ -0,0 +1,107 @@
/***
* 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.tree;
import org.objectweb.asm.Label;
import org.objectweb.asm.Constants;
import org.objectweb.asm.CodeVisitor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A node that represents a TABLESWITCH instruction.
*/
public class TableSwitchInsnNode extends AbstractInsnNode {
/**
* The minimum key value.
*/
public int min;
/**
* The maximum key value.
*/
public int max;
/**
* Beginning of the default handler block.
*/
public Label dflt;
/**
* Beginnings of the handler blocks. This list is a list of {@link Label
* Label} objects.
*/
public final List labels;
/**
* Constructs a new {@link TableSwitchInsnNode TableSwitchInsnNode}.
*
* @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.
*/
public TableSwitchInsnNode (
final int min,
final int max,
final Label dflt,
final Label[] labels)
{
super(Constants.TABLESWITCH);
this.min = min;
this.max = max;
this.dflt = dflt;
this.labels = new ArrayList();
if (labels != null) {
this.labels.addAll(Arrays.asList(labels));
}
}
public void accept (final CodeVisitor cv) {
Label[] labels = new Label[this.labels.size()];
this.labels.toArray(labels);
cv.visitTableSwitchInsn(min, max, dflt, labels);
}
}

View File

@ -0,0 +1,133 @@
/***
* 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.tree;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Attribute;
/**
* A {@link ClassAdapter ClassAdapter} that constructs a tree representation of
* the classes it vists. Each <tt>visit</tt><i>XXX</i> method of this class
* constructs an <i>XXX</i><tt>Node</tt> and adds it to the {@link #classNode
* classNode} node (except the {@link #visitEnd visitEnd} method, which just
* makes the {@link #cv cv} class visitor visit the tree that has just been
* constructed).
* <p>
* In order to implement a usefull class adapter based on a tree representation
* of classes, one just need to override the {@link #visitEnd visitEnd} method
* with a method of the following form:
* <pre>
* public void visitEnd () {
* // ...
* // code to modify the classNode tree, can be arbitrary complex
* // ...
* // makes the cv visitor visit this modified class:
* classNode.accept(cv);
* }
* </pre>
*/
public class TreeClassAdapter extends ClassAdapter {
/**
* A tree representation of the class that is being visited by this visitor.
*/
public ClassNode classNode;
/**
* Constructs a new {@link TreeClassAdapter TreeClassAdapter} object.
*
* @param cv the class visitor to which this adapter must delegate calls.
*/
public TreeClassAdapter (final ClassVisitor cv) {
super(cv);
}
public void visit (
final int access,
final String name,
final String superName,
final String[] interfaces,
final String sourceFile)
{
classNode = new ClassNode(access, name, superName, interfaces, sourceFile);
}
public void visitInnerClass (
final String name,
final String outerName,
final String innerName,
final int access)
{
InnerClassNode icn = new InnerClassNode(name, outerName, innerName, access);
classNode.innerClasses.add(icn);
}
public void visitField (
final int access,
final String name,
final String desc,
final Object value,
final Attribute attrs)
{
FieldNode fn = new FieldNode(access, name, desc, value, attrs);
classNode.fields.add(fn);
}
public CodeVisitor visitMethod (
final int access,
final String name,
final String desc,
final String[] exceptions,
final Attribute attrs)
{
MethodNode mn = new MethodNode(access, name, desc, exceptions, attrs);
classNode.methods.add(mn);
return new TreeCodeAdapter(mn);
}
public void visitAttribute (final Attribute attr) {
attr.next = classNode.attrs;
classNode.attrs = attr;
}
public void visitEnd () {
classNode.accept(cv);
}
}

View File

@ -0,0 +1,186 @@
/***
* 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.tree;
import org.objectweb.asm.CodeAdapter;
import org.objectweb.asm.Label;
import org.objectweb.asm.Attribute;
/**
* A {@link CodeAdapter CodeAdapter} that constructs a tree representation of
* the methods it vists. Each <tt>visit</tt><i>XXX</i> method of this class
* constructs an <i>XXX</i><tt>Node</tt> and adds it to the {@link #methodNode
* methodNode} node.
*/
public class TreeCodeAdapter extends CodeAdapter {
/**
* A tree representation of the method that is being visited by this visitor.
*/
public MethodNode methodNode;
/**
* Constructs a new {@link TreeCodeAdapter TreeCodeAdapter} object.
*
* @param methodNode the method node to be used to store the tree
* representation constructed by this code visitor.
*/
public TreeCodeAdapter (final MethodNode methodNode) {
super(null);
this.methodNode = methodNode;
}
public void visitInsn (final int opcode) {
AbstractInsnNode n = new InsnNode(opcode);
methodNode.instructions.add(n);
}
public void visitIntInsn (final int opcode, final int operand) {
AbstractInsnNode n = new IntInsnNode(opcode, operand);
methodNode.instructions.add(n);
}
public void visitVarInsn (final int opcode, final int var) {
AbstractInsnNode n = new VarInsnNode(opcode, var);
methodNode.instructions.add(n);
}
public void visitTypeInsn (final int opcode, final String desc) {
AbstractInsnNode n = new TypeInsnNode(opcode, desc);
methodNode.instructions.add(n);
}
public void visitFieldInsn (
final int opcode,
final String owner,
final String name,
final String desc)
{
AbstractInsnNode n = new FieldInsnNode(opcode, owner, name, desc);
methodNode.instructions.add(n);
}
public void visitMethodInsn (
final int opcode,
final String owner,
final String name,
final String desc)
{
AbstractInsnNode n = new MethodInsnNode(opcode, owner, name, desc);
methodNode.instructions.add(n);
}
public void visitJumpInsn (final int opcode, final Label label) {
AbstractInsnNode n = new JumpInsnNode(opcode, label);
methodNode.instructions.add(n);
}
public void visitLabel (final Label label) {
methodNode.instructions.add(label);
}
public void visitLdcInsn (final Object cst) {
AbstractInsnNode n = new LdcInsnNode(cst);
methodNode.instructions.add(n);
}
public void visitIincInsn (final int var, final int increment) {
AbstractInsnNode n = new IincInsnNode(var, increment);
methodNode.instructions.add(n);
}
public void visitTableSwitchInsn (
final int min,
final int max,
final Label dflt,
final Label labels[])
{
AbstractInsnNode n = new TableSwitchInsnNode(min, max, dflt, labels);
methodNode.instructions.add(n);
}
public void visitLookupSwitchInsn (
final Label dflt,
final int keys[],
final Label labels[])
{
AbstractInsnNode n = new LookupSwitchInsnNode(dflt, keys, labels);
methodNode.instructions.add(n);
}
public void visitMultiANewArrayInsn (final String desc, final int dims) {
AbstractInsnNode n = new MultiANewArrayInsnNode(desc, dims);
methodNode.instructions.add(n);
}
public void visitTryCatchBlock (
final Label start,
final Label end,
final Label handler,
final String type)
{
TryCatchBlockNode n = new TryCatchBlockNode(start, end, handler, type);
methodNode.tryCatchBlocks.add(n);
}
public void visitMaxs (final int maxStack, final int maxLocals) {
methodNode.maxStack = maxStack;
methodNode.maxLocals = maxLocals;
}
public void visitLocalVariable (
final String name,
final String desc,
final Label start,
final Label end,
final int index)
{
LocalVariableNode n = new LocalVariableNode(name, desc, start, end, index);
methodNode.localVariables.add(n);
}
public void visitLineNumber (final int line, final Label start) {
LineNumberNode n = new LineNumberNode(line, start);
methodNode.lineNumbers.add(n);
}
public void visitAttribute (final Attribute attr) {
attr.next = methodNode.attrs;
methodNode.attrs = attr;
}
}

View File

@ -0,0 +1,102 @@
/***
* 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.tree;
import org.objectweb.asm.Label;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a try catch block.
*/
public class TryCatchBlockNode {
/**
* Beginning of the exception handler's scope (inclusive).
*/
public Label start;
/**
* End of the exception handler's scope (exclusive).
*/
public Label end;
/**
* Beginning of the exception handler's code.
*/
public Label handler;
/**
* Internal name of the type of exceptions handled by the handler. May be
* <tt>null</tt> to catch any exceptions (for "finally" blocks).
*/
public String type;
/**
* Constructs a new {@link TryCatchBlockNode TryCatchBlockNode} object.
*
* @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).
*/
public TryCatchBlockNode (
final Label start,
final Label end,
final Label handler,
final String type)
{
this.start = start;
this.end = end;
this.handler = handler;
this.type = type;
}
/**
* Makes the given code visitor visit this try catch block.
*
* @param cv a code visitor.
*/
public void accept (final CodeVisitor cv) {
cv.visitTryCatchBlock(start, end, handler, type);
}
}

View File

@ -0,0 +1,81 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a type instruction. A type instruction is an
* instruction that takes a type descriptor as parameter.
*/
public class TypeInsnNode extends AbstractInsnNode {
/**
* The operand of this instruction. This operand is a type descriptor (see
* {@link org.objectweb.asm.Type Type}).
*/
public String desc;
/**
* Constructs a new {@link TypeInsnNode TypeInsnNode} object.
*
* @param opcode the opcode of the type instruction to be constructed. This
* opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
* @param desc the operand of the instruction to be constructed. This operand
* is a type descriptor (see {@link org.objectweb.asm.Type Type}).
*/
public TypeInsnNode (final int opcode, final String desc) {
super(opcode);
this.desc = desc;
}
/**
* Sets the opcode of this instruction.
*
* @param opcode the new instruction opcode. This opcode must be
* NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
*/
public void setOpcode (final int opcode) {
this.opcode = opcode;
}
public void accept (final CodeVisitor cv) {
cv.visitTypeInsn(opcode, desc);
}
}

View File

@ -0,0 +1,84 @@
/***
* 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.tree;
import org.objectweb.asm.CodeVisitor;
/**
* A node that represents a local variable instruction. A local variable
* instruction is an instruction that loads or stores the value of a local
* variable.
*/
public class VarInsnNode extends AbstractInsnNode {
/**
* The operand of this instruction. This operand is the index of a local
* variable.
*/
public int var;
/**
* 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
* constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,
* ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
* @param var the operand of the instruction to be constructed. This operand
* is the index of a local variable.
*/
public VarInsnNode (final int opcode, final int var) {
super(opcode);
this.var = var;
}
/**
* Sets the opcode of this instruction.
*
* @param opcode the new instruction opcode. This opcode must be ILOAD, LLOAD,
* FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
*/
public void setOpcode (final int opcode) {
this.opcode = opcode;
}
public void accept (final CodeVisitor cv) {
cv.visitVarInsn(opcode, var);
}
}

View File

@ -0,0 +1,230 @@
/***
* 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.util;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.Attribute;
/**
* A {@link ClassAdapter ClssAdapter} that checks that its methods are properly
* used. More precisely this class adapter checks each method call individually,
* based <i>only</i> on its arguments, but does <i>not</i> check the
* <i>sequence</i> of method calls. For example, the invalid sequence
* <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
* "i", "D", null)</tt> will <i>not</i> be detected by this class adapter.
*/
public class CheckClassAdapter extends ClassAdapter {
/**
* <tt>true</tt> if the visit method has been called.
*/
private boolean start;
/**
* <tt>true</tt> if the visitEnd method has been called.
*/
private boolean end;
/**
* Constructs a new {@link CheckClassAdapter CheckClassAdapter} object.
*
* @param cv the class visitor to which this adapter must delegate calls.
*/
public CheckClassAdapter (final ClassVisitor cv) {
super(cv);
}
public void visit (
final int access,
final String name,
final String superName,
final String[] interfaces,
final String sourceFile)
{
if (start) {
throw new IllegalStateException("visit must be called only once");
} else {
start = true;
}
checkState();
checkAccess(access, 1 + 2 + 4 + 16 + 512 + 1024 + 32 + 65536 + 131072);
CheckCodeAdapter.checkInternalName(name, "class name");
if (name.equals("java/lang/Object")) {
if (superName != null) {
throw new IllegalArgumentException(
"The super class name of the Object class must be 'null'");
}
} else {
CheckCodeAdapter.checkInternalName(superName, "super class name");
}
if ((access & Constants.ACC_INTERFACE) != 0) {
if (!superName.equals("java/lang/Object")) {
throw new IllegalArgumentException(
"The super class name of interfaces must be 'java/lang/Object'");
}
}
if (interfaces != null) {
for (int i = 0; i < interfaces.length; ++i) {
CheckCodeAdapter.checkInternalName(
interfaces[i], "interface name at index " + i);
}
}
cv.visit(access, name, superName, interfaces, sourceFile);
}
public void visitInnerClass (
final String name,
final String outerName,
final String innerName,
final int access)
{
checkState();
CheckCodeAdapter.checkInternalName(name, "class name");
if (outerName != null) {
CheckCodeAdapter.checkInternalName(outerName, "outer class name");
}
if (innerName != null) {
CheckCodeAdapter.checkIdentifier(innerName, "inner class name");
}
checkAccess(access, 1 + 2 + 4 + 8 + 16 + 512 + 1024 + 32);
cv.visitInnerClass(name, outerName, innerName, access);
}
public void visitField (
final int access,
final String name,
final String desc,
final Object value,
final Attribute attrs)
{
checkState();
checkAccess(access, 1 + 2 + 4 + 8 + 16 + 64 + 128 + 65536 + 131072);
CheckCodeAdapter.checkIdentifier(name, "field name");
CheckCodeAdapter.checkDesc(desc, false);
if (value != null) {
CheckCodeAdapter.checkConstant(value);
}
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)
{
checkState();
checkAccess(
access, 1 + 2 + 4 + 8 + 16 + 32 + 256 + 1024 + 2048 + 65536 + 131072);
CheckCodeAdapter.checkMethodIdentifier(name, "method name");
CheckCodeAdapter.checkMethodDesc(desc);
if (exceptions != null) {
for (int i = 0; i < exceptions.length; ++i) {
CheckCodeAdapter.checkInternalName(
exceptions[i], "exception name at index " + i);
}
}
return new CheckCodeAdapter(
cv.visitMethod(access, name, desc, exceptions, attrs));
}
public void visitAttribute (final Attribute attr) {
checkState();
if (attr == null) {
throw new IllegalArgumentException(
"Invalid attribute (must not be null)");
}
}
public void visitEnd () {
checkState();
end = true;
cv.visitEnd();
}
// ---------------------------------------------------------------------------
/**
* Checks that the visit method has been called and that visitEnd has not been
* called.
*/
private void checkState () {
if (!start) {
throw new IllegalStateException(
"Cannot visit member before visit has been called.");
}
if (end) {
throw new IllegalStateException(
"Cannot visit member after visitEnd has been called.");
}
}
/**
* Checks that the given access flags do not contain invalid flags. This
* method also checks that mutually incompatible flags are not set
* simultaneously.
*
* @param access the access flags to be checked
* @param possibleAccess the valid access flags.
*/
static void checkAccess (final int access, final int possibleAccess) {
if ((access & ~possibleAccess) != 0) {
throw new IllegalArgumentException("Invalid access flags: " + access);
}
int pub = ((access & Constants.ACC_PUBLIC) != 0 ? 1 : 0);
int pri = ((access & Constants.ACC_PRIVATE) != 0 ? 1 : 0);
int pro = ((access & Constants.ACC_PROTECTED) != 0 ? 1 : 0);
if (pub + pri + pro > 1) {
throw new IllegalArgumentException(
"public private and protected are mutually exclusive: " + access);
}
int fin = ((access & Constants.ACC_FINAL) != 0 ? 1 : 0);
int abs = ((access & Constants.ACC_ABSTRACT) != 0 ? 1 : 0);
if (fin + abs > 1) {
throw new IllegalArgumentException(
"final and abstract are mutually exclusive: " + access);
}
}
}

View File

@ -0,0 +1,859 @@
/***
* 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.util;
import org.objectweb.asm.Label;
import org.objectweb.asm.CodeAdapter;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.Attribute;
import java.util.HashMap;
/**
* A {@link CodeAdapter CodeAdapter} that checks that its methods are properly
* used. More precisely this code adapter checks each instruction individually
* (i.e., each visit method checks some preconditions based <i>only</i> on its
* arguments - such as the fact that the given opcode is correct for a given
* visit method), but does <i>not</i> check the <i>sequence</i> of instructions.
* For example, in a method whose signature is <tt>void m ()</tt>, the invalid
* instruction IRETURN, or the invalid sequence IADD L2I will <i>not</i> be
* detected by this code adapter.
*/
public class CheckCodeAdapter extends CodeAdapter {
/**
* <tt>true</tt> if the visitMaxs method has been called.
*/
private boolean end;
/**
* The already visited labels. This map associate Integer values to Label
* keys.
*/
private HashMap labels;
/**
* Code of the visit method to be used for each opcode.
*/
private final static int[] TYPE = new int[] {
0, //NOP
0, //ACONST_NULL
0, //ICONST_M1
0, //ICONST_0
0, //ICONST_1
0, //ICONST_2
0, //ICONST_3
0, //ICONST_4
0, //ICONST_5
0, //LCONST_0
0, //LCONST_1
0, //FCONST_0
0, //FCONST_1
0, //FCONST_2
0, //DCONST_0
0, //DCONST_1
1, //BIPUSH
1, //SIPUSH
7, //LDC
-1, //LDC_W
-1, //LDC2_W
2, //ILOAD
2, //LLOAD
2, //FLOAD
2, //DLOAD
2, //ALOAD
-1, //ILOAD_0
-1, //ILOAD_1
-1, //ILOAD_2
-1, //ILOAD_3
-1, //LLOAD_0
-1, //LLOAD_1
-1, //LLOAD_2
-1, //LLOAD_3
-1, //FLOAD_0
-1, //FLOAD_1
-1, //FLOAD_2
-1, //FLOAD_3
-1, //DLOAD_0
-1, //DLOAD_1
-1, //DLOAD_2
-1, //DLOAD_3
-1, //ALOAD_0
-1, //ALOAD_1
-1, //ALOAD_2
-1, //ALOAD_3
0, //IALOAD
0, //LALOAD
0, //FALOAD
0, //DALOAD
0, //AALOAD
0, //BALOAD
0, //CALOAD
0, //SALOAD
2, //ISTORE
2, //LSTORE
2, //FSTORE
2, //DSTORE
2, //ASTORE
-1, //ISTORE_0
-1, //ISTORE_1
-1, //ISTORE_2
-1, //ISTORE_3
-1, //LSTORE_0
-1, //LSTORE_1
-1, //LSTORE_2
-1, //LSTORE_3
-1, //FSTORE_0
-1, //FSTORE_1
-1, //FSTORE_2
-1, //FSTORE_3
-1, //DSTORE_0
-1, //DSTORE_1
-1, //DSTORE_2
-1, //DSTORE_3
-1, //ASTORE_0
-1, //ASTORE_1
-1, //ASTORE_2
-1, //ASTORE_3
0, //IASTORE
0, //LASTORE
0, //FASTORE
0, //DASTORE
0, //AASTORE
0, //BASTORE
0, //CASTORE
0, //SASTORE
0, //POP
0, //POP2
0, //DUP
0, //DUP_X1
0, //DUP_X2
0, //DUP2
0, //DUP2_X1
0, //DUP2_X2
0, //SWAP
0, //IADD
0, //LADD
0, //FADD
0, //DADD
0, //ISUB
0, //LSUB
0, //FSUB
0, //DSUB
0, //IMUL
0, //LMUL
0, //FMUL
0, //DMUL
0, //IDIV
0, //LDIV
0, //FDIV
0, //DDIV
0, //IREM
0, //LREM
0, //FREM
0, //DREM
0, //INEG
0, //LNEG
0, //FNEG
0, //DNEG
0, //ISHL
0, //LSHL
0, //ISHR
0, //LSHR
0, //IUSHR
0, //LUSHR
0, //IAND
0, //LAND
0, //IOR
0, //LOR
0, //IXOR
0, //LXOR
8, //IINC
0, //I2L
0, //I2F
0, //I2D
0, //L2I
0, //L2F
0, //L2D
0, //F2I
0, //F2L
0, //F2D
0, //D2I
0, //D2L
0, //D2F
0, //I2B
0, //I2C
0, //I2S
0, //LCMP
0, //FCMPL
0, //FCMPG
0, //DCMPL
0, //DCMPG
6, //IFEQ
6, //IFNE
6, //IFLT
6, //IFGE
6, //IFGT
6, //IFLE
6, //IF_ICMPEQ
6, //IF_ICMPNE
6, //IF_ICMPLT
6, //IF_ICMPGE
6, //IF_ICMPGT
6, //IF_ICMPLE
6, //IF_ACMPEQ
6, //IF_ACMPNE
6, //GOTO
6, //JSR
2, //RET
9, //TABLESWITCH
10, //LOOKUPSWITCH
0, //IRETURN
0, //LRETURN
0, //FRETURN
0, //DRETURN
0, //ARETURN
0, //RETURN
4, //GETSTATIC
4, //PUTSTATIC
4, //GETFIELD
4, //PUTFIELD
5, //INVOKEVIRTUAL
5, //INVOKESPECIAL
5, //INVOKESTATIC
5, //INVOKEINTERFACE
-1, //UNUSED
3, //NEW
1, //NEWARRAY
3, //ANEWARRAY
0, //ARRAYLENGTH
0, //ATHROW
3, //CHECKCAST
3, //INSTANCEOF
0, //MONITORENTER
0, //MONITOREXIT
-1, //WIDE
11, //MULTIANEWARRAY
6, //IFNULL
6, //IFNONNULL
-1, //GOTO_W
-1 //JSR_W
};
/**
* Constructs a new {@link CheckCodeAdapter CheckCodeAdapter} object.
*
* @param cv the code visitor to which this adapter must delegate calls.
*/
public CheckCodeAdapter (final CodeVisitor cv) {
super(cv);
this.labels = new HashMap();
}
public void visitInsn (final int opcode) {
checkEnd();
checkOpcode(opcode, 0);
cv.visitInsn(opcode);
}
public void visitIntInsn (final int opcode, final int operand) {
checkEnd();
checkOpcode(opcode, 1);
switch (opcode) {
case Constants.BIPUSH:
checkSignedByte(operand, "Invalid operand");
break;
case Constants.SIPUSH:
checkSignedShort(operand, "Invalid operand");
break;
//case Constants.NEWARRAY:
default:
if (operand < Constants.T_BOOLEAN || operand > Constants.T_LONG) {
throw new IllegalArgumentException(
"Invalid operand (must be an array type code T_...): " + operand);
}
}
cv.visitIntInsn(opcode, operand);
}
public void visitVarInsn (final int opcode, final int var) {
checkEnd();
checkOpcode(opcode, 2);
checkUnsignedShort(var, "Invalid variable index");
cv.visitVarInsn(opcode, var);
}
public void visitTypeInsn (final int opcode, final String desc) {
checkEnd();
checkOpcode(opcode, 3);
if (desc != null && desc.length() > 0 && desc.charAt(0) == '[') {
checkDesc(desc, false);
} else {
checkInternalName(desc, "type");
}
if (opcode == Constants.NEW && desc.charAt(0) == '[') {
throw new IllegalArgumentException(
"NEW cannot be used to create arrays: " + desc);
}
cv.visitTypeInsn(opcode, desc);
}
public void visitFieldInsn (
final int opcode,
final String owner,
final String name,
final String desc)
{
checkEnd();
checkOpcode(opcode, 4);
checkInternalName(owner, "owner");
checkIdentifier(name, "name");
checkDesc(desc, false);
cv.visitFieldInsn(opcode, owner, name, desc);
}
public void visitMethodInsn (
final int opcode,
final String owner,
final String name,
final String desc)
{
checkEnd();
checkOpcode(opcode, 5);
checkInternalName(owner, "owner");
checkMethodIdentifier(name, "name");
checkMethodDesc(desc);
cv.visitMethodInsn(opcode, owner, name, desc);
}
public void visitJumpInsn (final int opcode, final Label label) {
checkEnd();
checkOpcode(opcode, 6);
checkLabel(label, false, "label");
cv.visitJumpInsn(opcode, label);
}
public void visitLabel (final Label label) {
checkEnd();
checkLabel(label, false, "label");
if (labels.get(label) != null) {
throw new IllegalArgumentException("Already visited label");
} else {
labels.put(label, new Integer(labels.size()));
}
cv.visitLabel(label);
}
public void visitLdcInsn (final Object cst) {
checkEnd();
checkConstant(cst);
cv.visitLdcInsn(cst);
}
public void visitIincInsn (final int var, final int increment) {
checkEnd();
checkUnsignedShort(var, "Invalid variable index");
checkSignedShort(increment, "Invalid increment");
cv.visitIincInsn(var, increment);
}
public void visitTableSwitchInsn (
final int min,
final int max,
final Label dflt,
final Label labels[])
{
checkEnd();
if (max < min) {
throw new IllegalArgumentException(
"Max = " + max + " must be greater than or equal to min = " + min);
}
checkLabel(dflt, false, "default label");
if (labels == null || labels.length != max - min + 1) {
throw new IllegalArgumentException(
"There must be max - min + 1 labels");
}
for (int i = 0; i < labels.length; ++i) {
checkLabel(labels[i], false, "label at index " + i);
}
cv.visitTableSwitchInsn(min, max, dflt, labels);
}
public void visitLookupSwitchInsn (
final Label dflt,
final int keys[],
final Label labels[])
{
checkEnd();
checkLabel(dflt, false, "default label");
if (keys == null || labels == null || keys.length != labels.length) {
throw new IllegalArgumentException(
"There must be the same number of keys and labels");
}
for (int i = 0; i < labels.length; ++i) {
checkLabel(labels[i], false, "label at index " + i);
}
cv.visitLookupSwitchInsn(dflt, keys, labels);
}
public void visitMultiANewArrayInsn (final String desc, final int dims) {
checkEnd();
checkDesc(desc, false);
if (desc.charAt(0) != '[') {
throw new IllegalArgumentException(
"Invalid descriptor (must be an array type descriptor): " + desc);
}
if (dims < 1) {
throw new IllegalArgumentException(
"Invalid dimensions (must be greater than 0): " + dims);
}
if (dims > desc.lastIndexOf('[') + 1) {
throw new IllegalArgumentException(
"Invalid dimensions (must not be greater than dims(desc)): " + dims);
}
cv.visitMultiANewArrayInsn(desc, dims);
}
public void visitTryCatchBlock (
final Label start,
final Label end,
final Label handler,
final String type)
{
checkLabel(start, true, "start label");
checkLabel(end, true, "end label");
checkLabel(handler, true, "handler label");
if (type != null) {
checkInternalName(type, "type");
}
int s = ((Integer)labels.get(start)).intValue();
int e = ((Integer)labels.get(end)).intValue();
if (e <= s) {
throw new IllegalArgumentException(
"Invalid start and end labels (end must be greater than start)");
}
cv.visitTryCatchBlock(start, end, handler, type);
}
public void visitMaxs (final int maxStack, final int maxLocals) {
checkEnd();
end = true;
checkUnsignedShort(maxStack, "Invalid max stack");
checkUnsignedShort(maxLocals, "Invalid max locals");
cv.visitMaxs(maxStack, maxLocals);
}
public void visitLocalVariable (
final String name,
final String desc,
final Label start,
final Label end,
final int index)
{
checkIdentifier(name, "name");
checkDesc(desc, false);
checkLabel(start, true, "start label");
checkLabel(end, true, "end label");
checkUnsignedShort(index, "Invalid variable index");
int s = ((Integer)labels.get(start)).intValue();
int e = ((Integer)labels.get(end)).intValue();
if (e <= s) {
throw new IllegalArgumentException(
"Invalid start and end labels (end must be greater than start)");
}
cv.visitLocalVariable(name, desc, start, end, index);
}
public void visitLineNumber (final int line, final Label start) {
checkUnsignedShort(line, "Invalid line number");
checkLabel(start, true, "start label");
cv.visitLineNumber(line, start);
}
public void visitAttribute (Attribute attr) {
if (attr == null) {
throw new IllegalArgumentException(
"Invalid attribute (must not be null)");
}
}
// ---------------------------------------------------------------------------
/**
* Checks that the visitMaxs method has not been called.
*/
void checkEnd () {
if (end) {
throw new IllegalStateException(
"Cannot visit instructions after visitMaxs has been called.");
}
}
/**
* Checks that the type of the given opcode is equal to the given type.
*
* @param opcode the opcode to be checked.
* @param type the expected opcode type.
*/
static void checkOpcode (final int opcode, final int type) {
if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
throw new IllegalArgumentException("Invalid opcode: " + opcode);
}
}
/**
* Checks that the given value is a signed byte.
*
* @param value the value to be checked.
* @param msg an message to be used in case of error.
*/
static void checkSignedByte (final int value, final String msg) {
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
throw new IllegalArgumentException(
msg + " (must be a signed byte): " + value);
}
}
/**
* Checks that the given value is a signed short.
*
* @param value the value to be checked.
* @param msg an message to be used in case of error.
*/
static void checkSignedShort (final int value, final String msg) {
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
throw new IllegalArgumentException(
msg + " (must be a signed short): " + value);
}
}
/**
* Checks that the given value is an unsigned short.
*
* @param value the value to be checked.
* @param msg an message to be used in case of error.
*/
static void checkUnsignedShort (final int value, final String msg) {
if (value < 0 || value > 65535) {
throw new IllegalArgumentException(
msg + " (must be an unsigned short): " + value);
}
}
/**
* Checks that the given value is 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}.
*
* @param cst the value to be checked.
*/
static void checkConstant (final Object cst) {
if (!(cst instanceof Integer) &&
!(cst instanceof Float) &&
!(cst instanceof Long) &&
!(cst instanceof Double) &&
!(cst instanceof String))
{
throw new IllegalArgumentException("Invalid constant: " + cst);
}
}
/**
* Checks that the given string is a valid Java identifier.
*
* @param name the string to be checked.
* @param msg a message to be used in case of error.
*/
static void checkIdentifier (final String name, final String msg) {
checkIdentifier(name, 0, -1, msg);
}
/**
* Checks that the given substring is a valid Java identifier.
*
* @param name the string to be checked.
* @param start index of the first character of the identifier (inclusive).
* @param end index of the last character of the identifier (exclusive). -1 is
* equivalent to <tt>name.length()</tt> if name is not <tt>null</tt>.
* @param msg a message to be used in case of error.
*/
static void checkIdentifier (
final String name,
final int start,
final int end,
final String msg)
{
if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null or empty)");
}
if (!Character.isJavaIdentifierStart(name.charAt(start))) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must be a valid Java identifier): " + name);
}
int max = (end == -1 ? name.length() : end);
for (int i = start + 1; i < max; ++i) {
if (!Character.isJavaIdentifierPart(name.charAt(i))) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must be a valid Java identifier): " + name);
}
}
}
/**
* Checks that the given string is a valid Java identifier or is equal to
* '&lt;init&gt;' or '&lt;clinit&gt;'.
*
* @param name the string to be checked.
* @param msg a message to be used in case of error.
*/
static void checkMethodIdentifier (final String name, final String msg) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null or empty)");
}
if (name.equals("<init>") || name.equals("<clinit>")) {
return;
}
if (!Character.isJavaIdentifierStart(name.charAt(0))) {
throw new IllegalArgumentException(
"Invalid " + msg +
" (must be a '<init>', '<clinit>' or a valid Java identifier): " +
name);
}
for (int i = 1; i < name.length(); ++i) {
if (!Character.isJavaIdentifierPart(name.charAt(i))) {
throw new IllegalArgumentException(
"Invalid " + msg +
" (must be '<init>' or '<clinit>' or a valid Java identifier): " +
name);
}
}
}
/**
* Checks that the given string is a valid internal class name.
*
* @param name the string to be checked.
* @param msg a message to be used in case of error.
*/
static void checkInternalName (final String name, final String msg) {
checkInternalName(name, 0, -1, msg);
}
/**
* Checks that the given substring is a valid internal class name.
*
* @param name the string to be checked.
* @param start index of the first character of the identifier (inclusive).
* @param end index of the last character of the identifier (exclusive). -1 is
* equivalent to <tt>name.length()</tt> if name is not <tt>null</tt>.
* @param msg a message to be used in case of error.
*/
static void checkInternalName (
final String name,
final int start,
final int end,
final String msg)
{
if (name == null || name.length() == 0) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null or empty)");
}
int max = (end == -1 ? name.length() : end);
try {
int begin = start;
int slash;
do {
slash = name.indexOf('/', begin + 1);
if (slash == -1 || slash > max) {
slash = max;
}
checkIdentifier(name, begin, slash, null);
begin = slash + 1;
} while (slash != max);
} catch (IllegalArgumentException _) {
throw new IllegalArgumentException(
"Invalid " + msg +
" (must be a fully qualified class name in internal form): " +
name);
}
}
/**
* Checks that the given string is a valid type descriptor.
*
* @param desc the string to be checked.
* @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
*/
static void checkDesc (final String desc, final boolean canBeVoid) {
int end = checkDesc(desc, 0, canBeVoid);
if (end != desc.length()) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
}
/**
* Checks that a the given substring is a valid type descriptor.
*
* @param desc the string to be checked.
* @param start index of the first character of the identifier (inclusive).
* @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
* @return the index of the last character of the type decriptor, plus one.
*/
static int checkDesc (
final String desc,
final int start,
final boolean canBeVoid)
{
if (desc == null || start >= desc.length()) {
throw new IllegalArgumentException(
"Invalid type descriptor (must not be null or empty)");
}
int index;
switch (desc.charAt(start)) {
case 'V':
if (canBeVoid) {
return start + 1;
} else {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
case 'Z':
case 'C':
case 'B':
case 'S':
case 'I':
case 'F':
case 'J':
case 'D':
return start + 1;
case '[':
index = start + 1;
while (index < desc.length() && desc.charAt(index) == '[') {
++index;
}
if (index < desc.length()) {
return checkDesc(desc, index, false);
} else {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
case 'L':
index = desc.indexOf(';', start);
if (index == -1 || index - start < 2) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
try {
checkInternalName(desc, start + 1, index, null);
} catch (IllegalArgumentException _) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
return index + 1;
default:
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
}
/**
* Checks that the given string is a valid method descriptor.
*
* @param desc the string to be checked.
*/
static void checkMethodDesc (final String desc) {
if (desc == null || desc.length() == 0) {
throw new IllegalArgumentException(
"Invalid method descriptor (must not be null or empty)");
}
if (desc.charAt(0) != '(' || desc.length() < 3) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
int start = 1;
if (desc.charAt(start) != ')') {
do {
if (desc.charAt(start) == 'V') {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
start = checkDesc(desc, start, false);
} while (start < desc.length() && desc.charAt(start) != ')');
}
start = checkDesc(desc, start + 1, true);
if (start != desc.length()) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
}
/**
* Checks that the given label is not null. This method can also check that
* the label has been visited.
*
* @param label the label to be checked.
* @param checkVisited <tt>true</tt> to check that the label has been visited.
* @param msg a message to be used in case of error.
*/
void checkLabel (
final Label label,
final boolean checkVisited,
final String msg)
{
if (label == null) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null)");
}
if (checkVisited && labels.get(label) == null) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must be visited first)");
}
}
}

View File

@ -0,0 +1,532 @@
/***
* 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.util;
import java.io.FileInputStream;
import java.io.PrintWriter;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.attrs.Dumpable;
/**
* A {@link PrintClassVisitor PrintClassVisitor} that prints the ASM code that
* generates the classes it visits. This class visitor can be used to quickly
* write ASM code to generate some given bytecode:
* <ul>
* <li>write the Java source code equivalent to the bytecode you want to
* generate;</li>
* <li>compile it with <tt>javac</tt>;</li>
* <li>make a {@link DumpClassVisitor DumpClassVisitor} visit this compiled
* class (see the {@link #main main} method);</li>
* <li>edit the generated source code, if necessary.</li>
* </ul>
* The source code printed when visiting the <tt>Hello</tt> class is the
* following:
* <p>
* <blockquote>
* <pre>
* import org.objectweb.asm.*;
* import java.io.FileOutputStream;
*
* public class Dump implements Constants {
*
* public static void main (String[] args) throws Exception {
*
* ClassWriter cw = new ClassWriter(false);
* CodeVisitor cv;
*
* cw.visit(ACC_PUBLIC + ACC_SUPER, "Hello", "java/lang/Object", null, "Hello.java");
*
* {
* cv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
* cv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
* cv.visitLdcInsn("hello");
* cv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
* cv.visitInsn(RETURN);
* cv.visitMaxs(2, 1);
* }
* {
* cv = cw.visitMethod(ACC_PUBLIC, "&lt;init&gt;", "()V", null, null);
* cv.visitVarInsn(ALOAD, 0);
* cv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "&lt;init&gt;", "()V");
* cv.visitInsn(RETURN);
* cv.visitMaxs(1, 1);
* }
* cw.visitEnd();
*
* FileOutputStream os = new FileOutputStream("Dumped.class");
* os.write(cw.toByteArray());
* os.close();
* }
* }
* </pre>
* </blockquote>
* where <tt>Hello</tt> is defined by:
* <p>
* <blockquote>
* <pre>
* public class Hello {
*
* public static void main (String[] args) {
* System.out.println("hello");
* }
* }
* </pre>
* </blockquote>
*/
public class DumpClassVisitor extends PrintClassVisitor {
private static final int ACCESS_CLASS = 262144;
private static final int ACCESS_FIELD = 524288;
/**
* Prints the ASM source code to generate the given class to the standard
* output.
* <p>
* Usage: DumpClassVisitor
* &lt;fully qualified class name or class file name&gt;
*
* @param args the command line arguments.
*
* @throws Exception if the class cannot be found, or if an IO exception
* occurs.
*/
public static void main (final String[] args) throws Exception {
if (args.length == 0) {
System.err.println("Prints the ASM code to generate the given class.");
System.err.println("Usage: DumpClassVisitor " +
"<fully qualified class name or class file name>");
System.exit(-1);
}
ClassReader cr;
if (args[0].endsWith(".class")) {
cr = new ClassReader(new FileInputStream(args[0]));
} else {
cr = new ClassReader(args[0]);
}
cr.accept(new DumpClassVisitor(new PrintWriter(System.out)),
PrintClassVisitor.DEFAULT_ATTRIBUTES, true);
}
/**
* Constructs a new {@link DumpClassVisitor DumpClassVisitor} object.
*
* @param pw the print writer to be used to print the class.
*/
public DumpClassVisitor (final PrintWriter pw) {
super(pw);
}
public void visit (
final int access,
final String name,
final String superName,
final String[] interfaces,
final String sourceFile)
{
text.add("import org.objectweb.asm.*;\n");
text.add("import org.objectweb.asm.attrs.*;\n");
text.add("import java.io.FileOutputStream;\n\n");
text.add("public class Dump implements Constants {\n\n");
text.add("public static void main (String[] args) throws Exception {\n\n");
text.add("ClassWriter cw = new ClassWriter(false);\n");
text.add("CodeVisitor cv;\n\n");
buf.setLength(0);
buf.append("cw.visit(");
appendAccess(access | ACCESS_CLASS);
buf.append(", ");
appendConstant(buf, name);
buf.append(", ");
appendConstant(buf, superName);
buf.append(", ");
if (interfaces != null && interfaces.length > 0) {
buf.append("new String[] {");
for (int i = 0; i < interfaces.length; ++i) {
buf.append(i == 0 ? " " : ", ");
appendConstant(buf, interfaces[i]);
}
buf.append(" }");
} else {
buf.append("null");
}
buf.append(", ");
appendConstant(buf, sourceFile);
buf.append(");\n\n");
text.add(buf.toString());
}
public void visitInnerClass (
final String name,
final String outerName,
final String innerName,
final int access)
{
buf.setLength(0);
buf.append("cw.visitInnerClass(");
appendConstant(buf, name);
buf.append(", ");
appendConstant(buf, outerName);
buf.append(", ");
appendConstant(buf, innerName);
buf.append(", ");
appendAccess(access);
buf.append(");\n\n");
text.add(buf.toString());
}
public void visitField (
final int access,
final String name,
final String desc,
final Object value,
final Attribute attrs)
{
buf.setLength(0);
if (attrs != null) {
buf.append("// FIELD ATTRIBUTES\n");
Attribute a = attrs;
int n = 1;
while (a != null) {
if (a instanceof Dumpable) {
((Dumpable)a).dump(buf, "attrs" + n, null);
if (n > 1) {
buf.append("attrs" + (n - 1) + " = attrs" + n + ";\n");
}
} else {
buf.append("// WARNING! skipped non standard field attribute of type ");
buf.append(a.type).append("\n");
}
n++;
a = a.next;
}
}
buf.append("cw.visitField(");
appendAccess(access | ACCESS_FIELD);
buf.append(", ");
appendConstant(buf, name);
buf.append(", ");
appendConstant(buf, desc);
buf.append(", ");
appendConstant(buf, value);
if (attrs==null) {
buf.append(", null);\n\n");
} else {
buf.append(", attrs1);\n\n");
}
text.add(buf.toString());
}
public CodeVisitor visitMethod (
final int access,
final String name,
final String desc,
final String[] exceptions,
final Attribute attrs)
{
buf.setLength(0);
buf.append("{\n");
if (attrs != null) {
buf.append("// METHOD ATTRIBUTES\n");
Attribute a = attrs;
int n = 1;
while (a != null) {
if (a instanceof Dumpable) {
((Dumpable)a).dump(buf, "attrs" + n, null);
if (n > 1) {
buf.append("attrs" + (n - 1) + " = attrs" + n + ";\n");
}
} else {
buf.append("// WARNING! skipped non standard method attribute of type ");
buf.append(a.type).append("\n");
}
n++;
a = a.next;
}
}
buf.append("cv = cw.visitMethod(");
appendAccess(access);
buf.append(", ");
appendConstant(buf, name);
buf.append(", ");
appendConstant(buf, desc);
buf.append(", ");
if (exceptions != null && exceptions.length > 0) {
buf.append("new String[] {");
for (int i = 0; i < exceptions.length; ++i) {
buf.append(i == 0 ? " " : ", ");
appendConstant(buf, exceptions[i]);
}
buf.append(" }");
} else {
buf.append("null");
}
if (attrs==null) {
buf.append(", null);\n");
} else {
buf.append(", attrs1);\n");
}
text.add(buf.toString());
PrintCodeVisitor pcv = new DumpCodeVisitor();
text.add(pcv.getText());
text.add("}\n");
return pcv;
}
public void visitAttribute (final Attribute attr) {
buf.setLength(0);
if (attr instanceof Dumpable) {
buf.append("{\n");
buf.append("// CLASS ATRIBUTE\n");
((Dumpable)attr).dump(buf, "attr", null);
buf.append("cw.visitAttribute(attr);\n");
buf.append("}\n");
} else {
buf.append("// WARNING! skipped a non standard class attribute of type \"");
buf.append(attr.type).append("\"\n");
}
text.add(buf.toString());
}
public void visitEnd () {
text.add("cw.visitEnd();\n\n");
text.add("FileOutputStream os = new FileOutputStream(\"Dumped.class\");\n");
text.add("os.write(cw.toByteArray());\n");
text.add("os.close();\n");
text.add("}\n");
text.add("}\n");
super.visitEnd();
}
/**
* Appends a string representation of the given access modifiers to {@link
* #buf buf}.
*
* @param access some access modifiers.
*/
void appendAccess (final int access) {
boolean first = true;
if ((access & Constants.ACC_PUBLIC) != 0) {
buf.append("ACC_PUBLIC");
first = false;
}
if ((access & Constants.ACC_PRIVATE) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_PRIVATE");
first = false;
}
if ((access & Constants.ACC_PROTECTED) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_PROTECTED");
first = false;
}
if ((access & Constants.ACC_FINAL) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_FINAL");
first = false;
}
if ((access & Constants.ACC_STATIC) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_STATIC");
first = false;
}
if ((access & Constants.ACC_SYNCHRONIZED) != 0) {
if (!first) {
buf.append(" + ");
}
if ((access & ACCESS_CLASS) != 0) {
buf.append("ACC_SUPER");
} else {
buf.append("ACC_SYNCHRONIZED");
}
first = false;
}
if ((access & Constants.ACC_VOLATILE) != 0 && (access & ACCESS_FIELD) != 0 ) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_VOLATILE");
first = false;
}
if ((access & Constants.ACC_BRIDGE) != 0 &&
(access & ACCESS_CLASS) == 0 && (access & ACCESS_FIELD) == 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_BRIDGE");
first = false;
}
if ((access & Constants.ACC_VARARGS) != 0 &&
(access & ACCESS_CLASS) == 0 && (access & ACCESS_FIELD) == 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_VARARGS");
first = false;
}
if ((access & Constants.ACC_TRANSIENT) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_TRANSIENT");
first = false;
}
if ((access & Constants.ACC_NATIVE) != 0 &&
(access & ACCESS_CLASS) == 0 &&
(access & ACCESS_FIELD) == 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_NATIVE");
first = false;
}
if ((access & Constants.ACC_ENUM) != 0 &&
((access & ACCESS_CLASS) != 0 || (access & ACCESS_FIELD) != 0)) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_ENUM");
first = false;
}
if ((access & Constants.ACC_ABSTRACT) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_ABSTRACT");
first = false;
}
if ((access & Constants.ACC_INTERFACE) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_INTERFACE");
first = false;
}
if ((access & Constants.ACC_STRICT) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_STRICT");
first = false;
}
if ((access & Constants.ACC_SYNTHETIC) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_SYNTHETIC");
first = false;
}
if ((access & Constants.ACC_DEPRECATED) != 0) {
if (!first) {
buf.append(" + ");
}
buf.append("ACC_DEPRECATED");
first = false;
}
if (first) {
buf.append("0");
}
}
/**
* Appends a string representation of the given constant to the given buffer.
*
* @param buf a string buffer.
* @param cst an {@link java.lang.Integer Integer}, {@link java.lang.Float
* Float}, {@link java.lang.Long Long}, {@link java.lang.Double Double}
* or {@link String String} object. May be <tt>null</tt>.
*/
static void appendConstant (final StringBuffer buf, final Object cst) {
if (cst == null) {
buf.append("null");
} else if (cst instanceof String) {
String s = (String)cst;
buf.append("\"");
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (c == '\n') {
buf.append("\\n");
} else if (c == '\\') {
buf.append("\\\\");
} else if (c == '"') {
buf.append("\\\"");
} else {
buf.append(c);
}
}
buf.append("\"");
} else if (cst instanceof Integer) {
buf.append("new Integer(")
.append(cst)
.append(")");
} else if (cst instanceof Float) {
buf.append("new Float(")
.append(cst)
.append("F)");
} else if (cst instanceof Long) {
buf.append("new Long(")
.append(cst)
.append("L)");
} else if (cst instanceof Double) {
buf.append("new Double(")
.append(cst)
.append(")");
}
}
}

Some files were not shown because too many files have changed in this diff Show More