if (receiver instanceof Hash) {
if (args != null && args.length > 0) {
Hash hash = (Hash) receiver;
Object key = Hash.getRealKey(args[0].getNode());
if (!hash.isModified() && key != null) {
Vertex v = hash.get(key);
if (v != null) {
ts.addAll(v.getTypeSet());
}
}
}
} else if (receiver instanceof Array) {
if (args != null && args.length > 0) {
Array array = (Array) receiver;
Integer n = Vertex.getFixnum(args[0]);
if (!array.isModified() && n != null) {
Vertex v = array.getElement(n);
if (v != null) {
ts.addAll(v.getTypeSet());
}
}
}
} else if (receiver instanceof Proc) {
if (arg == null) {
if (args == null) {
arg = Arrays.asList((IRubyObject) RuntimeHelper.createArray(Graph.this, new Vertex[0]));
} else if (args.length == 1) {
arg = args[0].getTypeSet();
} else { arg = Arrays.asList((IRubyObject) RuntimeHelper.createArray(Graph.this, args));
}
}
Vertex returnVertex = createFreeVertex();
RuntimeHelper.yield(Graph.this, (Proc) receiver, arg, true, returnVertex);
ts.addAll(returnVertex.getTypeSet());
}
}
if (ts.isEmpty()) {
result.setCallNextMethod(true);
} else {
result.setResultTypeSet(ts);
}
}
});
addSpecialMethod("private", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.PRIVATE);
}
});
addSpecialMethod("protected", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.PROTECTED);
}
});
addSpecialMethod("public", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.PUBLIC);
}
});
addSpecialMethod("module_function", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.MODULE_FUNCTION);
}
});
addSpecialMethod("attr", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
if (args != null && args.length > 0) {
RuntimeHelper.defineAttrs(Graph.this, receivers, new Vertex[] { args[0] }, true, args.length > 1);
}
}
});
addSpecialMethod("attr_reader", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
RuntimeHelper.defineAttrs(Graph.this, receivers, args, true, false);
}
});
addSpecialMethod("attr_writer", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
RuntimeHelper.defineAttrs(Graph.this, receivers, args, false, true);
}
});
addSpecialMethod("attr_accessor", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
RuntimeHelper.defineAttrs(Graph.this, receivers, args, true, true);
}
});
addSpecialMethod("alias_method", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
boolean callNextMethod = true;
if (args != null && args.length == 2) {
for (IRubyObject receiver : receivers) {
if (receiver instanceof RubyModule) {
callNextMethod = false;
String newName = Vertex.getStringOrSymbol(args[0]);
String oldName = Vertex.getStringOrSymbol(args[1]);
if (newName != null && oldName != null) {
RubyModule module = (RubyModule) receiver;
DynamicMethod method = module.getMethod(oldName);
if (method instanceof Method)
module.addMethod(newName, new AliasMethod(newName, (Method) method));
}
}
}
}
result.setCallNextMethod(callNextMethod);
}
});
addSpecialMethod("unpack", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
if (args != null && args.length > 0) {
String template = Vertex.getString(args[0]);
if (template != null) {
TypeSet ts = new TypeSet();
for (IRubyObject object : receivers) {
if (object.isKindOf(runtime.getString())) {
List<Vertex> elements = new ArrayList<Vertex>();
for (char c : template.toCharArray()) {
RubyClass type = null;
switch (c) {
case 'a': case 'A': case 'Z': case 'b':
case 'B': case 'h': case 'H': case 'm':
case 'M': case 'p': case 'P': case 'u':
case 'U':
type = runtime.getString();
break;
case 'c': case 'C': case 's': case 'S':
case 'i': case 'I': case 'l': case 'L':
case 'q': case 'Q': case 'n': case 'N':
case 'v': case 'V': case 'w': case 'x':
case 'X':
type = runtime.getInteger();
break;
case 'f': case 'd': case 'e': case 'E':
case 'g': case 'G':
type = runtime.getFloat();
break;
}
if (type != null) {
elements.add(createFreeSingleTypeVertex(newInstanceOf(type)));
}
}
ts.add(RuntimeHelper.createArray(Graph.this, elements.toArray(new Vertex[0])));
}
}
if (ts.isEmpty()) {
result.setCallNextMethod(true);
} else {
result.setResultTypeSet(ts);
}
}
}
}
});
addSpecialMethod("proc", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
TypeSet ts = new TypeSet();
for (IRubyObject receiver : receivers) {
DynamicMethod method = receiver.getMetaClass().searchMethod("proc");
if (method != null && method.getModule() == runtime.getKernel()) {
if (block instanceof Proc)
ts.add((Proc) block);
else
Logger.debug("proc for no block is not supported yet");
}
}
if (ts.isEmpty())
result.setCallNextMethod(true);
else
result.setResultTypeSet(ts);
}
});
addSpecialMethod("lambda", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
TypeSet ts = new TypeSet();
for (IRubyObject receiver : receivers) {
DynamicMethod method = receiver.getMetaClass().searchMethod("lambda");
if (method != null && method.getModule() == runtime.getKernel()) {
if (block instanceof Proc)
ts.add((Proc) block);
else
Logger.debug("lambda for no block is not supported yet");
}
}
if (ts.isEmpty())
result.setCallNextMethod(true);
else
result.setResultTypeSet(ts);
}
});
addSpecialMethod("call", new SpecialMethod() {
public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
TypeSet ts = new TypeSet();
Vertex argVertex = null;
for (IRubyObject receiver : receivers) {
if (receiver instanceof Proc) {
if (argVertex == null) {
TypeSet argts;
if (args == null) {
argts = new TypeSet();
argts.add(RuntimeHelper.createArray(Graph.this, new Vertex[0]));
} else if (args.length == 1) {
argts = args[0].getTypeSet();
} else {
argts = new TypeSet();
argts.add(RuntimeHelper.createArray(Graph.this, args));
}
argVertex = createFreeVertex(argts);
argVertex.markUnchanged();
}
YieldVertex vertex = new YieldVertex(null,
RuntimeHelper.getFrameTemplate(runtime.getContext().getCurrentFrame()),
(Proc) receiver,
argVertex,