edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C735797
File: RubyTests.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C735797  (server)    2/6/2009 6:01 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;StackTraces1
@@ -505,6 +505,7 @@
                 Backtrace1,
                 Backtrace2,
                 Backtrace3,
+                Backtrace4,
             };
         }
     }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/BacktraceTests.cs;C633889
File: BacktraceTests.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/BacktraceTests.cs;C633889  (server)    2/6/2009 6:01 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/BacktraceTests.cs;StackTraces1
@@ -14,6 +14,7 @@
  * ***************************************************************************/
 
 using Microsoft.Scripting;
+using System;
 namespace IronRuby.Tests {
     public partial class Tests {
         private bool PreciseTraces {
@@ -50,7 +51,7 @@
 Backtrace1.rb:10:in `bar'
 Backtrace1.rb:6:in `foo'
 Backtrace1.rb:2:in `goo'
-:0
+Backtrace1.rb:0
 ");
         }
 
@@ -90,7 +91,7 @@
 Backtrace2.rb:10:in `bar'
 Backtrace2.rb:6:in `foo'
 Backtrace2.rb:2:in `goo'
-:0
+Backtrace2.rb:0
 ");
         }
 
@@ -134,8 +135,49 @@
 Backtrace3.rb:12:in `bar'
 Backtrace3.rb:8:in `foo'
 Backtrace3.rb:2:in `goo'
-:0
+Backtrace3.rb:0
 ");
         }
+
+        public class ClrBacktrace {
+            public void Bar(Action d) {
+                d();
+            }
+        }
+
+        public void Backtrace4() {
+            Context.ObjectClass.SetConstant("C", Context.GetClass(typeof(ClrBacktrace)));
+            Context.ObjectClass.SetConstant("A", Context.GetClass(typeof(Action)));
+
+            AssertOutput(delegate() {
+                CompilerTest(@"
+def goo
+  puts caller[0..4]
+end
+
+def baz
+  goo
+end
+
+def foo
+  C.new.bar(A.new { baz })
+end
+
+foo
+");
+            }, PreciseTraces ? @"
+Backtrace4.rb:7:in `baz'
+Backtrace4.rb:11:in `foo'
+*.cs:*:in `Bar'
+Backtrace4.rb:11:in `foo'
+Backtrace4.rb:14
+" : @"
+Backtrace4.rb:6:in `baz'
+Backtrace4.rb:11:in `foo'
+:0:in `Bar'
+Backtrace4.rb:10:in `foo'
+Backtrace4.rb:0
+", OutputFlags.Match);
+        }
     }
 }
\ No newline at end of file
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/AstGenerator.cs;C734117
File: AstGenerator.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/AstGenerator.cs;C734117  (server)    2/6/2009 6:01 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/AstGenerator.cs;StackTraces1
@@ -794,22 +794,6 @@
         internal virtual void TraceCallSite(Expression/*!*/ expression, MSA.DynamicExpression/*!*/ callSite) {
         }
 
-        internal string/*!*/ EncodeMethodName(string/*!*/ name, SourceSpan location) {
-            string encoded = name;
-
-            // TODO: hack
-            // encodes line number, file name into the method name
-#if !SILVERLIGHT && !DEBUG
-            if (!_debugMode)
-#endif
-            {
-                string fileName = _sourceUnit.HasPath ? Path.GetFileName(_sourceUnit.Path) : String.Empty;
-                encoded = String.Format("{0};{1};{2}", encoded, fileName, location.Start.Line);
-            }
-
-            return String.IsNullOrEmpty(encoded) ? RubyExceptionData.TopLevelMethodName : encoded;
-        }
-
         internal MSA.Expression/*!*/ TryCatchAny(MSA.Expression/*!*/ tryBody, MSA.Expression/*!*/ catchBody) {
             var variable = CurrentScope.DefineHiddenVariable("#value", tryBody.Type);
 
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs;C667392
File: BlockDefinition.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs;C667392  (server)    2/6/2009 6:01 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs;StackTraces1
@@ -176,7 +176,7 @@
                 Ast.Lambda(
                     BlockDispatcher.GetDelegateType(parameterCount, attributes),
                     body,
-                    gen.EncodeMethodName(gen.CurrentMethod.MethodName, Location), 
+                    RubyExceptionData.EncodeMethodName(gen.SourceUnit, gen.CurrentMethod.MethodName, Location), 
                     new ReadOnlyCollection<MSA.ParameterExpression>(parameters)
                 ),
                 Ast.Constant(parameterCount),
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C700904
File: SourceUnitTree.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C700904  (server)    2/6/2009 6:01 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;StackTraces1
@@ -200,7 +200,7 @@
 
             return Ast.Lambda<T>(
                 body,
-                RubyExceptionData.TopLevelMethodName,
+                RubyExceptionData.EncodeMethodName(gen.SourceUnit, RubyExceptionData.TopLevelMethodName, SourceSpan.None),
                 parameters
             );
         }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs;C656583
File: MethodDeclaration.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs;C656583  (server)    2/6/2009 6:01 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs;StackTraces1
@@ -82,7 +82,7 @@
         }
 
         private MSA.Expression/*!*/ TransformBody(AstGenerator/*!*/ gen, MSA.Expression/*!*/ methodDefinitionVariable) {
-            string encodedName = gen.EncodeMethodName(_name, Location);
+            string encodedName = RubyExceptionData.EncodeMethodName(gen.SourceUnit, _name, Location);
             
             ScopeBuilder scope = new ScopeBuilder();
             MSA.Expression parentScope = gen.CurrentScopeVariable;
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C700904
File: RubyExceptionData.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C700904  (server)    2/6/2009 6:01 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;StackTraces1
@@ -25,6 +25,9 @@
 using Microsoft.Scripting.Interpretation;
 using System.Linq.Expressions;
 using System.Threading;
+using System.IO;
+using Microsoft.Scripting;
+using IronRuby.Compiler;
 
 namespace IronRuby.Runtime {
     /// <summary>
@@ -33,7 +36,7 @@
     [Serializable]
     public class RubyExceptionData {
         private static readonly object/*!*/ _DataKey = new object();
-        internal const string TopLevelMethodName = "#top-level-method#";
+        internal const string TopLevelMethodName = "#";
 
         // owner exception, needed for lazy initialization of message, backtrace
         private Exception/*!*/ _exception;
@@ -218,11 +221,10 @@
 
             if (stackTrace != null) {
                 foreach (StackFrame frame in stackTrace) {
-                    if (IsVisibleFrame(frame.GetMethod()) || exceptionDetail) {
+                    string methodName, file;
+                    int line;
+                    if (TryGetStackFrameInfo(frame, hasFileAccessPermission, exceptionDetail, out methodName, out file, out line)) {
                         if (skipFrames == 0) {
-                            string methodName, file;
-                            int line;
-                            GetStackFrameInfo(frame, hasFileAccessPermission, out methodName, out file, out line);
                             result.Add(MutableString.Create(FormatFrame(file, line, methodName)));
                         } else {
                             skipFrames--;
@@ -242,7 +244,7 @@
             }
         }
 
-        private static void GetStackFrameInfo(StackFrame/*!*/ frame, bool hasFileAccessPermission, 
+        private static bool TryGetStackFrameInfo(StackFrame/*!*/ frame, bool hasFileAccessPermission, bool exceptionDetail,
             out string/*!*/ methodName, out string/*!*/ fileName, out int line) {
 
             MethodBase method = frame.GetMethod();
@@ -255,71 +257,45 @@
             fileName = (hasFileAccessPermission) ? frame.GetFileName() : null;
             line = frame.GetFileLineNumber();
 #endif
-            if (!TryParseRubyMethodName(ref methodName, ref fileName, ref line)) {
+            if (TryParseRubyMethodName(ref methodName, ref fileName, ref line)) {
+                // Ruby method:
+                if (methodName == TopLevelMethodName) {
+                    methodName = null;
+                }
+                return true;
+            } else if (method.IsDefined(typeof(RubyStackTraceHiddenAttribute), false)) {
+                return false;
+            } else {
                 object[] attrs = method.GetCustomAttributes(typeof(RubyMethodAttribute), false);
                 if (attrs.Length > 0) {
+                    // Ruby library method:
                     // TODO: aliases
                     methodName = ((RubyMethodAttribute)attrs[0]).Name;
-                }
-            }
-
-            if (methodName.StartsWith(TopLevelMethodName)) {
-                methodName = null;
-            }
-
+                    fileName = null;
+                    line = 0;
+                    return true;
+                } else if (exceptionDetail || IsVisibleClrFrame(method)) {
+                    // Visible CLR method:
 #if !SILVERLIGHT
-            if (String.IsNullOrEmpty(fileName)) {
-                if (method.DeclaringType != null) {
-                    fileName = (hasFileAccessPermission) ? method.DeclaringType.Assembly.GetName().Name : null;
-                    line = 0;
-                }
-            }
+                    if (String.IsNullOrEmpty(fileName)) {
+                        if (method.DeclaringType != null) {
+                            fileName = (hasFileAccessPermission) ? method.DeclaringType.Assembly.GetName().Name : null;
+                            line = 0;
+                        }
+                    }
 #endif
-        }
-
-        // {method-name};{file-name};{line-number}${dlr-suffix}
-        private static bool TryParseRubyMethodName(ref string methodName, ref string fileName, ref int line) {
-            int dollar = methodName.IndexOf('$'); // TODO: no support in DLR
-            if (dollar != -1) {
-                string[] parts = methodName.Substring(0, dollar).Split(';');
-                methodName = parts[0];
-                if (parts.Length == 3) {
-                    if (fileName == null) {
-                        fileName = parts[1];
-                    }
-                    if (line == 0) {
-                        line = Int32.Parse(parts[2]);
-                    }
+                    return true;
+                } else {
+                    // Invisible CLR method:
+                    return false;
                 }
-                return true;
-            } else {
-                return false;
             }
         }
 
-        private static string ParseRubyMethodName(string/*!*/ lambdaName) {
-            if (lambdaName.StartsWith(TopLevelMethodName)) {
-                return null;
-            }
-
-            int idx = lambdaName.IndexOf(';');
-            if (idx < 0) {
-                return lambdaName;
-            }
-
-            return lambdaName.Substring(0, idx);
-        }
-
-        // TODO: better filtering in DLR
-        private static bool IsVisibleFrame(MethodBase/*!*/ method) {
-            // filter out the _stub_ methods
-            if (method.Name.StartsWith("_stub_")) {
-                return false;
-            }
-                
+        private static bool IsVisibleClrFrame(MethodBase/*!*/ method) {
             Type type = method.DeclaringType;
-
             if (type != null) {
+                // TODO: better filtering
                 string typeName = type.FullName;
                 if (typeName.StartsWith("System.Reflection.") ||
                     typeName.StartsWith("System.Runtime") ||
@@ -328,23 +304,54 @@
                     return false;
                 }
 
-                // TODO: check loaded assemblies
                 if (type.Assembly == typeof(RubyOps).Assembly) {
                     return false;
                 }
 
-                if (method.IsDefined(typeof(RubyStackTraceHiddenAttribute), false)) {
-                    return false;
+                // TODO: check loaded assemblies?
+                return true;
+            } else {
+                // TODO: hide dynamic methods:
+                return Methods.DefineMethod.GetType() == method.GetType();
+            }
+        }
+
+        private const string RubyMethodPrefix = "\u2111\u211c;";
+
+        internal static string/*!*/ EncodeMethodName(SourceUnit/*!*/ sourceUnit, string/*!*/ methodName, SourceSpan location) {
+            // encodes line number, file name into the method name
+            string fileName = sourceUnit.HasPath ? Path.GetFileName(sourceUnit.Path) : String.Empty;
+            return String.Format(RubyMethodPrefix + "{0};{1};{2};", methodName, fileName, location.IsValid ? location.Start.Line : 0);
+        }
+
+        // \u2111\u211c;{method-name};{file-name};{line-number};{dlr-suffix}
+        private static bool TryParseRubyMethodName(ref string methodName, ref string fileName, ref int line) {
+            if (methodName.StartsWith(RubyMethodPrefix)) {
+                string[] parts = methodName.Split(';');
+                if (parts.Length > 4) {
+                    methodName = parts[1];
+                    if (fileName == null) {
+                        fileName = parts[2];
+                    }
+                    if (line == 0) {
+                        line = Int32.Parse(parts[3]);
+                    }
+                    return true;
                 }
-                 
-                if (type.Assembly.IsDefined(typeof(RubyLibraryAttribute), false)) {
-                    return method.IsDefined(typeof(RubyMethodAttribute), false);
-                }
             }
-                
-            return true;
+            return false;
         }
 
+        private static string ParseRubyMethodName(string/*!*/ lambdaName) {
+            if (!lambdaName.StartsWith(RubyMethodPrefix)) {
+                return lambdaName;
+            }
+
+            int nameEnd = lambdaName.IndexOf(';', RubyMethodPrefix.Length);
+            string name = lambdaName.Substring(RubyMethodPrefix.Length, nameEnd - RubyMethodPrefix.Length);
+            return (name != TopLevelMethodName) ? name : null;
+        }
+
         /// <summary>
         /// Gets the instance data associated with the exception
         /// </summary>
===================================================================
