Уникальный идентификатор / счетчик в Haskell - PullRequest
0 голосов
/ 26 мая 2019

Я пытаюсь сгенерировать некоторые инструкции по сборке в Haskell, и мне нужно сгенерировать несколько уникальных идентификаторов для обозначения разделов для jmp инструкций.Я полагаю, что мог бы сделать это, используя монаду состояния, но я все еще новичок в Haskell и не очень удобен с монадой состояний и нуждаюсь в некоторой помощи, чтобы использовать ее в этом контексте.

Вот один из примеров, где я хотел бынужен уникальный идентификатор

generateExpression :: AST.Expr -> String
generateExpression (AST.BinOpExpr AST.Or e1 e2) =
            (generateExpression e1) ++
            "    cmpl    $0, %eax\n" ++
            "    je      _or_clause2\n" ++
            "    movl    $1, %eax\n" ++
            "    jmp     _or_end\n" ++
            "_or_clause2:\n" ++           -- need to use a unique id here instead of clause 2
            (generateExpression e2) ++
            "    cmpl    $0, %eax\n" ++
            "    movl    $0, %eax\n" ++
            "    setne   %al\n" ++
            "_or_end:\n"                  -- need to use a unique id here to label the end

Редактировать: я прочитал несколько уроков по State Monad и могу реализовать простой счетчик, такой как

import Control.Monad.State

counter :: State Int Int
counter = do
    x <- get
    put (x+1)
    return x

runState counter 1 -- outputs (1,2) where the state has been incremented

, который будет отслеживать счетчик как состояние,Но я не уверен, как использовать это в моей функции, где мне нужно сохранять состояние в рекурсивных вызовах.

1 Ответ

4 голосов
/ 26 мая 2019

Таким образом, тип возвращаемого значения должен содержать State Int, это не может быть String. Главное, что вам нужно пропустить государство. Здесь я использовал нотацию do, так как вам это удобно.

counter :: State Int Int
counter = do
    n <- get
    put (n + 1)
    pure n

generateASM :: AST.Expr -> State Int String
generateASM (AST.BinOpExpr AST.Or e1 e2) = do
    e1ASM <- generateASM e1
    n <- counter
    e2ASM <- generateASM e2
    pure $
        e1ASM ++
        "    cmpl    $0, %eax\n" ++
        "    je      _or_clause" ++ show n ++ "\n" ++
        "    movl    $1, %eax\n" ++
        "    jmp     _or_end" ++ show n ++ "\n" ++
        "_or_clause" ++ show n ++ ":\n" ++ show n ++
        e2ASM ++
        "    cmpl    $0, %eax\n" ++
        "    movl    $0, %eax\n" ++
        "    setne   %al\n" ++
        "_or_end" ++ show n ++ ":\n"
generateASM (..) = .. -- other branches defined similarly...

generateASMFull :: AST.Expr -> String
generateASMFull e = evalState (generateASM e) 0

P.S. Я не проверил правильность вашей логики сборки.

...