Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2cb70d200843
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 76a64bba3043
Choose a head ref
  • 2 commits
  • 10 files changed
  • 1 contributor

Commits on Dec 8, 2015

  1. Copy the full SHA
    042ac3c View commit details
  2. Copy the full SHA
    76a64bb View commit details
8 changes: 7 additions & 1 deletion core/src/main/java/org/jruby/ast/AttrAssignNode.java
Original file line number Diff line number Diff line change
@@ -41,8 +41,9 @@ public class AttrAssignNode extends Node implements INameNode, IArgumentNode {
protected final Node receiverNode;
private String name;
private Node argsNode;
private final boolean isLazy;

public AttrAssignNode(ISourcePosition position, Node receiverNode, String name, Node argsNode) {
public AttrAssignNode(ISourcePosition position, Node receiverNode, String name, Node argsNode, boolean isLazy) {
super(position, receiverNode != null && receiverNode.containsVariableAssignment() || argsNode != null && argsNode.containsVariableAssignment());

assert receiverNode != null : "receiverNode is not null";
@@ -54,6 +55,7 @@ public AttrAssignNode(ISourcePosition position, Node receiverNode, String name,
this.receiverNode = receiverNode;
this.name = name;
this.argsNode = argsNode;
this.isLazy = isLazy;
}

public NodeType getNodeType() {
@@ -106,6 +108,10 @@ public Node setArgsNode(Node argsNode) {
return this;
}

public boolean isLazy() {
return isLazy;
}

public List<Node> childNodes() {
return Node.createList(receiverNode, argsNode);
}
11 changes: 11 additions & 0 deletions core/src/main/java/org/jruby/ast/CallNode.java
Original file line number Diff line number Diff line change
@@ -46,9 +46,15 @@ public class CallNode extends Node implements INameNode, IArgumentNode, BlockAcc
private Node argsNode;
protected Node iterNode;
private String name;
private final boolean isLazy;

public CallNode(ISourcePosition position, Node receiverNode, String name, Node argsNode,
Node iterNode) {
this(position, receiverNode, name, argsNode, iterNode, false);
}

public CallNode(ISourcePosition position, Node receiverNode, String name, Node argsNode,
Node iterNode, boolean isLazy) {
super(position, receiverNode.containsVariableAssignment() ||
argsNode != null && argsNode.containsVariableAssignment() ||
iterNode != null && iterNode.containsVariableAssignment());
@@ -59,6 +65,7 @@ public CallNode(ISourcePosition position, Node receiverNode, String name, Node a
this.receiverNode = receiverNode;
this.argsNode = argsNode;
this.iterNode = iterNode;
this.isLazy = isLazy;
}

public NodeType getNodeType() {
@@ -119,6 +126,10 @@ public String getName() {
public Node getReceiverNode() {
return receiverNode;
}

public boolean isLazy() {
return isLazy;
}

public List<Node> childNodes() {
return Node.createList(receiverNode, argsNode, iterNode);
8 changes: 7 additions & 1 deletion core/src/main/java/org/jruby/ast/OpAsgnNode.java
Original file line number Diff line number Diff line change
@@ -45,8 +45,9 @@ public class OpAsgnNode extends Node {
private final String variableName;
private final String operatorName;
private final String variableNameAsgn;
private final boolean isLazy;

public OpAsgnNode(ISourcePosition position, Node receiverNode, Node valueNode, String variableName, String operatorName) {
public OpAsgnNode(ISourcePosition position, Node receiverNode, Node valueNode, String variableName, String operatorName, boolean isLazy) {
super(position, receiverNode.containsVariableAssignment());

assert receiverNode != null : "receiverNode is not null";
@@ -57,6 +58,7 @@ public OpAsgnNode(ISourcePosition position, Node receiverNode, Node valueNode, S
this.variableName = variableName;
this.operatorName = operatorName;
this.variableNameAsgn = (variableName + "=").intern();
this.isLazy = isLazy;
}

public NodeType getNodeType() {
@@ -111,6 +113,10 @@ public List<Node> childNodes() {
return Node.createList(receiverNode, valueNode);
}

public boolean isLazy() {
return isLazy;
}

@Override
public boolean needsDefinitionCheck() {
return false;
67 changes: 59 additions & 8 deletions core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -841,11 +841,28 @@ public Operand buildArgsPush(final ArgsPushNode node) {
private Operand buildAttrAssign(final AttrAssignNode attrAssignNode) {
boolean containsAssignment = attrAssignNode.containsVariableAssignment();
Operand obj = buildWithOrder(attrAssignNode.getReceiverNode(), containsAssignment);

Label lazyLabel = getNewLabel();
Label endLabel = getNewLabel();
Variable result = createTemporaryVariable();
if (attrAssignNode.isLazy()) {
addInstr(new BNilInstr(lazyLabel, obj));
}

List<Operand> args = new ArrayList<>();
Node argsNode = attrAssignNode.getArgsNode();
Operand lastArg = buildAttrAssignCallArgs(args, argsNode, containsAssignment);
addInstr(AttrAssignInstr.create(obj, attrAssignNode.getName(), args.toArray(new Operand[args.size()]), scope.maybeUsingRefinements()));
return lastArg;
addInstr(new CopyInstr(result, lastArg));

if (attrAssignNode.isLazy()) {
addInstr(new JumpInstr(endLabel));
addInstr(new LabelInstr(lazyLabel));
addInstr(new CopyInstr(result, manager.getNil()));
addInstr(new LabelInstr(endLabel));
}

return result;
}

public Operand buildAttrAssignAssignment(Node node, Operand value) {
@@ -1002,9 +1019,17 @@ public Operand buildCall(CallNode callNode) {
// that is incorrect IR because the receiver has to be built *before* call arguments are built
// to preserve expected code execution order
Operand receiver = buildWithOrder(receiverNode, callNode.containsVariableAssignment());
Operand[] args = setupCallArgs(callArgsNode);
Operand block = setupCallClosure(callNode.getIterNode());
Variable callResult = createTemporaryVariable();

Label lazyLabel = getNewLabel();
Label endLabel = getNewLabel();
if (callNode.isLazy()) {
addInstr(new BNilInstr(lazyLabel, receiver));
}

Operand[] args = setupCallArgs(callArgsNode);
Operand block = setupCallClosure(callNode.getIterNode());

CallInstr callInstr = CallInstr.create(scope, callResult, callNode.getName(), receiver, args, block);

// This is to support the ugly Proc.new with no block, which must see caller's frame
@@ -1015,6 +1040,14 @@ public Operand buildCall(CallNode callNode) {
}

receiveBreakException(block, callInstr);

if (callNode.isLazy()) {
addInstr(new JumpInstr(endLabel));
addInstr(new LabelInstr(lazyLabel));
addInstr(new CopyInstr(callResult, manager.getNil()));
addInstr(new LabelInstr(endLabel));
}

return callResult;
}

@@ -2809,13 +2842,22 @@ public Operand buildNil() {
return manager.getNil();
}

// FIXME: The logic for lazy and non-lazy building is pretty icky...clean up
public Operand buildOpAsgn(OpAsgnNode opAsgnNode) {
Label l;
Variable readerValue = createTemporaryVariable();
Variable writerValue = createTemporaryVariable();

// get attr
Operand v1 = build(opAsgnNode.getReceiverNode());

Label lazyLabel = getNewLabel();
Label endLabel = getNewLabel();
Variable result = createTemporaryVariable();
if (opAsgnNode.isLazy()) {
addInstr(new BNilInstr(lazyLabel, v1));
}

addInstr(CallInstr.create(scope, readerValue, opAsgnNode.getVariableName(), v1, NO_ARGS, null));

// Ex: e.val ||= n
@@ -2834,10 +2876,10 @@ public Operand buildOpAsgn(OpAsgnNode opAsgnNode) {
addInstr(new CopyInstr(readerValue, v2));
addInstr(new LabelInstr(l));

return readerValue;
}
// Ex: e.val = e.val.f(n)
else {
if (!opAsgnNode.isLazy()) return readerValue;

addInstr(new CopyInstr(result, readerValue));
} else { // Ex: e.val = e.val.f(n)
// call operator
Operand v2 = build(opAsgnNode.getValueNode());
Variable setValue = createTemporaryVariable();
@@ -2847,8 +2889,17 @@ public Operand buildOpAsgn(OpAsgnNode opAsgnNode) {
addInstr(CallInstr.create(scope, writerValue, opAsgnNode.getVariableNameAsgn(), v1, new Operand[] {setValue}, null));
// Returning writerValue is incorrect becuase the assignment method
// might return something else other than the value being set!
return setValue;
if (!opAsgnNode.isLazy()) return setValue;

addInstr(new CopyInstr(result, setValue));
}

addInstr(new JumpInstr(endLabel));
addInstr(new LabelInstr(lazyLabel));
addInstr(new CopyInstr(result, manager.getNil()));
addInstr(new LabelInstr(endLabel));

return result;
}

// Translate "x &&= y" --> "x = y if is_true(x)" -->
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/lexer/yacc/RubyLexer.java
Original file line number Diff line number Diff line change
@@ -1543,6 +1543,9 @@ private int ampersand(boolean spaceSeen) throws IOException {
yaccValue = "&";
setState(LexState.EXPR_BEG);
return Tokens.tOP_ASGN;
case '.':
yaccValue = "&.";
return Tokens.tANDDOT;
}
pushback(c);

33 changes: 25 additions & 8 deletions core/src/main/java/org/jruby/parser/ParserSupport.java
Original file line number Diff line number Diff line change
@@ -280,7 +280,7 @@ public Node getMatchNode(Node firstNode, Node secondNode) {
public Node aryset(Node receiver, Node index) {
checkExpression(receiver);

return new_attrassign(receiver.getPosition(), receiver, "[]=", index);
return new_attrassign(receiver.getPosition(), receiver, "[]=", index, false);
}

/**
@@ -291,9 +291,13 @@ public Node aryset(Node receiver, Node index) {
* @return an AttrAssignNode
*/
public Node attrset(Node receiver, String name) {
return attrset(receiver, ".", name);
}

public Node attrset(Node receiver, String callType, String name) {
checkExpression(receiver);

return new_attrassign(receiver.getPosition(), receiver, name + "=", null);
return new_attrassign(receiver.getPosition(), receiver, name + "=", null, isLazy(callType));
}

public void backrefAssignError(Node node) {
@@ -731,9 +735,17 @@ public Node new_opElementAsgnNode(Node receiverNode, String operatorName, Node a

return newNode;
}

public Node newOpAsgn(ISourcePosition position, Node receiverNode, String callType, Node valueNode, String variableName, String operatorName) {
return new OpAsgnNode(position, receiverNode, valueNode, variableName, operatorName, isLazy(callType));
}

public boolean isLazy(String callType) {
return "&.".equals(callType);
}

public Node new_attrassign(ISourcePosition position, Node receiver, String name, Node args) {
return new AttrAssignNode(position, receiver, name, args);
public Node new_attrassign(ISourcePosition position, Node receiver, String name, Node args, boolean isLazy) {
return new AttrAssignNode(position, receiver, name, args, isLazy);
}

private boolean isNumericOperator(String name) {
@@ -755,15 +767,20 @@ private boolean isNumericOperator(String name) {
return false;
}

public Node new_call(Node receiver, String name, Node argsNode, Node iter) {
public Node new_call(Node receiver, String callType, String name, Node argsNode, Node iter) {
if (argsNode instanceof BlockPassNode) {
if (iter != null) lexer.compile_error(PID.BLOCK_ARG_AND_BLOCK_GIVEN, "Both block arg and actual block given.");

BlockPassNode blockPass = (BlockPassNode) argsNode;
return new CallNode(position(receiver, argsNode), receiver, name, blockPass.getArgsNode(), blockPass);
return new CallNode(position(receiver, argsNode), receiver, name, blockPass.getArgsNode(), blockPass, isLazy(callType));
}

return new CallNode(position(receiver, argsNode), receiver, name, argsNode, iter);
return new CallNode(position(receiver, argsNode), receiver, name, argsNode, iter, isLazy(callType));

}

public Node new_call(Node receiver, String name, Node argsNode, Node iter) {
return new_call(receiver, ".", name, argsNode, iter);
}

public Colon2Node new_colon2(ISourcePosition position, Node leftNode, String name) {
@@ -1369,7 +1386,7 @@ public NumericNode negateNumeric(NumericNode node) {
public Node new_defined(ISourcePosition position, Node something) {
return new DefinedNode(position, something);
}

public String internalId() {
return "";
}
Loading