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.runtime.core;
|
|
11
|
|
12 import com.oracle.truffle.api.*;
|
|
13 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
|
14 import com.oracle.truffle.api.frame.*;
|
|
15 import com.oracle.truffle.ruby.runtime.*;
|
|
16 import com.oracle.truffle.ruby.runtime.control.*;
|
|
17 import com.oracle.truffle.ruby.runtime.methods.*;
|
|
18 import com.oracle.truffle.ruby.runtime.objects.*;
|
|
19
|
|
20 /**
|
|
21 * Represents the Ruby {@code Proc} class.
|
|
22 */
|
|
23 public class RubyProc extends RubyObject {
|
|
24
|
|
25 /**
|
|
26 * The class from which we create the object that is {@code Proc}. A subclass of
|
|
27 * {@link RubyClass} so that we can override {@link #newInstance} and allocate a
|
|
28 * {@link RubyProc} rather than a normal {@link RubyBasicObject}.
|
|
29 */
|
|
30 public static class RubyProcClass extends RubyClass {
|
|
31
|
|
32 public RubyProcClass(RubyClass objectClass) {
|
|
33 super(null, objectClass, "Proc");
|
|
34 }
|
|
35
|
|
36 @Override
|
|
37 public RubyBasicObject newInstance() {
|
|
38 return new RubyProc(this);
|
|
39 }
|
|
40
|
|
41 }
|
|
42
|
|
43 public static enum Type {
|
|
44 PROC, LAMBDA
|
|
45 }
|
|
46
|
|
47 @CompilationFinal private Type type;
|
|
48 @CompilationFinal private Object self;
|
|
49 @CompilationFinal private RubyProc block;
|
|
50 @CompilationFinal private RubyMethod method;
|
|
51
|
|
52 public RubyProc(RubyClass procClass) {
|
|
53 super(procClass);
|
|
54 }
|
|
55
|
|
56 public RubyProc(RubyClass procClass, Type type, Object self, RubyProc block, RubyMethod method) {
|
|
57 super(procClass);
|
|
58 initialize(type, self, block, method);
|
|
59 }
|
|
60
|
|
61 public void initialize(Type setType, Object setSelf, RubyProc setBlock, RubyMethod setMethod) {
|
|
62 assert setSelf != null;
|
|
63 assert RubyContext.shouldObjectBeVisible(setSelf);
|
|
64 type = setType;
|
|
65 self = setSelf;
|
|
66 block = setBlock;
|
|
67 method = setMethod;
|
|
68 }
|
|
69
|
|
70 public Object getSelf() {
|
|
71 return self;
|
|
72 }
|
|
73
|
|
74 @CompilerDirectives.SlowPath
|
|
75 public Object call(PackedFrame caller, Object... args) {
|
|
76 return callWithModifiedSelf(caller, self, args);
|
|
77 }
|
|
78
|
|
79 public Object callWithModifiedSelf(PackedFrame caller, Object modifiedSelf, Object... args) {
|
|
80 assert modifiedSelf != null;
|
|
81
|
|
82 try {
|
|
83 return method.call(caller, modifiedSelf, block, args);
|
|
84 } catch (ReturnException e) {
|
|
85 switch (type) {
|
|
86 case PROC:
|
|
87 throw e;
|
|
88 case LAMBDA:
|
|
89 return e.getValue();
|
|
90 default:
|
|
91 throw new IllegalStateException();
|
|
92 }
|
|
93 }
|
|
94 }
|
|
95
|
|
96 public RubyMethod getMethod() {
|
|
97 return method;
|
|
98 }
|
|
99
|
|
100 public Type getType() {
|
|
101 return type;
|
|
102 }
|
|
103
|
|
104 public RubyProc getBlock() {
|
|
105 return block;
|
|
106 }
|
|
107
|
|
108 }
|