Skip to content

Commit

Permalink
[Truffle] Add a Hash check that keys are symbols when splatted
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon Fish committed Nov 30, 2016
1 parent 2eab42d commit 6bf398b
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/language/hash_tags.txt

This file was deleted.

Expand Up @@ -16,18 +16,23 @@
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.control.RaiseException;

import java.util.ArrayList;
import java.util.List;

public class ConcatHashLiteralNode extends RubyNode {

@Children private final RubyNode[] children;
private final boolean[] mergeChildren;

public ConcatHashLiteralNode(RubyContext context, SourceSection sourceSection, RubyNode[] children) {
public ConcatHashLiteralNode(RubyContext context, SourceSection sourceSection, RubyNode[] children, boolean[] mergeChildren) {
super(context, sourceSection);
assert children.length == mergeChildren.length;
this.children = children;
this.mergeChildren = mergeChildren;
}

@Override
Expand All @@ -54,6 +59,13 @@ protected DynamicObject[] executeChildren(VirtualFrame frame) {
for (int i = 0; i < children.length; i++) {
try {
DynamicObject hash = children[i].executeDynamicObject(frame);
if (mergeChildren[i]) {
for (KeyValue keyValue : HashOperations.iterableKeyValues(hash)) {
if (!RubyGuards.isRubySymbol(keyValue.getKey())) {
throw new RaiseException(coreExceptions().typeErrorWrongArgumentType(keyValue.getKey(), "Symbol", this));
}
}
}
values[i] = hash;
} catch (UnexpectedResultException e) {
throw new UnsupportedOperationException(children[i].getClass() + " " + e.getResult().getClass());
Expand Down
Expand Up @@ -1826,14 +1826,17 @@ public RubyNode visitHashNode(HashParseNode node) {
final SourceSection fullSourceSection = sourceSection.toSourceSection(source);

final List<RubyNode> hashConcats = new ArrayList<>();
final List<Boolean> hashConcatsIsMerge = new ArrayList<>();

final List<RubyNode> keyValues = new ArrayList<>();

for (KeyValuePair<ParseNode, ParseNode> pair: node.getPairs()) {
if (pair.getKey() == null) {
final RubyNode hashLiteralSoFar = HashLiteralNode.create(context, fullSourceSection, keyValues.toArray(new RubyNode[keyValues.size()]));
hashConcats.add(hashLiteralSoFar);
hashConcatsIsMerge.add(false);
hashConcats.add(HashCastNodeGen.create(context, fullSourceSection, pair.getValue().accept(this)));
hashConcatsIsMerge.add(true);
keyValues.clear();
} else {
keyValues.add(pair.getKey().accept(this));
Expand All @@ -1848,13 +1851,18 @@ public RubyNode visitHashNode(HashParseNode node) {

final RubyNode hashLiteralSoFar = HashLiteralNode.create(context, fullSourceSection, keyValues.toArray(new RubyNode[keyValues.size()]));
hashConcats.add(hashLiteralSoFar);
hashConcatsIsMerge.add(false);

if (hashConcats.size() == 1) {
final RubyNode ret = hashConcats.get(0);
return addNewlineIfNeeded(node, ret);
}

final RubyNode ret = new ConcatHashLiteralNode(context, fullSourceSection, hashConcats.toArray(new RubyNode[hashConcats.size()]));
boolean[] hashConcatsIsMergeArray = new boolean[hashConcatsIsMerge.size()];
for (int i = 0; i < hashConcatsIsMerge.size(); i++) {
hashConcatsIsMergeArray[i] = hashConcatsIsMerge.get(i);
}
final RubyNode ret = new ConcatHashLiteralNode(context, fullSourceSection, hashConcats.toArray(new RubyNode[hashConcats.size()]), hashConcatsIsMergeArray);
return addNewlineIfNeeded(node, ret);
}

Expand Down

0 comments on commit 6bf398b

Please sign in to comment.