• Stars
    star
    770
  • Rank 59,000 (Top 2 %)
  • Language
    C
  • License
    MIT License
  • Created about 4 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly ๐Ÿš€

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!

More Repositories

1

shan-shui-inf

Procedurally generated Chinese landscape painting.
HTML
5,488
star
2

fishdraw

procedurally generated fish drawings
JavaScript
2,200
star
3

qiji-font

้ฝŠไผ‹้ซ” - typeface from Ming Dynasty woodblock printed books
Python
1,296
star
4

rrpl

Describing Chinese Characters with Recursive Radical Packing Language (RRPL)
JavaScript
884
star
5

linedraw

Convert images to vectorized line drawings for plotters.
Python
755
star
6

q5xjs

A small and fast alternative (experimental) implementation of p5.js
JavaScript
541
star
7

nonflowers

Procedurally generated paintings of nonexistent flowers.
JavaScript
509
star
8

skeleton-tracing

A new algorithm for retrieving topological skeleton as a set of polylines from binary images
C
497
star
9

cope

A modern IDE for writing classical Chinese poetry ๆ ผๅพ‹่ฏ—็ผ–่พ‘็จ‹ๅบ
JavaScript
455
star
10

ndwfc

๐ŸŒŠ๐Ÿ’ฅ N-dimensional Wave Function Collapse with infinite canvas
JavaScript
311
star
11

psvg

Programmable Scalable Vector Graphics -- drawings that draw themselves
TypeScript
297
star
12

legumes

๐ŸŽผ A sheet music to polylines renderer
TypeScript
230
star
13

magic-square-poems

Discovering magic squares in Tang Dynasty poems
C
188
star
14

handpose-facemesh-demos

๐ŸŽฅ๐ŸคŸ 8 minimalistic templates for tfjs mediapipe handpose and facemesh
JavaScript
187
star
15

Hermit

A man. A horse. A nature.
Python
168
star
16

chinese-hershey-font

Convert Chinese Characters to Single-Line Fonts using Computer Vision
Python
129
star
17

Processing-Demos-for-The-Pocket-Handbook-of-Image-Processing-Algorithms

Processing Demos made when reading the book *The Pocket Handbook for Image Processing Algorithms in C*
Processing
127
star
18

edges2calligraphy

Using pix2pix to convert scribbles to Chinese calligraphy
JavaScript
115
star
19

tk-fangsong-font

ๅ‰”้ชจไปฟๅฎ‹: Experimental Fang Song style Chinese font
Python
112
star
20

grand-timeline

Interactive grand unified timeline of 30,800 ancient Chinese people / ๅคไบบๅ…จ่กจ
JavaScript
111
star
21

hfmath

Render LaTeX math with Hershey Fonts
TypeScript
94
star
22

VisionOSC

PoseOSC + FaceOSC + HandOSC + OcrOSC + CatOSC + DogOSC
Objective-C++
88
star
23

wechit

WeChat in Terminal (ๅพฎไฟก็ปˆ็ซฏ็‰ˆ)
Python
88
star
24

wasm-fun

Non-trivial programs in hand-written WebAssembly
WebAssembly
78
star
25

PoseOSC

๐Ÿ“น๐Ÿคธโ€โ™‚๏ธ๐Ÿคพโ€โ™€๏ธ๐Ÿคบ PoseNet + OSC: send realtime human pose estimation data to your apps
JavaScript
77
star
26

ci-ren

Generative Chinese poetry
Python
75
star
27

r1b

A thermal-printer-oriented, 1-bit graphics rasterizer for 2D and 3D
C
73
star
28

squiggy

vector brushstroke library
TypeScript
65
star
29

asciimare

3D engine powered by ASCII art
Python
63
star
30

Okb.js

Procedural generation toolkit for Javascript - noises, randomness, curves, and more
HTML
60
star
31

ofxPoissonFill

Poisson filling shader for OpenFrameworks
C++
56
star
32

p5-hershey-js

p5.js Hershey Vector Font Library
JavaScript
53
star
33

pmst

๐ŸŽจ Poor Man's Style Transfer - Painting an image with the style of another, without machine learning
C++
48
star
34

Loshu.js

A linear algebra library for JavaScript ๐Ÿ”ข
JavaScript
47
star
35

zdic-cli

An offline command-line interface to zdic.net dictionary (ๆผขๅ…ธ)
JavaScript
47
star
36

interesting-polygon-archive

Collection of polygon data in various formats for testing computational geometry algorithms.
Processing
46
star
37

ttf2hershey

Convert True Type Fonts (.ttf) to Hershey vector fonts
Python
43
star
38

skeletonization-js

Javascript implementation of image skeletonization
JavaScript
42
star
39

t43

A tiny 3D slicer written from scratch
C
32
star
40

fv

An experimental approach to expressing vector math in js (tagged template literals)
JavaScript
31
star
41

LingDong-

Automatically keep my Github profile README updated with a python script and Github Actions
Python
28
star
42

PContour

Processing/Java library for finding contours in binary images
HTML
28
star
43

srcsnap

screenshot-driven version tracking
JavaScript
22
star
44

dbn.js

Recreation of John Maeda's "Design By Numbers" programming environment in JavaScript
JavaScript
18
star
45

wax4vscode

Extension for the wax programming language in VS Code (highlight + transpile + run)
TypeScript
17
star
46

TrackpadOSC

๐Ÿ’ป๐Ÿ‘‹โœŒ๏ธ๐Ÿ‘‰Send mac's multitouch trackpad read-out through OSC
Objective-C
17
star
47

xcessing

Friendly Processing-like interface to X11/Xlib in C
C
16
star
48

svg2pl

convert svg to polylines
C
15
star
49

lbll

tiny experimental language for limited environments
C
14
star
50

fast-many-face-detection-with-cpp-or-openframeworks-on-mac-using-neural-networks

Fast Many Face Detection with C++/OpenFrameworks on macOS using Neural Networks
C++
14
star
51

galiano-drawing

A procedurally generated drawing
JavaScript
11
star
52

machining-projection-map

JavaScript
8
star
53

avrlass

AVR Lightweight Assembler (and disassembler)
JavaScript
6
star
54

60-212

JavaScript
5
star
55

teapot.lua

1 path tracer written in pure lua, 1 file, 0 dependencies.
Lua
5
star
56

Hello-World

Lorem Ipsum
3
star
57

cvDictUI

opencv-python tool for generating interactive GUI from any python dictionary
Python
3
star
58

lingdong

LingDong's project links
JavaScript
2
star
59

galiano-lidar-render

Semi-realistic rendering of LiDAR data from the entire Galiano Island, BC
C
1
star