Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I generate a Node.js module? #4055

Closed
VictorTaelin opened this issue Sep 5, 2017 · 4 comments
Closed

How can I generate a Node.js module? #4055

VictorTaelin opened this issue Sep 5, 2017 · 4 comments

Comments

@VictorTaelin
Copy link

The --codegen node option generates an executable Node.js program. Suppose, for example, that we try to compile the following Idris file:

module Lib

export
ones : Int -> List Int
ones 0 = []
ones n = 1 :: (ones (n - 1))

It doesn't work because of the following error:

~/dev/idris: idris --codegen node lib.idr -o lib.js
When checking an application of function run__IO:
        No such variable Main.main

Suppose, though, we modify the file to:

module Main

export
ones : Int -> List Int
ones 0 = []
ones n = 1 :: (ones (n - 1))

main : IO ()
main = putStrLn (show (ones 4))

That generates a .js file that outputs [1, 1, 1, 1]. On the last lines of that file, there is:

$_0_runMain();

Which executes Main.main. That is pretty useless, though. Much more desirable would be to export a CommonJS library with the exported values. If we merely replace that line with:

module.exports = {
   ones: Main__ones
};

It works as expected and we can use lib.js from other Node.js modules:

const lib = require("./lib.js");

console.log(JSON.stringify(lib.ones(4)));

Such feature could be useful for many reasons. For one, I could port eth-lib to Idris, compile it to JS and make thin wrappers to publish on npm, where people could use it from their JS codes. Of course, that would require settling a stable format for compiled ADTs. It currently uses: {"type": tag_of_the_constructor, "$1": first_field, "$1": second_field, ...}, which seems fine to me.

Note: it would also be desirable that, when generating a module, the BN.js dependency (which is inlined on Idris's output) would be just require("BN.js"), avoiding importing the same lib twice on JS bundles.

@xaviervia
Copy link

@MaiaVictor I'm not an Idris contributor, but I have been playing around with the JS codegen since JS is my day job.

I think it would be good to pull request support for this feature. It could be the default behavior for the target node. My rationale is that:

  • Exposing the functions as named entrypoints to the JS module with CommonJS would make it automatically supported in most environments (certainly in Node)
  • It could work so that only the code in the "main" function gets built without a wrapper around it so that it gets immediately executed.

@rbarreiro
Copy link
Collaborator

There is an --interface option in idris "--interface Generate interface files from ExportLists" I don't know what it is, but sounds what you need. It does not work on the js backend. I will try to figure it out and implement it.

@melted
Copy link
Contributor

melted commented Sep 7, 2017

@rbarreiro the test ffi006 is an example of the export functionality for the C backend.

@rbarreiro
Copy link
Collaborator

I propose a solution on #4073.
@melted thanks, your hint was very helpful :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants