Browse Source

Update: support method call

AnnulusGames 1 year ago
parent
commit
98ef85369b

+ 26 - 8
sandbox/ConsoleApp1/LVec3.cs

@@ -1,25 +1,43 @@
+using System.Numerics;
 using Lua;
 using Lua;
 
 
-[LuaObject("vec3")]
+[LuaObject]
 public partial class LVec3
 public partial class LVec3
 {
 {
+    Vector3 value;
+
     [LuaMember("x")]
     [LuaMember("x")]
-    public double X { get; set; }
+    public float X
+    {
+        get => value.X;
+        set => this.value = this.value with { X = value };
+    }
 
 
     [LuaMember("y")]
     [LuaMember("y")]
-    public double Y { get; set; }
+    public float Y
+    {
+        get => value.Y;
+        set => this.value = this.value with { Y = value };
+    }
 
 
     [LuaMember("z")]
     [LuaMember("z")]
-    public double Z { get; set; }
+    public float Z
+    {
+        get => value.Z;
+        set => this.value = this.value with { Z = value };
+    }
 
 
     [LuaMember("create")]
     [LuaMember("create")]
-    public static LVec3 Create(double x, double y, double z)
+    public static LVec3 Create(float x, float y, float z)
     {
     {
         return new LVec3()
         return new LVec3()
         {
         {
-            X = x,
-            Y = y,
-            Z = z,
+            value = new Vector3(x, y, z)
         };
         };
     }
     }
+
+    public override string ToString()
+    {
+        return value.ToString();
+    }
 }
 }

+ 2 - 0
sandbox/ConsoleApp1/Program.cs

@@ -7,6 +7,8 @@ using Lua.Standard;
 var state = LuaState.Create();
 var state = LuaState.Create();
 state.OpenStandardLibraries();
 state.OpenStandardLibraries();
 
 
+state.Environment["vec3"] = new LVec3().AsLuaValue();
+
 try
 try
 {
 {
     var source = File.ReadAllText("test.lua");
     var source = File.ReadAllText("test.lua");

+ 64 - 3
src/Lua.SourceGenerator/LuaObjectGenerator.Emit.cs

@@ -96,6 +96,11 @@ partial class LuaObjectGenerator
 
 
 """, false);
 """, false);
 
 
+            if (!TryEmitMethods(typeMetadata, builder, context))
+            {
+                return false;
+            }
+
             if (!TryEmitIndexMetamethod(typeMetadata, builder, context))
             if (!TryEmitIndexMetamethod(typeMetadata, builder, context))
             {
             {
                 return false;
                 return false;
@@ -147,7 +152,12 @@ partial class LuaObjectGenerator
                     }
                     }
                 }
                 }
 
 
