Mercurial > hg > graal-compiler
annotate graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java @ 13563:fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
author | Michael Van De Vanter <michael.van.de.vanter@oracle.com> |
---|---|
date | Tue, 07 Jan 2014 18:09:42 -0800 |
parents | 0fbee3eb71f0 |
children | 497fada09efb |
rev | line source |
---|---|
13514 | 1 /* |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
2 * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This |
13514 | 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; | |
11 | |
12 import java.math.*; | |
13 import java.util.concurrent.atomic.*; | |
14 | |
15 import jnr.posix.*; | |
16 | |
17 import com.oracle.truffle.api.*; | |
18 import com.oracle.truffle.api.frame.*; | |
19 import com.oracle.truffle.api.nodes.*; | |
20 import com.oracle.truffle.api.source.*; | |
21 import com.oracle.truffle.ruby.runtime.configuration.*; | |
22 import com.oracle.truffle.ruby.runtime.control.*; | |
23 import com.oracle.truffle.ruby.runtime.core.*; | |
24 import com.oracle.truffle.ruby.runtime.debug.*; | |
25 import com.oracle.truffle.ruby.runtime.methods.*; | |
26 import com.oracle.truffle.ruby.runtime.objects.*; | |
27 import com.oracle.truffle.ruby.runtime.subsystems.*; | |
28 | |
29 /** | |
30 * The global state of a running Ruby system. | |
31 */ | |
32 public class RubyContext implements ExecutionContext { | |
33 | |
34 private final Configuration configuration; | |
35 private final RubyParser parser; | |
36 private final CoreLibrary coreLibrary; | |
37 private final FeatureManager featureManager; | |
38 private final ObjectSpaceManager objectSpaceManager; | |
39 private final TraceManager traceManager; | |
40 private final ThreadManager threadManager; | |
41 private final FiberManager fiberManager; | |
42 private final AtExitManager atExitManager; | |
43 private final RubyDebugManager debugManager; | |
44 private final SourceManager sourceManager; | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
45 private final ASTPrinter astPrinter; |
13514 | 46 |
47 private AtomicLong nextObjectID = new AtomicLong(0); | |
48 | |
49 private String currentDirectory = System.getProperty("user.dir"); | |
50 | |
51 private POSIX posix = POSIXFactory.getPOSIX(); | |
52 | |
53 public RubyContext(RubyParser parser) { | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
54 this(new Configuration(new ConfigurationBuilder()), parser, null); |
13514 | 55 } |
56 | |
57 public RubyContext(Configuration configuration, RubyParser parser) { | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
58 this(configuration, parser, null); |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
59 } |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
60 |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
61 public RubyContext(Configuration configuration, RubyParser parser, ASTPrinter astPrinter) { |
13514 | 62 assert configuration != null; |
63 | |
64 this.configuration = configuration; | |
65 this.parser = parser; | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
66 this.astPrinter = astPrinter; |
13514 | 67 |
68 objectSpaceManager = new ObjectSpaceManager(this); | |
69 traceManager = new TraceManager(this); | |
70 | |
71 // See note in CoreLibrary#initialize to see why we need to break this into two statements | |
72 coreLibrary = new CoreLibrary(this); | |
73 coreLibrary.initialize(); | |
74 | |
75 featureManager = new FeatureManager(this); | |
76 atExitManager = new AtExitManager(); | |
77 sourceManager = new SourceManager(); | |
78 | |
79 debugManager = configuration.getDebug() ? new RubyDebugManager(this) : null; | |
80 | |
81 // Must initialize threads before fibers | |
82 | |
83 threadManager = new ThreadManager(this); | |
84 | |
85 if (configuration.getRubyVersion().is19OrLater()) { | |
86 fiberManager = new FiberManager(this); | |
87 } else { | |
88 fiberManager = null; | |
89 } | |
90 } | |
91 | |
92 public String getLanguageShortName() { | |
93 return configuration.getRubyVersion().getShortName(); | |
94 } | |
95 | |
96 public RubyDebugManager getDebugManager() { | |
97 return debugManager; | |
98 } | |
99 | |
13563
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
100 public ASTPrinter getASTPrinter() { |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
101 return astPrinter; |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
102 } |
fb846424299f
Truffle/Ruby: extend Instrumentation framework with language-agnostic interfaces for access to AST printing utilities and a Ruby implementation
Michael Van De Vanter <michael.van.de.vanter@oracle.com>
parents:
13514
diff
changeset
|
103 |
13514 | 104 public void implementationMessage(String format, Object... arguments) { |
105 System.err.println("rubytruffle: " + String.format(format, arguments)); | |
106 } | |
107 | |
108 public void load(Source source) { | |
109 execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); | |
110 } | |
111 | |
112 public void loadFile(String fileName) { | |
113 final Source source = sourceManager.get(fileName); | |
114 final String code = source.getCode(); | |
115 if (code == null) { | |
116 throw new RuntimeException("Can't read file " + fileName); | |
117 } | |
118 execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); | |
119 } | |
120 | |
121 /** | |
122 * Receives runtime notification that execution has halted. | |
123 */ | |
124 public void haltedAt(Node node, MaterializedFrame frame) { | |
125 runShell(node, frame); | |
126 } | |
127 | |
128 public Object eval(String code) { | |
129 final Source source = sourceManager.get("(eval)", code); | |
130 return execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); | |
131 } | |
132 | |
133 public Object eval(String code, RubyModule module) { | |
134 final Source source = sourceManager.get("(eval)", code); | |
135 return execute(this, source, RubyParser.ParserContext.MODULE, module, null); | |
136 } | |
137 | |
138 public Object eval(String code, RubyBinding binding) { | |
139 final Source source = sourceManager.get("(eval)", code); | |
140 return execute(this, source, RubyParser.ParserContext.TOP_LEVEL, binding.getSelf(), binding.getFrame()); | |
141 } | |
142 | |
143 public void runShell(Node node, MaterializedFrame frame) { | |
144 MaterializedFrame existingLocals = frame; | |
145 | |
146 String prompt = "Ruby> "; | |
147 if (node != null) { | |
148 final SourceSection src = node.getSourceSection(); | |
149 if (src != null) { | |
150 prompt = (src.getSource().getName() + ":" + src.getStartLine() + "> "); | |
151 } | |
152 } | |
153 | |
154 while (true) { | |
155 try { | |
156 final String line = configuration.getInputReader().readLine(prompt); | |
157 | |
158 final ShellResult result = evalShell(line, existingLocals); | |
159 | |
160 configuration.getStandardOut().println("=> " + result.getResult()); | |
161 | |
162 existingLocals = result.getFrame(); | |
163 } catch (BreakShellException e) { | |
164 return; | |
165 } catch (Exception e) { | |
166 e.printStackTrace(); | |
167 } | |
168 } | |
169 } | |
170 | |
171 public ShellResult evalShell(String code, MaterializedFrame existingLocals) { | |
172 final Source source = sourceManager.get("(shell)", code); | |
173 return (ShellResult) execute(this, source, RubyParser.ParserContext.SHELL, coreLibrary.getMainObject(), existingLocals); | |
174 } | |
175 | |
176 public Object execute(RubyContext context, Source source, RubyParser.ParserContext parserContext, Object self, MaterializedFrame parentFrame) { | |
177 if (configuration.getPrintExecutedFiles()) { | |
178 implementationMessage("executing: %s", source.getName()); | |
179 } | |
180 | |
181 try { | |
182 final RubyParserResult parseResult = parser.parse(context, source, parserContext, parentFrame); | |
183 final RubyArguments arguments = new RubyArguments(parentFrame, self, null); | |
184 final CallTarget callTarget = Truffle.getRuntime().createCallTarget(parseResult.getRootNode(), parseResult.getFrameDescriptor()); | |
185 | |
186 return callTarget.call(null, arguments); | |
187 } catch (RaiseException e) { | |
188 throw e; | |
189 } catch (ThrowException e) { | |
190 if (context.getConfiguration().getRubyVersion().is18OrEarlier()) { | |
191 throw new RaiseException(context.getCoreLibrary().nameErrorUncaughtThrow(e.getTag())); | |
192 } else { | |
193 throw new RaiseException(context.getCoreLibrary().argumentErrorUncaughtThrow(e.getTag())); | |
194 } | |
195 } catch (BreakShellException | QuitException e) { | |
196 throw e; | |
197 } catch (Throwable e) { | |
198 throw new RaiseException(ExceptionTranslator.translateException(this, e)); | |
199 } | |
200 } | |
201 | |
202 public long getNextObjectID() { | |
203 // TODO(CS): We can theoretically run out of long values | |
204 | |
205 final long id = nextObjectID.getAndIncrement(); | |
206 | |
207 if (id < 0) { | |
208 nextObjectID.set(Long.MIN_VALUE); | |
209 throw new RuntimeException("Object IDs exhausted"); | |
210 } | |
211 | |
212 return id; | |
213 } | |
214 | |
215 public void shutdown() { | |
216 atExitManager.run(); | |
217 | |
218 threadManager.leaveGlobalLock(); | |
219 | |
220 objectSpaceManager.shutdown(); | |
221 | |
222 if (fiberManager != null) { | |
223 fiberManager.shutdown(); | |
224 } | |
225 } | |
226 | |
227 public RubyString makeString(String string) { | |
228 return new RubyString(coreLibrary.getStringClass(), string); | |
229 } | |
230 | |
231 public RubyString makeString(char string) { | |
232 return makeString(Character.toString(string)); | |
233 } | |
234 | |
235 public Configuration getConfiguration() { | |
236 return configuration; | |
237 } | |
238 | |
239 public CoreLibrary getCoreLibrary() { | |
240 return coreLibrary; | |
241 } | |
242 | |
243 public FeatureManager getFeatureManager() { | |
244 return featureManager; | |
245 } | |
246 | |
247 public ObjectSpaceManager getObjectSpaceManager() { | |
248 return objectSpaceManager; | |
249 } | |
250 | |
251 public TraceManager getTraceManager() { | |
252 return traceManager; | |
253 } | |
254 | |
255 public FiberManager getFiberManager() { | |
256 return fiberManager; | |
257 } | |
258 | |
259 public ThreadManager getThreadManager() { | |
260 return threadManager; | |
261 } | |
262 | |
263 public RubyParser getParser() { | |
264 return parser; | |
265 } | |
266 | |
267 /** | |
268 * Utility method to check if an object should be visible in a Ruby program. Used in assertions | |
269 * at method boundaries to check that only values we want to be visible to the programmer become | |
270 * so. | |
271 */ | |
272 public static boolean shouldObjectBeVisible(Object object) { | |
273 // TODO(cs): RubyMethod should never be visible | |
274 | |
275 return object instanceof UndefinedPlaceholder || // | |
276 object instanceof Boolean || // | |
277 object instanceof Integer || // | |
278 object instanceof BigInteger || // | |
279 object instanceof Double || // | |
280 object instanceof RubyBasicObject || // | |
281 object instanceof RubyMethod || // | |
282 object instanceof NilPlaceholder || // | |
283 object instanceof RubyMethod; | |
284 } | |
285 | |
286 public static boolean shouldObjectsBeVisible(Object... objects) { | |
287 for (Object object : objects) { | |
288 if (!shouldObjectBeVisible(object)) { | |
289 return false; | |
290 } | |
291 } | |
292 | |
293 return true; | |
294 } | |
295 | |
296 public void setCurrentDirectory(String currentDirectory) { | |
297 this.currentDirectory = currentDirectory; | |
298 } | |
299 | |
300 public String getCurrentDirectory() { | |
301 return currentDirectory; | |
302 } | |
303 | |
304 public POSIX getPOSIX() { | |
305 return posix; | |
306 } | |
307 | |
308 public AtExitManager getAtExitManager() { | |
309 return atExitManager; | |
310 } | |
311 | |
312 public SourceManager getSourceManager() { | |
313 return sourceManager; | |
314 } | |
315 | |
316 } |