144 lines
4.4 KiB
C#
144 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using KitsuneCafe.Sys;
|
|
using UnityEngine;
|
|
using Wacs.Core.Runtime;
|
|
using Wacs.Core.Runtime.Types;
|
|
|
|
namespace KitsuneCafe.Scripting
|
|
{
|
|
public class RuntimeInstance
|
|
{
|
|
public const string DefaultStartFunction = "main";
|
|
|
|
public readonly WasmRuntime Runtime;
|
|
public readonly Runtime Asset;
|
|
public readonly IDictionary<BindingPath, IFunctionState> State;
|
|
|
|
public RuntimeInstance(WasmRuntime runtime, Runtime asset, IDictionary<BindingPath, IFunctionState> state)
|
|
{
|
|
Runtime = runtime;
|
|
Asset = asset;
|
|
State = state;
|
|
}
|
|
|
|
public IResult<Unit, Exception> Invoke(FuncAddr addr, InvokerOptions options = null)
|
|
{
|
|
var caller = Runtime.CreateInvokerAction(addr, options);
|
|
try
|
|
{
|
|
caller();
|
|
return Result.Ok<Unit, Exception>(default);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
return Result.Err<Unit, Exception>(e);
|
|
}
|
|
}
|
|
|
|
public IResult<T, Exception> Invoke<T>(FuncAddr addr, InvokerOptions options = null)
|
|
{
|
|
var caller = Runtime.CreateInvokerFunc<T>(addr, options);
|
|
try
|
|
{
|
|
T value = caller();
|
|
return Result.Ok<T, Exception>(default);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
return Result.Err<T, Exception>(e);
|
|
}
|
|
}
|
|
|
|
public IResult<Unit, Exception> Invoke(BindingPath path, InvokerOptions options = null)
|
|
{
|
|
if (Runtime.TryGetExportedFunction(path, out var addr))
|
|
{
|
|
return Invoke(addr, options);
|
|
}
|
|
|
|
return Result.Err<Unit, Exception>(new ArgumentException($"No such function \"{path}\""));
|
|
}
|
|
|
|
public IResult<T, Exception> Invoke<T>(BindingPath path, InvokerOptions options = null)
|
|
{
|
|
if (Runtime.TryGetExportedFunction(path, out var addr))
|
|
{
|
|
return Invoke<T>(addr, options);
|
|
}
|
|
|
|
return Result.Err<T, Exception>(new ArgumentException($"No such function \"{path}\""));
|
|
}
|
|
|
|
public IResult<Unit, Exception> Start(ModuleInstance module, InvokerOptions options = null)
|
|
{
|
|
return Invoke(module.StartFunc, options);
|
|
}
|
|
|
|
public IResult<Unit, Exception> Start(string moduleName, InvokerOptions options = null)
|
|
{
|
|
return Start(Runtime.GetModule(moduleName), options);
|
|
}
|
|
|
|
public IResult<Unit, Exception> Start(Module module, InvokerOptions options = null)
|
|
{
|
|
return Start(module.Name, options);
|
|
}
|
|
|
|
public IResult<Unit, Exception> Start(InvokerOptions options = null)
|
|
{
|
|
if (Asset.Modules.Count != 1)
|
|
{
|
|
return Result.Err<Unit, Exception>(new ArgumentException("Runtime has more than one module registered. Specify the module to start."));
|
|
}
|
|
|
|
return Start(Asset.Modules[0], options);
|
|
}
|
|
}
|
|
|
|
[CreateAssetMenu(menuName = KitsuneCafeMenu.Module + "Runtime")]
|
|
public class Runtime : ScriptableObject
|
|
{
|
|
[SerializeField]
|
|
private RuntimeAttributes attributes = new();
|
|
public RuntimeAttributes Attributes => attributes;
|
|
|
|
[SerializeField]
|
|
private List<Environment> environments = new();
|
|
public List<Environment> Environments => environments;
|
|
|
|
[SerializeField]
|
|
private List<Module> modules = new();
|
|
public List<Module> Modules => modules;
|
|
|
|
public RuntimeInstance Instantiate()
|
|
{
|
|
var runtime = new WasmRuntime(attributes);
|
|
var state = BindEnvironments(runtime);
|
|
RegisterModules(runtime);
|
|
|
|
return new RuntimeInstance(runtime, this, state);
|
|
}
|
|
|
|
private RuntimeState BindEnvironments(WasmRuntime runtime)
|
|
{
|
|
var state = new RuntimeState();
|
|
|
|
foreach (var env in environments)
|
|
{
|
|
env.Bind(runtime, state);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
private void RegisterModules(WasmRuntime runtime)
|
|
{
|
|
foreach (var module in modules)
|
|
{
|
|
var instance = module.Instantiate(runtime);
|
|
runtime.RegisterModule(module.Name, instance);
|
|
}
|
|
}
|
|
}
|
|
}
|