dhad (ﺽ) is an experimental compiler (+ WASM interpreter) for a small Arabic programming language.
It is still very much in its infancy: the grammar is evolving, the runtime is tiny,
and most subsystems are rough prototypes.
The language uses a handwritten LALR(1) parser and an LLVM backend.
🧪 Try it out online on the web playground
I probably should've written the README and docs in Arabic, but I don't have an arabic keyboard nor the energy atm.
This is probabily the most straightforward way to get things going
-
Go to the repository Releases page
-
Download the archive for your platform:
dhad-linux-x86_64.tar.gzdhad-macos-x86_64.tar.gzdhad-macos-arm64.tar.gzdhad-windows-x86_64.zip(On Windows, the AST interpreter is shipped, not the compiler)
-
Extract the archive
Linux/macOS:
tar -xzf dhad-<platform>.tar.gz cd dhad-<platform>
Windows (PowerShell):
Expand-Archive .\dhad-windows-x86_64.zip -DestinationPath . cd .\dhad-windows-x86_64
-
Run the compiler
e.g. run the
hello-worldexampleLinux/macOS:
chmod +x dhad ./dhad examples/hello-world.dh -o hello ./hello
Windows (PowerShell):
.\dhad.exe examples\hello-world.dh
Alternatively, if you'd rather build from source:
-
Install prerequisites
- CMake 3.22 or newer
- LLVM (version >= 17)
- Clang/Clang++ toolchain (incl.
clang-format) - Python 3.10 or newer
-
Clone and configure
git clone https://github.com/mqqz/dhad.git cd dhad cmake -S . -B build
-
Build the compiler
make
-
Run the smoke tests (lexer, parser, codegen)
make test -
Try the hello world example
./build/dhad examples/hello-world.dh -o hello ./hello
- The standard library is injected by default (so
اطبعworks without an import). Imports are for pulling in other source files:استورد foo;loadsfoo.dhfrom the same directory. - Programs should expose an entry point called
دالة بداية(). - The parser/generator infrastructure relies on Python scripts in
tools/. Regenerate tables withcmake --build build --target parser_tables_genif you edit the grammar. make formatrunsclang-formatoversrc/andtests/.requirements.txthas the requirements for the python scripts.- Checkout
examples/for a basic feel on how things work. --emit-irflag can be used to output LLVM IR only (only Linux/MacOS).
Contributions are welcome, just be aware that the design is changing quickly and I am still figuring out the fundamentals. Tune in via issues/PRs if you want to help shape the language.
The compiler and interpreter now use signed 64-bit integers and double-precision
floats. Integer overflow, division by zero, and invalid array access fail with
runtime diagnostics. Logical operators short-circuit; string equality compares
contents and array equality compares identity. Composite/function equality and
top-level statements are rejected. Constants reject rebinding and direct indexed
writes. These are breaking changes to the experimental language; see GRAMMAR.md
for the execution rules. Native compilation finds clang on PATH; DHAD_CLANG
can override the executable. Previously emitted IR and native binaries must be rebuilt.
The browser C API still returns a heap-allocated UTF-8 string, freed with
dhad_free, but that string is now a JSON object with success, stdout, stderr,
ast, and exitCode fields. Ship the rebuilt WASM and worker together. Output
emitted before runtime failure is preserved, and program output is never parsed
as diagnostics.
For local browser validation, build with emcmake cmake -S . -B build/wasm -DDHAD_BUILD_WASM=ON, then build the dhad_web target. Assemble web/ and the
JS/WASM pair under a site directory with a build/ subdirectory. Install
tests/requirements-web.txt and Playwright Chromium, then run
node tests/web_worker_test.cjs and
python3 tests/run_web_tests.py --site-dir <site-directory>.