Skip to content

Instantly share code, notes, and snippets.

@ohpauleez
Created November 19, 2015 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ohpauleez/d24674a3fc173f251842 to your computer and use it in GitHub Desktop.
Save ohpauleez/d24674a3fc173f251842 to your computer and use it in GitHub Desktop.
ML-like Java/Clojure Transpiler
package one.one.one.one
/* All declarations/statements are one-per-line; No semi-colon needed;
Comments are only multi-line;
Follow Java naming conventions */
/* If no package is found you'll be in the "user" package */
import clojure.lang.IFn
import java.util.stream.Collectors
/* This will produce an interface and do the necessary Clojure protocol-map stuff */
protocol IStep {
/* Values are 'public static final'.
They are always determined to be the smallest possible primitive, String or Object for scalars.
Otherwise, requires Java style type.
Type declarations are always used if supplied.
The right side of the assignment is Java code. */
val x = 5
val y : long = 19
/* Allowed, but discouraged. Turned into a `static` on the Interface */
fn greeting [] : String {
return "Hello";
}
/* `Self` is always type Object */
sig hi_there [Self t, String one]
[Self t, Object one]
[Selt t, Object one, String two] : Object /* return type is optional, assumed to be Object*/
/* A `def` signature has a default implementation, but is a Protocol signature */
def say_a_greeting [Self t] {
/* In here, it's Java */
return greeting();
} /* Return type is assumed Object unless otherwised typed */
}
/* We can create FunctionalInterfaces too
The method name will be the lower-case name of the Interface.
TODO: How should we extend IFn to allow passing in Clojure Functions? */
lambda-type IJump [Object something, String another] : Object
/* Enums are specifically excluded.
You should either use clasess/record-likes or code directly in Java if
you need per-member interface implementations in the enum */
/* Only functions and values can go in classes.
Classes have no public constructor (by default).
No subclassing allowed. */
class Computations {
val start_number = 42
/* All functions are public static; all args are final */
/* If return type is omitted, assumed to be Object */
fn some_name [int t] : int {
/* In here, it's Java */
return t;
}
}
/* Classes can be record-like objects by adding an optional arg-list.
All attributes are `public final`, and set by the constructor.
Three public constructors are generated - positional args, single List, and single Map (keys are strings of the attrs).
Three methods are generated - toMap (PersistentMap), toList (PersistentVector), toString
A class can specify all the protocols/interfaces it `implements`, just like Java, but requires the optional arg list (must be a record-like)
Signature implementations are defined with `def` */
class Point [Number x, Number y] implements IStep {
val origin = new Point(0, 0)
val str_compr : Comparator<String> = (lhs, rhs) -> lhs.compareTo(rhs); /* This is just for example - one should prefer `fn` to lambda objects.
Reserve using Lambdas for function/method args */
fn another_function [int a] : int {
return a;
}
/* IStep */
def hi_there [Self t, String one] {
return str_compr.compare("hello", one);
}
def hi_there [Self t, Object one] {
/* This is mostly just an example - the joiner uses StringBuilder under the hood */
return IStep.geeting().chars()
.map(e -> String.valueOf(e))
.collect(Collectors.joining(""));
}
def hi_there [Self t, Object one, String two] {
return IStep.say_a_greeting(t);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment