Compiler (onionc)¶
The onionc command compiles Onion source files into JVM class files.
Usage¶
Options¶
-classpath <classpath>¶
Set the classpath for compilation. Used when your code references external Java libraries or other compiled Onion classes.
-encoding <encoding>¶
Specify the character encoding of source files. Default is platform-dependent.
-d <output directory>¶
Set the output directory for generated class files. If not specified, classes are written to the current directory.
Class files are organized by module name:
- Unix-like: org/onion_lang/MyClass.class
- Windows: org\onion_lang\MyClass.class
-maxErrorReport <count>¶
Limit the number of compilation errors reported. Useful for large projects with many errors.
-super <super class>¶
Specify the class a top-level script's synthesized class extends. Only meaningful when the source has no explicit class declaration.
--verbose¶
Show timing for each compilation phase (parsing, rewriting, type checking, code generation) as it runs.
--dump-ast¶
Print the parsed AST to stderr. Useful when debugging syntax and parsing.
--dump-typed-ast¶
Print a typed AST summary (classes, fields, methods) to stderr.
--profile-compile¶
Emit a compile profile with per-phase timing, source count, classpath size, and generated class count.
--profile-format <text|json>¶
Choose how the compile profile is rendered.
--profile-output <target>¶
Write the compile profile to stderr, stdout, or a file path.
onionc --profile-compile --profile-format json \
--profile-output target/profile.json \
MyProgram.on
--warn <off|on|error>¶
Control warning reporting. error treats warnings as compilation errors.
--Wno <codes>¶
Suppress specific warning categories by code or name.
Every code accepts either its W#### form or the --Wno name shown below:
| Code | Name | Description |
|---|---|---|
W0001 |
unused-variable |
Unused variable |
W0002 |
unused-import |
Unused import |
W0003 |
unreachable-code |
Unreachable code |
W0004 |
deprecated, deprecated-feature |
Deprecated feature |
W0005 |
shadowed-variable |
Shadowed variable |
W0006 |
unused-parameter |
Unused parameter |
W0007 |
empty-block |
Empty block |
W0008 |
redundant-cast |
Redundant cast |
W0009 |
possible-null-deref, null-deref |
Possible null dereference |
W0010 |
unnecessary-conversion |
Unnecessary type conversion |
W0011 |
unchecked-cast |
Unchecked cast |
W0012 |
null-to-non-nullable |
Null assigned to non-nullable type |
W0013 |
suspicious-interpolation |
Suspicious string interpolation syntax |
W0014 |
discarded-toplevel |
Top-level statements ignored because a main is defined |
W0015 |
platform-unboxing |
Boxed platform value implicitly unboxed to a non-null primitive |
--no-check-laws¶
Do not execute a record's law / example clauses.
They run at compile time by default, which means the compiler executes that code.
Turn them off when compiling a file you do not want to run — the trade-off is that
invariants like parse ∘ format == id stop being checked.
--law-seed <n> / --law-samples <n>¶
Control how law clauses are sampled. A falsified law reports the settings that
produced its counterexample, so the run can be repeated exactly; raising the sample
count widens the search for others.
--effects¶
Print each compiled method's inferred effect set (read write net exec env clock rand
console unknown; empty means pure) to stderr.
Examples¶
Basic Compilation¶
Compile a single file:
This creates Hello.class in the current directory.
Multiple Files¶
Compile multiple source files:
With Output Directory¶
Organize output:
Class files appear in out/classes/.
With Classpath¶
Reference external libraries:
Complete Example¶
onionc \
-d build/classes \
-classpath lib/external.jar \
-encoding UTF-8 \
-maxErrorReport 20 \
src/*.on
Running Compiled Programs¶
After compilation, run with Java:
Or with a JAR:
# Compile
onionc -d build Main.on Helper.on
# Create JAR
jar cvfe program.jar Main -C build .
# Run JAR
java -jar program.jar
Module Organization¶
Onion uses module names (packages) similar to Java:
MyClass.on:
module com.example.myapp
class MyClass {
public:
static def main(args :String[]): void {
println("Hello")
}
}
Compile:
Output:
Run:
Compilation Errors¶
Common Errors¶
Type mismatch:
Undefined variable:
Method not found:
Incremental Compilation¶
onionc compiles all specified files each time. For large projects, consider:
- Compile only changed files
- Use a build tool (Make, SBT, Gradle)
- Organize code into modules
Build Integration¶
Makefile Example¶
SRC_DIR = src
OUT_DIR = build/classes
SOURCES = $(wildcard $(SRC_DIR)/*.on)
all: compile
compile:
mkdir -p $(OUT_DIR)
onionc -d $(OUT_DIR) $(SOURCES)
clean:
rm -rf $(OUT_DIR)
run: compile
java -cp $(OUT_DIR) Main
Shell Script Example¶
#!/bin/bash
SRC_DIR="src"
OUT_DIR="build/classes"
CLASSPATH="lib/*"
mkdir -p "$OUT_DIR"
echo "Compiling Onion sources..."
onionc -d "$OUT_DIR" -classpath "$CLASSPATH" "$SRC_DIR"/*.on
if [ $? -eq 0 ]; then
echo "Compilation successful"
echo "Running program..."
java -cp "$OUT_DIR:$CLASSPATH" Main
else
echo "Compilation failed"
exit 1
fi
Compiler Output¶
Successful Compilation¶
No output typically means success:
Compilation Errors¶
Errors are written to standard error:
$ onionc BadProgram.on
Error: Type mismatch at BadProgram.on:5
Error: Undefined variable at BadProgram.on:10
Compilation failed with 2 errors
Separate Compilation and Linking¶
Onion units can be compiled independently and linked at load time through the
classpath — you do not need all sources in one onionc invocation. Compile a
library, then compile clients against the emitted .class files.
Compile the library first:
// greeter/Greeter.on
class Greeter {
public:
def this {}
def greet(name: String): String = "Hello, " + name
}
Then compile a client against it by putting the library output on the classpath:
// app/Main.on
class Main {
public:
static def main(args: String[]): void {
IO::println((new Greeter()).greet("Onion"))
}
}
Linking is the JVM's job — run with every output directory (and onion.jar for
the runtime) on the classpath:
Classes, interfaces, records, enums, inheritance, static members and generic
types all cross unit boundaries. A generic type keeps its type parameters,
because onionc writes JVM generic signatures into the .class file:
onionc -d out/lib Container.on # class Container[T]
onionc -d out/app -classpath out/lib App.on # new Container[String](x) resolves
Compile units in dependency order (a unit must be compiled after the units it references). There is no incremental build cache — recompile a unit's dependents when its public API changes.
Next Steps¶
- Script Runner - Run Onion scripts directly
- REPL Shell - Interactive programming
- Building from Source - Build the compiler