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.math.*;
|
|
13 import java.util.*;
|
|
14
|
|
15 import com.oracle.truffle.api.*;
|
|
16 import com.oracle.truffle.api.dsl.*;
|
|
17 import com.oracle.truffle.api.frame.*;
|
|
18 import com.oracle.truffle.ruby.runtime.*;
|
|
19 import com.oracle.truffle.ruby.runtime.core.*;
|
|
20 import com.oracle.truffle.ruby.runtime.core.array.*;
|
|
21 import com.oracle.truffle.ruby.runtime.methods.*;
|
|
22 import com.oracle.truffle.ruby.runtime.objects.*;
|
|
23
|
|
24 @CoreClass(name = "Object")
|
|
25 public abstract class ObjectNodes {
|
|
26
|
|
27 @CoreMethod(names = "class", maxArgs = 0)
|
|
28 public abstract static class ClassNode extends CoreMethodNode {
|
|
29
|
|
30 public ClassNode(RubyContext context, SourceSection sourceSection) {
|
|
31 super(context, sourceSection);
|
|
32 }
|
|
33
|
|
34 public ClassNode(ClassNode prev) {
|
|
35 super(prev);
|
|
36 }
|
|
37
|
|
38 @Specialization
|
|
39 public RubyClass getClass(boolean value) {
|
|
40 if (value) {
|
|
41 return getContext().getCoreLibrary().getTrueClass();
|
|
42 } else {
|
|
43 return getContext().getCoreLibrary().getFalseClass();
|
|
44 }
|
|
45 }
|
|
46
|
|
47 @Specialization
|
|
48 public RubyClass getClass(@SuppressWarnings("unused") int value) {
|
|
49 return getContext().getCoreLibrary().getFixnumClass();
|
|
50 }
|
|
51
|
|
52 @Specialization
|
|
53 public RubyClass getClass(@SuppressWarnings("unused") BigInteger value) {
|
|
54 return getContext().getCoreLibrary().getBignumClass();
|
|
55 }
|
|
56
|
|
57 @Specialization
|
|
58 public RubyClass getClass(@SuppressWarnings("unused") double value) {
|
|
59 return getContext().getCoreLibrary().getFloatClass();
|
|
60 }
|
|
61
|
|
62 @Specialization
|
|
63 public RubyClass getClass(RubyBasicObject self) {
|
|
64 return self.getRubyClass();
|
|
65 }
|
|
66
|
|
67 }
|
|
68
|
|
69 @CoreMethod(names = "dup", maxArgs = 0)
|
|
70 public abstract static class DupNode extends CoreMethodNode {
|
|
71
|
|
72 public DupNode(RubyContext context, SourceSection sourceSection) {
|
|
73 super(context, sourceSection);
|
|
74 }
|
|
75
|
|
76 public DupNode(DupNode prev) {
|
|
77 super(prev);
|
|
78 }
|
|
79
|
|
80 @Specialization
|
|
81 public Object dup(RubyObject self) {
|
|
82 return self.dup();
|
|
83 }
|
|
84
|
|
85 }
|
|
86
|
|
87 @CoreMethod(names = "extend", isSplatted = true, minArgs = 1)
|
|
88 public abstract static class ExtendNode extends CoreMethodNode {
|
|
89
|
|
90 public ExtendNode(RubyContext context, SourceSection sourceSection) {
|
|
91 super(context, sourceSection);
|
|
92 }
|
|
93
|
|
94 public ExtendNode(ExtendNode prev) {
|
|
95 super(prev);
|
|
96 }
|
|
97
|
|
98 @Specialization
|
|
99 public RubyBasicObject extend(RubyBasicObject self, Object[] args) {
|
|
100 for (int n = 0; n < args.length; n++) {
|
|
101 self.extend((RubyModule) args[n]);
|
|
102 }
|
|
103
|
|
104 return self;
|
|
105 }
|
|
106
|
|
107 }
|
|
108
|
|
109 @CoreMethod(names = "freeze", maxArgs = 0)
|
|
110 public abstract static class FreezeNode extends CoreMethodNode {
|
|
111
|
|
112 public FreezeNode(RubyContext context, SourceSection sourceSection) {
|
|
113 super(context, sourceSection);
|
|
114 }
|
|
115
|
|
116 public FreezeNode(FreezeNode prev) {
|
|
117 super(prev);
|
|
118 }
|
|
119
|
|
120 @Specialization
|
|
121 public RubyObject freeze(RubyObject self) {
|
|
122 self.frozen = true;
|
|
123 return self;
|
|
124 }
|
|
125
|
|
126 }
|
|
127
|
|
128 @CoreMethod(names = "frozen?", maxArgs = 0)
|
|
129 public abstract static class FrozenNode extends CoreMethodNode {
|
|
130
|
|
131 public FrozenNode(RubyContext context, SourceSection sourceSection) {
|
|
132 super(context, sourceSection);
|
|
133 }
|
|
134
|
|
135 public FrozenNode(FrozenNode prev) {
|
|
136 super(prev);
|
|
137 }
|
|
138
|
|
139 @Specialization
|
|
140 public boolean isFrozen(RubyObject self) {
|
|
141 return self.frozen;
|
|
142 }
|
|
143
|
|
144 }
|
|
145
|
|
146 @CoreMethod(names = "inspect", maxArgs = 0)
|
|
147 public abstract static class InspectNode extends CoreMethodNode {
|
|
148
|
|
149 public InspectNode(RubyContext context, SourceSection sourceSection) {
|
|
150 super(context, sourceSection);
|
|
151 }
|
|
152
|
|
153 public InspectNode(InspectNode prev) {
|
|
154 super(prev);
|
|
155 }
|
|
156
|
|
157 @Specialization
|
|
158 public RubyString inspect(boolean value) {
|
|
159 return getContext().makeString(Boolean.toString(value));
|
|
160 }
|
|
161
|
|
162 @Specialization
|
|
163 public RubyString inspect(int value) {
|
|
164 return getContext().makeString(Integer.toString(value));
|
|
165 }
|
|
166
|
|
167 @Specialization
|
|
168 public RubyString inspect(BigInteger value) {
|
|
169 return getContext().makeString(value.toString());
|
|
170 }
|
|
171
|
|
172 @Specialization
|
|
173 public RubyString inspect(double value) {
|
|
174 return getContext().makeString(Double.toString(value));
|
|
175 }
|
|
176
|
|
177 @Specialization
|
|
178 public RubyString inspect(RubyObject self) {
|
|
179 return getContext().makeString(self.inspect());
|
|
180 }
|
|
181
|
|
182 }
|
|
183
|
|
184 @CoreMethod(names = "instance_eval", needsBlock = true, maxArgs = 0)
|
|
185 public abstract static class InstanceEvalNode extends CoreMethodNode {
|
|
186
|
|
187 public InstanceEvalNode(RubyContext context, SourceSection sourceSection) {
|
|
188 super(context, sourceSection);
|
|
189 }
|
|
190
|
|
191 public InstanceEvalNode(InstanceEvalNode prev) {
|
|
192 super(prev);
|
|
193 }
|
|
194
|
|
195 @Specialization
|
|
196 public Object instanceEval(VirtualFrame frame, RubyObject self, RubyProc block) {
|
|
197 return block.callWithModifiedSelf(frame.pack(), self);
|
|
198 }
|
|
199
|
|
200 }
|
|
201
|
|
202 @CoreMethod(names = "instance_variable_defined?", minArgs = 1, maxArgs = 1)
|
|
203 public abstract static class InstanceVariableDefinedNode extends CoreMethodNode {
|
|
204
|
|
205 public InstanceVariableDefinedNode(RubyContext context, SourceSection sourceSection) {
|
|
206 super(context, sourceSection);
|
|
207 }
|
|
208
|
|
209 public InstanceVariableDefinedNode(InstanceVariableDefinedNode prev) {
|
|
210 super(prev);
|
|
211 }
|
|
212
|
|
213 @Specialization
|
|
214 public boolean isInstanceVariableDefined(RubyBasicObject object, RubyString name) {
|
|
215 return object.isInstanceVariableDefined(RubyObject.checkInstanceVariableName(getContext(), name.toString()));
|
|
216 }
|
|
217
|
|
218 @Specialization
|
|
219 public boolean isInstanceVariableDefined(RubyBasicObject object, RubySymbol name) {
|
|
220 return object.isInstanceVariableDefined(RubyObject.checkInstanceVariableName(getContext(), name.toString()));
|
|
221 }
|
|
222
|
|
223 }
|
|
224
|
|
225 @CoreMethod(names = "instance_variable_get", minArgs = 1, maxArgs = 1)
|
|
226 public abstract static class InstanceVariableGetNode extends CoreMethodNode {
|
|
227
|
|
228 public InstanceVariableGetNode(RubyContext context, SourceSection sourceSection) {
|
|
229 super(context, sourceSection);
|
|
230 }
|
|
231
|
|
232 public InstanceVariableGetNode(InstanceVariableGetNode prev) {
|
|
233 super(prev);
|
|
234 }
|
|
235
|
|
236 @Specialization
|
|
237 public Object isInstanceVariableGet(RubyBasicObject object, RubyString name) {
|
|
238 return object.getInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString()));
|
|
239 }
|
|
240
|
|
241 @Specialization
|
|
242 public Object isInstanceVariableGet(RubyBasicObject object, RubySymbol name) {
|
|
243 return object.getInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString()));
|
|
244 }
|
|
245
|
|
246 }
|
|
247
|
|
248 @CoreMethod(names = "instance_variable_set", minArgs = 2, maxArgs = 2)
|
|
249 public abstract static class InstanceVariableSetNode extends CoreMethodNode {
|
|
250
|
|
251 public InstanceVariableSetNode(RubyContext context, SourceSection sourceSection) {
|
|
252 super(context, sourceSection);
|
|
253 }
|
|
254
|
|
255 public InstanceVariableSetNode(InstanceVariableSetNode prev) {
|
|
256 super(prev);
|
|
257 }
|
|
258
|
|
259 @Specialization
|
|
260 public Object isInstanceVariableSet(RubyBasicObject object, RubyString name, Object value) {
|
|
261 object.setInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString()), value);
|
|
262 return value;
|
|
263 }
|
|
264
|
|
265 @Specialization
|
|
266 public Object isInstanceVariableSet(RubyBasicObject object, RubySymbol name, Object value) {
|
|
267 object.setInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString()), value);
|
|
268 return value;
|
|
269 }
|
|
270
|
|
271 }
|
|
272
|
|
273 @CoreMethod(names = "instance_variables", maxArgs = 0)
|
|
274 public abstract static class InstanceVariablesNode extends CoreMethodNode {
|
|
275
|
|
276 public InstanceVariablesNode(RubyContext context, SourceSection sourceSection) {
|
|
277 super(context, sourceSection);
|
|
278 }
|
|
279
|
|
280 public InstanceVariablesNode(InstanceVariablesNode prev) {
|
|
281 super(prev);
|
|
282 }
|
|
283
|
|
284 @Specialization
|
|
285 public RubyArray instanceVariables(RubyObject self) {
|
|
286 final String[] instanceVariableNames = self.getInstanceVariableNames();
|
|
287
|
|
288 Arrays.sort(instanceVariableNames);
|
|
289
|
|
290 final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass());
|
|
291
|
|
292 for (String name : instanceVariableNames) {
|
|
293 array.push(new RubyString(getContext().getCoreLibrary().getStringClass(), name));
|
|
294 }
|
|
295
|
|
296 return array;
|
|
297 }
|
|
298
|
|
299 }
|
|
300
|
|
301 @CoreMethod(names = {"is_a?", "instance_of?", "kind_of?"}, minArgs = 1, maxArgs = 1)
|
|
302 public abstract static class IsANode extends CoreMethodNode {
|
|
303
|
|
304 public IsANode(RubyContext context, SourceSection sourceSection) {
|
|
305 super(context, sourceSection);
|
|
306 }
|
|
307
|
|
308 public IsANode(IsANode prev) {
|
|
309 super(prev);
|
|
310 }
|
|
311
|
|
312 @Specialization
|
|
313 public boolean isA(@SuppressWarnings("unused") RubyObject self, @SuppressWarnings("unused") NilPlaceholder nil) {
|
|
314 return false;
|
|
315 }
|
|
316
|
|
317 @Specialization
|
|
318 public boolean isA(RubyObject self, RubyClass rubyClass) {
|
|
319 return self.getRubyClass().assignableTo(rubyClass);
|
|
320 }
|
|
321
|
|
322 }
|
|
323
|
|
324 @CoreMethod(names = "methods", minArgs = 0, maxArgs = 1)
|
|
325 public abstract static class MethodsNode extends CoreMethodNode {
|
|
326
|
|
327 public MethodsNode(RubyContext context, SourceSection sourceSection) {
|
|
328 super(context, sourceSection);
|
|
329 }
|
|
330
|
|
331 public MethodsNode(MethodsNode prev) {
|
|
332 super(prev);
|
|
333 }
|
|
334
|
|
335 @Specialization
|
|
336 public RubyArray methods(RubyObject self, boolean includeInherited) {
|
|
337 if (!includeInherited) {
|
|
338 self.getRubyClass().getContext().implementationMessage("Object#methods always returns inherited methods at the moment");
|
|
339 }
|
|
340
|
|
341 return methods(self, UndefinedPlaceholder.INSTANCE);
|
|
342 }
|
|
343
|
|
344 @Specialization
|
|
345 public RubyArray methods(RubyObject self, @SuppressWarnings("unused") UndefinedPlaceholder includeInherited) {
|
|
346 final RubyArray array = new RubyArray(self.getRubyClass().getContext().getCoreLibrary().getArrayClass());
|
|
347
|
|
348 final Map<String, RubyMethod> methods = new HashMap<>();
|
|
349
|
|
350 self.getLookupNode().getMethods(methods);
|
|
351
|
|
352 for (RubyMethod method : methods.values()) {
|
|
353 if (method.getVisibility() == Visibility.PUBLIC || method.getVisibility() == Visibility.PROTECTED) {
|
|
354 array.push(new RubySymbol(self.getRubyClass().getContext().getCoreLibrary().getSymbolClass(), method.getName()));
|
|
355 }
|
|
356 }
|
|
357
|
|
358 return array;
|
|
359 }
|
|
360
|
|
361 }
|
|
362
|
|
363 @CoreMethod(names = "nil?", needsSelf = false, maxArgs = 0)
|
|
364 public abstract static class NilNode extends CoreMethodNode {
|
|
365
|
|
366 public NilNode(RubyContext context, SourceSection sourceSection) {
|
|
367 super(context, sourceSection);
|
|
368 }
|
|
369
|
|
370 public NilNode(NilNode prev) {
|
|
371 super(prev);
|
|
372 }
|
|
373
|
|
374 @Specialization
|
|
375 public boolean nil() {
|
|
376 return false;
|
|
377 }
|
|
378 }
|
|
379
|
|
380 @CoreMethod(names = "object_id", needsSelf = true, maxArgs = 0)
|
|
381 public abstract static class ObjectIDNode extends CoreMethodNode {
|
|
382
|
|
383 public ObjectIDNode(RubyContext context, SourceSection sourceSection) {
|
|
384 super(context, sourceSection);
|
|
385 }
|
|
386
|
|
387 public ObjectIDNode(ObjectIDNode prev) {
|
|
388 super(prev);
|
|
389 }
|
|
390
|
|
391 @Specialization
|
|
392 public Object objectID(RubyBasicObject object) {
|
|
393 return GeneralConversions.fixnumOrBignum(object.getObjectID());
|
|
394 }
|
|
395
|
|
396 }
|
|
397
|
|
398 @CoreMethod(names = "respond_to?", minArgs = 1, maxArgs = 2)
|
|
399 public abstract static class RespondToNode extends CoreMethodNode {
|
|
400
|
|
401 public RespondToNode(RubyContext context, SourceSection sourceSection) {
|
|
402 super(context, sourceSection);
|
|
403 }
|
|
404
|
|
405 public RespondToNode(RespondToNode prev) {
|
|
406 super(prev);
|
|
407 }
|
|
408
|
|
409 @Specialization(order = 1)
|
|
410 public boolean doesRespondTo(Object object, RubyString name, @SuppressWarnings("unused") UndefinedPlaceholder checkVisibility) {
|
|
411 return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), false);
|
|
412 }
|
|
413
|
|
414 @Specialization(order = 2)
|
|
415 public boolean doesRespondTo(Object object, RubyString name, boolean dontCheckVisibility) {
|
|
416 return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), dontCheckVisibility);
|
|
417 }
|
|
418
|
|
419 @Specialization(order = 3)
|
|
420 public boolean doesRespondTo(Object object, RubySymbol name, @SuppressWarnings("unused") UndefinedPlaceholder checkVisibility) {
|
|
421 return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), false);
|
|
422 }
|
|
423
|
|
424 @Specialization(order = 4)
|
|
425 public boolean doesRespondTo(Object object, RubySymbol name, boolean dontCheckVisibility) {
|
|
426 return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), dontCheckVisibility);
|
|
427 }
|
|
428
|
|
429 private static boolean doesRespondTo(RubyBasicObject object, String name, boolean dontCheckVisibility) {
|
|
430 final RubyMethod method = object.getLookupNode().lookupMethod(name);
|
|
431
|
|
432 if (method == null || method.isUndefined()) {
|
|
433 return false;
|
|
434 }
|
|
435
|
|
436 if (dontCheckVisibility) {
|
|
437 return true;
|
|
438 } else {
|
|
439 return method.getVisibility() == Visibility.PUBLIC;
|
|
440 }
|
|
441 }
|
|
442
|
|
443 }
|
|
444
|
|
445 @CoreMethod(names = "singleton_class", maxArgs = 0)
|
|
446 public abstract static class SingletonClassNode extends CoreMethodNode {
|
|
447
|
|
448 public SingletonClassNode(RubyContext context, SourceSection sourceSection) {
|
|
449 super(context, sourceSection);
|
|
450 }
|
|
451
|
|
452 public SingletonClassNode(SingletonClassNode prev) {
|
|
453 super(prev);
|
|
454 }
|
|
455
|
|
456 @Specialization
|
|
457 public RubyClass singletonClass(RubyBasicObject self) {
|
|
458 return self.getSingletonClass();
|
|
459 }
|
|
460
|
|
461 }
|
|
462
|
|
463 @CoreMethod(names = "singleton_methods", minArgs = 0, maxArgs = 1)
|
|
464 public abstract static class SingletonMethodsNode extends CoreMethodNode {
|
|
465
|
|
466 public SingletonMethodsNode(RubyContext context, SourceSection sourceSection) {
|
|
467 super(context, sourceSection);
|
|
468 }
|
|
469
|
|
470 public SingletonMethodsNode(SingletonMethodsNode prev) {
|
|
471 super(prev);
|
|
472 }
|
|
473
|
|
474 @Specialization
|
|
475 public RubyArray singletonMethods(RubyObject self, boolean includeInherited) {
|
|
476 if (!includeInherited) {
|
|
477 self.getRubyClass().getContext().implementationMessage("Object#singleton_methods always returns inherited methods at the moment");
|
|
478 }
|
|
479
|
|
480 return singletonMethods(self, UndefinedPlaceholder.INSTANCE);
|
|
481 }
|
|
482
|
|
483 @Specialization
|
|
484 public RubyArray singletonMethods(RubyObject self, @SuppressWarnings("unused") UndefinedPlaceholder includeInherited) {
|
|
485 final RubyArray array = new RubyArray(self.getRubyClass().getContext().getCoreLibrary().getArrayClass());
|
|
486
|
|
487 for (RubyMethod method : self.getSingletonClass().getDeclaredMethods()) {
|
|
488 array.push(new RubySymbol(self.getRubyClass().getContext().getCoreLibrary().getSymbolClass(), method.getName()));
|
|
489 }
|
|
490
|
|
491 return array;
|
|
492 }
|
|
493
|
|
494 }
|
|
495
|
|
496 @CoreMethod(names = "to_s", maxArgs = 0)
|
|
497 public abstract static class ToSNode extends CoreMethodNode {
|
|
498
|
|
499 public ToSNode(RubyContext context, SourceSection sourceSection) {
|
|
500 super(context, sourceSection);
|
|
501 }
|
|
502
|
|
503 public ToSNode(ToSNode prev) {
|
|
504 super(prev);
|
|
505 }
|
|
506
|
|
507 @Specialization
|
|
508 public RubyString toS(RubyObject self) {
|
|
509 return getContext().makeString(self.toString());
|
|
510 }
|
|
511
|
|
512 }
|
|
513
|
|
514 }
|