agracio / edge-js

Run .NET and Node.js code in-process on Windows, macOS, and Linux
MIT License
618 stars 93 forks source link

Support for F# #189

Closed andretrump closed 3 months ago

andretrump commented 7 months ago

I tried to use edge-js to compile F# but when I proceed as described in the README.md I frist get the error Error: Unsupported language 'fs'. To compile script in language 'fs' an npm module 'edge-fs' must be installed.

When I then install edge-fsI am informed that edge-fs is deprecated and when I run the program, I get the following error:

/Users/andre/typeprovider-test/node_modules/edge-js/lib/edge.js:177
    return edge.initializeClrFunc(options);
                ^
Error: The given assembly name was invalid.
    at exports.func (/Users/andre/typeprovider-test/node_modules/edge-js/lib/edge.js:177:17)
    at Object.<anonymous> (/Users/andre/typeprovider-test/index.js:3:20)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  Message: 'The given assembly name was invalid.',
  FileName: '/Users/andre/typeprovider-test/node_modules/edge-fs/lib\\edge-fs.dll',
  FusionLog: null,
  TargetSite: {
    Name: '',
    DeclaringType: '',
    ReflectedType: '',
    MemberType: '',
    MetadataToken: '',
    Module: '',
    IsSecurityCritical: '',
    IsSecuritySafeCritical: '',
    IsSecurityTransparent: '',
    MethodHandle: '',
    Attributes: '',
    CallingConvention: '',
    ReturnType: '',
    ReturnTypeCustomAttributes: '',
    ReturnParameter: '',
    IsCollectible: '',
    IsGenericMethod: '',
    IsGenericMethodDefinition: '',
    ContainsGenericParameters: '',
    MethodImplementationFlags: '',
    IsAbstract: '',
    IsConstructor: '',
    IsFinal: '',
    IsHideBySig: '',
    IsSpecialName: '',
    IsStatic: '',
    IsVirtual: '',
    IsAssembly: '',
    IsFamily: '',
    IsFamilyAndAssembly: '',
    IsFamilyOrAssembly: '',
    IsPrivate: '',
    IsPublic: '',
    IsConstructedGenericMethod: '',
    CustomAttributes: ''
  },
  Data: {},
  InnerException: null,
  HelpLink: null,
  Source: 'System.Private.CoreLib',
  HResult: -2146232799,
  StackTrace: '   at System.Reflection.AssemblyNameParser.ThrowInvalidAssemblyName()\n' +
    '   at System.Reflection.AssemblyNameParser.GetNextToken(String& tokenString)\n' +
    '   at System.Reflection.AssemblyNameParser.Parse()\n' +
    '   at System.Reflection.AssemblyNameParser.Parse(String name)\n' +
    '   at System.Reflection.AssemblyName..ctor(String assemblyName)\n' +
    '   at CoreCLREmbedding.CompileFunc(IntPtr v8Options, Int32 payloadType, IntPtr exception)',
  Name: 'System.IO.FileLoadException',
  name: 'System.IO.FileLoadException'
}

The second error might be caused by the fact that I am on MacOs. If they are not, are these errors known and is it planned to support F#?

agracio commented 7 months ago

It is likely caused by MacOs currently M1/Mx macs are known to have issues. Unfortunately the only M1 mac i have has a defective dotnet install and I was unable to fix it using any available solutions. If you create a fork will take a look at it on windows to see if it works at all.

agracio commented 7 months ago

Managed to fix my M1 dot net install by doing some correct linking to existing directories but stuck at dotnet version 7.0.101 as I am afraid to break it again when upgrading. edge-js-quick-start runs without any problems, try it out to see if it narrows down the problem to F#.

andretrump commented 7 months ago

Thank you for investigating this issue so quickly. Just to clarify: I should try to run edge-js-quick-start with the version of edge-js currently available on npm to see F# causes the issue, right?

agracio commented 7 months ago

Correct, run vanilla edge-js-quick-start following the instructions in README just to verify if it runs at all for you.

andretrump commented 7 months ago

I just tried it and except for the warning warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread, it works fine. I had also tried the C# example here before and it worked as well.

agracio commented 7 months ago

So the issue isnt Mx chip, create a fork for your F# code and I will take a look at.

andretrump commented 7 months ago

I created the fork and added a simple sample of F# code that uses the features I will need (TypeProviders and Reflection) in main.js: https://github.com/andretrump/edge-js-quick-start. For some reason the error meesage is now different, even if just enter a hello world program. It says:

