151 lines
5.6 KiB
C#
151 lines
5.6 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using PorygonSharp.DiagnosticHandling;
|
|
using PorygonSharp.EvalValues;
|
|
|
|
namespace PorygonSharp
|
|
{
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
internal struct InternalScript
|
|
{
|
|
private readonly IntPtr _evaluator;
|
|
private readonly IntPtr _scriptVariables;
|
|
private readonly IntPtr _scriptTypes;
|
|
private readonly SharedPointer<object> _boundScript;
|
|
private readonly SharedPointer<object> _returnType;
|
|
private readonly IntPtr _scriptOptions;
|
|
internal readonly SharedPointer<Diagnostics> Diagnostics;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
internal struct SharedPointer<T>
|
|
{
|
|
private readonly IntPtr _pointer;
|
|
private readonly int _references;
|
|
|
|
public static implicit operator IntPtr(SharedPointer<T> o)
|
|
{
|
|
return o._pointer;
|
|
}
|
|
|
|
public T Unwrap()
|
|
{
|
|
return Marshal.PtrToStructure<T>(_pointer);
|
|
}
|
|
}
|
|
|
|
public class Script : IDisposable
|
|
{
|
|
private readonly IntPtr _internalScriptHandle;
|
|
private readonly InternalScript _internalScript;
|
|
|
|
private Diagnostics _diagnostics;
|
|
public Diagnostics Diagnostics => _diagnostics ?? (_diagnostics = new Diagnostics(_internalScript.Diagnostics));
|
|
public bool HasErrors => Diagnostics.HasErrors();
|
|
|
|
private static readonly RuntimeTypeHandle SetupHandle = typeof(CoreSetup).TypeHandle;
|
|
|
|
public Script(string s, ScriptOptions options = null)
|
|
{
|
|
// Ensure core setup has been called
|
|
RuntimeHelpers.RunClassConstructor(SetupHandle);
|
|
|
|
var optionsPointer = options?.GetRawPointer() ?? IntPtr.Zero;
|
|
_internalScriptHandle = Create(s, optionsPointer);
|
|
_internalScript = Marshal.PtrToStructure<InternalScript>(_internalScriptHandle);
|
|
}
|
|
|
|
private Script(IntPtr ptr)
|
|
{
|
|
_internalScriptHandle = ptr;
|
|
_internalScript = Marshal.PtrToStructure<InternalScript>(_internalScriptHandle);
|
|
}
|
|
|
|
public static Script Clone(Script script)
|
|
{
|
|
// Ensure core setup has been called
|
|
RuntimeHelpers.RunClassConstructor(SetupHandle);
|
|
return new Script(CloneScript(script._internalScriptHandle));
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Marshal.FreeHGlobal(_internalScriptHandle);
|
|
}
|
|
|
|
internal IntPtr GetRawPointer()
|
|
{
|
|
return _internalScriptHandle;
|
|
}
|
|
|
|
public EvalValue Evaluate()
|
|
{
|
|
var ptr = Evaluate(_internalScriptHandle);
|
|
using (var result = new EvaluateResult(ptr))
|
|
{
|
|
if (result.IsSuccess())
|
|
{
|
|
return result.GetValue();
|
|
}
|
|
throw new EvaluationException(result.GetError());
|
|
}
|
|
}
|
|
|
|
public bool HasVariable(string key)
|
|
{
|
|
return HasVariable(_internalScriptHandle, key);
|
|
}
|
|
|
|
public EvalValue GetVariable(string key)
|
|
{
|
|
var ptr = GetVariable(_internalScriptHandle, key);
|
|
return new EvalValue(ptr);
|
|
}
|
|
|
|
public bool HasFunction(string key)
|
|
{
|
|
return HasFunction(_internalScriptHandle, key);
|
|
}
|
|
|
|
public EvalValue CallFunction(string key, params object[] parameters)
|
|
{
|
|
var scriptParameters = parameters.Select(x => EvalValueCreator.CreateValue(x).GetPointer()).ToArray();
|
|
var ptr = CallFunction(_internalScriptHandle, key, scriptParameters, scriptParameters.Length);
|
|
foreach (var parameter in scriptParameters)
|
|
{
|
|
Marshal.FreeHGlobal(parameter);
|
|
}
|
|
using (var result = new EvaluateResult(ptr))
|
|
{
|
|
if (result.IsSuccess())
|
|
{
|
|
return result.GetValue();
|
|
}
|
|
throw new EvaluationException(result.GetError());
|
|
}
|
|
}
|
|
|
|
[DllImport("PorygonLang", EntryPoint = "CreateScript", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr Create([MarshalAs(UnmanagedType.LPWStr)]string s, IntPtr options);
|
|
[DllImport("PorygonLang", EntryPoint = "EvaluateScript", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr Evaluate(IntPtr script);
|
|
[DllImport("PorygonLang", EntryPoint = "HasVariable", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool HasVariable(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key);
|
|
[DllImport("PorygonLang", EntryPoint = "GetVariable", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr GetVariable(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key);
|
|
|
|
[DllImport("PorygonLang", EntryPoint = "HasFunction", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool HasFunction(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key);
|
|
|
|
[DllImport("PorygonLang", EntryPoint = "CallFunction", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr CallFunction(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key,
|
|
IntPtr[] parameters, int parameterCount);
|
|
|
|
[DllImport("PorygonLang", EntryPoint = "CloneScript", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr CloneScript(IntPtr script);
|
|
|
|
|
|
}
|
|
} |