yanghuan / CSharp.lua

The C# to Lua compiler
Other
1.23k stars 202 forks source link

Namespace used before it is assigned when ref and stackalloc are used #459

Closed joelverhagen closed 10 months ago

joelverhagen commented 10 months ago

Repro:

namespace MyNamespace;

public static class Class1
{
    public static void MyMethod(ContainerThing sharedInstances)
    {
        RefTest(ref sharedInstances.LocationArray);
        Span<Location> neighbors = stackalloc Location[4];
    }

    private static void RefTest(ref Location[] locations)
    {
        locations = new Location[1];
    }
}

public class ContainerThing
{
    public Location[] LocationArray = new Location[0];
}

public struct Location
{
    public int X;
}

Generated Lua:

do
local System = System
local ArrayLocation = System.Array(MyNamespace.Location) -- this is the problem, MyNamespace is not assigned yet
local MyNamespace
local SpanLocation
System.import(function (out)
  MyNamespace = out.MyNamespace
  SpanLocation = System.Span(MyNamespace.Location)
end)
System.namespace("MyNamespace", function (namespace)
  namespace.class("Class1", function (namespace)
    local MyMethod, RefTest
    MyMethod = function (sharedInstances)
      sharedInstances.LocationArray = RefTest(sharedInstances.LocationArray)
      local neighbors = SpanLocation(ArrayLocation(4))
    end
    RefTest = function (locations)
      locations = ArrayLocation(1)
      return locations
    end
    return {
      MyMethod = MyMethod
    }
  end)

  namespace.class("ContainerThing", function (namespace)
    local __ctor__
    __ctor__ = function (this)
      this.LocationArray = ArrayLocation(0)
    end
    return {
      __ctor__ = __ctor__
    }
  end)

  namespace.struct("Location", function (namespace)
    return {
      X = 0
    }
  end)
end)

end
System.init({
  types = {
    "MyNamespace.Class1",
    "MyNamespace.ContainerThing",
    "MyNamespace.Location"
  }
})

Error when calling the Lua:

require("out")

print(MyNamespace.Class1.MyMethod(nil))
C:\Users\joelv\Downloads\lua-5.3.6_Win64_bin\lua53.exe: .\out.lua:19533: attempt to index a nil value (global 'MyNamespace')
stack traceback:
        .\out.lua:19533: in main chunk
        [C]: in function 'require'
        .\main.lua:1: in main chunk
        [C]: in ?
joelverhagen commented 10 months ago

It seems to happen with a List<Location> (list of structs) return value to. Example:

namespace Knapcode.FactorioTools.OilField.Algorithms;

public static class BreadthFirstFinder
{
    public static List<Location>? GetShortestPath(Location start, Location goal)
    {
        Span<Location> neighbors = stackalloc Location[4];
        return null;
    }
}

public struct Location
{
    public int X;
}

Generated Lua:

-- Generated by CSharp.lua Compiler
do
local System = System
local ArrayLocation = System.Array(KnapcodeAlgorithms.Location)
local KnapcodeAlgorithms
local SpanLocation
System.import(function (out)
  KnapcodeAlgorithms = Knapcode.FactorioTools.OilField.Algorithms
  SpanLocation = System.Span(KnapcodeAlgorithms.Location)
end)
System.namespace("Knapcode.FactorioTools.OilField.Algorithms", function (namespace)
  namespace.class("BreadthFirstFinder", function (namespace)
    local GetShortestPath
    GetShortestPath = function (start, goal)
      local neighbors = SpanLocation(ArrayLocation(4))
      return nil
    end
    return {
      GetShortestPath = GetShortestPath
    }
  end)

  namespace.struct("Location", function (namespace)
    return {
      X = 0
    }
  end)
end)

end
System.init({
  types = {
    "Knapcode.FactorioTools.OilField.Algorithms.BreadthFirstFinder",
    "Knapcode.FactorioTools.OilField.Algorithms.Location"
  }
})
joelverhagen commented 10 months ago

I wonder if my PR https://github.com/yanghuan/CSharp.lua/pull/452 is broken.

joelverhagen commented 10 months ago

I have worked around the problem by not using stackalloc in my C# and just initializing the array on the heap.