[基础软件理论与实践] 第四节作业实现 yhgu2000

yhgu2000 2023-01-15 15:15:47

作业信息

1. 完成汇编器(assembler)中的encode函数。
2. 使用C/C++/Rust实现支持课程中使用的指令的虚拟机。
3. 完整实现加入函数调用机制的语言的编译器(compiler)
4. 实现一个支持递归函数的解释器(interpreter)

作业实现

任务1和任务3

encode函数的重点在于`Label`伪指令的处理，它不需要生成字节码，只是用于指示`GOTO`指令的目标位置。示例代码的实现在碰到`Label`指令直接无操作，而在编码`GOTO`时查找标签的字节码序号，然后计算从序号到`GOTO`指令之间生成的字节码长度，将这个长度输出到字节码序列中，因此解释器在处理`GOTO`指令时，跳转目标是相对当前程序指针寻址的。

``````type prim = Add | Mul | Self

type rec expr =
| Cst(int)
| Var(string)
| Let(string, expr, expr)
| Letfn(string, list<string>, expr, expr) // fnName args body let-scope
| App(string, list<expr>)
| Prim(prim, list<expr>)
| If(expr, expr, expr)

``````

任务4

``````open Expr

module List = Belt.List
module HMapS = Belt.HashMap.String

type rec value = Int(int) | Closure(envs, list<string>, expr)
and env = HMapS.t<value>
and envs = list<env>

let rec print = (value: value) => {
switch value {
| Int(i) => Js.log(`Int(\${Belt.Int.toString(i)})`)
| Closure(a, b, c) => {
Js.log("Closure(")
Js.log(a)
Js.log(",")
Js.log(b)
Js.log(",")
Js.log(c)
Js.log(")")
}
}
}

let rec print_envs = (envs: envs) => {
switch envs {
| list{} => Js.log(None)
| list{env, ...rest} => {
Js.log(env)
print_envs(rest)
}
}
}

let rec resolve_helper = (envs: envs, name: string) => {
switch envs {
| list{} => None
| list{env, ...rest} => {
let val = HMapS.get(env, name)
if val == None { resolve_helper(rest, name) } else { val }
}
}
}

let resolve = (envs: envs, name: string): value => {
let v = resolve_helper(envs, name)
switch v {
| Some(t) => t
| None => {
Js.log(name)
print_envs(envs)
assert false
}
}
}

let rec eval = (expr: expr, envs: envs): value => {
let list{env, ..._} = envs

switch expr {
| Cst(n) => Int(n)
| Var(s) => resolve(envs, s)

| Let(name, e1, e2) => {
HMapS.set(env, name, eval(e1, envs))
eval(e2, envs)
}
| Letfn(name, args, body, scope) => {
HMapS.set(env, name, Closure(envs, args, body))
eval(scope, envs)
}

| App(name, args) => {
let closure = resolve(envs, name)
let Closure(cenvs, cargs, cexpr) = closure
let nenv = HMapS.make(~hintSize=1)
List.forEach2(cargs, args, (a, b) => HMapS.set(nenv, a, eval(b, envs)))
HMapS.set(nenv, "@", closure)  // 上下文环境里的 "@" 就指向当前调用的函数
eval(cexpr, list{nenv, ...cenvs})
}

| Prim(op, es) => {
switch op {
let list{a, b, ..._} = es
let Int(va) = eval(a, envs)
let Int(vb) = eval(b, envs)
Int(va + vb)
}
| Mul => {
let list{a, b, ..._} = es
let Int(va) = eval(a, envs)
let Int(vb) = eval(b, envs)
Int(va * vb)
}
| Self => {
let closure = resolve(envs, "@")
let Closure(cenvs, cargs, cexpr) = closure
// 上下文环境里的 "@" 就指向当前调用的函数
let nenv = HMapS.make(~hintSize=1)
HMapS.set(nenv, "@", closure)
List.forEach2(cargs, es, (a, b) => HMapS.set(nenv, a, eval(b, envs)))
eval(cexpr, list{nenv, ...cenvs})
}
}
}

| If(e1, e2, e3) => {
let Int(v1) = eval(e1, envs)
if (v1 != 0) { eval(e2, envs) } else { eval(e3, envs) }
}
}
}
``````

...全文
185 回复 打赏 收藏 转发到动态 举报

231

rescript开发语言 个人社区 广东省·深圳市

• 近7日
• 近30日
• 至今