1- {-# LANGUAGE DataKinds #-}
2- {-# LANGUAGE FlexibleContexts #-}
3- {-# LANGUAGE LambdaCase #-}
4- {-# LANGUAGE NamedFieldPuns #-}
5- {-# LANGUAGE OverloadedStrings #-}
1+ {-# LANGUAGE DataKinds #-}
2+ {-# LANGUAGE FlexibleContexts #-}
3+ {-# LANGUAGE LambdaCase #-}
4+ {-# LANGUAGE OverloadedStrings #-}
65{-# LANGUAGE TemplateHaskellQuotes #-}
7- {-# LANGUAGE TypeApplications #-}
8- {-# LANGUAGE TypeOperators #-}
9- {-# LANGUAGE ViewPatterns #-}
6+ {-# LANGUAGE TypeApplications #-}
7+ {-# LANGUAGE TypeOperators #-}
8+ {-# LANGUAGE ViewPatterns #-}
109-- For some reason this module is very slow to compile otherwise
1110{-# OPTIONS_GHC -O0 #-}
1211
1312module PlutusTx.Plugin (plugin , plc ) where
1413
14+ import Data.Bifunctor
1515import PlutusPrelude
1616import PlutusTx.AsData.Internal qualified
1717import PlutusTx.Bool ((&&) , (||) )
18- import PlutusTx.Builtins (equalsInteger , mkNilOpaque , useFromOpaque , useToOpaque )
18+ import PlutusTx.Builtins (mkNilOpaque , useFromOpaque , useToOpaque )
1919import PlutusTx.Code
2020import PlutusTx.Compiler.Builtins
2121import PlutusTx.Compiler.Error
@@ -24,7 +24,6 @@ import PlutusTx.Compiler.Trace
2424import PlutusTx.Compiler.Types
2525import PlutusTx.Coverage
2626import PlutusTx.Function qualified
27- import PlutusTx.List qualified
2827import PlutusTx.Optimize.Inline qualified
2928import PlutusTx.PIRTypes
3029import PlutusTx.PLCTypes
@@ -66,16 +65,14 @@ import Control.Monad.Except
6665import Control.Monad.Reader
6766import Control.Monad.State
6867import Control.Monad.Writer
69- import PlutusCore. Flat (Flat , flat , unflat )
68+ import Flat (Flat , flat , unflat )
7069
7170import Data.ByteString qualified as BS
7271import Data.ByteString.Unsafe qualified as BSUnsafe
7372import Data.Either.Validation
7473import Data.Map qualified as Map
75- import Data.Maybe (mapMaybe )
7674import Data.Monoid.Extra (mwhen )
7775import Data.Set qualified as Set
78- import Data.Text qualified as Text
7976import GHC.Num.Integer qualified
8077import PlutusCore.Default (DefaultFun , DefaultUni )
8178import PlutusIR.Compiler.Provenance (noProvenance , original )
@@ -87,10 +84,10 @@ import System.IO (openBinaryTempFile)
8784import System.IO.Unsafe (unsafePerformIO )
8885
8986data PluginCtx = PluginCtx
90- { pcOpts :: PluginOptions
91- , pcFamEnvs :: GHC. FamInstEnvs
92- , pcMarkerName :: GHC. Name
93- , pcModuleName :: GHC. ModuleName
87+ { pcOpts :: PluginOptions
88+ , pcFamEnvs :: GHC. FamInstEnvs
89+ , pcMarkerName :: GHC. Name
90+ , pcModuleName :: GHC. ModuleName
9491 , pcModuleModBreaks :: Maybe GHC. ModBreaks
9592 }
9693
@@ -221,8 +218,8 @@ mkSimplPass dflags =
221218 }
222219
223220{- Note [Marker resolution]
224- We use TH's 'foo exact syntax for resolving the 'plc marker's ghc name, as explained in:
225- <https ://hackage.haskell.org/package/ghc-9.6.6 /docs/GHC-Plugins .html#v:thNameToGhcName>
221+ We use TH's 'foo exact syntax for resolving the 'plc marker's ghc name, as
222+ explained in: <http ://hackage.haskell.org/package/ghc-8.10.1 /docs/GhcPlugins .html#v:thNameToGhcName>
226223
227224The GHC haddock suggests that the "exact syntax" will always succeed because it is statically
228225resolved here (inside this Plugin module);
@@ -406,15 +403,13 @@ compileMarkedExpr locStr codeTy origE = do
406403 , 'GHC. Num.Integer. integerNegate
407404 , '(PlutusTx.Bool. &&)
408405 , '(PlutusTx.Bool. ||)
409- , '(PlutusTx.List. !!)
410406 , 'PlutusTx. AsData.Internal. wrapTail
411407 , 'PlutusTx. AsData.Internal. wrapUnsafeDataAsConstr
412408 , 'PlutusTx. Function. fix
413409 , 'PlutusTx. Optimize.Inline. inline
414410 , 'useToOpaque
415411 , 'useFromOpaque
416412 , 'mkNilOpaque
417- , 'PlutusTx. Builtins. equalsInteger
418413 ]
419414 modBreaks <- asks pcModuleModBreaks
420415 let coverage =
@@ -428,10 +423,6 @@ compileMarkedExpr locStr codeTy origE = do
428423 CompileOptions
429424 { coProfile = _posProfile opts
430425 , coCoverage = coverage
431- , coDatatypeStyle =
432- if _posPlcTargetVersion opts < PLC. plcVersion110
433- then PIR. ScottEncoding
434- else PIR. _dcoStyle $ _posDatatypes opts
435426 , coRemoveTrace = _posRemoveTrace opts
436427 , coInlineFix = _posInlineFix opts
437428 }
@@ -491,33 +482,11 @@ runCompiler
491482 -> GHC. CoreExpr
492483 -> m (PIRProgram uni fun , UPLCProgram uni fun )
493484runCompiler moduleName opts expr = do
494- GHC. DynFlags {GHC. extensions = extensions} <- asks ccFlags
495- let
496- enabledExtensions =
497- mapMaybe
498- (\ case
499- GHC. On a -> Just a
500- GHC. Off _ -> Nothing )
501- extensions
502- extensionBlacklist =
503- [ GADTs
504- , PolyKinds
505- ]
506- unsupportedExtensions =
507- filter (`elem` extensionBlacklist) enabledExtensions
508-
509- when (not $ null unsupportedExtensions) $
510- throwPlain $ UnsupportedError $
511- " Following extensions are not supported: "
512- <> Text. intercalate " , " (Text. pack . show <$> unsupportedExtensions)
513-
514485 -- Plc configuration
515- plcTcConfig <-
516- modifyError (NoContext . PIRError . PIR. PLCTypeError ) $
517- PLC. getDefTypeCheckConfig PIR. noProvenance
518- datatypeStyle <- asks $ coDatatypeStyle . ccOpts
486+ plcTcConfig <- PLC. getDefTypeCheckConfig PIR. noProvenance
519487 let plcVersion = opts ^. posPlcTargetVersion
520- hints = UPLC. InlineHints $ \ ann _ -> case ann of
488+
489+ let hints = UPLC. InlineHints $ \ ann _ -> case ann of
521490 -- See Note [The problem of inlining destructors]
522491 -- We want to inline destructors, but even in UPLC our inlining heuristics
523492 -- aren't quite smart enough to tell that they're good inlining candidates,
@@ -582,7 +551,16 @@ runCompiler moduleName opts expr = do
582551 (PIR. ccOpts . PIR. coCaseOfCaseConservative)
583552 (opts ^. posCaseOfCaseConservative)
584553 & set (PIR. ccOpts . PIR. coPreserveLogging) (opts ^. posPreserveLogging)
585- & set (PIR. ccOpts . PIR. coDatatypes . PIR. dcoStyle) datatypeStyle
554+ -- We could make this configurable with an option, but:
555+ -- 1. The only other choice you can make is new version + Scott encoding, and
556+ -- there's really no reason to pick that
557+ -- 2. This is consistent with what we do in Lift
558+ & set
559+ (PIR. ccOpts . PIR. coDatatypes . PIR. dcoStyle)
560+ ( if plcVersion < PLC. plcVersion110
561+ then PIR. ScottEncoding
562+ else PIR. SumsOfProducts
563+ )
586564 -- TODO: ensure the same as the one used in the plugin
587565 & set PIR. ccBuiltinsInfo def
588566 & set PIR. ccBuiltinCostModel def
@@ -605,52 +583,55 @@ runCompiler moduleName opts expr = do
605583 & set
606584 (PLC. coSimplifyOpts . UPLC. soInlineCallsiteGrowth)
607585 (opts ^. posInlineCallsiteGrowth . to fromIntegral )
608- & set
609- (PLC. coSimplifyOpts . UPLC. soPreserveLogging)
610- (opts ^. posPreserveLogging)
611586
612587 -- GHC.Core -> Pir translation.
613- pirT <- original <$> (PIR. runDefT annMayInline $ compileExprWithDefs expr)
588+ pirT <-
589+ {-# SCC "plinth-plugin-core -to-pir-step" #-}
590+ original <$> (PIR. runDefT annMayInline $ compileExprWithDefs expr)
614591 let pirP = PIR. Program noProvenance plcVersion pirT
615592 when (opts ^. posDumpPir) . liftIO $
616593 dumpFlat (void pirP) " initial PIR program" (moduleName ++ " _initial.pir-flat" )
617594
618595 -- Pir -> (Simplified) Pir pass. We can then dump/store a more legible PIR program.
619596 spirP <-
620- flip runReaderT pirCtx $
621- modifyError (NoContext . PIRError ) $
622- PIR. compileToReadable pirP
597+ {-# SCC "plinth-plugin-pir-to-simp-step" #-}
598+ flip runReaderT pirCtx $ PIR. compileToReadable pirP
623599 when (opts ^. posDumpPir) . liftIO $
624- dumpFlat (void spirP) " simplified PIR program" (moduleName ++ " _simplified.pir-flat" )
600+ dumpFlat (void spirP) " simplified PIR program" (moduleName ++ " _simplified.pir-flat" )
625601
626602 -- (Simplified) Pir -> Plc translation.
627- plcP <- flip runReaderT pirCtx $
628- modifyError ( NoContext . PIRError ) $
629- PIR. compileReadableToPlc spirP
603+ plcP <-
604+ {-# SCC "plinth-plugin-simp-to-plc-step" #-}
605+ flip runReaderT pirCtx $ PIR. compileReadableToPlc spirP
630606 when (opts ^. posDumpPlc) . liftIO $
631- dumpFlat (void plcP) " typed PLC program" (moduleName ++ " .tplc-flat" )
607+ dumpFlat (void plcP) " typed PLC program" (moduleName ++ " .tplc-flat" )
632608
633609 -- We do this after dumping the programs so that if we fail typechecking we still get the dump.
634610 when (opts ^. posDoTypecheck) . void $
635- liftExcept $
636- modifyError PLC. TypeErrorE $
637- PLC. inferTypeOfProgram plcTcConfig (plcP $> annMayInline)
611+ liftExcept $
612+ PLC. inferTypeOfProgram plcTcConfig (plcP $> annMayInline)
638613
639- (uplcP, _) <- flip runReaderT plcOpts $ PLC. compileProgramWithTrace plcP
640- dbP <- liftExcept $ modifyError PLC. FreeVariableErrorE $ traverseOf UPLC. progTerm UPLC. deBruijnTerm uplcP
614+ uplcP <-
615+ {-# SCC "plinth-plugin-plc-to-uplc-step" #-}
616+ flip runReaderT plcOpts $ PLC. compileProgram plcP
617+ dbP <- liftExcept $ traverseOf UPLC. progTerm UPLC. deBruijnTerm uplcP
641618 when (opts ^. posDumpUPlc) . liftIO $
642- dumpFlat
643- (UPLC. UnrestrictedProgram $ void dbP)
644- " untyped PLC program"
645- (moduleName ++ " .uplc-flat" )
619+ dumpFlat
620+ (UPLC. UnrestrictedProgram $ void dbP)
621+ " untyped PLC program"
622+ (moduleName ++ " .uplc-flat" )
646623 -- Discard the Provenance information at this point, just keep the SrcSpans
647624 -- TODO: keep it and do something useful with it
648625 pure (fmap getSrcSpans spirP, fmap getSrcSpans dbP)
649626 where
650627 -- ugly trick to take out the concrete plc.error and in case of error, map it / rethrow it
651628 -- using our 'CompileError'
652629 liftExcept :: ExceptT (PLC. Error PLC. DefaultUni PLC. DefaultFun Ann ) m b -> m b
653- liftExcept = modifyError (NoContext . PLCError )
630+ liftExcept act = do
631+ plcTcError <- runExceptT act
632+ -- also wrap the PLC Error annotations into Original provenances, to match our expected
633+ -- 'CompileError'
634+ liftEither $ first (view (re PIR. _PLCError) . fmap PIR. Original ) plcTcError
654635
655636 dumpFlat :: (Flat t ) => t -> String -> String -> IO ()
656637 dumpFlat t desc fileName = do
@@ -666,7 +647,7 @@ thNameToGhcNameOrFail :: TH.Name -> PluginM uni fun GHC.Name
666647thNameToGhcNameOrFail name = do
667648 maybeName <- lift . lift $ GHC. thNameToGhcName name
668649 case maybeName of
669- Just n -> pure n
650+ Just n -> pure n
670651 Nothing -> throwError . NoContext $ CoreNameLookupError name
671652
672653-- | Create a GHC Core expression that will evaluate to the given ByteString at runtime.
0 commit comments