Soy nuevo en la raqueta/esquema, así que decidí aprender mediante la implementación de un emulador para el DCPU-16, un procesador simple de 16 bits.¿Cuál es la expresión apropiada de Raqueta/Esquema para este código?
Mi pregunta es por lo tanto: ¿Cuál es una mejor manera de implementar mi solución?
Esta es la solución que pirateé para controlar los registros de la CPU. El punto principal era permitir que las funciones que modifican un registro se encadenaran entre sí. Por ejemplo:
; Increment value stored in register r-id
; returns the updated register
;
; Reg - the register structure
; (reg-inc Reg 'SP)
(define (reg-inc reg r-id)
(reg-write reg r-id (+ (reg-read reg r-id) 1)))
; chain them together
;(reg-inc (reg-inc Reg 'SP)
; 'PC)
;
; returns structure with both 'SP and 'PC incremented
El texto completo de mi solución de registro está a continuación. My full program también está en github. Hay tanto repite la lógica, sé que debe haber una manera más fácil:
(struct registers (A B C X Y Z I J SP PC O Pa Pb Paadr Pbadr CLK)
#:transparent)
(define Reg (registers 0 0 0 0 0 0 0 0 #x10000 0 0 0 0 0 0 0))
(define (reg-name n)
(case n
[(0) 'A]
[(1) 'B]
[(2) 'C]
[(3) 'X]
[(4) 'Y]
[(5) 'Z]
[(6) 'I]
[(7) 'J]
[(8) 'SP]
[(9) 'PC]
[(10) 'O]
[(11) 'Pa]
[(12) 'Pb]
[(13) 'Paadr]
[(14) 'Pbadr]
[(15) 'CLK]
[else (error "Invalid register")]))
(define (reg-id s)
(cond
[(eq? 'A s) 0]
[(eq? 'B s) 1]
[(eq? 'C s) 2]
[(eq? 'X s) 3]
[(eq? 'Y s) 4]
[(eq? 'Z s) 5]
[(eq? 'I s) 6]
[(eq? 'J s) 7]
[(eq? 'SP s) 8]
[(eq? 'PC s) 9]
[(eq? 'O s) 10]
[(eq? 'Pa s) 11]
[(eq? 'Pb s) 12]
[(eq? 'Paadr s) 13]
[(eq? 'Pbadr s) 14]
[(eq? 'CLK s) 15]))
(define (reg-read reg r)
(if (symbol? r)
(reg-read reg (reg-id r))
(case r
[(0) (registers-A reg)]
[(1) (registers-B reg)]
[(2) (registers-C reg)]
[(3) (registers-X reg)]
[(4) (registers-Y reg)]
[(5) (registers-Z reg)]
[(6) (registers-I reg)]
[(7) (registers-J reg)]
[(8) (registers-SP reg)]
[(9) (registers-PC reg)]
[(10) (registers-O reg)]
[(11) (registers-Pa reg)]
[(12) (registers-Pb reg)]
[(13) (registers-Paadr reg)]
[(14) (registers-Pbadr reg)]
[(15) (registers-CLK reg)]
[else (error "Invalid register")])))
(define (reg-write reg r val)
(if (symbol? r)
(reg-write reg (reg-id r) val)
(let ([mask-val (bitwise-and val #xffff)])
(case r
[(0) (struct-copy registers reg [A mask-val])]
[(1) (struct-copy registers reg [B mask-val])]
[(2) (struct-copy registers reg [C mask-val])]
[(3) (struct-copy registers reg [X mask-val])]
[(4) (struct-copy registers reg [Y mask-val])]
[(5) (struct-copy registers reg [Z mask-val])]
[(6) (struct-copy registers reg [I mask-val])]
[(7) (struct-copy registers reg [J mask-val])]
[(8) (struct-copy registers reg [SP mask-val])]
[(9) (struct-copy registers reg [PC mask-val])]
[(10) (struct-copy registers reg [O mask-val])]
[(11) (struct-copy registers reg [Pa mask-val])]
[(12) (struct-copy registers reg [Pb mask-val])]
[(13) (struct-copy registers reg [Paadr mask-val])]
[(14) (struct-copy registers reg [Pbadr mask-val])]
[(15) (struct-copy registers reg [CLK mask-val])]
[else (error "Invalid register")]))))
Actualización:
Gracias a sugerencias de oobviat He refactorizado el uso de listas. La única parte difícil fue actualizar un valor en la lista. Escribí un procedimiento para obtener un mapa que actualizaría el registro deseado y dejar a los demás con su valor original:
;; a-list of registers and initial values
(define (build-reg)
'((A . 0) (B . 0) (C . 0) (X . 0)
(Y . 0) (Z . 0) (I . 0) (J . 0)
(SP . 0) (PC . 0) (O . 0) (Pa . 0)
(Pb . 0) (Paadr . 0) (Pbadr . 0) (CLK . 0)))
(define *REF-REG* (build-reg)) ; used to determine structure
(define (reg-name n)
(if (symbol? n)
n
(car (list-ref *REF-REG* n))))
(define (reg-id s)
(- (length *REF-REG*)
(length (memf (lambda (arg)
(eq? s (car arg)))
*REF-REG*))))
(define (reg-write reg r val)
(let ([r-name (reg-name r)])
(define (reg-write-helper entry)
(if (eq? r-name
(car entry))
(cons r-name val)
entry))
(map reg-write-helper reg)))
(define (reg-read reg r)
(cdr (assoc (reg-name r) reg)))
¿Las estructuras no tienen procedimientos de introspección? Estoy seguro de que sí. – leppie
@leppie, las estructuras no tienen sus nombres en la información de introspección. –