about summary refs log tree commit diff stats
path: root/js/scripting-lang/design/IDEAS.md
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/design/IDEAS.md')
-rw-r--r--js/scripting-lang/design/IDEAS.md375
1 files changed, 375 insertions, 0 deletions
diff --git a/js/scripting-lang/design/IDEAS.md b/js/scripting-lang/design/IDEAS.md
new file mode 100644
index 0000000..f11b9da
--- /dev/null
+++ b/js/scripting-lang/design/IDEAS.md
@@ -0,0 +1,375 @@
+# Ideas for future enhancements
+
+## io architecture ideas
+
+### ..listen and ..emit for external process interface
+- ..listen: receives well-defined state object from JS harness
+- ..emit: sends state/commands back to JS harness
+- pattern similar to Elm's TEA (The Elm Architecture)
+
+### js harness application:
+- holds the scripting language interpreter
+- manages state flow: input -> script -> output
+- provides well-known interface for data exchange
+- handles error recovery and safety
+
+### safety considerations:
+- sandboxed execution environment
+- timeouts for script execution
+- memory limits
+- input validation/sanitization
+- error boundaries around script execution
+- fallback state if script fails
+
+### error tolerance:
+- graceful degradation when scripts fail
+- default/fallback responses
+- retry mechanisms with backoff
+- circuit breaker pattern for repeated failures
+- logging and monitoring of script execution
+
+### architectural patterns this resembles:
+- actor model (isolated state, message passing)
+- event sourcing (state changes as events)
+- command pattern (emit commands, not direct state mutations)
+- microservices communication patterns
+- reactive programming (data flow, state updates)
+
+### js harness interface ideas:
+- onStateUpdate(callback) - register for state changes
+- sendState(state) - send state to script
+- onError(callback) - handle script errors
+- setConfig(options) - configure timeouts, limits, etc.
+
+### example flow:
+1. external system sends state to js harness
+2. harness calls script with ..listen state
+3. script processes state, emits new state/commands
+4. harness receives emit, updates external system
+5. cycle repeats
+
+### questions:
+- should scripts be stateless or maintain internal state?
+- how to handle async operations in scripts?
+- what format for state objects? (json, structured data?)
+- how to version state schemas?
+- should emit be synchronous or allow batching?
+
+---
+
+## js harness pseudo code
+
+### basic harness structure
+```javascript
+class ScriptHarness {
+  constructor(config) {
+    this.interpreter = new ScriptInterpreter();
+    this.stateHistory = [];
+    this.config = {
+      timeout: 5000,
+      memoryLimit: '10MB',
+      maxRetries: 3,
+      ...config
+    };
+  }
+
+  // main entry point
+  async processState(newState) {
+    try {
+      // validate and version state
+      const validatedState = this.validateState(newState);
+      
+      // add to history
+      this.stateHistory.push({
+        version: validatedState.version,
+        timestamp: Date.now(),
+        data: validatedState
+      });
+
+      // run script with state
+      const result = await this.runScript(validatedState);
+      
+      // emit result to external system
+      await this.emitResult(result);
+      
+    } catch (error) {
+      await this.handleError(error);
+    }
+  }
+
+  // run script with timeout and error handling
+  async runScript(state) {
+    return new Promise((resolve, reject) => {
+      const timeout = setTimeout(() => {
+        reject(new Error('Script execution timeout'));
+      }, this.config.timeout);
+
+      try {
+        // translate JS state to script format
+        const scriptState = this.translateToScript(state);
+        
+        // run script with ..listen and capture ..emit
+        const result = this.interpreter.run(scriptState);
+        
+        clearTimeout(timeout);
+        resolve(result);
+      } catch (error) {
+        clearTimeout(timeout);
+        reject(error);
+      }
+    });
+  }
+
+  // state translation layer
+  translateToScript(jsState) {
+    // convert JS objects to script tables
+    // handle null/undefined
+    // add version info
+    // validate schema
+    return {
+      data: this.convertToTable(jsState),
+      version: jsState.version || '1.0.0',
+      timestamp: Date.now()
+    };
+  }
+
+  translateFromScript(scriptResult) {
+    // convert script tables back to JS objects
+    // validate output schema
+    // handle errors
+    return this.convertFromTable(scriptResult);
+  }
+
+  // state history management
+  rewindToVersion(targetVersion) {
+    // find state at target version
+    // replay state changes up to that point
+    // return state at that version
+  }
+
+  stepForward() {
+    // move one state forward in history
+  }
+
+  stepBackward() {
+    // move one state backward in history
+  }
+
+  // error handling
+  async handleError(error) {
+    // log error
+    // apply fallback state
+    // notify external system
+    // implement circuit breaker if needed
+  }
+}
+```
+
+### external system integration
+```javascript
+// example usage
+const harness = new ScriptHarness({
+  timeout: 3000,
+  maxRetries: 2
+});
+
+// register callbacks
+harness.onStateUpdate((newState) => {
+  // send to external system
+  externalSystem.update(newState);
+});
+
+harness.onError((error) => {
+  // handle script errors
+  console.error('Script error:', error);
+  externalSystem.handleError(error);
+});
+
+// process incoming state
+await harness.processState({
+  user: { name: "Alice", age: 30 },
+  action: "login",
+  version: "1.0.0"
+});
+```
+
+### script execution flow
+```javascript
+// script gets state via ..listen
+// script processes state
+// script emits result via ..emit
+// harness captures emit and translates back to JS
+
+// example script:
+/*
+current_state : ..listen;
+processed : when current_state.action is
+    "login" then { user: current_state.user, status: "logged_in" }
+    "logout" then { user: null, status: "logged_out" }
+    _ then current_state;
+..emit processed;
+*/
+```
+
+---
+
+## script design decisions
+
+### stateless scripts (agreed - most functional approach)
+- scripts are pure functions: state in -> state out
+- no internal state, no side effects between calls
+- each ..listen call starts fresh
+- enables easy testing, debugging, replay
+- matches functional programming principles
+
+### async operations ideas:
+- ..wait ms - pause script execution for milliseconds
+- ..promise value - create a promise-like construct
+- ..yield - yield control back to harness, resume later
+- ..spawn script - run another script asynchronously
+- ..join handle - wait for spawned script to complete
+- or: keep scripts synchronous, handle async in JS harness
+
+### state format translation layer:
+- js objects -> script tables conversion
+- script tables -> js objects conversion
+- schema validation on both sides
+- type coercion (numbers, strings, booleans)
+- nested object/table translation
+- array/table translation (1-based indexing)
+- null/undefined handling
+
+### known architectural approaches:
+- adapter pattern (translate between formats)
+- facade pattern (simplify complex interfaces)
+- data transfer objects (DTOs)
+- serialization/deserialization layers
+- schema-first design (define format first)
+
+### schema versioning for state history:
+- version field in state objects
+- migration functions for old -> new schemas
+- state history as array of versioned states
+- rollback capability to previous versions
+- forward compatibility (new code handles old state)
+- backward compatibility (old code handles new state)
+
+### versioning approaches:
+- semantic versioning (major.minor.patch)
+- timestamp-based versioning
+- hash-based versioning (content-addressable)
+- incremental versioning (v1, v2, v3)
+
+### state history implementation:
+- append-only log of state changes
+- each state includes version and timestamp
+- rewind: replay state changes up to target version
+- step: move forward/backward one state at a time
+- snapshot: save current state for quick restore
+
+### emit behavior:
+- synchronous by default (simpler to reason about)
+- single emit per script execution
+- multiple emits could be batched by harness
+- or: allow multiple emits, harness decides how to handle
+- error if script doesn't emit anything
+
+---
+
+## type checking ideas
+
+### type checker functions
+- add to standard library: is_number, is_string, is_boolean, is_function, is_table, is_null, is_undefined
+- use with @ syntax in when expressions
+- no parser changes needed
+- composable with existing operators
+
+### example
+```
+is_number : x -> equals(typeof x, "number");
+classify : x -> when x is
+    @is_number then "number"
+    @is_string then "string"
+    @is_table then "table"
+    _ then "unknown";
+```
+
+### advantages:
+- uses existing features
+- composable (can combine with and/or)
+- extensible
+- consistent with functional patterns
+- immediate implementation possible
+
+### advanced type checking ideas
+
+#### error type support
+- add is_error to standard library
+- error objects could have structure: { type: "error", message: "string", code: "number" }
+- or simpler: just check if object has error-like properties
+
+```javascript
+// basic error checking using existing patterns
+is_error : x -> @is_table and not @equals(x.error, undefined);
+
+// more sophisticated error checking
+is_error : x -> @is_table and 
+    (@logicalOr 
+        (@not @equals(x.error, undefined))
+        (@logicalOr 
+            (@not @equals(x.message, undefined))
+            (@not @equals(x.code, undefined))
+        )
+    );
+
+// alternative: use table access with error handling
+is_error : x -> @is_table and 
+    (@logicalOr 
+        (@not @equals(x["error"], undefined))
+        (@logicalOr 
+            (@not @equals(x["message"], undefined))
+            (@not @equals(x["code"], undefined))
+        )
+    );
+
+// usage in when expressions
+handle_result : x -> when x is
+    @is_error then "error occurred"
+    @is_number then "success"
+    _ then "unknown";
+```
+
+#### tagged unions / discriminated unions
+- could represent different states: success/error, loading/loaded/error, etc.
+- structure: { tag: "success", data: value } or { tag: "error", error: message }
+
+```javascript
+// type checkers for tagged unions
+has_tag : tag -> obj -> @is_table and equals(obj.tag, tag);
+
+is_success : x -> has_tag "success" x;
+is_error_result : x -> has_tag "error" x;
+
+// usage
+process_result : x -> when x is
+    @is_success then x.data
+    @is_error_result then "error: " + x.error
+    _ then "unknown result";
+```
+
+#### questions about error types:
+- do we need a special error type or just error-like objects?
+- should errors be first-class or just table properties?
+- how do errors propagate through function composition?
+- should we have error handling combinators (map_error, catch_error)?
+
+#### questions about tagged unions:
+- are they worth the complexity for this language?
+- do they add enough value over simple when expressions?
+- would they make scripts harder to read/write?
+- are they more useful in the JS harness than in scripts?
+
+#### simpler alternatives:
+- just use when expressions with property checking
+- error handling in JS harness, keep scripts simple
+- use standard library functions for common error patterns
\ No newline at end of file