2
\$\begingroup\$

I am attempting to learn the Nim language by making a small and simplistic register machine. It is intended to interpret some basic instructions.

The entire parsing lexing process consists of splitting the inputted code by spaces (not whitespace in general), which newlines are counted as. Is this reasonable code style in Nim?

The code reads a file name containing the instructions from stdin and then executes those instructions on the seq.

I am a beginner at programming in general, not just Nim. Also, my very basic knowledge of Turing completeness suggests that it might be Turing complete. Is that so?

The instructions are as follows:

  • set+ ADDRESS: int, VALUE: int, which sets the value of ADDRESS to the previous value of ADDRESS plus the value.

  • set- ADDRESS: int, VALUE: int, which sets the value of ADDRESS to the previous value of ADDRESS minus the value.

  • mul ADDRESS1: int, ADDRESS2: int ADDRESS3: int, which sets ADDRESS3's value to ADDRESS1's * ADDRESS2's

  • add ADDRESS1: int, ADDRESS2: int ADDRESS3: int, which sets ADDRESS3's value to ADDRESS1's + ADDRESS2's

  • sub ADDRESS1: int, ADDRESS2: int ADDRESS3: int, which sets ADDRESS3's value to ADDRESS1's - ADDRESS2's

  • div ADDRESS1: int, ADDRESS2: int ADDRESS3: int, which sets ADDRESS3's value to ADDRESS1's // ADDRESS2's

  • if+ ADDRESS1: int, ADDRESS2: int, JUMPLEN: int ,EQUALORUNEQUAL: ! or =, which adds jumplen to code pointer if ADDRESS1 and ADDRESS2 are equal or unequal.

  • if- ADDRESS1: int, ADDRESS2: int JUMPLEN: int, EQUALORUNEQUAL: ! or =, which subtracts jumplen from code pointer if ADDRESS1 and ADDRESS2 are equal or unequal.

  • inp ADDRESS: int which takes one integer input and sets ADDRESS to it.

  • echo ADDRESS: int which echoes the value of ADDRESS

  • swap ADDRESS1: int ADDRESS2: int which swaps the values of ADDRESS1 and ADDRESS2

import strutils

var mem: seq[int]
for i in 0..30000:
  mem.add(0)
var code = readFile(readLine(stdin))
var codeptr = 0 
for i in 0..len(code) - 1:
  if code[i] == '\n':
    code[i] = ' ' 
