Skip to content

Commit 79af2c0

Browse files
committed
wip
1 parent 2a6be75 commit 79af2c0

File tree

1 file changed

+55
-74
lines changed

1 file changed

+55
-74
lines changed

plutus-tx-plugin/src/PlutusTx/Plugin.hs

Lines changed: 55 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
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

1312
module PlutusTx.Plugin (plugin, plc) where
1413

14+
import Data.Bifunctor
1515
import PlutusPrelude
1616
import PlutusTx.AsData.Internal qualified
1717
import PlutusTx.Bool ((&&), (||))
18-
import PlutusTx.Builtins (equalsInteger, mkNilOpaque, useFromOpaque, useToOpaque)
18+
import PlutusTx.Builtins (mkNilOpaque, useFromOpaque, useToOpaque)
1919
import PlutusTx.Code
2020
import PlutusTx.Compiler.Builtins
2121
import PlutusTx.Compiler.Error
@@ -24,7 +24,6 @@ import PlutusTx.Compiler.Trace
2424
import PlutusTx.Compiler.Types
2525
import PlutusTx.Coverage
2626
import PlutusTx.Function qualified
27-
import PlutusTx.List qualified
2827
import PlutusTx.Optimize.Inline qualified
2928
import PlutusTx.PIRTypes
3029
import PlutusTx.PLCTypes
@@ -66,16 +65,14 @@ import Control.Monad.Except
6665
import Control.Monad.Reader
6766
import Control.Monad.State
6867
import Control.Monad.Writer
69-
import PlutusCore.Flat (Flat, flat, unflat)
68+
import Flat (Flat, flat, unflat)
7069

7170
import Data.ByteString qualified as BS
7271
import Data.ByteString.Unsafe qualified as BSUnsafe
7372
import Data.Either.Validation
7473
import Data.Map qualified as Map
75-
import Data.Maybe (mapMaybe)
7674
import Data.Monoid.Extra (mwhen)
7775
import Data.Set qualified as Set
78-
import Data.Text qualified as Text
7976
import GHC.Num.Integer qualified
8077
import PlutusCore.Default (DefaultFun, DefaultUni)
8178
import PlutusIR.Compiler.Provenance (noProvenance, original)
@@ -87,10 +84,10 @@ import System.IO (openBinaryTempFile)
8784
import System.IO.Unsafe (unsafePerformIO)
8885

8986
data 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
227224
The GHC haddock suggests that the "exact syntax" will always succeed because it is statically
228225
resolved 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)
493484
runCompiler 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
666647
thNameToGhcNameOrFail 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

Comments
 (0)