24
24
import com .oracle .truffle .api .CompilerAsserts ;
25
25
import com .oracle .truffle .api .CompilerDirectives ;
26
26
import com .oracle .truffle .api .ContextThreadLocal ;
27
+ import com .oracle .truffle .api .Option ;
27
28
import com .oracle .truffle .api .TruffleFile ;
28
29
import com .oracle .truffle .api .frame .FrameDescriptor ;
29
30
import com .oracle .truffle .api .frame .MaterializedFrame ;
41
42
import com .oracle .truffle .api .strings .InternalByteArray ;
42
43
import com .oracle .truffle .api .strings .TruffleString ;
43
44
import org .graalvm .nativeimage .ImageInfo ;
45
+ import org .graalvm .options .OptionCategory ;
44
46
import org .graalvm .options .OptionDescriptors ;
47
+ import org .graalvm .options .OptionKey ;
45
48
import org .prism .Parser ;
46
49
import org .truffleruby .annotations .SuppressFBWarnings ;
47
50
import org .truffleruby .builtins .PrimitiveManager ;
123
126
import org .truffleruby .parser .BlockDescriptorInfo ;
124
127
import org .truffleruby .parser .ParserContext ;
125
128
import org .truffleruby .parser .ParsingParameters ;
126
- import org .truffleruby .parser .RubySource ;
127
129
import org .truffleruby .parser .TranslatorEnvironment ;
128
130
import org .truffleruby .shared .Platform ;
129
131
import org .truffleruby .shared .Metrics ;
158
160
id = TruffleRuby .LANGUAGE_ID ,
159
161
implementationName = TruffleRuby .FORMAL_NAME ,
160
162
version = TruffleRuby .LANGUAGE_VERSION ,
161
- characterMimeTypes = {
162
- RubyLanguage .MIME_TYPE ,
163
- RubyLanguage .MIME_TYPE_COVERAGE ,
164
- RubyLanguage .MIME_TYPE_MAIN_SCRIPT },
163
+ characterMimeTypes = RubyLanguage .MIME_TYPE ,
165
164
defaultMimeType = RubyLanguage .MIME_TYPE ,
166
165
dependentLanguages = { "nfi" , "llvm" , "regex" },
167
166
fileTypeDetectors = RubyFileTypeDetector .class )
178
177
})
179
178
public final class RubyLanguage extends TruffleLanguage <RubyContext > {
180
179
181
- /** Do not access directly, instead use {@link #getMimeType(boolean)} */
182
- static final String MIME_TYPE = "application/x-ruby" ;
183
- public static final String MIME_TYPE_COVERAGE = "application/x-ruby;coverage=true" ;
184
- public static final String MIME_TYPE_MAIN_SCRIPT = "application/x-ruby;main-script=true" ;
185
- public static final String [] MIME_TYPES = { MIME_TYPE , MIME_TYPE_COVERAGE , MIME_TYPE_MAIN_SCRIPT };
180
+ @ Option .Group (TruffleRuby .LANGUAGE_ID )
181
+ public abstract static class RubySourceOptions {
182
+ // @formatter:off
183
+ @ Option (help = "Whether Ruby coverage is enabled for this source" , category = OptionCategory .INTERNAL )
184
+ public static final OptionKey <Boolean > Coverage = new OptionKey <>(false );
185
+
186
+ @ Option (help = "Mark this source as the main Ruby script ($0)" , category = OptionCategory .INTERNAL )
187
+ public static final OptionKey <Boolean > MainScript = new OptionKey <>(false );
188
+
189
+ @ Option (help = "Record the line offset when this source was eval'ed" , category = OptionCategory .INTERNAL )
190
+ public static final OptionKey <Integer > LineOffset = new OptionKey <>(0 );
191
+ // @formatter:on
192
+ }
193
+
194
+ public static final String MIME_TYPE = "application/x-ruby" ;
195
+ /** To avoid some String[] allocations */
196
+ public static final String [] MIME_TYPES = { MIME_TYPE };
186
197
187
198
public static final String LLVM_BITCODE_MIME_TYPE = "application/x-llvm-ir-bitcode" ;
188
199
@@ -366,10 +377,6 @@ public static RubyLanguage get(Node node) {
366
377
return REFERENCE .get (node );
367
378
}
368
379
369
- public static String getMimeType (boolean coverageEnabled ) {
370
- return coverageEnabled ? MIME_TYPE_COVERAGE : MIME_TYPE ;
371
- }
372
-
373
380
public RubyLanguage () {
374
381
coreMethodAssumptions = new CoreMethodAssumptions (this );
375
382
coreStrings = new CoreStrings (this );
@@ -469,7 +476,7 @@ public RubyContext createContext(Env env) {
469
476
this .coreLoadPath = buildCoreLoadPath (this .options .CORE_LOAD_PATH );
470
477
this .corePath = coreLoadPath + File .separator + "core" + File .separator ;
471
478
Instrumenter instrumenter = Objects .requireNonNull (env .lookup (Instrumenter .class ));
472
- this .coverageManager = new CoverageManager (options , instrumenter );
479
+ this .coverageManager = new CoverageManager (this , instrumenter );
473
480
if (options .INSTRUMENT_ALL_NODES ) {
474
481
instrumentAllNodes (instrumenter );
475
482
}
@@ -597,7 +604,7 @@ protected RootCallTarget parse(ParsingRequest request) {
597
604
final ParsingParameters parsingParameters = parsingRequestParams .get ();
598
605
if (parsingParameters != null ) { // from #require or core library
599
606
assert parsingParameters .rubySource .getSource ().equals (source );
600
- final ParserContext parserContext = MIME_TYPE_MAIN_SCRIPT . equals ( source . getMimeType () )
607
+ final ParserContext parserContext = request . getOptionValues (). get ( RubySourceOptions . MainScript )
601
608
? ParserContext .TOP_LEVEL_FIRST
602
609
: ParserContext .TOP_LEVEL ;
603
610
final LexicalScope lexicalScope = contextIfSingleContext .map (RubyContext ::getRootLexicalScope ).orElse (null );
@@ -634,6 +641,11 @@ protected OptionDescriptors getOptionDescriptors() {
634
641
return OptionDescriptors .create (Arrays .asList (OptionsCatalog .allDescriptors ()));
635
642
}
636
643
644
+ @ Override
645
+ protected OptionDescriptors getSourceOptionDescriptors () {
646
+ return new RubySourceOptionsOptionDescriptors ();
647
+ }
648
+
637
649
@ Override
638
650
protected boolean isThreadAccessAllowed (Thread thread , boolean singleThreaded ) {
639
651
return true ;
@@ -944,18 +956,13 @@ public String getSourcePath(Source source) {
944
956
}
945
957
946
958
@ TruffleBoundary
947
- public static String getCorePath (Source source ) {
948
- final String path = getPath (source );
949
- String coreLoadPath = OptionsCatalog .CORE_LOAD_PATH_KEY .getDefaultValue ();
950
- if (path .startsWith (coreLoadPath )) {
951
- return "<internal:core> " + path .substring (coreLoadPath .length () + 1 );
952
- } else {
953
- throw CompilerDirectives .shouldNotReachHere (path + " is not a core path starting with " + coreLoadPath );
954
- }
959
+ public int getStartLineAdjusted (SourceSection sourceSection ) {
960
+ int lineOffset = sourceSection .getSource ().getOptions (this ).get (RubySourceOptions .LineOffset );
961
+ return sourceSection .getStartLine () + lineOffset ;
955
962
}
956
963
957
964
/** Only use when no language/context is available (e.g. Node#toString). Prefer
958
- * {@link RubyContext #fileLine(SourceSection)} as it accounts for coreLoadPath and line offsets. */
965
+ * {@link RubyLanguage #fileLine(SourceSection)} as it accounts for coreLoadPath and line offsets. */
959
966
@ TruffleBoundary
960
967
public static String fileLineRange (SourceSection section ) {
961
968
if (section == null ) {
@@ -975,48 +982,29 @@ public static String fileLineRange(SourceSection section) {
975
982
}
976
983
}
977
984
978
- /** Prefer {@link RubyContext#fileLine(SourceSection)} as it is more concise. */
979
985
@ TruffleBoundary
980
- String fileLine (RubyContext context , SourceSection section ) {
986
+ public String fileLine (SourceSection section ) {
981
987
if (section == null ) {
982
988
return "no source section" ;
983
989
} else {
984
990
final String path = getSourcePath (section .getSource ());
985
991
986
992
if (section .isAvailable ()) {
987
- return path + ":" + RubySource . getStartLineAdjusted (context , section );
993
+ return path + ":" + getStartLineAdjusted (section );
988
994
} else {
989
995
return path ;
990
996
}
991
997
}
992
998
}
993
999
994
- /** Only use when no language/context is available (e.g. Node#toString). Prefer
995
- * {@link RubyContext#fileLine(SourceSection)} as it accounts for coreLoadPath and line offsets. */
996
- @ TruffleBoundary
997
- public static String filenameLine (SourceSection section ) {
998
- if (section == null ) {
999
- return "no source section" ;
1000
- } else {
1001
- final String path = getPath (section .getSource ());
1002
- final String filename = new File (path ).getName ();
1003
-
1004
- if (section .isAvailable ()) {
1005
- return filename + ":" + section .getStartLine ();
1006
- } else {
1007
- return filename ;
1008
- }
1009
- }
1010
- }
1011
-
1012
- public Object rubySourceLocation (RubyContext context , SourceSection section ,
1000
+ public Object rubySourceLocation (SourceSection section ,
1013
1001
TruffleString .FromJavaStringNode fromJavaStringNode ,
1014
1002
Node node ) {
1015
1003
if (!BacktraceFormatter .isAvailable (section )) {
1016
1004
return nil ;
1017
1005
} else {
1018
1006
var file = createString (node , fromJavaStringNode , getSourcePath (section .getSource ()), Encodings .UTF_8 );
1019
- Object [] objects = new Object []{ file , RubySource . getStartLineAdjusted (context , section ) };
1007
+ Object [] objects = new Object []{ file , getStartLineAdjusted (section ) };
1020
1008
return createArray (node , objects );
1021
1009
}
1022
1010
}
0 commit comments