Elm 语言编码错误
Elm Language Coding Error
type Expr = Const Float | Var String| Add Expr Expr| Mult Expr Expr
list = [3,1,4]
polyX : List Float -> Expr
polyX coeffs = polyHelper <| map Const <| coeffs
polyHelper: List Expr -> Expr
polyHelper e = case e of
[x] -> x
(x::xs) -> Add x(Mult(Var "x")(polyHelper xs))
[] -> Const 1
type Instr = LoadImmediate RegisterNumber --put value here
RegisterValue --the value
| Addition RegisterNumber --put result here
RegisterNumber --first thing to add
RegisterNumber --first thing to multiply
| Multiply RegisterNumber --put result here
RegisterNumber --first thing to multiply
RegisterNumber --second thing to multiply
type RegisterNumber = Int
type RegisterValue = Float
expr2Code : Expr -> List Instr
expr2Code expr = e2C 1 expr
e2C result expr = case expr of
Const x -> ((LoadImmediate(result+2))x)
Add expr1 expr2 -> (Addition result result (result+1))::(e2C result expr2)++(e2C result expr1)
Mult expr1 expr2 -> (Mult result result(result+1))::(e2C result expr2)++(e2C result expr1)
Var x -> []
我的作业有困难。
问题:
Assume that the only variable you will see is x and it is already in register 2. Arrange for the result to arrive to be in register 1 at the end of the computation, and use registers 3 and 4 for other values, as needed. Write the helper function e2C to complete.
我的T.A说我现在的代码可以编译,但不能解决问题。
谁能告诉我如何修改代码以解决问题?
正在编译
好吧,你错了,该代码片段无法编译。这是一个编译版本:
type Expr
= Const Float
| Var String
| Add Expr Expr
| Mult Expr Expr
type Instr
= LoadImmediate RegisterNumber --put value here
RegisterValue --the value
| Addition RegisterNumber --put result here
RegisterNumber --first thing to add
RegisterNumber --first thing to multiply
| Multiply RegisterNumber --put result here
RegisterNumber --first thing to multiply
RegisterNumber --second thing to multiply
type alias RegisterNumber
= Int
type alias RegisterValue
= Float
list : List Float
list =
[3,1,4]
polyX : List Float -> Expr
polyX coeffs =
polyHelper <| List.map Const <| coeffs
polyHelper: List Expr -> Expr
polyHelper e =
case e of
[x] ->
x
(x::xs) ->
Add x (Mult (Var "x") (polyHelper xs))
[] ->
Const 1
expr2Code : Expr -> List Instr
expr2Code expr =
e2C 1 expr
e2C : RegisterNumber -> Expr -> List Instr
e2C result expr =
case expr of
Const x ->
[LoadImmediate (result+2) x]
Add expr1 expr2 ->
Addition result result (result+1)
:: e2C result expr2 ++ e2C result expr1
Mult expr1 expr2 ->
Multiply result result (result+1)
:: e2C result expr2 ++ e2C result expr1
Var x ->
[]
我已经根据 style guide 对代码进行了格式化。我在编译你的代码之前发现了以下问题:
polyX
使用了一个不合格的 map
函数,但是没有导入,所以你应该使用合格的 List.map
。
- 类型
RegisterNumber
和RegisterValue
是类型别名。对那些使用 type alias
,否则你要为完全独立的类型 RegisterNumber
和 [=16= 定义 构造函数 Int
和 Float
] 而不是将它们与 types Int and
Float` 相关联。
e2C
中的 Const
分支没有返回列表,但 case
的其他分支是。
e2C
中的 Mult
分支使用 Mult
而不是 Multiply
作为结果,它是 Expr
,而不是 Instr
.
开始工作
免责声明: 查看您的 school/course 欺诈法规。根据我的经验,学生应该只提交他们自己编写的解决方案。关于解决方案的高层讨论通常是可以的,复制代码很可能是不行的。根据您学校的欺诈规定,此答案可能过于详细。引用您的消息来源并不总是足够的!
考虑到您可以执行的三个指令,将结果从一个寄存器移动到另一个寄存器并不容易。这将需要像 [LoadImmediate freeRegister 0, Addition moveToThisRegister MoveFromThisRegister freeRegister]
这样的虚假指令。所以你不能优雅地创建一个精心设计的编译器,而且你可能不必这样做,因为你只被要求完成辅助函数 e2C
。
因此,我们将寻求简单、非通用的解决方案。您需要对输入的 Expr
做出一些假设。请注意,polyX
仅生成具有某种常数(Const
或 Var
)的加法和乘法左手边。这是我们要利用的 属性。
因此,如果您首先执行右侧表达式,并为该表达式提供与您提供的相同的结果寄存器,那么您的左侧仍然有两个空闲寄存器(3 和 4)。始终只使用其中一个,然后在结果寄存器和选择的空闲寄存器之间进行操作。
在没有移动操作的情况下,将变量 x 的值移动到不同的寄存器有点难看。但它相当通用,所以让我们使用剩余的空闲寄存器将 0 添加到变量 x 的值并将该值保存到我们应该将结果放入的寄存器中。这为您提供了以下实现:
registerOfX : RegisterNumber
registerOfX = 2
freeRegister1 : RegisterNumber
freeRegister1 = 3
freeRegister2 : RegisterNumber
freeRegister2 = 4
e2C : RegisterNumber -> Expr -> List Instr
e2C resultRegister expr =
case expr of
Const value ->
[LoadImmediate resultRegister value]
Add expr1 expr2 ->
e2C resultRegister expr2
++ e2C freeRegister1 expr1
++ [Addition resultRegister freeRegister1 resultRegister]
Mult expr1 expr2 ->
e2C resultRegister expr2
++ e2C freeRegister1 expr1
++ [Multiply resultRegister freeRegister1 resultRegister]
Var "x" ->
[LoadImmediate freeRegister2 0, Addition resultRegister registerOfX freeRegister2]
Var _ ->
"Cannot handle "
++ toString expr
++ ", we only know of "
++ toString (Var "x")
|> Debug.crash
最后一点,因为这已经是一个很长的答案了。您会看到此代码会产生一些冗余的 LoadImmediate 4 0
指令。您可以通过执行 LoadImmediate freeRegister2 0 :: case expr of ...
之类的操作将它的信号指令添加到列表的前面。然后您可以在一条指令中将变量 x 移动到寄存器。指令的任何进一步最小化都需要额外的步骤,这些步骤最好在进一步的辅助函数中完成,或者您需要通过直接匹配 Mult (Var "x") expr2
并直接使用变量 x 的寄存器来降低代码的通用性。
type Expr = Const Float | Var String| Add Expr Expr| Mult Expr Expr
list = [3,1,4]
polyX : List Float -> Expr
polyX coeffs = polyHelper <| map Const <| coeffs
polyHelper: List Expr -> Expr
polyHelper e = case e of
[x] -> x
(x::xs) -> Add x(Mult(Var "x")(polyHelper xs))
[] -> Const 1
type Instr = LoadImmediate RegisterNumber --put value here
RegisterValue --the value
| Addition RegisterNumber --put result here
RegisterNumber --first thing to add
RegisterNumber --first thing to multiply
| Multiply RegisterNumber --put result here
RegisterNumber --first thing to multiply
RegisterNumber --second thing to multiply
type RegisterNumber = Int
type RegisterValue = Float
expr2Code : Expr -> List Instr
expr2Code expr = e2C 1 expr
e2C result expr = case expr of
Const x -> ((LoadImmediate(result+2))x)
Add expr1 expr2 -> (Addition result result (result+1))::(e2C result expr2)++(e2C result expr1)
Mult expr1 expr2 -> (Mult result result(result+1))::(e2C result expr2)++(e2C result expr1)
Var x -> []
我的作业有困难。
问题:
Assume that the only variable you will see is x and it is already in register 2. Arrange for the result to arrive to be in register 1 at the end of the computation, and use registers 3 and 4 for other values, as needed. Write the helper function e2C to complete.
我的T.A说我现在的代码可以编译,但不能解决问题。
谁能告诉我如何修改代码以解决问题?
正在编译
好吧,你错了,该代码片段无法编译。这是一个编译版本:
type Expr
= Const Float
| Var String
| Add Expr Expr
| Mult Expr Expr
type Instr
= LoadImmediate RegisterNumber --put value here
RegisterValue --the value
| Addition RegisterNumber --put result here
RegisterNumber --first thing to add
RegisterNumber --first thing to multiply
| Multiply RegisterNumber --put result here
RegisterNumber --first thing to multiply
RegisterNumber --second thing to multiply
type alias RegisterNumber
= Int
type alias RegisterValue
= Float
list : List Float
list =
[3,1,4]
polyX : List Float -> Expr
polyX coeffs =
polyHelper <| List.map Const <| coeffs
polyHelper: List Expr -> Expr
polyHelper e =
case e of
[x] ->
x
(x::xs) ->
Add x (Mult (Var "x") (polyHelper xs))
[] ->
Const 1
expr2Code : Expr -> List Instr
expr2Code expr =
e2C 1 expr
e2C : RegisterNumber -> Expr -> List Instr
e2C result expr =
case expr of
Const x ->
[LoadImmediate (result+2) x]
Add expr1 expr2 ->
Addition result result (result+1)
:: e2C result expr2 ++ e2C result expr1
Mult expr1 expr2 ->
Multiply result result (result+1)
:: e2C result expr2 ++ e2C result expr1
Var x ->
[]
我已经根据 style guide 对代码进行了格式化。我在编译你的代码之前发现了以下问题:
polyX
使用了一个不合格的map
函数,但是没有导入,所以你应该使用合格的List.map
。- 类型
RegisterNumber
和RegisterValue
是类型别名。对那些使用type alias
,否则你要为完全独立的类型RegisterNumber
和 [=16= 定义 构造函数Int
和Float
] 而不是将它们与 typesInt and
Float` 相关联。 e2C
中的Const
分支没有返回列表,但case
的其他分支是。e2C
中的Mult
分支使用Mult
而不是Multiply
作为结果,它是Expr
,而不是Instr
.
开始工作
免责声明: 查看您的 school/course 欺诈法规。根据我的经验,学生应该只提交他们自己编写的解决方案。关于解决方案的高层讨论通常是可以的,复制代码很可能是不行的。根据您学校的欺诈规定,此答案可能过于详细。引用您的消息来源并不总是足够的!
考虑到您可以执行的三个指令,将结果从一个寄存器移动到另一个寄存器并不容易。这将需要像 [LoadImmediate freeRegister 0, Addition moveToThisRegister MoveFromThisRegister freeRegister]
这样的虚假指令。所以你不能优雅地创建一个精心设计的编译器,而且你可能不必这样做,因为你只被要求完成辅助函数 e2C
。
因此,我们将寻求简单、非通用的解决方案。您需要对输入的 Expr
做出一些假设。请注意,polyX
仅生成具有某种常数(Const
或 Var
)的加法和乘法左手边。这是我们要利用的 属性。
因此,如果您首先执行右侧表达式,并为该表达式提供与您提供的相同的结果寄存器,那么您的左侧仍然有两个空闲寄存器(3 和 4)。始终只使用其中一个,然后在结果寄存器和选择的空闲寄存器之间进行操作。
在没有移动操作的情况下,将变量 x 的值移动到不同的寄存器有点难看。但它相当通用,所以让我们使用剩余的空闲寄存器将 0 添加到变量 x 的值并将该值保存到我们应该将结果放入的寄存器中。这为您提供了以下实现:
registerOfX : RegisterNumber
registerOfX = 2
freeRegister1 : RegisterNumber
freeRegister1 = 3
freeRegister2 : RegisterNumber
freeRegister2 = 4
e2C : RegisterNumber -> Expr -> List Instr
e2C resultRegister expr =
case expr of
Const value ->
[LoadImmediate resultRegister value]
Add expr1 expr2 ->
e2C resultRegister expr2
++ e2C freeRegister1 expr1
++ [Addition resultRegister freeRegister1 resultRegister]
Mult expr1 expr2 ->
e2C resultRegister expr2
++ e2C freeRegister1 expr1
++ [Multiply resultRegister freeRegister1 resultRegister]
Var "x" ->
[LoadImmediate freeRegister2 0, Addition resultRegister registerOfX freeRegister2]
Var _ ->
"Cannot handle "
++ toString expr
++ ", we only know of "
++ toString (Var "x")
|> Debug.crash
最后一点,因为这已经是一个很长的答案了。您会看到此代码会产生一些冗余的 LoadImmediate 4 0
指令。您可以通过执行 LoadImmediate freeRegister2 0 :: case expr of ...
之类的操作将它的信号指令添加到列表的前面。然后您可以在一条指令中将变量 x 移动到寄存器。指令的任何进一步最小化都需要额外的步骤,这些步骤最好在进一步的辅助函数中完成,或者您需要通过直接匹配 Mult (Var "x") expr2
并直接使用变量 x 的寄存器来降低代码的通用性。