@five-vm/cli
Version:
High-performance CLI for Five VM development with WebAssembly integration
225 lines • 8.23 kB
JavaScript
/**
* Five Bytecode Compiler
*
* Handles compilation of Five script source (.v files) to bytecode (.bin files)
* using the existing WASM compilation infrastructure.
*
* This maintains the real compilation capabilities while providing a clean SDK interface.
*/
import { readFile } from 'fs/promises';
import { CompilationSDKError } from '../types.js';
/**
* Bytecode compiler for Five scripts
*/
export class BytecodeCompiler {
debug;
wasmCompiler;
constructor(config = {}) {
this.debug = config.debug || false;
if (this.debug) {
console.log('[BytecodeCompiler] Initialized');
}
}
/**
* Compile Five script source to bytecode
*/
async compile(source, options = {}) {
const startTime = Date.now();
// Compile source (debug info available in this.debug mode)
try {
// Lazy load WASM compiler
if (!this.wasmCompiler) {
await this.loadWasmCompiler();
}
// Prepare compilation options
const compilerOptions = {
optimize: options.optimize || false,
target: options.target || 'vm',
debug: options.debug || false,
maxSize: options.maxSize || 1048576, // 1MB default
optimizationLevel: options.optimizationLevel || 'v2' // Default to V2
};
// Perform compilation
const result = await this.wasmCompiler.compile(source, compilerOptions);
const compilationTime = Date.now() - startTime;
if (result.success && result.bytecode) {
if (this.debug) {
console.log(`[BytecodeCompiler] Compilation successful in ${compilationTime}ms`);
console.log(`[BytecodeCompiler] Bytecode size: ${result.bytecode.length} bytes`);
}
return {
success: true,
bytecode: result.bytecode,
abi: result.abi,
disassembly: result.disassembly || [],
metadata: {
sourceSize: source.length,
bytecodeSize: result.bytecode.length,
functions: this.extractFunctions(result.abi),
compilationTime
}
};
}
else {
const errors = this.transformErrors(result.errors || []);
if (this.debug) {
console.log(`[BytecodeCompiler] Compilation failed with ${errors.length} errors`);
errors.forEach(error => {
console.log(` - ${error.severity}: ${error.message} (${error.line}:${error.column})`);
});
}
return {
success: false,
errors
};
}
}
catch (error) {
throw new CompilationSDKError(`Compilation error: ${error instanceof Error ? error.message : 'Unknown error'}`, { source: source.substring(0, 200), options });
}
}
/**
* Compile script from file path
*/
async compileFile(filePath, options = {}) {
if (this.debug) {
console.log(`[BytecodeCompiler] Reading file: ${filePath}`);
}
try {
const source = await readFile(filePath, 'utf-8');
return this.compile(source, options);
}
catch (error) {
throw new CompilationSDKError(`Failed to read file ${filePath}: ${error instanceof Error ? error.message : 'Unknown error'}`, { filePath, options });
}
}
/**
* Validate Five script source without compiling
*/
async validateSource(source) {
if (this.debug) {
console.log(`[BytecodeCompiler] Validating source (${source.length} chars)...`);
}
try {
if (!this.wasmCompiler) {
await this.loadWasmCompiler();
}
const result = await this.wasmCompiler.validateSource(source);
return {
valid: result.valid,
errors: result.errors ? this.transformErrors(result.errors) : undefined
};
}
catch (error) {
if (this.debug) {
console.log(`[BytecodeCompiler] Validation error: ${error}`);
}
return {
valid: false,
errors: [{
message: error instanceof Error ? error.message : 'Unknown validation error',
severity: 'error'
}]
};
}
}
/**
* Get compiler version and information
*/
async getCompilerInfo() {
try {
if (!this.wasmCompiler) {
await this.loadWasmCompiler();
}
return {
version: '1.0.0', // TODO: Get from WASM module
wasmLoaded: !!this.wasmCompiler,
debug: this.debug
};
}
catch (error) {
return {
version: 'unknown',
wasmLoaded: false,
debug: this.debug,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
// ==================== Private Methods ====================
/**
* Load WASM compiler (reuse existing infrastructure)
*/
async loadWasmCompiler() {
try {
// Load WASM compiler silently unless debug
// Import existing WASM compiler from the CLI
// This path points to the existing working compiler
const { FiveCompilerWasm } = await import('../../wasm/compiler.js');
const wasmInstance = new FiveCompilerWasm(console); // Use console as logger
// CRITICAL: Initialize the compiler - this step was missing!
await wasmInstance.initialize();
this.wasmCompiler = wasmInstance;
if (this.debug) {
console.log('[BytecodeCompiler] WASM compiler loaded and initialized successfully');
}
}
catch (error) {
throw new CompilationSDKError(`Failed to load WASM compiler: ${error instanceof Error ? error.message : 'Unknown error'}`, { debug: this.debug });
}
}
/**
* Transform compiler errors to SDK format
*/
transformErrors(errors) {
return errors.map(error => ({
message: error.message || error.toString(),
line: error.line,
column: error.column,
severity: error.severity || 'error'
}));
}
/**
* Extract function definitions from ABI
*/
extractFunctions(abi) {
if (!abi || !abi.functions) {
return [];
}
return abi.functions.map((func, index) => ({
name: func.name,
index,
parameters: func.parameters?.map((param) => ({
name: param.name,
type: param.type,
optional: param.optional || false
})) || [],
returnType: func.returnType
}));
}
/**
* Generate ABI from Five script source code
*/
async generateABI(source) {
if (this.debug) {
console.log(`[BytecodeCompiler] Generating ABI for source (${source.length} chars)...`);
}
try {
if (!this.wasmCompiler) {
await this.loadWasmCompiler();
}
const abi = await this.wasmCompiler.generateABI(source);
if (this.debug) {
console.log(`[BytecodeCompiler] ABI generated:`, JSON.stringify(abi, null, 2));
}
return abi;
}
catch (error) {
if (this.debug) {
console.log(`[BytecodeCompiler] ABI generation error: ${error}`);
}
throw new CompilationSDKError(`ABI generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, { source });
}
}
}
//# sourceMappingURL=BytecodeCompiler.js.map