morley-1.16.3: src/Morley/Michelson/Parser/Ext.hs
-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA
-- TODO [#712]: Remove this next major release
{-# OPTIONS_GHC -Wno-deprecations #-}
-- | Parsing logic for extra instructions (Morley extensions)
module Morley.Michelson.Parser.Ext
( extInstr
, stackType
-- * For tests
, printComment
) where
import Prelude hiding (try)
import Text.Megaparsec (choice, label, satisfy, try)
import Text.Megaparsec.Char (alphaNumChar, string)
import Text.Megaparsec.Char.Lexer qualified as L
import Morley.Michelson.Macro (ParsedOp(..), ParsedUExtInstr)
import Morley.Michelson.Parser.Lexer
import Morley.Michelson.Parser.Type
import Morley.Michelson.Parser.Types (LetEnv, Parser')
import Morley.Michelson.Untyped qualified as U
extInstr :: Parser' LetEnv [ParsedOp] -> Parser' LetEnv ParsedUExtInstr
extInstr opsParser = do
label "morley instruction" $ choice [stackOp, testAssertOp opsParser, printOp]
stackOp :: Parser' LetEnv ParsedUExtInstr
stackOp = word' "STACKTYPE" U.STACKTYPE <*> stackType
testAssertOp :: Parser' LetEnv [ParsedOp] -> Parser' LetEnv ParsedUExtInstr
testAssertOp opsParser =
word' "TEST_ASSERT" U.UTEST_ASSERT <*> testAssert opsParser
printOp :: Parser' LetEnv ParsedUExtInstr
printOp = word' "PRINT" U.UPRINT <*> printComment
testAssert :: Parser' LetEnv [ParsedOp] -> Parser' LetEnv (U.TestAssert ParsedOp)
testAssert opsParser = do
n <- lexeme (toText <$> some alphaNumChar)
c <- printComment
o <- opsParser
return $ U.TestAssert n c o
printComment :: Parser' LetEnv U.PrintComment
printComment = do
string "\""
let validChar = toText <$> some (satisfy (\x -> x /= '%' && x /= '"'))
c <- many (Right <$> stackRef <|> Left <$> validChar)
symbol "\""
return $ U.PrintComment c
stackRef :: Parser' LetEnv U.StackRef
stackRef = do
string "%"
n <- brackets' L.decimal
return $ U.StackRef n
stackType :: Parser' LetEnv U.StackTypePattern
stackType = do
symbol "'[" >> (emptyStk <|> stkCons <|> stkRest)
where
emptyStk = try $ symbol "]" $> U.StkEmpty
stkRest = try $ symbol "..." >> symbol "]" $> U.StkRest
stkCons = try $ do
t <- tyVar
s <- (symbol "," >> stkCons <|> stkRest) <|> emptyStk
return $ U.StkCons t s
tyVar :: Parser' LetEnv U.TyVar
tyVar = (U.TyCon <$> type_) <|> (U.VarID <$> varID)