我在Python中编写了一个简单的基于堆栈的虚拟机,现在我正在尝试在Clojure中重写它,由于我没有太多使用Lisp的经验,这证明很难.这个Python片段处理字节码,它表示为元组列表,如下所示:
[("label", "entry"),
("load", 0),
("load", 1),
("add",),
("store", 0)]
Run Code Online (Sandbox Code Playgroud)
或者在Clojure中:
[[:label :entry]
[:load 0]
[:load 1]
[:add]
[:store 0]]
Run Code Online (Sandbox Code Playgroud)
当Function对象加载字节码时,每个"label"元组都会被专门处理以标记该位置,而其他每个元组都保留在最终的字节码中.我认为Clojure相当于这个函数会涉及折叠,但我不知道如何以优雅或惯用的方式做到这一点.有任何想法吗?
ama*_*loy 10
阅读Python片段,看起来您希望最终输出看起来像
{:code [[:load 0]
[:load 1]
[:add]
[:store 0]]
:labels {:entry 0}}
Run Code Online (Sandbox Code Playgroud)
一旦你对目标有了明确的描述,编写代码要容易得多,事实上这是一个非常简单的减少.有许多风格上不同的编写缩减器的方法,但对我来说,这种方式似乎最容易阅读.
(defn load [asm]
(reduce (fn [{:keys [code labels]} [op arg1 & args :as instruction]]
(if (= :label op)
{:code code
:labels (assoc labels arg1 (count code))}
{:code (conj code instruction)
:labels labels}))
{:code [], :labels {}},
asm))
Run Code Online (Sandbox Code Playgroud)
此版本支持name参数,并通过不重复不更改的元素来简化还原步骤.
(defn load [name asm]
(reduce (fn [program [op arg1 :as instruction]]
(if (= :label op)
(assoc-in program [:labels arg1] (count (:code program)))
(update-in program [:code] conj instruction)))
{:code [], :labels {}, :name name},
asm))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
598 次 |
| 最近记录: |