about summary refs log tree commit diff stats
path: root/js/scripting-lang/tutorials/12_Functional_Harness_Integration.md
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/tutorials/12_Functional_Harness_Integration.md')
-rw-r--r--js/scripting-lang/tutorials/12_Functional_Harness_Integration.md569
1 files changed, 0 insertions, 569 deletions
diff --git a/js/scripting-lang/tutorials/12_Functional_Harness_Integration.md b/js/scripting-lang/tutorials/12_Functional_Harness_Integration.md
deleted file mode 100644
index 7bc487f..0000000
--- a/js/scripting-lang/tutorials/12_Functional_Harness_Integration.md
+++ /dev/null
@@ -1,569 +0,0 @@
-# Functional Harness Integration
-
-The Functional Harness provides a TEA-inspired state management system for integrating scripts with external systems. This tutorial covers the core concepts and practical usage.
-
-## Overview
-
-The harness loosely implements The Elm Architecture (TEA):
-
-- **Model**: Current state (pure table data)
-- **Update**: Pure function (State → { model, commands, version })
-- **Commands**: Side effects processed by adapters
-- **View**: External system integration
-
-## Core Concepts
-
-### State Flow
-
-```
-External System → Adapter → Harness → Script (..listen/..emit) → Commands → Adapter → External System
-```
-
-### Pure Functions
-
-Scripts remain pure functions that:
-1. Read state via `..listen`
-2. Process state using pattern matching
-3. Emit commands via `..emit`
-4. Return new state (optional)
-
-## Basic Usage
-
-### Simple State Processing
-
-```javascript
-import { FunctionalHarness } from '../scripting-harness/core/harness.js';
-
-const script = `
-/* Get current state */
-state : ..listen;
-
-/* Process based on state */
-result : when state is
-    { status: "active" } then { action: "continue" }
-    { status: "paused" } then { action: "resume" }
-    _ then { action: "stop" };
-
-/* Emit result */
-..emit result;
-`;
-
-const harness = new FunctionalHarness(script);
-await harness.initialize(); // Important: Initialize the harness first
-const result = await harness.update({ status: "active" });
-
-console.log(result.commands);
-// [{ type: 'emit', value: { action: 'continue' } }]
-```
-
-### Multiple Commands
-
-Scripts can emit multiple commands:
-
-```javascript
-const script = `
-state : ..listen;
-
-/* Emit multiple commands */
-..emit { type: "log", message: "Processing state" };
-..emit { type: "update", data: state };
-..emit { type: "notify", user: state.user };
-`;
-
-const harness = new FunctionalHarness(script);
-await harness.initialize();
-const result = await harness.update({ user: "Alice", data: "test" });
-
-console.log(result.commands.length); // 3 commands emitted
-```
-
-### REPL Integration Example
-
-The REPL demonstrates practical harness usage:
-
-```javascript
-// From the REPL examples
-const counterScript = `
-/* Counter with state management */
-state : ..listen;
-count : when state is { count: count } then count _ then 0;
-new_count : count + 1;
-updated_state : { count: new_count };
-..emit updated_state;
-updated_state
-`;
-
-const harness = new FunctionalHarness(counterScript);
-await harness.initialize();
-
-// Process multiple state updates
-await harness.update({ count: 0 });     // Version 1: count = 1
-await harness.update({ count: 1 });     // Version 2: count = 2
-await harness.update({ count: 2 });     // Version 3: count = 3
-```
-
-## State Versioning
-
-### Automatic Versioning
-
-Each state change creates a new version:
-
-```javascript
-// Process multiple states
-await harness.update({ status: "active" });     // Version 1
-await harness.update({ status: "paused" });     // Version 2
-await harness.update({ status: "stopped" });    // Version 3
-
-// Get version history
-const history = harness.getVersionHistory();
-console.log(history);
-// [
-//   { version: 1, timestamp: 1234567890, hash: 12345 },
-//   { version: 2, timestamp: 1234567891, hash: 67890 },
-//   { version: 3, timestamp: 1234567892, hash: 11111 }
-// ]
-```
-
-### Rollback and Replay
-
-```javascript
-// Rollback to specific version
-const historicalState = await harness.rollbackToVersion(2);
-
-// Replay from version with new state
-const replayResult = await harness.replayFromVersion(1, { 
-    status: "active", 
-    user: "Bob" 
-});
-```
-
-### Branching (REPL Feature)
-
-The REPL demonstrates branching capabilities:
-
-```javascript
-// Create a branch from version 2
-const branchHarness = await harness.createBranch(2, "experimental");
-
-// Work on the branch
-await branchHarness.update({ status: "experimental", feature: "new" });
-
-// Original harness continues independently
-await harness.update({ status: "stable", feature: "existing" });
-```
-
-## Error Handling
-
-### Graceful Error Recovery
-
-The harness handles script errors gracefully:
-
-```javascript
-const script = `
-state : ..listen;
-/* This will cause an error */
-invalid : apply "not a function" to [1, 2, 3];
-..emit invalid;
-`;
-
-const result = await harness.update({ status: "active" });
-
-if (result.commands.some(cmd => cmd.type === 'error')) {
-    console.log('Script error handled:', result.commands[0].error);
-    // Script error handled: apply: first argument must be a function
-}
-```
-
-### Error Classification
-
-Errors are classified for better handling:
-
-```javascript
-const errorCommand = result.commands.find(cmd => cmd.type === 'error');
-console.log(errorCommand.errorType); // 'unknown_error', 'timeout', etc.
-```
-
-## Configuration
-
-### Harness Configuration
-
-```javascript
-const config = {
-    maxVersions: 100,        // Maximum versions to keep
-    timeout: 5000,           // Script execution timeout (ms)
-    logStateChanges: true,   // Log state changes
-    logCommands: true        // Log commands
-};
-
-const harness = new FunctionalHarness(script, config);
-```
-
-### State History Configuration
-
-```javascript
-// Clean up old versions
-harness.stateHistory.cleanupOldVersions(50); // Keep only 50 versions
-
-// Get diff between versions
-const diff = harness.stateHistory.getDiff(1, 5);
-console.log(diff);
-// {
-//   added: { newProperty: "value" },
-//   removed: { oldProperty: "value" },
-//   changed: { modifiedProperty: { from: "old", to: "new" } }
-// }
-```
-
-## Integration Patterns
-
-### Adapter Pattern (REPL Implementation)
-
-The REPL demonstrates the adapter pattern with Console, File, and Network adapters:
-
-```javascript
-// Console Adapter - handles general output
-const consoleAdapter = {
-    process: async (command) => {
-        if (command.type === 'log') {
-            console.log('[Console]', command.message);
-        }
-    }
-};
-
-// File Adapter - handles file operations
-const fileAdapter = {
-    process: async (command) => {
-        if (command.action === 'save_file') {
-            console.log('[File] Would save:', command.filename, command.content);
-        }
-    }
-};
-
-// Network Adapter - handles HTTP requests
-const networkAdapter = {
-    process: async (command) => {
-        if (command.action === 'http_request') {
-            console.log('[Network] Would make', command.method, 'request to:', command.url);
-        }
-    }
-};
-
-// Register adapters with harness
-const adapters = [consoleAdapter, fileAdapter, networkAdapter];
-```
-
-### Network Integration Example
-
-The REPL includes a PokéAPI integration example:
-
-```javascript
-const networkScript = `
-/* Network API integration example */
-/* Using PokéAPI to fetch Pokémon data */
-
-/* Get current state to see if we have a Pokémon name */
-state : ..listen;
-
-/* Determine which Pokémon to fetch */
-pokemon_name : when state is
-    { pokemon: name } then name
-    _ then "ditto";  /* Default to ditto */
-
-/* Emit network request to PokéAPI */
-..emit {
-    action: "http_request",
-    method: "GET",
-    url: "https://pokeapi.co/api/v2/pokemon/" + pokemon_name
-};
-
-/* Also fetch a list of Pokémon */
-..emit {
-    action: "http_request",
-    method: "GET",
-    url: "https://pokeapi.co/api/v2/pokemon?limit=5"
-};
-
-/* Return the request configuration */
-{
-    pokemon_name,
-    requests: [
-        { method: "GET", url: "https://pokeapi.co/api/v2/pokemon/" + pokemon_name },
-        { method: "GET", url: "https://pokeapi.co/api/v2/pokemon?limit=5" }
-    ]
-}
-`;
-
-const harness = new FunctionalHarness(networkScript);
-await harness.initialize();
-
-// Process with network adapter
-const result = await harness.update({ pokemon: "pikachu" });
-// Output: [Network] Would make GET request to: https://pokeapi.co/api/v2/pokemon/pikachu
-// Output: [Network] Would make GET request to: https://pokeapi.co/api/v2/pokemon?limit=5
-```
-
-## Advanced Patterns
-
-### State Composition (REPL Examples)
-
-The REPL demonstrates complex state processing:
-
-```javascript
-// Pattern matching example from REPL
-const patternScript = `
-/* Pattern matching with complex state */
-state : ..listen;
-
-/* Extract user data */
-user : state.user;
-age : user.age;
-
-/* Process based on age */
-status : when age is
-    age < 18 then "minor"
-    age < 65 then "adult"
-    _ then "senior";
-
-/* Process based on user type */
-access : when user is
-    { role: "admin" } then "full"
-    { role: "user" } then "limited"
-    _ then "guest";
-
-/* Compose final result */
-result : {
-    user: user.name,
-    age: age,
-    status: status,
-    access: access,
-    timestamp: state.timestamp
-};
-
-..emit result;
-result
-`;
-
-const harness = new FunctionalHarness(patternScript);
-await harness.initialize();
-
-const result = await harness.update({
-    user: { name: "Alice", age: 25, role: "admin" },
-    timestamp: Date.now()
-});
-```
-
-### Conditional Command Emission
-
-```javascript
-const conditionalScript = `
-state : ..listen;
-
-/* Only emit commands under certain conditions */
-when state.status is "active" then
-    ..emit { type: "process", data: state.data };
-
-when state.user.score > 100 then
-    ..emit { type: "achievement", score: state.user.score };
-
-when state.game.level > 10 then
-    ..emit { type: "levelup", level: state.game.level };
-`;
-```
-
-## Best Practices
-
-### 1. Keep Scripts Pure
-
-```javascript
-// ✅ Good: Pure function
-const script = `
-state : ..listen;
-result : process state;
-..emit result;
-`;
-
-// ❌ Avoid: Side effects in scripts
-const script = `
-state : ..listen;
-/* Don't do this - keep side effects in adapters */
-..out "banana";
-..emit state;
-`;
-```
-
-### 2. Use Pattern Matching
-
-```javascript
-// ✅ Good: Clear pattern matching
-const script = `
-state : ..listen;
-action : when state is
-    { type: "user_input" } then processUserInput state
-    { type: "system_event" } then processSystemEvent state
-    _ then { error: "unknown state type" };
-..emit action;
-`;
-```
-
-### 3. Emit Structured Commands
-
-```javascript
-// ✅ Good: Structured commands
-..emit { 
-    type: "game_action", 
-    action: "move", 
-    direction: "north",
-    player: state.player.id 
-};
-
-// ❌ Avoid: Unstructured data
-..emit "move north";
-```
-
-### 4. Handle Errors Gracefully
-
-```javascript
-const script = `
-state : ..listen;
-
-/* Always provide fallback patterns */
-result : when state is
-    { data: validData } then process validData
-    _ then { error: "invalid state", received: state };
-
-..emit result;
-`;
-```
-
-## Testing
-
-### Unit Testing Scripts
-
-```javascript
-// Test script in isolation
-const testScript = `
-state : ..listen;
-result : when state is
-    { input: "test" } then { output: "processed" }
-    _ then { output: "default" };
-..emit result;
-`;
-
-const harness = new FunctionalHarness(testScript);
-await harness.initialize();
-
-// Test cases
-const testCases = [
-    { input: { input: "test" }, expected: { output: "processed" } },
-    { input: { input: "other" }, expected: { output: "default" } },
-    { input: {}, expected: { output: "default" } }
-];
-
-for (const testCase of testCases) {
-    const result = await harness.update(testCase.input);
-    const command = result.commands[0];
-    assert.deepEqual(command.value, testCase.expected);
-}
-```
-
-### Integration Testing (REPL Style)
-
-```javascript
-// Test full integration with adapters
-class TestAdapter {
-    constructor(harness) {
-        this.harness = harness;
-        this.commands = [];
-    }
-    
-    async handleEvent(event) {
-        const result = await this.harness.update(event);
-        this.commands.push(...result.commands);
-        return result.model;
-    }
-    
-    getCommands() {
-        return this.commands;
-    }
-    
-    clearCommands() {
-        this.commands = [];
-    }
-}
-
-// Test with network adapter
-const networkTestScript = `
-state : ..listen;
-..emit {
-    action: "http_request",
-    method: "GET",
-    url: "https://api.example.com/test"
-};
-`;
-
-const testHarness = new FunctionalHarness(networkTestScript);
-await testHarness.initialize();
-
-const testAdapter = new TestAdapter(testHarness);
-const result = await testAdapter.handleEvent({ test: "data" });
-
-console.log(testAdapter.getCommands());
-// [{ type: 'emit', value: { action: 'http_request', method: 'GET', url: '...' } }]
-```
-
-## Summary
-
-The Functional Harness provides:
-
-- **Pure Functions**: Scripts remain functional and side-effect free
-- **Automatic Versioning**: State history with rollback capabilities
-- **Error Handling**: Graceful error recovery and classification
-- **Command Processing**: Atomic command collection and processing
-- **Integration Ready**: Foundation for building adapters
-- **REPL Integration**: Interactive development environment with examples
-
-## Key Learnings from REPL Implementation
-
-### 1. Initialization is Critical
-Always call `await harness.initialize()` before using the harness. This loads the language interpreter and sets up the environment.
-
-### 2. Use `update()` Instead of `processState()`
-The correct method is `harness.update(state)` for processing state changes. The `processState()` method is for internal use.
-
-### 3. Adapter Pattern Works
-The REPL demonstrates that the adapter pattern is effective for handling different types of commands (Console, File, Network).
-
-### 4. State Persistence
-The harness maintains state across multiple calls, making it suitable for interactive applications like the REPL.
-
-### 5. Versioning is Powerful
-Branching and rollback capabilities provide powerful debugging and experimentation tools.
-
-## Known Limitations and Considerations
-
-### 1. Harness Initialization Issue
-Currently, there's a known issue where `harness.initialize()` may hang during the `lang.js` import process. This affects script execution in some environments and prevents proper command processing.
-
-### 2. Language Syntax Requirements
-- Scripts must be assigned to variables: `result : myFunction arg1 arg2;`
-- Function calls require assignment: `output : add 3 4;` (not just `add 3 4;`)
-- Multi-line scripts must end with semicolon
-
-### 3. Adapter System Limitations
-- Only basic adapters (Console, File, Network) are currently implemented
-- Advanced adapters (WebSocket, HTTP, Game) are planned for future development
-- Adapter command processing requires proper harness initialization
-
-### 4. State Management Constraints
-- State is maintained in memory (not persisted to disk by default)
-- Version history is limited by `maxVersions` configuration
-- Large state objects may impact performance
-- State translation between JS and script formats may lose some metadata
-
-### 5. Error Handling
-- Script errors are captured and returned as error commands
-- Timeout protection prevents infinite loops
-- Error classification helps with debugging
-- Error states don't crash the harness but may affect subsequent operations
-
-This architecture enables building complex applications while maintaining functional purity and providing robust state management capabilities. The REPL serves as a practical demonstration of these concepts in action. 
\ No newline at end of file