gpt4 book ai didi

scheme - 这段代码的合适 Racket/Scheme 习惯用法是什么?

转载 作者:行者123 更新时间:2023-12-04 08:50:08 25 4
gpt4 key购买 nike

我是 Racket /方案的新手,所以我决定通过为 DCPU-16 实现一个模拟器来学习,一个简单的 16 位处理器。

因此,我的问题是:实现我的解决方案的更好方法是什么?

这是我一起破解以控制 cpu 寄存器的解决方案。重点是允许将修改寄存器的函数链接在一起。例如:

; 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

我的注册解决方案的全文如下。 My full program也在 github 上。有这么多重复的逻辑,我知道一定有一个更简单的方法:
(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")]))))

更新:

感谢 oobviat 的建议,我使用列表进行了重构。唯一棘手的部分是更新列表中的值。我为 map 编写了一个程序,该程序将更新所需的寄存器并保留其他寄存器的原始值:
;; 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)))

最佳答案

这不是用 Racket 编写的,因此它可能无法按原样运行。如果它抛出错误,请尝试在文件顶部指定 R5RS 代码类型。为简单起见,我会使用 a-list 而不是结构来做这样的事情。

;; a-list of registers and initial values
(define *reg*
'((A . 0) (B . 0) (C . 0) (X . 0) (Y . 0) (Z . 0)
(I . 0) (J . 0) (SP . #X10000) (PC . 0) (O . 0)
(Pa . 0) (Pb . 0) (Paadr . 0) (Pbadr . 0) (CLK . 0)))

(define (reg-write register val)
(set-cdr! (assoc register *reg*) val) ;write new value to register
val) ; return newly written value

(define (reg-read register)
(cdr (assoc register *reg*)))

(define (reg-inc register)
(reg-write register (+ 1 (reg-read register))))

;; to do many operations
;; input: a list of registers
;; EX: '(a b x)
(define (do-incs registers)
(if (null? registers)
'done ; return something when the incs are done
(begin ; lets you evaluate multiple expressions since `if` doesn't
(reg-inc (car registers))
(do-incs (cdr registers)))))

我假设 Racket 有一个内置的 assoc从 a-list 返回正确的列表。另外,请注意 *reg*在这种情况下被定义为全局变量,以便我们只需定义一次然后使用 set-cdr!向其写入值。

最后,这可能会对您的 SP 产生奇怪的影响登记。我的方案将其视为 65536 .. 如果这不对,您可能需要添加 ifreg-writereg-read以确保您在那里获得正确的值。
<EDIT>所以,我阅读了一些关于 Racket 程序的内容,这段代码几乎肯定不会在普通 Racket 中运行,因为它们显然同时具有可变和非可变对。如果您想在 Racket 而不是 R5RS 下运行它,您必须进行的更改如下:

您可能需要使用可变列表/对构造函数 (define *reg* (mlist (mcons 'A 0) (mcons 'B 0) ... ) 来制作寄存器列表,而不仅仅是使用带引号的列表。 .

而不是使用 set-cdr! Racket 版本是 set-mcdr!并且仅适用于可变对。 </EDIT>

关于scheme - 这段代码的合适 Racket/Scheme 习惯用法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10037466/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com