urm.scm 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. ;; This is my second attempt at a URM machine in Scheme
  2. ;; Like the old one, this is also licensed GPLv3
  3. (import (scheme base)
  4. (scheme char)
  5. (scheme file)
  6. (scheme read)
  7. (scheme write)
  8. (scheme process-context))
  9. (define (start-urm p)
  10. (define (inc n)
  11. (lambda ()
  12. (vector-set! registers
  13. n
  14. (+ (vector-ref registers n) 1))
  15. 1))
  16. (define (clr n)
  17. (lambda ()
  18. (vector-set! registers n 0)
  19. 1))
  20. (define (cpy m n)
  21. (lambda ()
  22. (vector-set! registers
  23. n
  24. (vector-ref registers m))
  25. 1))
  26. (define (jmp m n offset)
  27. (lambda ()
  28. (if (= (vector-ref registers m)
  29. (vector-ref registers n))
  30. offset
  31. 1)))
  32. (define (prn n)
  33. (lambda ()
  34. (display (vector-ref registers n))
  35. (newline)
  36. 1))
  37. (define (prc n)
  38. (lambda ()
  39. (write-char (integer->char (vector-ref registers n)))
  40. 1))
  41. (define (rdn n)
  42. (lambda ()
  43. (vector-set! registers
  44. n
  45. (read-integer (current-input-port)))
  46. 1))
  47. (define (rdc n)
  48. (lambda ()
  49. (vector-set! registers
  50. n
  51. (char->integer (read-char (current-input-port))))
  52. 1))
  53. (define (read-integer p)
  54. (define v (read p))
  55. (if (and (exact? v) (integer? v))
  56. v
  57. (error "read-integer" "Not an integer value")))
  58. (define (get-lines p)
  59. (define (strip s)
  60. (define sp (open-input-string s))
  61. (let loop ((peek (peek-char sp)))
  62. (cond
  63. ((member peek '(#\space #\tab #\return
  64. #\0 #\1 #\2 #\3 #\4
  65. #\5 #\6 #\7 #\8 #\9))
  66. (read-char sp)
  67. (loop (peek-char sp)))
  68. ((or (eof-object? peek)
  69. (char=? peek #\#))
  70. "")
  71. (else ; keep reading until eof or #\#
  72. (let loop2 ((out '())
  73. (peek2 (peek-char sp)))
  74. (if (or (eof-object? peek2)
  75. (char=? peek2 #\#))
  76. (list->string (reverse out))
  77. (begin
  78. (read-char sp)
  79. (loop2 (cons peek2 out)
  80. (peek-char sp)))))))))
  81. (let loop ((out '())
  82. (peek (peek-char p)))
  83. (if (eof-object? peek)
  84. (reverse out)
  85. (let ((next (strip (read-line p))))
  86. (loop (if (equal? next "")
  87. out
  88. (cons next out))
  89. (peek-char p))))))
  90. (define (parse-line s-in)
  91. (define s (string-downcase s-in))
  92. (define p (open-input-string s))
  93. (define result
  94. (case (read p)
  95. ((inc)
  96. (let ((n (read-integer p)))
  97. (cons (inc (- n 1)) n)))
  98. ((clr)
  99. (let ((n (read-integer p)))
  100. (cons (clr (- n 1)) n)))
  101. ((cpy)
  102. (let ((m (read-integer p)))
  103. (let ((n (read-integer p)))
  104. (cons (cpy (- m 1) (- n 1)) (max m n)))))
  105. ((jmp)
  106. (let ((m (read-integer p)))
  107. (let ((n (read-integer p)))
  108. (let ((offset (read-integer p)))
  109. (cons (jmp (- m 1) (- n 1) offset) (max m n))))))
  110. ((prn)
  111. (let ((n (read-integer p)))
  112. (cons (prn (- n 1)) n)))
  113. ((prc)
  114. (let ((n (read-integer p)))
  115. (cons (prc (- n 1)) n)))
  116. ((rdn)
  117. (let ((n (read-integer p)))
  118. (cons (rdn (- n 1)) n)))
  119. ((rdc)
  120. (let ((n (read-integer p)))
  121. (cons (rdc (- n 1)) n)))
  122. (else
  123. (error "parse-line" "Parsing failed"))))
  124. (if (not (eof-object? (read p)))
  125. (error "parse-line" "Unexpected character")
  126. result))
  127. (define pairs (map parse-line (get-lines p)))
  128. (define instructions (list->vector (map car pairs)))
  129. (define registers (make-vector (apply max (map cdr pairs)) 0))
  130. (let loop ((pc 0))
  131. (if (< pc (vector-length instructions))
  132. (loop (+ pc ((vector-ref instructions pc)))))))
  133. (define (main-prog args)
  134. (start-urm (open-input-file (car args))))
  135. (main-prog (cdr (command-line)))