comparison graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyContinuation.java @ 13514:0fbee3eb71f0

Ruby: import project.
author Chris Seaton <chris.seaton@oracle.com>
date Mon, 06 Jan 2014 17:12:09 +0000
parents
children
comparison
equal deleted inserted replaced
13513:64a23ce736a0 13514:0fbee3eb71f0
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.runtime.core;
11
12 import com.oracle.truffle.ruby.runtime.*;
13 import com.oracle.truffle.ruby.runtime.control.*;
14 import com.oracle.truffle.ruby.runtime.core.array.*;
15
16 /**
17 * Represents the Ruby {@code Continuation} class. We only support continuations that just move up
18 * the stack and are one-shot.
19 */
20 public class RubyContinuation extends RubyObject {
21
22 /*
23 * A continuation is dead if we have already resumed it once. We will not be able to resume it
24 * again due to the current implementation being an exception thrown to go back up the stack.
25 */
26 private boolean dead = false;
27
28 public RubyContinuation(RubyClass rubyClass) {
29 super(rubyClass);
30 }
31
32 /**
33 * To enter a continuation means to remember the execution state at this point, reify that into
34 * an object, and then call the passed block. For our implementation, the continuation will be
35 * dead when this method resumes.
36 */
37 public Object enter(RubyProc block) {
38 try {
39 return block.call(null, this);
40 } catch (ContinuationReturnException e) {
41 // Thrown in call
42
43 // Check the exception is for this continuation
44
45 if (e.getContinuation() == this) {
46 return e.getValue();
47 } else {
48 throw e;
49 }
50 } finally {
51 dead = true;
52 }
53 }
54
55 /**
56 * To call a continuation means to go back to the execution state when it was created. For our
57 * implementation we can only do this once, and only if that means jumping back up the stack.
58 */
59 public void call(Object... args) {
60 if (dead) {
61 throw new UnsupportedOperationException("Only continuations that just move up the stack and are one-shot are supported");
62 }
63
64 Object returnValue;
65
66 if (args.length == 0) {
67 returnValue = NilPlaceholder.INSTANCE;
68 } else if (args.length == 1) {
69 returnValue = args[0];
70 } else {
71 returnValue = RubyArray.specializedFromObjects(getRubyClass().getContext().getCoreLibrary().getArrayClass(), args);
72 }
73
74 // Caught in enter
75
76 throw new ContinuationReturnException(this, returnValue);
77 }
78
79 }