about summary refs log tree commit diff stats
path: root/js/scripting-lang/lang.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/lang.js')
-rw-r--r--js/scripting-lang/lang.js466
1 files changed, 290 insertions, 176 deletions
diff --git a/js/scripting-lang/lang.js b/js/scripting-lang/lang.js
index 3ed32a1..070998e 100644
--- a/js/scripting-lang/lang.js
+++ b/js/scripting-lang/lang.js
@@ -5,6 +5,91 @@
 import { lexer, TokenType } from './lexer.js';
 import { parser } from './parser.js';
 
+// Cross-platform environment detection
+const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
+const isBun = typeof process !== 'undefined' && process.versions && process.versions.bun;
+const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
+
+// Cross-platform debug flag
+const DEBUG = (isNode && process.env.DEBUG) || (isBrowser && window.DEBUG) || false;
+
+// Cross-platform IO operations
+const createReadline = () => {
+    if (isNode || isBun) {
+        const readline = require('readline');
+        return readline.createInterface({
+            input: process.stdin,
+            output: process.stdout
+        });
+    } else if (isBrowser) {
+        // Browser fallback - use prompt() for now
+        return {
+            question: (prompt, callback) => {
+                const result = window.prompt(prompt);
+                callback(result);
+            },
+            close: () => {}
+        };
+    } else {
+        // Fallback for other environments
+        return {
+            question: (prompt, callback) => {
+                callback("fallback input");
+            },
+            close: () => {}
+        };
+    }
+};
+
+const createFileSystem = () => {
+    if (isNode || isBun) {
+        return require('fs');
+    } else if (isBrowser) {
+        // Browser fallback - return a mock filesystem
+        return {
+            readFile: (path, encoding, callback) => {
+                callback(new Error('File system not available in browser'));
+            },
+            writeFile: (path, data, callback) => {
+                callback(new Error('File system not available in browser'));
+            }
+        };
+    } else {
+        // Fallback for other environments
+        return {
+            readFile: (path, encoding, callback) => {
+                callback(new Error('File system not available in this environment'));
+            },
+            writeFile: (path, data, callback) => {
+                callback(new Error('File system not available in this environment'));
+            }
+        };
+    }
+};
+
+// Cross-platform console output
+const safeConsoleLog = (message) => {
+    if (typeof console !== 'undefined') {
+        console.log(message);
+    }
+};
+
+const safeConsoleError = (message) => {
+    if (typeof console !== 'undefined') {
+        console.error(message);
+    }
+};
+
+// Cross-platform process exit
+const safeExit = (code) => {
+    if (isNode || isBun) {
+        process.exit(code);
+    } else if (isBrowser) {
+        // In browser, we can't exit, but we can throw an error or redirect
+        throw new Error(`Process would exit with code ${code}`);
+    }
+};
+
 /**
  * Environment interface for external system integration
  * 
@@ -47,6 +132,7 @@ import { parser } from './parser.js';
  * function arguments and validation of input data.
  */
 function initializeStandardLibrary(scope) {
+
     /**
      * Map: Apply a function to a value or collection
      * @param {Function} f - Function to apply
@@ -385,10 +471,10 @@ function initializeStandardLibrary(scope) {
      * application.
      */
     scope.reduce = function(f, init, x) { 
-        if (process.env.DEBUG) {
-            console.log(`[DEBUG] reduce: f =`, typeof f, f);
-            console.log(`[DEBUG] reduce: init =`, init);
-            console.log(`[DEBUG] reduce: x =`, x);
+        if (DEBUG) {
+            safeConsoleLog(`[DEBUG] reduce: f =`, typeof f, f);
+            safeConsoleLog(`[DEBUG] reduce: init =`, init);
+            safeConsoleLog(`[DEBUG] reduce: x =`, x);
         }
         
         if (typeof f !== 'function') {
@@ -398,10 +484,10 @@ function initializeStandardLibrary(scope) {
         if (init === undefined) {
             // Partial application: return a function that waits for the remaining arguments
             return function(init, x) {
-                if (process.env.DEBUG) {
-                    console.log(`[DEBUG] reduce returned function: f =`, typeof f, f);
-                    console.log(`[DEBUG] reduce returned function: init =`, init);
-                    console.log(`[DEBUG] reduce returned function: x =`, x);
+                if (DEBUG) {
+                    safeConsoleLog(`[DEBUG] reduce returned function: f =`, typeof f, f);
+                    safeConsoleLog(`[DEBUG] reduce returned function: init =`, init);
+                    safeConsoleLog(`[DEBUG] reduce returned function: x =`, x);
                 }
                 if (x === undefined) {
                     // Still partial application
@@ -496,6 +582,12 @@ function initializeStandardLibrary(scope) {
      * operations through the combinator foundation.
      */
     scope.add = function(x, y) {
+        if (y === undefined) {
+            // Partial application: return a function that waits for the second argument
+            return function(y) {
+                return x + y;
+            };
+        }
         return x + y;
     };
     
@@ -506,6 +598,12 @@ function initializeStandardLibrary(scope) {
      * @returns {number} Difference of x and y
      */
     scope.subtract = function(x, y) {
+        if (y === undefined) {
+            // Partial application: return a function that waits for the second argument
+            return function(y) {
+                return x - y;
+            };
+        }
         return x - y;
     };
     
@@ -528,6 +626,12 @@ function initializeStandardLibrary(scope) {
      * operations through the combinator foundation.
      */
     scope.multiply = function(x, y) {
+        if (y === undefined) {
+            // Partial application: return a function that waits for the second argument
+            return function(y) {
+                return x * y;
+            };
+        }
         return x * y;
     };
     
@@ -539,6 +643,15 @@ function initializeStandardLibrary(scope) {
      * @throws {Error} When second argument is zero
      */
     scope.divide = function(x, y) {
+        if (y === undefined) {
+            // Partial application: return a function that waits for the second argument
+            return function(y) {
+                if (y === 0) {
+                    throw new Error('Division by zero');
+                }
+                return x / y;
+            };
+        }
         if (y === 0) {
             throw new Error('Division by zero');
         }
@@ -552,6 +665,12 @@ function initializeStandardLibrary(scope) {
      * @returns {number} Remainder of x divided by y
      */
     scope.modulo = function(x, y) {
+        if (y === undefined) {
+            // Partial application: return a function that waits for the second argument
+            return function(y) {
+                return x % y;
+            };
+        }
         return x % y;
     };
     
@@ -562,6 +681,12 @@ function initializeStandardLibrary(scope) {
      * @returns {number} x raised to the power of y
      */
     scope.power = function(x, y) {
+        if (y === undefined) {
+            // Partial application: return a function that waits for the second argument
+            return function(y) {
+                return Math.pow(x, y);
+            };
+        }
         return Math.pow(x, y);
     };
     
@@ -798,9 +923,9 @@ function initializeStandardLibrary(scope) {
      * transformations.
      */
     scope.each = function(f, x) {
-        if (process.env.DEBUG) {
-            console.log(`[DEBUG] each called with: f=${typeof f}, x=${typeof x}`);
-            console.log(`[DEBUG] x value:`, x);
+        if (DEBUG) {
+            safeConsoleLog(`[DEBUG] each called with: f=${typeof f}, x=${typeof x}`);
+            safeConsoleLog(`[DEBUG] x value:`, x);
         }
         
         if (typeof f !== 'function') {
@@ -1250,10 +1375,10 @@ function interpreter(ast, environment = null, initialState = {}) {
     let ioOperationsPerformed = false;
     
     // Debug: Check if combinators are available
-    if (process.env.DEBUG) {
-        console.log('[DEBUG] Available functions in global scope:', Object.keys(globalScope));
-        console.log('[DEBUG] add function exists:', typeof globalScope.add === 'function');
-        console.log('[DEBUG] subtract function exists:', typeof globalScope.subtract === 'function');
+    if (DEBUG) {
+        safeConsoleLog('[DEBUG] Available functions in global scope:', Object.keys(globalScope));
+        safeConsoleLog('[DEBUG] add function exists:', typeof globalScope.add === 'function');
+        safeConsoleLog('[DEBUG] subtract function exists:', typeof globalScope.subtract === 'function');
     }
     
     // Reset call stack tracker at the start of interpretation
@@ -1380,8 +1505,8 @@ function interpreter(ast, environment = null, initialState = {}) {
                                 key = evalNode(entry.key);
                             }
                             // Special handling for FunctionDeclaration nodes
-                            if (process.env.DEBUG) {
-                                console.log(`[DEBUG] TableLiteral: entry.value.type = ${entry.value.type}`);
+                            if (DEBUG) {
+                                safeConsoleLog(`[DEBUG] TableLiteral: entry.value.type = ${entry.value.type}`);
                             }
                             if (entry.value.type === 'FunctionDeclaration') {
                                 // Don't evaluate the function body, just create the function
@@ -1577,27 +1702,27 @@ function interpreter(ast, environment = null, initialState = {}) {
                     if (typeof node.name === 'string') {
                         // Regular function call with string name
                         funcToCall = globalScope[node.name];
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] FunctionCall: looking up function '${node.name}' in globalScope, found:`, typeof funcToCall);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] FunctionCall: looking up function '${node.name}' in globalScope, found:`, typeof funcToCall);
                         }
                     } else if (node.name.type === 'Identifier') {
                         // Function call with identifier
                         funcToCall = globalScope[node.name.value];
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] FunctionCall: looking up function '${node.name.value}' in globalScope, found:`, typeof funcToCall);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] FunctionCall: looking up function '${node.name.value}' in globalScope, found:`, typeof funcToCall);
                         }
                     } else {
                         // Function call from expression (e.g., parenthesized function, higher-order)
                         funcToCall = evalNode(node.name);
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] FunctionCall: evaluated function expression, found:`, typeof funcToCall);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] FunctionCall: evaluated function expression, found:`, typeof funcToCall);
                         }
                     }
                     
-                    if (funcToCall instanceof Function) {
+                    if (typeof funcToCall === 'function') {
                         let args = node.args.map(evalNode);
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] FunctionCall: calling function with args:`, args);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] FunctionCall: calling function with args:`, args);
                         }
                         return funcToCall(...args);
                     }
@@ -1608,16 +1733,16 @@ function interpreter(ast, environment = null, initialState = {}) {
                         ? node.value.map(evalNode) 
                         : [evalNode(node.value)];
                     
-                    if (process.env.DEBUG) {
-                        console.log(`[DEBUG] WhenExpression: whenValues =`, whenValues);
+                    if (DEBUG) {
+                        safeConsoleLog(`[DEBUG] WhenExpression: whenValues =`, whenValues);
                     }
                     
                     for (const caseItem of node.cases) {
                         // Handle both single patterns and arrays of patterns
                         const patterns = caseItem.pattern.map(evalNode);
                         
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] WhenExpression: patterns =`, patterns);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] WhenExpression: patterns =`, patterns);
                         }
                         
                         // Check if patterns match the values
@@ -1629,14 +1754,14 @@ function interpreter(ast, environment = null, initialState = {}) {
                                 const value = whenValues[i];
                                 const pattern = patterns[i];
                                 
-                                if (process.env.DEBUG) {
-                                    console.log(`[DEBUG] WhenExpression: comparing value ${value} with pattern ${pattern}`);
+                                if (DEBUG) {
+                                    safeConsoleLog(`[DEBUG] WhenExpression: comparing value ${value} with pattern ${pattern}`);
                                 }
                                 
                                 if (pattern === true) { // Wildcard pattern
                                     // Wildcard always matches
-                                    if (process.env.DEBUG) {
-                                        console.log(`[DEBUG] WhenExpression: wildcard matches`);
+                                    if (DEBUG) {
+                                        safeConsoleLog(`[DEBUG] WhenExpression: wildcard matches`);
                                     }
                                     continue;
                                 } else if (typeof pattern === 'object' && pattern.type === 'FunctionCall') {
@@ -1652,20 +1777,20 @@ function interpreter(ast, environment = null, initialState = {}) {
                                         };
                                     }
                                     const patternResult = evalNode(patternToEvaluate);
-                                    if (process.env.DEBUG) {
-                                        console.log(`[DEBUG] WhenExpression: boolean pattern result = ${patternResult}`);
+                                    if (DEBUG) {
+                                        safeConsoleLog(`[DEBUG] WhenExpression: boolean pattern result = ${patternResult}`);
                                     }
                                     if (!patternResult) {
                                         matches = false;
-                                        if (process.env.DEBUG) {
-                                            console.log(`[DEBUG] WhenExpression: boolean pattern does not match`);
+                                        if (DEBUG) {
+                                            safeConsoleLog(`[DEBUG] WhenExpression: boolean pattern does not match`);
                                         }
                                         break;
-                                    } else {
-                                        if (process.env.DEBUG) {
-                                            console.log(`[DEBUG] WhenExpression: boolean pattern matches`);
+                                                                            } else {
+                                            if (DEBUG) {
+                                                safeConsoleLog(`[DEBUG] WhenExpression: boolean pattern matches`);
+                                            }
                                         }
-                                    }
                                 } else if (typeof pattern === 'object' && pattern !== null && typeof value === 'object' && value !== null) {
                                     // Table pattern matching - check if all pattern properties exist in value
                                     let tableMatches = true;
@@ -1677,31 +1802,31 @@ function interpreter(ast, environment = null, initialState = {}) {
                                     }
                                     if (!tableMatches) {
                                         matches = false;
-                                        if (process.env.DEBUG) {
-                                            console.log(`[DEBUG] WhenExpression: table pattern does not match`);
+                                        if (DEBUG) {
+                                            safeConsoleLog(`[DEBUG] WhenExpression: table pattern does not match`);
                                         }
                                         break;
-                                    } else {
-                                        if (process.env.DEBUG) {
-                                            console.log(`[DEBUG] WhenExpression: table pattern matches`);
+                                                                            } else {
+                                            if (DEBUG) {
+                                                safeConsoleLog(`[DEBUG] WhenExpression: table pattern matches`);
+                                            }
                                         }
-                                    }
                                 } else if (value !== pattern) {
                                     matches = false;
-                                    if (process.env.DEBUG) {
-                                        console.log(`[DEBUG] WhenExpression: pattern does not match`);
+                                    if (DEBUG) {
+                                        safeConsoleLog(`[DEBUG] WhenExpression: pattern does not match`);
                                     }
                                     break;
                                 } else {
-                                    if (process.env.DEBUG) {
-                                        console.log(`[DEBUG] WhenExpression: pattern matches`);
+                                    if (DEBUG) {
+                                        safeConsoleLog(`[DEBUG] WhenExpression: pattern matches`);
                                     }
                                 }
                             }
                         }
                         
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] WhenExpression: case matches = ${matches}`);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] WhenExpression: case matches = ${matches}`);
                         }
                         
                         if (matches) {
@@ -1716,11 +1841,7 @@ function interpreter(ast, environment = null, initialState = {}) {
                 case 'WildcardPattern':
                     return true;
                 case 'IOInExpression':
-                    const readline = require('readline');
-                    const rl = readline.createInterface({
-                        input: process.stdin,
-                        output: process.stdout
-                    });
+                    const rl = createReadline();
                     
                     return new Promise((resolve) => {
                         rl.question('', (input) => {
@@ -1731,7 +1852,7 @@ function interpreter(ast, environment = null, initialState = {}) {
                     });
                 case 'IOOutExpression':
                     const outputValue = evalNode(node.value);
-                    console.log(outputValue);
+                    safeConsoleLog(outputValue);
                     ioOperationsPerformed = true;
                     return outputValue;
                 case 'IOAssertExpression':
@@ -1743,13 +1864,13 @@ function interpreter(ast, environment = null, initialState = {}) {
                 case 'IOListenExpression':
                     // Return current state from environment if available, otherwise placeholder
                     if (environment && typeof environment.getCurrentState === 'function') {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..listen called - returning state from environment');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..listen called - returning state from environment');
                         }
                         return environment.getCurrentState();
                     } else {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..listen called - returning placeholder state');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..listen called - returning placeholder state');
                         }
                         return { status: 'placeholder', message: 'State not available in standalone mode' };
                     }
@@ -1757,19 +1878,19 @@ function interpreter(ast, environment = null, initialState = {}) {
                     const emitValue = evalNode(node.value);
                     // Send value to environment if available, otherwise log to console
                     if (environment && typeof environment.emitValue === 'function') {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..emit called - sending to environment');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..emit called - sending to environment');
                         }
                         environment.emitValue(emitValue);
                     } else {
-                        console.log('[EMIT]', emitValue);
+                        safeConsoleLog('[EMIT]', emitValue);
                     }
                     ioOperationsPerformed = true;
                     return emitValue;
                 case 'FunctionReference':
                     const functionValue = globalScope[node.name];
-                    if (process.env.DEBUG) {
-                        console.log(`[DEBUG] FunctionReference: looking up '${node.name}' in globalScope, found:`, typeof functionValue);
+                    if (DEBUG) {
+                        safeConsoleLog(`[DEBUG] FunctionReference: looking up '${node.name}' in globalScope, found:`, typeof functionValue);
                     }
                     if (functionValue === undefined) {
                         throw new Error(`Function ${node.name} is not defined`);
@@ -2016,16 +2137,16 @@ function interpreter(ast, environment = null, initialState = {}) {
                         ? node.value.map(val => localEvalNodeWithScope(val, scope)) 
                         : [localEvalNodeWithScope(node.value, scope)];
                     
-                    if (process.env.DEBUG) {
-                        console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: whenValues =`, whenValues);
+                    if (DEBUG) {
+                        safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: whenValues =`, whenValues);
                     }
                     
                     for (const caseItem of node.cases) {
                         // Handle both single patterns and arrays of patterns
                         const patterns = caseItem.pattern.map(pat => localEvalNodeWithScope(pat, scope));
                         
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: patterns =`, patterns);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: patterns =`, patterns);
                         }
                         
                         // Check if patterns match the values
@@ -2037,14 +2158,14 @@ function interpreter(ast, environment = null, initialState = {}) {
                                 const value = whenValues[i];
                                 const pattern = patterns[i];
                                 
-                                if (process.env.DEBUG) {
-                                    console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: comparing value ${value} with pattern ${pattern}`);
+                                if (DEBUG) {
+                                    safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: comparing value ${value} with pattern ${pattern}`);
                                 }
                                 
                                 if (pattern === true) { // Wildcard pattern
                                     // Wildcard always matches
-                                    if (process.env.DEBUG) {
-                                        console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: wildcard matches`);
+                                    if (DEBUG) {
+                                        safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: wildcard matches`);
                                     }
                                     continue;
                                 } else if (typeof pattern === 'object' && pattern !== null && typeof value === 'object' && value !== null) {
@@ -2058,31 +2179,31 @@ function interpreter(ast, environment = null, initialState = {}) {
                                     }
                                     if (!tableMatches) {
                                         matches = false;
-                                        if (process.env.DEBUG) {
-                                            console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: table pattern does not match`);
+                                        if (DEBUG) {
+                                            safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: table pattern does not match`);
                                         }
                                         break;
-                                    } else {
-                                        if (process.env.DEBUG) {
-                                            console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: table pattern matches`);
+                                                                            } else {
+                                            if (DEBUG) {
+                                                safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: table pattern matches`);
+                                            }
                                         }
-                                    }
                                 } else if (value !== pattern) {
                                     matches = false;
-                                    if (process.env.DEBUG) {
-                                        console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: pattern does not match`);
+                                    if (DEBUG) {
+                                        safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: pattern does not match`);
                                     }
                                     break;
                                 } else {
-                                    if (process.env.DEBUG) {
-                                        console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: pattern matches`);
+                                    if (DEBUG) {
+                                        safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: pattern matches`);
                                     }
                                 }
                             }
                         }
                         
-                        if (process.env.DEBUG) {
-                            console.log(`[DEBUG] localEvalNodeWithScope WhenExpression: case matches = ${matches}`);
+                        if (DEBUG) {
+                            safeConsoleLog(`[DEBUG] localEvalNodeWithScope WhenExpression: case matches = ${matches}`);
                         }
                         
                         if (matches) {
@@ -2097,22 +2218,18 @@ function interpreter(ast, environment = null, initialState = {}) {
                 case 'WildcardPattern':
                     return true;
                 case 'IOInExpression':
-                    const readline = require('readline');
-                    const rl = readline.createInterface({
-                        input: process.stdin,
-                        output: process.stdout
-                    });
+                    const rl2 = createReadline();
                     
                     return new Promise((resolve) => {
-                        rl.question('', (input) => {
-                            rl.close();
+                        rl2.question('', (input) => {
+                            rl2.close();
                             const num = parseInt(input);
                             resolve(isNaN(num) ? input : num);
                         });
                     });
                 case 'IOOutExpression':
                     const localOutputValue = localEvalNodeWithScope(node.value, scope);
-                    console.log(localOutputValue);
+                    safeConsoleLog(localOutputValue);
                     ioOperationsPerformed = true;
                     return localOutputValue;
                 case 'IOAssertExpression':
@@ -2124,13 +2241,13 @@ function interpreter(ast, environment = null, initialState = {}) {
                 case 'IOListenExpression':
                     // Return current state from environment if available, otherwise placeholder
                     if (environment && typeof environment.getCurrentState === 'function') {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..listen called - returning state from environment');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..listen called - returning state from environment');
                         }
                         return environment.getCurrentState();
                     } else {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..listen called - returning placeholder state');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..listen called - returning placeholder state');
                         }
                         return { status: 'placeholder', message: 'State not available in standalone mode' };
                     }
@@ -2138,12 +2255,12 @@ function interpreter(ast, environment = null, initialState = {}) {
                     const localEmitValue = localEvalNodeWithScope(node.value, scope);
                     // Send value to environment if available, otherwise log to console
                     if (environment && typeof environment.emitValue === 'function') {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..emit called - sending to environment');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..emit called - sending to environment');
                         }
                         environment.emitValue(localEmitValue);
                     } else {
-                        console.log('[EMIT]', localEmitValue);
+                        safeConsoleLog('[EMIT]', localEmitValue);
                     }
                     ioOperationsPerformed = true;
                     return localEmitValue;
@@ -2428,22 +2545,18 @@ function interpreter(ast, environment = null, initialState = {}) {
                 case 'WildcardPattern':
                     return true;
                 case 'IOInExpression':
-                    const readline = require('readline');
-                    const rl = readline.createInterface({
-                        input: process.stdin,
-                        output: process.stdout
-                    });
+                    const rl3 = createReadline();
                     
                     return new Promise((resolve) => {
-                        rl.question('', (input) => {
-                            rl.close();
+                        rl3.question('', (input) => {
+                            rl3.close();
                             const num = parseInt(input);
                             resolve(isNaN(num) ? input : num);
                         });
                     });
                 case 'IOOutExpression':
                     const localOutputValue = localEvalNode(node.value);
-                    console.log(localOutputValue);
+                    safeConsoleLog(localOutputValue);
                     ioOperationsPerformed = true;
                     return localOutputValue;
                 case 'IOAssertExpression':
@@ -2455,13 +2568,13 @@ function interpreter(ast, environment = null, initialState = {}) {
                 case 'IOListenExpression':
                     // Return current state from environment if available, otherwise placeholder
                     if (environment && typeof environment.getCurrentState === 'function') {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..listen called - returning state from environment');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..listen called - returning state from environment');
                         }
                         return environment.getCurrentState();
                     } else {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..listen called - returning placeholder state');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..listen called - returning placeholder state');
                         }
                         return { status: 'placeholder', message: 'State not available in standalone mode' };
                     }
@@ -2469,12 +2582,12 @@ function interpreter(ast, environment = null, initialState = {}) {
                     const localEmitValue = localEvalNode(node.value);
                     // Send value to environment if available, otherwise log to console
                     if (environment && typeof environment.emitValue === 'function') {
-                        if (process.env.DEBUG) {
-                            console.log('[DEBUG] ..emit called - sending to environment');
+                        if (DEBUG) {
+                            safeConsoleLog('[DEBUG] ..emit called - sending to environment');
                         }
                         environment.emitValue(localEmitValue);
                     } else {
-                        console.log('[EMIT]', localEmitValue);
+                        safeConsoleLog('[EMIT]', localEmitValue);
                     }
                     ioOperationsPerformed = true;
                     return localEmitValue;
@@ -2586,10 +2699,10 @@ function run(scriptContent, initialState = {}, environment = null) {
  * expressions and function applications.
  */
 function debugLog(message, data = null) {
-    if (process.env.DEBUG) {
-        console.log(`[DEBUG] ${message}`);
+    if (DEBUG) {
+        safeConsoleLog(`[DEBUG] ${message}`);
         if (data) {
-            console.log(data);
+            safeConsoleLog(data);
         }
     }
 }
@@ -2613,10 +2726,10 @@ function debugLog(message, data = null) {
  * execution pipeline.
  */
 function debugError(message, error = null) {
-    if (process.env.DEBUG) {
-        console.error(`[DEBUG ERROR] ${message}`);
+    if (DEBUG) {
+        safeConsoleError(`[DEBUG ERROR] ${message}`);
         if (error) {
-            console.error(error);
+            safeConsoleError(error);
         }
     }
 }
@@ -2677,8 +2790,8 @@ const callStackTracker = {
             throw new Error(`Potential infinite recursion detected. Call stack depth: ${this.stack.length}`);
         }
         
-        if (process.env.DEBUG && this.stack.length % 100 === 0) {
-            console.log(`[DEBUG] Call stack depth: ${this.stack.length}, Max: ${this.maxDepth}`);
+        if (DEBUG && this.stack.length % 100 === 0) {
+            safeConsoleLog(`[DEBUG] Call stack depth: ${this.stack.length}, Max: ${this.maxDepth}`);
         }
     },
     
@@ -2738,22 +2851,18 @@ const callStackTracker = {
  * workflow where tests and examples are stored as .txt files.
  */
 async function readFile(filePath) {
-    // Check if we're in a browser environment
-    if (typeof window !== 'undefined') {
-        // Browser environment - would need to implement file input or fetch
-        throw new Error('File I/O not supported in browser environment');
-    }
+    // Use cross-platform filesystem
+    const fs = createFileSystem();
     
-    // Node.js or Bun environment
-    try {
-        // Try dynamic import for ES modules compatibility
-        const fs = await import('fs');
-        return fs.readFileSync(filePath, 'utf8');
-    } catch (error) {
-        // Fallback to require for older Node.js versions
-        const fs = require('fs');
-        return fs.readFileSync(filePath, 'utf8');
-    }
+    return new Promise((resolve, reject) => {
+        fs.readFile(filePath, 'utf8', (error, data) => {
+            if (error) {
+                reject(error);
+            } else {
+                resolve(data);
+            }
+        });
+    });
 }
 
 /**
@@ -2807,50 +2916,50 @@ async function executeFile(filePath) {
         if (result instanceof Promise) {
             result.then(finalResult => {
                 // Only output result if debug mode is enabled (no automatic final result output)
-                if (finalResult.result !== undefined && process.env.DEBUG) {
-                    console.log(finalResult.result);
+                if (finalResult.result !== undefined && DEBUG) {
+                    safeConsoleLog(finalResult.result);
                 }
                 // Print call stack statistics only in debug mode
-                if (process.env.DEBUG) {
+                if (DEBUG) {
                     const stats = callStackTracker.getStats();
-                    console.log('\n=== CALL STACK STATISTICS ===');
-                    console.log('Maximum call stack depth:', stats.maxDepth);
-                    console.log('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
+                    safeConsoleLog('\n=== CALL STACK STATISTICS ===');
+                    safeConsoleLog('Maximum call stack depth:', stats.maxDepth);
+                    safeConsoleLog('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
                 }
             }).catch(error => {
-                console.error(`Error executing file: ${error.message}`);
+                safeConsoleError(`Error executing file: ${error.message}`);
                 // Print call stack statistics on error only in debug mode
-                if (process.env.DEBUG) {
+                if (DEBUG) {
                     const stats = callStackTracker.getStats();
-                    console.error('\n=== CALL STACK STATISTICS ON ERROR ===');
-                    console.error('Maximum call stack depth:', stats.maxDepth);
-                    console.error('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
+                    safeConsoleError('\n=== CALL STACK STATISTICS ON ERROR ===');
+                    safeConsoleError('Maximum call stack depth:', stats.maxDepth);
+                    safeConsoleError('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
                 }
-                process.exit(1);
+                safeExit(1);
             });
         } else {
             // Only output result if debug mode is enabled (no automatic final result output)
-            if (result.result !== undefined && process.env.DEBUG) {
-                console.log(result.result);
+            if (result.result !== undefined && DEBUG) {
+                safeConsoleLog(result.result);
             }
             // Print call stack statistics only in debug mode
-            if (process.env.DEBUG) {
+            if (DEBUG) {
                 const stats = callStackTracker.getStats();
-                console.log('\n=== CALL STACK STATISTICS ===');
-                console.log('Maximum call stack depth:', stats.maxDepth);
-                console.log('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
+                safeConsoleLog('\n=== CALL STACK STATISTICS ===');
+                safeConsoleLog('Maximum call stack depth:', stats.maxDepth);
+                safeConsoleLog('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
             }
         }
     } catch (error) {
-        console.error(`Error executing file: ${error.message}`);
+        safeConsoleError(`Error executing file: ${error.message}`);
         // Print call stack statistics on error only in debug mode
-        if (process.env.DEBUG) {
+        if (DEBUG) {
             const stats = callStackTracker.getStats();
-            console.error('\n=== CALL STACK STATISTICS ON ERROR ===');
-            console.error('Maximum call stack depth:', stats.maxDepth);
-            console.error('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
+            safeConsoleError('\n=== CALL STACK STATISTICS ON ERROR ===');
+            safeConsoleError('Maximum call stack depth:', stats.maxDepth);
+            safeConsoleError('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
         }
-        process.exit(1);
+        safeExit(1);
     }
 }
 
@@ -2868,29 +2977,34 @@ async function executeFile(filePath) {
  * Exits with appropriate error codes for different failure scenarios.
  */
 async function main() {
+    // Only run main function in Node.js/Bun environments
+    if (!isNode && !isBun) {
+        return; // Skip in browser environment
+    }
+    
     const args = process.argv.slice(2);
 
     if (args.length === 0) {
-        console.error('Usage: node lang.js <file>');
-        console.error('  Provide a file path to execute');
-        process.exit(1);
+        safeConsoleError('Usage: node lang.js <file>');
+        safeConsoleError('  Provide a file path to execute');
+        safeExit(1);
     } else if (args.length === 1) {
         // Execute the file
         const filePath = args[0];
         await executeFile(filePath);
     } else {
         // Too many arguments
-        console.error('Usage: node lang.js <file>');
-        console.error('  Provide exactly one file path to execute');
-        process.exit(1);
+        safeConsoleError('Usage: node lang.js <file>');
+        safeConsoleError('  Provide exactly one file path to execute');
+        safeExit(1);
     }
 }
 
-// Start the program only if this file is run directly
-if (process.argv[1] && process.argv[1].endsWith('lang.js')) {
+// Start the program only if this file is run directly in Node.js/Bun
+if ((isNode || isBun) && process.argv[1] && process.argv[1].endsWith('lang.js')) {
     main().catch(error => {
-        console.error('Fatal error:', error.message);
-        process.exit(1);
+        safeConsoleError('Fatal error:', error.message);
+        safeExit(1);
     });
 }