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

Better support for calling frege from java #20

Open
Ingo60 opened this issue Oct 18, 2012 · 5 comments
Open

Better support for calling frege from java #20

Ingo60 opened this issue Oct 18, 2012 · 5 comments

Comments

@Ingo60
Copy link
Member

Ingo60 commented Oct 18, 2012

Objective

Given a symbol table (either created through compilation or reconstructed from class-Files) and a set of function and variable names, it should be possible to derive a Java class with the following properties:

  • For each given name N, the class contains a method that returns the evaluated and possibly un-boxed value of a fully satisfied function call or just the value in case N is not a function.
  • The arguments to the methods are also values, even if the frege function is lazy in the corresponding argument.
  • Native values are passed as such (int, String, you name it).
  • Maybe conversion will be done for arguments and return values.

The support will remain limited, however. For, suppose we have

tuple :: a -> b -.> (a,b)
tuple a b = (a,b)

we must insist on getting java.rt.FV (frege values) as arguments. This is because we could not possibly create an overloaded java method, that covers all (infinite many) possibilities. And even if we restricted ourselves to do overloading for "well known" types only, like Int, Long, String, Bool, Char, Double, Float we still had to create 8^k overloaded methods, where k is the arity of the method.

To supplement this, there should also be utility functions for common tasks like converting a list to Iterable or vice versa. Also, for handling of IO and ST values.

Implementation details

I suggest first writing a command line tool that can work independently of the compiler. This will be valuable in any case, as someone might decide to use a library from java despite the devolper did not anticipate this and the source code is not available.

If the need arises, we can create syntax like

derive native class Foo(foo, bar, baz)
@Ingo60
Copy link
Member Author

Ingo60 commented Jan 17, 2013

This is now far easier with the new runtime system, as it is possible to pass in values where lazy values are expected.

OTOH, lazy arguments appear as Lazy or Object, hence it is easily possible to pass objects of the wrong type.

@Ingo60
Copy link
Member Author

Ingo60 commented Mar 24, 2015

New syntax to

  • make the module derive from some class
  • make the module implement some interfaces
  • copy java code given verbatim to the output file

The syntax goes like:

native module 
    type X                 -- optional, X must be native type
    interface Y, Z      -- optional, Y and Z must be native types
    where {               
         // your java code here
    }

X, Y and Z must be types (or type applications) that result in a native type. The compiler outputs

final public class Module extends XX implements YY, ZZ {
    // your java code here
    ... rest of generated code ...
}

where Module is the base name of your module name and XX, YY and ZZ are the native types corresponding to X, Y and Z.

Note that the braces must be written, otherwise the lexer will insert extra semicolons into your java.

The compiler does only check the syntax and that there is at most one such definition, and that the given types are of kind *. It does not interpret the java code in any way. If you want to use that code from inside frege, you need to provide further native method definitions. But note that you cannot refererence the module class as native data type, because it doesn't exist yet at compile time! (You can, however, use static methods.)

For an example, see tests/comp/Issue20.fr

@mmhelloworld
Copy link
Member

This is really nice and exciting! This feature allows Frege modules to be used in places where non-anonymous Java classes are expected, for example, a Java servlet class in web.xml.

I have few questions:

  1. Does it support constructors? Can we call super class constructors? I suppose this should be available as it allows extending a Java class.

  2. It looks like with this syntax we can't have annotations at class level.
    Annotations on a Frege generated Java class would be really useful in leveraging some existing Java frameworks. For example, the Java Microbenchmark framework, JMH, uses lot of annotations at class level and method level to configure benchmark options like here.

  3. This is both a question and like another proposal.
    Can we define public static inner classes? If we can't have annotations for module classes, I think we can make it work with inner classes. This would mean that a Frege module will serve as a namespace and an inner class and its methods would serve for native definitions.

    With this option, we can have something like below. I have made up a triple-quoted multi-line string syntax as in Scala. One nice thing with this approach is that it is not tied to Java language as in we don't specify anything about super class and interfaces. If someday someone creates a compiler that compiles Frege source to some other language, we can have native code for that language inside the triple-quoted string literal without needing any support from Frege.

module foo.Foo where

native """
  @MyAnnotation1
  @MyAnnotation2
  public static class Bar extends AnotherJavaClass implements AnotherJavaInterface {

    // constructors and methods

  }

  /**
   * You could even have some standalone methods
   */
   public static int foo(int n) { return n + 1; }

"""

-- My other Frege functions
f x = ...

main = ... 

Maybe in the distant future :), we could even provide an option to specify the language so that the compilers that are interested in one particular language native code can ignore others. Ideally I would like Frege to be completely independent/isolated from runtime dependency (currently Java, especially core Java types that Frege depend on) as much as possible as it allows targeting other runtimes easily.

module foo.Foo where

native """java

public static class MyJavaClass {}

"""

native """javascript

function foo() {}

"""

@Ingo60
Copy link
Member Author

Ingo60 commented Mar 25, 2015

Hi Marimuthu,

  1. It doesn't allow nor forbid anything. The code between the braces is just a sequence of tokens which is just copied into the generated class.
  2. Yes, annotations on the top level class are not possible with this.
  3. Absolutely. Your example would work by just replacing the first """ with

module where {

and the second one with a closing brace.

@mmhelloworld
Copy link
Member

Absolutely. Your example would work by just replacing the first """ with ...

Excellent! Thanks Ingo!

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

2 participants