about summary refs log tree commit diff stats
path: root/awk/vm/vm.awk
diff options
context:
space:
mode:
Diffstat (limited to 'awk/vm/vm.awk')
-rwxr-xr-xawk/vm/vm.awk254
1 files changed, 254 insertions, 0 deletions
diff --git a/awk/vm/vm.awk b/awk/vm/vm.awk
new file mode 100755
index 0000000..67da3e7
--- /dev/null
+++ b/awk/vm/vm.awk
@@ -0,0 +1,254 @@
+#!/usr/bin/awk -f
+
+
+# Stack: DROP, DUP, OVER, PUSH, POP
+# Math:	+ AND XOR NOT 2* 2/ multiply-step
+# Call:	JUMP CALL RETURN IF -IF
+# Loop:	NEXT UNEXT
+# Register:	A A! B!
+# Memory: @ ! @+ !+ @B !B @P !P
+# NO-OP: .
+
+
+BEGIN {
+    # Initialize VM state
+    stack_pointer = 0    # Points to next free position
+    pc = 0               # Program counter
+    MAX_STACK = 100      # Maximum stack size
+    MAX_MEM = 1000       # Memory size
+    
+    # Initialize registers
+    A = 0              # A register
+    B = 0              # B register
+    P = 0              # P register (auxiliary pointer)
+    
+    # Stack operations
+    split("", stack)   # Initialize stack array
+    split("", memory)  # Initialize memory array
+}
+
+# Stack operations
+function push(value) {
+    if (stack_pointer >= MAX_STACK) {
+        print "Stack overflow!" > "/dev/stderr"
+        exit 1
+    }
+    printf "# DEBUG: Pushing %d onto stack\n", value > "/dev/stderr"
+    stack[stack_pointer++] = value
+}
+
+function pop() {
+    if (stack_pointer <= 0) {
+        print "Stack underflow!" > "/dev/stderr"
+        exit 1
+    }
+    value = stack[--stack_pointer]
+    printf "# DEBUG: Popping %d from stack\n", value > "/dev/stderr"
+    return value
+}
+
+# Basic stack manipulation
+function op_drop() {
+    pop()
+}
+
+function op_dup() {
+    if (stack_pointer <= 0) {
+        print "Stack underflow on DUP!" > "/dev/stderr"
+        exit 1
+    }
+    push(stack[stack_pointer - 1])
+}
+
+function op_over() {
+    if (stack_pointer <= 1) {
+        print "Stack underflow on OVER!" > "/dev/stderr"
+        exit 1
+    }
+    push(stack[stack_pointer - 2])
+}
+
+# Basic arithmetic operations
+function op_add() {
+    b = pop()
+    a = pop()
+    result = a + b
+    printf "# DEBUG: Adding %d + %d = %d\n", a, b, result > "/dev/stderr"
+    push(result)
+}
+
+function op_and() {
+    b = pop()
+    a = pop()
+    # For now, we'll just multiply as a placeholder
+    # In a real implementation, we'd need to implement proper bitwise AND
+    push(a * b)
+}
+
+function op_xor() {
+    b = pop()
+    a = pop()
+    # For now, we'll just add as a placeholder
+    # In a real implementation, we'd need to implement proper bitwise XOR
+    push(a + b)
+}
+
+function op_not() {
+    a = pop()
+    # For now, we'll just negate as a placeholder
+    # In a real implementation, we'd need to implement proper bitwise NOT
+    push(-a - 1)
+}
+
+function op_2times() {
+    a = pop()
+    push(a * 2)
+}
+
+function op_2div() {
+    a = pop()
+    push(int(a / 2))
+}
+
+function op_multiply() {
+    b = pop()
+    a = pop()
+    result = a * b
+    printf "# DEBUG: Multiplying %d * %d = %d\n", a, b, result > "/dev/stderr"
+    push(result)
+}
+
+# Register operations
+function op_a() {
+    push(A)
+}
+
+function op_astore() {
+    A = pop()
+}
+
+function op_bstore() {
+    B = pop()
+}
+
+# Memory operations
+function op_fetch() {
+    addr = pop()
+    value = memory[addr]
+    printf "# DEBUG: Fetching %d from memory[%d]\n", value, addr > "/dev/stderr"
+    push(value)
+}
+
+function op_store() {
+    addr = pop()  # First pop the address
+    value = pop() # Then pop the value
+    printf "# DEBUG: Storing %d at memory[%d]\n", value, addr > "/dev/stderr"
+    memory[addr] = value
+}
+
+function op_fetchplus() {
+    push(memory[P++])
+}
+
+function op_storeplus() {
+    memory[P++] = pop()
+}
+
+function op_fetchb() {
+    push(memory[B])
+}
+
+function op_storeb() {
+    memory[B] = pop()
+}
+
+function op_fetchp() {
+    push(memory[P])
+}
+
+function op_storep() {
+    memory[P] = pop()
+}
+
+function print_stack() {
+    printf "Stack: "
+    for (i = 0; i < stack_pointer; i++) {
+        printf "%d ", stack[i]
+    }
+    printf "\n"
+}
+
+function print_state() {
+    print_stack()
+    printf "Registers: A=%d B=%d P=%d\n", A, B, P
+    printf "Memory[P]=%d Memory[B]=%d\n", memory[P], memory[B]
+    printf "Memory: "
+    for (i = 0; i < 4; i++) {  # Show first 4 memory locations
+        printf "[%d]=%d ", i, memory[i]
+    }
+    printf "\n-------------------\n"
+}
+
+function op_swap() {
+    if (stack_pointer < 2) {
+        print "Stack underflow on SWAP!" > "/dev/stderr"
+        exit 1
+    }
+    # Swap the top two elements on the stack
+    temp = stack[stack_pointer - 1]
+    stack[stack_pointer - 1] = stack[stack_pointer - 2]
+    stack[stack_pointer - 2] = temp
+    printf "# DEBUG: Swapping top two stack elements\n" > "/dev/stderr"
+}
+
+function execute_instruction(inst) {
+    if (inst ~ /^[0-9]+$/) {
+        # Numbers are pushed onto the stack
+        push(int(inst))
+        return
+    }
+    
+    if (inst == "BYE")      { exit 0 } # not really in the minimal spec as set out by Chuck Moore, but useful for a graceful exit.
+    if (inst == "DROP")     { op_drop(); return }
+    if (inst == "DUP")      { op_dup(); return }
+    if (inst == "OVER")     { op_over(); return } # copy second item to top of stack
+    if (inst == "SWAP")     { op_swap(); return } # swap top two stack items
+    if (inst == "+")        { op_add(); return }
+    if (inst == "AND")      { op_and(); return }
+    if (inst == "XOR")      { op_xor(); return }
+    if (inst == "NOT")      { op_not(); return }
+    if (inst == "2*")       { op_2times(); return } # multiply-step
+    if (inst == "2/")       { op_2div(); return } # divide-step
+    if (inst == "*")        { op_multiply(); return }
+    if (inst == "A")        { op_a(); return } # push A register
+    if (inst == "A!")       { op_astore(); return } # store A register
+    if (inst == "B!")       { op_bstore(); return } # store B register
+    if (inst == "@")        { op_fetch(); return } # fetch from memory
+    if (inst == "!")        { op_store(); return } # store to memory
+    if (inst == "@+")       { op_fetchplus(); return } # fetch from memory at P+
+    if (inst == "!+")       { op_storeplus(); return } # store to memory at P+
+    if (inst == "@B")       { op_fetchb(); return } # fetch from memory at B
+    if (inst == "!B")       { op_storeb(); return } # store to memory at B
+    if (inst == "@P")       { op_fetchp(); return } # fetch from memory at P
+    if (inst == "!P")       { op_storep(); return } # store to memory at P
+    if (inst == ".")        { return }  # NO-OP
+    if (inst == "SHOW")     { print_state(); return } # show state info
+    
+    print "Unknown instruction: " inst > "/dev/stderr"
+    exit 1
+}
+
+# Main execution loop
+{
+    # Remove comments (everything after #)
+    sub(/#.*$/, "")
+    
+    # Skip empty lines after comment removal
+    if (NF == 0) next
+    
+    # Split the input line into words
+    n = split($0, words)
+    for (i = 1; i <= n; i++) {
+        execute_instruction(words[i])
+    }
+}