English | 中文 · Official site: moon-lang.com
MoonLang is a lightweight static programming language implemented in C++ with LLVM. It supports dual syntax styles (: end and { }), and runs on Windows, Linux, macOS, and embedded platforms (ARM/RISC-V/ESP32). Compiled binaries are 15KB–300KB, suitable for MCU to desktop applications.
This repository contains compiler source only (frontend + LLVM backend + runtime). It does not include the standard library .moon files, examples, or executables.
- Supported features
- Examples
- Syntax overview
- Deploying and using moonc
- Building this repository
- Build scripts
- Directory layout
- License and copyright
The runtime provides a full set of built-in capabilities. Modules can be disabled at build time via MOON_NO_XXX or at compile time via moonc --no-xxx for smaller binaries.
| Area | Description |
|---|---|
| Types | int, float, string, bool, null, list, dict, functions, classes, closures, BigInt (arbitrary precision) |
| Literals | Hex 0x, binary 0b, octal 0o; list/dict literals; multi-line strings |
| Operators | Arithmetic, comparison, logical, bitwise (& | ^ ~ << >>), power ^, string concat |
| Control flow | if/elif/else, while, for-in, for-to, switch, break, continue |
| Functions | Named functions, lambdas, default args, closures, variadic-style via list |
| OOP | Classes, inheritance, super, self, constructors init |
| Modules | import "path" as name, from "path" import a, b |
| Errors | Try/catch/finally, throw, exception value |
| Function / area | Description |
|---|---|
| Console | print, input |
| Files | read_file, write_file, append_file (binary-safe) |
| Paths | exists, is_file, is_dir, list_dir, create_dir, file_size, getcwd, cd |
| Path utils | join_path, basename, dirname, extension, absolute_path, copy_file, move_file, remove_file, remove_dir |
| Area | Description |
|---|---|
| Time | time, now (ms), unix_time, sleep |
| Format/parse | date_format, date_parse with format string and optional timezone |
| Components | year, month, day, hour, minute, second, millisecond, weekday, day_of_year, week_of_year, quarter |
| Arithmetic | make_time, add_seconds/minutes/hours/days/months/years, diff_seconds, diff_days |
| Ranges | start_of_day, end_of_day, start_of_month, end_of_month |
| Helpers | days_in_month, is_leap_year, is_weekend, is_today, is_same_day, timezone, utc_offset, set_timezone |
| Area | Description |
|---|---|
| Basic | abs, min, max, pow, sqrt, floor, ceil, round, sign, clamp, lerp |
| Trig | sin, cos, tan, asin, acos, atan, atan2, degrees, radians |
| Log/exp | log, log10, log2, exp, sinh, cosh, tanh, hypot |
| Stats | mean, median (on list) |
| Random | random_int, random_float |
| Area | Description |
|---|---|
| String ops | len, substring, split, join, replace, trim, upper, lower, capitalize, title, contains, starts_with, ends_with, index_of, find, repeat, chr, ord |
| Predicates | is_alpha, is_digit, is_alnum, is_space, is_lower, is_upper |
| Padding | pad_left, pad_right, ltrim, rtrim |
| Binary | bytes_to_string (byte list → string), strings are binary-safe (length stored in header) |
| WebSocket | ws_parse_frame, ws_create_frame (low-level frame parse/create) |
| Area | Description |
|---|---|
| List | Index, set, append, insert, pop, remove, len, slice, contains, index_of, reverse, sort, sum, first, last, take, drop, shuffle, choice, unique, flatten, zip, count |
| Functional | list_map, list_filter, list_reduce (with callback) |
| Dict | get, set, has_key, keys, values, items, delete, merge |
| Range | range(n) or range(start, end) or range(start, end, step) |
| Area | Description |
|---|---|
| TCP | tcp_connect, tcp_listen, tcp_accept, tcp_send, tcp_recv, tcp_close; non-blocking: tcp_set_nonblocking, tcp_has_data, tcp_select, tcp_accept_nonblocking, tcp_recv_nonblocking |
| UDP | udp_socket, udp_bind, udp_send, udp_recv, udp_close |
| TLS (OpenSSL) | tls_connect, tls_listen, tls_accept, tls_send, tls_recv, tls_recv_all, tls_close; verify/hostname, cert/key/CA load, tls_wrap_client / tls_wrap_server |
Controlled by MOON_HAS_NETWORK; TLS by MOON_HAS_TLS (optional OpenSSL). On Windows: IOCP/WSAPoll; on Linux: epoll.
| Area | Description |
|---|---|
| Basic | gui_init, gui_create, gui_show, gui_set_title, gui_set_size, gui_set_position, gui_close, gui_run, gui_quit, gui_alert, gui_confirm |
| Advanced | gui_create_advanced (options: frameless, transparent, topmost, resizable, etc.), WebView: gui_load_url, gui_load_html, gui_on_message (JS ↔ MoonLang bridge) |
| Tray | gui_tray_create, gui_tray_remove, gui_tray_set_menu, gui_tray_on_click, gui_show_window |
- Windows: WebView2 (embedded Chromium).
- Linux: WebKitGTK.
- macOS: WKWebView.
Controlled by MOON_HAS_GUI. Disabled in --target=embedded and --target=mcu.
| Area | Description |
|---|---|
| Match | regex_match, regex_search, regex_test, regex_groups, regex_named, regex_find_all, regex_find_all_groups |
| Replace | regex_replace, regex_replace_all |
| Split | regex_split, regex_split_n |
| Compiled | regex_compile, then regex_match_compiled, regex_search_compiled, regex_find_all_compiled, regex_replace_compiled, regex_free |
| Utils | regex_escape, regex_error |
Uses PCRE2. Disable with --no-regex or MOON_NO_REGEX.
| Function | Description |
|---|---|
json_encode |
Value → JSON string |
json_decode |
JSON string → value (list/dict/number/string/bool/null) |
Disable with --no-json or MOON_NO_JSON.
| Area | Description |
|---|---|
| Async | async(fn, ...args) — run on coroutine pool; yield; wait_all; num_goroutines, num_cpu |
| Channels | Go-style: chan() or chan(n) (buffered), chan_send, chan_recv, chan_close, chan_is_closed |
| Timers | set_timeout(callback, ms), set_interval(callback, ms), clear_timer(id) |
| Sync | mutex(), lock, unlock, trylock, mutex_free; Atomics: atomic_counter(initial), atomic_add, atomic_get, atomic_set, atomic_cas |
Controlled by MOON_HAS_ASYNC. Disabled in --target=mcu.
| Area | Description |
|---|---|
| DLL | dll_load(path), dll_close, dll_func(handle, name); call: dll_call_int, dll_call_double, dll_call_str, dll_call_void; alloc_str / free_str for C strings; ptr_to_str, read_ptr, read_int32, write_ptr, write_int32 |
| FFI | Declare C signatures in source; call C functions and pass/return values. |
Controlled by MOON_HAS_DLL / MOON_HAS_FFI. Disabled in --target=mcu.
| Area | Description |
|---|---|
| Process | argv, env, set_env, exit, shell, shell_output, platform, getpid, system, exec |
| Format | format(fmt, ...) (sprintf-style) |
| Memory (MCU) | mem_stats, mem_reset, target_info |
| GC | Reference counting + cycle collection; gc_collect, gc_enable, gc_set_threshold, gc_stats |
When built with HAL (e.g. ESP32, Raspberry Pi Pico, STM32):
| Area | Description |
|---|---|
| GPIO | gpio_init(pin, mode), gpio_write, gpio_read, gpio_deinit; modes: INPUT, OUTPUT, INPUT_PULLUP, INPUT_PULLDOWN |
| PWM | pwm_init(pin, freq), pwm_write(pin, duty), pwm_deinit |
| ADC | adc_init, adc_read, adc_deinit |
| I2C | i2c_init(sda, scl, freq), i2c_write(addr, data), i2c_read(addr, length), i2c_deinit |
| SPI | spi_init(mosi, miso, sck, freq), spi_transfer(data), spi_deinit |
| UART | uart_init(tx, rx, baud), uart_write, uart_read, uart_available, uart_deinit |
| Time | delay_ms, delay_us, millis, micros |
| System | hal_init_runtime, hal_deinit_runtime, hal_platform_name, hal_debug_print |
Controlled by MOON_HAS_HAL (optional).
| Flag / target | Effect |
|---|---|
| Default | Full: GUI, network, TLS, regex, JSON, filesystem, float, DLL, async |
--target=embedded |
No GUI; network and rest available |
--target=mcu |
No GUI, network, DLL, async, JSON; optional MOON_NO_FLOAT |
--no-gui |
No GUI module |
--no-network |
No TCP/UDP/TLS |
--no-regex |
No regex (saves PCRE2) |
--no-json |
No JSON |
MOON_NO_FILESYSTEM / MOON_NO_FFI / etc. |
Disable individual modules in C++ build |
The snippets below are runnable: save as .moon, then moonc demo.moon and run the generated executable (e.g. demo.exe or ./demo).
print("Hello, MoonLang!")
# Output: Hello, MoonLang!numbers = [10, 20, 30]
for n in numbers {
print(n * 2)
}
# Output: 20, 40, 60function greet(name) {
return "Hello, " + name + "!"
}
print(greet("World"))
# Output: Hello, World!Read a JSON file, read a field, write a result file:
content = read_file("config.json")
if content != null {
data = json_decode(content)
print(data["version"]) # e.g. "1.0"
}
write_file("out.txt", "done")Create config.json with {"version": "1.0"} before running.
Simple HTTP GET over TCP:
sock = tcp_connect("127.0.0.1", 8080)
if sock != null and sock != -1 {
tcp_send(sock, "GET / HTTP/1.0\r\n\r\n")
reply = tcp_recv(sock)
print(reply)
tcp_close(sock)
} else {
print("Connection failed")
}Run with a server listening on port 8080, or change host/port.
Match and replace:
s = "foo 123 bar 456"
m = regex_match(s, "\\d+")
print(m) # 123
out = regex_replace_all(s, "\\d+", "X")
print(out) # foo X bar XGo-style channel: one coroutine sends, main receives:
ch = chan(0)
async(() => {
chan_send(ch, "hello from async")
})
msg = chan_recv(ch)
print(msg) # hello from async
chan_close(ch)class Counter {
function init() { self.n = 0 }
function inc() { self.n += 1; return self.n }
}
c = new Counter()
print(c.inc()) # 1
print(c.inc()) # 2Used when building a shared library (moonc mylib.moon --shared -o mylib.dll):
export function add(a, b) { return a + b }
export function greet(name) { return "Hello, " + name }# Integer, float, string, bool, null
x = 42
pi = 3.14159
name = "MoonLang"
flag = true
nothing = null
# Hex 0x, binary 0b, octal 0o
hex = 0xFF
bin = 0b1010
# List and dict
numbers = [1, 2, 3]
person = {"name": "Alice", "age": 25}
# Multiple assignment
x = y = z = 10Use global to assign to a global variable inside a function; otherwise the assignment creates a local variable.
Use one style per file (do not mix):
- Traditional:
:to start,endto close - Brace syntax:
{}around the block
# if / elif / else
if x > 10 { print("big") } elif x > 5 { print("mid") } else { print("small") }
# while
while i < 10 { print(i); i += 1 }
# for-in / for-to
for item in [1, 2, 3] { print(item) }
for i = 1 to 10 { print(i) }
# switch
switch n { case 1: print("One") case 2, 3: print("Two or Three") default: print("Other") }
# break / continue
for i = 1 to 100 { if i > 10 { break } }# Function (traditional or brace)
function add(a, b) { return a + b }
function greet(name, greeting="Hello") { return greeting + ", " + name }
# Lambda, closure, default args
square = (x) => x * x
x = 10
add_x = (y) => x + yclass Animal {
function init(name, species) {
self.name = name
self.species = species
}
function speak() { print(self.name, "says something") }
}
class Dog extends Animal {
function init(name) { super.init(name, "Canine") }
function speak() { print(self.name, "says Woof!") }
}
dog = new Dog("Max")
dog.speak()# Import
import "stdlib/io.moon" as io
from "stdlib/net.moon" import TcpClient, TcpServer
# Single-line # and multi-line """After building this repo you get moonc.exe (or moonc on Linux/macOS), used to compile .moon source into native executables or libraries.
moonc hello.moon
moonc hello.moon -o myapp.exe
moonc hello.moon --icon app.ico- Automatically bundles
imported modules and files referenced byread_file(); for GUI, resources referenced bygui_load_url("file:///...")are embedded. - Common options:
-ooutput name,--icon,--company,--copyright,--description,--file-version,--product-name,--product-version.
| Target / option | Description |
|---|---|
| Default | Full desktop EXE/ELF |
--target=embedded |
Embedded Linux, no GUI |
--target=mcu |
MCU minimal (no GUI/network/DLL) |
--no-gui / --no-network / --no-regex / --no-json |
Disable features as needed |
moonc app.moon
moonc app.moon --target=embedded
moonc app.moon --no-gui --no-regexYou can compile a MoonLang module into a shared library (DLL on Windows, .so on Linux, .dylib on macOS) and call its exported functions from C, C++, Python, or other languages.
1. Export functions in source
Only functions marked with export are exposed:
export function add(a, b) { return a + b }
export function greet(name) { return "Hello, " + name }2. Build the shared library
| Platform | Command (output) |
|---|---|
| Windows | moonc mylib.moon --shared -o mylib.dll |
| Linux | moonc mylib.moon --shared -o mylib.so |
| macOS | moonc mylib.moon --shared -o mylib.dylib |
Optional: generate a C header for the exported symbols:
moonc mylib.moon --shared -o mylib.dll --header mylib.h3. Use from C
The generated header declares the runtime init and your exports. Example usage:
#include "mylib.h"
int main(void) {
moon_runtime_init(0, NULL);
MoonValue* r = mylib_add(moon_int(2), moon_int(3)); // 5
moon_release(r);
moon_runtime_cleanup();
return 0;
}Link your program against mylib.dll (or mylib.so / mylib.dylib) and the MoonLang runtime. The DLL/SO embeds the compiled code and uses the same runtime ABI.
4. Summary
| Option | Description |
|---|---|
--shared |
Build a shared library instead of an executable |
-o <file> |
Output path (e.g. mylib.dll, mylib.so, libfoo.dylib) |
--header <file> |
Emit a C header with declarations for exported functions |
-
Visual Studio 2022
- Download: Visual Studio 2022.
- During setup, select the “Desktop development with C++” workload.
- The script uses
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat. If you use Professional or Enterprise, changeCommunityin that path accordingly.
-
LLVM (prebuilt)
- Download from LLVM releases — choose the Windows MSVC build (e.g.
clang+llvm-21.1.8-x86_64-pc-windows-msvcor newer). - Extract to a folder such as
C:\LLVM-dev\clang+llvm-21.1.8-x86_64-pc-windows-msvc. - Note the full path; you will set it in the next step.
- Download from LLVM releases — choose the Windows MSVC build (e.g.
-
Open
rebuild_all.batand find the line (around line 29):
set LLVM_DIR=C:\LLVM-dev\clang+llvm-21.1.8-x86_64-pc-windows-msvc
Set the right-hand side to your LLVM path (no trailing backslash). -
Open
llvm_libs.rsp. Every line is a path to an LLVM.libfile. Replace the prefix
C:\LLVM-dev\clang+llvm-21.1.8-x86_64-pc-windows-msvc
with your LLVM path in all lines.
Optional — auto-detect LLVM and build:
Run python build_auto.py in the repo root. It detects LLVM (from LLVM_PATH/LLVM_DIR, or common install locations), writes llvm_libs.rsp and rebuild_auto.bat (with the correct path), then runs the build. Use --no-run to only generate files; use --llvm C:\path\to\llvm to force a path.
- Go to the repository root (where
rebuild_all.batlives). - Double-click
rebuild_all.bator run it from a “x64 Native Tools Command Prompt for VS”:rebuild_all.bat - The script will:
- Set up the MSVC environment
- Use PCRE2/OpenSSL if present under
lib\pcre2andlib\openssl - Generate
llvm\version.hfromversion.json - Build the runtime and produce
llvm\moonrt.lib - Build and link the compiler to produce
moonc.exe(in the repo root or the script’s output directory) - If
pack_dist.batexists, run it to populatedist\moonscript\
| Dependency | Purpose | Notes |
|---|---|---|
| PCRE2 | Regex engine | Place PCRE2 source in lib\pcre2\ and build as required, or run lib\pcre2\download_pcre2.bat if present. Without it, the build uses std::regex. |
| OpenSSL | TLS/HTTPS | Place OpenSSL libraries and headers in lib\openssl\ (see lib\openssl\README.md if present). Without it, TLS is disabled. |
| WebView2 | Windows GUI | Place WebView2 files in webview2\. Without it, GUI may be limited or unavailable. |
From the repo root, use build/build_linux.sh. Install:
-
Runtime only (no
moonc):
sudo apt install build-essential cmake
(Ubuntu/Debian; other distros: install g++, cmake as appropriate.) -
Compiler (to get
moonc):
Also install LLVM:
sudo apt install llvm-dev
(orlibllvm-dev, depending on distro.) -
With GUI (WebKitGTK):
sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev
(orlibwebkit2gtk-4.1-dev; the script detects either.)
Optional:libappindicator3-devfor system tray.
Example (Ubuntu/Debian):
# Runtime + compiler, no GUI
sudo apt install build-essential cmake llvm-dev
# Runtime + compiler + GUI
sudo apt install build-essential cmake llvm-dev pkg-config libgtk-3-dev libwebkit2gtk-4.0-devFrom the repo root:
cd build
chmod +x build_linux.sh
./build_linux.sh --help # list optionsCommon commands:
| Command | Description |
|---|---|
./build_linux.sh |
Build runtime only (no moonc) |
./build_linux.sh --compiler |
Build runtime + compiler (requires llvm-dev); produces moonc |
./build_linux.sh --compiler --no-gui |
Build compiler without GUI (e.g. for servers) |
./build_linux.sh --clean |
Clean build directory |
./build_linux.sh --install |
Install to system (path shown by script) |
Output is under build/linux_build/; the moonc binary is in that directory or the path printed by the script.
-
Xcode Command Line Tools (required):
xcode-select --install
Follow the prompt to install.
-
Homebrew (recommended, for CMake, LLVM, OpenSSL):
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Apple Silicon:
/opt/homebrew; Intel:/usr/local. -
CMake, LLVM, OpenSSL:
brew install cmake llvm openssl@3
-
Add LLVM to PATH (so
llvm-configis found):- Apple Silicon:
export PATH="/opt/homebrew/opt/llvm/bin:$PATH" - Intel:
export PATH="/usr/local/opt/llvm/bin:$PATH"Add the appropriate line to~/.zshrcor~/.bash_profileto make it permanent.
- Apple Silicon:
From the repo root:
cd build
chmod +x build_macos.sh
./build_macos.sh --help # list optionsCommon commands:
| Command | Description |
|---|---|
./build_macos.sh |
Build runtime only |
./build_macos.sh --compiler |
Build runtime + compiler (LLVM must be in PATH) |
./build_macos.sh --compiler --no-gui |
Build compiler without GUI |
./build_macos.sh --no-tls |
Do not link OpenSSL; TLS disabled |
./build_macos.sh --clean |
Clean build directory |
./build_macos.sh --install |
Install to system |
Output is under build/macos_build/. If OpenSSL is not installed or you use --no-tls, TLS support is disabled.
| File | Purpose |
|---|---|
rebuild_all.bat |
Windows full rebuild |
link_llvm.cmd / llvm_libs.rsp |
Link moonc.exe |
pack_dist.bat |
Package distribution |
build/build_linux.sh |
Linux build (--compiler, --no-gui, --clean, --install) |
build/build_macos.sh |
macOS build (--compiler, --no-gui, --no-tls, --clean, --install) |
| Path | Description |
|---|---|
lexer.* parser.* ast.h token.h alias_loader.* |
Compiler frontend |
llvm/ |
LLVM codegen and runtime |
lib/ |
Third-party (pcre2, openssl, db) |
webview2/ |
Windows GUI |
build/ |
Linux/macOS build |
This project is under GNU General Public License v3.0 (GPLv3). See LICENSE.
- Open-source use: You may copy, modify, and distribute under GPLv3; modified versions must be released under GPLv3 with source.
- Proprietary / commercial use of modified compiler: If you modify this compiler and distribute or use it in closed-source or commercial form, you must obtain a commercial license and pay the applicable fee from the copyright holder. Contact: forkp@greenteng.com.
Copyright (c) 2026 moon-lang.com