|
10 | 10 | package org.truffleruby.language.arguments;
|
11 | 11 |
|
12 | 12 | import org.truffleruby.core.hash.RubyHash;
|
| 13 | +import org.truffleruby.core.hash.library.HashStoreLibrary; |
| 14 | +import org.truffleruby.core.symbol.RubySymbol; |
13 | 15 | import org.truffleruby.language.RubyBaseNode;
|
14 | 16 |
|
15 | 17 | import com.oracle.truffle.api.frame.VirtualFrame;
|
16 | 18 | import com.oracle.truffle.api.profiles.ConditionProfile;
|
17 | 19 |
|
18 | 20 | public final class ReadUserKeywordsHashNode extends RubyBaseNode {
|
19 | 21 |
|
20 |
| - private final ConditionProfile keywordArgumentsProfile = ConditionProfile.create(); |
| 22 | + @Child protected HashStoreLibrary hashStoreLibrary; |
21 | 23 |
|
22 |
| - public ReadUserKeywordsHashNode() { |
23 |
| - } |
| 24 | + private final ConditionProfile keywordArgumentsProfile = ConditionProfile.create(); |
24 | 25 |
|
25 | 26 | public RubyHash execute(VirtualFrame frame) {
|
26 | 27 | final ArgumentsDescriptor descriptor = RubyArguments.getDescriptor(frame);
|
27 | 28 | if (keywordArgumentsProfile.profile(descriptor instanceof KeywordArgumentsDescriptor)) {
|
28 | 29 | final RubyHash keywords = (RubyHash) RubyArguments.getLastArgument(frame);
|
29 | 30 | assert !keywords.empty();
|
| 31 | + assert assertHashMatchesDescriptor(keywords, (KeywordArgumentsDescriptor) descriptor); |
30 | 32 | return keywords;
|
31 | 33 | } else {
|
32 | 34 | return null;
|
33 | 35 | }
|
34 | 36 | }
|
| 37 | + |
| 38 | + /** Verify that all keywords the descriptor claims should be in the hash, are in fact in the hash. **/ |
| 39 | + private boolean assertHashMatchesDescriptor(RubyHash hash, KeywordArgumentsDescriptor descriptor) { |
| 40 | + if (hashStoreLibrary == null) { |
| 41 | + hashStoreLibrary = insert(HashStoreLibrary.createDispatched()); |
| 42 | + } |
| 43 | + |
| 44 | + for (String keyword : descriptor.getKeywords()) { |
| 45 | + final RubySymbol symbol = getSymbol(keyword); |
| 46 | + final Object value = hashStoreLibrary.lookupOrDefault(hash.store, null, hash, symbol, (f, h, k) -> null); |
| 47 | + assert value != null : "descriptor claims " + keyword + |
| 48 | + " was a passed keyword argument but it's not in the hash"; |
| 49 | + } |
| 50 | + return true; |
| 51 | + } |
| 52 | + |
35 | 53 | }
|
0 commit comments