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

Native interface and plugins #23

Open
SpencerPark opened this issue May 13, 2017 · 1 comment
Open

Native interface and plugins #23

SpencerPark opened this issue May 13, 2017 · 1 comment

Comments

@SpencerPark
Copy link
Owner

SpencerPark commented May 13, 2017

There are some things that would be nice to have in MellowD but the language is not the right place to implement them. Just like plugins for sound editors it would make sense to allow plugins to be written in Java and added to the "MellowD VM". These things need an interface then and it could actually just be inferred from the injected function classes or explicitly declared in an interface declaration.

This could take a form like TypeScript's .d.ts files with declarations something like Java's native keyword.

def native function myFunction => chord arg1, arg2

Possible implementation solutions

  1. In the declaration files there could be a direct link to a class file that can be resolved.
def native function myFunction => chord arg1, arg2 {
    invoke my.java.package.ClassName::methodImplemtingMyFunction
    //or
    implementation my.java.package.ClassName::methodImplemtingMyFunction
}

The problem with the above is that this tightly couples the language with a Java interpreter. It also requires an implementation to be provided to the interpreter as well as the declaration in the right folder with the source. The namespace is then also decided by the developer including the library and not the author.

  1. Another option is with annotations in the injected classes
@MellowDFunction("my.namespace.myFunction")
public void myFunction(Chord arg1, Object arg2) {
    ...
}

@MellowDConstant("my.namespace.MyValue")
public static final Rhythm MY_VALUE = new Rhythm(...);

@MellowDConstant("my.namespace.MyValue2")
public static Rhythm getRhythm() { ... }

Where the getRhythm call would be invoked once to construct the rhythm and stored in the namespace.
This approach would require a fresh plugin API which might be a bit more work but also decouples the injection from the interpreter a bit. Although the Rhythm, Chord, etc. classes are still exposed anyways.

  1. Plugins could register themselves with the existing interpreter API.
public class MyPlugin {
    public MyPlugin(MellowD mellowd) {
        final Parameter<Chord> param1 = Parameter.newRequiredParameter("param1", Chord.class);

        FunctionSignature sig = new FunctionSignature("myFunction", param1);

        mellowd.getFunctionBank("my", "namespace").addFunction(new Function(sig, false, (env, out) -> {
            Chord arg1 = param1.getReference().dereference(env.getMemory());
            out.put(...);
        }));
    }
}

This is exactly what the default functions do and essentially it is already all implemented. It would just be beneficial to formalize the interface and maybe clean it up a bit (#10). This approach would reject an import syntax though as a loaded plugin would immediately inject itself into the function bank whether it is needed or not.

  1. A little bit of both with a namespace and interface configuration file packed into the plugin jar. This would map imports to classes and then a custom source resolver that looks for plugins would be used to preform the lookup. Unfortunately it wouldn't resolve source, but rather implementation, and so the import mechanism would need to be fixed to account for this.
@SpencerPark
Copy link
Owner Author

With d6ecf73 the implementation is closest to the 3rd option but with the application taking place via an apply(MellowD) call so that plugin's can cache the function signature creations in fields.

There is still a bit to implement (see #25) but the basics are here. The plugin must be in the classpath for the import mechanism to find it which is outside the scope of the compiler api leaving the interpreter to still be language agnostic (#24)

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

1 participant