Error: Could not load file or assembly 'Edge.js.CSharp, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

    at exports.func (/Users/andre/edge-js-quick-start/node_modules/edge-js/lib/edge.js:177:17)
    at Object.<anonymous> (/Users/andre/edge-js-quick-start/main.js:95:25)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  Message: "Could not load file or assembly 'Edge.js.CSharp, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.\n",
  FileName: 'Edge.js.CSharp, Culture=neutral, PublicKeyToken=null',
  FusionLog: null,
  TargetSite: {
    Name: '',
    DeclaringType: '',
    ReflectedType: '',
    MemberType: '',
    MetadataToken: '',
    Module: '',
    IsSecurityCritical: '',
    IsSecuritySafeCritical: '',
    IsSecurityTransparent: '',
    MethodHandle: '',
    Attributes: '',
    CallingConvention: '',
    ReturnType: '',
    ReturnTypeCustomAttributes: '',
    ReturnParameter: '',
    IsCollectible: '',
    IsGenericMethod: '',
    IsGenericMethodDefinition: '',
    ContainsGenericParameters: '',
    MethodImplementationFlags: '',
    IsAbstract: '',
    IsConstructor: '',
    IsFinal: '',
    IsHideBySig: '',
    IsSpecialName: '',
    IsStatic: '',
    IsVirtual: '',
    IsAssembly: '',
    IsFamily: '',
    IsFamilyAndAssembly: '',
    IsFamilyOrAssembly: '',
    IsPrivate: '',
    IsPublic: '',
    IsConstructedGenericMethod: '',
    CustomAttributes: ''
  },
  Data: {},
  InnerException: null,
  HelpLink: null,
  Source: 'System.Private.CoreLib',
  HResult: -2147024894,
  StackTrace: '   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, StackCrawlMark& stackMark, AssemblyLoadContext assemblyLoadContext, RuntimeAssembly requestingAssembly, Boolean throwOnFileNotFound)\n' +
    '   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)\n' +
    '   at CoreCLREmbedding.CompileFunc(IntPtr v8Options, Int32 payloadType, IntPtr exception) in /Users/andre/edge-js-quick-start/node_modules/edge-js/src/double/Edge.js/dotnetcore/coreclrembedding.cs:line 652',
  Name: 'System.IO.FileNotFoundException',
  name: 'System.IO.FileNotFoundException'
}

Maybe I am doing something wrong.

agracio commented 7 months ago

I meant to create a fork of edge-js where you were getting the original error.

agracio commented 7 months ago

Actually dont worry about it, i was able to recreate the original error in edge-js-quick-start

andretrump commented 7 months ago

In case it helps: I originally got the error by just running the F# sample from the README.md

agracio commented 7 months ago

Managed to get to the bottom of the issue edge-fs is only compatible with .NET 4,x.

You can check out the project yourself at https://github.com/7sharp9/edge-fs. It has a dependency on FSharp.Build.dll from VS build tools which is then copied to edge-fs lib and to build the project it requires dlls from .NET 4.0 on Windows. It uses various FSharp.Build methods to dynamically compile underlying 'f#' code when called which restricts it to .NET 4x.

If you desperately need f# integration your best option is to re-write a compiler based on edge-cs code https://github.com/tjanczuk/edge-cs.

andretrump commented 7 months ago

Allright, thank you for your help.

agracio commented 7 months ago

If you can convert https://github.com/agracio/edge-js/blob/master/src/double/Edge.js.CSharp/EdgeCompiler.cs to F# I will give it a try. Just make sure that all regexes, etc are still valid.

andretrump commented 7 months ago

I am currently not sure if I desparately need F# for my project and I am quite a newbe to .NET, so it will take me some time to convert it. If I figure out that I will definitely need F#, I will try to cenvert it. Thank you for the offer anyway.

agracio commented 7 months ago

F# should only be used for very specific applications that benefit from functional language approach for anything else you should always use C#.

andretrump commented 7 months ago

If I use it, I use it because of the TypeProviders. I think there is no similar concept in C#.

agracio commented 4 months ago

It appears that there is a way to implement F# support using .NET Standard, will be looking at it in the coming weeks.

agracio commented 3 months ago

New version released with support for CoreCLR using netstandard 2.0 if you still need it.

andretrump commented 3 months ago

I won‘t need it. But thanks for the update anyway.