add native extensions
This commit is contained in:
parent
0e11be061b
commit
3013a338ed
|
|
@ -368,6 +368,25 @@ public class Runner : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool InvokeNative(Value target, NativeExtension extension, int argumentCount)
|
||||||
|
{
|
||||||
|
_logger.Method(extension);
|
||||||
|
if (argumentCount != extension.Parameters.Length) {
|
||||||
|
Error($"{extension} expects {extension.Parameters.Length} arguments, received {argumentCount}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var values = new Value[argumentCount];
|
||||||
|
for (int i = 0; i < argumentCount; i++) {
|
||||||
|
values[i] = Peek(-i - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack.Decimate(Stack.Position - argumentCount - 1);
|
||||||
|
Value result = extension.Callback(target, values);
|
||||||
|
Push(result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private bool Invoke(Context closure, int argumentCount)
|
private bool Invoke(Context closure, int argumentCount)
|
||||||
{
|
{
|
||||||
_logger.Method();
|
_logger.Method();
|
||||||
|
|
@ -390,9 +409,13 @@ public class Runner : IDisposable
|
||||||
{
|
{
|
||||||
Value value = Peek(-argumentCount - 1);
|
Value value = Peek(-argumentCount - 1);
|
||||||
if (!value.Is(T.Instance)) {
|
if (!value.Is(T.Instance)) {
|
||||||
Error($"Can not call {methodName} on value of {value}");
|
NativeExtension? extension = NativeExtension.Get(value.Type, methodName);
|
||||||
|
if (extension == null) {
|
||||||
|
Error($"Could not invoke {methodName} on {value}, no method or extension by that name found for this type.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return InvokeNative(value, extension, argumentCount);
|
||||||
|
}
|
||||||
|
|
||||||
Instance instance = value.Ptr.As<Instance>()!;
|
Instance instance = value.Ptr.As<Instance>()!;
|
||||||
if (instance.Values.TryGet(methodName, out Value method))
|
if (instance.Values.TryGet(methodName, out Value method))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
using Qrakhen.Qamp.Core.Collections;
|
||||||
|
using Qrakhen.Qamp.Core.Values.Objects;
|
||||||
|
|
||||||
|
namespace Qrakhen.Qamp.Core.Values;
|
||||||
|
|
||||||
|
public delegate Value ExtensionDelegate(Value target, Value[] parameters);
|
||||||
|
|
||||||
|
public class NativeExtension(
|
||||||
|
ValueType targetType,
|
||||||
|
string name,
|
||||||
|
ExtensionDelegate callback,
|
||||||
|
string[] parameters)
|
||||||
|
{
|
||||||
|
private static readonly Register<ValueType, Register<string, NativeExtension>> _register = new();
|
||||||
|
|
||||||
|
public readonly string Name = name;
|
||||||
|
public readonly ValueType TargetType = targetType;
|
||||||
|
public readonly ExtensionDelegate Callback = callback;
|
||||||
|
public readonly string[] Parameters = parameters.ToArray();
|
||||||
|
|
||||||
|
public static NativeExtension? Get(ValueType targetType, string name)
|
||||||
|
{
|
||||||
|
if (!_register.Has(targetType))
|
||||||
|
return null;
|
||||||
|
if (!_register[targetType].Has(name))
|
||||||
|
return null;
|
||||||
|
return _register[targetType][name];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Register(ValueType targetType,
|
||||||
|
string name,
|
||||||
|
ExtensionDelegate callback,
|
||||||
|
params string[] parameters)
|
||||||
|
{
|
||||||
|
if (!_register.Has(targetType))
|
||||||
|
_register.Add(targetType, new());
|
||||||
|
if (_register[targetType].Has(name))
|
||||||
|
throw new QampException($"Extension {name} already exists for type {targetType}.");
|
||||||
|
_register[targetType].Add(name, new NativeExtension(targetType, name, callback, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
static NativeExtension()
|
||||||
|
{
|
||||||
|
Register(ValueType.String, "Length", (v, p) => new Value((long)v.Ptr.As<Objects.String>()!.Value!.Length), []);
|
||||||
|
Register(ValueType.String, "IndexOf", (v, p) => new Value((long)v.Ptr.As<Objects.String>()!.Value!.IndexOf(p[0].Ptr.As<Objects.String>()!.Value!)), [ "needle" ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{TargetType}.{Name}({string.Join(", ", Parameters)}) (NativeExtension)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Qrakhen.Qamp.Core.Values.Objects;
|
||||||
|
|
||||||
|
public class Extension(ValueType targetType, Function function) : Context(function)
|
||||||
|
{
|
||||||
|
public ValueType TargetType = targetType;
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{TargetType}.{Function.Name}() (Extension)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Qrakhen.Qamp.Core.Values.Objects;
|
||||||
|
|
||||||
|
public class Native(string name) : Class(name)
|
||||||
|
{
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Name} (Native)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,8 +4,5 @@ namespace Qrakhen.Qamp.Core.Values;
|
||||||
|
|
||||||
internal static class ValueExtensions
|
internal static class ValueExtensions
|
||||||
{
|
{
|
||||||
public static Value ExecuteOperation(this Value value, Value other, OpCode operation)
|
|
||||||
{
|
|
||||||
return new Value();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue