luma-lang
Version:
The Embeddable Luma Language Compiler and Runtime
1,057 lines (1,035 loc) • 33.6 kB
TypeScript
declare enum Opcode {
HALT = "HALT",// Stop execution
CONST = "CONST",// Push a value onto the stack
SWAP = "SWAP",// Swap top two values on the stack
EXPORT = "EXPORT",// Mark top of stack for export (2 values: name, value)
IMPORT = "IMPORT",// Import a module (arg: module name)
WAIT = "WAIT",// Pause execution for X milliseconds (stack: [duration])
NEW = "NEW",// Stack: [arg1, arg2..., class] -> Instance
SUPER = "SUPER",// Invoke parent method ({name: string, args: number})
ADD = "ADD",
SUB = "SUB",
MUL = "MUL",
DIV = "DIV",
MOD = "MOD",
EXP = "EXP",
NEG = "NEG",
EQ = "EQ",
NEQ = "NEQ",
GT = "GT",
GTE = "GTE",
LT = "LT",
LTE = "LTE",
IN = "IN",
IS = "IS",
NOT = "NOT",
JMP = "JMP",// Unconditional Jump
JMP_IF_FALSE = "JMP_IF_FALSE",// Jump if top of stack is false
JMP_IF_TRUE = "JMP_IF_TRUE",// Jump if top is true (pops value)
DUP = "DUP",// Duplicate top value (A -> A, A)
POP = "POP",// Discard top value (A -> )
LOAD = "LOAD",// Load variable value onto stack
STORE = "STORE",// Store top of stack into variable
LOAD_LOCAL = "LOAD_LOCAL",// Load local slot value onto stack
STORE_LOCAL = "STORE_LOCAL",// Store top of stack into local slot
CALL = "CALL",// { name: string, addr: number, args: number }
CALL_METHOD = "CALL_METHOD",// { name: string, args: number }
CALL_PARENT = "CALL_PARENT",// arg: number of args
RET = "RET",
MAKE_ARRAY = "MAKE_ARRAY",// Stack: [arg1, arg2...] -> Array
MAKE_RANGE = "MAKE_RANGE",// Stack: [start, end] -> Range
MAKE_OBJECT = "MAKE_OBJECT",// Stack: [key1, val1...] -> Object
MAKE_FUNCTION = "MAKE_FUNCTION",// { name: string, addr: number, args: number }
MAKE_CLASS = "MAKE_CLASS",// [ name, startIndex ]
MAKE_METHOD = "MAKE_METHOD",// Stack: [{ ... MAKE_FUNCTION result ... }]
GET_PROP = "GET_PROP",// Stack: [Object, Key] -> [Value]
SET_PROP = "SET_PROP",// Stack: [Object, Key, Value] -> [Value]
ITER_INIT = "ITER_INIT",// Stack: [Array] -> [Iterator]
ITER_NEXT = "ITER_NEXT",// Stack: [Iterator] -> [Value] (or Jump if done)
ARRAY_PUSH = "ARRAY_PUSH"
}
declare enum OpcodeBytes {
HALT = 0,
CONST = 1,
SWAP = 2,
EXPORT = 3,
IMPORT = 4,
WAIT = 5,
NEW = 6,
SUPER = 7,
ADD = 16,
SUB = 17,
MUL = 18,
DIV = 19,
MOD = 20,
EXP = 21,
NEG = 22,
EQ = 32,
NEQ = 33,
GT = 34,
GTE = 35,
LT = 36,
LTE = 37,
IN = 38,
IS = 39,
NOT = 48,
JMP = 64,
JMP_IF_FALSE = 65,
JMP_IF_TRUE = 66,
DUP = 67,
POP = 68,
LOAD = 80,
STORE = 81,
LOAD_LOCAL = 82,
STORE_LOCAL = 83,
CALL = 96,
CALL_METHOD = 97,
CALL_PARENT = 98,
RET = 99,
MAKE_ARRAY = 112,
MAKE_RANGE = 113,
MAKE_OBJECT = 114,
MAKE_FUNCTION = 115,
MAKE_CLASS = 116,
MAKE_METHOD = 117,
GET_PROP = 128,
SET_PROP = 129,
ITER_INIT = 144,
ITER_NEXT = 145,
ARRAY_PUSH = 146
}
type Program = {
hash: string;
source: string;
moduleName?: string;
instructions: Instruction[];
references: {
functions: Record<string, CallableAddress>;
events: Record<string, CallableAddress>;
};
exported: {
functions: string[];
variables: string[];
};
};
type CallableAddress = {
address: number;
numArgs: number;
};
interface Instruction {
op: Opcode;
arg?: any;
comment?: string;
pos?: {
lineStart: number;
lineEnd: number;
columnStart: number;
columnEnd: number;
};
}
declare class Reader {
/**
* Reads a Luma program from a binary Uint8Array.
*
* @param {Uint8Array} data
* @returns {Program}
*/
static read(data: Uint8Array): Program;
private readonly reader;
private pool;
private withDebugInfo;
private constructor();
private read;
private readHeader;
private readConstants;
private readExports;
private readReferences;
private readInstructions;
private readSource;
private readValueArg;
private getPoolString;
}
declare class Writer {
/**
* Writes the given program to a binary format.
*
* Includes an option to add debug information such as source code and
* instruction comments, as well as line/column positions. This may be
* useful for debugging, but increases the size of the output binary.
*
* @param {Program} program
* @param {boolean} withDebugInfo - Whether to include debug information.
* @returns {Uint8Array}
*/
static write(program: Program, withDebugInfo: boolean): Uint8Array;
private readonly program;
private readonly writer;
private readonly pool;
private readonly withDebugInfo;
private constructor();
private write;
private writeHeader;
private writeConstants;
private writeExports;
private writeReferences;
private writeInstructions;
private writeSource;
private writeValueArg;
private getPoolId;
}
declare class Compiler {
private loopStack;
private currentPos;
private pendingCalls;
private currentClassName;
private localScopes;
private program;
static compile(source: string, moduleName?: string): Program;
private compile;
private visit;
private visitBinaryExpression;
private visitLogicalExpression;
private visitUnaryExpression;
private visitMethodDefinition;
private visitIfStatement;
private visitCallExpression;
private visitArrayExpression;
private visitObjectExpression;
private visitObjectComprehension;
private visitMemberExpression;
private visitAssignmentExpression;
private visitArrayComprehension;
private visitForStatement;
private visitWhileStatement;
private visitDoWhileStatement;
private visitBreakStatement;
private visitContinueStatement;
private visitClassStatement;
private visitNewExpression;
private visitParentMethodCallExpression;
private hoistFunctions;
private hoistEventHooks;
private emit;
private patch;
private replaceIdentifier;
/**
* Creates a 32-character hash of the program source.
*
* @private
*/
private createHash;
private throwError;
private enterLocalScope;
private exitLocalScope;
private get currentLocalScope();
private ensureLocalSlot;
private getLocalSlot;
private emitLoadByName;
private emitStoreByName;
}
declare const Keywords: readonly ["fn", "on", "if", "else", "do", "while", "for", "in", "break", "continue", "return", "true", "false", "null", "not", "this", "and", "or", "local", "public", "import", "wait", "new", "class", "extends", "parent"];
declare const Operators: {
readonly ASSIGN: "=";
readonly PLUS: "+";
readonly MINUS: "-";
readonly MULTIPLY: "*";
readonly DIVIDE: "/";
readonly MODULO: "%";
readonly EXPONENTIATION: "^";
readonly EQUALS: "==";
readonly NOT_EQUALS: "!=";
readonly GREATER_THAN: ">";
readonly LESS_THAN: "<";
readonly GREATER_EQUAL: ">=";
readonly LESS_EQUAL: "<=";
readonly NOT: "!";
readonly RANGE: "..";
readonly IS: "is";
};
declare const Punctuation: {
readonly MEMBER_ACCESS: ".";
readonly COMMA: ",";
readonly COLON: ":";
readonly QUESTION_MARK: "?";
readonly OPEN_PAREN: "(";
readonly CLOSE_PAREN: ")";
readonly OPEN_BRACKET: "[";
readonly CLOSE_BRACKET: "]";
readonly OPEN_BRACE: "{";
readonly CLOSE_BRACE: "}";
readonly BANG: "!";
};
declare const TokenType: {
readonly IDENTIFIER: "IDENTIFIER";
readonly KEYWORD: "KEYWORD";
readonly OPERATOR: "OPERATOR";
readonly PUNCTUATION: "PUNCTUATION";
readonly STRING: "STRING";
readonly NUMBER: "NUMBER";
readonly COMMENT: "COMMENT";
readonly BLOCK_COMMENT: "BLOCK_COMMENT";
readonly NEWLINE: "NEWLINE";
readonly INDENT: "INDENT";
readonly DEDENT: "DEDENT";
readonly EOF: "EOF";
};
type TokenPosition = {
lineStart: number;
lineEnd: number;
columnStart: number;
columnEnd: number;
};
type Token = {
type: keyof typeof TokenType;
value: string;
position: TokenPosition;
};
declare class TokenStream {
private readonly _tokens;
private _index;
constructor(tokens: Token[]);
get tokens(): Token[];
get length(): number;
peek(offset?: number): Token | null;
consume(): Token;
get isEof(): boolean;
}
declare class Tokenizer {
private static readonly KEYWORD_SET;
private static readonly PUNCTUATION_SET;
private static readonly SYMBOL_MAP;
private static readonly SORTED_SYMBOLS;
private readonly _tokens;
private readonly _source;
private readonly _moduleName;
private index;
private line;
private col;
private indentStack;
private isAtStartOfLine;
private constructor();
static tokenize(source: string, moduleName?: string | undefined): TokenStream;
private tokenize;
private handleNewline;
private handleIndentation;
private parseWord;
private parseSymbol;
private parseNumberLiteral;
private parseStringLiteral;
private parseInterpolationSegments;
private extractBalancedExpression;
private unescapeString;
private currentPos;
private stripInterpolatedIndentation;
private stripIndentation;
private parseComment;
private parseBlockComment;
private createToken;
private advance;
private get isEof();
private throwError;
private throwUnexpectedCharacterError;
private tokenizeExpression;
}
type NodeType = 'Script' | 'Block' | 'FunctionDeclaration' | 'MethodDefinition' | 'IfStatement' | 'ReturnStatement' | 'ExpressionStatement' | 'AssignmentExpression' | 'BinaryExpression' | 'LogicalExpression' | 'UnaryExpression' | 'CallExpression' | 'MemberExpression' | 'ArrayExpression' | 'ArrayComprehension' | 'ObjectExpression' | 'ObjectComprehension' | 'Property' | 'Identifier' | 'Literal' | 'ForStatement' | 'WhileStatement' | 'DoWhileStatement' | 'BreakStatement' | 'ContinueStatement' | 'ThisExpression' | 'EventHook' | 'ImportStatement' | 'WaitStatement' | 'ClassStatement' | 'PromotedParameter' | 'NewExpression' | 'ParentMethodCallExpression';
interface BaseStmt {
type: NodeType;
position: TokenPosition;
}
interface BaseExpr {
type: NodeType;
position: TokenPosition;
}
interface Script extends BaseStmt {
type: 'Script';
body: Stmt[];
}
interface Block extends BaseStmt {
type: 'Block';
body: Stmt[];
}
interface EventHook extends BaseStmt {
type: 'EventHook';
name: Identifier;
params: Identifier[];
body: Block;
}
interface FunctionDeclaration extends BaseStmt {
type: 'FunctionDeclaration';
name: Identifier;
params: Identifier[];
body: Block;
isPublic: boolean;
}
interface MethodDefinition extends BaseStmt {
type: 'MethodDefinition';
objectName: Identifier;
methodName: string;
params: Identifier[];
body: Block;
}
interface ClassStatement extends BaseStmt {
type: 'ClassStatement';
name: Identifier;
params: (Identifier | PromotedParameter)[];
properties: {
key: Identifier;
value: Expr;
}[];
methods: FunctionDeclaration[];
isPublic?: boolean;
parent?: Identifier | MemberExpression;
parentArgs?: Expr[];
}
interface PromotedParameter extends BaseExpr {
type: 'PromotedParameter';
value: string;
}
interface NewExpression extends BaseExpr {
type: 'NewExpression';
className: Identifier | MemberExpression;
arguments: Expr[];
}
interface ParentMethodCallExpression extends BaseExpr {
type: 'ParentMethodCallExpression';
methodName: Identifier;
arguments: Expr[];
}
interface IfStatement extends BaseStmt {
type: 'IfStatement';
test: Expr;
consequent: Block;
alternate?: Block | IfStatement;
}
interface ImportStatement extends BaseStmt {
type: 'ImportStatement';
moduleName: string;
}
interface WaitStatement extends BaseStmt {
type: 'WaitStatement';
duration: Expr;
}
interface ReturnStatement extends BaseStmt {
type: 'ReturnStatement';
argument?: Expr;
}
interface ExpressionStatement extends BaseStmt {
type: 'ExpressionStatement';
expression: Expr;
}
interface BreakStatement extends BaseStmt {
type: 'BreakStatement';
}
interface ContinueStatement extends BaseStmt {
type: 'ContinueStatement';
}
interface AssignmentExpression extends BaseExpr {
type: 'AssignmentExpression';
left: Expr;
operator: string;
right: Expr;
isPublic: boolean;
isLocal: boolean;
}
interface BinaryExpression extends BaseExpr {
type: 'BinaryExpression';
left: Expr;
operator: string;
right: Expr;
}
interface LogicalExpression extends BaseExpr {
type: 'LogicalExpression';
left: Expr;
operator: 'and' | 'or';
right: Expr;
}
interface UnaryExpression extends BaseExpr {
type: 'UnaryExpression';
operator: string;
argument: Expr;
}
interface CallExpression extends BaseExpr {
type: 'CallExpression';
callee: Expr;
arguments: Expr[];
}
interface MemberExpression extends BaseExpr {
type: 'MemberExpression';
object: Expr;
property: Expr;
computed: boolean;
}
interface ArrayExpression extends BaseExpr {
type: 'ArrayExpression';
elements: Expr[];
}
interface ArrayComprehension extends BaseExpr {
type: 'ArrayComprehension';
expression: Expr;
iterator: Identifier;
collection: Expr;
}
interface ObjectExpression extends BaseExpr {
type: 'ObjectExpression';
properties: Property[];
}
interface ObjectComprehension extends BaseExpr {
type: 'ObjectComprehension';
key: Expr;
value: Expr;
iterator: Identifier;
collection: Expr;
}
interface Property extends BaseExpr {
type: 'Property';
key: Identifier;
value: Expr;
}
interface Identifier extends BaseExpr {
type: 'Identifier';
value: string;
}
interface ThisExpression extends BaseExpr {
type: 'ThisExpression';
}
interface Literal extends BaseExpr {
type: 'Literal';
value: any;
raw: string;
}
interface ForStatement extends BaseStmt {
type: 'ForStatement';
iterator: Identifier;
collection: Expr;
body: Block;
}
interface WhileStatement extends BaseStmt {
type: 'WhileStatement';
condition: Expr;
body: Block;
}
interface DoWhileStatement extends BaseStmt {
type: 'DoWhileStatement';
body: Block;
condition: Expr;
}
type Stmt = Script | Block | EventHook | FunctionDeclaration | MethodDefinition | IfStatement | ImportStatement | ReturnStatement | ExpressionStatement | ForStatement | WhileStatement | DoWhileStatement | BreakStatement | ContinueStatement | WaitStatement | ClassStatement;
type Expr = AssignmentExpression | BinaryExpression | LogicalExpression | UnaryExpression | CallExpression | MemberExpression | ArrayExpression | ArrayComprehension | ObjectExpression | ObjectComprehension | Identifier | Literal | ThisExpression | NewExpression | PromotedParameter | ParentMethodCallExpression;
declare class Parser {
private stream;
private moduleName?;
private lastToken?;
static parse(tokens: TokenStream, moduleName?: string | undefined): Script;
private constructor();
parse(): Script;
private parseStatement;
private parseEventHook;
private parseClassStatement;
private parseFunctionDeclaration;
private parseBlock;
private parseImportStatement;
private parseWaitStatement;
private parseReturnStatement;
private parseIfStatement;
private parseForStatement;
private parseWhileStatement;
private parseDoWhileStatement;
private parseBreakStatement;
private parseContinueStatement;
private parseExpressionStatement;
private parseExpression;
private parseLogicalOr;
private parseLogicalAnd;
private parseEquality;
private parseRelational;
private parseRange;
private parseAdditive;
private parseMultiplicative;
private parseUnary;
private parseExponentiation;
private parsePostfix;
private parsePrimary;
private skipFormatting;
private parseArrayExpression;
private parseObjectExpression;
private parseIdentifier;
private consume;
private match;
private check;
private currentPos;
}
interface ExecutionResult {
/**
* True if the script has completed execution, false otherwise.
*/
isCompleted: boolean;
/**
* True if the VM is currently sleeping, false otherwise.
*/
isSleeping: boolean;
/**
* Remaining execution budget after the run.
*/
remainingBudget: number;
/**
* Diagnostic information about the error if one occurred.
*
* @remarks {@link isCompleted} will be true if an error occurred to
* prevent the VM from continuing execution.
*/
error?: DiagnosticInfo;
}
type DiagnosticInfo = {
/**
* Error message if an error occurred, undefined otherwise.
*/
message: string;
/**
* A couple of lines of source code indicating where the error originated from, if available.
*/
source?: string;
/**
* Stack trace at the point of error, if available.
*/
trace?: StackTraceFrame[];
};
type StackTraceFrame = {
/**
* The type of the stack frame.
*/
type: 'module' | 'interrupt' | 'function';
/**
* The name of the module where the error occurred, if available.
*/
moduleName?: string;
/**
* The name of the function where the error occurred, if available.
*/
functionName?: string;
/**
* The line number in the source code where the error occurred.
*/
line: number;
/**
* The column number in the source code where the error occurred.
*/
column: number;
/**
* A few lines of source code around the error location, if available.
*/
source?: string;
};
type StackFrame = {
ip: number;
program: Program;
returnIp: number;
name: string;
isInterrupt: boolean;
isModule: boolean;
moduleName?: string;
locals: Record<string, any>;
localSlots: any[];
exports: Record<string, any>;
sleepTimer: number;
isFastCall?: boolean;
};
type VMEvent = {
name: string;
args: any[];
};
/**
* Represents the current state of the virtual machine.
*
* All data inside the State must be considered volatile and can change at any
* time.
*/
declare class State {
ip: number;
isHalted: boolean;
sleepTime: number;
deltaTime: number;
wallTime: number;
isAwaitingPromise: boolean;
private _program;
private _mainScope;
private _programs;
private _stack;
private _frames;
private _eventQueue;
private _scopes;
private _frameKinds;
private _fastReturnIps;
private _fastIps;
private _fastPrograms;
private _fastNames;
private _fastModuleNames;
private _fastSleepTimers;
private _fastLocalSlots;
private _fastLocals;
private _topSlowFrame;
private _currentProgram;
private _currentScope;
currentLocalSlots: any[];
constructor(program: Program, globals?: Record<string, any>);
get currentProgram(): Program;
import(data: {
stack?: any[];
programs?: Record<string, Program>;
frames?: StackFrame[];
scopes?: Record<string, any>;
events?: VMEvent[];
sleepTime?: number;
deltaTime?: number;
}): void;
get stack(): any[];
get frames(): StackFrame[];
get scopes(): Record<string, any>;
get eventQueue(): VMEvent[];
get programs(): Record<string, Program>;
push(val: any): void;
pop(): any;
peek(): any;
pushFrame(returnIp: number, options?: PushFrameOptions | string): StackFrame;
pushCallFrame(returnIp: number, name: string): void;
popFastCallFrame(): number | undefined;
popFrame(): StackFrame | undefined;
get topFrame(): StackFrame | null;
get topMutableFrame(): StackFrame | null;
get numFrames(): number;
get hasFrames(): boolean;
getVar(name: string): any;
setVar(name: string, value: any, local?: boolean): void;
get isInsideInterrupt(): boolean;
tickSleepTimers(deltaTime: number): void;
setTopSleepTimer(duration: number): void;
get isSleeping(): boolean;
findProgramByHash(hash: string): Program | null;
private get topModuleName();
private refreshExecutionContext;
isTruthy(value: any): boolean;
}
type PushFrameOptions = {
program?: Program;
isInterrupt?: boolean;
isModule?: boolean;
name?: string;
moduleName?: string;
};
interface VirtualMachineOptions {
/**
* Enables opcode-level profiling.
*
* When enabled, the VM records timing and count metrics for each executed
* opcode. This adds runtime overhead and is disabled by default.
*/
profile?: boolean;
/**
* The maximum number of operations (instructions) the VM is allowed to
* execute in a single run.
*
* Defaults to {@link Infinity} if not specified.
*
* You can tweak this value during runtime via {@link VirtualMachine.budget}
* property on the VM instance. A typical use-case is to set a budget for
* AI agents that are far away from the player, and increase it when they
* come closer (AI LOD).
*/
budget?: number;
/**
* Custom functions that can be invoked by scripts running inside the
* virtual machine.
*/
functions?: Record<string, (...args: any[]) => any>;
/**
* Custom classes that can be instantiated or extended by scripts running
* inside the virtual machine.
*/
classes?: Record<string, HostClassContract>;
/**
* Initial global variables to set in the VM's state.
*
* Variables set here are mutable by scripts running in the VM. Once a
* script modifies a variable, it can be fetched again via the VM's
* `globals` property.
*/
variables?: Record<string, any>;
/**
* Whether the VM should throw an {@link Error} when it encounters a
* runtime error, or simply write the error message to the console and
* halt execution.
*/
throwOnError?: boolean;
/**
* A function that resolves and returns a module by its name.
*
* The function should return a {@link Program} instance if the module
* exists, or `undefined` if it cannot be found. Scripts can import modules
* using the "import" statement.
*
* @param moduleName
*/
resolveModule?: (moduleName: string) => Program | undefined;
/**
* A cache of previously loaded and evaluated modules to avoid redundant
* execution of shared code between scripts. This object should be shared
* among multiple VM instances to maximize cache hits.
*
* The value of each entry can either be a {@link Program} instance or
* a plain object containing exported functions and variables.
*
* @remarks Functions and variables can be shared by using the "public"
* modifier. It is important to remember that each script can
* modify the values of exported variables, so care must be taken
* when sharing state between multiple VM instances.
*/
moduleCache?: Record<string, any>;
/**
* A custom function that returns the current time in milliseconds.
*
* This is used to manage time-based operations inside the VM, such as
* delays and timeouts. If not provided, the VM will use the built-in
* {@link performance.now()} function or {@link Date.now()} as a fallback.
*
* @returns The current time in milliseconds.
*/
now?: () => number;
/**
* Whether the VM should write ANSI escape codes to error messages.
*
* Defaults to {@link process.stdout.isTTY} and the ENV variable
* "TERM" is not set to "dumb" or ENV variable "FORCE_COLOR" is set.
*
* @remarks Defaults to `false` in browser environments.
*/
colors?: boolean;
}
type HostClassContract = {
/**
* A reference to the class declaration.
*
* You MUST provide a list of allowed properties and methods via
* {@link HostClassContract.properties} and {@link HostClassContract.methods}
* to allow scripts to access them. Omitting these lists will result in scripts
* being unable to interact with instances of this class, except for the
* constructor.
*/
constructor: new (...args: any[]) => any;
/**
* A list of names of properties that the script is allowed to access on
* instances of this class.
*/
properties?: string[];
/**
* A list of methods that the script is allowed to invoke on instances of
* this class.
*/
methods?: string[];
};
/**
* Handles instruction execution for the VM.
*
* This class is auto-generated. Do not edit directly.
*/
declare abstract class InstructionSet {
protected abstract state: State;
protected abstract program: Program;
protected abstract hostFunctions: Map<string, Function>;
protected abstract hostClasses: Map<string, HostClassContract>;
protected abstract moduleCache: Record<string, any>;
protected abstract resolveModule: (moduleName: string) => Program | undefined;
protected abstract profilingEnabled: boolean;
protected abstract profileNow: () => number;
protected abstract recordOpcodeProfile: (opcode: Opcode, duration: number) => void;
/**
* Executes instructions until the budget is exhausted or the VM halts.
*
* @param {number} budget The maximum number of instructions to execute.
* @param {number} deltaTime The time elapsed since the last execution (in milliseconds).
* @returns {boolean} True if the VM has halted, false otherwise.
*/
protected execute(budget: number, deltaTime?: number): [number, boolean];
protected __op_add(arg: any): void;
protected __op_arrayPush(arg: any): void;
protected __op_call(arg: any): void;
protected __op_callMethod(arg: any): void;
protected __op_callParent(arg: any): void;
protected __op__super(arg: any): void;
protected __op_constant(arg: any): void;
protected __op_div(arg: any): void;
protected __op_dup(arg: any): void;
protected __op_eq(arg: any): void;
protected __op_exp(arg: any): void;
protected __op__export(arg: any): void;
protected __op_getProp(arg: any): void;
protected __op_gt(arg: any): void;
protected __op_gte(arg: any): void;
protected __op_halt(arg: any): void;
protected __op__import(arg: any): void;
protected __op__in(arg: any): void;
protected __op_is(arg: any): void;
protected __op_iterInit(arg: any): void;
protected __op_iterNext(arg: any): void;
protected __op_jmp(arg: any): void;
protected __op_jmpIfFalse(arg: any): void;
protected __op_jmpIfTrue(arg: any): void;
protected __op_load(arg: any): void;
protected __op_loadLocal(arg: any): void;
protected __op_lt(arg: any): void;
protected __op_lte(arg: any): void;
protected __op_makeArray(arg: any): void;
protected __op_makeClass(arg: any): void;
protected __op_makeFunction(arg: any): void;
protected __op_makeMethod(arg: any): void;
protected __op_makeObject(arg: any): void;
protected __op_makeRange(arg: any): void;
protected __op_mod(arg: any): void;
protected __op_mul(arg: any): void;
protected __op_neg(arg: any): void;
protected __op_neq(arg: any): void;
protected __op__new(arg: any): void;
protected __op_not(arg: any): void;
protected __op_pop(arg: any): void;
protected __op_ret(arg: any): void;
protected __op_setProp(arg: any): void;
protected __op_store(arg: any): void;
protected __op_storeLocal(arg: any): void;
protected __op_sub(arg: any): void;
protected __op_swap(arg: any): void;
protected __op_wait(arg: any): void;
}
type OpcodeProfileEntry = {
count: number;
totalTime: number;
minTime: number;
maxTime: number;
};
type OpcodeProfileStats = {
opcode: string;
count: number;
totalTime: number;
averageTime: number;
minTime: number;
maxTime: number;
percentage: number;
};
type VirtualMachineProfile = {
enabled: boolean;
totalInstructions: number;
totalTime: number;
byOpcode: OpcodeProfileStats[];
};
declare class VirtualMachine extends InstructionSet {
readonly state: State;
budget: number;
throwOnError: boolean;
protected readonly program: Program;
protected readonly hostFunctions: Map<string, Function>;
protected readonly hostClasses: Map<string, HostClassContract>;
protected readonly resolveModule: (moduleName: string) => Program | undefined;
protected readonly moduleCache: Record<string, any>;
protected readonly profilingEnabled: boolean;
protected readonly profileNow: () => number;
protected readonly recordOpcodeProfile: (opcode: Opcode, duration: number) => void;
private readonly serializer;
private readonly deserializer;
private readonly result;
private readonly opcodeProfile;
private totalProfiledInstructions;
private totalProfiledTime;
constructor(program: Program, options?: VirtualMachineOptions);
/**
* Register a native function that can be called from the VM.
*
* @param {string} name
* @param {Function} fn
*/
registerFunction(name: string, fn: Function): this;
/**
* Register a native class that can be instantiated or extended from the VM.
*
* @param {string} name
* @param {HostClassContract} contract
*/
registerClass(name: string, contract: HostClassContract): this;
/**
* Returns opcode profiling metrics ordered by total execution time.
*/
getProfile(): Readonly<VirtualMachineProfile>;
/**
* Clears all collected profiling samples.
*/
resetProfile(): void;
/**
* Run the VM for a specific number of "ops".
*
* @returns TRUE if the script finished, FALSE if it paused (ran out of budget or crashed).
*/
run(deltaTime?: number): Readonly<ExecutionResult>;
/**
* Returns a list of event names that can be dispatched to the VM.
*
* @returns {string[]}
*/
get eventNames(): string[];
/**
* Dispatch an event to the VM.
*
* Returns true if a hook for the given event name exists and that the
* event was successfully queued, false otherwise.
*
* @param {string} name - The name of the event.
* @param {any[]} args - Arguments to pass to the event handler.
* @returns {boolean}
*/
dispatch(name: string, args?: any[]): boolean;
/**
* Saves the current state of the VM to a string.
*
* @returns {string}
*/
save(): string;
/**
* Restores the VM state from a string.
*
* @param {string} state
*/
load(state: string): void;
/**
* Returns a ROM hash based on the loaded instructions.
*
* @returns {string}
*/
get romHash(): string;
private executeNextEvent;
private createErrorDiagnosticInfo;
private createStackTrace;
private createErrorSourceLines;
/**
* Create a human-readable error message from a DiagnosticInfo object.
*
* @param {DiagnosticInfo} diag - The diagnostic information.
* @returns {string} - The formatted error message.
*/
createErrorMessageFromDiagnostic(diag: DiagnosticInfo): string;
}
declare class LumaError extends Error {
readonly moduleName?: string;
readonly position?: TokenPosition;
constructor(options: LumaErrorOptions);
}
type LumaErrorOptions = {
message: string;
moduleName?: string;
position?: TokenPosition;
cause?: Error;
};
declare class LumaRuntimeError extends LumaError {
readonly address: number;
readonly program: Program;
constructor(options: LumaRuntimeErrorOptions);
}
type LumaRuntimeErrorOptions = LumaErrorOptions & {
address: number;
program: Program;
};
export { type ArrayComprehension, type ArrayExpression, type AssignmentExpression, type BaseExpr, type BaseStmt, type BinaryExpression, type Block, type BreakStatement, type CallExpression, type CallableAddress, type ClassStatement, Compiler, type ContinueStatement, type DiagnosticInfo, type DoWhileStatement, type EventHook, type ExecutionResult, type Expr, type ExpressionStatement, type ForStatement, type FunctionDeclaration, type HostClassContract, type Identifier, type IfStatement, type ImportStatement, type Instruction, Keywords, type Literal, type LogicalExpression, LumaError, type LumaErrorOptions, LumaRuntimeError, type LumaRuntimeErrorOptions, type MemberExpression, type MethodDefinition, type NewExpression, type NodeType, type ObjectComprehension, type ObjectExpression, Opcode, OpcodeBytes, type OpcodeProfileEntry, type OpcodeProfileStats, Operators, type ParentMethodCallExpression, Parser, type Program, type PromotedParameter, type Property, Punctuation, Reader, type ReturnStatement, type Script, type StackTraceFrame, type Stmt, type ThisExpression, type Token, type TokenPosition, TokenStream, TokenType, Tokenizer, type UnaryExpression, VirtualMachine, type VirtualMachineOptions, type VirtualMachineProfile, type WaitStatement, type WhileStatement, Writer };