diff options
Diffstat (limited to 'awk/forth/old/f.awk')
-rwxr-xr-x | awk/forth/old/f.awk | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/awk/forth/old/f.awk b/awk/forth/old/f.awk new file mode 100755 index 0000000..eed9774 --- /dev/null +++ b/awk/forth/old/f.awk @@ -0,0 +1,344 @@ +#!/usr/bin/awk -f + +# Forth interpreter in AWK + +BEGIN { + print "Welcome to the AWK Forth Interpreter!" + print "Type your commands below. Use 'bye' to quit." + # Initialize variables + top = -1 # Initialize stack pointer + + # Initialize the dictionary with basic words + words["+"] = "+" + words["-"] = "-" + words["*"] = "*" + words["/"] = "/" + words["dup"] = "dup" + words["over"] = "over" + words["swap"] = "swap" + words["."] = "." + words["bye"] = "bye" + words["rot"] = "rot" + words["drop"] = "drop" + words["nip"] = "nip" + words["tuck"] = "tuck" + words["roll"] = "roll" + words["pick"] = "pick" + words["negate"] = "negate" + words["abs"] = "abs" + words["max"] = "max" + words["min"] = "min" + words["mod"] = "mod" + words["="] = "=" + words["see"] = "see" + words["if"] = "if" + 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" + desc["-"] = "( n1 n2 -- diff ) Subtract top number from second" + desc["*"] = "( n1 n2 -- prod ) Multiply top two numbers" + desc["/"] = "( n1 n2 -- quot ) Divide second by top" + desc["dup"] = "( n -- n n ) Duplicate top of stack" + desc["over"] = "( n1 n2 -- n1 n2 n1 ) Copy second item to top" + desc["swap"] = "( n1 n2 -- n2 n1 ) Swap top two items" + desc["rot"] = "( n1 n2 n3 -- n2 n3 n1 ) Rotate top three items" + desc["drop"] = "( n -- ) Discard top item" + desc["nip"] = "( n1 n2 -- n2 ) Remove second item" + desc["tuck"] = "( n1 n2 -- n2 n1 n2 ) Copy top item below second" + desc["roll"] = "( nk ... n1 n0 k -- nk-1 ... n1 n0 nk ) Move kth item to top" + desc["pick"] = "( nk ... n1 n0 k -- nk ... n1 n0 nk ) Copy kth item to top" + desc["negate"] = "( n -- -n ) Negate number" + desc["abs"] = "( n -- |n| ) Absolute value" + desc["max"] = "( n1 n2 -- max ) Maximum of top two numbers" + desc["min"] = "( n1 n2 -- min ) Minimum of top two numbers" + desc["mod"] = "( n1 n2 -- rem ) Remainder of n1/n2" + desc["="] = "( n1 n2 -- flag ) Test if equal, leaves 1 if true, 0 if false" + desc["if"] = "( flag -- ) Begin conditional execution" + 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" + 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 + + # Mark these as compile-only words + compile_only["if"] = 1 + compile_only["then"] = 1 + compile_only["else"] = 1 +} + +# Stack operations +function push(value) { + stack[++top] = value +} + +function pop() { + if (top < 0) { + print "Error: Stack underflow" + return 0 + } + 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() + first = pop() + if (operation == "+") push(first + second) + else if (operation == "-") push(first - second) + else if (operation == "*") push(first * second) + else if (operation == "/") { + if (second == 0) { + print "Error: Division by zero" + push(first) + push(second) + return + } + push(first / second) + } + else if (operation == "mod") push(first % second) + else if (operation == "=") push(first == second ? 1 : 0) + else if (operation == "<") push(first < second ? 1 : 0) + else if (operation == ">") push(first > second ? 1 : 0) +} + +# Handler functions +function add() { binary_op("+") } +function subtract() { binary_op("-") } +function multiply() { binary_op("*") } +function divide() { binary_op("/") } +function mod() { binary_op("mod") } +function equals() { binary_op("=") } +function less_than() { binary_op("<") } +function greater_than() { binary_op(">") } + +function dup() { + if (!check_stack(1)) return + push(stack[top]) +} + +function over() { + if (!check_stack(2)) return + push(stack[top - 1]) +} + +function swap() { + if (!check_stack(2)) return + temp = pop() + second = pop() + push(temp) + push(second) +} + +function rot() { + if (!check_stack(3)) return + third = pop() + second = pop() + first = pop() + push(second) + push(third) + push(first) +} + +function drop() { + if (!check_stack(1)) return + top-- +} + +function nip() { + if (!check_stack(2)) return + temp = stack[top] + drop() + drop() + push(temp) +} + +function tuck() { + if (!check_stack(2)) return + temp = pop() + second = pop() + push(temp) + push(second) + push(temp) +} + +function roll() { + if (!check_stack(1)) return + n = int(pop()) + if (!check_stack(n)) return + if (n <= 0) return + + temp = stack[top - n + 1] + for (i = top - n + 1; i < top; i++) { + stack[i] = stack[i + 1] + } + stack[top] = temp +} + +function pick() { + if (!check_stack(1)) return + n = int(pop()) + if (!check_stack(n)) return + if (n < 0) return + push(stack[top - n]) +} + +function negate() { + if (!check_stack(1)) return + push(-pop()) +} + +function abs() { + if (!check_stack(1)) return + n = pop() + push(n < 0 ? -n : n) +} + +function max() { + if (!check_stack(2)) return + b = pop() + a = pop() + push(a > b ? a : b) +} + +function min() { + if (!check_stack(2)) return + b = pop() + a = pop() + push(a < b ? a : b) +} + +function print_top() { + if (!check_stack(1)) return + print stack[top] + drop() +} + +function bye() { + exit +} + +function see(word) { + if (!(word in words)) { + print "Error: Word '" word "' not found" + return + } + if (word in desc) { + print desc[word] + } + if (word in raw_definitions) { + print ": " word " " raw_definitions[word] " ;" + } +} + +# Main processing function +function execute_word(word) { + if (word in handlers) { + 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 (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 '" handler "' not implemented" + return 0 + } + return 1 + } + return 0 +} + +# Process each line of input +{ + if (NF > 0) { + # Remove comments and normalize whitespace + gsub(/\(.*\)/, "") + gsub(/^[[:space:]]+/, "") + gsub(/[[:space:]]+$/, "") + gsub(/[[:space:]]+/, " ") + + # Process each token + for (i = 1; i <= NF; i++) { + if ($i ~ /^-?[0-9]+$/) { + push($i) + } else if ($i in words) { + if (!execute_word($i)) { + print "Error: Failed to execute word '" $i "'" + } + } else { + print "Error: Unknown word '" $i "'" + } + } + } +} \ No newline at end of file |