ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 재귀로 인해 추가된 코드 부분
    컴공지식/프로그래밍언어론 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가 없다면 재귀 호출할 때 아직 함수 정의가 환경에 없어서 에러가 날 거다.

     

     

    '컴공지식 > 프로그래밍언어론' 카테고리의 다른 글

    JVM은 일종의 인터프리터  (0) 2024.11.03
    Box 데이터 구조  (2) 2024.11.02
    재귀 호출 비교  (1) 2024.10.27
    에타 축약이란?  (1) 2024.10.27
    재귀 BNF  (1) 2024.10.27
Designed by Tistory.