about summary refs log tree commit diff stats
path: root/js/baba-yaga/src/legacy/engine-optimized.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/baba-yaga/src/legacy/engine-optimized.js')
-rw-r--r--js/baba-yaga/src/legacy/engine-optimized.js526
1 files changed, 526 insertions, 0 deletions
diff --git a/js/baba-yaga/src/legacy/engine-optimized.js b/js/baba-yaga/src/legacy/engine-optimized.js
new file mode 100644
index 0000000..5f78da7
--- /dev/null
+++ b/js/baba-yaga/src/legacy/engine-optimized.js
@@ -0,0 +1,526 @@
+// engine-optimized.js - High-performance Baba Yaga engine with all optimizations
+
+import { createOptimizedLexer, createLexerWithFallback } from './lexer-optimized.js';
+import { createParser } from './parser.js';
+import { createInterpreter } from './interpreter.js';
+import { BabaYagaConfig } from './config.js';
+import { InputValidator, SecurityValidator } from './validation.js';
+import { BabaError } from './error.js';
+import { ScopeStack, CompatibleScopeStack } from './scope-stack.js';
+import { OptimizedBuiltins } from './builtins-optimized.js';
+import { globalASTPool } from './ast-pool.js';
+
+/**
+ * High-performance Baba Yaga engine with all optimizations enabled
+ */
+export class OptimizedBabaYagaEngine {
+  constructor(config = new BabaYagaConfig()) {
+    this.config = config;
+    this.validator = config.sandboxMode 
+      ? new SecurityValidator(config) 
+      : new InputValidator(config);
+    
+    // Initialize optimization components
+    this.optimizedBuiltins = new OptimizedBuiltins();
+    this.astPool = globalASTPool;
+    
+    // Performance tracking with more detail
+    this.stats = {
+      totalExecutions: 0,
+      totalTime: 0,
+      averageTime: 0,
+      errors: 0,
+      lexingTime: 0,
+      parsingTime: 0,
+      interpretingTime: 0,
+      optimizationStats: {
+        lexerOptimizations: 0,
+        scopeOptimizations: 0,
+        builtinOptimizations: 0,
+        astPoolHits: 0
+      }
+    };
+
+    // Warm up optimization components
+    if (config.enableOptimizations) {
+      this.warmUp();
+    }
+  }
+
+  /**
+   * Warm up optimization components for better initial performance
+   */
+  warmUp() {
+    // Warm up AST pools
+    this.astPool.warmUp('BinaryExpression', 50);
+    this.astPool.warmUp('FunctionCall', 30);
+    this.astPool.warmUp('Identifier', 100);
+    this.astPool.warmUp('NumberLiteral', 50);
+    
+    // Warm up with a simple program
+    const warmupCode = 'x : 1 + 2; y : x * 3;';
+    try {
+      this.executeSync(warmupCode, { silent: true });
+    } catch (error) {
+      // Ignore warmup errors
+    }
+  }
+
+  /**
+   * Execute Baba Yaga source code with all optimizations
+   */
+  async execute(source, options = {}) {
+    const startTime = performance.now();
+    
+    try {
+      // Validate input
+      this.validator.validateSourceCode(source, options.filename || '<input>');
+      
+      // Optimized lexical analysis
+      const lexStart = performance.now();
+      const lexer = this.config.enableOptimizations 
+        ? createOptimizedLexer(source)
+        : await createLexerWithFallback(source, false);
+      const tokens = lexer.allTokens();
+      const lexTime = performance.now() - lexStart;
+      
+      if (this.config.enableDebugMode) {
+        console.log(`[DEBUG] Lexing: ${lexTime.toFixed(2)}ms, Tokens: ${tokens.length}`);
+      }
+      
+      // Parsing with AST pooling
+      const parseStart = performance.now();
+      const parser = this.createOptimizedParser(tokens, source);
+      const ast = parser.parse();
+      const parseTime = performance.now() - parseStart;
+      
+      // Validate AST
+      this.validator.validateAST(ast, source);
+      
+      if (this.config.enableDebugMode) {
+        console.log(`[DEBUG] Parsing: ${parseTime.toFixed(2)}ms, AST depth: ${this.getASTDepth(ast)}`);
+      }
+      
+      // Optimized interpretation
+      const interpretStart = performance.now();
+      const host = this.createOptimizedHostInterface(source, options);
+      const interpreter = this.createOptimizedInterpreter(ast, host);
+      
+      // Set up execution timeout
+      const result = await this.executeWithTimeout(interpreter, host);
+      const interpretTime = performance.now() - interpretStart;
+      
+      // Update statistics
+      const executionTime = performance.now() - startTime;
+      this.updateStats(executionTime, false, lexTime, parseTime, interpretTime);
+      
+      if (this.config.showTimings) {
+        console.log(`[TIMING] Total: ${executionTime.toFixed(2)}ms (Lex: ${lexTime.toFixed(2)}ms, Parse: ${parseTime.toFixed(2)}ms, Interpret: ${interpretTime.toFixed(2)}ms)`);
+      }
+      
+      // Clean up AST if pooling is enabled
+      if (this.config.enableOptimizations) {
+        this.astPool.releaseTree(ast);
+      }
+      
+      return {
+        result,
+        executionTime,
+        success: true,
+        breakdown: {
+          lexingTime: lexTime,
+          parsingTime: parseTime,
+          interpretingTime: interpretTime
+        }
+      };
+      
+    } catch (error) {
+      const executionTime = performance.now() - startTime;
+      this.updateStats(executionTime, true);
+      
+      // Format error for display
+      if (error instanceof BabaError) {
+        const formattedError = this.config.verboseErrors ? error.formatError() : error.message;
+        
+        return {
+          error: formattedError,
+          errorType: error.name,
+          executionTime,
+          success: false,
+          suggestions: error.suggestions
+        };
+      } else {
+        // Unexpected error
+        if (this.config.enableDebugMode) {
+          console.error('[INTERNAL ERROR]', error);
+        }
+        return {
+          error: 'Internal error occurred',
+          errorType: 'InternalError',
+          executionTime,
+          success: false,
+          suggestions: ['Report this as a bug', 'Check for malformed input']
+        };
+      }
+    }
+  }
+
+  /**
+   * Synchronous execution for simple cases
+   */
+  executeSync(source, options = {}) {
+    // Use Promise.resolve to handle async execute in sync context
+    let result;
+    let error;
+    
+    this.execute(source, options).then(
+      res => { result = res; },
+      err => { error = err; }
+    );
+    
+    // Simple busy wait for sync execution (not recommended for production)
+    const start = Date.now();
+    while (result === undefined && error === undefined && Date.now() - start < 1000) {
+      // Wait
+    }
+    
+    if (error) throw error;
+    return result;
+  }
+
+  /**
+   * Create optimized parser with AST pooling
+   */
+  createOptimizedParser(tokens, source) {
+    const parser = createParser(tokens, this.config.enableDebugMode, source);
+    
+    // If optimizations are enabled, wrap parser methods to use pooling
+    if (this.config.enableOptimizations) {
+      const originalParse = parser.parse.bind(parser);
+      parser.parse = () => {
+        const ast = originalParse();
+        this.stats.optimizationStats.astPoolHits += this.astPool.getStats().poolHits;
+        return ast;
+      };
+    }
+    
+    return parser;
+  }
+
+  /**
+   * Create optimized interpreter with scope stack and built-in optimizations
+   */
+  createOptimizedInterpreter(ast, host) {
+    const interpreter = createInterpreter(ast, host);
+    
+    if (this.config.enableOptimizations) {
+      // Replace scope with optimized scope stack
+      const originalScope = interpreter.scope;
+      const optimizedScope = new CompatibleScopeStack();
+      
+      // Copy existing scope data
+      for (const [key, value] of originalScope.entries()) {
+        optimizedScope.set(key, value);
+      }
+      
+      interpreter.scope = optimizedScope;
+      
+      // Inject optimized built-ins
+      this.injectOptimizedBuiltins(interpreter);
+    }
+    
+    return interpreter;
+  }
+
+  /**
+   * Inject optimized built-in functions into interpreter
+   */
+  injectOptimizedBuiltins(interpreter) {
+    const originalVisitFunctionCall = interpreter.visitFunctionCall;
+    
+    interpreter.visitFunctionCall = (node) => {
+      // Try optimized path first
+      if (node.callee && node.callee.type === 'Identifier') {
+        const functionName = node.callee.name;
+        const args = node.arguments.map(arg => interpreter.visit(arg));
+        
+        if (this.optimizedBuiltins.canOptimize(functionName, args)) {
+          const result = this.optimizedBuiltins.execute(functionName, args, interpreter);
+          if (result !== null) {
+            this.stats.optimizationStats.builtinOptimizations++;
+            return result;
+          }
+        }
+      }
+      
+      // Fall back to standard implementation
+      return originalVisitFunctionCall.call(interpreter, node);
+    };
+  }
+
+  /**
+   * Create optimized host interface
+   */
+  createOptimizedHostInterface(source, options) {
+    const host = {
+      source,
+      scope: options.scope || new Map(),
+      io: {
+        out: (...args) => {
+          if (options.silent) return; // Skip output in silent mode
+          
+          if (options.onOutput) {
+            options.onOutput(...args);
+          } else {
+            console.log(...args);
+          }
+        },
+        in: () => {
+          if (options.onInput) {
+            return options.onInput();
+          } else {
+            throw new BabaError('Input not available in this context');
+          }
+        },
+        emit: (event) => {
+          if (options.onEvent) {
+            options.onEvent(event);
+          }
+        },
+        addListener: (topic, handler) => {
+          if (options.onAddListener) {
+            return options.onAddListener(topic, handler);
+          }
+          return () => {}; // No-op unsubscribe
+        },
+        debug: this.config.enableDebugMode ? console.log : () => {},
+        ...this.config.ioHandlers
+      }
+    };
+
+    // Add optimization-specific extensions
+    if (this.config.enableOptimizations) {
+      host.optimizations = {
+        builtins: this.optimizedBuiltins,
+        astPool: this.astPool
+      };
+    }
+
+    return host;
+  }
+
+  /**
+   * Execute interpreter with timeout protection
+   */
+  async executeWithTimeout(interpreter, host) {
+    let timeoutId;
+    
+    const executionPromise = new Promise((resolve, reject) => {
+      try {
+        const result = interpreter.interpret();
+        resolve(result);
+      } catch (error) {
+        reject(error);
+      }
+    });
+    
+    const timeoutPromise = new Promise((_, reject) => {
+      timeoutId = setTimeout(() => {
+        reject(new BabaError(
+          `Execution timeout after ${this.config.maxExecutionTime}ms`,
+          null,
+          host.source,
+          ['Reduce recursion depth', 'Optimize algorithm complexity', 'Increase maxExecutionTime']
+        ));
+      }, this.config.maxExecutionTime);
+    });
+    
+    try {
+      const result = await Promise.race([executionPromise, timeoutPromise]);
+      clearTimeout(timeoutId);
+      return result;
+    } catch (error) {
+      clearTimeout(timeoutId);
+      throw error;
+    }
+  }
+
+  /**
+   * Get AST depth for validation and debugging
+   */
+  getASTDepth(node, depth = 0) {
+    if (!node || typeof node !== 'object') {
+      return depth;
+    }
+
+    let maxDepth = depth;
+    
+    // Check common AST node children
+    const childFields = ['body', 'left', 'right', 'operand', 'callee', 'arguments', 'elements', 'discriminants', 'cases'];
+    
+    for (const field of childFields) {
+      const child = node[field];
+      if (child) {
+        if (Array.isArray(child)) {
+          for (const item of child) {
+            maxDepth = Math.max(maxDepth, this.getASTDepth(item, depth + 1));
+          }
+        } else {
+          maxDepth = Math.max(maxDepth, this.getASTDepth(child, depth + 1));
+        }
+      }
+    }
+
+    return maxDepth;
+  }
+
+  /**
+   * Update execution statistics with detailed breakdown
+   */
+  updateStats(executionTime, isError, lexTime = 0, parseTime = 0, interpretTime = 0) {
+    this.stats.totalExecutions++;
+    this.stats.totalTime += executionTime;
+    this.stats.averageTime = this.stats.totalTime / this.stats.totalExecutions;
+    this.stats.lexingTime += lexTime;
+    this.stats.parsingTime += parseTime;
+    this.stats.interpretingTime += interpretTime;
+    
+    if (isError) {
+      this.stats.errors++;
+    }
+  }
+
+  /**
+   * Get comprehensive engine statistics
+   */
+  getStats() {
+    const builtinStats = this.optimizedBuiltins.getStats();
+    const astPoolStats = this.astPool.getStats();
+    
+    return {
+      ...this.stats,
+      errorRate: this.stats.totalExecutions > 0 ? this.stats.errors / this.stats.totalExecutions : 0,
+      averageLexTime: this.stats.totalExecutions > 0 ? this.stats.lexingTime / this.stats.totalExecutions : 0,
+      averageParseTime: this.stats.totalExecutions > 0 ? this.stats.parsingTime / this.stats.totalExecutions : 0,
+      averageInterpretTime: this.stats.totalExecutions > 0 ? this.stats.interpretingTime / this.stats.totalExecutions : 0,
+      optimizations: {
+        builtinOptimizationRate: builtinStats.optimizationRate,
+        astPoolHitRate: astPoolStats.hitRate,
+        astPoolReuseRate: astPoolStats.reuseRate,
+        totalOptimizations: this.stats.optimizationStats.builtinOptimizations + this.stats.optimizationStats.astPoolHits
+      }
+    };
+  }
+
+  /**
+   * Reset all statistics
+   */
+  resetStats() {
+    this.stats = {
+      totalExecutions: 0,
+      totalTime: 0,
+      averageTime: 0,
+      errors: 0,
+      lexingTime: 0,
+      parsingTime: 0,
+      interpretingTime: 0,
+      optimizationStats: {
+        lexerOptimizations: 0,
+        scopeOptimizations: 0,
+        builtinOptimizations: 0,
+        astPoolHits: 0
+      }
+    };
+    
+    this.optimizedBuiltins.resetStats();
+    this.astPool.resetStats();
+  }
+
+  /**
+   * Get optimization recommendations
+   */
+  getOptimizationRecommendations() {
+    const stats = this.getStats();
+    const recommendations = [];
+    
+    if (stats.optimizations.builtinOptimizationRate < 0.7) {
+      recommendations.push('Consider using more built-in functions (map, filter, reduce) for better performance');
+    }
+    
+    if (stats.optimizations.astPoolHitRate < 0.5) {
+      recommendations.push('Enable AST pooling for better memory efficiency');
+    }
+    
+    if (stats.averageLexTime > stats.averageParseTime) {
+      recommendations.push('Lexing is taking longer than parsing - consider optimizing token patterns');
+    }
+    
+    if (stats.errorRate > 0.1) {
+      recommendations.push('High error rate detected - consider input validation improvements');
+    }
+    
+    return recommendations;
+  }
+
+  /**
+   * Create a performance profile for the current workload
+   */
+  createPerformanceProfile() {
+    const stats = this.getStats();
+    
+    return {
+      timestamp: new Date().toISOString(),
+      config: this.config.summary(),
+      performance: {
+        totalExecutions: stats.totalExecutions,
+        averageExecutionTime: stats.averageTime,
+        breakdown: {
+          lexing: stats.averageLexTime,
+          parsing: stats.averageParseTime,
+          interpreting: stats.averageInterpretTime
+        },
+        optimizations: stats.optimizations
+      },
+      recommendations: this.getOptimizationRecommendations()
+    };
+  }
+}
+
+/**
+ * Convenience function for optimized execution
+ */
+export async function executeOptimized(source, config = new BabaYagaConfig({ enableOptimizations: true })) {
+  const engine = new OptimizedBabaYagaEngine(config);
+  return engine.execute(source);
+}
+
+/**
+ * Create optimized engine with preset configurations
+ */
+export function createOptimizedEngine(preset = 'performance') {
+  let config;
+  
+  switch (preset) {
+    case 'performance':
+      config = new BabaYagaConfig({
+        enableOptimizations: true,
+        enableDebugMode: false,
+        strictMode: false,
+        maxRecursionDepth: 2000,
+        maxExecutionTime: 10000
+      });
+      break;
+    case 'development':
+      config = BabaYagaConfig.development();
+      config.enableOptimizations = true;
+      break;
+    case 'production':
+      config = BabaYagaConfig.production();
+      config.enableOptimizations = true;
+      break;
+    default:
+      config = new BabaYagaConfig({ enableOptimizations: true });
+  }
+  
+  return new OptimizedBabaYagaEngine(config);
+}