Mercurial > hg > graal-compiler
annotate graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/KernelNodes.java @ 13659:62bfc12dc9e1
Ruby: more tidy up.
author | Chris Seaton <chris.seaton@oracle.com> |
---|---|
date | Wed, 15 Jan 2014 19:54:48 +0000 |
parents | 497fada09efb |
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.io.*; | |
13 import java.math.*; | |
14 import java.util.*; | |
15 | |
16 import com.oracle.truffle.api.CompilerDirectives.SlowPath; | |
17 import com.oracle.truffle.api.*; | |
18 import com.oracle.truffle.api.dsl.*; | |
19 import com.oracle.truffle.api.frame.*; | |
20 import com.oracle.truffle.api.nodes.*; | |
21 import com.oracle.truffle.ruby.nodes.*; | |
22 import com.oracle.truffle.ruby.nodes.call.*; | |
23 import com.oracle.truffle.ruby.nodes.cast.*; | |
24 import com.oracle.truffle.ruby.nodes.control.*; | |
25 import com.oracle.truffle.ruby.nodes.literal.*; | |
26 import com.oracle.truffle.ruby.nodes.yield.*; | |
27 import com.oracle.truffle.ruby.runtime.*; | |
28 import com.oracle.truffle.ruby.runtime.control.*; | |
29 import com.oracle.truffle.ruby.runtime.core.*; | |
30 import com.oracle.truffle.ruby.runtime.core.array.*; | |
31 import com.oracle.truffle.ruby.runtime.objects.*; | |
32 import com.oracle.truffle.ruby.runtime.subsystems.*; | |
33 | |
34 @CoreClass(name = "Kernel") | |
35 public abstract class KernelNodes { | |
36 | |
37 @CoreMethod(names = "Array", isModuleMethod = true, needsSelf = false, isSplatted = true) | |
38 public abstract static class ArrayNode extends CoreMethodNode { | |
39 | |
40 public ArrayNode(RubyContext context, SourceSection sourceSection) { | |
41 super(context, sourceSection); | |
42 } | |
43 | |
44 public ArrayNode(ArrayNode prev) { | |
45 super(prev); | |
46 } | |
47 | |
48 @Specialization | |
49 public RubyArray array(Object[] args) { | |
50 if (args.length == 1 && args[0] instanceof RubyArray) { | |
51 return (RubyArray) args[0]; | |
52 } else { | |
53 return RubyArray.specializedFromObjects(getContext().getCoreLibrary().getArrayClass(), args); | |
54 } | |
55 } | |
56 | |
57 } | |
58 | |
59 @CoreMethod(names = "at_exit", isModuleMethod = true, needsSelf = false, needsBlock = true, maxArgs = 0) | |
60 public abstract static class AtExitNode extends CoreMethodNode { | |
61 | |
62 public AtExitNode(RubyContext context, SourceSection sourceSection) { | |
63 super(context, sourceSection); | |
64 } | |
65 | |
66 public AtExitNode(AtExitNode prev) { | |
67 super(prev); | |
68 } | |
69 | |
70 @Specialization | |
71 public Object atExit(RubyProc block) { | |
72 getContext().getAtExitManager().add(block); | |
73 return NilPlaceholder.INSTANCE; | |
74 } | |
75 } | |
76 | |
77 @CoreMethod(names = "binding", isModuleMethod = true, needsSelf = true, maxArgs = 0) | |
78 public abstract static class BindingNode extends CoreMethodNode { | |
79 | |
80 public BindingNode(RubyContext context, SourceSection sourceSection) { | |
81 super(context, sourceSection); | |
82 } | |
83 | |
84 public BindingNode(BindingNode prev) { | |
85 super(prev); | |
86 } | |
87 | |
88 @Specialization | |
89 public Object binding(VirtualFrame frame, Object self) { | |
90 return new RubyBinding(getContext().getCoreLibrary().getBindingClass(), self, frame.getCaller().unpack().materialize()); | |
91 } | |
92 } | |
93 | |
94 @CoreMethod(names = "block_given?", isModuleMethod = true, needsSelf = false, maxArgs = 0) | |
95 public abstract static class BlockGivenNode extends CoreMethodNode { | |
96 | |
97 public BlockGivenNode(RubyContext context, SourceSection sourceSection) { | |
98 super(context, sourceSection); | |
99 } | |
100 | |
101 public BlockGivenNode(BlockGivenNode prev) { | |
102 super(prev); | |
103 } | |
104 | |
105 @Specialization | |
106 public boolean blockGiven(VirtualFrame frame) { | |
107 return frame.getCaller().unpack().getArguments(RubyArguments.class).getBlock() != null; | |
108 } | |
109 } | |
110 | |
111 // TODO(CS): should hide this in a feature | |
112 | |
113 @CoreMethod(names = "callcc", isModuleMethod = true, needsSelf = false, needsBlock = true, maxArgs = 0) | |
114 public abstract static class CallccNode extends CoreMethodNode { | |
115 | |
116 public CallccNode(RubyContext context, SourceSection sourceSection) { | |
117 super(context, sourceSection); | |
118 } | |
119 | |
120 public CallccNode(CallccNode prev) { | |
121 super(prev); | |
122 } | |
123 | |
124 @Specialization | |
125 public Object callcc(RubyProc block) { | |
126 final RubyContext context = getContext(); | |
127 | |
128 if (block == null) { | |
129 // TODO(CS): should really have acceptsBlock and needsBlock to do this automatically | |
130 throw new RaiseException(context.getCoreLibrary().localJumpError("no block given")); | |
131 } | |
132 | |
133 final RubyContinuation continuation = new RubyContinuation(context.getCoreLibrary().getContinuationClass()); | |
134 return continuation.enter(block); | |
135 } | |
136 } | |
137 | |
138 @CoreMethod(names = "catch", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 1, maxArgs = 1) | |
139 public abstract static class CatchNode extends YieldingCoreMethodNode { | |
140 | |
141 public CatchNode(RubyContext context, SourceSection sourceSection) { | |
142 super(context, sourceSection); | |
143 } | |
144 | |
145 public CatchNode(CatchNode prev) { | |
146 super(prev); | |
147 } | |
148 | |
149 @Specialization | |
150 public Object doCatch(VirtualFrame frame, Object tag, RubyProc block) { | |
151 try { | |
152 return yield(frame, block); | |
153 } catch (ThrowException e) { | |
154 if (e.getTag().equals(tag)) { | |
155 // TODO(cs): unset rather than set to Nil? | |
156 getContext().getCoreLibrary().getGlobalVariablesObject().setInstanceVariable("$!", NilPlaceholder.INSTANCE); | |
157 return e.getValue(); | |
158 } else { | |
159 throw e; | |
160 } | |
161 } | |
162 } | |
163 } | |
164 | |
165 @CoreMethod(names = "eval", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 2) | |
166 public abstract static class EvalNode extends CoreMethodNode { | |
167 | |
168 public EvalNode(RubyContext context, SourceSection sourceSection) { | |
169 super(context, sourceSection); | |
170 } | |
171 | |
172 public EvalNode(EvalNode prev) { | |
173 super(prev); | |
174 } | |
175 | |
176 @Specialization | |
177 public Object eval(RubyString source, @SuppressWarnings("unused") UndefinedPlaceholder binding) { | |
178 return getContext().eval(source.toString()); | |
179 } | |
180 | |
181 @Specialization | |
182 public Object eval(RubyString source, RubyBinding binding) { | |
183 return getContext().eval(source.toString(), binding); | |
184 } | |
185 | |
186 } | |
187 | |
188 @CoreMethod(names = "exec", isModuleMethod = true, needsSelf = false, minArgs = 1, isSplatted = true) | |
189 public abstract static class ExecNode extends CoreMethodNode { | |
190 | |
191 public ExecNode(RubyContext context, SourceSection sourceSection) { | |
192 super(context, sourceSection); | |
193 } | |
194 | |
195 public ExecNode(ExecNode prev) { | |
196 super(prev); | |
197 } | |
198 | |
199 @Specialization | |
200 public Object require(Object[] args) { | |
201 final String[] commandLine = new String[args.length]; | |
202 | |
203 for (int n = 0; n < args.length; n++) { | |
204 commandLine[n] = args[n].toString(); | |
205 } | |
206 | |
207 exec(getContext(), commandLine); | |
208 | |
209 return null; | |
210 } | |
211 | |
212 @SlowPath | |
213 private static void exec(RubyContext context, String[] commandLine) { | |
214 context.implementationMessage("starting child process to simulate exec: "); | |
215 | |
216 for (int n = 0; n < commandLine.length; n++) { | |
217 if (n > 0) { | |
218 System.err.print(" "); | |
219 } | |
220 | |
221 System.err.print(commandLine[n]); | |
222 } | |
223 | |
224 final ProcessBuilder builder = new ProcessBuilder(commandLine); | |
225 builder.inheritIO(); | |
226 | |
227 final RubyHash env = (RubyHash) context.getCoreLibrary().getObjectClass().lookupConstant("ENV"); | |
228 | |
229 for (Map.Entry<Object, Object> entry : env.getMap().entrySet()) { | |
230 builder.environment().put(entry.getKey().toString(), entry.getValue().toString()); | |
231 } | |
232 | |
233 Process process; | |
234 | |
235 try { | |
236 process = builder.start(); | |
237 } catch (IOException e) { | |
238 // TODO(cs): proper Ruby exception | |
239 throw new RuntimeException(e); | |
240 } | |
241 | |
242 int exitCode; | |
243 | |
244 while (true) { | |
245 try { | |
246 exitCode = process.waitFor(); | |
247 break; | |
248 } catch (InterruptedException e) { | |
249 continue; | |
250 } | |
251 } | |
252 | |
253 context.implementationMessage("child process simulating exec finished"); | |
254 | |
255 System.exit(exitCode); | |
256 } | |
257 | |
258 } | |
259 | |
260 @CoreMethod(names = "exit", isModuleMethod = true, needsSelf = false, minArgs = 0, maxArgs = 1) | |
261 public abstract static class ExitNode extends CoreMethodNode { | |
262 | |
263 public ExitNode(RubyContext context, SourceSection sourceSection) { | |
264 super(context, sourceSection); | |
265 } | |
266 | |
267 public ExitNode(ExitNode prev) { | |
268 super(prev); | |
269 } | |
270 | |
271 @Specialization | |
272 public Object exit(@SuppressWarnings("unused") UndefinedPlaceholder exitCode) { | |
273 getContext().shutdown(); | |
274 System.exit(0); | |
275 return null; | |
276 } | |
277 | |
278 @Specialization | |
279 public Object exit(int exitCode) { | |
280 getContext().shutdown(); | |
281 System.exit(exitCode); | |
282 return null; | |
283 } | |
284 | |
285 } | |
286 | |
287 @CoreMethod(names = "gets", isModuleMethod = true, needsSelf = false, maxArgs = 0) | |
288 public abstract static class GetsNode extends CoreMethodNode { | |
289 | |
290 public GetsNode(RubyContext context, SourceSection sourceSection) { | |
291 super(context, sourceSection); | |
292 } | |
293 | |
294 public GetsNode(GetsNode prev) { | |
295 super(prev); | |
296 } | |
297 | |
298 @Specialization | |
299 public RubyString gets(VirtualFrame frame) { | |
300 final RubyContext context = getContext(); | |
301 | |
302 final ThreadManager threadManager = context.getThreadManager(); | |
303 | |
304 RubyString line; | |
305 | |
306 try { | |
307 final RubyThread runningThread = threadManager.leaveGlobalLock(); | |
308 | |
309 try { | |
310 line = context.makeString(context.getConfiguration().getInputReader().readLine("")); | |
311 } finally { | |
312 threadManager.enterGlobalLock(runningThread); | |
313 } | |
314 } catch (IOException e) { | |
315 throw new RuntimeException(e); | |
316 } | |
317 | |
318 // Set the local variable $_ in the caller | |
319 | |
320 final Frame unpacked = frame.getCaller().unpack(); | |
321 final FrameSlot slot = unpacked.getFrameDescriptor().findFrameSlot("$_"); | |
322 | |
323 if (slot != null) { | |
324 unpacked.setObject(slot, line); | |
325 } | |
326 | |
327 return line; | |
328 } | |
329 } | |
330 | |
331 @CoreMethod(names = "Integer", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) | |
332 public abstract static class IntegerNode extends CoreMethodNode { | |
333 | |
334 @Child protected DispatchHeadNode toInt; | |
335 | |
336 public IntegerNode(RubyContext context, SourceSection sourceSection) { | |
337 super(context, sourceSection); | |
338 toInt = adoptChild(new DispatchHeadNode(context, getSourceSection(), "to_int", false)); | |
339 } | |
340 | |
341 public IntegerNode(IntegerNode prev) { | |
342 super(prev); | |
343 toInt = adoptChild(prev.toInt); | |
344 } | |
345 | |
346 @Specialization | |
347 public int integer(int value) { | |
348 return value; | |
349 } | |
350 | |
351 @Specialization | |
352 public BigInteger integer(BigInteger value) { | |
353 return value; | |
354 } | |
355 | |
356 @Specialization | |
357 public int integer(double value) { | |
358 return (int) value; | |
359 } | |
360 | |
361 @Specialization | |
362 public Object integer(RubyString value) { | |
363 return value.toInteger(); | |
364 } | |
365 | |
366 @Specialization | |
367 public Object integer(VirtualFrame frame, Object value) { | |
368 return toInt.dispatch(frame, value, null); | |
369 } | |
370 | |
371 } | |
372 | |
373 @CoreMethod(names = "lambda", isModuleMethod = true, needsBlock = true, maxArgs = 0) | |
374 public abstract static class LambdaNode extends CoreMethodNode { | |
375 | |
376 public LambdaNode(RubyContext context, SourceSection sourceSection) { | |
377 super(context, sourceSection); | |
378 } | |
379 | |
380 public LambdaNode(LambdaNode prev) { | |
381 super(prev); | |
382 } | |
383 | |
384 @Specialization | |
385 public RubyProc proc(Object self, RubyProc block) { | |
386 return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA, self, block, block.getMethod()); | |
387 | |
388 } | |
389 } | |
390 | |
391 @CoreMethod(names = "load", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) | |
392 public abstract static class LoadNode extends CoreMethodNode { | |
393 | |
394 public LoadNode(RubyContext context, SourceSection sourceSection) { | |
395 super(context, sourceSection); | |
396 } | |
397 | |
398 public LoadNode(LoadNode prev) { | |
399 super(prev); | |
400 } | |
401 | |
402 @Specialization | |
403 public boolean load(RubyString file) { | |
404 getContext().loadFile(file.toString()); | |
405 return true; | |
406 } | |
407 } | |
408 | |
409 @CoreMethod(names = "loop", isModuleMethod = true, needsSelf = false, maxArgs = 0) | |
410 public abstract static class LoopNode extends CoreMethodNode { | |
411 | |
412 @Child protected WhileNode whileNode; | |
413 | |
414 public LoopNode(RubyContext context, SourceSection sourceSection) { | |
415 super(context, sourceSection); | |
416 whileNode = adoptChild(new WhileNode(context, sourceSection, BooleanCastNodeFactory.create(context, sourceSection, new BooleanLiteralNode(context, sourceSection, true)), new YieldNode( | |
417 context, getSourceSection(), new RubyNode[]{}))); | |
418 } | |
419 | |
420 public LoopNode(LoopNode prev) { | |
421 super(prev); | |
422 whileNode = adoptChild(prev.whileNode); | |
423 } | |
424 | |
425 @Specialization | |
426 public Object loop(VirtualFrame frame) { | |
427 return whileNode.execute(frame); | |
428 } | |
429 } | |
430 | |
431 @CoreMethod(names = "print", isModuleMethod = true, needsSelf = false, isSplatted = true) | |
432 public abstract static class PrintNode extends CoreMethodNode { | |
433 | |
434 public PrintNode(RubyContext context, SourceSection sourceSection) { | |
435 super(context, sourceSection); | |
436 } | |
437 | |
438 public PrintNode(PrintNode prev) { | |
439 super(prev); | |
440 } | |
441 | |
442 @Specialization | |
443 public NilPlaceholder print(Object[] args) { | |
444 final RubyContext context = getContext(); | |
445 final ThreadManager threadManager = context.getThreadManager(); | |
446 | |
447 final RubyThread runningThread = threadManager.leaveGlobalLock(); | |
448 | |
449 try { | |
450 for (Object arg : args) { | |
451 /* | |
452 * TODO(cs): If it's a RubyString and made up of bytes, just write the bytes out | |
453 * - using toString will mess up the encoding. We need to stop using toString | |
454 * everywhere, and write our own bytes, possibly using JRuby's library for this. | |
455 */ | |
456 | |
457 if (arg instanceof RubyString && !((RubyString) arg).isFromJavaString()) { | |
458 try { | |
459 context.getConfiguration().getStandardOut().write(((RubyString) arg).getBytes()); | |
460 } catch (IOException e) { | |
461 throw new RuntimeException(e); | |
462 } | |
463 } else { | |
464 context.getConfiguration().getStandardOut().print(arg); | |
465 } | |
466 } | |
467 } finally { | |
468 threadManager.enterGlobalLock(runningThread); | |
469 } | |
470 | |
471 return NilPlaceholder.INSTANCE; | |
472 } | |
473 } | |
474 | |
475 @CoreMethod(names = "printf", isModuleMethod = true, needsSelf = false, isSplatted = true) | |
476 public abstract static class PrintfNode extends CoreMethodNode { | |
477 | |
478 public PrintfNode(RubyContext context, SourceSection sourceSection) { | |
479 super(context, sourceSection); | |
480 } | |
481 | |
482 public PrintfNode(PrintfNode prev) { | |
483 super(prev); | |
484 } | |
485 | |
486 @Specialization | |
487 public NilPlaceholder printf(Object[] args) { | |
488 final RubyContext context = getContext(); | |
489 final ThreadManager threadManager = context.getThreadManager(); | |
490 | |
491 if (args.length > 0) { | |
492 final String format = ((RubyString) args[0]).toString(); | |
493 final List<Object> values = Arrays.asList(args).subList(1, args.length); | |
494 | |
495 final RubyThread runningThread = threadManager.leaveGlobalLock(); | |
496 | |
497 try { | |
498 StringFormatter.format(context.getConfiguration().getStandardOut(), format, values); | |
499 } finally { | |
500 threadManager.enterGlobalLock(runningThread); | |
501 } | |
502 } | |
503 | |
504 return NilPlaceholder.INSTANCE; | |
505 } | |
506 } | |
507 | |
508 /* | |
509 * Kernel#pretty_inspect is normally part of stdlib, in pp.rb, but we aren't able to execute | |
510 * that file yet. Instead we implement a very simple version here, which is the solution | |
511 * suggested by RubySpec. | |
512 */ | |
513 | |
514 @CoreMethod(names = "pretty_inspect", maxArgs = 0) | |
515 public abstract static class PrettyInspectNode extends CoreMethodNode { | |
516 | |
517 @Child protected DispatchHeadNode toS; | |
518 | |
519 public PrettyInspectNode(RubyContext context, SourceSection sourceSection) { | |
520 super(context, sourceSection); | |
521 toS = adoptChild(new DispatchHeadNode(context, getSourceSection(), "to_s", false)); | |
522 } | |
523 | |
524 public PrettyInspectNode(PrettyInspectNode prev) { | |
525 super(prev); | |
526 toS = adoptChild(prev.toS); | |
527 } | |
528 | |
529 @Specialization | |
530 public Object prettyInspect(VirtualFrame frame, Object self) { | |
531 return toS.dispatch(frame, self, null); | |
532 | |
533 } | |
534 } | |
535 | |
13645
497fada09efb
Ruby: remove versioning.
Chris Seaton <chris.seaton@oracle.com>
parents:
13514
diff
changeset
|
536 @CoreMethod(names = "proc", isModuleMethod = true, needsBlock = true, maxArgs = 0) |
13514 | 537 public abstract static class ProcNode extends CoreMethodNode { |
538 | |
539 public ProcNode(RubyContext context, SourceSection sourceSection) { | |
540 super(context, sourceSection); | |
541 } | |
542 | |
543 public ProcNode(ProcNode prev) { | |
544 super(prev); | |
545 } | |
546 | |
547 @Specialization | |
548 public RubyProc proc(Object self, RubyProc block) { | |
549 return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.PROC, self, block, block.getMethod()); | |
550 | |
551 } | |
552 } | |
553 | |
554 @CoreMethod(names = "puts", isModuleMethod = true, needsSelf = false, isSplatted = true) | |
555 public abstract static class PutsNode extends CoreMethodNode { | |
556 | |
557 public PutsNode(RubyContext context, SourceSection sourceSection) { | |
558 super(context, sourceSection); | |
559 } | |
560 | |
561 public PutsNode(PutsNode prev) { | |
562 super(prev); | |
563 } | |
564 | |
565 @ExplodeLoop | |
566 @Specialization | |
567 public NilPlaceholder puts(Object[] args) { | |
568 final RubyContext context = getContext(); | |
569 final ThreadManager threadManager = context.getThreadManager(); | |
570 final PrintStream standardOut = context.getConfiguration().getStandardOut(); | |
571 | |
572 final RubyThread runningThread = threadManager.leaveGlobalLock(); | |
573 | |
574 try { | |
575 if (args.length == 0) { | |
576 standardOut.println(); | |
577 } else { | |
578 for (int n = 0; n < args.length; n++) { | |
579 puts(context, standardOut, args[n]); | |
580 } | |
581 } | |
582 } finally { | |
583 threadManager.enterGlobalLock(runningThread); | |
584 } | |
585 | |
586 return NilPlaceholder.INSTANCE; | |
587 } | |
588 | |
589 @SlowPath | |
590 private void puts(RubyContext context, PrintStream standardOut, Object value) { | |
591 if (value instanceof RubyArray) { | |
592 final RubyArray array = (RubyArray) value; | |
593 | |
594 for (int n = 0; n < array.size(); n++) { | |
595 puts(context, standardOut, array.get(n)); | |
596 } | |
597 } else { | |
598 // TODO(CS): slow path send | |
599 standardOut.println(context.getCoreLibrary().box(value).send("to_s", null)); | |
600 } | |
601 } | |
602 | |
603 } | |
604 | |
605 @CoreMethod(names = "raise", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 2) | |
606 public abstract static class RaiseNode extends CoreMethodNode { | |
607 | |
608 @Child protected DispatchHeadNode initialize; | |
609 | |
610 public RaiseNode(RubyContext context, SourceSection sourceSection) { | |
611 super(context, sourceSection); | |
612 initialize = adoptChild(new DispatchHeadNode(context, getSourceSection(), "initialize", false)); | |
613 } | |
614 | |
615 public RaiseNode(RaiseNode prev) { | |
616 super(prev); | |
617 initialize = adoptChild(prev.initialize); | |
618 } | |
619 | |
620 @Specialization(order = 1) | |
621 public Object raise(VirtualFrame frame, RubyString message, @SuppressWarnings("unused") UndefinedPlaceholder undefined) { | |
622 return raise(frame, getContext().getCoreLibrary().getRuntimeErrorClass(), message); | |
623 } | |
624 | |
625 @Specialization(order = 2) | |
626 public Object raise(VirtualFrame frame, RubyClass exceptionClass, @SuppressWarnings("unused") UndefinedPlaceholder undefined) { | |
627 return raise(frame, exceptionClass, getContext().makeString("")); | |
628 } | |
629 | |
630 @Specialization(order = 3) | |
631 public Object raise(VirtualFrame frame, RubyClass exceptionClass, RubyString message) { | |
632 final RubyBasicObject exception = exceptionClass.newInstance(); | |
633 initialize.dispatch(frame, exception, null, message); | |
634 throw new RaiseException(exception); | |
635 } | |
636 | |
637 } | |
638 | |
639 @CoreMethod(names = "require", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) | |
640 public abstract static class RequireNode extends CoreMethodNode { | |
641 | |
642 public RequireNode(RubyContext context, SourceSection sourceSection) { | |
643 super(context, sourceSection); | |
644 } | |
645 | |
646 public RequireNode(RequireNode prev) { | |
647 super(prev); | |
648 } | |
649 | |
650 @Specialization | |
651 public boolean require(RubyString feature) { | |
652 try { | |
653 getContext().getFeatureManager().require(feature.toString()); | |
654 } catch (IOException e) { | |
655 throw new RuntimeException(e); | |
656 } | |
657 | |
658 return true; | |
659 } | |
660 } | |
661 | |
662 @CoreMethod(names = "set_trace_func", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) | |
663 public abstract static class SetTraceFuncNode extends CoreMethodNode { | |
664 | |
665 public SetTraceFuncNode(RubyContext context, SourceSection sourceSection) { | |
666 super(context, sourceSection); | |
667 } | |
668 | |
669 public SetTraceFuncNode(SetTraceFuncNode prev) { | |
670 super(prev); | |
671 } | |
672 | |
673 @Specialization | |
674 public NilPlaceholder setTraceFunc(NilPlaceholder proc) { | |
675 getContext().getTraceManager().setTraceProc(null); | |
676 return proc; | |
677 } | |
678 | |
679 @Specialization | |
680 public RubyProc setTraceFunc(RubyProc proc) { | |
681 getContext().getTraceManager().setTraceProc(proc); | |
682 return proc; | |
683 } | |
684 | |
685 } | |
686 | |
687 @CoreMethod(names = "String", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) | |
688 public abstract static class StringNode extends CoreMethodNode { | |
689 | |
690 @Child protected DispatchHeadNode toS; | |
691 | |
692 public StringNode(RubyContext context, SourceSection sourceSection) { | |
693 super(context, sourceSection); | |
694 toS = adoptChild(new DispatchHeadNode(context, getSourceSection(), "to_s", false)); | |
695 } | |
696 | |
697 public StringNode(StringNode prev) { | |
698 super(prev); | |
699 toS = adoptChild(prev.toS); | |
700 } | |
701 | |
702 @Specialization | |
703 public RubyString string(int value) { | |
704 return getContext().makeString(Integer.toString(value)); | |
705 } | |
706 | |
707 @Specialization | |
708 public RubyString string(BigInteger value) { | |
709 return getContext().makeString(value.toString()); | |
710 } | |
711 | |
712 @Specialization | |
713 public RubyString string(double value) { | |
714 return getContext().makeString(Double.toString(value)); | |
715 } | |
716 | |
717 @Specialization | |
718 public RubyString string(RubyString value) { | |
719 return value; | |
720 } | |
721 | |
722 @Specialization | |
723 public Object string(VirtualFrame frame, Object value) { | |
724 return toS.dispatch(frame, value, null); | |
725 } | |
726 | |
727 } | |
728 | |
729 @CoreMethod(names = "sleep", isModuleMethod = true, needsSelf = false, maxArgs = 1) | |
730 public abstract static class SleepNode extends CoreMethodNode { | |
731 | |
732 public SleepNode(RubyContext context, SourceSection sourceSection) { | |
733 super(context, sourceSection); | |
734 } | |
735 | |
736 public SleepNode(SleepNode prev) { | |
737 super(prev); | |
738 } | |
739 | |
740 @Specialization | |
741 public double sleep(double duration) { | |
742 final RubyContext context = getContext(); | |
743 | |
744 final RubyThread runningThread = context.getThreadManager().leaveGlobalLock(); | |
745 | |
746 try { | |
747 final long start = System.nanoTime(); | |
748 | |
749 try { | |
750 Thread.sleep((long) (duration * 1000)); | |
751 } catch (InterruptedException e) { | |
752 // Ignore interruption | |
753 } | |
754 | |
755 final long end = System.nanoTime(); | |
756 | |
757 return (end - start) / 1e9; | |
758 } finally { | |
759 context.getThreadManager().enterGlobalLock(runningThread); | |
760 } | |
761 } | |
762 | |
763 @Specialization | |
764 public double sleep(int duration) { | |
765 return sleep((double) duration); | |
766 } | |
767 | |
768 } | |
769 | |
770 @CoreMethod(names = "throw", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 2) | |
771 public abstract static class ThrowNode extends CoreMethodNode { | |
772 | |
773 public ThrowNode(RubyContext context, SourceSection sourceSection) { | |
774 super(context, sourceSection); | |
775 } | |
776 | |
777 public ThrowNode(ThrowNode prev) { | |
778 super(prev); | |
779 } | |
780 | |
781 @Specialization | |
782 public Object doThrow(Object tag, UndefinedPlaceholder value) { | |
783 return doThrow(tag, (Object) value); | |
784 } | |
785 | |
786 @Specialization | |
787 public Object doThrow(Object tag, Object value) { | |
788 if (value instanceof UndefinedPlaceholder) { | |
789 throw new ThrowException(tag, NilPlaceholder.INSTANCE); | |
790 } else { | |
791 throw new ThrowException(tag, value); | |
792 } | |
793 } | |
794 | |
795 } | |
796 | |
797 } |