Skip to content

Frequently Asked Questions

Dave Moten edited this page Nov 1, 2015 · 15 revisions

Can Frege be used to ....

If it cannot be done with Java, then it cannot be done with Frege either. Otherwise, the answer is "most likely". Remember, writing Frege code is just a more convenient way to write Java code.

Why would I need Java 7?

JDK7 is the official development platform, it is choosen because it has the fork/join packages which are used for parallelization and because the compiler of JDK-6 has severe bugs.

If you absolutely need Java6, read on.

How can I still use Frege with Java 6?

It is possible to make oneself a JAR that runs under JRE-6 and creates Java6 compatible class files. However, due to the bugs mentioned above, most programs will still only compile if you have a Java7 compiler! The compiled classes, can be run with JRE6 when the JAR is in the classpath.

Here are the steps to follow, based on the "Re-Compiling the Compiler" section of the Getting Started page. You must still have JDK-7 to do this.

  1. Using JDK7 under UNIX, compile the compiler with:

    make runtime fregec.jar

  2. Make the compiler for JDK-6:

    make fregec6.jar

The compiler built that way can be run with JDK-6 or JDK-7 with the following command:

java -Dfrege.javac="javac" -jar fregec6.jar -target 1.6

However, to avoid compilation errors, javac must still be a Java7 compiler! Whatever you compile this way will be good for JRE-6, and can be run with:

java -cp fregec6.jar:... some.module.Main

From the fregec6.jar and any compiled code, you can also build a standalone application in the same way as with fregec.jar.

Can I make a stand-alone Frege application JAR?

Sure. Use the tool of your choice. Here is an example, using ProGuard:

  • The configuration file for ProGuard pg.conf

    -injars       build(**/*.class)
    -injars       ../frege/fregec.jar
    -outjars      application.jar
    -libraryjars  /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar
     
    -optimizationpasses 3
    -dontobfuscate
     
    -keep public class examples.Mockingbird {
          public protected *;
    }
    

    This assumes the classes of the application are below build/, the sibling ../frege/ directory holds the fregec.jar and the main class is examples.Mockingbird. The output will be in application.jar

  • Now run the following commands:

    java -jar $HOME/bin/proguard.jar @pg.conf       # adapt proguard.jar location!
    jar -ufve application.jar examples.Mockingbird  # or whatever your main module is
    java -jar application.jar                       # will run your program
    

    The size of the application.jar was well below 1MB.

Can I hack the compiler/library in Eclipse?

Yes, it is possible. But you must set the Prefix option in the Frege preferences to some string, for example my. This will cause all Java packages generated by Frege to start with my. This way, modules compiled in Eclipse cannot get confused with the ones in the fregec.jar that is part of the plugin.

If you don't set the prefix, the builder will get severely confused. For example, it may recompile the whole thing on every change, because it thinks that the compiled classes are too old. Or it may think it is not necessary to compile something at all. Or modules get imported from the JAR, instead of from your bin directory.

OTOH, it seems that Eclipse will not like the bin/myfrege directory and removes it from time to time (on restarts, for example). This will then cause a full build, because the Frege builder sees that nothing is there.

Why does the Frege compiler generate Java code? All other JVM languages generate byte code directly!

This is a consequence of the way the native interface works. Consider this, for example:

data Bar = pure native com.foo.Bar where
    pure native new :: Int -> Bar
    pure native another :: Bar -> String -> Maybe Bar

This tells the compiler, among other things, that a Frege expression like

Bar.another (Bar.new 42) "foo"

can be compiled to a Java expression

new com.foo.Bar(42).another("foo")

and that this well typed expression yields a Bar or null.

Note that Frege code generation does not need to know whether com.foo.Bar exists, nor does it need to check the method signature of the constructors to find a matching one. Those boring tasks are left to the Java compiler.

This is an all-or-nothing approach: even if we knew everything javac could ever know about com.foo.Bar, it would still not be enough information for the Frege compiler. For example, the fact that the method another could return null is not necessarily available from class files or JARs. Hence, instead of doing a half cooked job checking native declarations, they aren't checked at all. Rather, code is generated under the assumption that they are correct. If they aren't, you'll get error messages from the Java compiler.

This has the additional advantage that Frege is (almost) decoupled of Java and could in principle generate code in any OO language. Only the code generation pass needs to know a small subset of Java at all, and this is merely knowledge about the syntactical representation of some concepts and idioms common to most imperative languages. So, maybe one day we can generate JavaScript, C# or whatnot with only small changes to the backend. While in the case that the backend would generate byte code, we would have to throw it away entirely and start from scratch.

That being said, if you think that a JVM byte code backend would be somehow superior, just write one!

Clone this wiki locally