public void buildBlockArgsAssignment(Node node, IRScope s, int argIndex, boolean isSplat) {
Variable v;
switch (node.getNodeType()) {
case ATTRASSIGNNODE:
v = s.getNewTemporaryVariable();
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
buildAttrAssignAssignment(node, s, v);
break;
// SSS FIXME:
//
// There are also differences in variable scoping between 1.8 and 1.9
// Ruby 1.8 is the buggy semantics if I understand correctly.
//
// The semantics of how this shadows other variables outside the block needs
// to be figured out during live var analysis.
case DASGNNODE: {
DAsgnNode dynamicAsgn = (DAsgnNode) node;
// SSS FIXME: Isn't it sufficient to use "getLocalVariable(variable.getName())"?
v = getScopeNDown(s, dynamicAsgn.getDepth()).getLocalVariable(dynamicAsgn.getName());
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
break;
}
// SSS FIXME: What is the difference between ClassVarAsgnNode & ClassVarDeclNode
case CLASSVARASGNNODE:
v = s.getNewTemporaryVariable();
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
s.addInstr(new PutClassVariableInstr(MetaObject.create(s).getNearestClass(), ((ClassVarAsgnNode)node).getName(), v));
break;
case CLASSVARDECLNODE:
v = s.getNewTemporaryVariable();
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
s.addInstr(new PutClassVariableInstr(MetaObject.create(s).getNearestClass(), ((ClassVarDeclNode)node).getName(), v));
break;
case CONSTDECLNODE:
v = s.getNewTemporaryVariable();
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
buildConstDeclAssignment((ConstDeclNode) node, s, v);
break;
case GLOBALASGNNODE:
v = s.getNewTemporaryVariable();
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
s.addInstr(new PutGlobalVarInstr(((GlobalAsgnNode)node).getName(), v));
break;
case INSTASGNNODE:
v = s.getNewTemporaryVariable();
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
// NOTE: if 's' happens to the a class, this is effectively an assignment of a class instance variable
s.addInstr(new PutFieldInstr(getSelf(s), ((InstAsgnNode)node).getName(), v));
break;
case LOCALASGNNODE: {
LocalAsgnNode localVariable = (LocalAsgnNode) node;
int depth = localVariable.getDepth();
// SSS FIXME: Isn't it sufficient to use "getLocalVariable(variable.getName())"?
v = getScopeNDown(s, depth).getLocalVariable(localVariable.getName());
s.addInstr(new ReceiveClosureArgInstr(v, argIndex, isSplat));
break;
}
case MULTIPLEASGNNODE:
// SSS FIXME: Are we guaranteed that we splats dont head to multiple-assignment nodes! i.e. |*(a,b)|?
buildMultipleAsgnAssignment((MultipleAsgnNode) node, s, null);