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.shell;
|
|
11
|
|
12 import java.io.*;
|
|
13
|
|
14 import jline.console.*;
|
|
15
|
|
16 import com.oracle.truffle.api.*;
|
|
17 import com.oracle.truffle.ruby.nodes.core.*;
|
|
18 import com.oracle.truffle.ruby.parser.*;
|
|
19 import com.oracle.truffle.ruby.runtime.*;
|
|
20 import com.oracle.truffle.ruby.runtime.configuration.*;
|
|
21 import com.oracle.truffle.ruby.runtime.core.array.*;
|
|
22
|
|
23 /**
|
|
24 * The entry point class for RubyTruffle. Implements the MRI command line interface.
|
|
25 */
|
|
26 public class Shell {
|
|
27
|
|
28 /**
|
|
29 * Entry point method for Ruby both in batch and interactive mode.
|
|
30 */
|
|
31 public static void main(String[] args) throws IOException {
|
|
32 // Parse the command line
|
|
33
|
|
34 final CommandLineOptions options = CommandLineParser.parse(args);
|
|
35
|
|
36 if (options == null) {
|
|
37 return;
|
|
38 }
|
|
39
|
|
40 // Setup JLine
|
|
41
|
|
42 ConsoleReader console = null;
|
|
43
|
|
44 if (options.useJLine()) {
|
|
45 System.setProperty("jline.shutdownhook", "true");
|
|
46 console = new ConsoleReader();
|
|
47 console.setExpandEvents(false);
|
|
48 }
|
|
49
|
|
50 // Override the home directory if RUBYHOME is set
|
|
51
|
|
52 final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(options.getConfiguration());
|
|
53
|
|
54 if (System.getenv("RUBYHOME") != null) {
|
|
55 configurationBuilder.setStandardLibrary(System.getenv("RUBYHOME") + "/" + ConfigurationBuilder.JRUBY_STDLIB_JAR);
|
|
56 }
|
|
57
|
|
58 // Use JLine for console input
|
|
59
|
|
60 final ConsoleReader finalConsole = console;
|
|
61
|
|
62 if (options.useJLine()) {
|
|
63 configurationBuilder.setInputReader(new InputReader() {
|
|
64
|
|
65 @Override
|
|
66 public String readLine(String prompt) throws IOException {
|
|
67 return finalConsole.readLine(prompt);
|
|
68 }
|
|
69
|
|
70 });
|
|
71 }
|
|
72
|
|
73 // Set up a context
|
|
74
|
|
75 final RubyContext context = new RubyContext(new Configuration(configurationBuilder), new JRubyParser());
|
|
76
|
|
77 // Bring in core method nodes
|
|
78
|
|
79 CoreMethodNodeManager.addMethods(context.getCoreLibrary().getObjectClass());
|
|
80
|
|
81 // Give the core library manager a chance to tweak some of those methods
|
|
82
|
|
83 context.getCoreLibrary().initializeAfterMethodsAdded();
|
|
84
|
|
85 // Set program arguments
|
|
86
|
|
87 for (String arg : options.getProgramArgs()) {
|
|
88 context.getCoreLibrary().getArgv().push(context.makeString(arg));
|
|
89 }
|
|
90
|
|
91 if (!options.getSwitchArgs().isEmpty()) {
|
|
92 context.implementationMessage("can't set -s switch arguments yet");
|
|
93 }
|
|
94
|
|
95 // Set the load path
|
|
96
|
|
97 final RubyArray loadPath = (RubyArray) context.getCoreLibrary().getGlobalVariablesObject().getInstanceVariable("$:");
|
|
98
|
|
99 final String pathVar = System.getenv("PATH");
|
|
100
|
|
101 if (options.isImportFromPath() && pathVar != null) {
|
|
102 for (String path : pathVar.split(File.pathSeparator)) {
|
|
103 loadPath.push(context.makeString(path));
|
|
104 }
|
|
105 }
|
|
106
|
|
107 for (String path : options.getExtraLoadPath()) {
|
|
108 loadPath.push(context.makeString(path));
|
|
109 }
|
|
110
|
|
111 final String rubylibVar = System.getenv("RUBYLIB");
|
|
112
|
|
113 if (rubylibVar != null) {
|
|
114 for (String path : rubylibVar.split(File.pathSeparator)) {
|
|
115 loadPath.push(context.makeString(path));
|
|
116 }
|
|
117 }
|
|
118
|
|
119 if (context.getConfiguration().getStandardLibrary().endsWith(".jar")) {
|
|
120 String version = null;
|
|
121
|
|
122 switch (configurationBuilder.getRubyVersion()) {
|
|
123 case RUBY_18:
|
|
124 version = "1.8";
|
|
125 break;
|
|
126 case RUBY_19:
|
|
127 version = "1.9";
|
|
128 break;
|
|
129 case RUBY_20:
|
|
130 version = "2.0";
|
|
131 break;
|
|
132 case RUBY_21:
|
|
133 version = "2.0";
|
|
134 break;
|
|
135 }
|
|
136
|
|
137 loadPath.push(context.makeString("jar:file:" + context.getConfiguration().getStandardLibrary() + "!/META-INF/jruby.home/lib/ruby/" + version));
|
|
138
|
|
139 } else {
|
|
140 loadPath.push(context.makeString(context.getConfiguration().getStandardLibrary()));
|
|
141 }
|
|
142
|
|
143 // Pre-required modules
|
|
144
|
|
145 for (String feature : options.getPreRequires()) {
|
|
146 context.getFeatureManager().require(feature);
|
|
147 }
|
|
148
|
|
149 // Check for other options that are not implemented yet
|
|
150
|
|
151 if (options.getRecordSeparator() != -1) {
|
|
152 context.implementationMessage("record separator not implemented");
|
|
153 }
|
|
154
|
|
155 if (options.isAutosplit()) {
|
|
156 context.implementationMessage("autosplit not implemented");
|
|
157 }
|
|
158
|
|
159 if (options.getPreChangeDirectory() != null) {
|
|
160 context.implementationMessage("not able to change directory");
|
|
161 }
|
|
162
|
|
163 if (options.isLineEndingProcessing()) {
|
|
164 context.implementationMessage("line end processing not implemented");
|
|
165 }
|
|
166
|
|
167 if (options.isInPlaceEdit()) {
|
|
168 context.implementationMessage("in place editing not implemented");
|
|
169 }
|
|
170
|
|
171 if (options.isImplicitLoop() || options.isImplicitSedLoop()) {
|
|
172 context.implementationMessage("implicit loops not implemented");
|
|
173 }
|
|
174
|
|
175 if (options.isStripMessage()) {
|
|
176 context.implementationMessage("strip message -x option not implemented");
|
|
177 }
|
|
178
|
|
179 // Run the scripts, program file, or run the temporary version of IRB
|
|
180
|
|
181 try {
|
|
182 if (!options.getCommandLineScripts().isEmpty()) {
|
|
183 final StringBuilder combinedScript = new StringBuilder();
|
|
184
|
|
185 for (String script : options.getCommandLineScripts()) {
|
|
186 combinedScript.append(script);
|
|
187 combinedScript.append("\n");
|
|
188 }
|
|
189
|
|
190 try {
|
|
191 final Source source = context.getSourceManager().get("-e", combinedScript.toString());
|
|
192 if (options.isCheckSyntaxOnly()) {
|
|
193 context.getParser().parse(context, source, RubyParser.ParserContext.TOP_LEVEL, null);
|
|
194 System.out.println("Syntax OK");
|
|
195 } else {
|
|
196 context.execute(context, source, RubyParser.ParserContext.TOP_LEVEL, context.getCoreLibrary().getMainObject(), null);
|
|
197 }
|
|
198 } catch (Exception e) {
|
|
199 e.printStackTrace();
|
|
200 }
|
|
201 } else if (options.getProgramFile() != null) {
|
|
202 try {
|
|
203 if (options.isCheckSyntaxOnly()) {
|
|
204 final Source source = context.getSourceManager().get(options.getProgramFile());
|
|
205 context.getParser().parse(context, source, RubyParser.ParserContext.TOP_LEVEL, null);
|
|
206 System.out.println("Syntax OK");
|
|
207 } else {
|
|
208 context.loadFile(options.getProgramFile());
|
|
209 }
|
|
210 } catch (Exception e) {
|
|
211 e.printStackTrace();
|
|
212 }
|
|
213 } else {
|
|
214 if (options.isCheckSyntaxOnly()) {
|
|
215 System.err.println("Can't check syntax in IRB mode");
|
|
216 return;
|
|
217 }
|
|
218
|
|
219 context.runShell(null, null);
|
|
220 }
|
|
221 } finally {
|
|
222 context.shutdown();
|
|
223 }
|
|
224 }
|
|
225
|
|
226 }
|