-                builder.AppendLine(@$"_ => throw new global::Lua.LuaRuntimeException(context.State.GetTraceback(), $""{typeMetadata.LuaTypeName}.{{key}} not found.""),");
+                foreach (var methodMetadata in typeMetadata.Methods)
+                {
+                    builder.AppendLine(@$"""{methodMetadata.LuaMemberName}"" => new global::Lua.LuaValue(__function_{methodMetadata.LuaMemberName}),");
+                }
+
+                builder.AppendLine(@$"_ => global::Lua.LuaValue.Nil,");
             }
             }
             builder.AppendLine(";");
             builder.AppendLine(";");
 
 
@@ -180,7 +190,7 @@ partial class LuaObjectGenerator
                     {
                     {
                         if (propertyMetadata.IsReadOnly)
                         if (propertyMetadata.IsReadOnly)
                         {
                         {
-                            builder.AppendLine($@"throw new global::Lua.LuaRuntimeException(context.State.GetTraceback(), $""{typeMetadata.LuaTypeName}.{{key}}cannot overwrite."");");
+                            builder.AppendLine($@"throw new global::Lua.LuaRuntimeException(context.State.GetTraceback(), $""'{{key}}' cannot overwrite."");");
                         }
                         }
                         else if (propertyMetadata.IsStatic)
                         else if (propertyMetadata.IsStatic)
                         {
                         {
@@ -195,11 +205,21 @@ partial class LuaObjectGenerator
                     }
                     }
                 }
                 }
 
 
+                foreach (var methodMetadata in typeMetadata.Methods)
+                {
+                    builder.AppendLine(@$"case ""{methodMetadata.LuaMemberName}"":");
+
+                    using (builder.BeginIndentScope())
+                    {
+                        builder.AppendLine($@"throw new global::Lua.LuaRuntimeException(context.State.GetTraceback(), $""'{{key}}' cannot overwrite."");");
+                    }
+                }
+
                 builder.AppendLine(@$"default:");
                 builder.AppendLine(@$"default:");
 
 
                 using (builder.BeginIndentScope())
                 using (builder.BeginIndentScope())
                 {
                 {
-                    builder.AppendLine(@$"throw new global::Lua.LuaRuntimeException(context.State.GetTraceback(), $""{typeMetadata.LuaTypeName}.{{key}} not found."");");
+                    builder.AppendLine(@$"throw new global::Lua.LuaRuntimeException(context.State.GetTraceback(), $""'{{key}}'  not found."");");
                 }
                 }
             }
             }
 
 
@@ -211,4 +231,45 @@ partial class LuaObjectGenerator
         return true;
         return true;
     }
     }
 
 
+    static bool TryEmitMethods(TypeMetadata typeMetadata, CodeBuilder builder, in SourceProductionContext context)
+    {
+        builder.AppendLine();
+
+        foreach (var methodMetadata in typeMetadata.Methods)
+        {
+            builder.AppendLine($"static readonly global::Lua.LuaFunction __function_{methodMetadata.LuaMemberName} = new global::Lua.LuaFunction((context, buffer, ct) =>");
+
+            using (builder.BeginBlockScope())
+            {
+                var index = 0;
+
+                foreach (var parameter in methodMetadata.Symbol.Parameters)
+                {
+                    builder.AppendLine($"var arg{index} = context.GetArgument<{parameter.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>({index});");
+                    index++;
+                }
+
+                if (methodMetadata.IsStatic)
+                {
+                    builder.Append($"var result = {typeMetadata.FullTypeName}.{methodMetadata.Symbol.Name}(");
+                    builder.Append(string.Join(",", Enumerable.Range(0, index).Select(x => $"arg{x}")));
+                    builder.AppendLine(");");
+                }
+                else
+                {
+
+                    builder.Append($"var result = userData.{methodMetadata.Symbol.Name}(");
+                    builder.Append(string.Join(",", Enumerable.Range(1, index).Select(x => $"arg{x}")));
+                    builder.AppendLine(");");
+                }
+
+                builder.AppendLine("buffer.Span[0] = new global::Lua.LuaValue(result);");
+                builder.AppendLine("return new(1);");
+            }
+
+            builder.AppendLine(");");
+        }
+
+        return true;
+    }
 }
 }

+ 0 - 7
src/Lua.SourceGenerator/TypeMetadata.cs

@@ -10,7 +10,6 @@ internal record class TypeMetadata
     public INamedTypeSymbol Symbol { get; }
     public INamedTypeSymbol Symbol { get; }
     public string TypeName { get; }
     public string TypeName { get; }
     public string FullTypeName { get; }
     public string FullTypeName { get; }
-    public string LuaTypeName { get; }
     public PropertyMetadata[] Properties { get; }
     public PropertyMetadata[] Properties { get; }
     public MethodMetadata[] Methods { get; }
     public MethodMetadata[] Methods { get; }
 
 
@@ -22,12 +21,6 @@ internal record class TypeMetadata
         TypeName = symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
         TypeName = symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
         FullTypeName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
         FullTypeName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
 
 
-        var objectAttribute = symbol.GetAttributes().FindAttributeShortName("LuaObjectAttribute")!;
-
-        LuaTypeName = objectAttribute.ConstructorArguments.Length > 0
-            ? (string)objectAttribute.ConstructorArguments[0].Value!
-            : symbol.Name;
-
         Properties = Symbol.GetAllMembers()
         Properties = Symbol.GetAllMembers()
             .Where(x => x is (IFieldSymbol or IPropertySymbol) and { IsImplicitlyDeclared: false })
             .Where(x => x is (IFieldSymbol or IPropertySymbol) and { IsImplicitlyDeclared: false })
             .Where(x =>
             .Where(x =>