榆树语言编码错误

时间:2015-11-28 22:29:35

标签: variable-assignment elm

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 -> []

我在执行任务时遇到困难。

问题:

  

假设你将看到的唯一变量是x,它已经在寄存器2中。安排结果在计算结束时到达寄存器1,并使用寄存器3和4作为其他值,如需要。编写辅助函数e2C来完成。

我的T.A说我现在的代码会编译,但它不会解决问题。

任何人都可以告诉我如何修复代码,以便解决问题吗?

1 个答案:

答案 0 :(得分:0)

让它编译

嗯,你的TA错了,代码片段无法编译。这是一个编译版本:

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更多地格式化了代码。在编译代码之前我发现了以下问题:

  1. polyX使用了不合格的map函数,但没有导入,因此您应该使用限定的List.map
  2. 类型RegisterNumberRegisterValue别名。请使用type alias,否则您需要为完全独立的类型IntFloat定义构造函数 RegisterNumberRegisterValue而不是将它们与类型 Int and Float`相关联。
  3. Const中的e2C分支未返回列表,但case的其他分支是。Mult
  4. e2C中的Mult分支正在使用Multiply代替Expr作为结果,Instr而不是[LoadImmediate freeRegister 0, Addition moveToThisRegister MoveFromThisRegister freeRegister]
  5. 开始工作

    免责声明:检查有关FRAUD的学校/课程规定。根据我的经验,学生只能提交他们自己编写的解决方案。关于解决方案的高级讨论通常都可以,复制代码很可能不行。根据您学校的欺诈规定,这个答案可能会进一步详细说明。引用你的消息来源并不总是足够的!

    鉴于您可以执行三条指令,将结果从一个寄存器移动到另一个寄存器并不容易。这需要e2C之类的虚假指令。因此,您不能优雅地创建精心编译的编译器,并且您可能不必这样做,因为您只需要完成辅助函数Expr

    因此,我们正在寻求简单,非通用的解决方案。您将对您所获得的polyX做一些假设。请注意,Const仅生成具有某种程度不变的加法和乘法(Var或{{1} }) 左手边。这是我们将要利用的财产。

    因此,如果您先执行右侧表达式,并将该表达式赋予您给出的相同结果寄存器,那么您的左侧仍然有两个空闲寄存器(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的寄存器来使代码不那么通用。