ZeroTurnaround is proud to announce Frostbyte, a new stack-based language for the JVM. The language was born out of frustration of working with the standard Java software stack and tools. Hopefully this language will be the long awaited answer to the myriad of JVM languages that have hit the streets in the past couple of years. With some confidence, we believe that Frostbyte will solve both social and engineering problems that software developers have to deal with.
A key innovation in Frostbyte as a stack-based language is the use of inverse reverse Polish notation with parentheses. Instead of first putting things on the stack and then executing an instruction on it, we let you write it the other way around, which feels more natural.
Frostbyte code maps very closely to Java bytecode, and any overhead in code becomes blatantly obvious. Instead of adding in the whole kitchen sink, we chose to cherry-pick the features that make the language both easy and simple yet powerful enough to replace Java in most if not all applications.
Let’s look at a basic hello world example:
fun main := (call echo „Hello World!“)
Frostbyte lets you define
chunks of bytecode that are always inlined when called. For example, the standard library defines echo as a chunk:
chunk echo := (with System (with (get out) (call println ...)))
And the expanded form of the hello world is:
fun main := (with System (with (get out) (call println „Hello World!“)))
Instead of Strings, Frostbyte has Ropes as the main text type, but Ropes are implicitly converted to Strings, e.g. when interfacing with existing Java code.
fun main (args: Rope) := (echo (with „Hello, “ (call concat (args head))))
If the above is saved in a file hello.fb, you can run it with the
> fb hello Jim Hello, Jim
The Frostbyte language is fully internationalizable. In fact, the built-in default language is Estonian, but language is detected from each source file. Other languages are provided as simple translation files — English (British) and Russian are included by default. For example:
Köis=Rope esik=main kaja=echo võttes=with kutsu=call jätka=concat head=pea
The Estonian translation of hello.fb would be:
fun esik(argumendid: Köis) := (kaja (võttes „Hello, “ (kutsu jätka (võttes argumendid (kutsu pea)))))
You can also provide translation maps for your own code — the translations are stored as annotations in .class files. The Frostbyte IDE (coming soon) has knowledge of these translations and will suggest code completions based on your selected language.
Of course, no language introduction is complete without the Fibonacci example. There are several ways to do it. While if statement + recursion is one way, we are trying to deprecate the if statement, since it’s really just a degenerate form of pattern matching. One way to do pattern matching in Frostbyte is to describe the patterns in function arguments and provide a separate function body for each case.
fun fib (0) := 0 fib (1) := 1 fib (n) := + (call fib (- n 1)) (call fib (- n 2))
As you can see, operators like + and * don’t need the
call keyword. You can also create your own operators by using the
op keyword instead of fun.
Pattern matches can also appear as expressions in function bodies. Here’s an example in Estonian. We’ll also introduce code blocks, loops/closures and let (olgu) keyword.
// get current time as Aeg (Time) type amps praegu: Aeg := pööra (võttes System (kutsu currentTimeMillis)) Aeg // Funktsioon, mis leiab raamatukogust laenutatud raamatud, mille tagastamisega on hilinetud või mis on rikutud fun leiaHilinenudRaamatud := ( olgu raamatud := võttes Andmebaas (kutsu leiaLaenutatudRaamatud); võttes raamatud (kutsu koonda ( raamat -> ons? (< (võta tähtaeg) (kutsu praegu)) -> (uus Hilinemine raamat) ons? (võta rikutud?) -> (uus Rikkumine raamat) )) )
For those few who don’t speak Estonian, a translation is in order:
amps=chunk praegu=now Aeg=Time pööra=convert olgu=let koonda=collect (filter + map) ons?=case (introduce a pattern) uus=new raamatud=books raamat=book tähtaeg=due date etc.
Let’s look at a bit more complex example that introduces classes as well.
class Vector2(x: Double, y: Double) := // dot product op ·(that: Vector2) := + (* (get this x) (get that x)) (* (get this y) (get that y))
We can write
(get this x) as a shorthand for
(with this (get x)). But we can also use the
with keyword to shorten the field accesses:
op ·(that: Vector2) := (with this ( + (* (get x) (get that x)) (* (get y) (get that y)) ))
But even better, if we write
with X or Y, then a tuple of X and Y is put on the stack, and any access to their fields or methods will alternate between X and Y.
op ·(that: Vector2) := (with this or that ( + (* (get x) (get x)) (* (get y) (get y)) ))
We can then see some repeating patterns here and can reduce it down further
(with this or that ( + (* dup (get x)) (* dup (get y)) ))
dup will duplicate the next bytecode instructions, but combined with
this or that means the first
(get x) will be (in Java-speak)
this.x and the next
(get x) will be
that.x . How cool is that.
I bet you are curious about the kind of bytecode generated by Frostbyte. Lets look at the expanded hello world again.
fun main := (with System (with (get out) (call println „Hello World!“)))
javap gives us this:
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #22; //String Hello World! 5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;) 8: return
So the translation is quite straightforward:
with System (get out) in this case translates to
getstatic, then “Hello World!” to
call always translates to either
invokespecial, except when it’s used to expand a
chunk, in which case it gets replaced with the chunk and any arguments are inserted into the bitemarks (e.g. in the
… is a bitemark).
chunk echo := (with System.out (call println ...))
Frostbyte 1.0 Roadmap
The language is still in development, but we are getting close to the first public Beta release. For 1.0, we have some more awesome things planned:
- First class co-monads
- Kabanov-Raudjärv type inference
- Lazy chunks
- goto statement with labels
While we are still working towards the first publicly available version, here are some links for you to familiarize yourself with the language to be ready for the big release.
Into the Future
We think Frostbyte will make a real change to the way software is developed. ZeroTurnaround is confident that it will become the next Java and will solve most of the problems that plague developers around the world, such as difficulties dealing with concurrency, parallelism, and the CPU-memory gap.
The Frostbyte 2.0 compiler will have built-in AI that is able to make aesthetic judgments about your code and will outright disallow ugly code, over-abstractions and excessive copy-and-pasting *.
To enable the latter, the AI will have a connection to a centralized data cloud and will be able to compare your code to everyone else’s. It will automatically find copyright and patent infringements and end the software patent wars forever. The AI will utilize automated crowd sourcing to some extent and you can also play your part in improving everyone’s code!
Exciting times are ahead and we are glad to take part in inventing the future!
* we know some people want more freedom, and are working on ways to lift some of these constraints for commercial Frostbyte subscriptions.