diff --git a/src/MoonSharp.Interpreter/CoreLib/CoroutineModule.cs b/src/MoonSharp.Interpreter/CoreLib/CoroutineModule.cs
index d405a88e..c01facc6 100644
--- a/src/MoonSharp.Interpreter/CoreLib/CoroutineModule.cs
+++ b/src/MoonSharp.Interpreter/CoreLib/CoroutineModule.cs
@@ -121,7 +121,18 @@ public static DynValue status(ScriptExecutionContext executionContext, CallbackA
}
}
-
+
+ [MoonSharpModuleMethod]
+ public static DynValue is_return_value(ScriptExecutionContext executionContext, CallbackArguments args)
+ {
+ return args[0].Type == DataType.ClrCoroutineReturn ? DynValue.True : DynValue.False;
+ }
+
+ [MoonSharpModuleMethod]
+ public static DynValue get_return_value(ScriptExecutionContext executionContext, CallbackArguments args)
+ {
+ return args[0].Type == DataType.ClrCoroutineReturn ? args[0].ClrCoroutineReturnValue : DynValue.Nil;
+ }
}
}
diff --git a/src/MoonSharp.Interpreter/DataTypes/DataType.cs b/src/MoonSharp.Interpreter/DataTypes/DataType.cs
index 46694a6e..220b2f54 100644
--- a/src/MoonSharp.Interpreter/DataTypes/DataType.cs
+++ b/src/MoonSharp.Interpreter/DataTypes/DataType.cs
@@ -64,6 +64,10 @@ public enum DataType
/// A request to coroutine.yield
///
YieldRequest,
+ ///
+ /// Return a value from a clr coroutine
+ ///
+ ClrCoroutineReturn,
}
///
@@ -114,6 +118,8 @@ public static string ToErrorTypeString(this DataType type)
return "userdata";
case DataType.Thread:
return "coroutine";
+ case DataType.ClrCoroutineReturn:
+ return "coroutine_return";
case DataType.Tuple:
case DataType.TailCallRequest:
case DataType.YieldRequest:
@@ -164,6 +170,8 @@ public static string ToLuaTypeString(this DataType type)
return "userdata";
case DataType.Thread:
return "thread";
+ case DataType.ClrCoroutineReturn:
+ return "coroutine_return";
case DataType.Tuple:
case DataType.TailCallRequest:
case DataType.YieldRequest:
diff --git a/src/MoonSharp.Interpreter/DataTypes/DynValue.cs b/src/MoonSharp.Interpreter/DataTypes/DynValue.cs
index 9df80fe0..4af0dfbf 100644
--- a/src/MoonSharp.Interpreter/DataTypes/DynValue.cs
+++ b/src/MoonSharp.Interpreter/DataTypes/DynValue.cs
@@ -76,6 +76,11 @@ public sealed class DynValue
/// Gets the tail call data.
///
public UserData UserData { get { return m_Object as UserData; } }
+
+ ///
+ /// Gets the clr couroutine return value
+ ///
+ public DynValue ClrCoroutineReturnValue { get { return m_Object as DynValue; } }
///
/// Returns true if this instance is write protected.
@@ -373,6 +378,14 @@ public static DynValue NewUserData(UserData userData)
};
}
+ public static DynValue NewClrCoroutineReturn(DynValue returnedValue) {
+ return new DynValue()
+ {
+ m_Object = returnedValue,
+ m_Type = DataType.ClrCoroutineReturn,
+ };
+ }
+
///
/// Returns this value as readonly - eventually cloning it in the process if it isn't readonly to start with.
///
diff --git a/src/MoonSharp.Interpreter/Interop/Attributes/MoonSharpClrCoroutineAttribute.cs b/src/MoonSharp.Interpreter/Interop/Attributes/MoonSharpClrCoroutineAttribute.cs
new file mode 100644
index 00000000..8a1d6261
--- /dev/null
+++ b/src/MoonSharp.Interpreter/Interop/Attributes/MoonSharpClrCoroutineAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace MoonSharp.Interpreter
+{
+ ///
+ /// Marks a method as a clr enumerator based coroutine
+ ///
+ [AttributeUsage(AttributeTargets.Method, Inherited = true)]
+ public sealed class MoonSharpClrCoroutineAttribute : Attribute
+ {
+ public MoonSharpClrCoroutineAttribute()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs b/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs
index 8867be86..18a92f62 100644
--- a/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs
+++ b/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs
@@ -178,7 +178,7 @@ private void AddMemberTo(Dictionary members, string n
{
IOverloadableMemberDescriptor odesc = desc as IOverloadableMemberDescriptor;
- if (odesc != null)
+ if (odesc != null && !(desc is MethodMemberDescriptorCoroutine))
{
if (members.ContainsKey(name))
{
diff --git a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/ReflectionMemberDescriptors/MethodMemberDescriptorCoroutine.cs b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/ReflectionMemberDescriptors/MethodMemberDescriptorCoroutine.cs
new file mode 100644
index 00000000..d1de80e2
--- /dev/null
+++ b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/ReflectionMemberDescriptors/MethodMemberDescriptorCoroutine.cs
@@ -0,0 +1,48 @@
+using System.Reflection;
+
+namespace MoonSharp.Interpreter.Interop
+{
+ public class MethodMemberDescriptorCoroutine : MethodMemberDescriptor
+ {
+ public MethodMemberDescriptorCoroutine(MethodBase methodBase, InteropAccessMode accessMode = InteropAccessMode.Default) : base(methodBase, accessMode)
+ {
+ }
+
+ public override DynValue GetValue(Script script, object obj)
+ {
+ var enumerateYielder = script.DoString(@"return function (callable)
+ return function (...)
+ for y in callable(...) do
+ if coroutine.is_return_value(y) then
+ return coroutine.get_return_value(y)
+ else
+ coroutine.yield(y)
+ end
+ end
+ end
+end", null, MethodInfo + "_yielder");
+ return script.Call(enumerateYielder, base.GetValue(script, obj));
+ }
+
+ /// Tries to create a new MethodMemberDescriptorCoroutine, returning
+ /// null in case the method is not
+ /// visible to script code.
+ ///
+ /// The MethodBase.
+ /// The
+ /// if set to true forces visibility.
+ ///
+ /// A new MethodMemberDescriptor or null.
+ ///
+ public static MethodMemberDescriptorCoroutine TryCreateCoroutineIfVisible(MethodBase methodBase, InteropAccessMode accessMode, bool forceVisibility = false)
+ {
+ if (!CheckMethodIsCompatible(methodBase, false))
+ return null;
+
+ if (forceVisibility || (methodBase.GetVisibilityFromAttributes() ?? methodBase.IsPublic))
+ return new MethodMemberDescriptorCoroutine(methodBase, accessMode);
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/StandardUserDataDescriptor.cs b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/StandardUserDataDescriptor.cs
index 6eece605..0bb97c2c 100755
--- a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/StandardUserDataDescriptor.cs
+++ b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/StandardUserDataDescriptor.cs
@@ -78,7 +78,12 @@ private void FillMemberList()
{
if (membersToIgnore.Contains(mi.Name)) continue;
- MethodMemberDescriptor md = MethodMemberDescriptor.TryCreateIfVisible(mi, this.AccessMode);
+ MethodMemberDescriptor md;
+ if (mi.CustomAttributes.Any(data => data.AttributeType == typeof(MoonSharpClrCoroutineAttribute))) {
+ md = MethodMemberDescriptorCoroutine.TryCreateCoroutineIfVisible(mi, this.AccessMode);
+ } else {
+ md = MethodMemberDescriptor.TryCreateIfVisible(mi, this.AccessMode);
+ }
if (md != null)
{