var codes = code.split(" ") 
var done: bool 
var pyqt = false 
while codeptr < len(codes):
  done = false
  pyqt = false
  if codes[codeptr] == "set+" and done == false:
    var IP = codes[codeptr + 1].parseInt()
    mem[IP] = mem[IP] + codes[codeptr + 2].parseInt()
    inc(codeptr, 2)
    done = true
  if codes[codeptr] == "set-" and done == false:
    var IP1 = codes[codeptr + 1].parseInt()
    mem[IP1] = mem[IP1] - codes[codeptr + 2].parseInt()
    inc(codeptr, 2)
    done = true
  if codes[codeptr] == "add" and done == false:
    var IP2 = codes[codeptr + 1].parseInt()
    var IP3 = codes[codeptr + 2].parseInt()
    var IP4 = codes[codeptr + 3].parseInt()
    mem[IP4] = mem[IP2] + mem[IP3]
    inc(codeptr, 2)
    done = true
  if codes[codeptr] == "sub" and done == false:
    var IP5 = codes[codeptr + 1].parseInt()
    var IP6 = codes[codeptr + 2].parseInt()
    var IP7 = codes[codeptr + 3].parseInt()
    mem[IP7] = mem[IP5] - mem[IP6]
    inc(codeptr, 2)
    done = true
  if codes[codeptr] == "mul" and done == false:
    var IP8 = codes[codeptr + 1].parseInt()
    var IP9 = codes[codeptr + 2].parseInt()
    var IP10 = codes[codeptr + 3].parseInt()
    mem[IP10] = mem[IP8] * mem[IP9]
    inc(codeptr, 2)
    done = true
  if codes[codeptr] == "div" and done == false:
    var IP11 = codes[codeptr + 1].parseInt()
    var IP12 = codes[codeptr + 2].parseInt()
    var IP13 = codes[codeptr + 3].parseInt()
    mem[IP13] = int(mem[IP11] / mem[IP12])
    inc(codeptr, 2)
    done = true
  if codes[codeptr] == "if-" and done == false:
    var IP14 = codes[codeptr + 1].parseInt()
    var IP15 = codes[codeptr + 2].parseInt()
    var IP16 = codes[codeptr + 3].parseInt()
    var IP17 = codes[codeptr + 4]
    if IP17 == "=":
      if mem[IP14] == mem[IP15]:
        codeptr = codeptr - IP16
        pyqt = true
    if IP17 == "!":
      if mem[IP14] != mem[IP15]:
        codeptr = codeptr - IP16
        pyqt = true
    done = true 
  if codes[codeptr] == "if+" and done == false:
    var IP14 = codes[codeptr + 1].parseInt()
    var IP15 = codes[codeptr + 2].parseInt()
    var IP16 = codes[codeptr + 3].parseInt()
    var IP17 = codes[codeptr + 4]
    if IP17 == "=":
      if mem[IP14] == mem[IP15]:
        codeptr = codeptr + IP16
        pyqt = true
    if IP17 == "!":
      if mem[IP14] != mem[IP15]:
        codeptr = codeptr + IP16
        pyqt = true
    done = true 
    
  if codes[codeptr] == "inp" and done == false:
    var IP18 = codes[codeptr + 1].parseInt()
    mem[IP18] = readLine(stdin).parseInt()
    inc(codeptr, 1)
    done = true 
  if codes[codeptr] == "echo" and done == false:
    var IP19 = codes[codeptr + 1].parseInt()
    echo mem[IP19]
    inc(codeptr, 1)
    done = true 
  if codes[codeptr] == "swap" and done == false:
    var IP20 = codes[codeptr + 1].parseInt()
    var IP21 = codes[codeptr + 2].parseInt()
    var temp = mem[IP21]
    mem[IP21] = mem[IP20]
    mem[IP20] = temp
    inc(codeptr, 2)
    done = true 
  if codes[codeptr] == "cp" and done == false:
    var IP22 = codes[codeptr + 1].parseInt()
    var IP23 = codes[codeptr + 2].parseInt()
    mem[IP23] = mem[IP22] 
    inc(codeptr, 2)
    done = true 
      

  if pyqt == false:
    codeptr = codeptr + 1 
\$\endgroup\$
2
  • \$\begingroup\$ I rolled back your last edit. In this exchange, editing the question after it's been answered, invalidates the answer. \$\endgroup\$
    – vnp
    Jun 13, 2021 at 17:30
  • \$\begingroup\$ Sorry, should have realized. It was just not my intention to convey what the answerer thought I was trying to. I was trying to ask if the code was using reasonable Nim style, not the minimal language implemented. It pays to proofread twice, and I should have. \$\endgroup\$ Jun 13, 2021 at 21:19

1 Answer 1

1
\$\begingroup\$

The entire parsing lexing process consists of splitting the inputted code by spaces (not whitespace in general), which newlines are counted as. Is this reasonable code style in Nim?

Those are completely different things: you're writing an interpreter for some other language in Nim, so it doesn't matter if this style is reasonable in Nim - it should be reasonable in your language. I'm not pretty sure if it will be ok, but this is your language, so you're the one who decides if it's reasonable.

Yes, your language looks pretty much Turing complete.

Review:

  1. Pay attention to newSeq proc.

  2. "done == false" looks better as "not done":

    if not done and codes[codeptr] == "if+":

but with this whole done thing you're reinventing elif statement in Nim.

Everything else is ok since you're a beginner. You should learn all keywords and System module.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for the feedback. \$\endgroup\$ Jun 13, 2021 at 13:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.