about summary refs log tree commit diff stats
path: root/forth
diff options
context:
space:
mode:
Diffstat (limited to 'forth')
-rw-r--r--forth/foreforthfourth/README.md108
-rw-r--r--forth/foreforthfourth/forth.js177
2 files changed, 213 insertions, 72 deletions
diff --git a/forth/foreforthfourth/README.md b/forth/foreforthfourth/README.md
index 3e8579b..29c3b5e 100644
--- a/forth/foreforthfourth/README.md
+++ b/forth/foreforthfourth/README.md
@@ -25,9 +25,10 @@ This Forth interpreter features **4 separate stacks** that users can juggle betw
 
 ### Multi-Stack Operations
 - **Stack Focus System**: `focus.red`, `focus.teal`, `focus.blue`, `focus.yellow` (or `focus.1`, `focus.2`, `focus.3`, `focus.4`)
-- **Push Operations**: `push.red`, `push.teal`, `push.blue`, `push.yellow` (or `push.1`, `push.2`, `push.3`, `push.4`)
+- **Move Operations**: `move.red`, `move.teal`, `move.blue`, `move.yellow` (or `move.1`, `move.2`, `move.3`, `move.4`)
 - **Pop Operations**: `pop.red`, `pop.teal`, `pop.blue`, `pop.yellow` (or `pop.1`, `pop.2`, `pop.3`, `pop.4`)
-- **Move Operations**: `move` (interactive stack-to-stack movement), `push.red`, `push.teal`, `push.blue`, `push.yellow` (or `push.1`, `push.2`, `push.3`, `push.4`)
+- **Copy Operations**: `copy.red`, `copy.teal`, `copy.blue`, `copy.yellow` (or `copy.1`, `copy.2`, `copy.3`, `copy.4`)
+- **Move Operations**: `move` (interactive stack-to-stack movement), `move.red`, `move.teal`, `move.blue`, `move.yellow` (or `move.1`, `move.2`, `move.3`, `move.4`)
 - **Clear Operations**: `clear.all` (clear all stacks), `clear.focused` (clear focused stack)
 - **Cross-Stack Operations**: `dup.stacks`, `over.stacks`, `swap.stacks`, `nip.stacks`, `tuck.stacks`, `rot.stacks`, `2dup.stacks`, `2over.stacks`, `2swap.stacks`
 
@@ -98,8 +99,8 @@ dup over          # Duplicate top, copy second over top
 ### Multi-Stack Juggling
 ```forth
 5 3 2             # Push to red stack
-push.teal         # Move top of red to teal stack
-push.blue         # Move top of red to blue stack
+move.teal         # Move top of red to teal stack
+move.blue         # Move top of red to blue stack
 ```
 
 ### Stack Focus System
@@ -130,11 +131,17 @@ focus.2            # Same as focus.teal
 focus.3            # Same as focus.blue
 focus.4            # Same as focus.yellow
 
-# Push commands
-push.1             # Same as push.red
-push.2             # Same as push.teal
-push.3             # Same as push.blue
-push.4             # Same as push.yellow
+# Move commands
+move.1             # Same as move.red
+move.2             # Same as move.teal
+move.3             # Same as move.blue
+move.4             # Same as move.yellow
+
+# Copy commands
+copy.1             # Same as copy.red
+copy.2             # Same as copy.teal
+copy.3             # Same as copy.blue
+copy.4             # Same as copy.yellow
 
 # Pop commands
 pop.1              # Same as pop.red
@@ -258,36 +265,47 @@ move    # Start move operation
 3. Enter the **destination stack number** (1-4)
 4. The item is **removed** from source and **added** to destination
 
