AutolangDocs

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.

๐ŸŒ Browser (WASM)๐Ÿ–ฅ๏ธ Node.js๐Ÿ“ฆ TypeScript ready

๐Ÿ“ฆ Installation

Install the latest version via npm. The package ships with a bundled WebAssembly module โ€” no native build steps required.

Terminal
$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 = 2
๐Ÿ’ก

How getOutput() works

All 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 = 10
โš ๏ธ

Sandbox safety

Always set a reasonable opcode limit when running untrusted user code. An unlimited execution (e.g. an infinite loop) will block the JavaScript event loop or freeze the browser tab.

๐Ÿ’ฅ 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(). Use setOnError() to receive them as a callback.
  • Runtime exceptions are thrown during program execution (e.g. throw, divide-by-zero). Check with hasException() / 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! // 42
๐Ÿ’ก

AutolangNativeFunc signature

The first argument 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 };