Skip to content

Commit

Permalink
{**b, r: 1, **c} - kwargs splat can be anywhere in a hash literal
Browse files Browse the repository at this point in the history
  • Loading branch information
enebo committed Apr 8, 2015
1 parent d333a3a commit 5c8702a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 24 deletions.
28 changes: 18 additions & 10 deletions core/src/main/java/org/jruby/ir/IRBuilder.java
Expand Up @@ -2476,30 +2476,38 @@ public Operand buildGlobalVar(GlobalVarNode node) {

public Operand buildHash(HashNode hashNode) {
List<KeyValuePair<Operand, Operand>> args = new ArrayList<>();
Operand splatKeywordArgument = null;
boolean hasAssignments = hashNode.containsVariableAssignment();
Variable hash = null;

for (KeyValuePair<Node, Node> pair: hashNode.getPairs()) {
Node key = pair.getKey();
Operand keyOperand;

if (key == null) { // splat kwargs [e.g. foo(a: 1, **splat)] key is null and will be in last pair of hash
splatKeywordArgument = build(pair.getValue());
break;
if (key == null) { // Splat kwarg [e.g. {**splat1, a: 1, **splat2)]
if (hash == null) { // No hash yet. Define so order is preserved.
hash = copyAndReturnValue(new Hash(args));
args = new ArrayList<>(); // Used args but we may find more after the splat so we reset
} else if (!args.isEmpty()) {
addInstr(new RuntimeHelperCall(hash, MERGE_KWARGS, new Operand[] { hash, new Hash(args) }));
args = new ArrayList<>();
}
Operand splat = buildWithOrder(pair.getValue(), hasAssignments);
addInstr(new RuntimeHelperCall(hash, MERGE_KWARGS, new Operand[] { hash, splat}));
continue;
} else {
keyOperand = buildWithOrder(key, hasAssignments);
}

args.add(new KeyValuePair<>(keyOperand, buildWithOrder(pair.getValue(), hasAssignments)));
}

if (splatKeywordArgument != null) { // splat kwargs merge with any explicit kwargs
Variable tmp = createTemporaryVariable();
addInstr(new RuntimeHelperCall(tmp, MERGE_KWARGS, new Operand[] { splatKeywordArgument, new Hash(args)}));
return tmp;
} else {
return copyAndReturnValue(new Hash(args));
if (hash == null) { // non-**arg ordinary hash
hash = copyAndReturnValue(new Hash(args));
} else if (!args.isEmpty()) { // ordinary hash values encountered after a **arg
addInstr(new RuntimeHelperCall(hash, MERGE_KWARGS, new Operand[] { hash, new Hash(args) }));
}

return hash;
}

// Translate "r = if (cond); .. thenbody ..; else; .. elsebody ..; end" to
Expand Down
17 changes: 3 additions & 14 deletions test/mri/excludes/TestKeywordArguments.rb
@@ -1,18 +1,7 @@
exclude :test_bare_kwrest, "needs investigation"
exclude :test_block, "needs investigation"
exclude :test_f1, "needs investigation"
exclude :test_f2, "needs investigation"
exclude :test_f3, "needs investigation"
exclude :test_f4, "needs investigation"
exclude :test_f5, "needs investigation"
exclude :test_f7, "needs investigation"
exclude :test_f8, "needs investigation"
exclude :test_f9, "needs investigation"
exclude :test_lambda, "needs investigation"
exclude :test_block_required_keyword, "needs investigation"
exclude :test_implicit_hash_conversion, "needs investigation"
exclude :test_p1, "needs investigation"
exclude :test_p2, "needs investigation"
exclude :test_p3, "needs investigation"
exclude :test_p4, "needs investigation"
exclude :test_p5, "needs investigation"
exclude :test_p6, "needs investigation"
exclude :test_required_keyword_with_reserved, "needs investigation"
exclude :test_rest_keyrest, "needs investigation"

0 comments on commit 5c8702a

Please sign in to comment.