-#### **Push Commands with Focus System**
-Use `push.` commands to move items from the focused stack to a specific target stack:
+#### **Move Commands with Focus System**
+Use `move.` commands to move items from the focused stack to a specific target stack:
 
 ```forth
 focus.red         # Focus on Red stack (1)
 42                # Add item to Red stack
-push.3            # Move top item to Blue stack (3)
+move.3            # Move top item to Blue stack (3)
 # Result: 42 moved from Red to Blue stack
 
 focus.teal        # Focus on Teal stack (2)
 100               # Add item to Teal stack
-push.yellow       # Move top item to Yellow stack (4)
+move.yellow       # Move top item to Yellow stack (4)
 # Result: 100 moved from Teal to Yellow stack
 ```
 
 #### **Number and Color Aliases**
-All push commands support both number and color naming:
+All move and copy commands support both number and color naming:
 
 ```forth
-# Number aliases
-push.1            # Move to Red stack (1)
-push.2            # Move to Teal stack (2)
-push.3            # Move to Blue stack (3)
-push.4            # Move to Yellow stack (4)
+# Move commands (remove from source)
+move.1            # Move to Red stack (1)
+move.2            # Move to Teal stack (2)
+move.3            # Move to Blue stack (3)
+move.4            # Move to Yellow stack (4)
+
+# Copy commands (keep in source)
+copy.1            # Copy to Red stack (1)
+copy.2            # Copy to Teal stack (2)
+copy.3            # Copy to Blue stack (3)
+copy.4            # Copy to Yellow stack (4)
 
 # Color aliases
-push.red          # Move to Red stack (1)
-push.teal         # Move to Teal stack (2)
-push.blue         # Move to Blue stack (3)
-push.yellow       # Move to Yellow stack (4)
+move.red          # Move to Red stack (1)
+move.teal         # Move to Teal stack (2)
+move.blue         # Move to Blue stack (3)
+move.yellow       # Move to Yellow stack (4)
+
+copy.red          # Copy to Red stack (1)
+copy.teal         # Copy to Teal stack (2)
+copy.blue         # Copy to Blue stack (3)
+copy.yellow       # Copy to Yellow stack (4)
 ```
 
 #### **Comparison: Move vs Copy Operations**
@@ -295,19 +313,24 @@ push.yellow       # Move to Yellow stack (4)
 | Operation | Effect | Duplication | Use Case |
 |-----------|--------|-------------|----------|
 | `move` | **Moves** item from source to destination | ❌ No | Relocate items between stacks |
-| `push.` | **Moves** item from focused stack to target | ❌ No | Move from focused stack to specific stack |
+| `move.{stack}` | **Moves** item from focused stack to target | ❌ No | Move from focused stack to specific stack |
+| `copy.{stack}` | **Copies** item from focused stack to target | ✅ Yes | Keep item on source, copy to target |
 | `dup.stacks` | **Copies** item from focused stack to target | ✅ Yes | Keep item on source, copy to target |
 | `over.stacks` | **Copies** second item from focused stack to target | ✅ Yes | Copy second item without affecting top |
 
-#### **Quick Reference: All Move Operations**
+#### **Quick Reference: All Move and Copy Operations**
 
 | Command | From | To | Effect |
 |---------|------|----|---------|
 | `move` + source + dest | Any stack | Any stack | Move top item between specified stacks |
