about summary refs log tree commit diff stats
path: root/awk/forth/f.awk
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2025-01-09 16:57:05 -0500
committerelioat <elioat@tilde.institute>2025-01-09 16:57:05 -0500
commit662c3ceae2a4ffc598a8b99690a0cfdc0b4f47a8 (patch)
tree22c03fefb86b314341fbea70afaa95d91c7e7bbe /awk/forth/f.awk
parentb9440ce32de013237d61d2cccab229537ba19caa (diff)
downloadtour-662c3ceae2a4ffc598a8b99690a0cfdc0b4f47a8.tar.gz
*
Diffstat (limited to 'awk/forth/f.awk')
-rwxr-xr-xawk/forth/f.awk449
1 files changed, 100 insertions, 349 deletions
diff --git a/awk/forth/f.awk b/awk/forth/f.awk
index 23bc9f0..eed9774 100755
--- a/awk/forth/f.awk
+++ b/awk/forth/f.awk
@@ -35,6 +35,36 @@ BEGIN {
     words["then"] = "then"
     words["else"] = "else"
     words[">"] = ">"
+    words["<"] = "<"
+    
+    # Add handlers for all words
+    handlers["+"] = "add"
+    handlers["-"] = "subtract"
+    handlers["*"] = "multiply"
+    handlers["/"] = "divide"
+    handlers["dup"] = "dup"
+    handlers["over"] = "over"
+    handlers["swap"] = "swap"
+    handlers["."] = "print_top"
+    handlers["<"] = "less_than"
+    handlers[">"] = "greater_than"
+    handlers["rot"] = "rot"
+    handlers["drop"] = "drop"
+    handlers["nip"] = "nip"
+    handlers["tuck"] = "tuck"
+    handlers["roll"] = "roll"
+    handlers["pick"] = "pick"
+    handlers["negate"] = "negate"
+    handlers["abs"] = "abs"
+    handlers["max"] = "max"
+    handlers["min"] = "min"
+    handlers["mod"] = "mod"
+    handlers["="] = "equals"
+    handlers["if"] = "handle_if"
+    handlers["then"] = "handle_then"
+    handlers["else"] = "handle_else"
+    handlers["bye"] = "bye"
+    handlers["see"] = "see"
 
     # Add descriptions for words
     desc["+"] = "( n1 n2 -- sum ) Add top two numbers"
@@ -60,24 +90,9 @@ BEGIN {
     desc["then"] = "( -- ) End conditional execution"
     desc["else"] = "( -- ) Execute if previous condition was false"
     desc[">"] = "( n1 n2 -- flag ) Returns true if n1 is greater than n2"
-
-    # Add variable-related words to dictionary
-    words["variable"] = "variable"
-    words["!"] = "!"
-    words["@"] = "@"
-    words["?"] = "?"
-
-    # Add descriptions for the new words
-    desc["variable"] = "( -- addr ) Create a variable"
-    desc["!"] = "( n addr -- ) Store n at addr"
-    desc["@"] = "( addr -- n ) Fetch contents of addr"
-    desc["?"] = "( addr -- ) Print contents of addr"
-
-    # Initialize test-related words
-    words["test"] = "test"
-    words["testing"] = "testing"
-    desc["test"] = "( n1 n2 -- ) Compare values and report test result"
-    desc["testing"] = "( -- ) Print test description"
+    desc["<"] = "( n1 n2 -- flag ) Returns true if n1 is less than n2"
+    desc["bye"] = "( -- ) Exit the interpreter"
+    desc["see"] = "( -- ) Show definition of a word"
 
     # Initialize condition stack
     cond_top = -1
@@ -86,127 +101,9 @@ BEGIN {
     compile_only["if"] = 1
     compile_only["then"] = 1
     compile_only["else"] = 1
-
-    # Add dot-quote to dictionary
-    words[".\""] = ".\""
-    desc[".\""] = "( -- ) Print following string up to closing quote"
-
-    # Handle file input
-    if (ARGC > 1) {
-        print "Loading file:", ARGV[1]
-        while ((getline < ARGV[1]) > 0) {
-            if ($0 ~ /^[[:space:]]*$/) continue  # Skip empty lines
-            print "> " $0
-            process_line()
-        }
-        close(ARGV[1])
-        exit
-    }
-
-    # Add to dictionary initialization
-    words["<"] = "<"
-    words[">"] = ">"
-    
-    # Add descriptions
-    desc["<"] = "( n1 n2 -- flag ) Returns true if n1 is less than n2"
-    desc[">"] = "( n1 n2 -- flag ) Returns true if n1 is greater than n2"
-
-    # Add handlers
-    handlers["+" ] = "add"
-    handlers["-" ] = "subtract"
-    handlers["*" ] = "multiply"
-    handlers["/" ] = "divide"
-    handlers["dup"] = "dup"
-    handlers["over"] = "over"
-    handlers["swap"] = "swap"
-    handlers["."] = "print_top"
-    handlers["<"] = "less_than"
-    handlers[">"] = "greater_than"
-
-    # Add variable handler
-    handlers["variable"] = "create_variable"
-    handlers["!"] = "store"
-    handlers["@"] = "fetch"
-    handlers["?"] = "print_var"
-}
-
-# Add these helper functions near the top
-function check_stack(min_items, error_msg) {
-    if (top < min_items - 1) {
-        print error_msg ? error_msg : "Error: Not enough values on stack"
-        return 0
-    }
-    return 1
-}
-
-function check_underflow() {
-    return check_stack(1, "Error: Stack underflow")
-}
-
-# Function to define a new word
-function define_word(name, definition) {
-    # Store the raw definition
-    raw_definitions[name] = definition
-    print "DEBUG: Raw definition for " name ": " definition
-    
-    # Process the definition to handle conditionals
-    processed = process_definition(definition)
-    print "DEBUG: Processed definition for " name ": " processed
-    words[name] = processed
-}
-
-function process_definition(definition) {
-    # Normalize whitespace in definition
-    gsub(/^[[:space:]]+/, "", definition)
-    gsub(/[[:space:]]+$/, "", definition)
-    gsub(/[[:space:]]+/, " ", definition)
-    
-    # Split definition into words
-    split(definition, def_words, " ")
-    processed = ""
-    in_string = 0
-    string_content = ""
-    
-    for (i = 1; i <= length(def_words); i++) {
-        word = def_words[i]
-        
-        if (word == ".\"") {
-            # Start collecting string
-            in_string = 1
-            string_content = ""
-            continue
-        }
-        
-        if (in_string) {
-            # Check if this word contains the closing quote
-            if (word ~ /"$/) {
-                # End of string found
-                string_content = string_content (string_content == "" ? "" : " ") substr(word, 1, length(word)-1)
-                processed = processed " <string>" string_content "</string>"
-                in_string = 0
-            } else {
-                # Add to string content
-                string_content = string_content (string_content == "" ? "" : " ") word
-            }
-            continue
-        }
-        
-        # Handle non-string words
-        if (word == "if") {
-            processed = processed " <if>"
-        } else if (word == "else") {
-            processed = processed " <else>"
-        } else if (word == "then") {
-            processed = processed " <then>"
-        } else {
-            processed = processed " " word
-        }
-    }
-    
-    return processed
 }
 
-# Stack to hold values
+# Stack operations
 function push(value) {
     stack[++top] = value
 }
@@ -219,6 +116,15 @@ function pop() {
     return stack[top--]
 }
 
+function check_stack(min_items, error_msg) {
+    if (top < min_items - 1) {
+        print error_msg ? error_msg : "Error: Not enough values on stack"
+        return 0
+    }
+    return 1
+}
+
+# Binary operations
 function binary_op(operation) {
     if (!check_stack(2)) return
     second = pop()
@@ -241,7 +147,7 @@ function binary_op(operation) {
     else if (operation == ">") push(first > second ? 1 : 0)
 }
 
-# Then simplify the operation functions:
+# Handler functions
 function add() { binary_op("+") }
 function subtract() { binary_op("-") }
 function multiply() { binary_op("*") }
@@ -251,19 +157,16 @@ function equals() { binary_op("=") }
 function less_than() { binary_op("<") }
 function greater_than() { binary_op(">") }
 
-# Function to duplicate the top value
 function dup() {
     if (!check_stack(1)) return
     push(stack[top])
 }
 
-# Function to copy the second value to the top
 function over() {
     if (!check_stack(2)) return
     push(stack[top - 1])
 }
 
-# Function to swap the top two values
 function swap() {
     if (!check_stack(2)) return
     temp = pop()
@@ -272,19 +175,6 @@ function swap() {
     push(second)
 }
 
-function print_top() {
-    if (!check_stack(1)) return
-    print stack[top]
-}
-
-# Function to list all available words
-function list_words() {
-    print "Available words:"
-    for (word in words) {
-        print word
-    }
-}
-
 function rot() {
     if (!check_stack(3)) return
     third = pop()
@@ -363,147 +253,65 @@ function min() {
     push(a < b ? a : b)
 }
 
-function see(word) {
-    if (word in desc) {
-        print desc[word]
-    } else if (word in words) {
-        print ": " word " " words[word] " ;"
-    } else {
-        print "Word '" word "' not found"
-    }
-}
-
-# Add these new functions for variable handling:
-
-# Function to create a new variable
-function create_variable(name) {
-    if (name == "") {
-        print "Error: Variable name required"
-        return
-    }
-    variables[name] = 0  # Initialize variable to 0
-    # No need to push the variable name onto the stack
-}
-
-# Function to store a value in a variable
-function check_variable(addr, error_msg) {
-    if (!(addr in variables)) {
-        print error_msg ? error_msg : "Error: Invalid variable '" addr "'"
-        return 0
-    }
-    return 1
-}
-
-function store() {
-    if (!check_stack(2)) return
-    addr = pop()
-    if (!check_variable(addr)) return
-    variables[addr] = pop()
-}
-
-# Function to fetch a value from a variable
-function fetch() {
+function print_top() {
     if (!check_stack(1)) return
-    addr = pop()
-    if (!check_variable(addr)) return
-    push(variables[addr])
-}
-
-# Function to print a variable's value
-function print_var() {
-    if (top < 0) {
-        print "Error: Stack underflow"
-        return
-    }
-    addr = pop()
-    if (!(addr in variables)) {
-        print "Error: Invalid variable '" addr "'"
-        return
-    }
-    print variables[addr]
+    print stack[top]
+    drop()
 }
 
-# Add these test-related functions:
-function run_test(expected) {
-    if (top < 0) {
-        print "❌ FAIL: Stack is empty"
-        return
-    }
-    actual = pop()
-    if (actual == expected) {
-        print "✓ PASS"
-    } else {
-        print "❌ FAIL: Expected", expected, "but got", actual
-    }
+function bye() {
+    exit
 }
 
-function print_test_description() {
-    if (NF < 2) {
-        print "Error: testing requires a description"
-        return
-    }
-    # Collect all words after 'testing' as the description
-    test_desc = ""
-    for (i = 2; i <= NF; i++) {
-        test_desc = test_desc " " $i
-    }
-    print "\nTesting:" test_desc
-}
-
-# Add these new functions for conditional handling:
-
-# Function to handle if statement
-function handle_if() {
-    if (top < 0) {
-        print "Error: Stack underflow"
+function see(word) {
+    if (!(word in words)) {
+        print "Error: Word '" word "' not found"
         return
     }
-    # Save condition without consuming it
-    cond_stack[++cond_top] = (stack[top] != 0)
-}
-
-# Function to handle then statement
-function handle_then() {
-    if (cond_top < 0) {
-        print "Error: Unmatched then"
-        return
+    if (word in desc) {
+        print desc[word]
     }
-    cond_top--  # Pop condition
-}
-
-# Function to handle else statement
-function handle_else() {
-    if (cond_top < 0) {
-        print "Error: Unmatched else"
-        return
+    if (word in raw_definitions) {
+        print ": " word " " raw_definitions[word] " ;"
     }
-    cond_stack[cond_top] = !cond_stack[cond_top]
 }
 
-# Add this function
+# Main processing function
 function execute_word(word) {
     if (word in handlers) {
-        if (handlers[word] == "add") add()
-        else if (handlers[word] == "subtract") subtract()
-        else if (handlers[word] == "multiply") multiply()
-        else if (handlers[word] == "divide") divide()
-        else if (handlers[word] == "dup") dup()
-        else if (handlers[word] == "over") over()
-        else if (handlers[word] == "swap") swap()
-        else if (handlers[word] == "print_top") print_top()
-        else if (handlers[word] == "create_variable") {
-            # Special handling for variable creation
-            if (i + 1 <= NF) {
-                create_variable($(++i))
-            } else {
-                print "Error: variable requires a name"
-            }
+        handler = handlers[word]
+        if (handler == "bye") exit
+        else if (handler == "see") {
+            if (i + 1 <= NF) see($(++i))
+            else print "Error: see requires a word name"
         }
-        else if (handlers[word] == "store") store()
-        else if (handlers[word] == "fetch") fetch()
-        else if (handlers[word] == "print_var") print_var()
+        else if (handler == "add") add()
+        else if (handler == "subtract") subtract()
+        else if (handler == "multiply") multiply()
+        else if (handler == "divide") divide()
+        else if (handler == "dup") dup()
+        else if (handler == "over") over()
+        else if (handler == "swap") swap()
+        else if (handler == "print_top") print_top()
+        else if (handler == "less_than") less_than()
+        else if (handler == "greater_than") greater_than()
+        else if (handler == "rot") rot()
+        else if (handler == "drop") drop()
+        else if (handler == "nip") nip()
+        else if (handler == "tuck") tuck()
+        else if (handler == "roll") roll()
+        else if (handler == "pick") pick()
+        else if (handler == "negate") negate()
+        else if (handler == "abs") abs()
+        else if (handler == "max") max()
+        else if (handler == "min") min()
+        else if (handler == "mod") mod()
+        else if (handler == "equals") equals()
+        else if (handler == "handle_if") handle_if()
+        else if (handler == "handle_then") handle_then()
+        else if (handler == "handle_else") handle_else()
         else {
-            print "Error: Handler '" handlers[word] "' not implemented"
+            print "Error: Handler '" handler "' not implemented"
             return 0
         }
         return 1
@@ -511,83 +319,26 @@ function execute_word(word) {
     return 0
 }
 
-# Move the main command processing into a function
-function process_line() {
-    # Process input only if it's not empty
+# Process each line of input
+{
     if (NF > 0) {
         # Remove comments and normalize whitespace
-        gsub(/\(.*\)/, "")  # Remove everything from ( to )
-        gsub(/^[[:space:]]+/, "")  # Remove leading whitespace
-        gsub(/[[:space:]]+$/, "")  # Remove trailing whitespace
-        gsub(/[[:space:]]+/, " ")  # Normalize internal whitespace
+        gsub(/\(.*\)/, "")
+        gsub(/^[[:space:]]+/, "")
+        gsub(/[[:space:]]+$/, "")
+        gsub(/[[:space:]]+/, " ")
 
-        # Special handling for testing command
-        if ($1 == "testing") {
-            # Collect the description string
-            if ($2 ~ /^".*"$/) {  # Check if the second token is a quoted string
-                test_desc = substr($2, 2, length($2) - 2)  # Remove quotes
-                print "\nTesting: " test_desc
-            } else {
-                print "Error: testing requires a description in quotes"
-            }
-            return
-        }
-
-        # Check for word definitions
-        if ($1 == ":") {
-            word_name = $2
-            definition = ""
-            in_definition = 1
-            # Remove : and word name from the input
-            for (i = 3; i <= NF; i++) {
-                definition = definition " " $i
-            }
-            # If we don't find a semicolon, keep reading lines
-            while (definition !~ /;$/) {  # Changed to match semicolon at end
-                if ((getline) <= 0) break
-                gsub(/\(.*\)/, "")  # Remove comments
-                gsub(/^[[:space:]]+/, "")
-                gsub(/[[:space:]]+$/, "")
-                definition = definition " " $0
-            }
-            # Remove the semicolon
-            sub(/[[:space:]]*;[[:space:]]*$/, "", definition)
-            
-            if (definition != "") {
-                define_word(word_name, definition)
-                print "Defined new word: " word_name
-            }
-            in_definition = 0
-            return
-        }
-
-        # Process remaining input
+        # Process each token
         for (i = 1; i <= NF; i++) {
             if ($i ~ /^-?[0-9]+$/) {
                 push($i)
-            } else if ($i in variables) {  # Check if it's a variable
-                push(variables[$i])  # Push the value of the variable onto the stack
-            } else if ($i in words) {  # Check if it's a defined word
-                if (!in_definition && compile_only[$i]) {
-                    print "Error: '" $i "' is compile-only"
-                    return
-                }
+            } else if ($i in words) {
                 if (!execute_word($i)) {
-                    print "Error: Unknown command '" $i "'"
+                    print "Error: Failed to execute word '" $i "'"
                 }
-            } else if ($i != "") {  # Ignore empty tokens
-                print "Error: Unknown command '" $i "'"
+            } else {
+                print "Error: Unknown word '" $i "'"
             }
         }
     }
-}
-
-# Main loop to read commands (for interactive mode)
-{
-    process_line()
-}
-
-# Add function to handle dot-quote
-function print_string(str) {
-    printf "%s", str
-}
+}
\ No newline at end of file