npm Integration Guide
The autolang-compiler package lets you embed and run the Autolang language directly inside any JavaScript or TypeScript project โ in the browser via WebAssembly, or server-side via Node.js.
๐ฆ Installation
Install the latest version via npm. The package ships with a bundled WebAssembly module โ no native build steps required.
npm install autolang-compiler@latest๐ Basic Usage
Create a compiler instance with ACompiler.create(), then call compileAndRun() and retrieve output via getOutput().
import { ACompiler } from 'autolang-compiler';
// 1. Create the compiler instance (loads WebAssembly asynchronously)
const compiler = await ACompiler.create();
// 2. Compile and run Autolang code
compiler.compileAndRun("main.al", `
println("Hello from Autolang!")
println("1 + 1 = " + (1 + 1))
`);
// 3. Retrieve all printed output
const output = compiler.getOutput();
console.log(output);
// Hello from Autolang!
// 1 + 1 = 2How getOutput() works
print and println calls inside Autolang are captured internally. Call compiler.getOutput() after execution to retrieve the printed output. Use compiler.clearOutput() before a new run if you want a clean output buffer.โ๏ธ Compile & Run Separately
For advanced use-cases you can split compilation and execution. This lets you validate code, inspect errors, then run โ or run multiple times without re-compiling.
import { ACompiler } from 'autolang-compiler';
const compiler = await ACompiler.create();
const code = `println("Running step: " + step)`;
// Compile only โ returns true if successful
const ok = compiler.compile("main.al", code);
if (compiler.hasCompilerError()) {
console.error("Compilation failed!");
} else {
// Run the compiled bytecode (can be called multiple times)
compiler.run();
console.log(compiler.getOutput());
// Re-run after clearing output
compiler.clearOutput();
compiler.run();
console.log(compiler.getOutput());
}
// Reset the compiler state entirely before next compilation
compiler.refresh();๐ข Opcode Execution Limit
To protect against infinite loops or runaway scripts, you can cap how many virtual machine instructions (opcodes) can be executed in a single run. The default limit is 1000.
import { ACompiler } from 'autolang-compiler';
const compiler = await ACompiler.create();
// Set a custom opcode limit (e.g. 50 000 ops)
compiler.setLimitOpcodeCount(50_000);
// Set to INT32_MAX to effectively disable the limit
compiler.setLimitOpcodeCount(2_147_483_647);
compiler.compileAndRun("main.al", `
var i = 0
while (true) {
i = i + 1
if (i >= 10) break
}
println("i = " + i)
`);
console.log(compiler.getOutput()); // i = 10Sandbox safety
๐ฅ Exception Handling
Autolang supports runtime exceptions (errors thrown during execution, distinct from compile-time errors). Use hasException() and getException() to detect and inspect them from the host side.
import { ACompiler } from 'autolang-compiler';
const compiler = await ACompiler.create();
compiler.compileAndRun("main.al", `
throw Exception("Something went wrong!")
`);
if (compiler.hasException()) {
const err = compiler.getException();
// err is AException | null
// AException = { message: string }
console.error("Runtime exception:", err?.message);
// Runtime exception: Something went wrong!
}
// You can also throw exceptions from the host side:
// compiler.throwException("Triggered from JavaScript");Exceptions vs Compiler Errors
- Compiler errors occur during compilation โ check with
hasCompilerError(). UsesetOnError()to receive them as a callback. - Runtime exceptions are thrown during program execution (e.g.
throw, divide-by-zero). Check withhasException()/getException().
๐ Registering Native Libraries
You can extend Autolang with custom functions backed by JavaScript โ great for I/O, DOM manipulation, or bridging your existing APIs. Use registerBuiltInLibrary() to declare an Autolang source interface and bind it to native JS implementations.
import { ACompiler, AutolangNativeFunc, LibraryConfig } from 'autolang-compiler';
const compiler = await ACompiler.create();
// Define native implementations
// AutolangNativeFunc = (thisArg, ...args) => number | string | boolean | null | void
const greet: AutolangNativeFunc = (_thisArg, name) => {
return `Hello, ${name}!`;
};
const add: AutolangNativeFunc = (_thisArg, a, b) => {
return (a as number) + (b as number);
};
// LibraryConfig controls compiler behavior for this library
const config: LibraryConfig = {
autoImport: true, // auto-imported into all files (no @import needed)
allowLateinitKeyword: false,
allowNonNullAssertion: false,
};
// Register the library: name, Autolang type declarations, config, native bindings
compiler.registerBuiltInLibrary(
"my/utils",
`
@native("greet")
func greet(name: String): String
@native("add")
func add(a: Int, b: Int): Int
`,
config,
{ greet, add }
);
compiler.compileAndRun("main.al", `
println(greet("World"))
println(add(10, 32))
`);
console.log(compiler.getOutput());
// Hello, World!
// 42AutolangNativeFunc signature
thisArg is the Autolang object instance the method was called on (for instance methods). For top-level functions it will be undefined. Remaining ...args correspond to the declared Autolang function parameters in order.๐ Error & Warning Callbacks
Subscribe to compiler diagnostics in real time using setOnError() and setOnWarning(). These are called during compilation, not at runtime.
import { ACompiler } from 'autolang-compiler';
const compiler = await ACompiler.create();
// Subscribe to compiler errors
compiler.setOnError((message: string) => {
console.error("[Autolang Error]", message);
});
// Subscribe to compiler warnings
compiler.setOnWarning((message: string) => {
console.warn("[Autolang Warning]", message);
});
// This will trigger the error callback
compiler.compile("main.al", `
val x: Int = "not a number"
`);
// Unsubscribe by passing null
compiler.setOnError(null);
compiler.setOnWarning(null);๐ ๏ธ Main Source Config
setMainSourceConfig() lets you adjust compiler strictness for the main user code (not libraries). Useful for enabling advanced features or relaxing constraints.
import { ACompiler, LibraryConfig } from 'autolang-compiler';
const compiler = await ACompiler.create();
const config: LibraryConfig = {
allowNonNullAssertion: true, // allow the ! postfix operator
allowLateinitKeyword: true, // allow lateinit var declarations
};
compiler.setMainSourceConfig(config);
compiler.compileAndRun("main.al", `
lateinit var name: String
name = "Autolang"
println(name!)
`);
console.log(compiler.getOutput()); // Autolang๐ Full Type Reference
Complete TypeScript definitions exported from the package.
// โโ Primitive types โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
type AObject = number;
type AutolangType = number | null | undefined | string | boolean | void | AObject;
// Native function bound to an Autolang function declaration.
type AutolangNativeFunc = (thisArg: AutolangType, ...args: AutolangType[]) => (number | null | string | boolean | void);
// โโ Compiler configuration โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
interface ACompilerConfig {
addStdFile?: boolean;
addStdRegex?: boolean;
addStdJson?: boolean;
addStdMath?: boolean;
}
// โโ Library configuration โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
interface LibraryConfig {
autoImport?: boolean;
allowLateinitKeyword?: boolean;
allowNonNullAssertion?: boolean;
}
// โโ Runtime exception object โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
interface AException {
message: string;
}
// โโ Main compiler class โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
declare class ACompiler {
static create(config?: ACompilerConfig): Promise<ACompiler>;
getOutput(): any;
clearOutput(): void;
registerBuiltInLibrary(
name: string,
source: string,
config?: LibraryConfig,
methods?: Record<string, AutolangNativeFunc>
): void;
setMainSourceConfig(config: LibraryConfig): void;
setLimitOpcodeCount(limit: number): void;
compileAndRun(path: string, code: string): boolean;
compile(path: string, code: string): boolean;
run(): boolean;
hasCompilerError(): boolean;
throwException(message: string): boolean;
hasException(): boolean;
getException(): AException | null;
setOnError(callback: ((error: string) => void) | null): void;
setOnWarning(callback: ((warning: string) => void) | null): void;
refresh(): void;
}
export {
ACompiler,
type ACompilerConfig,
type AException,
type AObject,
type AutolangNativeFunc,
type AutolangType,
type LibraryConfig
};