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)
|
||||
{
|
||||
_logger.Method();
|
||||
|
|
@ -390,8 +409,12 @@ public class Runner : IDisposable
|
|||
{
|
||||
Value value = Peek(-argumentCount - 1);
|
||||
if (!value.Is(T.Instance)) {
|
||||
Error($"Can not call {methodName} on value of {value}");
|
||||
return false;
|
||||
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 InvokeNative(value, extension, argumentCount);
|
||||
}
|
||||
|
||||
Instance instance = value.Ptr.As<Instance>()!;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
public static Value ExecuteOperation(this Value value, Value other, OpCode operation)
|
||||
{
|
||||
return new Value();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue