Permalink
Browse files

Args splat pass support.

  • Loading branch information...
1 parent 571604e commit 898b5b84659f445f021c9581ec4264736a5fd141 @m2ym committed Feb 16, 2010
@@ -49,6 +49,10 @@ public Scope getCurrentScope() {
return scopes.peek();
}
+ public IRubyObject getConstant(String name) {
+ return getCurrentScope().getModule().getConstant(name);
+ }
+
public Frame getCurrentFrame() {
return frame;
}
@@ -68,8 +72,4 @@ public Block getFrameBlock() {
public Visibility getFrameVisibility() {
return getCurrentFrame().getVisibility();
}
-
- public IRubyObject getConstant(String name) {
- return getFrameModule().getConstant(name);
- }
}
@@ -11,6 +11,7 @@
import java.util.HashMap;
import java.util.Queue;
import java.util.Collections;
+import java.util.Arrays;
import org.jruby.ast.AliasNode;
import org.jruby.ast.AndNode;
@@ -571,10 +572,33 @@ public Object visitArgsNode(ArgsNode node) {
}
public Object visitArgsCatNode(ArgsCatNode node) {
- // FIXME
- Logger.fixme("argscat node is not implemented yet.");
- return NULL_VERTEX;
- //throw new UnsupportedOperationException();
+ Vertex vertex = createEmptyVertex(node);
+ Vertex first = createVertex(node.getFirstNode());
+ SplatVertex second = new SplatVertex(node, createVertex(node.getSecondNode()));
+ RuntimeHelper.splatValue(this, second);
+ for (IRubyObject a : first.getTypeSet()) {
+ List<Vertex> elements = new ArrayList<Vertex>();
+ if (a instanceof Array) {
+ Array array = (Array) a;
+ if (array.getElements() != null) {
+ elements.addAll(Arrays.asList(array.getElements()));
+ }
+ } else {
+ elements.add(createFreeSingleTypeVertex(a));
+ }
+ for (IRubyObject b : second.getTypeSet()) {
+ if (b instanceof Array) {
+ Array array = (Array) b;
+ if (array.getElements() != null) {
+ elements.addAll(Arrays.asList(array.getElements()));
+ }
+ } else {
+ elements.add(createFreeSingleTypeVertex(a));
+ }
+ }
+ vertex.addType(RuntimeHelper.createArray(this, elements.toArray(new Vertex[0])));
+ }
+ return vertex;
}
public Object visitArgsPushNode(ArgsPushNode node) {
@@ -657,24 +681,8 @@ public Object visitClassVarNode(ClassVarNode node) {
public Object visitCallNode(CallNode node) {
Vertex receiverVertex = createVertex(node.getReceiverNode());
- Vertex[] argVertices = null;
- if (node.getArgsNode() != null) {
- List<Node> argNodes = node.getArgsNode().childNodes();
- argVertices = new Vertex[argNodes.size()];
- for (int i = 0; i < argVertices.length; i++) {
- argVertices[i] = createVertex(argNodes.get(i));
- }
- }
-
- Block block = null;
- if (node.getIterNode() instanceof IterNode) {
- IterNode iterNode = (IterNode) node.getIterNode();
- DynamicScope scope = new DynamicScope(context.getCurrentScope().getModule(), context.getCurrentScope());
- block = new Block(iterNode.getVarNode(), iterNode.getBodyNode(), context.getCurrentFrame(), scope);
- } else if (node.getIterNode() != null) {
- // FIXME
- Logger.debug("unknnown iternode: %s", node.getIterNode());
- }
+ Vertex[] argVertices = RuntimeHelper.setupCallArgs(this, node.getArgsNode());
+ Block block = RuntimeHelper.setupCallBlock(this, node.getIterNode());
CallVertex vertex = new CallVertex(node, receiverVertex, argVertices, block);
return RuntimeHelper.call(this, vertex);
}
@@ -887,28 +895,8 @@ public Object visitEvStrNode(EvStrNode node) {
}
public Object visitFCallNode(FCallNode node) {
- Vertex[] argVertices = null;
- if (node.getArgsNode() != null) {
- List<Node> argNodes = node.getArgsNode().childNodes();
- argVertices = new Vertex[argNodes.size()];
- for (int i = 0; i < argVertices.length; i++) {
- argVertices[i] = createVertex(argNodes.get(i));
- }
- }
-
- Block block = null;
- if (node.getIterNode() != null) {
- switch (node.getIterNode().getNodeType()) {
- case ITERNODE: {
- IterNode iterNode = (IterNode) node.getIterNode();
- block = new Block(iterNode.getVarNode(), iterNode.getBodyNode(), context.getCurrentFrame(), context.getCurrentScope());
- break;
- }
- case BLOCKPASSNODE:
- block = context.getFrameBlock();
- break;
- }
- }
+ Vertex[] argVertices = RuntimeHelper.setupCallArgs(this, node.getArgsNode());
+ Block block = RuntimeHelper.setupCallBlock(this, node.getIterNode());
CallVertex vertex = new CallVertex(node, createFreeSingleTypeVertex(context.getFrameSelf()), argVertices, block);
return RuntimeHelper.call(this, vertex);
}
@@ -30,6 +30,7 @@
import org.jruby.ast.Colon2ImplicitNode;
import org.jruby.ast.Colon3Node;
import org.jruby.ast.AssignableNode;
+import org.jruby.ast.IterNode;
import org.jruby.ast.YieldNode;
import org.jruby.ast.ZeroArgNode;
import org.jruby.ast.MethodDefNode;
@@ -411,6 +412,53 @@ public static void multipleAssign(Graph graph, MultipleAsgnNode node, Array arra
}
}
+ public static Vertex[] setupCallArgs(Graph graph, Node argsNode) {
+ List<Vertex> args = new ArrayList<Vertex>();
+ if (argsNode != null) {
+ switch (argsNode.getNodeType()) {
+ case ARGSCATNODE:
+ case SPLATNODE: {
+ Vertex arrayVertex = graph.createVertex(argsNode);
+ for (IRubyObject object : arrayVertex.getTypeSet()) {
+ if (object instanceof Array) {
+ Array array = (Array) object;
+ if (array.getElements() != null) {
+ for (Vertex element : array.getElements()) {
+ args.add(element);
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ for (Node arg : argsNode.childNodes()) {
+ args.add(graph.createVertex(arg));
+ }
+ }
+ }
+ return args.isEmpty() ? null : args.toArray(new Vertex[0]);
+ }
+
+ public static Block setupCallBlock(Graph graph, Node iterNode) {
+ Context context = graph.getRuntime().getContext();
+ Block block = null;
+ if (iterNode != null) {
+ switch (iterNode.getNodeType()) {
+ case ITERNODE: {
+ IterNode inode = (IterNode) iterNode;
+ DynamicScope scope = new DynamicScope(context.getCurrentScope().getModule(), context.getCurrentScope());
+ block = new Block(inode.getVarNode(), inode.getBodyNode(), context.getCurrentFrame(), scope);
+ break;
+ }
+ case BLOCKPASSNODE:
+ block = context.getFrameBlock();
+ break;
+ }
+ }
+ return block;
+ }
+
public static Vertex call(Graph graph, CallVertex vertex) {
return call(graph, vertex, false);
}
@@ -1,13 +1,13 @@
package org.cx4a.rsense.typing.vertex;
-import org.jruby.ast.SplatNode;
+import org.jruby.ast.Node;
import org.cx4a.rsense.typing.Propagation;
public class SplatVertex extends Vertex {
private Vertex valueVertex;
- public SplatVertex(SplatNode node, Vertex valueVertex) {
+ public SplatVertex(Node node, Vertex valueVertex) {
super(node);
this.valueVertex = valueVertex;
valueVertex.addEdge(this);
View
@@ -6,6 +6,48 @@ type-inference --test=String --should-be=String
''_|_
EOF
+type-inference --test=Constant1 --should-be=Fixnum
+C = 1
+C_|_
+EOF
+
+type-inference --test=Constant2 --should-be=Fixnum
+module M
+ C = 1
+end
+M::C_|_
+EOF
+
+type-inference --test=Constant3 --should-be=Fixnum
+C = 1
+def f
+ C
+end
+f_|_
+EOF
+
+type-inference --test=Constant4 --should-be=Fixnum
+class C
+ D = 1
+ def f
+ D
+ end
+end
+C.new.f_|_
+EOF
+
+type-inference --test=Constant5 --should-be=Fixnum
+class C
+ A = 1
+end
+class D < C
+ def f
+ A
+ end
+end
+D.new.f_|_
+EOF
+
type-inference --test=Array --should-be=Array
[]_|_
EOF
@@ -149,6 +191,29 @@ end
f(1, 2)_|_
EOF
+type-inference --test=Method.Arg.Splat.Pass1 --should-be=Float
+def f(x, y)
+ y
+end
+f(*[1, 2.3])_|_
+EOF
+
+type-inference --test=Method.Arg.Splat.Pass2 --should-be=Fixnum
+def f(x, y)
+ x
+end
+f(1, *[1, 2.3])_|_
+EOF
+
+type-inference --test=Method.Arg.Splat.Pass3 --should-be=Float
+a = [2.3, '']
+b = [1]
+def f(x, y, z)
+ y
+end
+f(b, *a)_|_
+EOF
+
type-inference --test=Method.Arg.OptionalAndSplat1 --should-be=Fixnum
def f(x, y = 1, *z)
y

0 comments on commit 898b5b8

Please sign in to comment.