Skip to content
This repository has been archived by the owner on Dec 29, 2018. It is now read-only.

Commit

Permalink
Args splat pass support.
Browse files Browse the repository at this point in the history
  • Loading branch information
m2ym committed Feb 16, 2010
1 parent 571604e commit 898b5b8
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 50 deletions.
8 changes: 4 additions & 4 deletions src/org/cx4a/rsense/ruby/Context.java
Expand Up @@ -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;
}
Expand All @@ -68,8 +72,4 @@ public Block getFrameBlock() {
public Visibility getFrameVisibility() {
return getCurrentFrame().getVisibility();
}

public IRubyObject getConstant(String name) {
return getFrameModule().getConstant(name);
}
}
76 changes: 32 additions & 44 deletions src/org/cx4a/rsense/typing/Graph.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
48 changes: 48 additions & 0 deletions src/org/cx4a/rsense/typing/runtime/RuntimeHelper.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/org/cx4a/rsense/typing/vertex/SplatVertex.java
@@ -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);
Expand Down
65 changes: 65 additions & 0 deletions test/script/builtin.rsense
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 898b5b8

Please sign in to comment.