-| `push.red` / `push.1` | Focused stack | Red stack (1) | Move top item to Red stack |
-| `push.teal` / `push.2` | Focused stack | Teal stack (2) | Move top item to Teal stack |
-| `push.blue` / `push.3` | Focused stack | Blue stack (3) | Move top item to Blue stack |
-| `push.yellow` / `push.4` | Focused stack | Yellow stack (4) | Move top item to Yellow stack |
+| `move.red` / `move.1` | Focused stack | Red stack (1) | Move top item to Red stack |
+| `move.teal` / `move.2` | Focused stack | Teal stack (2) | Move top item to Teal stack |
+| `move.blue` / `move.3` | Focused stack | Blue stack (3) | Move top item to Blue stack |
+| `move.yellow` / `move.4` | Focused stack | Yellow stack (4) | Move top item to Yellow stack |
+| `copy.red` / `copy.1` | Focused stack | Red stack (1) | Copy top item to Red stack |
+| `copy.teal` / `copy.2` | Focused stack | Teal stack (2) | Copy top item to Teal stack |
+| `copy.blue` / `copy.3` | Focused stack | Blue stack (3) | Copy top item to Blue stack |
+| `copy.yellow` / `copy.4` | Focused stack | Yellow stack (4) | Copy top item to Yellow stack |
 
 #### **Complete Move Example**
 ```forth
@@ -321,11 +344,11 @@ focus.blue
 
 # Move items between stacks
 focus.red
-push.2            # Move 42 from Red to Teal
+move.2            # Move 42 from Red to Teal
 # Red stack: [], Teal stack: [100, 42]
 
 focus.teal
-push.3            # Move 100 from Teal to Blue
+move.3            # Move 100 from Teal to Blue
 # Teal stack: [42], Blue stack: [200, 100]
 
 # Use interactive move for complex operations
@@ -376,7 +399,7 @@ words             # List all available words
 
 ## Current Status
 
-### ✅ **Fully Implemented Features**
+### **Fully Implemented Features**
 - **Control Flow**: `IF ... THEN`, `IF ... ELSE ... THEN`, `BEGIN ... UNTIL` constructs
 - **String Operations**: String literals (`."` and `s"`), manipulation (`strlen`, `strcat`, `char+`, `type`, `count`)
 - **Stack Focus System**: Operate on any of the 4 stacks using focus commands
@@ -384,25 +407,14 @@ words             # List all available words
 - **Help System**: Comprehensive help (`help`) and word documentation (`doc`)
 - **Multi-Stack Operations**: Full support for all 4 stacks with focus system
 - **Enhanced Clear Operations**: `clear.all` and `clear.focused` commands
-- **Move Operations**: Interactive `move` command and `push.` commands for moving items between stacks
-- **Number Aliases**: All focus, push, and pop commands support both color names and numbers (1-4)
+- **Move Operations**: Interactive `move` command and `move.{stack}` commands for moving items between stacks
+- **Copy Operations**: `copy.{stack}` commands for copying items between stacks without removal
+- **Number Aliases**: All focus, move, copy, and pop commands support both color names and numbers (1-4)
 - **Math Utilities**: `abs`, `negate`, `min`, `max` operations
 
-### 🚀 **Advanced Capabilities**
+### **Advanced Capabilities**
 - **Universal Stack Operations**: All built-in words work on any focused stack
 - **Dual Naming System**: Both color names and numbers work for all commands
 - **Professional Error Handling**: Context-aware error messages with solutions
 - **Visual Focus Indicators**: UI shows which stack is currently focused
-- **Complete Test Coverage**: 100% test coverage of all features
-
-### Potential Extensions
-- **Graphics**: Simple drawing operations
-- **Networking**: HTTP requests and responses
-- **Persistence**: Save state between sessions
-- **Modules**: Import/export word definitions
-
-## Known Issues
-
-- The `move` operation requires two separate command inputs
-- Some edge cases in error handling may need refinement
-- Performance optimization for large programs
+- **Complete Test Coverage**: 100% test coverage of all features
\ No newline at end of file
diff --git a/forth/foreforthfourth/forth.js b/forth/foreforthfourth/forth.js
index 3a654d1..af133ea 100644
--- a/forth/foreforthfourth/forth.js
+++ b/forth/foreforthfourth/forth.js
@@ -933,11 +933,11 @@ const builtinWords = {
     },
 
     // Multi-stack operations
-    'push.red': {
+    'move.red': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.red - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.red - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -945,15 +945,15 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 0, value)
             });
         },
-        doc: 'Move top item from focused stack to red stack',
+        doc: 'Move top item from focused stack to red stack (removes from focused stack)',
         stack: '( x -- )'
     },
 
-    'push.1': {
+    'move.1': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.1 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.1 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -961,15 +961,15 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 0, value)
             });
         },
-        doc: 'Move top item from focused stack to red stack (Stack 1)',
+        doc: 'Move top item from focused stack to red stack (Stack 1) (removes from focused stack)',
         stack: '( x -- )'
     },
 
-    'push.teal': {
+    'move.teal': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.teal - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.teal - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -977,15 +977,15 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 1, value)
             });
         },
-        doc: 'Move top item from focused stack to teal stack',
+        doc: 'Move top item from focused stack to teal stack (removes from focused stack)',
         stack: '( x -- )'
     },
 
-    'push.2': {
+    'move.2': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.2 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.2 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -993,15 +993,15 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 1, value)
             });
         },
-        doc: 'Move top item from focused stack to teal stack (Stack 2)',
+        doc: 'Move top item from focused stack to teal stack (Stack 2) (removes from focused stack)',
         stack: '( x -- )'
     },
 
-    'push.blue': {
+    'move.blue': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.blue - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.blue - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -1009,15 +1009,15 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 2, value)
             });
         },
-        doc: 'Move top item from focused stack to blue stack',
+        doc: 'Move top item from focused stack to blue stack (removes from focused stack)',
         stack: '( x -- )'
     },
 
-    'push.3': {
+    'move.3': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.3 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.3 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -1025,15 +1025,15 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 2, value)
             });
         },
-        doc: 'Move top item from focused stack to blue stack (Stack 3)',
+        doc: 'Move top item from focused stack to blue stack (Stack 3) (removes from focused stack)',
         stack: '( x -- )'
     },
 
-    'push.yellow': {
+    'move.yellow': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.yellow - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.yellow - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -1041,15 +1041,15 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 3, value)
             });
         },
-        doc: 'Move top item from focused stack to yellow stack',
+        doc: 'Move top item from focused stack to yellow stack (removes from focused stack)',
         stack: '( x -- )'
     },
 
-    'push.4': {
+    'move.4': {
         fn: (state) => {
             if (state.stacks[state.focusedStack].length === 0) {
                 return updateState(state, { 
-                    output: [...state.output, `Error: Stack underflow on push.4 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
+                    output: [...state.output, `Error: Stack underflow on move.4 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to move.`] 
                 });
             }
             const { stacks, value } = popFromStack(state.stacks, state.focusedStack);
