A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly 🚀

Overview

wax

wax

wax is a tiny language designed to transpile to other languages easily. Currently supported backends: C, C++, Java, TypeScript, Python, C#, Swift, Lua, as well as directly to WebAssembly.

Playground | Quickstart | Examples | IDE

The goal of wax is to be a "common subset" of most major imperative programming languages. By lacking the unique fancy features in each of these languages and being as boring as possible, wax transpiles to all of them seamlessly, producing outputs that are:

  • Readable: The output code looks just like the input code.
  • Editable: A human programmer should be able to work from the output even if the original wax source is unavailable.
  • Integrable: The output code can be imported as libraries to use with the rest of the target language (in addition to just being runnable alone).

These of course, from the programmers' perspective, come at the cost of losing some of the interesting features offered by other languages. Nevertheless, wax retains the crucial bits for a programming language to be productive.

The syntax of wax is inspired by WebAssembly Text Format (wat), hence the name. Though it uses S-expressions reminiscent of the Lisp family, it is actually quite imperative and most resemblant of C in its design. The idea of transpiling to many languages is inspired by Haxe.

wax is currently experimental, so there might be bugs as well as aspects to be improved, in which case PR and Issues are very much appreciated.

Hello World

(func main (result int)
  (print "hello world!")
  (return 0)
)

Newlines and indentations are entirely cosmetic. You can use any type of brackets anywhere (() [] {}). You can mix different types of brackets if you somehow prefer that.

[func main [result int] [print "hello world!"] [return 0]]

{func main {result int} {print "hello world!"} {return 0}}

{func main [result int] 
	(print "hello world!") 
	(return 0)
}

Here's an in-place quicksort to get a quick taste of the language:

;; sort array in-place for index range [lo,hi] inclusive
(func qksort_inplace (param A (arr float)) (param lo int) (param hi int)
	(if (>= lo hi) (then
		(return)
	))
	(let pivot float (get A lo))
	(let left  int lo)
	(let right int hi)
	(while (<= left right) (do
		(while (< (get A left) pivot) (do
			(set left (+ left 1))
		))
		(while (> (get A right) pivot) (do
			(set right (- right 1))
		))
		(if (<= left right) (then
			(let tmp float (get A left))
			(set A left (get A right))
			(set A right tmp)
			(set left  (+ left 1))
			(set right (- right 1))
		))
	))
	(call qksort_inplace A lo right)
	(call qksort_inplace A left hi)
)

