CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rapydscript-ng

Pythonic JavaScript that doesn't suck - a Python-to-JavaScript transpiler with clean syntax and performance

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

embedded.mddocs/

Embedded Compiler

Streaming compilation interface optimized for web browsers and embedded environments. Provides incremental compilation with state preservation, making it ideal for REPL-style applications and dynamic code execution.

Capabilities

Embedded Compiler Factory

Creates an embedded compiler instance that maintains compilation state across multiple operations.

/**
 * Create an embedded compiler instance
 * @param compiler - Main compiler instance from create_compiler()
 * @param baselib - Base library code as string
 * @param runjs - JavaScript execution function (default: eval)
 * @param name - Module name for compiled code (default: '__embedded__')
 * @returns Embedded compiler interface
 */
function create_embedded_compiler(
  compiler: CompilerInstance,
  baselib: string,
  runjs?: Function,
  name?: string
): EmbeddedCompiler;

interface EmbeddedCompiler {
  /** Compile RapydScript code to JavaScript with state preservation */
  compile(code: string, options?: EmbeddedCompileOptions): string;
  /** Current top-level AST node maintaining compilation state */
  toplevel: AST_Toplevel | null;
}

Usage Example:

const { create_compiler } = require("rapydscript-ng");
const embedded_compiler = require("rapydscript-ng/tools/embedded_compiler");
const fs = require("fs");

// Create main compiler and load base library
const RapydScript = create_compiler();
const baselib = fs.readFileSync("path/to/baselib.js", "utf-8");

// Create embedded compiler
const embeddedCompiler = embedded_compiler(
  RapydScript, 
  baselib, 
  eval, 
  "my_module"
);

// Compile code incrementally
const js1 = embeddedCompiler.compile(`
def greet(name):
    return "Hello, " + name
`);

const js2 = embeddedCompiler.compile(`
print(greet("World"))
`);

Streaming Compilation

Compile RapydScript source code with incremental state management and flexible output options.

/**
 * Compile RapydScript code to JavaScript
 * @param code - RapydScript source code
 * @param options - Compilation options
 * @returns Generated JavaScript code
 */
compile(code: string, options?: EmbeddedCompileOptions): string;

interface EmbeddedCompileOptions {
  /** Source filename for error reporting */
  filename?: string;
  /** Include base library in output */
  keep_baselib?: boolean;
  /** Preserve docstrings as __doc__ attributes */
  keep_docstrings?: boolean;
  /** Target JavaScript version (5 or 6) */
  js_version?: number;
  /** Wrap output in private scope */
  private_scope?: boolean;
  /** Include __name__ assignment */
  write_name?: boolean;
  /** Remove assert statements */
  discard_asserts?: boolean;
}

Advanced Usage:

// Configure compilation options
const options = {
  filename: "repl_input.pyj",
  keep_baselib: false,        // Don't repeat baselib
  keep_docstrings: true,      // Preserve documentation
  js_version: 6,              // Use ES6 features
  private_scope: true,        // Wrap in function scope
  write_name: false,          // Skip __name__ assignment
  discard_asserts: false      // Keep assert statements
};

const javascript = embeddedCompiler.compile(`
class Calculator:
    """A simple calculator class."""
    
    def add(self, a, b):
        """Add two numbers."""
        assert isinstance(a, (int, float))
        assert isinstance(b, (int, float))
        return a + b
        
    def multiply(self, a, b):
        """Multiply two numbers."""
        return a * b

calc = Calculator()
result = calc.add(5, 3)
print("Result:", result)
`, options);

State Management

The embedded compiler maintains compilation state across multiple compile calls, enabling:

  • Class persistence: Classes defined in earlier compilations remain available
  • Scope preservation: Variable scopes and flags are maintained
  • Export tracking: Module exports accumulate across compilations
  • Incremental compilation: Build complex applications piece by piece

Example - Building an Application Incrementally:

const embeddedCompiler = embedded_compiler(RapydScript, baselib);

// Step 1: Define utility functions
embeddedCompiler.compile(`
def utils_multiply(a, b):
    return a * b

def utils_format(value):
    return "Result: " + str(value)
`);

// Step 2: Define main class (can use previously defined functions)
embeddedCompiler.compile(`
class MathApp:
    def calculate(self, x, y):
        result = utils_multiply(x, y)
        return utils_format(result)
`);

// Step 3: Create and use application
const finalJS = embeddedCompiler.compile(`
app = MathApp()
output = app.calculate(6, 7)
print(output)  # Prints: Result: 42
`);

// All previous definitions are preserved and available
console.log(finalJS);

Web Browser Integration

The embedded compiler is designed for browser environments and can be integrated into web-based development tools:

HTML Integration:

<!DOCTYPE html>
<html>
<head>
  <script src="rapydscript-compiler.js"></script>
  <script src="rapydscript-baselib.js"></script>
</head>
<body>
  <textarea id="code">
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))
  </textarea>
  <button onclick="compileAndRun()">Run</button>
  <pre id="output"></pre>

  <script>
    // Create embedded compiler
    const RapydScript = window.create_compiler();
    const embeddedCompiler = window.create_embedded_compiler(
      RapydScript, 
      window.baselib_code,
      function(code) { 
        // Custom execution function
        try {
          return eval(code);
        } catch(e) {
          document.getElementById('output').textContent = 'Error: ' + e.message;
        }
      }
    );

    function compileAndRun() {
      const code = document.getElementById('code').value;
      try {
        const js = embeddedCompiler.compile(code);
        eval(js);
      } catch(e) {
        document.getElementById('output').textContent = 'Compilation error: ' + e.message;
      }
    }
  </script>
</body>
</html>

Error Handling

The embedded compiler provides detailed error information for debugging:

try {
  const result = embeddedCompiler.compile(`
  def broken_function(:
      return "missing parenthesis"
  `);
} catch (error) {
  if (error instanceof RapydScript.SyntaxError) {
    console.error(`Syntax error in ${error.filename || '<embedded>'}: ${error.message}`);
    if (error.line) console.error(`Line ${error.line}, Column ${error.col || 0}`);
  } else {
    console.error('Compilation failed:', error.message);
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-rapydscript-ng

docs

ast.md

cli.md

compilation.md

embedded.md

index.md

libraries.md

output.md

tile.json