@@ -1057,10 +1057,139 @@ const builtinWords = {
                 stacks: pushToStack(stacks, 3, value)
             });
         },
-        doc: 'Move top item from focused stack to yellow stack (Stack 4)',
+        doc: 'Move top item from focused stack to yellow stack (Stack 4) (removes from focused stack)',
         stack: '( x -- )'
     },
 
+    // Copy operations (keep item in source stack)
+    'copy.red': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.red - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 0, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to red stack (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
+    'copy.1': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.1 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 0, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to red stack (Stack 1) (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
+    'copy.teal': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.teal - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 1, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to teal stack (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
+    'copy.2': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.2 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 1, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to teal stack (Stack 2) (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
+    'copy.blue': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.blue - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 2, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to blue stack (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
+    'copy.3': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.3 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 2, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to blue stack (Stack 3) (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
+    'copy.yellow': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.yellow - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 3, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to yellow stack (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
+    'copy.4': {
+        fn: (state) => {
+            if (state.stacks[state.focusedStack].length === 0) {
+                return updateState(state, { 
+                    output: [...state.output, `Error: Stack underflow on copy.4 - ${getFocusedStackName(state.focusedStack)} is empty. Nothing to copy.`] 
+                });
+            }
+            const top = state.stacks[state.focusedStack][state.stacks[state.focusedStack].length - 1];
+            return updateState(state, {
+                stacks: pushToStack(state.stacks, 3, top)
+            });
+        },
+        doc: 'Copy top item from focused stack to yellow stack (Stack 4) (keeps item on focused stack)',
+        stack: '( x -- x )'
+    },
+
     'pop.red': {
         fn: (state) => popAndPrint(state, 0),
         doc: 'Pop and print top item from red stack',