Commit 96e42df5 authored by Vít Kabele's avatar Vít Kabele

Determined context of snippet arguments. Issue #6

parent ce858db6
Pipeline #3324 passed with stages
in 3 minutes and 40 seconds
......@@ -503,7 +503,7 @@ abstract class AbstractParser {
}
static void ensureMethodHasOnlyContextArguments (
void ensureMethodHasOnlyContextArguments (
final MethodNode method
) throws ParserException {
//
......
......@@ -6,9 +6,13 @@
package ch.usi.dag.disl;
import ch.usi.dag.util.Strings;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -65,4 +69,79 @@ class IsolatedSnippetParser extends SnippetParser {
return classLoader.getClass (allClasses.get(guardName));
}
/**
* The type of each method argument must be a context of some kind.
* @param method
* @throws ParserException
*/
@Override
void ensureMethodHasOnlyContextArguments (MethodNode method)
throws ParserException
{
final Type [] argTypes = Type.getArgumentTypes (method.desc);
// For every argument, try if its type implements the interface.
// If not, then try to traverse up through the inheritance tree.
for (int argIndex = 0; argIndex < argTypes.length; argIndex++) {
final Type argType = argTypes [argIndex];
if (!isContext (argType)) {
throw new ParserException (
"argument #%d has invalid type, %s does not "+
"implement any context interface!",
(argIndex + 1), argType.getClassName ()
);
}
}
}
/**
* Recursively determine, if the given type extends one of the context types.
* Plus, if the argument extends (even transitively) the {@link ch.usi.dag.disl.staticcontext.StaticContext }
* load all the unloaded classes to the VM for later execution.
* @param type
* @return
*/
boolean isContext(final Type type){
ContextKind contextType = ContextKind.forType (type);
String className = type.getClassName ();
ClassNode classNode = allClasses.getOrDefault ( className, null );
List<ClassNode> classNodes= new ArrayList<> (); // The class nodes to load when
// StaticContext found at the end of the chain
Type t;
while(true){
if(classNode != null)
classNodes.add (classNode);
if(contextType == ContextKind.STATIC) break;
if(contextType != null) return true;
if(classNode != null){
// Then check, whether the superclass extends the context
final String superclass = classNode.superName;
// If not, return false
if (superclass.isEmpty ()) return false;
t = Type.getObjectType (superclass);
contextType = ContextKind.forType (t);
className = t.getClassName ();
classNode = allClasses.getOrDefault (className, null);
}
}
for( ClassNode cn : classNodes){
classLoader.getClass (cn);
}
return true;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment