Add support for a CLR language

tjanczuk edited this page Mar 28, 2013 · 4 revisions

If you are new to edge.js, first read the overview

Out of the box edge.js enables compiling C# script embedded in a node.js application. This is a guide to adding the capability to compile other CLR languages using the compiler composition mechanism supported by edge.js.

The primary motivation is to enable other CLR languages like F# and to support custom idioms of constructing C# scripts. But the mechanism is generic enough to enable a much broader range of scenarios, including integrating non-CLR languages (e.g. Python).

The goal

The goal is to enable a programming experience in node.js that allows executing scripts of a CLR language embedded in the node.js code. Consider this hypothetical example based on integrating F# into node.js:

var edge = require('edge');

var hello = edge.func('fsharp', function() {/*
    async {
        return async.Return("F# welcomes " + input)

hello('Node.js', function (error, result) {
    if (error) throw error;
    console.log(result); // prints F# welcomes Node.js

Model overview

As a provider of an edge.js extension for a custom language you will need to implement a CLR 4.0 library that normalizes script in your target language to a Func<object,Task<object>> delegate. You will then need to make this library available as part of a published NPM module which application developers can take dependency on. You must come up with your language identifier as a string, say fsharp. The NPM module you publish must then by convention be called edge-fsharp.

The application developer will need to take dependency on both edge and edge-fsharp modules. The easiest way to do this is to list both modules in the dependency section of package.json.

At runtime, when the edge.func function is asked to provide a JavaScript proxy to a CLR function expressed as a script in a particular language, say fsharp, it will load the edge-fsharp module to perform the compilation of the script. At that point the module must be accessible on the target machine.

The NPM module

Please refer to the edge-cs reference module implementation for C#. It is a good starting point for adding support for custom languages.

The NPM module should export a single, parameterless function called getCompiler. The function must return a string which the fully qualified file name of the CLR 4.0 assembly that imlements the compilation logic. By convention, the assembly must contain a public EdgeCompiler class with a public instance method CompileFunc with the following signature:

public class EdgeCompiler
    public Func<object, Task<object>> CompileFunc(IDictionary<string, object> parameters) {}

The parameters represent any parameters the JavaScript call to edge.func has passed as the second argument, normalized to an object representation. The exact contract is between you and the developer of the node.js application. However, you are guaranteed that the dictionary will contain a source key with a string value. The value may be literal source code or a file name.

Usage in an application

If your language name is fsharp, the application developer is expected to take dependency on both edge and edge-fsharp npm modules, which is best done in package.json:

  "name": "sample-app",
  "version": "0.0.0",
  "dependencies": {
    "edge": "0.7.5",
    "edge-fsharp": "0.2.3"

Then in the code, the developer would invoke the edge.func function and provide the language name as the first parameter:

var edge = require('edge');

var myFunc = edge.func('fsarp', '... any representation of a string allowed by edge.js ...');