gal — the general abstract language
gal is a programming language that compiles to six others. Write a program once and the compiler gives you Python, JavaScript, Go, Java, C++ or MUMPS source that does the same thing in each.
one program
This is FizzBuzz in gal. Names start with a capital letter, keywords are lowercase, and a statement ends with a semicolon or a block.
module Fizzbuzz
{
main
{
for range I 1 20
{
if ((I mod 15) = 0)
{
say "FizzBuzz";
}
else if ((I mod 3) = 0)
{
say "Fizz";
}
else if ((I mod 5) = 0)
{
say "Buzz";
}
else
{
say I;
}
}
}
}
six languages
This is what the gal 3.3 compiler generates from that program, unedited.
python
# module: Fizzbuzz
if __name__ == '__main__':
for I in range(1,20+1):
if I % 15 == 0:
print('FizzBuzz')
elif I % 3 == 0:
print('Fizz')
elif I % 5 == 0:
print('Buzz')
else:
print(str(I))javascript
// module: Fizzbuzz
// main program
for (var I = 1; I <= 20; I++)
{
if (I % 15 == 0)
{
console.log('FizzBuzz');
}
else if (I % 3 == 0)
{
console.log('Fizz');
}
else if (I % 5 == 0)
{
console.log('Buzz');
}
else
{
console.log(globalThis.String(I));
}
}go
package main
import "fmt"
// module: Fizzbuzz
func main() {
for I := 1; I <= 20; I++ {
if ((I % 15) == 0) {
fmt.Println("FizzBuzz")
} else if ((I % 3) == 0) {
fmt.Println("Fizz")
} else if ((I % 5) == 0) {
fmt.Println("Buzz")
} else {
fmt.Printf("%d\n", I)
}
}
}java
@SuppressWarnings({"unchecked", "cast", "serial", "rawtypes", "this-escape", "deprecation", "removal"})
public class Fizzbuzz {
public static void main(String[] args) {
for (int I = 1; I <= 20; I++) {
if (((I % 15) == 0)) {
System.out.println("FizzBuzz");
} else if (((I % 3) == 0)) {
System.out.println("Fizz");
} else if (((I % 5) == 0)) {
System.out.println("Buzz");
} else {
System.out.println(I);
}
}
}
}c++
#include <iostream>
// module: Fizzbuzz
int main() {
for (int I = 1; I <= 20; I++) {
if ((I % 15) == 0) {
std::cout << "FizzBuzz\n";
} else if ((I % 3) == 0) {
std::cout << "Fizz\n";
} else if ((I % 5) == 0) {
std::cout << "Buzz\n";
} else {
std::cout << I << "\n";
}
}
return 0;
}mumps
Fizzbuzz ; gal ; Fizzbuzz module.
do init^galrt
do main()
quit
main() ; main program
new %etin set %etin=$etrap
new $etrap,$estack set $etrap=%etin
set I=1
goto:$select(1<0:I<20,1:I>20) L41K
goto L41B
L41C ; for range continue
goto:$select(1<0:I+1<20,1:I+1>20) L41K
set I=I+1
L41B ; for I range begin
if ((I#15)=0)
else goto L80X
use $principal write "FizzBuzz",!
goto L80E
L80X ; if-else
if ((I#3)=0)
else goto L173X
use $principal write "Fizz",!
goto L80E
L173X ; else-if-else
if ((I#5)=0)
else goto L266X
use $principal write "Buzz",!
goto L80E
L266X ; else-if-else
use $principal write I,!
L80E ; end if
goto L41C
L41K ; for I range break
quitEach of them prints the same 20 lines:
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz
The repository's five-languages oracle runs five programs through every target and fails if any two outputs differ by a byte.
a compiler written in gal
The gal compiler is a gal program. It compiles its own source, the result compiles the source again, and the two generations come out byte-identical across all fourteen of its parts. Because the compiler is ordinary gal, it also runs wherever gal runs: on CPython, node, the JVM and YottaDB — and in your browser.
try it
- open the idewrite gal, compile it to Python or JavaScript, and run the program in the page. nothing to install.
- playgroundwatch one example move through every stage of the compiler.
- articleswalkthroughs with video, starting from hello world.
- downloadthe open-source compiler, all six targets, for your own machine.
what comes next
gal3 goes one way: from gal down to a target language. gal4 is the next release, and it adds the other directions — reading programs written in other languages into gal, and lifting low-level code back up into more abstract code.