Implements new handling of exceptions

This commit is contained in:
Deukhoofd 2019-07-27 19:45:39 +02:00
parent d452a740f0
commit 4a42254b62
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
6 changed files with 101 additions and 32 deletions

View File

@ -8,14 +8,14 @@ namespace PorygonSharp
public static Action<string> Print = Console.WriteLine; public static Action<string> Print = Console.WriteLine;
private delegate void InternalPrintDelegate(IntPtr ptr); private delegate void InternalPrintDelegate(IntPtr ptr);
private static InternalPrintDelegate InternalPrint = PrintFunc; private static readonly InternalPrintDelegate InternalPrint = PrintFunc;
static CoreSetup() static CoreSetup()
{ {
SetPrintFunc(); SetPrintFunc();
} }
internal static void SetPrintFunc() private static void SetPrintFunc()
{ {
var funcPtr = Marshal.GetFunctionPointerForDelegate(InternalPrint); var funcPtr = Marshal.GetFunctionPointerForDelegate(InternalPrint);
InternalSetPrintFunc(funcPtr); InternalSetPrintFunc(funcPtr);

View File

@ -0,0 +1,47 @@
using System;
using System.Runtime.InteropServices;
namespace PorygonSharp
{
internal struct EvaluateResult : IDisposable
{
[StructLayout(LayoutKind.Sequential)]
private struct EvaluateResultInternal
{
public readonly IntPtr Value;
public readonly byte Result;
}
private readonly IntPtr _ptr;
private readonly EvaluateResultInternal _internal;
public EvaluateResult(IntPtr ptr)
{
_ptr = ptr;
_internal = Marshal.PtrToStructure<EvaluateResultInternal>(ptr);
}
public EvalValue GetValue()
{
return !IsSuccess() ? null : new EvalValue(_internal.Value);
}
public bool IsSuccess()
{
return _internal.Result == 0;
}
public string GetError()
{
return GetErrorMessage(_ptr);
}
public void Dispose()
{
Marshal.FreeHGlobal(_ptr);
}
[DllImport("libPorygonLang", EntryPoint = "GetResultError", CallingConvention = CallingConvention.Cdecl)]
private static extern string GetErrorMessage(IntPtr ptr);
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace PorygonSharp
{
public class EvaluationException : Exception
{
public EvaluationException(string message) : base(message)
{
}
}
}

View File

@ -1,7 +1,9 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security;
using PorygonSharp.DiagnosticHandling; using PorygonSharp.DiagnosticHandling;
namespace PorygonSharp namespace PorygonSharp
@ -57,15 +59,17 @@ namespace PorygonSharp
Marshal.FreeHGlobal(_internalScriptHandle); Marshal.FreeHGlobal(_internalScriptHandle);
} }
public void Evaluate() public EvalValue Evaluate()
{ {
Evaluate(_internalScriptHandle); var ptr = Evaluate(_internalScriptHandle);
using (var result = new EvaluateResult(ptr))
{
if (result.IsSuccess())
{
return result.GetValue();
}
throw new EvaluationException(result.GetError());
} }
public EvalValue GetLastValue()
{
var ptr = GetLastValue(_internalScriptHandle);
return new EvalValue(ptr);
} }
public bool HasVariable(string key) public bool HasVariable(string key)
@ -94,9 +98,7 @@ namespace PorygonSharp
[DllImport("libPorygonLang", EntryPoint = "CreateScript", CallingConvention = CallingConvention.Cdecl)] [DllImport("libPorygonLang", EntryPoint = "CreateScript", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr Create([MarshalAs(UnmanagedType.LPWStr)]string s); private static extern IntPtr Create([MarshalAs(UnmanagedType.LPWStr)]string s);
[DllImport("libPorygonLang", EntryPoint = "EvaluateScript", CallingConvention = CallingConvention.Cdecl)] [DllImport("libPorygonLang", EntryPoint = "EvaluateScript", CallingConvention = CallingConvention.Cdecl)]
private static extern void Evaluate(IntPtr script); private static extern IntPtr Evaluate(IntPtr script);
[DllImport("libPorygonLang", EntryPoint = "GetLastValue", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GetLastValue(IntPtr script);
[DllImport("libPorygonLang", EntryPoint = "HasVariable", CallingConvention = CallingConvention.Cdecl)] [DllImport("libPorygonLang", EntryPoint = "HasVariable", CallingConvention = CallingConvention.Cdecl)]
private static extern bool HasVariable(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key); private static extern bool HasVariable(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key);
[DllImport("libPorygonLang", EntryPoint = "GetVariable", CallingConvention = CallingConvention.Cdecl)] [DllImport("libPorygonLang", EntryPoint = "GetVariable", CallingConvention = CallingConvention.Cdecl)]

View File

@ -36,10 +36,9 @@ namespace PorygonSharpTests
{ {
using (var script = new Script("1+10")) using (var script = new Script("1+10"))
{ {
script.Evaluate(); var result = script.Evaluate();
var lastVal = script.GetLastValue(); Assert.AreEqual(TypeClass.Number, result.GetTypeClass());
Assert.AreEqual(TypeClass.Number, lastVal.GetTypeClass()); var val = result.EvaluateInteger();
var val = lastVal.EvaluateInteger();
Assert.AreEqual(11, val); Assert.AreEqual(11, val);
} }
} }
@ -49,10 +48,9 @@ namespace PorygonSharpTests
{ {
using (var script = new Script("1+10.24")) using (var script = new Script("1+10.24"))
{ {
script.Evaluate(); var result = script.Evaluate();
var lastVal = script.GetLastValue(); Assert.AreEqual(TypeClass.Number, result.GetTypeClass());
Assert.AreEqual(TypeClass.Number, lastVal.GetTypeClass()); var val = result.EvaluateFloat();
var val = lastVal.EvaluateFloat();
Assert.AreEqual(11.24d, val, 5); Assert.AreEqual(11.24d, val, 5);
} }
} }
@ -62,10 +60,9 @@ namespace PorygonSharpTests
{ {
using (var script = new Script("true and true")) using (var script = new Script("true and true"))
{ {
script.Evaluate(); var result = script.Evaluate();
var lastVal = script.GetLastValue(); Assert.AreEqual(TypeClass.Bool, result.GetTypeClass());
Assert.AreEqual(TypeClass.Bool, lastVal.GetTypeClass()); var val = result.EvaluateBool();
var val = lastVal.EvaluateBool();
Assert.AreEqual(true, val); Assert.AreEqual(true, val);
} }
} }
@ -75,10 +72,9 @@ namespace PorygonSharpTests
{ {
using (var script = new Script("'foo' + 'bar'")) using (var script = new Script("'foo' + 'bar'"))
{ {
script.Evaluate(); var result = script.Evaluate();
var lastVal = script.GetLastValue(); Assert.AreEqual(TypeClass.String, result.GetTypeClass());
Assert.AreEqual(TypeClass.String, lastVal.GetTypeClass()); var val = result.EvaluateString();
var val = lastVal.EvaluateString();
Assert.AreEqual("foobar", val); Assert.AreEqual("foobar", val);
} }
} }
@ -102,7 +98,9 @@ namespace PorygonSharpTests
using (var script = new Script("function add(number a, number b) result = a + b end")) using (var script = new Script("function add(number a, number b) result = a + b end"))
{ {
script.Evaluate(); script.Evaluate();
Assert.That(script.HasFunction("add"));
script.CallFunction("add", 100, 50); script.CallFunction("add", 100, 50);
var variable = script.GetVariable("result"); var variable = script.GetVariable("result");
Assert.AreEqual(TypeClass.Number, variable.GetTypeClass()); Assert.AreEqual(TypeClass.Number, variable.GetTypeClass());
var val = variable.EvaluateInteger(); var val = variable.EvaluateInteger();
@ -139,6 +137,16 @@ namespace PorygonSharpTests
} }
} }
[Test]
public void TestExceptions()
{
using (var script = new Script("error('test')"))
{
Assert.Throws<EvaluationException>(() => script.Evaluate());
}
}
[Test] [Test]
public void TestHash() public void TestHash()
{ {

Binary file not shown.