Mercurial > hg > graal-compiler
annotate graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java @ 13556:44288fe54352
Ruby: fix some ?break? semantics.
author | Chris Seaton <chris.seaton@oracle.com> |
---|---|
date | Wed, 08 Jan 2014 17:42:10 +0000 |
parents | f70c894ae874 |
children |
rev | line source |
---|---|
13514 | 1 /* |
2 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This | |
3 * code is released under a tri EPL/GPL/LGPL license. You can use it, | |
4 * redistribute it and/or modify it under the terms of the: | |
5 * | |
6 * Eclipse Public License version 1.0 | |
7 * GNU General Public License version 2 | |
8 * GNU Lesser General Public License version 2.1 | |
9 */ | |
10 package com.oracle.truffle.ruby.nodes.core; | |
11 | |
12 import java.util.*; | |
13 | |
14 import com.oracle.truffle.api.*; | |
15 import com.oracle.truffle.api.dsl.*; | |
16 import com.oracle.truffle.api.frame.*; | |
17 import com.oracle.truffle.ruby.runtime.*; | |
18 import com.oracle.truffle.ruby.runtime.core.*; | |
19 import com.oracle.truffle.ruby.runtime.core.array.*; | |
20 | |
21 @CoreClass(name = "Hash") | |
22 public abstract class HashNodes { | |
23 | |
24 @CoreMethod(names = "[]", isModuleMethod = true, needsSelf = false, isSplatted = true) | |
25 public abstract static class ConstructNode extends CoreMethodNode { | |
26 | |
27 public ConstructNode(RubyContext context, SourceSection sourceSection) { | |
28 super(context, sourceSection); | |
29 } | |
30 | |
31 public ConstructNode(ConstructNode prev) { | |
32 super(prev); | |
33 } | |
34 | |
35 @Specialization | |
36 public RubyHash construct(Object[] args) { | |
37 final RubyHash hash = new RubyHash(getContext().getCoreLibrary().getHashClass()); | |
38 | |
39 if (args.length == 1) { | |
40 final RubyArray array = (RubyArray) args[0]; | |
41 | |
42 for (int n = 0; n < array.size(); n++) { | |
43 final RubyArray keyValue = (RubyArray) array.get(n); | |
44 hash.put(keyValue.get(0), keyValue.get(1)); | |
45 } | |
46 } else { | |
13555
f70c894ae874
Ruby: fix minor issues.
Chris Seaton <chris.seaton@oracle.com>
parents:
13514
diff
changeset
|
47 if (args.length % 2 != 0) { |
f70c894ae874
Ruby: fix minor issues.
Chris Seaton <chris.seaton@oracle.com>
parents:
13514
diff
changeset
|
48 // TODO(CS): figure out what error to throw here |
f70c894ae874
Ruby: fix minor issues.
Chris Seaton <chris.seaton@oracle.com>
parents:
13514
diff
changeset
|
49 throw new UnsupportedOperationException(); |
f70c894ae874
Ruby: fix minor issues.
Chris Seaton <chris.seaton@oracle.com>
parents:
13514
diff
changeset
|
50 } |
13514 | 51 |
52 for (int n = 0; n < args.length; n += 2) { | |
53 hash.put(args[n], args[n + 1]); | |
54 } | |
55 } | |
56 | |
57 return hash; | |
58 } | |
59 | |
60 } | |
61 | |
62 @CoreMethod(names = "[]", minArgs = 1, maxArgs = 1) | |
63 public abstract static class GetIndexNode extends CoreMethodNode { | |
64 | |
65 public GetIndexNode(RubyContext context, SourceSection sourceSection) { | |
66 super(context, sourceSection); | |
67 } | |
68 | |
69 public GetIndexNode(GetIndexNode prev) { | |
70 super(prev); | |
71 } | |
72 | |
73 @Specialization | |
74 public Object construct(VirtualFrame frame, RubyHash hash, Object index) { | |
75 final Object value = hash.get(index); | |
76 | |
77 if (value == null) { | |
78 if (hash.defaultBlock == null) { | |
79 return NilPlaceholder.INSTANCE; | |
80 } else { | |
81 return hash.defaultBlock.call(frame.pack(), hash, index); | |
82 } | |
83 } else { | |
84 return value; | |
85 } | |
86 } | |
87 | |
88 } | |
89 | |
90 @CoreMethod(names = "[]=", minArgs = 2, maxArgs = 2) | |
91 public abstract static class SetIndexNode extends CoreMethodNode { | |
92 | |
93 public SetIndexNode(RubyContext context, SourceSection sourceSection) { | |
94 super(context, sourceSection); | |
95 } | |
96 | |
97 public SetIndexNode(SetIndexNode prev) { | |
98 super(prev); | |
99 } | |
100 | |
101 @Specialization | |
102 public Object construct(RubyHash hash, Object index, Object value) { | |
103 hash.put(index, value); | |
104 return value; | |
105 } | |
106 | |
107 } | |
108 | |
109 @CoreMethod(names = "delete", minArgs = 1, maxArgs = 1) | |
110 public abstract static class DeleteNode extends CoreMethodNode { | |
111 | |
112 public DeleteNode(RubyContext context, SourceSection sourceSection) { | |
113 super(context, sourceSection); | |
114 } | |
115 | |
116 public DeleteNode(DeleteNode prev) { | |
117 super(prev); | |
118 } | |
119 | |
120 @Specialization | |
121 public Object delete(RubyHash hash, Object index) { | |
122 hash.checkFrozen(); | |
123 | |
124 final Object value = hash.getMap().remove(index); | |
125 | |
126 if (value == null) { | |
127 return NilPlaceholder.INSTANCE; | |
128 } else { | |
129 return value; | |
130 } | |
131 } | |
132 | |
133 } | |
134 | |
135 @CoreMethod(names = "each", needsBlock = true, maxArgs = 0) | |
136 public abstract static class EachNode extends YieldingCoreMethodNode { | |
137 | |
138 public EachNode(RubyContext context, SourceSection sourceSection) { | |
139 super(context, sourceSection); | |
140 } | |
141 | |
142 public EachNode(EachNode prev) { | |
143 super(prev); | |
144 } | |
145 | |
146 @Specialization | |
147 public NilPlaceholder each(VirtualFrame frame, RubyHash hash, RubyProc block) { | |
148 for (Map.Entry<Object, Object> entry : hash.storage.entrySet()) { | |
149 yield(frame, block, entry.getKey(), entry.getValue()); | |
150 } | |
151 | |
152 return NilPlaceholder.INSTANCE; | |
153 } | |
154 | |
155 } | |
156 | |
157 @CoreMethod(names = "empty?", maxArgs = 0) | |
158 public abstract static class EmptyNode extends CoreMethodNode { | |
159 | |
160 public EmptyNode(RubyContext context, SourceSection sourceSection) { | |
161 super(context, sourceSection); | |
162 } | |
163 | |
164 public EmptyNode(EmptyNode prev) { | |
165 super(prev); | |
166 } | |
167 | |
168 @Specialization | |
169 public boolean empty(RubyHash hash) { | |
170 return hash.storage.isEmpty(); | |
171 } | |
172 | |
173 } | |
174 | |
175 @CoreMethod(names = "initialize", needsBlock = true, maxArgs = 0) | |
176 public abstract static class InitializeNode extends CoreMethodNode { | |
177 | |
178 public InitializeNode(RubyContext context, SourceSection sourceSection) { | |
179 super(context, sourceSection); | |
180 } | |
181 | |
182 public InitializeNode(InitializeNode prev) { | |
183 super(prev); | |
184 } | |
185 | |
186 @Specialization | |
187 public NilPlaceholder initialize(RubyHash hash, @SuppressWarnings("unused") UndefinedPlaceholder block) { | |
188 hash.initialize(null); | |
189 return NilPlaceholder.INSTANCE; | |
190 } | |
191 | |
192 @Specialization | |
193 public NilPlaceholder initialize(RubyHash hash, RubyProc block) { | |
194 hash.initialize(block); | |
195 return NilPlaceholder.INSTANCE; | |
196 } | |
197 | |
198 } | |
199 | |
200 @CoreMethod(names = {"map", "collect"}, needsBlock = true, maxArgs = 0) | |
201 public abstract static class MapNode extends YieldingCoreMethodNode { | |
202 | |
203 public MapNode(RubyContext context, SourceSection sourceSection) { | |
204 super(context, sourceSection); | |
205 } | |
206 | |
207 public MapNode(MapNode prev) { | |
208 super(prev); | |
209 } | |
210 | |
211 @Specialization | |
212 public RubyArray map(VirtualFrame frame, RubyHash hash, RubyProc block) { | |
213 final RubyArray result = new RubyArray(getContext().getCoreLibrary().getArrayClass()); | |
214 | |
215 for (Map.Entry<Object, Object> entry : hash.storage.entrySet()) { | |
216 result.push(yield(frame, block, entry.getKey(), entry.getValue())); | |
217 } | |
218 | |
219 return result; | |
220 } | |
221 | |
222 } | |
223 | |
224 @CoreMethod(names = "key?", minArgs = 1, maxArgs = 1) | |
225 public abstract static class KeyNode extends CoreMethodNode { | |
226 | |
227 public KeyNode(RubyContext context, SourceSection sourceSection) { | |
228 super(context, sourceSection); | |
229 } | |
230 | |
231 public KeyNode(KeyNode prev) { | |
232 super(prev); | |
233 } | |
234 | |
235 @Specialization | |
236 public boolean key(RubyHash hash, Object key) { | |
237 return hash.storage.containsKey(key); | |
238 } | |
239 | |
240 } | |
241 | |
242 @CoreMethod(names = "keys", maxArgs = 0) | |
243 public abstract static class KeysNode extends CoreMethodNode { | |
244 | |
245 public KeysNode(RubyContext context, SourceSection sourceSection) { | |
246 super(context, sourceSection); | |
247 } | |
248 | |
249 public KeysNode(KeysNode prev) { | |
250 super(prev); | |
251 } | |
252 | |
253 @Specialization | |
254 public RubyArray keys(RubyHash hash) { | |
255 final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass()); | |
256 | |
257 for (Object key : hash.storage.keySet()) { | |
258 array.push(key); | |
259 } | |
260 | |
261 return array; | |
262 } | |
263 | |
264 } | |
265 | |
266 @CoreMethod(names = "size", maxArgs = 0) | |
267 public abstract static class SizeNode extends CoreMethodNode { | |
268 | |
269 public SizeNode(RubyContext context, SourceSection sourceSection) { | |
270 super(context, sourceSection); | |
271 } | |
272 | |
273 public SizeNode(SizeNode prev) { | |
274 super(prev); | |
275 } | |
276 | |
277 @Specialization | |
278 public int size(RubyHash hash) { | |
279 return hash.storage.size(); | |
280 } | |
281 | |
282 } | |
283 | |
284 @CoreMethod(names = "values", maxArgs = 0) | |
285 public abstract static class ValuesNode extends CoreMethodNode { | |
286 | |
287 public ValuesNode(RubyContext context, SourceSection sourceSection) { | |
288 super(context, sourceSection); | |
289 } | |
290 | |
291 public ValuesNode(ValuesNode prev) { | |
292 super(prev); | |
293 } | |
294 | |
295 @Specialization | |
296 public RubyArray values(RubyHash hash) { | |
297 final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass()); | |
298 | |
299 for (Object value : hash.storage.values()) { | |
300 array.push(value); | |
301 } | |
302 | |
303 return array; | |
304 } | |
305 | |
306 } | |
307 | |
308 } |