packages feed

caml-parser-0.1.0.0: src/MLQE/Plugin.hs

{-# LANGUAGE OverloadedStrings #-}
module MLQE.Plugin where

import Control.Monad (void)
import Data.Map (Map)
import qualified Data.Map as Map
import Text.Megaparsec hiding (Token)
import CamlParser.Lexer.Token
import CamlParser.Syntax.Expr
import CamlParser.Syntax.Pattern
import CamlParser.Syntax.Type
import CamlParser.Syntax.Decl
import CamlParser.Syntax.Location
import CamlParser.Parser.Combinators
import CamlParser.Parser.Expr (parseExpr)
import CamlParser.Parser.Type (parseType)
import CamlParser.Plugin.Interface
import MLQE.Syntax

mlqeKeywords :: Map String Token
mlqeKeywords = Map.fromList
  [ ("qubit",    TokKeywordExt mlqeTag "qubit")
  , ("qdef",     TokKeywordExt mlqeTag "qdef")
  , ("qalloc",   TokKeywordExt mlqeTag "qalloc")
  , ("qlift",    TokKeywordExt mlqeTag "qlift")
  , ("measure",  TokKeywordExt mlqeTag "measure")
  , ("unitary",  TokKeywordExt mlqeTag "unitary")
  , ("kraus",    TokKeywordExt mlqeTag "kraus")
  , ("gate",     TokKeywordExt mlqeTag "gate")
  , ("channel",  TokKeywordExt mlqeTag "channel")
  , ("pulse",    TokKeywordExt mlqeTag "pulse")
  , ("complex",  TokKeywordExt mlqeTag "complex")
  , ("matrix",   TokKeywordExt mlqeTag "matrix")
  ]

mlqePlugin :: CamlParserPlugin
mlqePlugin = CamlParserPlugin
  { pluginName = "mlqe"
  , pluginKeywords = mlqeKeywords
  , pluginExprAtom = Nothing  -- qalloc, qlift, measure parse as ordinary applications
  , pluginDecl = Just mlqeDeclParser
  }

mlqeDeclParser :: Parser (Decl Expr Pattern)
mlqeDeclParser = do
  keyword "qdef"
  name <- identP
  choice
    [ parseQDefConcrete name
    , parseQDefParamAbstract name
    , parseQDefAbstract name
    ]

parseQDefAbstract :: String -> Parser (Decl Expr Pattern)
parseQDefAbstract name = do
  tok TokColon
  ty <- parseType
  void (tok TokSemiSemi)
  return $ DExt mlqeTag (DeclExt mlqeTag (QDefAbstract name (Just ty)))

parseQDefParamAbstract :: String -> Parser (Decl Expr Pattern)
parseQDefParamAbstract name = do
  tok TokOf
  pty <- parseType
  tok TokColon
  ty <- parseType
  void (tok TokSemiSemi)
  return $ DExt mlqeTag (DeclExt mlqeTag (QDefParamAbstract name pty ty))

parseQDefConcrete :: String -> Parser (Decl Expr Pattern)
parseQDefConcrete name = do
  tok TokEqual
  qe <- parseQExpr
  void (tok TokSemiSemi)
  return $ DExt mlqeTag (DeclExt mlqeTag (QDefConcrete name qe))

parseQExpr :: Parser QExpr
parseQExpr = parseQTensor

parseQTensor :: Parser QExpr
parseQTensor = do
  e1 <- parseQSeq
  (do tok TokStar
      e2 <- parseQTensor
      return $ QTensor e1 e2
   ) <|> return e1

parseQSeq :: Parser QExpr
parseQSeq = do
  e1 <- parseQAtom
  (do tok (TokInfix 1 "@")
      e2 <- parseQSeq
      return $ QSeq e1 e2
   ) <|> return e1

parseQAtom :: Parser QExpr
parseQAtom = choice
  [ do n <- identP
       (do e <- parens parseExpr
           return $ QParam n e
        ) <|> return (QVar n)
  , QId <$ keyword "id"
  ]