Jestem nowy w rakiecie/schemacie, więc postanowiłem dowiedzieć się poprzez implementację emulatora dla DCPU-16, prostego procesora 16-bitowego.Jaki jest odpowiedni idiom Rakieta/Schemat dla tego kodu?
Moje pytanie brzmi: jaki jest lepszy sposób wdrożenia mojego rozwiązania?
To jest rozwiązanie, które zhakowałem, aby kontrolować rejestry procesora. Głównym celem było umożliwienie funkcji, które modyfikują rejestr, aby były połączone razem. Na przykład:
; 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
Pełny tekst mojego rozwiązania rejestru znajduje się poniżej. My full program jest również na github. Jest tyle powtarzane logiki, wiem, że musi być łatwiejszy sposób:
(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")]))))
Aktualizacja:
Dzięki za sugestie oobviat Mam refactored za pomocą list. Jedyną trudną częścią było zaktualizowanie wartości na liście. Napisałem procedurę mapie, które zaktualizować żądany rejestr i pozostawić innym z ich pierwotnej wartości:
;; 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)))
Czy struktura nie ma procedur introspekcji? Jestem pewien, że tak. – leppie
@leppie, struktury nie mają swoich nazw w informacjach introspekcji. –