(func qksort (param A (arr float))
	(if (! (# A)) (then
		(return)
	))
	(call qksort_inplace A 0 (- (# A) 1))
)

As you might have noticed, writing in wax is pretty much like writing an abstract syntax tree directly!

There're many more examples, check them out here or on the online playground.

Overview

  • wax is strongly statically typed.
  • wax has built-in support for arrays, hashtables and structs.
  • wax supports C-like macros, allowing specifying different behavior/branches for each compile target, as well as embedding target code directly.
  • syntax is simple: an expression is always a list of tokens enclosed in parenthesis (), and the first token is always a keyword/operator. There're 50 keywords in total.
  • wax does not support OOP (meaning that you get structs to pack data together, but you cannot blend methods into structs), nor does it support functional programming.
  • wax does not have a boolean: zero is false, non-zero is true.
  • wax is not garbage-collected. However, it does have constructs to facilitate memory management and make leaky bugs less likely. On compile targets that do support garbage collection (e.g. Java, JS), explicit freeing of resources is not required, and theoretically you can ignore memory management altogether if you intend to compile to these targets only. Check out the Array/Vector/Struct sections in Quickstart for details.

The Compiler

This repo contains a reference implementation of wax called waxc, written from scratch in C99.

  • Compiles from wax to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly.
  • It seems pretty fast. Compiling a 700 lines file takes 0.015 seconds on Macbook Pro 2015. Comparison: the output TypeScript, which is also 700 lines long, took tsc 1.5 seconds to compile.
  • Additionally, it can emit a very detailed and low-level syntax tree in JSON format. (If your favourite language is not a supported wax target yet, it's not too hard to go from this file and write a code generator :)
  • It can print the tokenization and the abstract syntax tree to terminal.
  • Usage:
 _____                                           
|||'  |                                          
|''   |                                          
|_WAX_| Compiler                                 

built Oct 27 2020                               

USAGE: waxc [options] code.wax                   

OPTIONS:                                         
--c     path/out.c     transpile to c            
--java  path/out.java  transpile to java         
--ts    path/out.ts    transpile to typescript   
--py    path/out.py    transpile to python       
--cs    path/out.cs    transpile to c#           
--cpp   path/out.cpp   transpile to c++          
--swift path/out.swift transpile to swift  
--lua   path/out.lua   transpile to lua 
--wat   path/out.wat   transpile to webassembly         
--json  path/out.json  syntax tree to JSON file  
--tokens               print tokenization        
--ast                  print abstract syntax tree
--silent               don't print info          
--help                 print this message 

Example

To compile the fib.wax example included in the example folder to C, and print the abstract syntax tree to terminal:

./waxc examples/fib.wax --c fib.c --ast

Now compile the C output with gcc and run the example:

gcc fib.c
./a.out

Compile to all targets and compile all outputs with target languages' compilers and run all outputs of target languages' compilers:

./waxc examples/fib.wax \
--c fib.c   --java  fib.java  --ts  fib.ts    --py fib.py  --cs  fib.cs  --swift  fib.swift --lua fib.lua;
gcc fib.c;    javac fib.java;   tsc fib.ts;                  csc fib.cs;   swiftc fib.swift;
./a.out;      java  fib;       node fib.js; python fib.py;  mono fib.exe;       ./fib;        lua fib.lua;

Compiling to C++ requires flag -std=c++11:

./waxc examples/fib.wax --cpp fib.cpp;
g++ fib.cpp -std=c++11;
./a.out;

Compiling to WebAssembly

waxc also supports compiling to WebAssembly Text Format (.wat). As the output needs to be further transformed to binary (.wasm) and wrapped with JS for calling, there's a couple more steps:

1. Compile to wat with waxc:

./waxc examples/fib.wax --wat fib.wat

2. Compile wat to wasm, using wat2wasm from wabt:

./wat2wasm fib.wat

3. Optional: Optimize with wasm-opt from binaryen for massive speedups, since (currently) waxc is not an optimizing compiler.

./wasm-opt fib.wasm -o fib.O4.wasm -O4

4. Now that the wasm is ready, you probably need some JS to call it, which basically involves WebAssembly.instantiate(bytes,imports) with console.log (and Math if you used (@include math)) as imports. Luckily you can find a readymade wrapper in tools/waxwasmwrap.js. To use:

Node:

const wrapper = require("tools/waxwasmwrap.js");
wrapper("fib.wasm",function(lib){
  lib.main();
});

Browser:

WAXWASMWRAP("fib.wasm",function(lib){
  lib.main();
});

All user-defined functions are exported under their original names, so you can call

lib.fib(42);

and so on.

Compiling the Compiler

You need:

  • A C compiler that supports C99. e.g. gcc or clang.

To compile:

gcc src/wax.c -o waxc

That's it, no dependencies.

Alternatively you can run the Makefile:

  • make c. Compile it.
  • make co. Compile it with -std=c99 -O3 -std=c99 -pedantic -Wall.
  • make em. Compile it with emscripten as a node.js app. (You might need to edit the rule based on how/when/where you installed emscripten.)
  • make emlib. Compile it as a javascript library with emscripten, without filesystem dependencies. This is what powers the online playground.

VSCode Extension

Syntax Highlighting + Transpile + Compile + Run + Render

Get Started

Now that the compiler is compiled, head over to QUICKSTART.md for a tour of language features!

Comments
  • More languages transpiling support

    More languages transpiling support

    @LingDong- I ❤️ how wax works and if possible to see more languages wax can transpile to in near future i would be very grateful...

    Languages like JavaScript, Ruby, Lisp (Or Scheme), PHP, Kotlin, Objective-C, and more... Not forcing ya, But if there are any guide about adding transpilers i can work on one if possible!

    And thanks for wax!

    opened by Rabios 6
  • Fixes for Lua transpiler!

    Fixes for Lua transpiler!

    Fixes:

    1. Let transpiler generate require for bit or bit32 module if one of them found, With edit on transpiling them...
    2. Fix ternary operators, It shouldn't be as functions (hilbert example didn't worked with that case...)
    opened by Rabios 5
  • WAT globals interpreted as locals

    WAT globals interpreted as locals

    In the example raycast.wax using WebAssembly output, the variable INFINITY is imported from math:

    (global $INFINITY f32 (f32.const 340282346638528859811704183484516925440))

    but later is called as local:

    (call $set__ray__tmax (local.get $r) (local.get $INFINITY))

    which results in a parse error using wabt afterwards to convert to binary.

    opened by stagas 3
  • Does wax use short-circuit evaluation for boolean expressions?

    Does wax use short-circuit evaluation for boolean expressions?

    Hi, this is a cool project, I'm really enjoying reading through it right now.

    Quick question regarding this part of the QUICKSTART.MD documentation:

    a && b && c is:

    (&& a b c)

    which the compiler will read as:

    (&& (&& a b) c)

    I'm not proficient in all the languages that Wax compiles to, but the ones that I do know would use short-circuit evaluation on this expression - that is, if a is false, then expressions b and c are not evaluated. Does wax also do this to? Or does it always evaluate all expressions? In either case, does it take special care that all compile targets behave as expected? Or does it not make any assumptions about this at all?

    https://en.wikipedia.org/wiki/Short-circuit_evaluation

    opened by JobLeonard 2
  • docs: Fix a few typos

    docs: Fix a few typos

    There are small typos in:

    • QUICKSTART.md
    • src/parser.c

    Fixes:

    • Should read idiomatic rather than idomatic.
    • Should read generated rather than genrated.
    • Should read function rather than funciton.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 1
  • How to #include with C backend?

    How to #include with C backend?

    How can I get a valid #include for C?

    (asm "#include \"some_file.h\"")
    (func main (result int)
        (return 0)
    )
    

    gives malformed include

    #include "some_file.h"int main() {
        return 0;
    }
    

    I tried using an escaped newline and escaping the backslash in the newline but this was included raw into the final output instead of actually escaping a new line

    (asm "#include \"some_file.h\"\n")
    (func main (result int)
        (return 0)
    )
    

    gives

    #include "some_file.h"\nint main() {
        return 0;
    }
    
    opened by phillvancejr 1
  • What string operations are supported?

    What string operations are supported?

    The quickstart only mentions appending to strings and comparing strings. It does not mention accessing the length of strings or indexing characters or substrings. Is that supported?

    opened by johnynek 1
  • Typo on `insert` operations

    Typo on `insert` operations

    At line 212 it seems that the snippet is not correct.

    The doc says:

    To insert v into a an array x at index i, use

    But the index i is missing in the snippet.

    (insert x v)
    

    Should it not be?

    (insert x i v)
    
    opened by sixclones 1
  • Replace int with bool in token, type and string comparisons.

    Replace int with bool in token, type and string comparisons.

    Hello again,

    I have this small patch with some refactoring. Please let me know if you don't like these types of small contributions and I can delete this branch. I have a couple of other small patches that I am interested in contributing if you would like.

    opened by efferifick 1
  • Typo

    Typo

    Hi,

    cool project. I found a typo while reading your README. I also googled integretable, which I thought was the correct word without the typo, but apparently the correct word is integrable. Since this is kind of a silly PR, just let me know if you'd prefer if I delete it.

    opened by efferifick 1
  • [file error] cannot read file

    [file error] cannot read file

    Under Windows, waxc works with the files in the examples folder, but not with new files. Working from a examples file, copy, rename, edit, waxc works again. There is a slight 3 byte difference between the helloworld.wax and the self-created hello.wax. Any idea what can cause the different behavior and how to fix it?

    opened by bardo84 0
  • Feature Request - keep comments in generated code

    Feature Request - keep comments in generated code

    Thanks @LingDong- for your nice little language!
    The generated code is really clean and very close to the wax code.

    I think it would be really nice if we had the option to keep the comments from wax code in the generated target code.

    Not sure if everybody would like this. Maybe an optional compiler flag like --keepComments or a second syntax for comments that should be kept could be introduced?

    opened by Quentie 6
  • Wax compiler in wax - working implementation

    Wax compiler in wax - working implementation

    @LingDong- I've made some surprisingly rapid progress on a self hosted compiler implementation, please see:

    https://github.com/jacoblister/wax/blob/compiler/examples/compiler.wax

    To use, copy the wax code into the Playground and run - this will output javascript , copy and paste into a browser console window, and get - working example programs!

    The following programs are working so far:

    • hello world
    • fibonacci sequence
    • n queens problem
    • hilbert curve
    • turing machine example

    just uncomment to example to run in the compiler 'main' function to see the others.

    I've only been worked on this for about a week in my spare time/weekends, and already have this much working, so I think the minimal wax language might really be on to something. Looking at what it can do so far, I don't think I'll be too far away from having a self hosted compiler working pretty soon, and all in < 1000 lines of code, with embedded examples!

    I have also made a merge request for a Brainfu*k implementation as well - getting that working so easily that got me motivated to try to do a compiler: https://github.com/LingDong-/wax/pull/24/commits/28ae5ebdce2dc4ca888f35ac91a3b49a2acb8a59

    Could you please have a look at that and perhaps merge it into the examples if that's ok?

    I'll be having a look at the C language target as well after I get all the basic functionality covered. I would be quite interested in collaborating with you as I make more progress. I can do a longer brain dump about thoughts on approaches if you'd like.

    Thanks Kindly,

    Jacob

    opened by jacoblister 0
  • C89 and CMake

    C89 and CMake

    @LingDong- So I added C89 support and integrated CMake. Whilst I was at it, I implemented header files for all your files, being careful to only add protoypes for functions and globals that are used in more than the implementation file.

    Builds tested on: macOS (AppleClang) and Windows (MSVC).

    opened by SamuelMarks 0
  • representing unions/enums

    representing unions/enums

    Have you given any thought to how one can represent a tagged union/enum: so, we either have struct1, struct2, etc..?

    In C this can be done with a struct with a field holding a tag, and then a field that is the union of all the other possibilities.

    It would be very interesting to have this ability in wax.

    opened by johnynek 0
Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

Rasmus 1.3k Dec 24, 2022
Whitee is a tiny compiler written in C++17, which translates SysY language into ARM-v7a assembly.

Whitee is a tiny compiler written in C++17, which translates SysY language into ARM-v7a assembly. Table of Contents Background Install Usage Ar

null 14 Dec 11, 2022
use ptrace hook Hotspot JavaVM, instrument java bytecode

taycan 通过native层修改java层(JVM),使用JVMTI及JNI API可以修改java任意类、执行任意代码,完成hook、插入内存马、反射等功能。 适用环境 LINUX KERNEL version > 3.2 GLIBC > 2.15 openJDK/OracleJDK 1.8

null 26 Jul 12, 2022
SWIG bindings for raylib (to Lua, and hopefully other languages)

swigraylib SWIG binding for raylib This repo generates raylib bindings to other languages (eg. Lua), by providing a raylib.i SWIG interface file. SWIG

null 6 Oct 28, 2021
Statically typed programming language.

Summary Luxury is a statically programming langage which is targeting embedded programming. I will eventually stop using C and fully use this language

null 39 Oct 5, 2022
An implementation of yacc for the janet programming language.

janet-yacc An implementation of yacc for the janet programming language. The implementation is based heavily on https://c9x.me/yacc/. Example from ./e

null 11 Nov 22, 2021
tiny recursive descent expression parser, compiler, and evaluation engine for math expressions

TinyExpr TinyExpr is a very small recursive descent parser and evaluation engine for math expressions. It's handy when you want to add the ability to

Lewis Van Winkle 1.2k Dec 30, 2022
Python random library for c++

Python random library for c++

tyson 1 Oct 28, 2021
Python module to reduce a cmake file to an AST

CMake AST Status Travis CI (Ubuntu) AppVeyor (Windows) Coverage PyPI Licence cmake-ast has been tested against every single CMake module that ships wi

ポリ平方 POLYSQUARE 29 Sep 14, 2022
A simple and easy-to-use library to enjoy videogames programming

hb-raylib v3.5 Harbour bindings for raylib 3.5, a simple and easy to use library to learn videogames programming raylib v3.5. The project has an educa

MarcosLMG 1 Aug 28, 2022
Haxe bindings for raylib, a simple and easy-to-use library to learn videogame programming

Haxe bindings for raylib, a simple and easy-to-use library to learn videogame programming, Currently works only for windows but feel free the expand t

FSasquatch 36 Dec 16, 2022
Tool based in nodes to build GLSL shaders without any programming knowledge written in C using OpenGL and GLFW.

FNode Tool based in nodes to build GLSL shaders without any programming knowledge written in C using OpenGL and GLFW (raylib library). It contains a c

Víctor Fisac 80 Dec 26, 2022
WAFer is a C language-based software platform for scalable server-side and networking applications. Think node.js for C programmers.

WAFer WAFer is a C language-based ultra-light scalable server-side web applications framework. Think node.js for C programmers. Because it's written i

Riolet Corporation 693 Dec 6, 2022
Simple Virtual Machine with its own Bytecode and Assembly language.

BM Simple Virtual Machine with its own Bytecode and Assembly language. Build We are using nobuild build system which requires a bootstrapping step wit

Tsoding 87 Jan 1, 2023
My collection of raylib code examples - For learning the C language with 2D and 3D games.

Raylib-Examples My collection of raylib examples. ( https://www.raylib.com/index.html ) For Raylib Version of 4 april 2020 ( Notepad++ windows install

Rudy Boudewijn van Etten 49 Dec 28, 2022
Writing our own printf function, this is a project done under ALX Low Level Programming.

0x11. C - printf Writing our own printf function, this is a project done under ALX Low Level Programming. Resource secrets of printf Implementing prin

Ephantus Mwangi 4 Oct 26, 2022
C-code generator for docopt language.

C-code generator for docopt language Note, at this point the code generator handles only options (positional arguments, commands and pattern matching

null 311 Dec 25, 2022
Open Data Description Language

Open Data Description Language This is the reference parser for the Open Data Description Language (OpenDDL), version 3.0. The official language speci

Eric Lengyel 40 Dec 27, 2022
C language utility library

versatile and easy to use C language utility library with functions and macros commonly used in various applications

Tilen Majerle 42 Dec 28, 2022