add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby.vsmdi
File: Ruby.vsmdi
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby.vsmdi;exc
@@ -1,0 +1,6 @@
+?
+
+
+
+
+
\ No newline at end of file
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby.vssscc;C390406
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;C761655
File: Initializers.Generated.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;C761655 (server) 3/2/2009 12:40 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;exc
@@ -1005,7 +1005,7 @@
module.DefineRuleGenerator("exception", 0x51, IronRuby.Builtins.ExceptionOps.GetException());
module.DefineLibraryMethod("initialize", 0x52,
- new System.Func(IronRuby.Builtins.ExceptionOps.ReinitializeException)
+ new System.Func(IronRuby.Builtins.ExceptionOps.InitializeException)
);
module.DefineLibraryMethod("inspect", 0x51,
@@ -2340,7 +2340,7 @@
module.DefineLibraryMethod("fail", 0x52,
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
- new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
+ new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
);
module.DefineLibraryMethod("Float", 0x52,
@@ -2524,7 +2524,7 @@
module.DefineLibraryMethod("raise", 0x52,
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
- new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
+ new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
);
module.DefineLibraryMethod("rand", 0x52,
@@ -2707,7 +2707,7 @@
module.DefineLibraryMethod("fail", 0x61,
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
- new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
+ new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
);
module.DefineLibraryMethod("Float", 0x61,
@@ -2801,7 +2801,7 @@
module.DefineLibraryMethod("raise", 0x61,
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
new System.Action(IronRuby.Builtins.KernelOps.RaiseException),
- new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
+ new System.Action(IronRuby.Builtins.KernelOps.RaiseException)
);
module.DefineLibraryMethod("rand", 0x61,
@@ -5107,7 +5107,7 @@
module.DefineLibraryMethod("raise", 0x51,
new System.Action(IronRuby.Builtins.ThreadOps.RaiseException),
new System.Action(IronRuby.Builtins.ThreadOps.RaiseException),
- new System.Action(IronRuby.Builtins.ThreadOps.RaiseException)
+ new System.Action(IronRuby.Builtins.ThreadOps.RaiseException)
);
#if !SILVERLIGHT
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ExceptionOps.cs;C759835
File: ExceptionOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ExceptionOps.cs;C759835 (server) 3/2/2009 10:45 AM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ExceptionOps.cs;exc
@@ -23,6 +23,7 @@
using System.Dynamic;
using System.Diagnostics;
using System.Reflection;
+using IronRuby.Compiler;
using IronRuby.Compiler.Generation;
using Ast = System.Linq.Expressions.Expression;
@@ -72,16 +73,15 @@
}
[Emitted]
- public static Exception/*!*/ ReinitializeException(Exception/*!*/ self, object/*!*/ message) {
+ public static Exception/*!*/ InitializeException(Exception/*!*/ self, object/*!*/ message) {
var instance = RubyExceptionData.GetInstance(self);
- instance.Backtrace = null;
instance.Message = message;
return self;
}
[RubyMethod("initialize", RubyMethodAttributes.PrivateInstance)]
- public static Exception/*!*/ ReinitializeException(RubyContext/*!*/ context, Exception/*!*/ self, [DefaultParameterValue(null)]object message) {
- return ReinitializeException(self, message ?? context.GetClassOf(self).Name);
+ public static Exception/*!*/ InitializeException(RubyContext/*!*/ context, Exception/*!*/ self, [DefaultParameterValue(null)]object message) {
+ return InitializeException(self, message ?? context.GetClassOf(self).Name);
}
[RubyMethod("exception", RubyMethodAttributes.PublicSingleton)]
@@ -128,20 +128,30 @@
} else {
RubyClass cls = args.RubyContext.GetClassOf(args.Target);
var classExpression = AstUtils.Constant(cls);
- args.SetTarget(classExpression, cls);
+ ParameterExpression messageVariable = metaBuilder.GetTemporary(typeof(object), "#message");
+ Expression clrMessage = Ast.Call(
+ null,
+ new Func(GetClrMessage).Method,
+ classExpression,
+ Ast.Assign(messageVariable, AstFactory.Box(argsBuilder[0])));
- ParameterExpression messageVariable = null;
+ // if (self == null)
+ //
+ // else if (self == message)
+ // self
+ // else
+ // #message =
+ // new (GetClrMessage(#message))
- // ReinitializeException(new (GetClrMessage(, #message = )), #message)
- metaBuilder.Result = Ast.Call(null, new Func(ReinitializeException).Method,
- cls.MakeAllocatorCall(args, () =>
- Ast.Call(null, new Func(GetClrMessage).Method,
- classExpression,
- Ast.Assign(messageVariable = metaBuilder.GetTemporary(typeof(object), "#message"), AstFactory.Box(argsBuilder[0]))
- )
- ),
- messageVariable ?? AstFactory.Box(argsBuilder[0])
- );
+ metaBuilder.Result = Ast.Condition(
+ Ast.Call(typeof(object).GetMethod("ReferenceEquals"), args.TargetExpression, argsBuilder[0]),
+ Ast.Convert(args.TargetExpression, typeof(Exception)),
+ Ast.Call(
+ typeof(RubyOps).GetMethod("InitializeException"),
+ cls.MakeAllocatorCall(args, classExpression, clrMessage),
+ AstFactory.Box(argsBuilder[0]),
+ Ast.Constant(false)),
+ typeof(Exception));
}
}
});
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;C761655
File: KernelOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;C761655 (server) 3/2/2009 2:45 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;exc
@@ -711,10 +711,10 @@
[RubyMethod("fail", RubyMethodAttributes.PrivateInstance)]
[RubyMethod("fail", RubyMethodAttributes.PublicSingleton)]
[RubyStackTraceHidden]
- public static void RaiseException(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1,
+ public static void RaiseException(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1, SetBacktraceStorage/*!*/ setBackTraceStorage,
RubyContext/*!*/ context, object self, object/*!*/ obj, [Optional]object arg, [Optional]RubyArray backtrace) {
- Exception exception = CreateExceptionToRaise(respondToStorage, storage0, storage1, context, obj, arg, backtrace);
+ Exception exception = CreateExceptionToRaise(respondToStorage, storage0, storage1, setBackTraceStorage, context, obj, arg, backtrace);
#if DEBUG && !SILVERLIGHT
if (RubyOptions.UseThreadAbortForSyncRaise) {
RubyUtils.RaiseAsyncException(Thread.CurrentThread, exception);
@@ -724,7 +724,7 @@
throw exception;
}
- internal static Exception CreateExceptionToRaise(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1,
+ internal static Exception CreateExceptionToRaise(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1, SetBacktraceStorage/*!*/ setBackTraceStorage,
RubyContext/*!*/ context, object/*!*/ obj, object arg, RubyArray backtrace) {
if (Protocols.RespondTo(respondToStorage, context, obj, "exception")) {
@@ -739,7 +739,7 @@
if (e != null) {
if (backtrace != null) {
- ExceptionOps.SetBacktrace(e, backtrace);
+ RubyExceptionData.GetInstance(e).SetBacktrace(setBackTraceStorage, context, backtrace);
}
return e;
}
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;C700904
File: ThreadOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;C700904 (server) 3/1/2009 11:50 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;exc
@@ -25,6 +25,7 @@
using IronRuby.Runtime;
using System.Text;
using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
namespace IronRuby.Builtins {
///
@@ -442,18 +443,18 @@
[RubyMethod("raise")]
[RubyStackTraceHidden]
- public static void RaiseException(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1,
+ public static void RaiseException(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1, SetBacktraceStorage/*!*/ setBackTraceStorage,
RubyContext/*!*/ context, Thread/*!*/ self, object/*!*/ obj, [Optional]object arg, [Optional]RubyArray backtrace) {
if (self == Thread.CurrentThread) {
- KernelOps.RaiseException(respondToStorage, storage0, storage1, context, self, obj, arg, backtrace);
+ KernelOps.RaiseException(respondToStorage, storage0, storage1, setBackTraceStorage, context, self, obj, arg, backtrace);
return;
}
#if SILVERLIGHT
throw new NotImplementedError("Thread#raise is not implemented on Silverlight");
#else
- Exception e = KernelOps.CreateExceptionToRaise(respondToStorage, storage0, storage1, context, obj, arg, backtrace);
+ Exception e = KernelOps.CreateExceptionToRaise(respondToStorage, storage0, storage1, setBackTraceStorage, context, obj, arg, backtrace);
RaiseAsyncException(self, e);
#endif
}
@@ -654,7 +655,7 @@
trace.AppendLine();
trace.AppendLine();
RubyExceptionData data = RubyExceptionData.GetInstance(e);
- if (data.Backtrace != null) { // ReinitializeException sets Backtrace to null
+ if (data.Backtrace != null) {
foreach (var frame in data.Backtrace) {
trace.Append(frame.ToString());
}
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs;C761655
File: RubyClass.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs;C761655 (server) 3/2/2009 1:02 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs;exc
@@ -864,7 +864,7 @@
argsBuilder.AddCallArguments(metaBuilder, args);
if (!metaBuilder.Error) {
- metaBuilder.Result = MakeAllocatorCall(args, () => AstUtils.Constant(Name));
+ metaBuilder.Result = MakeAllocatorCall(args, AstUtils.Constant(Name));
}
}
@@ -894,7 +894,7 @@
// Is user class (defined in Ruby code) => construct it as if it had initializer that calls super immediately
// (we need to "inherit" factories/constructors from the base class (e.g. class S < String; self; end.new('foo')).
if (overriddenInitializer != null || (_isRubyClass && _structInfo == null)) {
- metaBuilder.Result = MakeAllocatorCall(args, () => AstUtils.Constant(Name));
+ metaBuilder.Result = MakeAllocatorCall(args, AstUtils.Constant(Name));
if (overriddenInitializer != null || (_isRubyClass && initializer != null && !initializer.IsEmpty)) {
BuildOverriddenInitializerCall(metaBuilder, args, initializer);
@@ -964,11 +964,15 @@
}
}
- public Expression/*!*/ MakeAllocatorCall(CallArguments/*!*/ args, Func/*!*/ defaultExceptionMessage) {
+ public Expression/*!*/ MakeAllocatorCall(CallArguments/*!*/ args, Expression/*!*/ clrExceptionMessage) {
+ return MakeAllocatorCall(args, args.TargetExpression, clrExceptionMessage);
+ }
+
+ public Expression/*!*/ MakeAllocatorCall(CallArguments/*!*/ args, Expression/*!*/ classExpression, Expression/*!*/ clrExceptionMessage) {
Type type = GetUnderlyingSystemType();
if (_structInfo != null) {
- return Methods.AllocateStructInstance.OpCall(AstUtils.Convert(args.TargetExpression, typeof(RubyClass)));
+ return Methods.AllocateStructInstance.OpCall(AstUtils.Convert(classExpression, typeof(RubyClass)));
}
if (type.IsSubclassOf(typeof(Delegate))) {
@@ -978,14 +982,14 @@
ConstructorInfo ctor;
if (IsException()) {
if ((ctor = type.GetConstructor(new[] { typeof(string) })) != null) {
- return Ast.New(ctor, defaultExceptionMessage());
+ return Ast.New(ctor, clrExceptionMessage);
} else if ((ctor = type.GetConstructor(new[] { typeof(string), typeof(Exception) })) != null) {
- return Ast.New(ctor, defaultExceptionMessage(), AstUtils.Constant(null));
+ return Ast.New(ctor, clrExceptionMessage, AstUtils.Constant(null));
}
}
if ((ctor = type.GetConstructor(new[] { typeof(RubyClass) })) != null) {
- return Ast.New(ctor, AstUtils.Convert(args.TargetExpression, typeof(RubyClass)));
+ return Ast.New(ctor, AstUtils.Convert(classExpression, typeof(RubyClass)));
}
if ((ctor = type.GetConstructor(new[] { typeof(RubyContext) })) != null) {
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;C748168
File: RubyOptionsParser.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;C748168 (server) 3/2/2009 1:23 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;exc
@@ -83,6 +83,8 @@
}
switch (optionName) {
+ #region Ruby options
+
case "-v":
CommonConsoleOptions.PrintVersion = true;
CommonConsoleOptions.Exit = true;
@@ -119,6 +121,12 @@
CommonConsoleOptions.Command += PopNextArg();
break;
+ case "-I":
+ _loadPaths.AddRange(PopNextArg().Split(Path.PathSeparator));
+ break;
+
+ #endregion
+
#if DEBUG && !SILVERLIGHT
case "-DT*":
SetTraceFilter(String.Empty, false);
@@ -152,10 +160,6 @@
LanguageSetup.Options["CompileRegexps"] = true;
break;
#endif
- case "-I":
- _loadPaths.AddRange(PopNextArg().Split(Path.PathSeparator));
- break;
-
case "-trace":
LanguageSetup.Options["EnableTracing"] = ScriptingRuntimeHelpers.True;
break;
@@ -204,11 +208,43 @@
base.GetHelp(out commandLine, out standardOptions, out environmentVariables, out comments);
string [,] rubyOptions = new string[,] {
- { "-opt", "dummy" },
+ // { "-0[octal]", "specify record separator (\0, if no argument)" },
+ // { "-a", "autosplit mode with -n or -p (splits $_ into $F)" },
+ // { "-c", "check syntax only" },
+ // { "-Cdirectory", "cd to directory, before executing your script" },
+ { "-d", "set debugging flags (set $DEBUG to true)" },
+ { "-e 'command'", "one line of script. Several -e's allowed. Omit [programfile]" },
+ // { "-Fpattern", "split() pattern for autosplit (-a)" },
+ // { "-i[extension]", "edit ARGV files in place (make backup if extension supplied)" },
+ { "-Idirectory", "specify $LOAD_PATH directory (may be used more than once)" },
+ // { "-Kkcode", "specifies KANJI (Japanese) code-set" },
+ // { "-l", "enable line ending processing" },
+ // { "-n", "assume 'while gets(); ... end' loop around your script" },
+ // { "-p", "assume loop like -n but print line also like sed" },
+ { "-rlibrary", "require the library, before executing your script" },
+ // { "-s", "enable some switch parsing for switches after script name" },
+ // { "-S", "look for the script using PATH environment variable" },
+ // { "-T[level]", "turn on tainting checks" },
+ { "-v", "print version number, then turn on verbose mode" },
+ { "-w", "turn warnings on for your script" },
+ { "-W[level]", "set warning level; 0=silence, 1=medium, 2=verbose (default)" },
+ // { "-x[directory]", "strip off text before #!ruby line and perhaps cd to directory" },
#if DEBUG
+ { "-opt", "dummy" },
+ { "-DT", "" },
+ { "-DT*", "" },
+ { "-ET", "" },
+ { "-ET*", "" },
+ { "-save [path]", "Save generated code to given path" },
+ { "-load", "Load pre-compiled code" },
{ "-useThreadAbortForSyncRaise", "For testing purposes" },
{ "-compileRegexps", "Faster throughput, slower startup" },
#endif
+ { "-trace", "Enable support for set_trace_func" },
+ { "-profile", "Enable support Clr.profile" },
+ { "-18", "Ruby 1.8 mode" },
+ { "-19", "Ruby 1.9 mode" },
+ { "-20", "Ruby 2.0 mode" },
};
// Append the Ruby-specific options and the standard options
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Loader.cs;C764619
File: Loader.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Loader.cs;C764619 (server) 3/2/2009 1:40 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Loader.cs;exc
@@ -185,7 +185,7 @@
string savePath = _context.RubyOptions.SavePath;
if (savePath != null) {
lock (_compiledFileMutex) {
- var assemblyPath = Path.Combine(savePath, Path.GetFileName(_context.RubyOptions.MainFile) + ".dll");
+ var assemblyPath = Path.Combine(savePath, (Path.GetFileName(_context.RubyOptions.MainFile) ?? "snippets") + ".dll");
Utils.Log(String.Format("SAVING to {0}", Path.GetFullPath(assemblyPath)), "LOADER");
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C749683
File: RubyExceptionData.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C749683 (server) 3/2/2009 10:36 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;exc
@@ -55,44 +55,36 @@
// can be set explicitly by the user (even to nil):
private RubyArray _backtrace;
+ private bool _backtraceInitialized;
- // false if _backtrace needs to be initialized.
- private bool _backtraceInitialized;
+ private SetBacktraceStorage/*!*/ _setBacktraceStorage = new SetBacktraceStorage();
- // Compiled trace: contains frames above and including the first Ruby filter/catch site that the exception was caught by:
- private StackTrace _catchSiteTrace;
-
- // Compiled trace: contains frames starting with the throw site up to the first filter/catch that the exception was caught by:
- private StackTrace _throwSiteTrace;
-
private RubyExceptionData(Exception/*!*/ exception) {
_exception = exception;
_visibleException = exception;
_throwingThread = Thread.CurrentThread;
}
- // Called lazily to create a Ruby backtrace.
- private void CreateBacktrace() {
+ private void CreateBacktrace(RubyContext context, StackTrace catchSiteTrace) {
int skipFrames = 0;
bool hasFileAccessPermissions = DetectFileAccessPermissions();
var result = new RubyArray();
- if (_throwSiteTrace == null) {
- SetCompiledTrace();
- }
+ // Compiled trace: contains frames starting with the throw site up to the first filter/catch that the exception was caught by:
+ StackTrace throwSiteTrace = DebugInfoAvailable ? new StackTrace(_exception, true) : new StackTrace(_exception);
+ AddBacktrace(result, throwSiteTrace.GetFrames(), hasFileAccessPermissions, skipFrames, false);
- AddBacktrace(result, _throwSiteTrace.GetFrames(), hasFileAccessPermissions, skipFrames, false);
-
- if (_catchSiteTrace != null) {
+ if (catchSiteTrace != null) {
// skip one frame - the catch-site frame is already included
- AddBacktrace(result, _catchSiteTrace.GetFrames(), hasFileAccessPermissions, 1, false);
+ AddBacktrace(result, catchSiteTrace.GetFrames(), hasFileAccessPermissions, 1, false);
}
_backtrace = result;
_backtraceInitialized = true;
+ SetBacktrace(_setBacktraceStorage, context, _backtrace);
}
- internal void SetCompiledTrace() {
+ internal void SetCompiledTrace(RubyContext/*!*/ context) {
if (_exception != _visibleException) {
// Thread#raise uses Thread.Abort to raise an async exception. In such cases, a different instance of
// ThreadAbortException is thrown at the end of every catch block (as long as Thread.ResetAbort is not called).
@@ -105,8 +97,10 @@
Debug.Assert(!_backtraceInitialized);
- _catchSiteTrace = DebugInfoAvailable ? new StackTrace(true) : new StackTrace();
- _throwSiteTrace = DebugInfoAvailable ? new StackTrace(_exception, true) : new StackTrace(_exception);
+ // Compiled trace: contains frames above and including the first Ruby filter/catch site that the exception was caught by:
+ StackTrace catchSiteTrace = DebugInfoAvailable ? new StackTrace(true) : new StackTrace();
+
+ CreateBacktrace(context, catchSiteTrace);
}
internal void SetInterpretedTrace(InterpreterState/*!*/ state) {
@@ -124,7 +118,21 @@
// we need to copy the trace since the source locations in frames above catch site could be altered by further interpretation:
_backtrace = AddBacktrace(new RubyArray(), state, 0);
+ SetBacktrace(_setBacktraceStorage, state.ScriptCode.LanguageContext as RubyContext, _backtrace);
+ }
+
+ public RubyArray SetBacktrace(SetBacktraceStorage setBacktraceStorage, RubyContext context, RubyArray backtrace) {
_backtraceInitialized = true;
+
+ if (context == null) {
+ // TODO: If we do not have a RubyContext, we cannot dispatch to the overriden Exception#set_backtrace method.
+ // We need to ensure that we have a non-null RubyContext.
+ Backtrace = backtrace;
+ return backtrace;
+ } else {
+ var site = setBacktraceStorage.GetCallSite();
+ return site.Target(site, context, _exception, backtrace);
+ }
}
internal static RubyArray/*!*/ CreateBacktrace(RubyContext/*!*/ context, IEnumerable/*!*/ stackTrace, int skipFrames) {
@@ -362,8 +370,13 @@
public RubyArray Backtrace {
get {
if (!_backtraceInitialized) {
- CreateBacktrace();
+ // This path is rarely executed - if $! is accessed from a ensure clause without a rescue clause.
+ // Ast.Body.TransformExceptionHandling should be updated such that SetCompiledTrace is always called,
+ // which will guarantee that the backtrace is created after every exception before any Ruby code
+ // is executed.
+ CreateBacktrace(null, null);
}
+
return _backtrace;
}
set {
@@ -372,20 +385,6 @@
}
}
- ///
- /// Called from Kernel#raise, when throwing a user created Exception objects
- /// Clears out any backtrace set by the user
- /// This causes the new one to be lazily created the next time it is accessed
- ///
- public static void ClearBacktrace(Exception e) {
- RubyExceptionData result = TryGetInstance(e);
- if (result != null) {
- result._backtraceInitialized = false;
- result._backtrace = null;
- result._catchSiteTrace = null;
- }
- }
-
public static string/*!*/ GetClrMessage(object message, string/*!*/ className) {
// TODO: we can use to_s protocol conversion that doesn't throw an exception:
var str = message as MutableString;
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C761655
File: RubyOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C761655 (server) 3/2/2009 2:18 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;exc
@@ -1303,7 +1303,7 @@
[Emitted] //Body:
public static void SetCurrentExceptionAndStackTrace(RubyScope/*!*/ scope, Exception/*!*/ exception) {
if (RubyExceptionData.TryGetInstance(exception) == null) {
- RubyExceptionData.AssociateInstance(exception).SetCompiledTrace();
+ RubyExceptionData.AssociateInstance(exception).SetCompiledTrace(scope.RubyContext);
}
scope.RubyContext.CurrentException = exception;
}
@@ -1357,6 +1357,15 @@
}
[Emitted]
+ public static Exception/*!*/ InitializeException(Exception/*!*/ e, object message, bool captureStackTrace) {
+ RubyExceptionData.InitializeException(e, message);
+ if (captureStackTrace == false) {
+ RubyExceptionData.GetInstance(e).Backtrace = null;
+ }
+ return e;
+ }
+
+ [Emitted]
public static ArgumentException/*!*/ CreateArgumentsError(string message) {
return (ArgumentException)RubyExceptions.CreateArgumentError(message);
}
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs;C747909
File: RubyUtils.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs;C747909 (server) 3/2/2009 10:50 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs;exc
@@ -70,6 +70,11 @@
}
}
+ public class SetBacktraceStorage : CallSiteStorage> {
+ public CallSite>/*!*/ GetCallSite() {
+ return GetCallSite("set_backtrace", 1);
+ }
+ }
public static class RubyUtils {
#region Objects
===================================================================
add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/RubySpec/RubySpec.csproj
File: RubySpec.csproj
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/RubySpec/RubySpec.csproj;exc
@@ -1,0 +1,58 @@
+?
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {534A82C6-3EB0-4888-ABD2-A15284683E8D}
+ Exe
+ Properties
+ RubySpec
+ RubySpec
+ v3.5
+ 512
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+ IronRuby-tags\critical_tags.txt
+
+
+
+
+ MSpec\Spec\spec_helper.rb
+
+
+ RubySpec\spec_helper.rb
+
+
+
\ No newline at end of file
===================================================================
add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/RubySpec/RubySpec.csproj.vspscc
File: RubySpec.csproj.vspscc
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/RubySpec/RubySpec.csproj.vspscc;exc
@@ -1,0 +1,10 @@
+?""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
===================================================================
add: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/core/exception/backtrace_tags.txt
File: backtrace_tags.txt
===================================================================
--- [no source file]
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/core/exception/backtrace_tags.txt;exc
@@ -1,0 +1,1 @@
+fails:Exception#backtrace is set for exceptions in an ensure block
===================================================================
delete: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/library/uri/parse_tags.txt;C715722
File: parse_tags.txt
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/library/uri/parse_tags.txt;C715722 (server) 2/26/2009 4:41 PM
+++ [no target file]
@@ -1,1 +1,0 @@
-fails:URI.parse populates the components of a parsed URI::FTP object
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/backtrace_spec.rb;C715722
File: backtrace_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/backtrace_spec.rb;C715722 (server) 3/3/2009 12:48 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/backtrace_spec.rb;exc
@@ -1,1 +1,10 @@
require File.dirname(__FILE__) + '/../../spec_helper'
+require File.dirname(__FILE__) + '/fixtures/common'
+
+describe "Exception#backtrace" do
+ it "is set for exceptions in an ensure block" do
+ # IronRuby used to get this wrong.
+ ExceptionSpecs.record_exception_from_ensure_block_with_rescue_clauses
+ /record_exception_from_ensure_block_with_rescue_clauses/.match(ScratchPad.recorded.join).should_not be_nil
+ end
+end
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/exception_spec.rb;C715722
File: exception_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/exception_spec.rb;C715722 (server) 3/1/2009 11:51 PM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/exception_spec.rb;exc
@@ -1,10 +1,82 @@
require File.dirname(__FILE__) + '/../../spec_helper'
+require File.dirname(__FILE__) + '/../../fixtures/class'
+require File.dirname(__FILE__) + '/fixtures/common'
require File.dirname(__FILE__) + '/shared/new'
describe "Exception.exception" do
it_behaves_like(:exception_new, :exception)
end
+describe "Exception.exception" do
+ it "returns new exception even if argument is Exception (unlike Exception#exception)" do
+ e = Exception.new
+ Exception.exception(e).message.should equal(e)
+ end
+
+ it "returns new exception with string message" do
+ Exception.exception("new message").message.should == "new message"
+ end
+
+ it "creates new object if an argument responding to to_s is given" do
+ m = ClassSpecs::A.new
+ m.should_receive(:to_s).any_number_of_times.and_return("new message")
+ e2 = Exception.exception(m)
+ e2.message.should equal(m)
+ end
+
+ it "allows nil argument" do
+ e2 = Exception.exception(nil)
+ e2.message.should == "Exception"
+ end
+end
+
+describe "Exception#exception" do
+ before(:each) do
+ @e = RuntimeError.new "test message"
+ @e.set_backtrace ["func0", "func1"]
+ end
+
+ it "returns self if no arguments are given" do
+ @e.exception.should equal(@e)
+ end
+
+ it "returns self if argument is self" do
+ @e.exception(@e).should equal(@e)
+ end
+
+ it "preserves backtrace" do
+ b = @e.backtrace
+ @e.exception.backtrace.should equal(b)
+ end
+
+ it "creates new object ands sets #message to argument" do
+ ["new message", ClassSpecs::A.new, ClassSpecs::Undef_to_s.new].each do |m|
+ e2 = @e.exception(m)
+ e2.message.should equal(m)
+ end
+ end
+
+ it "does not call initialize" do
+ e = ExceptionSpecs::InitializedException.new
+ ScratchPad.clear
+ e2 = e.exception("new message")
+
+ e2.should_not equal(e)
+ ScratchPad.recorded.should == nil
+ end
+
+ it "creates a new object with an empty backtrace" do
+ e2 = @e.exception("new message")
+ e2.backtrace.should be_nil
+ end
+
+ it "allows nil argument" do
+ e2 = @e.exception(nil)
+ e2.should_not equal(@e)
+ e2.message.should == @e.class.to_s
+ end
+end
+
describe "Exception" do
it "is a Class" do
Exception.should be_kind_of(Class)
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/fixtures/common.rb;C715722
File: common.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/fixtures/common.rb;C715722 (server) 3/2/2009 12:31 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/core/exception/fixtures/common.rb;exc
@@ -12,3 +12,26 @@
class NoMethodErrorD; end
end
+
+module ExceptionSpecs
+ class InitializedException < Exception
+ def initialize
+ ScratchPad.record :initialized_exception
+ end
+ end
+
+ def self.exception_from_ensure_block_with_rescue_clauses
+ begin
+ raise "some message"
+ ensure
+ ScratchPad.record $!.backtrace
+ end
+ end
+
+ def self.record_exception_from_ensure_block_with_rescue_clauses
+ begin
+ exception_from_ensure_block_with_rescue_clauses
+ rescue
+ end
+ end
+end
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/fixtures/class.rb;C715722
File: class.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/fixtures/class.rb;C715722 (server) 3/2/2009 12:27 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/fixtures/class.rb;exc
@@ -85,6 +85,16 @@
class L; end
class M < L; end
+
+ class Undef_to_s
+ undef to_s
+ end
+
+ class InitializeMethod
+ def initialize
+ ScratchPad.record :initialize_method
+ end
+ end
end
class Class
===================================================================
add: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/fixtures/kernel/classes.rb
File: classes.rb
===================================================================
--- [no source file]
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/fixtures/kernel/classes.rb;exc
@@ -1,0 +1,29 @@
+module KernelSpecs
+ class TestException < StandardError
+ def initialize record_exception_method = false, record_set_backtrace = false
+ @record_exception_method = record_exception_method
+ @record_set_backtrace = record_set_backtrace
+ end
+
+ def exception arg="default value"
+ if @record_exception_method then
+ ScratchPad << self
+ ScratchPad << :exception_method
+ ScratchPad << arg
+ end
+
+ TestException.new(@record_exception_method, @record_set_backtrace)
+ end
+
+ def set_backtrace b
+ if @record_set_backtrace then
+ ScratchPad << self
+ ScratchPad << :set_backtrace_method
+ ScratchPad << b.class
+ ScratchPad << b[0].class
+ end
+ super(b)
+ end
+ end
+
+end
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/language/regexp_spec.rb;C754096
File: regexp_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/language/regexp_spec.rb;C754096 (server) 3/2/2009 9:45 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/language/regexp_spec.rb;exc
@@ -1,5 +1,6 @@
require File.dirname(__FILE__) + '/../spec_helper'
require File.dirname(__FILE__) + '/fixtures/classes'
+require File.dirname(__FILE__) + '/../fixtures/class'
describe "Literal Regexps" do
it "matches against $_ (last input) in a conditional if no explicit matchee provided" do
@@ -95,7 +96,7 @@
end
it "throws NoMethodError on missing to_s" do
- o = LanguageSpecs::ClassWithout_to_s.new
+ o = ClassSpecs::Undef_to_s.new
lambda { /#{o}/ }.should raise_error(NoMethodError)
end
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/language/fixtures/classes.rb;C754096
File: classes.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/language/fixtures/classes.rb;C754096 (server) 3/2/2009 1:12 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/language/fixtures/classes.rb;exc
@@ -13,10 +13,6 @@
end
end
- class ClassWithout_to_s
- undef :to_s
- end
-
#############################################################################
# Regexp support
#############################################################################
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/library/uri/parse_spec.rb;C715722
File: parse_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/library/uri/parse_spec.rb;C715722 (server) 2/27/2009 9:55 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/library/uri/parse_spec.rb;exc
@@ -54,7 +54,8 @@
URI.parse("https://example.com/").port.should == 443
end
- ruby_version_is "".."1.8.6" do
+ compliant_on :ruby do
+ ruby_version_is "".."1.8.5" do
it "populates the components of a parsed URI::FTP object" do
# generic, empty password.
url = URI.parse("ftp://anonymous@ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.bz2;type=i")
@@ -95,8 +96,9 @@
end
end
+ end
- ruby_version_is "1.8.7".."" do
+ ruby_bug "", "1.8.5" do
it "populates the components of a parsed URI::FTP object" do
# generic, empty password.
url = URI.parse("ftp://anonymous@ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.bz2;type=i")
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/shared/kernel/raise.rb;C715722
File: raise.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/shared/kernel/raise.rb;C715722 (server) 3/2/2009 9:39 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/shared/kernel/raise.rb;exc
@@ -1,3 +1,5 @@
+require File.dirname(__FILE__) + '/../../fixtures/kernel/classes'
+
describe :kernel_raise, :shared => true do
before :each do
ScratchPad.clear
@@ -36,8 +38,55 @@
end
it "allows Exception, message, and backtrace parameters" do
- lambda do
- @object.raise(ArgumentError, "message", caller)
- end.should raise_error(ArgumentError, "message")
+ b = ["func0", "func1"]
+ begin
+ @object.raise(ArgumentError, "test message", b)
+ rescue ArgumentError => e
+ end
+ e.backtrace.should == b
+ e.message == "test message"
end
+
+ it "calls Exception#exception when raising an existing Exception object" do
+ ScratchPad.record []
+ existing = KernelSpecs::TestException.new true
+ begin
+ raise existing
+ rescue => e
+ ScratchPad << e
+ end
+ ScratchPad.recorded[0].should equal(existing)
+ ScratchPad.recorded[1..2].should == [:exception_method, "default value"]
+ ScratchPad.recorded[3].should_not equal(existing)
+ end
+
+ it "calls Exception#set_backtrace when raising an existing Exception object" do
+ ScratchPad.record []
+ existing = KernelSpecs::TestException.new false, true
+ begin
+ raise existing
+ rescue => e
+ ScratchPad << e
+ end
+ ScratchPad.recorded[0].should_not equal(existing)
+ ScratchPad.recorded[1..3].should == [:set_backtrace_method, Array, String]
+ ScratchPad.recorded[0].should equal(ScratchPad.recorded[4])
+ end
+
+ it "accepts any object responding to #exception" do
+ m = mock("non-Exception")
+ m.should_receive(:exception).and_return(KernelSpecs::TestException.new)
+ lambda { raise m }.should raise_error(KernelSpecs::TestException)
+ end
+
+ it "requires #exception to return an Exception" do
+ m = mock("non-Exception")
+ m.should_receive(:exception).and_return(m)
+ lambda { raise m }.should raise_error(TypeError)
+ end
+
+ it "requires an object responding to #exception" do
+ m = mock("non-Exception")
+ lambda { raise m }.should raise_error(TypeError)
+ end
end
===================================================================