컴공지식/프로그래밍언어론

재귀로 인해 추가된 코드 부분

개강한 공대생 2024. 10. 27. 17:07

trait Expr

case class Num(n: Int) extends Expr
case class Add(lhs: Expr, rhs: Expr) extends Expr
case class Sub(lhs: Expr, rhs: Expr) extends Expr
case class Id(name: String) extends Expr
case class Fun(param: Id, body: Expr) extends Expr
case class App(funExpr: Expr, argExpr: Expr) extends Expr

case class If0(testExpr: Expr, thenExpr: Expr, elseExpr: Expr) extends Expr
case class Rec(fname: Id, namedExpr: Expr, fstCall: Expr) extends Expr

 

 

If0이랑 Rec이 새로 추가됐다.

case class If0(testExpr: Expr, thenExpr: Expr, elseExpr: Expr) extends Expr

은 testExpr이 0인지 검사해서, 참일 경우 thenExpr를 실행하고, 거짓일 경우 elseExpr를 실행한다.

 

case class Rec(fname: Id, namedExpr: Expr, fstCall: Expr) extends Expr

은 재귀 함수를 정의하는 표현이다.

 

 

다음은 interp 함수다.

// interp : Expr -> DefrdSub -> ExprValue
def interp(expr: Expr, ds: DefrdSub): ExprValue = expr match {
  case Num(n) =>
    NumV(n)

  case Add(lhs, rhs) =>
    numAdd(interp(lhs, ds), interp(rhs, ds))

  case Sub(lhs, rhs) =>
    numSub(interp(lhs, ds), interp(rhs, ds))

  case Id(name) =>
    lookup(name, ds)

  case Fun(param, body) =>
    ClosureV(param, body, ds)

  case App(funExpr, argExpr) =>
    val fVal = interp(funExpr, ds)
    val aVal = interp(argExpr, ds)
    fVal match {
      case ClosureV(param, body, closureDs) =>
        interp(body, ASub(param, aVal, closureDs))
      case _ =>
        throw new Exception("Expected a function")
    }

  case If0(testExpr, thenExpr, elseExpr) =>
    if (numzero(interp(testExpr, ds)))
      interp(thenExpr, ds)
    else
      interp(elseExpr, ds)

  case Rec(fname, namedExpr, fstCall) =>
    // 1. 더미 값을 사용해 valueHolder 초기화
    var valueHolder = NumV(198)  // 초기화용 임의 값

    // 2. ARecSub를 사용해 새로운 DS 생성
    val newDs = ARecSub(fname, valueHolder, ds)

    // 3. namedExpr을 인터프리팅해서 함수 값으로 업데이트
    valueHolder = interp(namedExpr, newDs)
    newDs.valueBox = valueHolder  // 박스에 실제 값 저장

    // 4. 첫 번째 호출 실행
    interp(fstCall, newDs)
}

 

 

만약 valueHolder가 없다면 재귀 호출할 때 아직 함수 정의가 환경에 없어서 에러가 날 거다.