Skip to content

Commit

Permalink
[dotnet] Add storage of exception handlers per block, sketch out a co…
Browse files Browse the repository at this point in the history
…uple of ops for searching for exception handlers lexically and dynamically and a few other bits of stubbing in.
  • Loading branch information
jnthn committed Oct 22, 2010
1 parent c556af5 commit 3d934db
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 0 deletions.
10 changes: 10 additions & 0 deletions dotnet/runtime/Metamodel/Representations/RakudoCodeRef.cs
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using Rakudo.Runtime;
using Rakudo.Runtime.Exceptions;

namespace Rakudo.Metamodel.Representations
{
Expand Down Expand Up @@ -42,7 +43,16 @@ public sealed class Instance : RakudoObject
/// The context currently using this sub.
/// </summary>
public Context CurrentContext;

/// <summary>
/// Exception handlers this block has, if any.
/// </summary>
public Handler[] Handlers;

/// <summary>
/// Creates a new instance with the given S-Table.
/// </summary>
/// <param name="STable"></param>
public Instance(SharedTable STable)
{
this.STable = STable;
Expand Down
3 changes: 3 additions & 0 deletions dotnet/runtime/Rakudo.Net.csproj
Expand Up @@ -59,6 +59,9 @@
<Compile Include="Metamodel\Representations\RakudoCodeRef.cs" />
<Compile Include="Metamodel\REPRRegistry.cs" />
<Compile Include="Runtime\Context.cs" />
<Compile Include="Runtime\Exceptions\ExceptionDispatcher.cs" />
<Compile Include="Runtime\Exceptions\ExceptionType.cs" />
<Compile Include="Runtime\Exceptions\Handler.cs" />
<Compile Include="Runtime\Exceptions\LeaveStackUnwinderException.cs" />
<Compile Include="Runtime\ExecutionDomain.cs" />
<Compile Include="Metamodel\KnowHOW\KnowHOWBootstrapper.cs" />
Expand Down
51 changes: 51 additions & 0 deletions dotnet/runtime/Runtime/Exceptions/ExceptionDispatcher.cs
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rakudo.Metamodel;

namespace Rakudo.Runtime.Exceptions
{
/// <summary>
/// Various bits of logic relating to exception dispatch.
/// </summary>
public static class ExceptionDispatcher
{
/// <summary>
/// Invokes the specified exception handler with the given exception
/// object.
/// </summary>
/// <param name="Handler"></param>
/// <param name="ExceptionObject"></param>
/// <returns></returns>
public static RakudoObject CallHandler(ThreadContext TC, RakudoObject Handler, RakudoObject ExceptionObject)
{
throw new NotImplementedException();
}

/// <summary>
/// Dies from an unhandled exception.
/// </summary>
/// <param name="Exception"></param>
public static void DieFromUnhandledException(ThreadContext TC, RakudoObject Exception)
{
// Try to stringify the exception object.
try
{
var StrMeth = Exception.STable.FindMethod(TC, Exception, "Str", Hints.NO_HINT);
var Stringified = StrMeth.STable.Invoke(TC, StrMeth, CaptureHelper.FormWith(new RakudoObject[] { Exception }));
Console.WriteLine(Ops.unbox_str(TC, Stringified));
}
catch
{
Console.Error.WriteLine("Died from an exception, and died trying to stringify it too.");
}

// We'll also write a stack trace. It's a .Net one for now.
Console.Error.Write(new Exception().StackTrace);

// Exit with an error code.
Environment.Exit(1);
}
}
}
28 changes: 28 additions & 0 deletions dotnet/runtime/Runtime/Exceptions/ExceptionType.cs
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Rakudo.Runtime.Exceptions
{
/// <summary>
/// Various types of exceptions that can occur. (The constant values
/// match those used in Parrot for the control exceptions. Maybe that'll
/// be OK, maybe we should encapsulate things a bit more. We'll see.)
/// </summary>
public static class ExceptionType
{
public const int NORMAL = 0;
public const int CONTROL_RETURN = 57;
public const int CONTROL_OK = 58;
public const int CONTROL_BREAK = 59;
public const int CONTROL_CONTINUE = 60;
public const int CONTROL_ERROR = 61;
public const int CONTROL_TAKE = 62;
public const int CONTROL_LEAVE = 63;
public const int CONTROL_EXIT = 64;
public const int CONTROL_LOOP_NEXT = 65;
public const int CONTROL_LOOP_LAST = 66;
public const int CONTROL_LOOP_REDO = 67;
}
}
21 changes: 21 additions & 0 deletions dotnet/runtime/Runtime/Exceptions/Handler.cs
@@ -0,0 +1,21 @@
using System;
using Rakudo.Metamodel;

namespace Rakudo.Runtime.Exceptions
{
/// <summary>
/// Represents an exception handler.
/// </summary>
public struct Handler
{
/// <summary>
/// The type of exception that the handler accepts.
/// </summary>
public int Type;

/// <summary>
/// Something invokable that will handle the exception.
/// </summary>
public RakudoObject HandleBlock;
}
}
52 changes: 52 additions & 0 deletions dotnet/runtime/Runtime/Ops.cs
Expand Up @@ -688,5 +688,57 @@ public static RakudoObject leave_block(ThreadContext TC, RakudoObject Block, Rak
{
throw new Exceptions.LeaveStackUnwinderException(Block as RakudoCodeRef.Instance, ReturnValue);
}

/// <summary>
/// Throws the specified exception, looking for an exception handler in the
/// dynmaic scope.
/// </summary>
/// <param name="TC"></param>
/// <param name="ExceptionObject"></param>
/// <param name="ExceptionType"></param>
/// <returns></returns>
public static RakudoObject throw_dynamic(ThreadContext TC, RakudoObject ExceptionObject, RakudoObject ExceptionType)
{
int WantType = Ops.unbox_int(TC, ExceptionType);
var CurContext = TC.CurrentContext;
while (CurContext != null)
{
var Handlers = CurContext.StaticCodeObject.Handlers;
if (Handlers != null)
for (int i = 0; i < Handlers.Length; i++)
if (Handlers[i].Type == WantType)
return Exceptions.ExceptionDispatcher.CallHandler(TC,
Handlers[i].HandleBlock, ExceptionObject);
CurContext = CurContext.Caller;
}
Exceptions.ExceptionDispatcher.DieFromUnhandledException(TC, ExceptionObject);
return null; // Unreachable; above call exits always.
}

/// <summary>
/// Throws the specified exception, looking for an exception handler in the
/// lexical scope.
/// </summary>
/// <param name="TC"></param>
/// <param name="ExceptionObject"></param>
/// <param name="ExceptionType"></param>
/// <returns></returns>
public static RakudoObject throw_lexical(ThreadContext TC, RakudoObject ExceptionObject, RakudoObject ExceptionType)
{
int WantType = Ops.unbox_int(TC, ExceptionType);
var CurContext = TC.CurrentContext;
while (CurContext != null)
{
var Handlers = CurContext.StaticCodeObject.Handlers;
if (Handlers != null)
for (int i = 0; i < Handlers.Length; i++)
if (Handlers[i].Type == WantType)
return Exceptions.ExceptionDispatcher.CallHandler(TC,
Handlers[i].HandleBlock, ExceptionObject);
CurContext = CurContext.Outer;
}
Exceptions.ExceptionDispatcher.DieFromUnhandledException(TC, ExceptionObject);
return null; // Unreachable; above call exits always.
}
}
}

0 comments on commit 3d934db

Please sign in to comment.